//===-- 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: ", this);
    s->Indent();
    *s << "CompileUnit" << (const UserID&)*this
        << ", language = \"" << (const Language&)*this
        << "\", file = '" << (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 a Mangled::Tokens token list. This
// function currently implements an interative approach designed to find
// all instances of certain functions. It isn't designed to the 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() == NULL)
    {
        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 == NULL)
        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() == NULL && 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 artifically 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();
    bool file_spec_matches_cu_file_spec = FileSpec::Equal(file_spec, *this, full_match);

    // 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);
    while (file_idx != UINT32_MAX)
    {
        file_indexes.push_back (file_idx);
        file_idx = GetSupportFiles().FindFileIndex (file_idx + 1, file_spec, true);
    }
    
    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 != NULL)
        {
            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;
}

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;
}


