//===-- Function.cpp ------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "lldb/Symbol/Function.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Disassembler.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleList.h"
#include "lldb/Core/Section.h"
#include "lldb/Host/Host.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/CompilerType.h"
#include "lldb/Symbol/LineTable.h"
#include "lldb/Symbol/SymbolFile.h"
#include "lldb/Target/Language.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
#include "llvm/Support/Casting.h"

using namespace lldb;
using namespace lldb_private;

// Basic function information is contained in the FunctionInfo class. It is
// designed to contain the name, linkage name, and declaration location.
FunctionInfo::FunctionInfo(const char *name, const Declaration *decl_ptr)
    : m_name(name), m_declaration(decl_ptr) {}

FunctionInfo::FunctionInfo(ConstString name, const Declaration *decl_ptr)
    : m_name(name), m_declaration(decl_ptr) {}

FunctionInfo::~FunctionInfo() = default;

void FunctionInfo::Dump(Stream *s, bool show_fullpaths) const {
  if (m_name)
    *s << ", name = \"" << m_name << "\"";
  m_declaration.Dump(s, show_fullpaths);
}

int FunctionInfo::Compare(const FunctionInfo &a, const FunctionInfo &b) {
  int result = ConstString::Compare(a.GetName(), b.GetName());
  if (result)
    return result;

  return Declaration::Compare(a.m_declaration, b.m_declaration);
}

Declaration &FunctionInfo::GetDeclaration() { return m_declaration; }

const Declaration &FunctionInfo::GetDeclaration() const {
  return m_declaration;
}

ConstString FunctionInfo::GetName() const { return m_name; }

size_t FunctionInfo::MemorySize() const {
  return m_name.MemorySize() + m_declaration.MemorySize();
}

InlineFunctionInfo::InlineFunctionInfo(const char *name,
                                       llvm::StringRef mangled,
                                       const Declaration *decl_ptr,
                                       const Declaration *call_decl_ptr)
    : FunctionInfo(name, decl_ptr), m_mangled(mangled),
      m_call_decl(call_decl_ptr) {}

InlineFunctionInfo::InlineFunctionInfo(ConstString name,
                                       const Mangled &mangled,
                                       const Declaration *decl_ptr,
                                       const Declaration *call_decl_ptr)
    : FunctionInfo(name, decl_ptr), m_mangled(mangled),
      m_call_decl(call_decl_ptr) {}

InlineFunctionInfo::~InlineFunctionInfo() = default;

void InlineFunctionInfo::Dump(Stream *s, bool show_fullpaths) const {
  FunctionInfo::Dump(s, show_fullpaths);
  if (m_mangled)
    m_mangled.Dump(s);
}

void InlineFunctionInfo::DumpStopContext(Stream *s) const {
  //    s->Indent("[inlined] ");
  s->Indent();
  if (m_mangled)
    s->PutCString(m_mangled.GetName().AsCString());
  else
    s->PutCString(m_name.AsCString());
}

ConstString InlineFunctionInfo::GetName() const {
  if (m_mangled)
    return m_mangled.GetName();
  return m_name;
}

ConstString InlineFunctionInfo::GetDisplayName() const {
  if (m_mangled)
    return m_mangled.GetDisplayDemangledName();
  return m_name;
}

Declaration &InlineFunctionInfo::GetCallSite() { return m_call_decl; }

const Declaration &InlineFunctionInfo::GetCallSite() const {
  return m_call_decl;
}

Mangled &InlineFunctionInfo::GetMangled() { return m_mangled; }

const Mangled &InlineFunctionInfo::GetMangled() const { return m_mangled; }

size_t InlineFunctionInfo::MemorySize() const {
  return FunctionInfo::MemorySize() + m_mangled.MemorySize();
}

/// @name Call site related structures
/// @{

CallEdge::~CallEdge() = default;

CallEdge::CallEdge(AddrType caller_address_type, lldb::addr_t caller_address,
                   bool is_tail_call, CallSiteParameterArray &&parameters)
    : caller_address(caller_address), caller_address_type(caller_address_type),
      is_tail_call(is_tail_call), parameters(std::move(parameters)) {}

