//===-- CompileUnit.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/Symbol/CompileUnit.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/Language.h"
#include "lldb/Symbol/LineTable.h"
#include "lldb/Symbol/SymbolVendor.h"
#include "lldb/Symbol/VariableList.h"

using namespace lldb;
using namespace lldb_private;

CompileUnit::CompileUnit (const lldb::ModuleSP &module_sp, void *user_data, const char *pathname, const lldb::user_id_t cu_sym_id, lldb::LanguageType language) :
    ModuleChild(module_sp),
    FileSpec (pathname, false),
    UserID(cu_sym_id),
    m_user_data (user_data),
    m_language (language),
    m_flags (0),
    m_functions (),
    m_support_files (),
    m_line_table_ap (),
    m_variables()
{
    if (language != eLanguageTypeUnknown)
        m_flags.Set(flagsParsedLanguage);
    assert(module_sp);
}

CompileUnit::CompileUnit (const lldb::ModuleSP &module_sp, void *user_data, const FileSpec &fspec, const lldb::user_id_t cu_sym_id, lldb::LanguageType language) :
    ModuleChild(module_sp),
    FileSpec (fspec),
    UserID(cu_sym_id),
    m_user_data (user_data),
    m_language (language),
    m_flags (0),
    m_functions (),
    m_support_files (),
    m_line_table_ap (),
    m_variables()
{
    if (language != eLanguageTypeUnknown)
        m_flags.Set(flagsParsedLanguage);
    assert(module_sp);
}

CompileUnit::~CompileUnit ()
{
}

void
CompileUnit::CalculateSymbolContext(SymbolContext* sc)
{
    sc->comp_unit = this;
    GetModule()->CalculateSymbolContext(sc);
}

ModuleSP
CompileUnit::CalculateSymbolContextModule ()
{
    return GetModule();
}

CompileUnit *
CompileUnit::CalculateSymbolContextCompileUnit ()
{
    return this;
}

void
CompileUnit::DumpSymbolContext(Stream *s)
{
    GetModule()->DumpSymbolContext(s);
    s->Printf(", CompileUnit{0x%8.8" PRIx64 "}", GetID());
}


void
CompileUnit::GetDescription(Stream *s, lldb::DescriptionLevel level) const
{
    Language language(m_language);
    *s << "id = " << (const UserID&)*this << ", file = \"" << (const FileSpec&)*this << "\", language = \"" << language << '"';
}


//----------------------------------------------------------------------
// Dump the current contents of this object. No functions that cause on
// demand parsing of functions, globals, statics are called, so this
// is a good function to call to get an idea of the current contents of
// the CompileUnit object.
//----------------------------------------------------------------------
void
CompileUnit::Dump(Stream *s, bool show_context) const
{
    s->Printf("%p: ", static_cast<const void*>(this));
    s->Indent();
    *s << "CompileUnit" << static_cast<const UserID&>(*this)
       << ", language = \"" << reinterpret_cast<const Language&>(*this)
       << "\", file = '" << static_cast<const FileSpec&>(*this) << "'\n";

//  m_types.Dump(s);

    if (m_variables.get())
    {
        s->IndentMore();
        m_variables->Dump(s, show_context);
        s->IndentLess();
    }

    if (!m_functions.empty())
    {
        s->IndentMore();
        std::vector<FunctionSP>::const_iterator pos;
        std::vector<FunctionSP>::const_iterator end = m_functions.end();
        for (pos = m_functions.begin(); pos != end; ++pos)
        {
            (*pos)->Dump(s, show_context);
        }

        s->IndentLess();
        s->EOL();
    }
}

//----------------------------------------------------------------------
// Add a function to this compile unit
//----------------------------------------------------------------------
void
CompileUnit::AddFunction(FunctionSP& funcSP)
{
    // TODO: order these by address
    m_functions.push_back(funcSP);
}

FunctionSP
CompileUnit::GetFunctionAtIndex (size_t idx)
{
    FunctionSP funcSP;
    if (idx < m_functions.size())
        funcSP = m_functions[idx];
    return funcSP;
}

