//===- IRSymtab.cpp - implementation of IR symbol tables ------------------===//
//
// 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 "llvm/Object/IRSymtab.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Bitcode/BitcodeReader.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/IR/Comdat.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/GlobalAlias.h"
#include "llvm/IR/GlobalObject.h"
#include "llvm/IR/Mangler.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/RuntimeLibcalls.h"
#include "llvm/MC/StringTableBuilder.h"
#include "llvm/Object/ModuleSymbolTable.h"
#include "llvm/Object/SymbolicFile.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/StringSaver.h"
#include "llvm/Support/VCSRevision.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TargetParser/Triple.h"
#include <cassert>
#include <string>
#include <utility>
#include <vector>

using namespace llvm;
using namespace irsymtab;

static cl::opt<bool> DisableBitcodeVersionUpgrade(
    "disable-bitcode-version-upgrade", cl::Hidden,
    cl::desc("Disable automatic bitcode upgrade for version mismatch"));

namespace {

const char *getExpectedProducerName() {
  static char DefaultName[] = LLVM_VERSION_STRING
#ifdef LLVM_REVISION
      " " LLVM_REVISION
#endif
      ;
  // Allows for testing of the irsymtab writer and upgrade mechanism. This
  // environment variable should not be set by users.
  if (char *OverrideName = getenv("LLVM_OVERRIDE_PRODUCER"))
    return OverrideName;
  return DefaultName;
}

const char *kExpectedProducerName = getExpectedProducerName();

/// Stores the temporary state that is required to build an IR symbol table.
struct Builder {
  SmallVector<char, 0> &Symtab;
  StringTableBuilder &StrtabBuilder;
  StringSaver Saver;

  // This ctor initializes a StringSaver using the passed in BumpPtrAllocator.
  // The StringTableBuilder does not create a copy of any strings added to it,
  // so this provides somewhere to store any strings that we create.
  Builder(SmallVector<char, 0> &Symtab, StringTableBuilder &StrtabBuilder,
          BumpPtrAllocator &Alloc, const Triple &TT)
      : Symtab(Symtab), StrtabBuilder(StrtabBuilder), Saver(Alloc), TT(TT),
        Libcalls(TT) {}

  DenseMap<const Comdat *, int> ComdatMap;
  Mangler Mang;
  const Triple &TT;

  // FIXME: This shouldn't be here.
  RTLIB::RuntimeLibcallsInfo Libcalls;

  std::vector<storage::Comdat> Comdats;
  std::vector<storage::Module> Mods;
  std::vector<storage::Symbol> Syms;
  std::vector<storage::Uncommon> Uncommons;

  std::string COFFLinkerOpts;
  raw_string_ostream COFFLinkerOptsOS{COFFLinkerOpts};

  std::vector<storage::Str> DependentLibraries;

  bool isPreservedName(StringRef Name) {
    return Libcalls.getSupportedLibcallImpl(Name) != RTLIB::Unsupported;
  }

  void setStr(storage::Str &S, StringRef Value) {
    S.Offset = StrtabBuilder.add(Value);
    S.Size = Value.size();
  }

  template <typename T>
  void writeRange(storage::Range<T> &R, const std::vector<T> &Objs) {
    R.Offset = Symtab.size();
    R.Size = Objs.size();
    Symtab.insert(Symtab.end(), reinterpret_cast<const char *>(Objs.data()),
                  reinterpret_cast<const char *>(Objs.data() + Objs.size()));
  }

  Expected<int> getComdatIndex(const Comdat *C, const Module *M);

  Error addModule(Module *M);
  Error addSymbol(const ModuleSymbolTable &Msymtab,
                  const SmallPtrSet<GlobalValue *, 4> &Used,
                  ModuleSymbolTable::Symbol Sym);