lldb::addr_t CallEdge::GetLoadAddress(lldb::addr_t unresolved_pc,
                                      Function &caller, Target &target) {
  Log *log = GetLog(LLDBLog::Step);

  const Address &caller_start_addr = caller.GetAddress();

  ModuleSP caller_module_sp = caller_start_addr.GetModule();
  if (!caller_module_sp) {
    LLDB_LOG(log, "GetLoadAddress: cannot get Module for caller");
    return LLDB_INVALID_ADDRESS;
  }

  SectionList *section_list = caller_module_sp->GetSectionList();
  if (!section_list) {
    LLDB_LOG(log, "GetLoadAddress: cannot get SectionList for Module");
    return LLDB_INVALID_ADDRESS;
  }

  Address the_addr = Address(unresolved_pc, section_list);
  lldb::addr_t load_addr = the_addr.GetLoadAddress(&target);
  return load_addr;
}

lldb::addr_t CallEdge::GetReturnPCAddress(Function &caller,
                                          Target &target) const {
  return GetLoadAddress(GetUnresolvedReturnPCAddress(), caller, target);
}

void DirectCallEdge::ParseSymbolFileAndResolve(ModuleList &images) {
  if (resolved)
    return;

  Log *log = GetLog(LLDBLog::Step);
  LLDB_LOG(log, "DirectCallEdge: Lazily parsing the call graph for {0}",
           lazy_callee.symbol_name);

  auto resolve_lazy_callee = [&]() -> Function * {
    ConstString callee_name{lazy_callee.symbol_name};
    SymbolContextList sc_list;
    images.FindFunctionSymbols(callee_name, eFunctionNameTypeAuto, sc_list);
    size_t num_matches = sc_list.GetSize();
    if (num_matches == 0 || !sc_list[0].symbol) {
      LLDB_LOG(log,
               "DirectCallEdge: Found no symbols for {0}, cannot resolve it",
               callee_name);
      return nullptr;
    }
    Address callee_addr = sc_list[0].symbol->GetAddress();
    if (!callee_addr.IsValid()) {
      LLDB_LOG(log, "DirectCallEdge: Invalid symbol address");
      return nullptr;
    }
    Function *f = callee_addr.CalculateSymbolContextFunction();
    if (!f) {
      LLDB_LOG(log, "DirectCallEdge: Could not find complete function");
      return nullptr;
    }
    return f;
  };
  lazy_callee.def = resolve_lazy_callee();
  resolved = true;
}

DirectCallEdge::DirectCallEdge(const char *symbol_name,
                               AddrType caller_address_type,
                               lldb::addr_t caller_address, bool is_tail_call,
                               CallSiteParameterArray &&parameters)
    : CallEdge(caller_address_type, caller_address, is_tail_call,
               std::move(parameters)) {
  lazy_callee.symbol_name = symbol_name;
}

Function *DirectCallEdge::GetCallee(ModuleList &images, ExecutionContext &) {
  ParseSymbolFileAndResolve(images);
  assert(resolved && "Did not resolve lazy callee");
  return lazy_callee.def;
}

IndirectCallEdge::IndirectCallEdge(DWARFExpressionList call_target,
                                   AddrType caller_address_type,
                                   lldb::addr_t caller_address,
                                   bool is_tail_call,
                                   CallSiteParameterArray &&parameters)
    : CallEdge(caller_address_type, caller_address, is_tail_call,
               std::move(parameters)),
      call_target(std::move(call_target)) {}

Function *IndirectCallEdge::GetCallee(ModuleList &images,
                                      ExecutionContext &exe_ctx) {
  Log *log = GetLog(LLDBLog::Step);
  Status error;
  llvm::Expected<Value> callee_addr_val = call_target.Evaluate(
      &exe_ctx, exe_ctx.GetRegisterContext(), LLDB_INVALID_ADDRESS,
      /*initial_value_ptr=*/nullptr,
      /*object_address_ptr=*/nullptr);
  if (!callee_addr_val) {
    LLDB_LOG_ERROR(log, callee_addr_val.takeError(),
                   "IndirectCallEdge: Could not evaluate expression: {0}");
    return nullptr;
  }

  addr_t raw_addr =
      callee_addr_val->GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
  if (raw_addr == LLDB_INVALID_ADDRESS) {
    LLDB_LOG(log, "IndirectCallEdge: Could not extract address from scalar");
    return nullptr;
  }

  Address callee_addr;
  if (!exe_ctx.GetTargetPtr()->ResolveLoadAddress(raw_addr, callee_addr)) {
    LLDB_LOG(log, "IndirectCallEdge: Could not resolve callee's load address");
    return nullptr;
  }

  Function *f = callee_addr.CalculateSymbolContextFunction();
  if (!f) {
    LLDB_LOG(log, "IndirectCallEdge: Could not find complete function");
    return nullptr;
  }

  return f;
}

