//===-- llvm-libtool-darwin.cpp - a tool for creating libraries -----------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// A utility for creating static and dynamic libraries for Darwin.
//
//===----------------------------------------------------------------------===//

#include "llvm/BinaryFormat/Magic.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/Object/ArchiveWriter.h"
#include "llvm/Object/IRObjectFile.h"
#include "llvm/Object/MachO.h"
#include "llvm/Object/MachOUniversal.h"
#include "llvm/Object/MachOUniversalWriter.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/LineIterator.h"
#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/Support/WithColor.h"
#include "llvm/TextAPI/Architecture.h"
#include <map>

using namespace llvm;
using namespace llvm::object;

static LLVMContext LLVMCtx;

typedef std::map<uint64_t, std::vector<NewArchiveMember>>
    MembersPerArchitectureMap;

cl::OptionCategory LibtoolCategory("llvm-libtool-darwin Options");

static cl::opt<std::string> OutputFile("o", cl::desc("Specify output filename"),
                                       cl::value_desc("filename"),
                                       cl::cat(LibtoolCategory));

static cl::list<std::string> InputFiles(cl::Positional,
                                        cl::desc("<input files>"),
                                        cl::ZeroOrMore,
                                        cl::cat(LibtoolCategory));

static cl::opt<std::string> ArchType(
    "arch_only", cl::desc("Specify architecture type for output library"),
    cl::value_desc("arch_type"), cl::ZeroOrMore, cl::cat(LibtoolCategory));

enum class Operation { None, Static };

static cl::opt<Operation> LibraryOperation(
    cl::desc("Library Type: "),
    cl::values(
        clEnumValN(Operation::Static, "static",
                   "Produce a statically linked library from the input files")),
    cl::init(Operation::None), cl::cat(LibtoolCategory));

static cl::opt<bool> DeterministicOption(
    "D", cl::desc("Use zero for timestamps and UIDs/GIDs (Default)"),
    cl::init(false), cl::cat(LibtoolCategory));

static cl::opt<bool>
    NonDeterministicOption("U", cl::desc("Use actual timestamps and UIDs/GIDs"),
                           cl::init(false), cl::cat(LibtoolCategory));

static cl::opt<std::string>
    FileList("filelist",
             cl::desc("Pass in file containing a list of filenames"),
             cl::value_desc("listfile[,dirname]"), cl::cat(LibtoolCategory));

static cl::list<std::string> Libraries(
    "l",
    cl::desc(
        "l<x> searches for the library libx.a in the library search path. If"
        " the string 'x' ends with '.o', then the library 'x' is searched for"
        " without prepending 'lib' or appending '.a'"),
    cl::ZeroOrMore, cl::Prefix, cl::cat(LibtoolCategory));

static cl::list<std::string> LibrarySearchDirs(
    "L",
    cl::desc(
        "L<dir> adds <dir> to the list of directories in which to search for"
        " libraries"),
    cl::ZeroOrMore, cl::Prefix, cl::cat(LibtoolCategory));

static cl::opt<bool>
    VersionOption("V", cl::desc("Print the version number and exit"),
                  cl::cat(LibtoolCategory));

static cl::opt<bool> NoWarningForNoSymbols(
    "no_warning_for_no_symbols",
    cl::desc("Do not warn about files that have no symbols"),
    cl::cat(LibtoolCategory), cl::init(false));

static const std::array<std::string, 3> StandardSearchDirs{
    "/lib",
    "/usr/lib",
    "/usr/local/lib",
};

struct Config {
  bool Deterministic = true; // Updated by 'D' and 'U' modifiers.
  uint32_t ArchCPUType;
  uint32_t ArchCPUSubtype;
};

static Expected<std::string> searchForFile(const Twine &FileName) {

  auto FindLib =
      [FileName](ArrayRef<std::string> SearchDirs) -> Optional<std::string> {
    for (StringRef Dir : SearchDirs) {
      SmallString<128> Path;
      sys::path::append(Path, Dir, FileName);

      if (sys::fs::exists(Path))
        return std::string(Path);
    }
    return None;
  };

  Optional<std::string> Found = FindLib(LibrarySearchDirs);
  if (!Found)
    Found = FindLib(StandardSearchDirs);
  if (Found)
    return *Found;

  return createStringError(std::errc::invalid_argument,
                           "cannot locate file '%s'", FileName.str().c_str());
}