//----------------------------------------------------------------------
// Find functions using the Mangled::Tokens token list. This
// function currently implements an interactive approach designed to find
// all instances of certain functions. It isn't designed to the
// quickest way to lookup functions as it will need to iterate through
// all functions and see if they match, though it does provide a powerful
// and context sensitive way to search for all functions with a certain
// name, all functions in a namespace, or all functions of a template
// type. See Mangled::Tokens::Parse() comments for more information.
//
// The function prototype will need to change to return a list of
// results. It was originally used to help debug the Mangled class
// and the Mangled::Tokens::MatchesQuery() function and it currently
// will print out a list of matching results for the functions that
// are currently in this compile unit.
//
// A FindFunctions method should be called prior to this that takes
// a regular function name (const char * or ConstString as a parameter)
// before resorting to this slower but more complete function. The
// other FindFunctions method should be able to take advantage of any
// accelerator tables available in the debug information (which is
// parsed by the SymbolFile parser plug-ins and registered with each
// Module).
//----------------------------------------------------------------------
//void
//CompileUnit::FindFunctions(const Mangled::Tokens& tokens)
//{
//  if (!m_functions.empty())
//  {
//      Stream s(stdout);
//      std::vector<FunctionSP>::const_iterator pos;
//      std::vector<FunctionSP>::const_iterator end = m_functions.end();
//      for (pos = m_functions.begin(); pos != end; ++pos)
//      {
//          const ConstString& demangled = (*pos)->Mangled().Demangled();
//          if (demangled)
//          {
//              const Mangled::Tokens& func_tokens = (*pos)->Mangled().GetTokens();
//              if (func_tokens.MatchesQuery (tokens))
//                  s << "demangled MATCH found: " << demangled << "\n";
//          }
//      }
//  }
//}

FunctionSP
CompileUnit::FindFunctionByUID (lldb::user_id_t func_uid)
{
    FunctionSP funcSP;
    if (!m_functions.empty())
    {
        std::vector<FunctionSP>::const_iterator pos;
        std::vector<FunctionSP>::const_iterator end = m_functions.end();
        for (pos = m_functions.begin(); pos != end; ++pos)
        {
            if ((*pos)->GetID() == func_uid)
            {
                funcSP = *pos;
                break;
            }
        }
    }
    return funcSP;
}


lldb::LanguageType
CompileUnit::GetLanguage()
{
    if (m_language == eLanguageTypeUnknown)
    {
        if (m_flags.IsClear(flagsParsedLanguage))
        {
            m_flags.Set(flagsParsedLanguage);
            SymbolVendor* symbol_vendor = GetModule()->GetSymbolVendor();
            if (symbol_vendor)
            {
                SymbolContext sc;
                CalculateSymbolContext(&sc);
                m_language = symbol_vendor->ParseCompileUnitLanguage(sc);
            }
        }
    }
    return m_language;
}

LineTable*
CompileUnit::GetLineTable()
{
    if (m_line_table_ap.get() == nullptr)
    {
        if (m_flags.IsClear(flagsParsedLineTable))
        {
            m_flags.Set(flagsParsedLineTable);
            SymbolVendor* symbol_vendor = GetModule()->GetSymbolVendor();
            if (symbol_vendor)
            {
                SymbolContext sc;
                CalculateSymbolContext(&sc);
                symbol_vendor->ParseCompileUnitLineTable(sc);
            }
        }
    }
    return m_line_table_ap.get();
}

void
CompileUnit::SetLineTable(LineTable* line_table)
{
    if (line_table == nullptr)
        m_flags.Clear(flagsParsedLineTable);
    else
        m_flags.Set(flagsParsedLineTable);
    m_line_table_ap.reset(line_table);
}

VariableListSP
CompileUnit::GetVariableList(bool can_create)
{
    if (m_variables.get() == nullptr && can_create)
    {
        SymbolContext sc;
        CalculateSymbolContext(&sc);
        assert(sc.module_sp);
        sc.module_sp->GetSymbolVendor()->ParseVariablesForContext(sc);
    }

    return m_variables;
}

uint32_t
CompileUnit::FindLineEntry (uint32_t start_idx, uint32_t line, const FileSpec* file_spec_ptr, bool exact, LineEntry *line_entry_ptr)
{
    uint32_t file_idx = 0;

    if (file_spec_ptr)
    {
        file_idx = GetSupportFiles().FindFileIndex (1, *file_spec_ptr, true);
        if (file_idx == UINT32_MAX)
            return UINT32_MAX;
    }
    else
    {
        // All the line table entries actually point to the version of the Compile
        // Unit that is in the support files (the one at 0 was artificially added.)
        // So prefer the one further on in the support files if it exists...
        FileSpecList &support_files = GetSupportFiles();
        const bool full = true;
        file_idx = support_files.FindFileIndex (1, support_files.GetFileSpecAtIndex(0), full);
        if (file_idx == UINT32_MAX)
            file_idx = 0;
    }
    LineTable *line_table = GetLineTable();
    if (line_table)
        return line_table->FindLineEntryIndexByFileIndex (start_idx, file_idx, line, exact, line_entry_ptr);
    return UINT32_MAX;
}




