//===----- COFFLinkGraphBuilder.h - COFF LinkGraph builder ----*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// Generic COFF LinkGraph building code.
//
//===----------------------------------------------------------------------===//

#ifndef LIB_EXECUTIONENGINE_JITLINK_COFFLINKGRAPHBUILDER_H
#define LIB_EXECUTIONENGINE_JITLINK_COFFLINKGRAPHBUILDER_H

#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ExecutionEngine/JITLink/JITLink.h"
#include "llvm/Object/COFF.h"

#include "COFFDirectiveParser.h"
#include "EHFrameSupportImpl.h"
#include "JITLinkGeneric.h"

#define DEBUG_TYPE "jitlink"

#include <list>

namespace llvm {
namespace jitlink {

class COFFLinkGraphBuilder {
public:
  virtual ~COFFLinkGraphBuilder();
  Expected<std::unique_ptr<LinkGraph>> buildGraph();

protected:
  using COFFSectionIndex = int32_t;
  using COFFSymbolIndex = int32_t;

  COFFLinkGraphBuilder(const object::COFFObjectFile &Obj, Triple TT,
                       LinkGraph::GetEdgeKindNameFunction GetEdgeKindName);

  LinkGraph &getGraph() const { return *G; }

  const object::COFFObjectFile &getObject() const { return Obj; }

  virtual Error addRelocations() = 0;

  Error graphifySections();
  Error graphifySymbols();

  void setGraphSymbol(COFFSectionIndex SecIndex, COFFSymbolIndex SymIndex,
                      Symbol &Sym) {
    assert(!GraphSymbols[SymIndex] && "Duplicate symbol at index");
    GraphSymbols[SymIndex] = &Sym;
    if (!COFF::isReservedSectionNumber(SecIndex))
      SymbolSets[SecIndex].insert({Sym.getOffset(), &Sym});
  }

  Symbol *getGraphSymbol(COFFSymbolIndex SymIndex) const {
    if (SymIndex < 0 ||
        SymIndex >= static_cast<COFFSymbolIndex>(GraphSymbols.size()))
      return nullptr;
    return GraphSymbols[SymIndex];
  }

  void setGraphBlock(COFFSectionIndex SecIndex, Block *B) {
    assert(!GraphBlocks[SecIndex] && "Duplicate section at index");
    assert(!COFF::isReservedSectionNumber(SecIndex) && "Invalid section index");
    GraphBlocks[SecIndex] = B;
  }

  Block *getGraphBlock(COFFSectionIndex SecIndex) const {
    if (SecIndex <= 0 ||
        SecIndex >= static_cast<COFFSectionIndex>(GraphSymbols.size()))
      return nullptr;
    return GraphBlocks[SecIndex];
  }

  object::COFFObjectFile::section_iterator_range sections() const {
    return Obj.sections();
  }

  /// Traverse all matching relocation records in the given section. The handler
  /// function Func should be callable with this signature:
  ///   Error(const object::RelocationRef&,
  ///         const object::SectionRef&, Section &)
  ///
  template <typename RelocHandlerFunction>
  Error forEachRelocation(const object::SectionRef &RelSec,
                          RelocHandlerFunction &&Func,
                          bool ProcessDebugSections = false);

  /// Traverse all matching relocation records in the given section. Convenience
  /// wrapper to allow passing a member function for the handler.
  ///
  template <typename ClassT, typename RelocHandlerMethod>
  Error forEachRelocation(const object::SectionRef &RelSec, ClassT *Instance,
                          RelocHandlerMethod &&Method,
                          bool ProcessDebugSections = false) {
    return forEachRelocation(
        RelSec,
        [Instance, Method](const auto &Rel, const auto &Target, auto &GS) {
          return (Instance->*Method)(Rel, Target, GS);
        },
        ProcessDebugSections);
  }

private:
  // Pending comdat symbol export that is initiated by the first symbol of
  // COMDAT sequence.
  struct ComdatExportRequest {
    COFFSymbolIndex SymbolIndex;
    jitlink::Linkage Linkage;
    orc::ExecutorAddrDiff Size;
  };
  std::vector<std::optional<ComdatExportRequest>> PendingComdatExports;