/// @}

//
Function::Function(CompileUnit *comp_unit, lldb::user_id_t func_uid,
                   lldb::user_id_t type_uid, const Mangled &mangled, Type *type,
                   Address address, AddressRanges ranges)
    : UserID(func_uid), m_comp_unit(comp_unit), m_type_uid(type_uid),
      m_type(type), m_mangled(mangled), m_block(*this, func_uid),
      m_address(std::move(address)), m_prologue_byte_size(0) {
  assert(comp_unit != nullptr);
  lldb::addr_t base_file_addr = m_address.GetFileAddress();
  for (const AddressRange &range : ranges)
    m_block.AddRange(
        Block::Range(range.GetBaseAddress().GetFileAddress() - base_file_addr,
                     range.GetByteSize()));
  m_block.FinalizeRanges();
}

Function::~Function() = default;

void Function::GetStartLineSourceInfo(SupportFileSP &source_file_sp,
                                      uint32_t &line_no) {
  line_no = 0;
  source_file_sp.reset();

  if (m_comp_unit == nullptr)
    return;

  // Initialize m_type if it hasn't been initialized already
  GetType();

  if (m_type != nullptr && m_type->GetDeclaration().GetLine() != 0) {
    source_file_sp =
        std::make_shared<SupportFile>(m_type->GetDeclaration().GetFile());
    line_no = m_type->GetDeclaration().GetLine();
  } else {
    LineTable *line_table = m_comp_unit->GetLineTable();
    if (line_table == nullptr)
      return;

    LineEntry line_entry;
    if (line_table->FindLineEntryByAddress(GetAddress(), line_entry, nullptr)) {
      line_no = line_entry.line;
      source_file_sp = line_entry.file_sp;
    }
  }
}

llvm::Expected<std::pair<SupportFileSP, Function::SourceRange>>
Function::GetSourceInfo() {
  SupportFileSP source_file_sp;
  uint32_t start_line;
  GetStartLineSourceInfo(source_file_sp, start_line);
  LineTable *line_table = m_comp_unit->GetLineTable();
  if (start_line == 0 || !line_table) {
    return llvm::createStringError(llvm::formatv(
        "Could not find line information for function \"{0}\".", GetName()));
  }

  uint32_t end_line = start_line;
  for (const AddressRange &range : GetAddressRanges()) {
    for (auto [idx, end] = line_table->GetLineEntryIndexRange(range); idx < end;
         ++idx) {
      LineEntry entry;
      // Ignore entries belonging to inlined functions or #included files.
      if (line_table->GetLineEntryAtIndex(idx, entry) &&
          source_file_sp->Equal(*entry.file_sp,
                                SupportFile::eEqualFileSpecAndChecksumIfSet))
        end_line = std::max(end_line, entry.line);
    }
  }
  return std::make_pair(std::move(source_file_sp),
                        SourceRange(start_line, end_line - start_line));
}

llvm::ArrayRef<std::unique_ptr<CallEdge>> Function::GetCallEdges() {
  std::lock_guard<std::mutex> guard(m_call_edges_lock);

  if (m_call_edges_resolved)
    return m_call_edges;

  Log *log = GetLog(LLDBLog::Step);
  LLDB_LOG(log, "GetCallEdges: Attempting to parse call site info for {0}",
           GetDisplayName());

  m_call_edges_resolved = true;

  // Find the SymbolFile which provided this function's definition.
  Block &block = GetBlock(/*can_create*/true);
  SymbolFile *sym_file = block.GetSymbolFile();
  if (!sym_file)
    return std::nullopt;

  // Lazily read call site information from the SymbolFile.
  m_call_edges = sym_file->ParseCallEdgesInFunction(GetID());

  // Sort the call edges to speed up return_pc lookups.
  llvm::sort(m_call_edges, [](const std::unique_ptr<CallEdge> &LHS,
                              const std::unique_ptr<CallEdge> &RHS) {
    return LHS->GetSortKey() < RHS->GetSortKey();
  });

  return m_call_edges;
}

