summaryrefslogtreecommitdiffstats
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/LLVMWrapper.h1
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp17
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp71
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp96
4 files changed, 178 insertions, 7 deletions
diff --git a/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h b/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h
index 015c1c52b..727cfc441 100644
--- a/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h
+++ b/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h
@@ -76,7 +76,6 @@ enum LLVMRustAttribute {
OptimizeNone = 24,
ReturnsTwice = 25,
ReadNone = 26,
- InaccessibleMemOnly = 27,
SanitizeHWAddress = 28,
WillReturn = 29,
StackProtectReq = 30,
diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
index 18d37d95a..1a3d458c3 100644
--- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
@@ -205,7 +205,12 @@ enum class LLVMRustCodeModel {
None,
};
-static Optional<CodeModel::Model> fromRust(LLVMRustCodeModel Model) {
+#if LLVM_VERSION_LT(16, 0)
+static Optional<CodeModel::Model>
+#else
+static std::optional<CodeModel::Model>
+#endif
+fromRust(LLVMRustCodeModel Model) {
switch (Model) {
case LLVMRustCodeModel::Tiny:
return CodeModel::Tiny;
@@ -627,14 +632,22 @@ 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){
LLVMSelfProfileInitializeCallbacks(PIC,LlvmSelfProfiler,BeforePassCallback,AfterPassCallback);
}
+#if LLVM_VERSION_LT(16, 0)
Optional<PGOOptions> PGOOpt;
+#else
+ std::optional<PGOOptions> PGOOpt;
+#endif
if (PGOGenPath) {
assert(!PGOUsePath && !PGOSampleUsePath);
PGOOpt = PGOOptions(PGOGenPath, "", "", PGOOptions::IRInstr,
@@ -800,7 +813,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 6f36281af..3a748f389 100644
--- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
@@ -8,13 +8,18 @@
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/IntrinsicsARM.h"
#include "llvm/IR/Mangler.h"
+#if LLVM_VERSION_GE(16, 0)
+#include "llvm/Support/ModRef.h"
+#endif
#include "llvm/Object/Archive.h"
#include "llvm/Object/COFFImportFile.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Pass.h"
#include "llvm/Bitcode/BitcodeWriter.h"
#include "llvm/Support/Signals.h"
+#if LLVM_VERSION_LT(16, 0)
#include "llvm/ADT/Optional.h"
+#endif
#include <iostream>
@@ -213,8 +218,6 @@ static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) {
return Attribute::ReturnsTwice;
case ReadNone:
return Attribute::ReadNone;
- case InaccessibleMemOnly:
- return Attribute::InaccessibleMemOnly;
case SanitizeHWAddress:
return Attribute::SanitizeHWAddress;
case WillReturn:
@@ -379,6 +382,43 @@ extern "C" LLVMAttributeRef LLVMRustCreateAllocKindAttr(LLVMContextRef C, uint64
#endif
}
+// Simplified representation of `MemoryEffects` across the FFI boundary.
+//
+// Each variant corresponds to one of the static factory methods on `MemoryEffects`.
+enum class LLVMRustMemoryEffects {
+ None,
+ ReadOnly,
+ InaccessibleMemOnly,
+};
+
+extern "C" LLVMAttributeRef LLVMRustCreateMemoryEffectsAttr(LLVMContextRef C,
+ LLVMRustMemoryEffects Effects) {
+#if LLVM_VERSION_GE(16, 0)
+ switch (Effects) {
+ case LLVMRustMemoryEffects::None:
+ return wrap(Attribute::getWithMemoryEffects(*unwrap(C), MemoryEffects::none()));
+ case LLVMRustMemoryEffects::ReadOnly:
+ return wrap(Attribute::getWithMemoryEffects(*unwrap(C), MemoryEffects::readOnly()));
+ case LLVMRustMemoryEffects::InaccessibleMemOnly:
+ return wrap(Attribute::getWithMemoryEffects(*unwrap(C),
+ MemoryEffects::inaccessibleMemOnly()));
+ default:
+ report_fatal_error("bad MemoryEffects.");
+ }
+#else
+ switch (Effects) {
+ case LLVMRustMemoryEffects::None:
+ return wrap(Attribute::get(*unwrap(C), Attribute::ReadNone));
+ case LLVMRustMemoryEffects::ReadOnly:
+ return wrap(Attribute::get(*unwrap(C), Attribute::ReadOnly));
+ case LLVMRustMemoryEffects::InaccessibleMemOnly:
+ return wrap(Attribute::get(*unwrap(C), Attribute::InaccessibleMemOnly));
+ default:
+ report_fatal_error("bad MemoryEffects.");
+ }
+#endif
+}
+
// Enable a fast-math flag
//
// https://llvm.org/docs/LangRef.html#fast-math-flags
@@ -670,7 +710,11 @@ enum class LLVMRustChecksumKind {
SHA256,
};
+#if LLVM_VERSION_LT(16, 0)
static Optional<DIFile::ChecksumKind> fromRust(LLVMRustChecksumKind Kind) {
+#else
+static std::optional<DIFile::ChecksumKind> fromRust(LLVMRustChecksumKind Kind) {
+#endif
switch (Kind) {
case LLVMRustChecksumKind::None:
return None;
@@ -749,8 +793,18 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFile(
const char *Filename, size_t FilenameLen,
const char *Directory, size_t DirectoryLen, LLVMRustChecksumKind CSKind,
const char *Checksum, size_t ChecksumLen) {
+
+#if LLVM_VERSION_LT(16, 0)
Optional<DIFile::ChecksumKind> llvmCSKind = fromRust(CSKind);
+#else
+ std::optional<DIFile::ChecksumKind> llvmCSKind = fromRust(CSKind);
+#endif
+
+#if LLVM_VERSION_LT(16, 0)
Optional<DIFile::ChecksumInfo<StringRef>> CSInfo{};
+#else
+ std::optional<DIFile::ChecksumInfo<StringRef>> CSInfo{};
+#endif
if (llvmCSKind)
CSInfo.emplace(*llvmCSKind, StringRef{Checksum, ChecksumLen});
return wrap(Builder->createFile(StringRef(Filename, FilenameLen),
@@ -998,8 +1052,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(
@@ -1073,6 +1128,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);
@@ -1924,3 +1983,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 000000000..974207e91
--- /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;
+}