static Error processCommandLineLibraries() {
  for (StringRef BaseName : Libraries) {
    Expected<std::string> FullPath = searchForFile(
        BaseName.endswith(".o") ? BaseName.str() : "lib" + BaseName + ".a");
    if (!FullPath)
      return FullPath.takeError();
    InputFiles.push_back(FullPath.get());
  }

  return Error::success();
}

static Error processFileList() {
  StringRef FileName, DirName;
  std::tie(FileName, DirName) = StringRef(FileList).rsplit(",");

  ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
      MemoryBuffer::getFileOrSTDIN(FileName, /*IsText=*/false,
                                   /*RequiresNullTerminator=*/false);
  if (std::error_code EC = FileOrErr.getError())
    return createFileError(FileName, errorCodeToError(EC));
  const MemoryBuffer &Ref = *FileOrErr.get();

  line_iterator I(Ref, /*SkipBlanks=*/false);
  if (I.is_at_eof())
    return createStringError(std::errc::invalid_argument,
                             "file list file: '%s' is empty",
                             FileName.str().c_str());
  for (; !I.is_at_eof(); ++I) {
    StringRef Line = *I;
    if (Line.empty())
      return createStringError(std::errc::invalid_argument,
                               "file list file: '%s': filename cannot be empty",
                               FileName.str().c_str());

    SmallString<128> Path;
    if (!DirName.empty())
      sys::path::append(Path, DirName, Line);
    else
      sys::path::append(Path, Line);
    InputFiles.push_back(static_cast<std::string>(Path));
  }
  return Error::success();
}

static Error validateArchitectureName(StringRef ArchitectureName) {
  if (!MachOObjectFile::isValidArch(ArchitectureName)) {
    std::string Buf;
    raw_string_ostream OS(Buf);
    for (StringRef Arch : MachOObjectFile::getValidArchs())
      OS << Arch << " ";

    return createStringError(
        std::errc::invalid_argument,
        "invalid architecture '%s': valid architecture names are %s",
        ArchitectureName.str().c_str(), OS.str().c_str());
  }
  return Error::success();
}

static uint64_t getCPUID(uint32_t CPUType, uint32_t CPUSubtype) {
  switch (CPUType) {
  case MachO::CPU_TYPE_ARM:
  case MachO::CPU_TYPE_ARM64:
  case MachO::CPU_TYPE_ARM64_32:
  case MachO::CPU_TYPE_X86_64:
    // We consider CPUSubtype only for the above 4 CPUTypes to match cctools'
    // libtool behavior.
    return static_cast<uint64_t>(CPUType) << 32 | CPUSubtype;
  default:
    return CPUType;
  }
}

// Check that a file's architecture [FileCPUType, FileCPUSubtype]
// matches the architecture specified under -arch_only flag.
static bool acceptFileArch(uint32_t FileCPUType, uint32_t FileCPUSubtype,
                           const Config &C) {
  if (C.ArchCPUType != FileCPUType)
    return false;

  switch (C.ArchCPUType) {
  case MachO::CPU_TYPE_ARM:
  case MachO::CPU_TYPE_ARM64_32:
  case MachO::CPU_TYPE_X86_64:
    return C.ArchCPUSubtype == FileCPUSubtype;

  case MachO::CPU_TYPE_ARM64:
    if (C.ArchCPUSubtype == MachO::CPU_SUBTYPE_ARM64_ALL)
      return FileCPUSubtype == MachO::CPU_SUBTYPE_ARM64_ALL ||
             FileCPUSubtype == MachO::CPU_SUBTYPE_ARM64_V8;
    else
      return C.ArchCPUSubtype == FileCPUSubtype;

  default:
    return true;
  }
}

static Error verifyAndAddMachOObject(MembersPerArchitectureMap &Members,
                                     NewArchiveMember Member, const Config &C) {
  auto MBRef = Member.Buf->getMemBufferRef();
  Expected<std::unique_ptr<object::ObjectFile>> ObjOrErr =
      object::ObjectFile::createObjectFile(MBRef);

  // Throw error if not a valid object file.
  if (!ObjOrErr)
    return createFileError(Member.MemberName, ObjOrErr.takeError());

  // Throw error if not in Mach-O format.
  if (!isa<object::MachOObjectFile>(**ObjOrErr))
    return createStringError(std::errc::invalid_argument,
                             "'%s': format not supported",
                             Member.MemberName.data());

  auto *O = dyn_cast<MachOObjectFile>(ObjOrErr->get());
  uint32_t FileCPUType, FileCPUSubtype;
  std::tie(FileCPUType, FileCPUSubtype) = MachO::getCPUTypeFromArchitecture(
      MachO::getArchitectureFromName(O->getArchTriple().getArchName()));

  // If -arch_only is specified then skip this file if it doesn't match
  // the architecture specified.
  if (!ArchType.empty() && !acceptFileArch(FileCPUType, FileCPUSubtype, C)) {
    return Error::success();
  }

  if (!NoWarningForNoSymbols && O->symbols().empty())
    WithColor::warning() << Member.MemberName + " has no symbols\n";

  uint64_t FileCPUID = getCPUID(FileCPUType, FileCPUSubtype);
  Members[FileCPUID].push_back(std::move(Member));
  return Error::success();
}