  Error build(ArrayRef<Module *> Mods);
};

Error Builder::addModule(Module *M) {
  if (M->getDataLayoutStr().empty())
    return make_error<StringError>("input module has no datalayout",
                                   inconvertibleErrorCode());

  // Symbols in the llvm.used list will get the FB_Used bit and will not be
  // internalized. We do this for llvm.compiler.used as well:
  //
  // IR symbol table tracks module-level asm symbol references but not inline
  // asm. A symbol only referenced by inline asm is not in the IR symbol table,
  // so we may not know that the definition (in another translation unit) is
  // referenced. That definition may have __attribute__((used)) (which lowers to
  // llvm.compiler.used on ELF targets) to communicate to the compiler that it
  // may be used by inline asm. The usage is perfectly fine, so we treat
  // llvm.compiler.used conservatively as llvm.used to work around our own
  // limitation.
  SmallVector<GlobalValue *, 4> UsedV;
  collectUsedGlobalVariables(*M, UsedV, /*CompilerUsed=*/false);
  collectUsedGlobalVariables(*M, UsedV, /*CompilerUsed=*/true);
  SmallPtrSet<GlobalValue *, 4> Used(llvm::from_range, UsedV);

  ModuleSymbolTable Msymtab;
  Msymtab.addModule(M);

  storage::Module Mod;
  Mod.Begin = Syms.size();
  Mod.End = Syms.size() + Msymtab.symbols().size();
  Mod.UncBegin = Uncommons.size();
  Mods.push_back(Mod);

  if (TT.isOSBinFormatCOFF()) {
    if (auto E = M->materializeMetadata())
      return E;
    if (NamedMDNode *LinkerOptions =
            M->getNamedMetadata("llvm.linker.options")) {
      for (MDNode *MDOptions : LinkerOptions->operands())
        for (const MDOperand &MDOption : cast<MDNode>(MDOptions)->operands())
          COFFLinkerOptsOS << " " << cast<MDString>(MDOption)->getString();
    }
  }

  if (TT.isOSBinFormatELF()) {
    if (auto E = M->materializeMetadata())
      return E;
    if (NamedMDNode *N = M->getNamedMetadata("llvm.dependent-libraries")) {
      for (MDNode *MDOptions : N->operands()) {
        const auto OperandStr =
            cast<MDString>(cast<MDNode>(MDOptions)->getOperand(0))->getString();
        storage::Str Specifier;
        setStr(Specifier, OperandStr);
        DependentLibraries.emplace_back(Specifier);
      }
    }
  }

  for (ModuleSymbolTable::Symbol Msym : Msymtab.symbols())
    if (Error Err = addSymbol(Msymtab, Used, Msym))
      return Err;

  return Error::success();
}

Expected<int> Builder::getComdatIndex(const Comdat *C, const Module *M) {
  auto P = ComdatMap.insert(std::make_pair(C, Comdats.size()));
  if (P.second) {
    std::string Name;
    if (TT.isOSBinFormatCOFF()) {
      const GlobalValue *GV = M->getNamedValue(C->getName());
      if (!GV)
        return make_error<StringError>("Could not find leader",
                                       inconvertibleErrorCode());
      // Internal leaders do not affect symbol resolution, therefore they do not
      // appear in the symbol table.
      if (GV->hasLocalLinkage()) {
        P.first->second = -1;
        return -1;
      }
      llvm::raw_string_ostream OS(Name);
      Mang.getNameWithPrefix(OS, GV, false);
    } else {
      Name = std::string(C->getName());
    }

    storage::Comdat Comdat;
    setStr(Comdat.Name, Saver.save(Name));
    Comdat.SelectionKind = C->getSelectionKind();
    Comdats.push_back(Comdat);
  }

  return P.first->second;
}

Error Builder::addSymbol(const ModuleSymbolTable &Msymtab,
                         const SmallPtrSet<GlobalValue *, 4> &Used,
                         ModuleSymbolTable::Symbol Msym) {
  Syms.emplace_back();
  storage::Symbol &Sym = Syms.back();
  Sym = {};

  storage::Uncommon *Unc = nullptr;
  auto Uncommon = [&]() -> storage::Uncommon & {
    if (Unc)
      return *Unc;
    Sym.Flags |= 1 << storage::Symbol::FB_has_uncommon;
    Uncommons.emplace_back();
    Unc = &Uncommons.back();
    *Unc = {};
    setStr(Unc->COFFWeakExternFallbackName, "");
    setStr(Unc->SectionName, "");
    return *Unc;
  };

  SmallString<64> Name;
  {
    raw_svector_ostream OS(Name);
    Msymtab.printSymbolName(OS, Msym);
  }
  setStr(Sym.Name, Saver.save(Name.str()));

  auto Flags = Msymtab.getSymbolFlags(Msym);
  if (Flags & object::BasicSymbolRef::SF_Undefined)
    Sym.Flags |= 1 << storage::Symbol::FB_undefined;
  if (Flags & object::BasicSymbolRef::SF_Weak)
    Sym.Flags |= 1 << storage::Symbol::FB_weak;
  if (Flags & object::BasicSymbolRef::SF_Common)
    Sym.Flags |= 1 << storage::Symbol::FB_common;
  if (Flags & object::BasicSymbolRef::SF_Indirect)
    Sym.Flags |= 1 << storage::Symbol::FB_indirect;
  if (Flags & object::BasicSymbolRef::SF_Global)
    Sym.Flags |= 1 << storage::Symbol::FB_global;
  if (Flags & object::BasicSymbolRef::SF_FormatSpecific)
    Sym.Flags |= 1 << storage::Symbol::FB_format_specific;
  if (Flags & object::BasicSymbolRef::SF_Executable)
    Sym.Flags |= 1 << storage::Symbol::FB_executable;

  Sym.ComdatIndex = -1;
  auto *GV = dyn_cast_if_present<GlobalValue *>(Msym);
  if (!GV) {
    // Undefined module asm symbols act as GC roots and are implicitly used.
    if (Flags & object::BasicSymbolRef::SF_Undefined)
      Sym.Flags |= 1 << storage::Symbol::FB_used;
    setStr(Sym.IRName, "");
    return Error::success();
  }

  StringRef GVName = GV->getName();
  setStr(Sym.IRName, GVName);

  if (Used.count(GV) || isPreservedName(GVName))
    Sym.Flags |= 1 << storage::Symbol::FB_used;
  if (GV->isThreadLocal())
    Sym.Flags |= 1 << storage::Symbol::FB_tls;
  if (GV->hasGlobalUnnamedAddr())
    Sym.Flags |= 1 << storage::Symbol::FB_unnamed_addr;
  if (GV->canBeOmittedFromSymbolTable())
    Sym.Flags |= 1 << storage::Symbol::FB_may_omit;
  Sym.Flags |= unsigned(GV->getVisibility()) << storage::Symbol::FB_visibility;

  if (Flags & object::BasicSymbolRef::SF_Common) {
    auto *GVar = dyn_cast<GlobalVariable>(GV);
    if (!GVar)
      return make_error<StringError>("Only variables can have common linkage!",
                                     inconvertibleErrorCode());
    Uncommon().CommonSize =
        GV->getDataLayout().getTypeAllocSize(GV->getValueType());
    Uncommon().CommonAlign = GVar->getAlign() ? GVar->getAlign()->value() : 0;
  }

  const GlobalObject *GO = GV->getAliaseeObject();
  if (!GO) {
    if (isa<GlobalIFunc>(GV))
      GO = cast<GlobalIFunc>(GV)->getResolverFunction();
    if (!GO)
      return make_error<StringError>("Unable to determine comdat of alias!",
                                     inconvertibleErrorCode());
  }
  if (const Comdat *C = GO->getComdat()) {
    Expected<int> ComdatIndexOrErr = getComdatIndex(C, GV->getParent());
    if (!ComdatIndexOrErr)
      return ComdatIndexOrErr.takeError();
    Sym.ComdatIndex = *ComdatIndexOrErr;
  }

  if (TT.isOSBinFormatCOFF()) {
    emitLinkerFlagsForGlobalCOFF(COFFLinkerOptsOS, GV, TT, Mang);

    if ((Flags & object::BasicSymbolRef::SF_Weak) &&
        (Flags & object::BasicSymbolRef::SF_Indirect)) {
      auto *Fallback = dyn_cast<GlobalValue>(
          cast<GlobalAlias>(GV)->getAliasee()->stripPointerCasts());
      if (!Fallback)
        return make_error<StringError>("Invalid weak external",
                                       inconvertibleErrorCode());
      std::string FallbackName;
      raw_string_ostream OS(FallbackName);
      Msymtab.printSymbolName(OS, Fallback);
      OS.flush();
      setStr(Uncommon().COFFWeakExternFallbackName, Saver.save(FallbackName));
    }
  }

  if (!GO->getSection().empty())
    setStr(Uncommon().SectionName, Saver.save(GO->getSection()));

  return Error::success();
}

Error Builder::build(ArrayRef<Module *> IRMods) {
  storage::Header Hdr;

  assert(!IRMods.empty());
  Hdr.Version = storage::Header::kCurrentVersion;
  setStr(Hdr.Producer, kExpectedProducerName);
  setStr(Hdr.TargetTriple, IRMods[0]->getTargetTriple().str());
  setStr(Hdr.SourceFileName, IRMods[0]->getSourceFileName());

  for (auto *M : IRMods)
    if (Error Err = addModule(M))
      return Err;

  COFFLinkerOptsOS.flush();
  setStr(Hdr.COFFLinkerOpts, Saver.save(COFFLinkerOpts));

  // We are about to fill in the header's range fields, so reserve space for it
  // and copy it in afterwards.
  Symtab.resize(sizeof(storage::Header));
  writeRange(Hdr.Modules, Mods);
  writeRange(Hdr.Comdats, Comdats);
  writeRange(Hdr.Symbols, Syms);
  writeRange(Hdr.Uncommons, Uncommons);
  writeRange(Hdr.DependentLibraries, DependentLibraries);
  *reinterpret_cast<storage::Header *>(Symtab.data()) = Hdr;
  return Error::success();
}

} // end anonymous namespace

