//===-- 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/WithColor.h"
#include "llvm/TextAPI/MachO/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 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, /*FileSize=*/-1,
                                   /*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();
  }

  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, &ColorCategory});
  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;
  }
}