uint32_t
CompileUnit::ResolveSymbolContext
(
    const FileSpec& file_spec,
    uint32_t line,
    bool check_inlines,
    bool exact,
    uint32_t resolve_scope,
    SymbolContextList &sc_list
)
{
    // First find all of the file indexes that match our "file_spec". If 
    // "file_spec" has an empty directory, then only compare the basenames
    // when finding file indexes
    std::vector<uint32_t> file_indexes;
    const bool full_match = (bool)file_spec.GetDirectory();
    const bool remove_backup_dots = true;
    bool file_spec_matches_cu_file_spec = FileSpec::Equal(file_spec, *this, full_match, remove_backup_dots);

    // If we are not looking for inlined functions and our file spec doesn't
    // match then we are done...
    if (file_spec_matches_cu_file_spec == false && check_inlines == false)
        return 0;

    uint32_t file_idx = GetSupportFiles().FindFileIndex (1, file_spec, true, remove_backup_dots);
    while (file_idx != UINT32_MAX)
    {
        file_indexes.push_back (file_idx);
        file_idx = GetSupportFiles().FindFileIndex (file_idx + 1, file_spec, true, remove_backup_dots);
    }
    
    const size_t num_file_indexes = file_indexes.size();
    if (num_file_indexes == 0)
        return 0;

    const uint32_t prev_size = sc_list.GetSize();

    SymbolContext sc(GetModule());
    sc.comp_unit = this;


    if (line != 0)
    {
        LineTable *line_table = sc.comp_unit->GetLineTable();

        if (line_table != nullptr)
        {
            uint32_t found_line;
            uint32_t line_idx;
            
            if (num_file_indexes == 1)
            {
                // We only have a single support file that matches, so use
                // the line table function that searches for a line entries
                // that match a single support file index
                LineEntry line_entry;
                line_idx = line_table->FindLineEntryIndexByFileIndex (0, file_indexes.front(), line, exact, &line_entry);

                // If "exact == true", then "found_line" will be the same
                // as "line". If "exact == false", the "found_line" will be the
                // closest line entry with a line number greater than "line" and 
                // we will use this for our subsequent line exact matches below.
                found_line = line_entry.line;

                while (line_idx != UINT32_MAX)
                {
                    // If they only asked for the line entry, then we're done, we can just copy that over.
                    // But if they wanted more than just the line number, fill it in.
                    if (resolve_scope == eSymbolContextLineEntry)
                    {
                        sc.line_entry = line_entry;
                    }
                    else
                    {
                        line_entry.range.GetBaseAddress().CalculateSymbolContext(&sc, resolve_scope);
                    }
                    
                    sc_list.Append(sc);
                    line_idx = line_table->FindLineEntryIndexByFileIndex (line_idx + 1, file_indexes.front(), found_line, true, &line_entry);
                }
            }
            else
            {
                // We found multiple support files that match "file_spec" so use
                // the line table function that searches for a line entries
                // that match a multiple support file indexes.
                LineEntry line_entry;
                line_idx = line_table->FindLineEntryIndexByFileIndex (0, file_indexes, line, exact, &line_entry);

                // If "exact == true", then "found_line" will be the same
                // as "line". If "exact == false", the "found_line" will be the
                // closest line entry with a line number greater than "line" and 
                // we will use this for our subsequent line exact matches below.
                found_line = line_entry.line;

                while (line_idx != UINT32_MAX)
                {
                    if (resolve_scope == eSymbolContextLineEntry)
                    {
                        sc.line_entry = line_entry;
                    }
                    else
                    {
                        line_entry.range.GetBaseAddress().CalculateSymbolContext(&sc, resolve_scope);
                    }
                    
                    sc_list.Append(sc);
                    line_idx = line_table->FindLineEntryIndexByFileIndex (line_idx + 1, file_indexes, found_line, true, &line_entry);
                }
            }
        }
    }
    else if (file_spec_matches_cu_file_spec && !check_inlines)
    {
        // only append the context if we aren't looking for inline call sites
        // by file and line and if the file spec matches that of the compile unit
        sc_list.Append(sc);
    }
    return sc_list.GetSize() - prev_size;
}

void
CompileUnit::SetVariableList(VariableListSP &variables)
{
    m_variables = variables;
}

const std::vector<ConstString> &
CompileUnit::GetImportedModules ()
{
    if (m_imported_modules.empty() &&
        m_flags.IsClear(flagsParsedImportedModules))
    {
        m_flags.Set(flagsParsedImportedModules);
        if (SymbolVendor *symbol_vendor = GetModule()->GetSymbolVendor())
        {
            SymbolContext sc;
            CalculateSymbolContext(&sc);
            symbol_vendor->ParseImportedModules(sc, m_imported_modules);
        }
    }
    return m_imported_modules;
}

FileSpecList&
CompileUnit::GetSupportFiles ()
{
    if (m_support_files.GetSize() == 0)
    {
        if (m_flags.IsClear(flagsParsedSupportFiles))
        {
            m_flags.Set(flagsParsedSupportFiles);
            SymbolVendor* symbol_vendor = GetModule()->GetSymbolVendor();
            if (symbol_vendor)
            {
                SymbolContext sc;
                CalculateSymbolContext(&sc);
                symbol_vendor->ParseCompileUnitSupportFiles(sc, m_support_files);
            }
        }
    }
    return m_support_files;
}

void *
CompileUnit::GetUserData () const
{
    return m_user_data;
}