Error irsymtab::build(ArrayRef<Module *> Mods, SmallVector<char, 0> &Symtab,
                      StringTableBuilder &StrtabBuilder,
                      BumpPtrAllocator &Alloc) {
  const Triple &TT = Mods[0]->getTargetTriple();
  return Builder(Symtab, StrtabBuilder, Alloc, TT).build(Mods);
}

// Upgrade a vector of bitcode modules created by an old version of LLVM by
// creating an irsymtab for them in the current format.
static Expected<FileContents> upgrade(ArrayRef<BitcodeModule> BMs) {
  FileContents FC;

  LLVMContext Ctx;
  std::vector<Module *> Mods;
  std::vector<std::unique_ptr<Module>> OwnedMods;
  for (auto BM : BMs) {
    Expected<std::unique_ptr<Module>> MOrErr =
        BM.getLazyModule(Ctx, /*ShouldLazyLoadMetadata*/ true,
                         /*IsImporting*/ false);
    if (!MOrErr)
      return MOrErr.takeError();

    Mods.push_back(MOrErr->get());
    OwnedMods.push_back(std::move(*MOrErr));
  }

  StringTableBuilder StrtabBuilder(StringTableBuilder::RAW);
  BumpPtrAllocator Alloc;
  if (Error E = build(Mods, FC.Symtab, StrtabBuilder, Alloc))
    return std::move(E);

  StrtabBuilder.finalizeInOrder();
  FC.Strtab.resize(StrtabBuilder.getSize());
  StrtabBuilder.write((uint8_t *)FC.Strtab.data());

  FC.TheReader = {{FC.Symtab.data(), FC.Symtab.size()},
                  {FC.Strtab.data(), FC.Strtab.size()}};
  return std::move(FC);
}

