about summary refs log tree commit diff
path: root/compiler/rustc_llvm/llvm-wrapper
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_llvm/llvm-wrapper')
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp6
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp15
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp96
3 files changed, 113 insertions, 4 deletions
diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
index 18d37d95a83..7f4d63eed8b 100644
--- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
@@ -627,7 +627,11 @@ LLVMRustOptimize(
   bool DebugPassManager = false;
 
   PassInstrumentationCallbacks PIC;
+#if LLVM_VERSION_LT(16, 0)
   StandardInstrumentations SI(DebugPassManager);
+#else
+  StandardInstrumentations SI(TheModule->getContext(), DebugPassManager);
+#endif
   SI.registerCallbacks(PIC);
 
   if (LlvmSelfProfiler){
@@ -800,7 +804,7 @@ LLVMRustOptimize(
       auto Plugin = PassPlugin::Load(PluginPath.str());
       if (!Plugin) {
         LLVMRustSetLastError(("Failed to load pass plugin" + PluginPath.str()).c_str());
-        continue;
+        return LLVMRustResult::Failure;
       }
       Plugin->registerPassBuilderCallbacks(PB);
     }
diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
index 0d9b5a57b69..792d921c6a4 100644
--- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
@@ -9,7 +9,7 @@
 #include "llvm/IR/IntrinsicsARM.h"
 #include "llvm/IR/Mangler.h"
 #if LLVM_VERSION_GE(16, 0)
-#include "llvm/IR/ModRef.h"
+#include "llvm/Support/ModRef.h"
 #endif
 #include "llvm/Object/Archive.h"
 #include "llvm/Object/COFFImportFile.h"
@@ -1036,8 +1036,9 @@ extern "C" LLVMValueRef LLVMRustDIBuilderInsertDeclareAtEnd(
 
 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerator(
     LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen,
-    int64_t Value, bool IsUnsigned) {
-  return wrap(Builder->createEnumerator(StringRef(Name, NameLen), Value, IsUnsigned));
+    const uint64_t Value[2], unsigned SizeInBits, bool IsUnsigned) {
+  return wrap(Builder->createEnumerator(StringRef(Name, NameLen),
+      APSInt(APInt(SizeInBits, makeArrayRef(Value, 2)), IsUnsigned)));
 }
 
 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerationType(
@@ -1111,6 +1112,10 @@ extern "C" uint64_t LLVMRustDIBuilderCreateOpPlusUconst() {
   return dwarf::DW_OP_plus_uconst;
 }
 
+extern "C" int64_t LLVMRustDIBuilderCreateOpLLVMFragment() {
+  return dwarf::DW_OP_LLVM_fragment;
+}
+
 extern "C" void LLVMRustWriteTypeToString(LLVMTypeRef Ty, RustStringRef Str) {
   RawRustStringOstream OS(Str);
   unwrap<llvm::Type>(Ty)->print(OS);
@@ -1962,3 +1967,7 @@ extern "C" int32_t LLVMRustGetElementTypeArgIndex(LLVMValueRef CallSite) {
 #endif
     return -1;
 }
+
+extern "C" bool LLVMRustIsBitcode(char *ptr, size_t len) {
+  return identify_magic(StringRef(ptr, len)) == file_magic::bitcode;
+}
diff --git a/compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp
new file mode 100644
index 00000000000..974207e918c
--- /dev/null
+++ b/compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp
@@ -0,0 +1,96 @@
+// 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/8ef3e895ad8ab1724e2b87cabad1dacdc7a397a3/llvm/include/llvm/Object/ArchiveWriter.h
+// * https://github.com/llvm/llvm-project/blob/8ef3e895ad8ab1724e2b87cabad1dacdc7a397a3/llvm/lib/Object/ArchiveWriter.cpp
+
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/Object/ObjectFile.h"
+#include "llvm/ADT/Optional.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 *);
+
+// 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;
+  raw_svector_ostream SymName(SymNameBuf);
+
+  // In the scenario when LLVMContext is populated SymbolicFile will contain a
+  // reference to it, thus SymbolicFile should be destroyed first.
+  LLVMContext Context;
+  std::unique_ptr<object::SymbolicFile> Obj;
+
+  const file_magic Type = identify_magic(Buf->getBuffer());
+  if (!object::SymbolicFile::isSymbolicFile(Type, &Context)) {
+    return 0;
+  }
+
+  if (Type == file_magic::bitcode) {
+    auto ObjOrErr = object::SymbolicFile::createSymbolicFile(
+      Buf->getMemBufferRef(), file_magic::bitcode, &Context);
+    if (!ObjOrErr) {
+      Error E = ObjOrErr.takeError();
+      SmallString<0> ErrorBuf;
+      raw_svector_ostream Error(ErrorBuf);
+      Error << E << '\0';
+      return ErrorCallback(Error.str().data());
+    }
+    Obj = std::move(*ObjOrErr);
+  } else {
+    auto ObjOrErr = object::SymbolicFile::createSymbolicFile(Buf->getMemBufferRef());
+    if (!ObjOrErr) {
+      Error E = ObjOrErr.takeError();
+      SmallString<0> ErrorBuf;
+      raw_svector_ostream Error(ErrorBuf);
+      Error << E << '\0';
+      return ErrorCallback(Error.str().data());
+    }
+    Obj = std::move(*ObjOrErr);
+  }
+
+
+  for (const object::BasicSymbolRef &S : Obj->symbols()) {
+    if (!isArchiveSymbol(S))
+      continue;
+    if (Error E = S.printName(SymName)) {
+      SmallString<0> ErrorBuf;
+      raw_svector_ostream Error(ErrorBuf);
+      Error << E << '\0';
+      return ErrorCallback(Error.str().data());
+    }
+    SymName << '\0';
+    if (void *E = Callback(State, SymNameBuf.str().data())) {
+      return E;
+    }
+    SymNameBuf.clear();
+  }
+  return 0;
+}