static Error verifyAndAddIRObject(MembersPerArchitectureMap &Members,
                                  NewArchiveMember Member, const Config &C) {
  auto MBRef = Member.Buf->getMemBufferRef();
  Expected<std::unique_ptr<object::IRObjectFile>> IROrErr =
      object::IRObjectFile::create(MBRef, LLVMCtx);

  // Throw error if not a valid IR object file.
  if (!IROrErr)
    return createFileError(Member.MemberName, IROrErr.takeError());

  Triple TT = Triple(IROrErr->get()->getTargetTriple());

  Expected<uint32_t> FileCPUTypeOrErr = MachO::getCPUType(TT);
  if (!FileCPUTypeOrErr)
    return FileCPUTypeOrErr.takeError();

  Expected<uint32_t> FileCPUSubTypeOrErr = MachO::getCPUSubType(TT);
  if (!FileCPUSubTypeOrErr)
    return FileCPUSubTypeOrErr.takeError();

  // If -arch_only is specified then skip this file if it doesn't match
  // the architecture specified.
  if (!ArchType.empty() &&
      !acceptFileArch(*FileCPUTypeOrErr, *FileCPUSubTypeOrErr, C)) {
    return Error::success();
  }

  uint64_t FileCPUID = getCPUID(*FileCPUTypeOrErr, *FileCPUSubTypeOrErr);
  Members[FileCPUID].push_back(std::move(Member));
  return Error::success();
}

static Error addChildMember(MembersPerArchitectureMap &Members,
                            const object::Archive::Child &M, const Config &C) {
  Expected<NewArchiveMember> NMOrErr =
      NewArchiveMember::getOldMember(M, C.Deterministic);
  if (!NMOrErr)
    return NMOrErr.takeError();

  file_magic Magic = identify_magic(NMOrErr->Buf->getBuffer());

  if (Magic == file_magic::bitcode)
    return verifyAndAddIRObject(Members, std::move(*NMOrErr), C);

  if (Error E = verifyAndAddMachOObject(Members, std::move(*NMOrErr), C))
    return E;

  return Error::success();
}

static Error processArchive(MembersPerArchitectureMap &Members,
                            object::Archive &Lib, StringRef FileName,
                            const Config &C) {
  Error Err = Error::success();
  for (const object::Archive::Child &Child : Lib.children(Err))
    if (Error E = addChildMember(Members, Child, C))
      return createFileError(FileName, std::move(E));
  if (Err)
    return createFileError(FileName, std::move(Err));

  return Error::success();
}

static Error
addArchiveMembers(MembersPerArchitectureMap &Members,
                  std::vector<std::unique_ptr<MemoryBuffer>> &ArchiveBuffers,
                  NewArchiveMember NM, StringRef FileName, const Config &C) {
  Expected<std::unique_ptr<Archive>> LibOrErr =
      object::Archive::create(NM.Buf->getMemBufferRef());
  if (!LibOrErr)
    return createFileError(FileName, LibOrErr.takeError());

  if (Error E = processArchive(Members, **LibOrErr, FileName, C))
    return E;

  // Update vector ArchiveBuffers with the MemoryBuffers to transfer
  // ownership.
  ArchiveBuffers.push_back(std::move(NM.Buf));
  return Error::success();
}