Expected<FileContents> irsymtab::readBitcode(const BitcodeFileContents &BFC) {
  if (BFC.Mods.empty())
    return make_error<StringError>("Bitcode file does not contain any modules",
                                   inconvertibleErrorCode());

  if (!DisableBitcodeVersionUpgrade) {
    if (BFC.StrtabForSymtab.empty() ||
        BFC.Symtab.size() < sizeof(storage::Header))
      return upgrade(BFC.Mods);

    // We cannot use the regular reader to read the version and producer,
    // because it will expect the header to be in the current format. The only
    // thing we can rely on is that the version and producer will be present as
    // the first struct elements.
    auto *Hdr = reinterpret_cast<const storage::Header *>(BFC.Symtab.data());
    unsigned Version = Hdr->Version;
    StringRef Producer = Hdr->Producer.get(BFC.StrtabForSymtab);
    if (Version != storage::Header::kCurrentVersion ||
        Producer != kExpectedProducerName)
      return upgrade(BFC.Mods);
  }

  FileContents FC;
  FC.TheReader = {{BFC.Symtab.data(), BFC.Symtab.size()},
                  {BFC.StrtabForSymtab.data(), BFC.StrtabForSymtab.size()}};

  // Finally, make sure that the number of modules in the symbol table matches
  // the number of modules in the bitcode file. If they differ, it may mean that
  // the bitcode file was created by binary concatenation, so we need to create
  // a new symbol table from scratch.
  if (FC.TheReader.getNumModules() != BFC.Mods.size())
    return upgrade(std::move(BFC.Mods));

  return std::move(FC);
}