  // This represents a pending request to create a weak external symbol with a
  // name.
  struct WeakExternalRequest {
    COFFSymbolIndex Alias;
    COFFSymbolIndex Target;
    uint32_t Characteristics;
    StringRef SymbolName;
  };
  std::vector<WeakExternalRequest> WeakExternalRequests;

  // Per COFF section jitlink symbol set sorted by offset.
  // Used for calculating implicit size of defined symbols.
  using SymbolSet = std::set<std::pair<orc::ExecutorAddrDiff, Symbol *>>;
  std::vector<SymbolSet> SymbolSets;

  Section &getCommonSection();

  Symbol *createExternalSymbol(COFFSymbolIndex SymIndex, StringRef SymbolName,
                               object::COFFSymbolRef Symbol,
                               const object::coff_section *Section);
  Expected<Symbol *> createAliasSymbol(StringRef SymbolName, Linkage L, Scope S,
                                       Symbol &Target);
  Expected<Symbol *> createDefinedSymbol(COFFSymbolIndex SymIndex,
                                         StringRef SymbolName,
                                         object::COFFSymbolRef Symbol,
                                         const object::coff_section *Section);
  Expected<Symbol *> createCOMDATExportRequest(
      COFFSymbolIndex SymIndex, object::COFFSymbolRef Symbol,
      const object::coff_aux_section_definition *Definition);
  Expected<Symbol *> exportCOMDATSymbol(COFFSymbolIndex SymIndex,
                                        StringRef SymbolName,
                                        object::COFFSymbolRef Symbol);

  Error handleDirectiveSection(StringRef Str);
  Error flushWeakAliasRequests();
  Error handleAlternateNames();
  Error calculateImplicitSizeOfSymbols();

  static uint64_t getSectionAddress(const object::COFFObjectFile &Obj,
                                    const object::coff_section *Section);
  static uint64_t getSectionSize(const object::COFFObjectFile &Obj,
                                 const object::coff_section *Section);
  static bool isComdatSection(const object::coff_section *Section);
  static unsigned getPointerSize(const object::COFFObjectFile &Obj);
  static support::endianness getEndianness(const object::COFFObjectFile &Obj);
  static StringRef getDLLImportStubPrefix() { return "__imp_"; }
  static StringRef getDirectiveSectionName() { return ".drectve"; }
  StringRef getCOFFSectionName(COFFSectionIndex SectionIndex,
                               const object::coff_section *Sec,
                               object::COFFSymbolRef Sym);

  const object::COFFObjectFile &Obj;
  std::unique_ptr<LinkGraph> G;
  COFFDirectiveParser DirectiveParser;

  Section *CommonSection = nullptr;
  std::vector<Block *> GraphBlocks;
  std::vector<Symbol *> GraphSymbols;

  DenseMap<StringRef, StringRef> AlternateNames;
  DenseMap<StringRef, Symbol *> ExternalSymbols;
  DenseMap<StringRef, Symbol *> DefinedSymbols;
};

template <typename RelocHandlerFunction>
Error COFFLinkGraphBuilder::forEachRelocation(const object::SectionRef &RelSec,
                                              RelocHandlerFunction &&Func,
                                              bool ProcessDebugSections) {

  auto COFFRelSect = Obj.getCOFFSection(RelSec);

  // Target sections have names in valid COFF object files.
  Expected<StringRef> Name = Obj.getSectionName(COFFRelSect);
  if (!Name)
    return Name.takeError();
  LLVM_DEBUG(dbgs() << "  " << *Name << ":\n");

  // Lookup the link-graph node corresponding to the target section name.
  auto *BlockToFix = getGraphBlock(RelSec.getIndex() + 1);
  if (!BlockToFix)
    return make_error<StringError>(
        "Referencing a section that wasn't added to the graph: " + *Name,
        inconvertibleErrorCode());

  // Let the callee process relocation entries one by one.
  for (const auto &R : RelSec.relocations())
    if (Error Err = Func(R, RelSec, *BlockToFix))
      return Err;

  LLVM_DEBUG(dbgs() << "\n");
  return Error::success();
}

} // end namespace jitlink
} // end namespace llvm

#endif // LIB_EXECUTIONENGINE_JITLINK_COFFLINKGRAPHBUILDER_H