llvm::ArrayRef<std::unique_ptr<CallEdge>> Function::GetTailCallingEdges() {
  // Tail calling edges are sorted at the end of the list. Find them by dropping
  // all non-tail-calls.
  return GetCallEdges().drop_until(
      [](const std::unique_ptr<CallEdge> &edge) { return edge->IsTailCall(); });
}

CallEdge *Function::GetCallEdgeForReturnAddress(addr_t return_pc,
                                                Target &target) {
  auto edges = GetCallEdges();
  auto edge_it =
      llvm::partition_point(edges, [&](const std::unique_ptr<CallEdge> &edge) {
        return std::make_pair(edge->IsTailCall(),
                              edge->GetReturnPCAddress(*this, target)) <
               std::make_pair(false, return_pc);
      });
  if (edge_it == edges.end() ||
      edge_it->get()->GetReturnPCAddress(*this, target) != return_pc)
    return nullptr;
  return edge_it->get();
}

Block &Function::GetBlock(bool can_create) {
  if (!m_block.BlockInfoHasBeenParsed() && can_create) {
    ModuleSP module_sp = CalculateSymbolContextModule();
    if (module_sp) {
      module_sp->GetSymbolFile()->ParseBlocksRecursive(*this);
    } else {
      Debugger::ReportError(llvm::formatv(
          "unable to find module shared pointer for function '{0}' in {1}",
          GetName().GetCString(), m_comp_unit->GetPrimaryFile().GetPath()));
    }
    m_block.SetBlockInfoHasBeenParsed(true, true);
  }
  return m_block;
}

CompileUnit *Function::GetCompileUnit() { return m_comp_unit; }

const CompileUnit *Function::GetCompileUnit() const { return m_comp_unit; }

void Function::GetDescription(Stream *s, lldb::DescriptionLevel level,
                              Target *target) {
  ConstString name = GetName();
  ConstString mangled = m_mangled.GetMangledName();

  *s << "id = " << (const UserID &)*this;
  if (name)
    s->AsRawOstream() << ", name = \"" << name << '"';
  if (mangled)
    s->AsRawOstream() << ", mangled = \"" << mangled << '"';
  if (level == eDescriptionLevelVerbose) {
    *s << ", decl_context = {";
    auto decl_context = GetCompilerContext();
    // Drop the function itself from the context chain.
    if (decl_context.size())
      decl_context.pop_back();
    llvm::interleaveComma(decl_context, *s, [&](auto &ctx) { ctx.Dump(*s); });
    *s << "}";
  }
  *s << ", range" << (m_block.GetNumRanges() > 1 ? "s" : "") << " = ";
  Address::DumpStyle fallback_style =
      level == eDescriptionLevelVerbose
          ? Address::DumpStyleModuleWithFileAddress
          : Address::DumpStyleFileAddress;
  for (unsigned idx = 0; idx < m_block.GetNumRanges(); ++idx) {
    AddressRange range;
    m_block.GetRangeAtIndex(idx, range);
    range.Dump(s, target, Address::DumpStyleLoadAddress, fallback_style);
  }
}

void Function::Dump(Stream *s, bool show_context) const {
  s->Printf("%p: ", static_cast<const void *>(this));
  s->Indent();
  *s << "Function" << static_cast<const UserID &>(*this);

  m_mangled.Dump(s);

  if (m_type)
    s->Printf(", type = %p", static_cast<void *>(m_type));
  else if (m_type_uid != LLDB_INVALID_UID)
    s->Printf(", type_uid = 0x%8.8" PRIx64, m_type_uid);

  s->EOL();
  // Dump the root object
  if (m_block.BlockInfoHasBeenParsed())
    m_block.Dump(s, m_address.GetFileAddress(), INT_MAX, show_context);
}

void Function::CalculateSymbolContext(SymbolContext *sc) {
  sc->function = this;
  m_comp_unit->CalculateSymbolContext(sc);
}

ModuleSP Function::CalculateSymbolContextModule() {
  if (SectionSP section_sp = m_address.GetSection())
    return section_sp->GetModule();

  return this->GetCompileUnit()->GetModule();
}