static Error addUniversalMembers(
    MembersPerArchitectureMap &Members,
    std::vector<std::unique_ptr<MemoryBuffer>> &UniversalBuffers,
    NewArchiveMember NM, StringRef FileName, const Config &C) {
  Expected<std::unique_ptr<MachOUniversalBinary>> BinaryOrErr =
      MachOUniversalBinary::create(NM.Buf->getMemBufferRef());
  if (!BinaryOrErr)
    return createFileError(FileName, BinaryOrErr.takeError());

  auto *UO = BinaryOrErr->get();
  for (const MachOUniversalBinary::ObjectForArch &O : UO->objects()) {

    Expected<std::unique_ptr<MachOObjectFile>> MachOObjOrErr =
        O.getAsObjectFile();
    if (MachOObjOrErr) {
      NewArchiveMember NewMember =
          NewArchiveMember(MachOObjOrErr->get()->getMemoryBufferRef());
      NewMember.MemberName = sys::path::filename(NewMember.MemberName);

      if (Error E = verifyAndAddMachOObject(Members, std::move(NewMember), C))
        return E;
      continue;
    }

    Expected<std::unique_ptr<IRObjectFile>> IRObjectOrError =
        O.getAsIRObject(LLVMCtx);
    if (IRObjectOrError) {
      // A universal file member can be a MachOObjectFile, an IRObject or an
      // Archive. In case we can successfully cast the member as an IRObject, it
      // is safe to throw away the error generated due to casting the object as
      // a MachOObjectFile.
      consumeError(MachOObjOrErr.takeError());

      NewArchiveMember NewMember =
          NewArchiveMember(IRObjectOrError->get()->getMemoryBufferRef());
      NewMember.MemberName = sys::path::filename(NewMember.MemberName);

      if (Error E = verifyAndAddIRObject(Members, std::move(NewMember), C))
        return E;
      continue;
    }

    Expected<std::unique_ptr<Archive>> ArchiveOrError = O.getAsArchive();
    if (ArchiveOrError) {
      // A universal file member can be a MachOObjectFile, an IRObject or an
      // Archive. In case we can successfully cast the member as an Archive, it
      // is safe to throw away the error generated due to casting the object as
      // a MachOObjectFile.
      consumeError(MachOObjOrErr.takeError());
      consumeError(IRObjectOrError.takeError());

      if (Error E = processArchive(Members, **ArchiveOrError, FileName, C))
        return E;
      continue;
    }

    Error CombinedError = joinErrors(
        ArchiveOrError.takeError(),
        joinErrors(IRObjectOrError.takeError(), MachOObjOrErr.takeError()));
    return createFileError(FileName, std::move(CombinedError));
  }

  // Update vector UniversalBuffers with the MemoryBuffers to transfer
  // ownership.
  UniversalBuffers.push_back(std::move(NM.Buf));
  return Error::success();
}

static Error addMember(MembersPerArchitectureMap &Members,
                       std::vector<std::unique_ptr<MemoryBuffer>> &FileBuffers,
                       StringRef FileName, const Config &C) {
  Expected<NewArchiveMember> NMOrErr =
      NewArchiveMember::getFile(FileName, C.Deterministic);
  if (!NMOrErr)
    return createFileError(FileName, NMOrErr.takeError());

  // For regular archives, use the basename of the object path for the member
  // name.
  NMOrErr->MemberName = sys::path::filename(NMOrErr->MemberName);
  file_magic Magic = identify_magic(NMOrErr->Buf->getBuffer());

  // Flatten archives.
  if (Magic == file_magic::archive)
    return addArchiveMembers(Members, FileBuffers, std::move(*NMOrErr),
                             FileName, C);

  // Flatten universal files.
  if (Magic == file_magic::macho_universal_binary)
    return addUniversalMembers(Members, FileBuffers, std::move(*NMOrErr),
                               FileName, C);

  // Bitcode files.
  if (Magic == file_magic::bitcode)
    return verifyAndAddIRObject(Members, std::move(*NMOrErr), C);

  if (Error E = verifyAndAddMachOObject(Members, std::move(*NMOrErr), C))
    return E;
  return Error::success();
}

static Expected<SmallVector<Slice, 2>>
buildSlices(ArrayRef<OwningBinary<Archive>> OutputBinaries) {
  SmallVector<Slice, 2> Slices;

  for (const auto &OB : OutputBinaries) {
    const Archive &A = *OB.getBinary();
    Expected<Slice> ArchiveSlice = Slice::create(A, &LLVMCtx);
    if (!ArchiveSlice)
      return ArchiveSlice.takeError();
    Slices.push_back(*ArchiveSlice);
  }
  return Slices;
}

