// Derived from code in LLVM, which is:
// 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

// Derived from:
// * https://github.com/llvm/llvm-project/blob/ef6d1ec07c693352c4a60dd58db08d2d8558f6ea/llvm/include/llvm/Object/ArchiveWriter.h
// * https://github.com/llvm/llvm-project/blob/ef6d1ec07c693352c4a60dd58db08d2d8558f6ea/llvm/lib/Object/ArchiveWriter.cpp

#include "LLVMWrapper.h"
#include "SuppressLLVMWarnings.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/Object/COFF.h"
#include "llvm/Object/COFFImportFile.h"
#include "llvm/Object/IRObjectFile.h"
#include "llvm/Object/ObjectFile.h"
#include <llvm/Support/raw_ostream.h>

using namespace llvm;
using namespace llvm::sys;
using namespace llvm::object;

static bool isArchiveSymbol(const object::BasicSymbolRef &S) {
  Expected<uint32_t> SymFlagsOrErr = S.getFlags();
  if (!SymFlagsOrErr)
    // FIXME: Actually report errors helpfully.
    report_fatal_error(SymFlagsOrErr.takeError());
  if (*SymFlagsOrErr & object::SymbolRef::SF_FormatSpecific)
    return false;
  if (!(*SymFlagsOrErr & object::SymbolRef::SF_Global))
    return false;
  if (*SymFlagsOrErr & object::SymbolRef::SF_Undefined)
    return false;
  return true;
}

typedef void *(*LLVMRustGetSymbolsCallback)(void *, const char *);
typedef void *(*LLVMRustGetSymbolsErrorCallback)(const char *);

// This function is copied from ArchiveWriter.cpp.
static Expected<std::unique_ptr<SymbolicFile>>
getSymbolicFile(MemoryBufferRef Buf, LLVMContext &Context) {
  const file_magic Type = identify_magic(Buf.getBuffer());
  // Don't attempt to read non-symbolic file types.
  if (!object::SymbolicFile::isSymbolicFile(Type, &Context))
    return nullptr;
  if (Type == file_magic::bitcode) {
    auto ObjOrErr = object::SymbolicFile::createSymbolicFile(
        Buf, file_magic::bitcode, &Context);
    if (!ObjOrErr)
      return ObjOrErr.takeError();
    return std::move(*ObjOrErr);
  } else {
    auto ObjOrErr = object::SymbolicFile::createSymbolicFile(Buf);
    if (!ObjOrErr)
      return ObjOrErr.takeError();
    return std::move(*ObjOrErr);
  }
}

// Note: This is implemented in C++ instead of using the C api from Rust as
// IRObjectFile doesn't implement getSymbolName, only printSymbolName, which is
// inaccessible from the C api.
extern "C" void *
LLVMRustGetSymbols(char *BufPtr, size_t BufLen, void *State,
                   LLVMRustGetSymbolsCallback Callback,
                   LLVMRustGetSymbolsErrorCallback ErrorCallback) {
  std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(
      StringRef(BufPtr, BufLen), StringRef("LLVMRustGetSymbolsObject"), false);
  SmallString<0> SymNameBuf;
  auto SymName = raw_svector_ostream(SymNameBuf);

  // In the scenario when LLVMContext is populated SymbolicFile will contain a
  // reference to it, thus SymbolicFile should be destroyed first.
  LLVMContext Context;
  Expected<std::unique_ptr<object::SymbolicFile>> ObjOrErr =
      getSymbolicFile(Buf->getMemBufferRef(), Context);
  if (!ObjOrErr) {
    return ErrorCallback(toString(ObjOrErr.takeError()).c_str());
  }
  std::unique_ptr<object::SymbolicFile> Obj = std::move(*ObjOrErr);
  if (Obj == nullptr) {
    return 0;
  }

  for (const object::BasicSymbolRef &S : Obj->symbols()) {
    if (!isArchiveSymbol(S))
      continue;
    if (Error E = S.printName(SymName)) {
      return ErrorCallback(toString(std::move(E)).c_str());
    }
    SymName << '\0';
    if (void *E = Callback(State, SymNameBuf.str().data())) {
      return E;
    }
    SymNameBuf.clear();
  }
  return 0;
}

// Encoding true and false as invalid pointer values
#define TRUE_PTR (void *)1
#define FALSE_PTR (void *)0

extern "C" bool LLVMRustIs64BitSymbolicFile(char *BufPtr, size_t BufLen) {
  std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(
      StringRef(BufPtr, BufLen), StringRef("LLVMRustGetSymbolsObject"), false);
  SmallString<0> SymNameBuf;
  auto SymName = raw_svector_ostream(SymNameBuf);

  // Code starting from this line is copied from s64BitSymbolicFile in
  // ArchiveWriter.cpp.
  // In the scenario when LLVMContext is populated SymbolicFile will contain a
  // reference to it, thus SymbolicFile should be destroyed first.
  LLVMContext Context;
  Expected<std::unique_ptr<object::SymbolicFile>> ObjOrErr =
      getSymbolicFile(Buf->getMemBufferRef(), Context);
  if (!ObjOrErr) {
    return false;
  }
  std::unique_ptr<object::SymbolicFile> Obj = std::move(*ObjOrErr);

  return Obj != nullptr ? Obj->is64Bit() : false;
}

extern "C" bool LLVMRustIsECObject(char *BufPtr, size_t BufLen) {
  std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(
      StringRef(BufPtr, BufLen), StringRef("LLVMRustGetSymbolsObject"), false);
  SmallString<0> SymNameBuf;
  auto SymName = raw_svector_ostream(SymNameBuf);

  // In the scenario when LLVMContext is populated SymbolicFile will contain a
  // reference to it, thus SymbolicFile should be destroyed first.
  LLVMContext Context;
  Expected<std::unique_ptr<object::SymbolicFile>> ObjOrErr =
      getSymbolicFile(Buf->getMemBufferRef(), Context);
  if (!ObjOrErr) {
    return false;
  }
  std::unique_ptr<object::SymbolicFile> Obj = std::move(*ObjOrErr);

  if (Obj == nullptr) {
    return false;
  }

  // Code starting from this line is copied from isECObject in
  // ArchiveWriter.cpp with an extra #if to work with LLVM 17.
  if (Obj->isCOFF())
    return cast<llvm::object::COFFObjectFile>(&*Obj)->getMachine() !=
           COFF::IMAGE_FILE_MACHINE_ARM64;

  if (Obj->isCOFFImportFile())
    return cast<llvm::object::COFFImportFile>(&*Obj)->getMachine() !=
           COFF::IMAGE_FILE_MACHINE_ARM64;

  if (Obj->isIR()) {
    Expected<std::string> TripleStr =
        getBitcodeTargetTriple(Obj->getMemoryBufferRef());
    if (!TripleStr)
      return false;
    Triple T(*TripleStr);
    return T.isWindowsArm64EC() || T.getArch() == Triple::x86_64;
  }

  return false;
}