CompileUnit *Function::CalculateSymbolContextCompileUnit() {
  return this->GetCompileUnit();
}

Function *Function::CalculateSymbolContextFunction() { return this; }

lldb::DisassemblerSP Function::GetInstructions(const ExecutionContext &exe_ctx,
                                               const char *flavor,
                                               bool prefer_file_cache) {
  ModuleSP module_sp = GetAddress().GetModule();
  if (module_sp && exe_ctx.HasTargetScope()) {
    return Disassembler::DisassembleRange(
        module_sp->GetArchitecture(), nullptr, nullptr, nullptr, flavor,
        exe_ctx.GetTargetRef(), GetAddressRanges(), !prefer_file_cache);
  }
  return lldb::DisassemblerSP();
}

bool Function::GetDisassembly(const ExecutionContext &exe_ctx,
                              const char *flavor, Stream &strm,
                              bool prefer_file_cache) {
  lldb::DisassemblerSP disassembler_sp =
      GetInstructions(exe_ctx, flavor, prefer_file_cache);
  if (disassembler_sp) {
    const bool show_address = true;
    const bool show_bytes = false;
    const bool show_control_flow_kind = false;
    disassembler_sp->GetInstructionList().Dump(
        &strm, show_address, show_bytes, show_control_flow_kind, &exe_ctx);
    return true;
  }
  return false;
}

// Symbol *
// Function::CalculateSymbolContextSymbol ()
//{
//    return // TODO: find the symbol for the function???
//}

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

size_t Function::MemorySize() const {
  size_t mem_size = sizeof(Function) + m_block.MemorySize();
  return mem_size;
}

bool Function::GetIsOptimized() {
  bool result = false;

  // Currently optimization is only indicted by the vendor extension
  // DW_AT_APPLE_optimized which is set on a compile unit level.
  if (m_comp_unit) {
    result = m_comp_unit->GetIsOptimized();
  }
  return result;
}

bool Function::IsTopLevelFunction() {
  bool result = false;

  if (Language *language = Language::FindPlugin(GetLanguage()))
    result = language->IsTopLevelFunction(*this);

  return result;
}

ConstString Function::GetDisplayName() const {
  return m_mangled.GetDisplayDemangledName();
}

CompilerDeclContext Function::GetDeclContext() {
  if (ModuleSP module_sp = CalculateSymbolContextModule())
    if (SymbolFile *sym_file = module_sp->GetSymbolFile())
      return sym_file->GetDeclContextForUID(GetID());
  return {};
}

std::vector<CompilerContext> Function::GetCompilerContext() {
  if (ModuleSP module_sp = CalculateSymbolContextModule())
    if (SymbolFile *sym_file = module_sp->GetSymbolFile())
      return sym_file->GetCompilerContextForUID(GetID());
  return {};
}

Type *Function::GetType() {
  if (m_type == nullptr) {
    SymbolContext sc;

    CalculateSymbolContext(&sc);

    if (!sc.module_sp)
      return nullptr;

    SymbolFile *sym_file = sc.module_sp->GetSymbolFile();

    if (sym_file == nullptr)
      return nullptr;

    m_type = sym_file->ResolveTypeUID(m_type_uid);
  }
  return m_type;
}

const Type *Function::GetType() const { return m_type; }

CompilerType Function::GetCompilerType() {
  Type *function_type = GetType();
  if (function_type)
    return function_type->GetFullCompilerType();
  return CompilerType();
}