static Error createStaticLibrary(const Config &C) {
  MembersPerArchitectureMap NewMembers;
  std::vector<std::unique_ptr<MemoryBuffer>> FileBuffers;
  for (StringRef FileName : InputFiles)
    if (Error E = addMember(NewMembers, FileBuffers, FileName, C))
      return E;

  if (!ArchType.empty()) {
    uint64_t ArchCPUID = getCPUID(C.ArchCPUType, C.ArchCPUSubtype);
    if (NewMembers.find(ArchCPUID) == NewMembers.end())
      return createStringError(std::errc::invalid_argument,
                               "no library created (no object files in input "
                               "files matching -arch_only %s)",
                               ArchType.c_str());
  }

  if (NewMembers.size() == 1) {
    if (Error E =
            writeArchive(OutputFile, NewMembers.begin()->second,
                         /*WriteSymtab=*/true,
                         /*Kind=*/object::Archive::K_DARWIN, C.Deterministic,
                         /*Thin=*/false))
      return E;
  } else {
    SmallVector<OwningBinary<Archive>, 2> OutputBinaries;
    for (const std::pair<const uint64_t, std::vector<NewArchiveMember>> &M :
         NewMembers) {
      Expected<std::unique_ptr<MemoryBuffer>> OutputBufferOrErr =
          writeArchiveToBuffer(M.second,
                               /*WriteSymtab=*/true,
                               /*Kind=*/object::Archive::K_DARWIN,
                               C.Deterministic,
                               /*Thin=*/false);
      if (!OutputBufferOrErr)
        return OutputBufferOrErr.takeError();
      std::unique_ptr<MemoryBuffer> &OutputBuffer = OutputBufferOrErr.get();

      Expected<std::unique_ptr<Archive>> ArchiveOrError =
          Archive::create(OutputBuffer->getMemBufferRef());
      if (!ArchiveOrError)
        return ArchiveOrError.takeError();
      std::unique_ptr<Archive> &A = ArchiveOrError.get();

      OutputBinaries.push_back(
          OwningBinary<Archive>(std::move(A), std::move(OutputBuffer)));
    }

    Expected<SmallVector<Slice, 2>> Slices = buildSlices(OutputBinaries);
    if (!Slices)
      return Slices.takeError();

    llvm::stable_sort(*Slices);
    if (Error E = writeUniversalBinary(*Slices, OutputFile))
      return E;
  }
  return Error::success();
}

static Expected<Config> parseCommandLine(int Argc, char **Argv) {
  Config C;
  cl::ParseCommandLineOptions(Argc, Argv, "llvm-libtool-darwin\n");

  if (LibraryOperation == Operation::None) {
    if (!VersionOption) {
      std::string Error;
      raw_string_ostream Stream(Error);
      LibraryOperation.error("must be specified", "", Stream);
      return createStringError(std::errc::invalid_argument, Error.c_str());
    }
    return C;
  }

  if (OutputFile.empty()) {
    std::string Error;
    raw_string_ostream Stream(Error);
    OutputFile.error("must be specified", "o", Stream);
    return createStringError(std::errc::invalid_argument, Error.c_str());
  }

  if (DeterministicOption && NonDeterministicOption)
    return createStringError(std::errc::invalid_argument,
                             "cannot specify both -D and -U flags");
  else if (NonDeterministicOption)
    C.Deterministic = false;

  if (!Libraries.empty())
    if (Error E = processCommandLineLibraries())
      return std::move(E);

  if (!FileList.empty())
    if (Error E = processFileList())
      return std::move(E);

  if (InputFiles.empty())
    return createStringError(std::errc::invalid_argument,
                             "no input files specified");

  if (ArchType.getNumOccurrences()) {
    if (Error E = validateArchitectureName(ArchType))
      return std::move(E);

    std::tie(C.ArchCPUType, C.ArchCPUSubtype) =
        MachO::getCPUTypeFromArchitecture(
            MachO::getArchitectureFromName(ArchType));
  }

  return C;
}

int main(int Argc, char **Argv) {
  InitLLVM X(Argc, Argv);
  cl::HideUnrelatedOptions({&LibtoolCategory, &getColorCategory()});
  Expected<Config> ConfigOrErr = parseCommandLine(Argc, Argv);
  if (!ConfigOrErr) {
    WithColor::defaultErrorHandler(ConfigOrErr.takeError());
    return EXIT_FAILURE;
  }

  if (VersionOption)
    cl::PrintVersionMessage();

  Config C = *ConfigOrErr;
  switch (LibraryOperation) {
  case Operation::None:
    break;
  case Operation::Static:
    if (Error E = createStaticLibrary(C)) {
      WithColor::defaultErrorHandler(std::move(E));
      return EXIT_FAILURE;
    }
    break;
  }
}