uint32_t Function::GetPrologueByteSize() {
  if (m_prologue_byte_size == 0 &&
      m_flags.IsClear(flagsCalculatedPrologueSize)) {
    m_flags.Set(flagsCalculatedPrologueSize);
    LineTable *line_table = m_comp_unit->GetLineTable();
    uint32_t prologue_end_line_idx = 0;

    if (line_table) {
      LineEntry first_line_entry;
      uint32_t first_line_entry_idx = UINT32_MAX;
      if (line_table->FindLineEntryByAddress(GetAddress(), first_line_entry,
                                             &first_line_entry_idx)) {
        // Make sure the first line entry isn't already the end of the prologue
        addr_t prologue_end_file_addr = LLDB_INVALID_ADDRESS;
        addr_t line_zero_end_file_addr = LLDB_INVALID_ADDRESS;

        if (first_line_entry.is_prologue_end) {
          prologue_end_file_addr =
              first_line_entry.range.GetBaseAddress().GetFileAddress();
          prologue_end_line_idx = first_line_entry_idx;
        } else {
          // Check the first few instructions and look for one that has
          // is_prologue_end set to true.
          const uint32_t last_line_entry_idx = first_line_entry_idx + 6;
          for (uint32_t idx = first_line_entry_idx + 1;
               idx < last_line_entry_idx; ++idx) {
            LineEntry line_entry;
            if (line_table->GetLineEntryAtIndex(idx, line_entry)) {
              if (line_entry.is_prologue_end) {
                prologue_end_file_addr =
                    line_entry.range.GetBaseAddress().GetFileAddress();
                prologue_end_line_idx = idx;
                break;
              }
            }
          }
        }

        // If we didn't find the end of the prologue in the line tables, then
        // just use the end address of the first line table entry
        if (prologue_end_file_addr == LLDB_INVALID_ADDRESS) {
          // Check the first few instructions and look for one that has a line
          // number that's different than the first entry.
          uint32_t last_line_entry_idx = first_line_entry_idx + 6;
          for (uint32_t idx = first_line_entry_idx + 1;
               idx < last_line_entry_idx; ++idx) {
            LineEntry line_entry;
            if (line_table->GetLineEntryAtIndex(idx, line_entry)) {
              if (line_entry.line != first_line_entry.line) {
                prologue_end_file_addr =
                    line_entry.range.GetBaseAddress().GetFileAddress();
                prologue_end_line_idx = idx;
                break;
              }
            }
          }

          if (prologue_end_file_addr == LLDB_INVALID_ADDRESS) {
            prologue_end_file_addr =
                first_line_entry.range.GetBaseAddress().GetFileAddress() +
                first_line_entry.range.GetByteSize();
            prologue_end_line_idx = first_line_entry_idx;
          }
        }

        AddressRange entry_range;
        m_block.GetRangeContainingAddress(m_address, entry_range);

        // Deliberately not starting at entry_range.GetBaseAddress() because the
        // function entry point need not be the first address in the range.
        const addr_t func_start_file_addr = m_address.GetFileAddress();
        const addr_t range_end_file_addr =
            entry_range.GetBaseAddress().GetFileAddress() +
            entry_range.GetByteSize();

        // Now calculate the offset to pass the subsequent line 0 entries.
        uint32_t first_non_zero_line = prologue_end_line_idx;
        while (true) {
          LineEntry line_entry;
          if (line_table->GetLineEntryAtIndex(first_non_zero_line,
                                              line_entry)) {
            if (line_entry.line != 0)
              break;
          }
          if (line_entry.range.GetBaseAddress().GetFileAddress() >=
              range_end_file_addr)
            break;

          first_non_zero_line++;
        }

        if (first_non_zero_line > prologue_end_line_idx) {
          LineEntry first_non_zero_entry;
          if (line_table->GetLineEntryAtIndex(first_non_zero_line,
                                              first_non_zero_entry)) {
            line_zero_end_file_addr =
                first_non_zero_entry.range.GetBaseAddress().GetFileAddress();
          }
        }

        // Verify that this prologue end file address inside the function just
        // to be sure
        if (func_start_file_addr < prologue_end_file_addr &&
            prologue_end_file_addr < range_end_file_addr) {
          m_prologue_byte_size = prologue_end_file_addr - func_start_file_addr;
        }

        if (prologue_end_file_addr < line_zero_end_file_addr &&
            line_zero_end_file_addr < range_end_file_addr) {
          m_prologue_byte_size +=
              line_zero_end_file_addr - prologue_end_file_addr;
        }
      }
    }
  }

  return m_prologue_byte_size;
}

lldb::LanguageType Function::GetLanguage() const {
  lldb::LanguageType lang = m_mangled.GuessLanguage();
  if (lang != lldb::eLanguageTypeUnknown)
    return lang;

  if (m_comp_unit)
    return m_comp_unit->GetLanguage();

  return lldb::eLanguageTypeUnknown;
}

ConstString Function::GetName() const {
  return m_mangled.GetName();
}

ConstString Function::GetNameNoArguments() const {
  return m_mangled.GetName(Mangled::ePreferDemangledWithoutArguments);
}
