2020-07-26 17:11:30 +00:00
|
|
|
|
#include "LLVMWrapper.h"
|
2017-03-16 20:10:04 +00:00
|
|
|
|
#include "llvm/IR/DebugInfoMetadata.h"
|
2021-11-12 00:00:00 +00:00
|
|
|
|
#include "llvm/IR/DiagnosticHandler.h"
|
2014-09-12 15:17:58 +00:00
|
|
|
|
#include "llvm/IR/DiagnosticInfo.h"
|
|
|
|
|
#include "llvm/IR/DiagnosticPrinter.h"
|
2018-05-23 19:19:07 +00:00
|
|
|
|
#include "llvm/IR/GlobalVariable.h"
|
2016-08-01 23:35:09 +00:00
|
|
|
|
#include "llvm/IR/Instructions.h"
|
2020-06-04 04:19:34 +00:00
|
|
|
|
#include "llvm/IR/Intrinsics.h"
|
2022-04-19 12:55:24 +00:00
|
|
|
|
#include "llvm/IR/Mangler.h"
|
2016-12-30 11:22:11 +00:00
|
|
|
|
#include "llvm/Object/Archive.h"
|
2021-03-08 20:42:54 +00:00
|
|
|
|
#include "llvm/Object/COFFImportFile.h"
|
2016-12-30 11:22:11 +00:00
|
|
|
|
#include "llvm/Object/ObjectFile.h"
|
2022-03-10 16:16:33 +00:00
|
|
|
|
#include "llvm/Pass.h"
|
2017-07-23 15:14:38 +00:00
|
|
|
|
#include "llvm/Bitcode/BitcodeWriterPass.h"
|
2018-10-12 19:35:55 +00:00
|
|
|
|
#include "llvm/Support/Signals.h"
|
2017-07-21 11:26:41 +00:00
|
|
|
|
#include "llvm/ADT/Optional.h"
|
|
|
|
|
|
2018-10-12 19:35:55 +00:00
|
|
|
|
#include <iostream>
|
|
|
|
|
|
2011-10-22 00:35:52 +00:00
|
|
|
|
//===----------------------------------------------------------------------===
|
2011-03-15 21:57:26 +00:00
|
|
|
|
//
|
|
|
|
|
// This file defines alternate interfaces to core functions that are more
|
|
|
|
|
// readily callable by Rust's FFI.
|
|
|
|
|
//
|
2011-10-22 00:35:52 +00:00
|
|
|
|
//===----------------------------------------------------------------------===
|
2011-03-15 21:57:26 +00:00
|
|
|
|
|
2011-04-15 21:35:46 +00:00
|
|
|
|
using namespace llvm;
|
2012-09-11 06:05:51 +00:00
|
|
|
|
using namespace llvm::sys;
|
2013-12-17 04:58:21 +00:00
|
|
|
|
using namespace llvm::object;
|
2011-04-15 21:35:46 +00:00
|
|
|
|
|
2016-08-01 23:35:09 +00:00
|
|
|
|
// LLVMAtomicOrdering is already an enum - don't create another
|
|
|
|
|
// one.
|
2016-12-31 17:01:23 +00:00
|
|
|
|
static AtomicOrdering fromRust(LLVMAtomicOrdering Ordering) {
|
2016-08-01 23:35:09 +00:00
|
|
|
|
switch (Ordering) {
|
2016-12-30 11:22:11 +00:00
|
|
|
|
case LLVMAtomicOrderingNotAtomic:
|
|
|
|
|
return AtomicOrdering::NotAtomic;
|
|
|
|
|
case LLVMAtomicOrderingUnordered:
|
|
|
|
|
return AtomicOrdering::Unordered;
|
|
|
|
|
case LLVMAtomicOrderingMonotonic:
|
|
|
|
|
return AtomicOrdering::Monotonic;
|
|
|
|
|
case LLVMAtomicOrderingAcquire:
|
|
|
|
|
return AtomicOrdering::Acquire;
|
|
|
|
|
case LLVMAtomicOrderingRelease:
|
|
|
|
|
return AtomicOrdering::Release;
|
|
|
|
|
case LLVMAtomicOrderingAcquireRelease:
|
|
|
|
|
return AtomicOrdering::AcquireRelease;
|
|
|
|
|
case LLVMAtomicOrderingSequentiallyConsistent:
|
|
|
|
|
return AtomicOrdering::SequentiallyConsistent;
|
2016-08-01 23:35:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-11-20 16:47:29 +00:00
|
|
|
|
report_fatal_error("Invalid LLVMAtomicOrdering value!");
|
2016-08-01 23:35:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-10-10 12:11:28 +00:00
|
|
|
|
static LLVM_THREAD_LOCAL char *LastError;
|
2013-04-06 00:17:49 +00:00
|
|
|
|
|
2018-10-12 19:35:55 +00:00
|
|
|
|
// Custom error handler for fatal LLVM errors.
|
|
|
|
|
//
|
|
|
|
|
// Notably it exits the process with code 101, unlike LLVM's default of 1.
|
|
|
|
|
static void FatalErrorHandler(void *UserData,
|
2021-10-05 14:31:36 +00:00
|
|
|
|
#if LLVM_VERSION_LT(14, 0)
|
2018-10-12 19:35:55 +00:00
|
|
|
|
const std::string& Reason,
|
2021-10-05 14:31:36 +00:00
|
|
|
|
#else
|
|
|
|
|
const char* Reason,
|
|
|
|
|
#endif
|
2018-10-12 19:35:55 +00:00
|
|
|
|
bool GenCrashDiag) {
|
|
|
|
|
// Do the same thing that the default error handler does.
|
|
|
|
|
std::cerr << "LLVM ERROR: " << Reason << std::endl;
|
|
|
|
|
|
|
|
|
|
// Since this error handler exits the process, we have to run any cleanup that
|
|
|
|
|
// LLVM would run after handling the error. This might change with an LLVM
|
|
|
|
|
// upgrade.
|
|
|
|
|
sys::RunInterruptHandlers();
|
|
|
|
|
|
|
|
|
|
exit(101);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
extern "C" void LLVMRustInstallFatalErrorHandler() {
|
|
|
|
|
install_fatal_error_handler(FatalErrorHandler);
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-28 00:53:17 +00:00
|
|
|
|
extern "C" void LLVMRustDisableSystemDialogsOnCrash() {
|
|
|
|
|
sys::DisableSystemDialogsOnCrash();
|
|
|
|
|
}
|
|
|
|
|
|
2014-04-15 14:25:22 +00:00
|
|
|
|
extern "C" char *LLVMRustGetLastError(void) {
|
2016-12-31 17:01:23 +00:00
|
|
|
|
char *Ret = LastError;
|
2016-12-30 12:21:21 +00:00
|
|
|
|
LastError = nullptr;
|
2016-12-31 17:01:23 +00:00
|
|
|
|
return Ret;
|
2014-04-15 14:25:22 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-10-23 13:08:26 +00:00
|
|
|
|
extern "C" unsigned int LLVMRustGetInstructionCount(LLVMModuleRef M) {
|
|
|
|
|
return unwrap(M)->getInstructionCount();
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-04 20:19:23 +00:00
|
|
|
|
extern "C" void LLVMRustSetLastError(const char *Err) {
|
2016-12-30 11:22:11 +00:00
|
|
|
|
free((void *)LastError);
|
2016-12-31 17:01:23 +00:00
|
|
|
|
LastError = strdup(Err);
|
2011-03-15 21:57:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-01-04 20:19:23 +00:00
|
|
|
|
extern "C" LLVMContextRef LLVMRustContextCreate(bool shouldDiscardNames) {
|
|
|
|
|
auto ctx = new LLVMContext();
|
|
|
|
|
ctx->setDiscardValueNames(shouldDiscardNames);
|
|
|
|
|
return wrap(ctx);
|
|
|
|
|
}
|
|
|
|
|
|
2016-12-30 11:22:11 +00:00
|
|
|
|
extern "C" void LLVMRustSetNormalizedTarget(LLVMModuleRef M,
|
2016-12-31 17:01:23 +00:00
|
|
|
|
const char *Triple) {
|
|
|
|
|
unwrap(M)->setTargetTriple(Triple::normalize(Triple));
|
2011-05-05 18:34:15 +00:00
|
|
|
|
}
|
|
|
|
|
|
2011-05-10 23:10:08 +00:00
|
|
|
|
extern "C" void LLVMRustPrintPassTimings() {
|
2016-12-30 11:22:11 +00:00
|
|
|
|
raw_fd_ostream OS(2, false); // stderr.
|
2011-05-10 23:10:08 +00:00
|
|
|
|
TimerGroup::printAll(OS);
|
|
|
|
|
}
|
2011-10-31 21:42:17 +00:00
|
|
|
|
|
2020-03-10 00:00:00 +00:00
|
|
|
|
extern "C" LLVMValueRef LLVMRustGetNamedValue(LLVMModuleRef M, const char *Name,
|
|
|
|
|
size_t NameLen) {
|
|
|
|
|
return wrap(unwrap(M)->getNamedValue(StringRef(Name, NameLen)));
|
2015-02-27 11:37:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-08-01 23:35:09 +00:00
|
|
|
|
extern "C" LLVMValueRef LLVMRustGetOrInsertFunction(LLVMModuleRef M,
|
2016-12-30 11:22:11 +00:00
|
|
|
|
const char *Name,
|
2020-03-10 00:00:00 +00:00
|
|
|
|
size_t NameLen,
|
2016-12-30 11:22:11 +00:00
|
|
|
|
LLVMTypeRef FunctionTy) {
|
2020-03-10 00:00:00 +00:00
|
|
|
|
return wrap(unwrap(M)
|
|
|
|
|
->getOrInsertFunction(StringRef(Name, NameLen),
|
|
|
|
|
unwrap<FunctionType>(FunctionTy))
|
|
|
|
|
.getCallee()
|
|
|
|
|
);
|
2011-11-14 16:32:31 +00:00
|
|
|
|
}
|
2011-11-10 05:55:09 +00:00
|
|
|
|
|
2016-12-30 11:22:11 +00:00
|
|
|
|
extern "C" LLVMValueRef
|
2019-12-04 20:00:28 +00:00
|
|
|
|
LLVMRustGetOrInsertGlobal(LLVMModuleRef M, const char *Name, size_t NameLen, LLVMTypeRef Ty) {
|
2021-11-20 03:33:29 +00:00
|
|
|
|
Module *Mod = unwrap(M);
|
2019-12-04 20:00:28 +00:00
|
|
|
|
StringRef NameRef(Name, NameLen);
|
2021-11-20 03:33:29 +00:00
|
|
|
|
|
|
|
|
|
// We don't use Module::getOrInsertGlobal because that returns a Constant*,
|
|
|
|
|
// which may either be the real GlobalVariable*, or a constant bitcast of it
|
|
|
|
|
// if our type doesn't match the original declaration. We always want the
|
|
|
|
|
// GlobalVariable* so we can access linkage, visibility, etc.
|
|
|
|
|
GlobalVariable *GV = Mod->getGlobalVariable(NameRef, true);
|
|
|
|
|
if (!GV)
|
|
|
|
|
GV = new GlobalVariable(*Mod, unwrap(Ty), false,
|
|
|
|
|
GlobalValue::ExternalLinkage, nullptr, NameRef);
|
|
|
|
|
return wrap(GV);
|
2015-03-03 22:57:44 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-05-23 19:19:07 +00:00
|
|
|
|
extern "C" LLVMValueRef
|
|
|
|
|
LLVMRustInsertPrivateGlobal(LLVMModuleRef M, LLVMTypeRef Ty) {
|
|
|
|
|
return wrap(new GlobalVariable(*unwrap(M),
|
|
|
|
|
unwrap(Ty),
|
|
|
|
|
false,
|
|
|
|
|
GlobalValue::PrivateLinkage,
|
|
|
|
|
nullptr));
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-01 23:35:09 +00:00
|
|
|
|
extern "C" LLVMTypeRef LLVMRustMetadataTypeInContext(LLVMContextRef C) {
|
2011-11-10 05:55:09 +00:00
|
|
|
|
return wrap(Type::getMetadataTy(*unwrap(C)));
|
|
|
|
|
}
|
2012-06-21 22:01:32 +00:00
|
|
|
|
|
2016-12-31 17:01:23 +00:00
|
|
|
|
static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) {
|
|
|
|
|
switch (Kind) {
|
2016-12-30 11:22:11 +00:00
|
|
|
|
case AlwaysInline:
|
|
|
|
|
return Attribute::AlwaysInline;
|
|
|
|
|
case ByVal:
|
|
|
|
|
return Attribute::ByVal;
|
|
|
|
|
case Cold:
|
|
|
|
|
return Attribute::Cold;
|
|
|
|
|
case InlineHint:
|
|
|
|
|
return Attribute::InlineHint;
|
|
|
|
|
case MinSize:
|
|
|
|
|
return Attribute::MinSize;
|
|
|
|
|
case Naked:
|
|
|
|
|
return Attribute::Naked;
|
|
|
|
|
case NoAlias:
|
|
|
|
|
return Attribute::NoAlias;
|
|
|
|
|
case NoCapture:
|
|
|
|
|
return Attribute::NoCapture;
|
|
|
|
|
case NoInline:
|
|
|
|
|
return Attribute::NoInline;
|
|
|
|
|
case NonNull:
|
|
|
|
|
return Attribute::NonNull;
|
|
|
|
|
case NoRedZone:
|
|
|
|
|
return Attribute::NoRedZone;
|
|
|
|
|
case NoReturn:
|
|
|
|
|
return Attribute::NoReturn;
|
|
|
|
|
case NoUnwind:
|
|
|
|
|
return Attribute::NoUnwind;
|
|
|
|
|
case OptimizeForSize:
|
|
|
|
|
return Attribute::OptimizeForSize;
|
|
|
|
|
case ReadOnly:
|
|
|
|
|
return Attribute::ReadOnly;
|
|
|
|
|
case SExt:
|
|
|
|
|
return Attribute::SExt;
|
|
|
|
|
case StructRet:
|
|
|
|
|
return Attribute::StructRet;
|
|
|
|
|
case UWTable:
|
|
|
|
|
return Attribute::UWTable;
|
|
|
|
|
case ZExt:
|
|
|
|
|
return Attribute::ZExt;
|
|
|
|
|
case InReg:
|
|
|
|
|
return Attribute::InReg;
|
2016-12-30 04:28:11 +00:00
|
|
|
|
case SanitizeThread:
|
|
|
|
|
return Attribute::SanitizeThread;
|
|
|
|
|
case SanitizeAddress:
|
|
|
|
|
return Attribute::SanitizeAddress;
|
|
|
|
|
case SanitizeMemory:
|
|
|
|
|
return Attribute::SanitizeMemory;
|
2018-09-26 16:19:55 +00:00
|
|
|
|
case NonLazyBind:
|
|
|
|
|
return Attribute::NonLazyBind;
|
2018-10-27 12:29:06 +00:00
|
|
|
|
case OptimizeNone:
|
|
|
|
|
return Attribute::OptimizeNone;
|
2019-02-09 14:55:30 +00:00
|
|
|
|
case ReturnsTwice:
|
|
|
|
|
return Attribute::ReturnsTwice;
|
2020-02-17 21:36:01 +00:00
|
|
|
|
case ReadNone:
|
|
|
|
|
return Attribute::ReadNone;
|
|
|
|
|
case InaccessibleMemOnly:
|
|
|
|
|
return Attribute::InaccessibleMemOnly;
|
2021-01-23 02:32:38 +00:00
|
|
|
|
case SanitizeHWAddress:
|
|
|
|
|
return Attribute::SanitizeHWAddress;
|
2021-02-20 16:02:23 +00:00
|
|
|
|
case WillReturn:
|
|
|
|
|
return Attribute::WillReturn;
|
add rustc option for using LLVM stack smash protection
LLVM has built-in heuristics for adding stack canaries to functions. These
heuristics can be selected with LLVM function attributes. This patch adds a
rustc option `-Z stack-protector={none,basic,strong,all}` which controls the use
of these attributes. This gives rustc the same stack smash protection support as
clang offers through options `-fno-stack-protector`, `-fstack-protector`,
`-fstack-protector-strong`, and `-fstack-protector-all`. The protection this can
offer is demonstrated in test/ui/abi/stack-protector.rs. This fills a gap in the
current list of rustc exploit
mitigations (https://doc.rust-lang.org/rustc/exploit-mitigations.html),
originally discussed in #15179.
Stack smash protection adds runtime overhead and is therefore still off by
default, but now users have the option to trade performance for security as they
see fit. An example use case is adding Rust code in an existing C/C++ code base
compiled with stack smash protection. Without the ability to add stack smash
protection to the Rust code, the code base artifacts could be exploitable in
ways not possible if the code base remained pure C/C++.
Stack smash protection support is present in LLVM for almost all the current
tier 1/tier 2 targets: see
test/assembly/stack-protector/stack-protector-target-support.rs. The one
exception is nvptx64-nvidia-cuda. This patch follows clang's example, and adds a
warning message printed if stack smash protection is used with this target (see
test/ui/stack-protector/warn-stack-protector-unsupported.rs). Support for tier 3
targets has not been checked.
Since the heuristics are applied at the LLVM level, the heuristics are expected
to add stack smash protection to a fraction of functions comparable to C/C++.
Some experiments demonstrating how Rust code is affected by the different
heuristics can be found in
test/assembly/stack-protector/stack-protector-heuristics-effect.rs. There is
potential for better heuristics using Rust-specific safety information. For
example it might be reasonable to skip stack smash protection in functions which
transitively only use safe Rust code, or which uses only a subset of functions
the user declares safe (such as anything under `std.*`). Such alternative
heuristics could be added at a later point.
LLVM also offers a "safestack" sanitizer as an alternative way to guard against
stack smashing (see #26612). This could possibly also be included as a
stack-protection heuristic. An alternative is to add it as a sanitizer (#39699).
This is what clang does: safestack is exposed with option
`-fsanitize=safe-stack`.
The options are only supported by the LLVM backend, but as with other codegen
options it is visible in the main codegen option help menu. The heuristic names
"basic", "strong", and "all" are hopefully sufficiently generic to be usable in
other backends as well.
Reviewed-by: Nikita Popov <nikic@php.net>
Extra commits during review:
- [address-review] make the stack-protector option unstable
- [address-review] reduce detail level of stack-protector option help text
- [address-review] correct grammar in comment
- [address-review] use compiler flag to avoid merging functions in test
- [address-review] specify min LLVM version in fortanix stack-protector test
Only for Fortanix test, since this target specifically requests the
`--x86-experimental-lvi-inline-asm-hardening` flag.
- [address-review] specify required LLVM components in stack-protector tests
- move stack protector option enum closer to other similar option enums
- rustc_interface/tests: sort debug option list in tracking hash test
- add an explicit `none` stack-protector option
Revert "set LLVM requirements for all stack protector support test revisions"
This reverts commit a49b74f92a4e7d701d6f6cf63d207a8aff2e0f68.
2021-04-06 19:37:49 +00:00
|
|
|
|
case StackProtectReq:
|
|
|
|
|
return Attribute::StackProtectReq;
|
|
|
|
|
case StackProtectStrong:
|
|
|
|
|
return Attribute::StackProtectStrong;
|
|
|
|
|
case StackProtect:
|
|
|
|
|
return Attribute::StackProtect;
|
2022-02-05 06:00:37 +00:00
|
|
|
|
case NoUndef:
|
|
|
|
|
return Attribute::NoUndef;
|
2021-12-03 21:11:13 +00:00
|
|
|
|
case SanitizeMemTag:
|
|
|
|
|
return Attribute::SanitizeMemTag;
|
2016-11-16 22:36:08 +00:00
|
|
|
|
}
|
2017-11-20 16:47:29 +00:00
|
|
|
|
report_fatal_error("bad AttributeKind");
|
2016-11-16 22:36:08 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-02-21 16:19:16 +00:00
|
|
|
|
template<typename T> static inline void AddAttributes(T *t, unsigned Index,
|
|
|
|
|
LLVMAttributeRef *Attrs, size_t AttrsLen) {
|
|
|
|
|
AttributeList PAL = t->getAttributes();
|
|
|
|
|
AttributeList PALNew;
|
2021-09-07 18:49:03 +00:00
|
|
|
|
#if LLVM_VERSION_LT(14, 0)
|
2022-02-26 22:16:01 +00:00
|
|
|
|
AttrBuilder B;
|
|
|
|
|
for (LLVMAttributeRef Attr : makeArrayRef(Attrs, AttrsLen))
|
|
|
|
|
B.addAttribute(unwrap(Attr));
|
2022-02-21 16:19:16 +00:00
|
|
|
|
PALNew = PAL.addAttributes(t->getContext(), Index, B);
|
2021-09-07 18:49:03 +00:00
|
|
|
|
#else
|
2022-02-26 22:16:01 +00:00
|
|
|
|
AttrBuilder B(t->getContext());
|
|
|
|
|
for (LLVMAttributeRef Attr : makeArrayRef(Attrs, AttrsLen))
|
|
|
|
|
B.addAttribute(unwrap(Attr));
|
2022-02-21 16:19:16 +00:00
|
|
|
|
PALNew = PAL.addAttributesAtIndex(t->getContext(), Index, B);
|
2021-09-07 18:49:03 +00:00
|
|
|
|
#endif
|
2022-02-21 16:19:16 +00:00
|
|
|
|
t->setAttributes(PALNew);
|
2021-09-07 18:49:03 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-02-21 16:19:16 +00:00
|
|
|
|
extern "C" void LLVMRustAddFunctionAttributes(LLVMValueRef Fn, unsigned Index,
|
|
|
|
|
LLVMAttributeRef *Attrs, size_t AttrsLen) {
|
|
|
|
|
Function *F = unwrap<Function>(Fn);
|
|
|
|
|
AddAttributes(F, Index, Attrs, AttrsLen);
|
2017-10-03 07:45:07 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-02-21 16:19:16 +00:00
|
|
|
|
extern "C" void LLVMRustAddCallSiteAttributes(LLVMValueRef Instr, unsigned Index,
|
|
|
|
|
LLVMAttributeRef *Attrs, size_t AttrsLen) {
|
2020-06-26 01:52:41 +00:00
|
|
|
|
CallBase *Call = unwrap<CallBase>(Instr);
|
2022-02-21 16:19:16 +00:00
|
|
|
|
AddAttributes(Call, Index, Attrs, AttrsLen);
|
2019-07-06 19:52:25 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-02-21 16:19:16 +00:00
|
|
|
|
extern "C" LLVMAttributeRef LLVMRustCreateAttrNoValue(LLVMContextRef C,
|
|
|
|
|
LLVMRustAttribute RustAttr) {
|
|
|
|
|
return wrap(Attribute::get(*unwrap(C), fromRust(RustAttr)));
|
2020-11-03 21:47:16 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-02-21 16:19:16 +00:00
|
|
|
|
extern "C" LLVMAttributeRef LLVMRustCreateAlignmentAttr(LLVMContextRef C,
|
|
|
|
|
uint64_t Bytes) {
|
|
|
|
|
return wrap(Attribute::getWithAlignment(*unwrap(C), llvm::Align(Bytes)));
|
2017-10-03 07:45:07 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-02-21 16:19:16 +00:00
|
|
|
|
extern "C" LLVMAttributeRef LLVMRustCreateDereferenceableAttr(LLVMContextRef C,
|
|
|
|
|
uint64_t Bytes) {
|
|
|
|
|
return wrap(Attribute::getWithDereferenceableBytes(*unwrap(C), Bytes));
|
2014-07-25 23:06:44 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-02-21 16:19:16 +00:00
|
|
|
|
extern "C" LLVMAttributeRef LLVMRustCreateDereferenceableOrNullAttr(LLVMContextRef C,
|
|
|
|
|
uint64_t Bytes) {
|
|
|
|
|
return wrap(Attribute::getWithDereferenceableOrNullBytes(*unwrap(C), Bytes));
|
2017-10-03 07:45:07 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-02-21 16:19:16 +00:00
|
|
|
|
extern "C" LLVMAttributeRef LLVMRustCreateByValAttr(LLVMContextRef C, LLVMTypeRef Ty) {
|
|
|
|
|
return wrap(Attribute::getWithByValType(*unwrap(C), unwrap(Ty)));
|
2019-07-06 19:52:25 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-02-21 16:19:16 +00:00
|
|
|
|
extern "C" LLVMAttributeRef LLVMRustCreateStructRetAttr(LLVMContextRef C, LLVMTypeRef Ty) {
|
|
|
|
|
return wrap(Attribute::getWithStructRetType(*unwrap(C), unwrap(Ty)));
|
2020-11-03 21:47:16 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-02-21 16:19:16 +00:00
|
|
|
|
extern "C" LLVMAttributeRef LLVMRustCreateUWTableAttr(LLVMContextRef C, bool Async) {
|
2022-02-14 19:01:19 +00:00
|
|
|
|
#if LLVM_VERSION_LT(15, 0)
|
2022-02-21 16:19:16 +00:00
|
|
|
|
return wrap(Attribute::get(*unwrap(C), Attribute::UWTable));
|
2021-09-07 18:49:03 +00:00
|
|
|
|
#else
|
2022-02-21 16:19:16 +00:00
|
|
|
|
return wrap(Attribute::getWithUWTableKind(
|
|
|
|
|
*unwrap(C), Async ? UWTableKind::Async : UWTableKind::Sync));
|
2021-09-07 18:49:03 +00:00
|
|
|
|
#endif
|
2014-04-19 17:33:46 +00:00
|
|
|
|
}
|
2013-09-09 06:32:30 +00:00
|
|
|
|
|
2021-04-17 17:40:59 +00:00
|
|
|
|
// Enable a fast-math flag
|
|
|
|
|
//
|
|
|
|
|
// https://llvm.org/docs/LangRef.html#fast-math-flags
|
|
|
|
|
extern "C" void LLVMRustSetFastMath(LLVMValueRef V) {
|
2016-12-30 11:22:11 +00:00
|
|
|
|
if (auto I = dyn_cast<Instruction>(unwrap<Value>(V))) {
|
2018-01-23 01:28:23 +00:00
|
|
|
|
I->setFast(true);
|
2016-12-30 11:22:11 +00:00
|
|
|
|
}
|
2016-03-14 23:01:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-12-30 11:22:11 +00:00
|
|
|
|
extern "C" LLVMValueRef
|
2021-07-04 15:49:51 +00:00
|
|
|
|
LLVMRustBuildAtomicLoad(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Source,
|
|
|
|
|
const char *Name, LLVMAtomicOrdering Order) {
|
2020-06-26 01:52:41 +00:00
|
|
|
|
Value *Ptr = unwrap(Source);
|
2021-07-04 15:49:51 +00:00
|
|
|
|
LoadInst *LI = unwrap(B)->CreateLoad(unwrap(Ty), Ptr, Name);
|
2016-12-31 17:01:23 +00:00
|
|
|
|
LI->setAtomic(fromRust(Order));
|
2020-06-26 01:52:41 +00:00
|
|
|
|
return wrap(LI);
|
2013-05-12 19:22:20 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-08-01 23:35:09 +00:00
|
|
|
|
extern "C" LLVMValueRef LLVMRustBuildAtomicStore(LLVMBuilderRef B,
|
2016-12-31 17:01:23 +00:00
|
|
|
|
LLVMValueRef V,
|
|
|
|
|
LLVMValueRef Target,
|
2017-06-01 18:50:53 +00:00
|
|
|
|
LLVMAtomicOrdering Order) {
|
2020-06-26 01:52:41 +00:00
|
|
|
|
StoreInst *SI = unwrap(B)->CreateStore(unwrap(V), unwrap(Target));
|
2016-12-31 17:01:23 +00:00
|
|
|
|
SI->setAtomic(fromRust(Order));
|
2020-06-26 01:52:41 +00:00
|
|
|
|
return wrap(SI);
|
2016-12-30 11:22:11 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-06-26 01:52:41 +00:00
|
|
|
|
// FIXME: Use the C-API LLVMBuildAtomicCmpXchg and LLVMSetWeak
|
|
|
|
|
// once we raise our minimum support to LLVM 10.
|
2016-12-30 11:22:11 +00:00
|
|
|
|
extern "C" LLVMValueRef
|
2016-12-31 17:01:23 +00:00
|
|
|
|
LLVMRustBuildAtomicCmpXchg(LLVMBuilderRef B, LLVMValueRef Target,
|
|
|
|
|
LLVMValueRef Old, LLVMValueRef Source,
|
|
|
|
|
LLVMAtomicOrdering Order,
|
|
|
|
|
LLVMAtomicOrdering FailureOrder, LLVMBool Weak) {
|
2021-03-19 20:46:40 +00:00
|
|
|
|
#if LLVM_VERSION_GE(13,0)
|
2021-03-22 18:37:49 +00:00
|
|
|
|
// Rust probably knows the alignment of the target value and should be able to
|
|
|
|
|
// specify something more precise than MaybeAlign here. See also
|
|
|
|
|
// https://reviews.llvm.org/D97224 which may be a useful reference.
|
2021-03-16 20:11:09 +00:00
|
|
|
|
AtomicCmpXchgInst *ACXI = unwrap(B)->CreateAtomicCmpXchg(
|
|
|
|
|
unwrap(Target), unwrap(Old), unwrap(Source), llvm::MaybeAlign(), fromRust(Order),
|
|
|
|
|
fromRust(FailureOrder));
|
|
|
|
|
#else
|
2016-12-31 17:01:23 +00:00
|
|
|
|
AtomicCmpXchgInst *ACXI = unwrap(B)->CreateAtomicCmpXchg(
|
|
|
|
|
unwrap(Target), unwrap(Old), unwrap(Source), fromRust(Order),
|
|
|
|
|
fromRust(FailureOrder));
|
2021-03-16 20:11:09 +00:00
|
|
|
|
#endif
|
2016-12-31 17:01:23 +00:00
|
|
|
|
ACXI->setWeak(Weak);
|
|
|
|
|
return wrap(ACXI);
|
2012-10-22 02:23:50 +00:00
|
|
|
|
}
|
2016-08-01 23:35:09 +00:00
|
|
|
|
|
|
|
|
|
enum class LLVMRustSynchronizationScope {
|
2016-12-30 11:22:11 +00:00
|
|
|
|
SingleThread,
|
|
|
|
|
CrossThread,
|
2016-08-01 23:35:09 +00:00
|
|
|
|
};
|
|
|
|
|
|
2017-07-21 12:02:52 +00:00
|
|
|
|
static SyncScope::ID fromRust(LLVMRustSynchronizationScope Scope) {
|
|
|
|
|
switch (Scope) {
|
|
|
|
|
case LLVMRustSynchronizationScope::SingleThread:
|
|
|
|
|
return SyncScope::SingleThread;
|
|
|
|
|
case LLVMRustSynchronizationScope::CrossThread:
|
|
|
|
|
return SyncScope::System;
|
|
|
|
|
default:
|
2017-11-20 16:47:29 +00:00
|
|
|
|
report_fatal_error("bad SynchronizationScope.");
|
2017-07-21 12:02:52 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2016-08-01 23:35:09 +00:00
|
|
|
|
|
2016-12-30 11:22:11 +00:00
|
|
|
|
extern "C" LLVMValueRef
|
2016-12-31 17:01:23 +00:00
|
|
|
|
LLVMRustBuildAtomicFence(LLVMBuilderRef B, LLVMAtomicOrdering Order,
|
|
|
|
|
LLVMRustSynchronizationScope Scope) {
|
|
|
|
|
return wrap(unwrap(B)->CreateFence(fromRust(Order), fromRust(Scope)));
|
2013-07-28 07:48:16 +00:00
|
|
|
|
}
|
2012-07-25 19:06:03 +00:00
|
|
|
|
|
2016-08-02 21:25:19 +00:00
|
|
|
|
enum class LLVMRustAsmDialect {
|
2016-12-30 11:22:11 +00:00
|
|
|
|
Att,
|
|
|
|
|
Intel,
|
2016-08-02 21:25:19 +00:00
|
|
|
|
};
|
|
|
|
|
|
2016-12-31 17:01:23 +00:00
|
|
|
|
static InlineAsm::AsmDialect fromRust(LLVMRustAsmDialect Dialect) {
|
|
|
|
|
switch (Dialect) {
|
2016-12-30 11:22:11 +00:00
|
|
|
|
case LLVMRustAsmDialect::Att:
|
|
|
|
|
return InlineAsm::AD_ATT;
|
|
|
|
|
case LLVMRustAsmDialect::Intel:
|
|
|
|
|
return InlineAsm::AD_Intel;
|
|
|
|
|
default:
|
2017-11-20 16:47:29 +00:00
|
|
|
|
report_fatal_error("bad AsmDialect.");
|
2016-12-30 11:22:11 +00:00
|
|
|
|
}
|
2016-08-02 21:25:19 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-03-10 00:00:00 +00:00
|
|
|
|
extern "C" LLVMValueRef
|
|
|
|
|
LLVMRustInlineAsm(LLVMTypeRef Ty, char *AsmString, size_t AsmStringLen,
|
|
|
|
|
char *Constraints, size_t ConstraintsLen,
|
|
|
|
|
LLVMBool HasSideEffects, LLVMBool IsAlignStack,
|
2021-08-28 17:02:00 +00:00
|
|
|
|
LLVMRustAsmDialect Dialect, LLVMBool CanThrow) {
|
2021-09-04 17:25:09 +00:00
|
|
|
|
#if LLVM_VERSION_GE(13, 0)
|
2020-03-10 00:00:00 +00:00
|
|
|
|
return wrap(InlineAsm::get(unwrap<FunctionType>(Ty),
|
|
|
|
|
StringRef(AsmString, AsmStringLen),
|
|
|
|
|
StringRef(Constraints, ConstraintsLen),
|
2021-08-28 17:02:00 +00:00
|
|
|
|
HasSideEffects, IsAlignStack,
|
|
|
|
|
fromRust(Dialect), CanThrow));
|
2021-09-04 17:25:09 +00:00
|
|
|
|
#else
|
|
|
|
|
return wrap(InlineAsm::get(unwrap<FunctionType>(Ty),
|
|
|
|
|
StringRef(AsmString, AsmStringLen),
|
|
|
|
|
StringRef(Constraints, ConstraintsLen),
|
|
|
|
|
HasSideEffects, IsAlignStack,
|
|
|
|
|
fromRust(Dialect)));
|
|
|
|
|
#endif
|
2013-03-10 06:37:50 +00:00
|
|
|
|
}
|
2013-06-14 04:25:12 +00:00
|
|
|
|
|
2020-03-10 00:00:00 +00:00
|
|
|
|
extern "C" bool LLVMRustInlineAsmVerify(LLVMTypeRef Ty, char *Constraints,
|
|
|
|
|
size_t ConstraintsLen) {
|
|
|
|
|
return InlineAsm::Verify(unwrap<FunctionType>(Ty),
|
|
|
|
|
StringRef(Constraints, ConstraintsLen));
|
2018-09-25 18:35:19 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-03-10 00:00:00 +00:00
|
|
|
|
extern "C" void LLVMRustAppendModuleInlineAsm(LLVMModuleRef M, const char *Asm,
|
|
|
|
|
size_t AsmLen) {
|
|
|
|
|
unwrap(M)->appendModuleInlineAsm(StringRef(Asm, AsmLen));
|
2017-03-22 00:50:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-12-30 11:22:11 +00:00
|
|
|
|
typedef DIBuilder *LLVMRustDIBuilderRef;
|
2013-06-14 18:38:29 +00:00
|
|
|
|
|
2017-07-21 11:15:36 +00:00
|
|
|
|
template <typename DIT> DIT *unwrapDIPtr(LLVMMetadataRef Ref) {
|
2016-12-31 17:01:23 +00:00
|
|
|
|
return (DIT *)(Ref ? unwrap<MDNode>(Ref) : nullptr);
|
rustc: Update LLVM
This commit updates the LLVM submodule in use to the current HEAD of the LLVM
repository. This is primarily being done to start picking up unwinding support
for MSVC, which is currently unimplemented in the revision of LLVM we are using.
Along the way a few changes had to be made:
* As usual, lots of C++ debuginfo bindings in LLVM changed, so there were some
significant changes to our RustWrapper.cpp
* As usual, some pass management changed in LLVM, so clang was re-scrutinized to
ensure that we're doing the same thing as clang.
* Some optimization options are now passed directly into the
`PassManagerBuilder` instead of through CLI switches to LLVM.
* The `NoFramePointerElim` option was removed from LLVM, favoring instead the
`no-frame-pointer-elim` function attribute instead.
Additionally, LLVM has picked up some new optimizations which required fixing an
existing soundness hole in the IR we generate. It appears that the current LLVM
we use does not expose this hole. When an enum is moved, the previous slot in
memory is overwritten with a bit pattern corresponding to "dropped". When the
drop glue for this slot is run, however, the switch on the discriminant can
often start executing the `unreachable` block of the switch due to the
discriminant now being outside the normal range. This was patched over locally
for now by having the `unreachable` block just change to a `ret void`.
2015-05-14 19:10:43 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define DIDescriptor DIScope
|
|
|
|
|
#define DIArray DINodeArray
|
2016-12-31 17:01:23 +00:00
|
|
|
|
#define unwrapDI unwrapDIPtr
|
2013-06-14 18:38:29 +00:00
|
|
|
|
|
2016-11-18 22:15:14 +00:00
|
|
|
|
// These values **must** match debuginfo::DIFlags! They also *happen*
|
|
|
|
|
// to match LLVM, but that isn't required as we do giant sets of
|
|
|
|
|
// matching below. The value shouldn't be directly passed to LLVM.
|
|
|
|
|
enum class LLVMRustDIFlags : uint32_t {
|
2016-12-30 11:22:11 +00:00
|
|
|
|
FlagZero = 0,
|
|
|
|
|
FlagPrivate = 1,
|
|
|
|
|
FlagProtected = 2,
|
|
|
|
|
FlagPublic = 3,
|
|
|
|
|
FlagFwdDecl = (1 << 2),
|
|
|
|
|
FlagAppleBlock = (1 << 3),
|
|
|
|
|
FlagBlockByrefStruct = (1 << 4),
|
|
|
|
|
FlagVirtual = (1 << 5),
|
|
|
|
|
FlagArtificial = (1 << 6),
|
|
|
|
|
FlagExplicit = (1 << 7),
|
|
|
|
|
FlagPrototyped = (1 << 8),
|
|
|
|
|
FlagObjcClassComplete = (1 << 9),
|
|
|
|
|
FlagObjectPointer = (1 << 10),
|
|
|
|
|
FlagVector = (1 << 11),
|
|
|
|
|
FlagStaticMember = (1 << 12),
|
|
|
|
|
FlagLValueReference = (1 << 13),
|
|
|
|
|
FlagRValueReference = (1 << 14),
|
2018-01-20 20:32:33 +00:00
|
|
|
|
FlagExternalTypeRef = (1 << 15),
|
|
|
|
|
FlagIntroducedVirtual = (1 << 18),
|
|
|
|
|
FlagBitField = (1 << 19),
|
|
|
|
|
FlagNoReturn = (1 << 20),
|
2016-12-30 11:22:11 +00:00
|
|
|
|
// Do not add values that are not supported by the minimum LLVM
|
2018-01-20 20:32:33 +00:00
|
|
|
|
// version we support! see llvm/include/llvm/IR/DebugInfoFlags.def
|
2016-11-18 22:15:14 +00:00
|
|
|
|
};
|
|
|
|
|
|
2016-12-31 17:01:23 +00:00
|
|
|
|
inline LLVMRustDIFlags operator&(LLVMRustDIFlags A, LLVMRustDIFlags B) {
|
|
|
|
|
return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(A) &
|
|
|
|
|
static_cast<uint32_t>(B));
|
2016-11-18 22:15:14 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-12-31 17:01:23 +00:00
|
|
|
|
inline LLVMRustDIFlags operator|(LLVMRustDIFlags A, LLVMRustDIFlags B) {
|
|
|
|
|
return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(A) |
|
|
|
|
|
static_cast<uint32_t>(B));
|
2016-11-18 22:15:14 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-12-31 17:01:23 +00:00
|
|
|
|
inline LLVMRustDIFlags &operator|=(LLVMRustDIFlags &A, LLVMRustDIFlags B) {
|
|
|
|
|
return A = A | B;
|
2016-11-18 22:15:14 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-12-31 17:01:23 +00:00
|
|
|
|
inline bool isSet(LLVMRustDIFlags F) { return F != LLVMRustDIFlags::FlagZero; }
|
2016-11-18 22:15:14 +00:00
|
|
|
|
|
2016-12-31 17:01:23 +00:00
|
|
|
|
inline LLVMRustDIFlags visibility(LLVMRustDIFlags F) {
|
|
|
|
|
return static_cast<LLVMRustDIFlags>(static_cast<uint32_t>(F) & 0x3);
|
2016-11-18 22:15:14 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-12-31 17:01:23 +00:00
|
|
|
|
static DINode::DIFlags fromRust(LLVMRustDIFlags Flags) {
|
|
|
|
|
DINode::DIFlags Result = DINode::DIFlags::FlagZero;
|
2016-11-18 22:15:14 +00:00
|
|
|
|
|
2016-12-31 17:01:23 +00:00
|
|
|
|
switch (visibility(Flags)) {
|
2016-12-30 11:22:11 +00:00
|
|
|
|
case LLVMRustDIFlags::FlagPrivate:
|
2016-12-31 17:01:23 +00:00
|
|
|
|
Result |= DINode::DIFlags::FlagPrivate;
|
2016-12-30 11:22:11 +00:00
|
|
|
|
break;
|
|
|
|
|
case LLVMRustDIFlags::FlagProtected:
|
2016-12-31 17:01:23 +00:00
|
|
|
|
Result |= DINode::DIFlags::FlagProtected;
|
2016-12-30 11:22:11 +00:00
|
|
|
|
break;
|
|
|
|
|
case LLVMRustDIFlags::FlagPublic:
|
2016-12-31 17:01:23 +00:00
|
|
|
|
Result |= DINode::DIFlags::FlagPublic;
|
2016-12-30 11:22:11 +00:00
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
// The rest are handled below
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2016-12-31 17:01:23 +00:00
|
|
|
|
if (isSet(Flags & LLVMRustDIFlags::FlagFwdDecl)) {
|
|
|
|
|
Result |= DINode::DIFlags::FlagFwdDecl;
|
2016-12-30 11:22:11 +00:00
|
|
|
|
}
|
2016-12-31 17:01:23 +00:00
|
|
|
|
if (isSet(Flags & LLVMRustDIFlags::FlagAppleBlock)) {
|
|
|
|
|
Result |= DINode::DIFlags::FlagAppleBlock;
|
2016-12-30 11:22:11 +00:00
|
|
|
|
}
|
2016-12-31 17:01:23 +00:00
|
|
|
|
if (isSet(Flags & LLVMRustDIFlags::FlagVirtual)) {
|
|
|
|
|
Result |= DINode::DIFlags::FlagVirtual;
|
2016-12-30 11:22:11 +00:00
|
|
|
|
}
|
2016-12-31 17:01:23 +00:00
|
|
|
|
if (isSet(Flags & LLVMRustDIFlags::FlagArtificial)) {
|
|
|
|
|
Result |= DINode::DIFlags::FlagArtificial;
|
2016-12-30 11:22:11 +00:00
|
|
|
|
}
|
2016-12-31 17:01:23 +00:00
|
|
|
|
if (isSet(Flags & LLVMRustDIFlags::FlagExplicit)) {
|
|
|
|
|
Result |= DINode::DIFlags::FlagExplicit;
|
2016-12-30 11:22:11 +00:00
|
|
|
|
}
|
2016-12-31 17:01:23 +00:00
|
|
|
|
if (isSet(Flags & LLVMRustDIFlags::FlagPrototyped)) {
|
|
|
|
|
Result |= DINode::DIFlags::FlagPrototyped;
|
2016-12-30 11:22:11 +00:00
|
|
|
|
}
|
2016-12-31 17:01:23 +00:00
|
|
|
|
if (isSet(Flags & LLVMRustDIFlags::FlagObjcClassComplete)) {
|
|
|
|
|
Result |= DINode::DIFlags::FlagObjcClassComplete;
|
2016-12-30 11:22:11 +00:00
|
|
|
|
}
|
2016-12-31 17:01:23 +00:00
|
|
|
|
if (isSet(Flags & LLVMRustDIFlags::FlagObjectPointer)) {
|
|
|
|
|
Result |= DINode::DIFlags::FlagObjectPointer;
|
2016-12-30 11:22:11 +00:00
|
|
|
|
}
|
2016-12-31 17:01:23 +00:00
|
|
|
|
if (isSet(Flags & LLVMRustDIFlags::FlagVector)) {
|
|
|
|
|
Result |= DINode::DIFlags::FlagVector;
|
2016-12-30 11:22:11 +00:00
|
|
|
|
}
|
2016-12-31 17:01:23 +00:00
|
|
|
|
if (isSet(Flags & LLVMRustDIFlags::FlagStaticMember)) {
|
|
|
|
|
Result |= DINode::DIFlags::FlagStaticMember;
|
2016-12-30 11:22:11 +00:00
|
|
|
|
}
|
2016-12-31 17:01:23 +00:00
|
|
|
|
if (isSet(Flags & LLVMRustDIFlags::FlagLValueReference)) {
|
|
|
|
|
Result |= DINode::DIFlags::FlagLValueReference;
|
2016-12-30 11:22:11 +00:00
|
|
|
|
}
|
2016-12-31 17:01:23 +00:00
|
|
|
|
if (isSet(Flags & LLVMRustDIFlags::FlagRValueReference)) {
|
|
|
|
|
Result |= DINode::DIFlags::FlagRValueReference;
|
2016-12-30 11:22:11 +00:00
|
|
|
|
}
|
2018-01-20 20:32:33 +00:00
|
|
|
|
if (isSet(Flags & LLVMRustDIFlags::FlagIntroducedVirtual)) {
|
|
|
|
|
Result |= DINode::DIFlags::FlagIntroducedVirtual;
|
|
|
|
|
}
|
|
|
|
|
if (isSet(Flags & LLVMRustDIFlags::FlagBitField)) {
|
|
|
|
|
Result |= DINode::DIFlags::FlagBitField;
|
|
|
|
|
}
|
|
|
|
|
if (isSet(Flags & LLVMRustDIFlags::FlagNoReturn)) {
|
|
|
|
|
Result |= DINode::DIFlags::FlagNoReturn;
|
|
|
|
|
}
|
2016-12-30 11:22:11 +00:00
|
|
|
|
|
2016-12-31 17:01:23 +00:00
|
|
|
|
return Result;
|
2016-11-18 22:15:14 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-01-16 17:59:03 +00:00
|
|
|
|
// These values **must** match debuginfo::DISPFlags! They also *happen*
|
|
|
|
|
// to match LLVM, but that isn't required as we do giant sets of
|
|
|
|
|
// matching below. The value shouldn't be directly passed to LLVM.
|
|
|
|
|
enum class LLVMRustDISPFlags : uint32_t {
|
|
|
|
|
SPFlagZero = 0,
|
|
|
|
|
SPFlagVirtual = 1,
|
|
|
|
|
SPFlagPureVirtual = 2,
|
|
|
|
|
SPFlagLocalToUnit = (1 << 2),
|
|
|
|
|
SPFlagDefinition = (1 << 3),
|
|
|
|
|
SPFlagOptimized = (1 << 4),
|
2019-04-04 20:05:41 +00:00
|
|
|
|
SPFlagMainSubprogram = (1 << 5),
|
2019-01-16 17:59:03 +00:00
|
|
|
|
// Do not add values that are not supported by the minimum LLVM
|
|
|
|
|
// version we support! see llvm/include/llvm/IR/DebugInfoFlags.def
|
|
|
|
|
// (In LLVM < 8, createFunction supported these as separate bool arguments.)
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
inline LLVMRustDISPFlags operator&(LLVMRustDISPFlags A, LLVMRustDISPFlags B) {
|
|
|
|
|
return static_cast<LLVMRustDISPFlags>(static_cast<uint32_t>(A) &
|
|
|
|
|
static_cast<uint32_t>(B));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline LLVMRustDISPFlags operator|(LLVMRustDISPFlags A, LLVMRustDISPFlags B) {
|
|
|
|
|
return static_cast<LLVMRustDISPFlags>(static_cast<uint32_t>(A) |
|
|
|
|
|
static_cast<uint32_t>(B));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline LLVMRustDISPFlags &operator|=(LLVMRustDISPFlags &A, LLVMRustDISPFlags B) {
|
|
|
|
|
return A = A | B;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inline bool isSet(LLVMRustDISPFlags F) { return F != LLVMRustDISPFlags::SPFlagZero; }
|
|
|
|
|
|
|
|
|
|
inline LLVMRustDISPFlags virtuality(LLVMRustDISPFlags F) {
|
|
|
|
|
return static_cast<LLVMRustDISPFlags>(static_cast<uint32_t>(F) & 0x3);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static DISubprogram::DISPFlags fromRust(LLVMRustDISPFlags SPFlags) {
|
|
|
|
|
DISubprogram::DISPFlags Result = DISubprogram::DISPFlags::SPFlagZero;
|
|
|
|
|
|
|
|
|
|
switch (virtuality(SPFlags)) {
|
|
|
|
|
case LLVMRustDISPFlags::SPFlagVirtual:
|
|
|
|
|
Result |= DISubprogram::DISPFlags::SPFlagVirtual;
|
|
|
|
|
break;
|
|
|
|
|
case LLVMRustDISPFlags::SPFlagPureVirtual:
|
|
|
|
|
Result |= DISubprogram::DISPFlags::SPFlagPureVirtual;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
// The rest are handled below
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagLocalToUnit)) {
|
|
|
|
|
Result |= DISubprogram::DISPFlags::SPFlagLocalToUnit;
|
|
|
|
|
}
|
|
|
|
|
if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagDefinition)) {
|
|
|
|
|
Result |= DISubprogram::DISPFlags::SPFlagDefinition;
|
|
|
|
|
}
|
|
|
|
|
if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagOptimized)) {
|
|
|
|
|
Result |= DISubprogram::DISPFlags::SPFlagOptimized;
|
|
|
|
|
}
|
2019-04-04 20:05:41 +00:00
|
|
|
|
if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagMainSubprogram)) {
|
|
|
|
|
Result |= DISubprogram::DISPFlags::SPFlagMainSubprogram;
|
|
|
|
|
}
|
2019-01-16 17:59:03 +00:00
|
|
|
|
|
|
|
|
|
return Result;
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-22 21:01:14 +00:00
|
|
|
|
enum class LLVMRustDebugEmissionKind {
|
|
|
|
|
NoDebug,
|
|
|
|
|
FullDebug,
|
|
|
|
|
LineTablesOnly,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static DICompileUnit::DebugEmissionKind fromRust(LLVMRustDebugEmissionKind Kind) {
|
|
|
|
|
switch (Kind) {
|
|
|
|
|
case LLVMRustDebugEmissionKind::NoDebug:
|
|
|
|
|
return DICompileUnit::DebugEmissionKind::NoDebug;
|
|
|
|
|
case LLVMRustDebugEmissionKind::FullDebug:
|
|
|
|
|
return DICompileUnit::DebugEmissionKind::FullDebug;
|
|
|
|
|
case LLVMRustDebugEmissionKind::LineTablesOnly:
|
|
|
|
|
return DICompileUnit::DebugEmissionKind::LineTablesOnly;
|
|
|
|
|
default:
|
|
|
|
|
report_fatal_error("bad DebugEmissionKind.");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-31 05:17:15 +00:00
|
|
|
|
enum class LLVMRustChecksumKind {
|
|
|
|
|
None,
|
|
|
|
|
MD5,
|
|
|
|
|
SHA1,
|
2020-10-13 15:41:06 +00:00
|
|
|
|
SHA256,
|
2020-03-31 05:17:15 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static Optional<DIFile::ChecksumKind> fromRust(LLVMRustChecksumKind Kind) {
|
|
|
|
|
switch (Kind) {
|
|
|
|
|
case LLVMRustChecksumKind::None:
|
|
|
|
|
return None;
|
|
|
|
|
case LLVMRustChecksumKind::MD5:
|
|
|
|
|
return DIFile::ChecksumKind::CSK_MD5;
|
|
|
|
|
case LLVMRustChecksumKind::SHA1:
|
|
|
|
|
return DIFile::ChecksumKind::CSK_SHA1;
|
2020-10-13 15:41:06 +00:00
|
|
|
|
case LLVMRustChecksumKind::SHA256:
|
|
|
|
|
return DIFile::ChecksumKind::CSK_SHA256;
|
2020-03-31 05:17:15 +00:00
|
|
|
|
default:
|
|
|
|
|
report_fatal_error("bad ChecksumKind.");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-30 13:50:12 +00:00
|
|
|
|
extern "C" uint32_t LLVMRustDebugMetadataVersion() {
|
2016-12-30 11:22:11 +00:00
|
|
|
|
return DEBUG_METADATA_VERSION;
|
2015-05-12 04:07:38 +00:00
|
|
|
|
}
|
2014-01-28 05:05:33 +00:00
|
|
|
|
|
2020-10-13 02:33:27 +00:00
|
|
|
|
extern "C" uint32_t LLVMRustVersionPatch() { return LLVM_VERSION_PATCH; }
|
|
|
|
|
|
2016-12-30 11:22:11 +00:00
|
|
|
|
extern "C" uint32_t LLVMRustVersionMinor() { return LLVM_VERSION_MINOR; }
|
2015-01-24 11:00:35 +00:00
|
|
|
|
|
2016-12-30 11:22:11 +00:00
|
|
|
|
extern "C" uint32_t LLVMRustVersionMajor() { return LLVM_VERSION_MAJOR; }
|
2015-01-24 11:00:35 +00:00
|
|
|
|
|
2022-01-19 14:51:59 +00:00
|
|
|
|
extern "C" void LLVMRustAddModuleFlag(
|
|
|
|
|
LLVMModuleRef M,
|
|
|
|
|
Module::ModFlagBehavior MergeBehavior,
|
|
|
|
|
const char *Name,
|
|
|
|
|
uint32_t Value) {
|
|
|
|
|
unwrap(M)->addModuleFlag(MergeBehavior, Name, Value);
|
2014-01-28 05:05:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-12-12 17:27:37 +00:00
|
|
|
|
extern "C" LLVMValueRef LLVMRustMetadataAsValue(LLVMContextRef C, LLVMMetadataRef MD) {
|
|
|
|
|
return wrap(MetadataAsValue::get(*unwrap(C), unwrap(MD)));
|
2017-02-13 09:57:50 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-08-01 23:35:09 +00:00
|
|
|
|
extern "C" LLVMRustDIBuilderRef LLVMRustDIBuilderCreate(LLVMModuleRef M) {
|
2016-12-30 11:22:11 +00:00
|
|
|
|
return new DIBuilder(*unwrap(M));
|
2013-06-14 18:38:29 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-08-01 23:35:09 +00:00
|
|
|
|
extern "C" void LLVMRustDIBuilderDispose(LLVMRustDIBuilderRef Builder) {
|
2016-12-30 11:22:11 +00:00
|
|
|
|
delete Builder;
|
2013-06-14 18:38:29 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-08-01 23:35:09 +00:00
|
|
|
|
extern "C" void LLVMRustDIBuilderFinalize(LLVMRustDIBuilderRef Builder) {
|
2016-12-30 11:22:11 +00:00
|
|
|
|
Builder->finalize();
|
2013-06-14 18:38:29 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-07-21 11:15:36 +00:00
|
|
|
|
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateCompileUnit(
|
|
|
|
|
LLVMRustDIBuilderRef Builder, unsigned Lang, LLVMMetadataRef FileRef,
|
2020-03-06 00:00:00 +00:00
|
|
|
|
const char *Producer, size_t ProducerLen, bool isOptimized,
|
|
|
|
|
const char *Flags, unsigned RuntimeVer,
|
|
|
|
|
const char *SplitName, size_t SplitNameLen,
|
2020-09-23 15:25:20 +00:00
|
|
|
|
LLVMRustDebugEmissionKind Kind,
|
|
|
|
|
uint64_t DWOId, bool SplitDebugInlining) {
|
2017-02-11 21:01:25 +00:00
|
|
|
|
auto *File = unwrapDI<DIFile>(FileRef);
|
|
|
|
|
|
2020-03-06 00:00:00 +00:00
|
|
|
|
return wrap(Builder->createCompileUnit(Lang, File, StringRef(Producer, ProducerLen),
|
|
|
|
|
isOptimized, Flags, RuntimeVer,
|
|
|
|
|
StringRef(SplitName, SplitNameLen),
|
2020-09-23 15:25:20 +00:00
|
|
|
|
fromRust(Kind), DWOId, SplitDebugInlining));
|
2016-12-30 11:22:11 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-03-06 00:00:00 +00:00
|
|
|
|
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFile(
|
|
|
|
|
LLVMRustDIBuilderRef Builder,
|
|
|
|
|
const char *Filename, size_t FilenameLen,
|
2020-03-31 05:17:15 +00:00
|
|
|
|
const char *Directory, size_t DirectoryLen, LLVMRustChecksumKind CSKind,
|
|
|
|
|
const char *Checksum, size_t ChecksumLen) {
|
|
|
|
|
Optional<DIFile::ChecksumKind> llvmCSKind = fromRust(CSKind);
|
|
|
|
|
Optional<DIFile::ChecksumInfo<StringRef>> CSInfo{};
|
|
|
|
|
if (llvmCSKind)
|
|
|
|
|
CSInfo.emplace(*llvmCSKind, StringRef{Checksum, ChecksumLen});
|
2020-03-06 00:00:00 +00:00
|
|
|
|
return wrap(Builder->createFile(StringRef(Filename, FilenameLen),
|
2020-03-31 05:17:15 +00:00
|
|
|
|
StringRef(Directory, DirectoryLen),
|
|
|
|
|
CSInfo));
|
2016-12-30 11:22:11 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-07-21 11:15:36 +00:00
|
|
|
|
extern "C" LLVMMetadataRef
|
2016-12-30 11:22:11 +00:00
|
|
|
|
LLVMRustDIBuilderCreateSubroutineType(LLVMRustDIBuilderRef Builder,
|
2017-07-21 11:15:36 +00:00
|
|
|
|
LLVMMetadataRef ParameterTypes) {
|
2016-12-30 11:22:11 +00:00
|
|
|
|
return wrap(Builder->createSubroutineType(
|
|
|
|
|
DITypeRefArray(unwrap<MDTuple>(ParameterTypes))));
|
2013-06-14 18:38:29 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-07-21 11:15:36 +00:00
|
|
|
|
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFunction(
|
2020-03-06 00:00:00 +00:00
|
|
|
|
LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
|
|
|
|
|
const char *Name, size_t NameLen,
|
|
|
|
|
const char *LinkageName, size_t LinkageNameLen,
|
|
|
|
|
LLVMMetadataRef File, unsigned LineNo,
|
2019-01-16 17:59:03 +00:00
|
|
|
|
LLVMMetadataRef Ty, unsigned ScopeLine, LLVMRustDIFlags Flags,
|
2020-02-10 20:30:51 +00:00
|
|
|
|
LLVMRustDISPFlags SPFlags, LLVMValueRef MaybeFn, LLVMMetadataRef TParam,
|
2019-01-16 17:59:03 +00:00
|
|
|
|
LLVMMetadataRef Decl) {
|
2016-12-30 11:22:11 +00:00
|
|
|
|
DITemplateParameterArray TParams =
|
|
|
|
|
DITemplateParameterArray(unwrap<MDTuple>(TParam));
|
2019-04-04 20:05:41 +00:00
|
|
|
|
DISubprogram::DISPFlags llvmSPFlags = fromRust(SPFlags);
|
|
|
|
|
DINode::DIFlags llvmFlags = fromRust(Flags);
|
2019-01-16 17:59:03 +00:00
|
|
|
|
DISubprogram *Sub = Builder->createFunction(
|
2020-03-06 00:00:00 +00:00
|
|
|
|
unwrapDI<DIScope>(Scope),
|
|
|
|
|
StringRef(Name, NameLen),
|
|
|
|
|
StringRef(LinkageName, LinkageNameLen),
|
|
|
|
|
unwrapDI<DIFile>(File), LineNo,
|
|
|
|
|
unwrapDI<DISubroutineType>(Ty), ScopeLine, llvmFlags,
|
2019-04-04 20:05:41 +00:00
|
|
|
|
llvmSPFlags, TParams, unwrapDIPtr<DISubprogram>(Decl));
|
2020-02-10 20:30:51 +00:00
|
|
|
|
if (MaybeFn)
|
|
|
|
|
unwrap<Function>(MaybeFn)->setSubprogram(Sub);
|
2016-12-30 11:22:11 +00:00
|
|
|
|
return wrap(Sub);
|
2013-06-14 18:38:29 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-03-06 00:00:00 +00:00
|
|
|
|
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateBasicType(
|
|
|
|
|
LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen,
|
2020-05-21 17:53:41 +00:00
|
|
|
|
uint64_t SizeInBits, unsigned Encoding) {
|
2020-03-06 00:00:00 +00:00
|
|
|
|
return wrap(Builder->createBasicType(StringRef(Name, NameLen), SizeInBits, Encoding));
|
2013-06-14 18:38:29 +00:00
|
|
|
|
}
|
2013-07-02 16:10:24 +00:00
|
|
|
|
|
2020-06-25 06:28:00 +00:00
|
|
|
|
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateTypedef(
|
|
|
|
|
LLVMRustDIBuilderRef Builder, LLVMMetadataRef Type, const char *Name, size_t NameLen,
|
|
|
|
|
LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Scope) {
|
|
|
|
|
return wrap(Builder->createTypedef(
|
|
|
|
|
unwrap<DIType>(Type), StringRef(Name, NameLen), unwrap<DIFile>(File),
|
2020-10-28 01:05:16 +00:00
|
|
|
|
LineNo, unwrapDIPtr<DIScope>(Scope)));
|
2020-06-25 06:28:00 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-07-21 11:15:36 +00:00
|
|
|
|
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreatePointerType(
|
|
|
|
|
LLVMRustDIBuilderRef Builder, LLVMMetadataRef PointeeTy,
|
2020-03-06 00:00:00 +00:00
|
|
|
|
uint64_t SizeInBits, uint32_t AlignInBits, unsigned AddressSpace,
|
|
|
|
|
const char *Name, size_t NameLen) {
|
2016-12-30 11:22:11 +00:00
|
|
|
|
return wrap(Builder->createPointerType(unwrapDI<DIType>(PointeeTy),
|
2017-07-21 11:26:41 +00:00
|
|
|
|
SizeInBits, AlignInBits,
|
2020-03-06 00:00:00 +00:00
|
|
|
|
AddressSpace,
|
|
|
|
|
StringRef(Name, NameLen)));
|
2013-06-14 18:38:29 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-07-21 11:15:36 +00:00
|
|
|
|
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStructType(
|
2020-03-06 00:00:00 +00:00
|
|
|
|
LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
|
|
|
|
|
const char *Name, size_t NameLen,
|
2017-07-21 11:15:36 +00:00
|
|
|
|
LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
|
2017-02-04 10:51:10 +00:00
|
|
|
|
uint32_t AlignInBits, LLVMRustDIFlags Flags,
|
2017-07-21 11:15:36 +00:00
|
|
|
|
LLVMMetadataRef DerivedFrom, LLVMMetadataRef Elements,
|
|
|
|
|
unsigned RunTimeLang, LLVMMetadataRef VTableHolder,
|
2020-03-06 00:00:00 +00:00
|
|
|
|
const char *UniqueId, size_t UniqueIdLen) {
|
2016-12-30 11:22:11 +00:00
|
|
|
|
return wrap(Builder->createStructType(
|
2020-03-06 00:00:00 +00:00
|
|
|
|
unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
|
|
|
|
|
unwrapDI<DIFile>(File), LineNumber,
|
2016-12-31 17:01:23 +00:00
|
|
|
|
SizeInBits, AlignInBits, fromRust(Flags), unwrapDI<DIType>(DerivedFrom),
|
2016-12-30 11:22:11 +00:00
|
|
|
|
DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang,
|
2020-03-06 00:00:00 +00:00
|
|
|
|
unwrapDI<DIType>(VTableHolder), StringRef(UniqueId, UniqueIdLen)));
|
2013-06-14 18:38:29 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-11-29 21:42:25 +00:00
|
|
|
|
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantPart(
|
2020-03-06 00:00:00 +00:00
|
|
|
|
LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
|
|
|
|
|
const char *Name, size_t NameLen,
|
2017-11-29 21:42:25 +00:00
|
|
|
|
LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
|
|
|
|
|
uint32_t AlignInBits, LLVMRustDIFlags Flags, LLVMMetadataRef Discriminator,
|
2020-03-06 00:00:00 +00:00
|
|
|
|
LLVMMetadataRef Elements, const char *UniqueId, size_t UniqueIdLen) {
|
2017-11-29 21:42:25 +00:00
|
|
|
|
return wrap(Builder->createVariantPart(
|
2020-03-06 00:00:00 +00:00
|
|
|
|
unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
|
|
|
|
|
unwrapDI<DIFile>(File), LineNumber,
|
2017-11-29 21:42:25 +00:00
|
|
|
|
SizeInBits, AlignInBits, fromRust(Flags), unwrapDI<DIDerivedType>(Discriminator),
|
2020-03-06 00:00:00 +00:00
|
|
|
|
DINodeArray(unwrapDI<MDTuple>(Elements)), StringRef(UniqueId, UniqueIdLen)));
|
2017-11-29 21:42:25 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-07-21 11:15:36 +00:00
|
|
|
|
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateMemberType(
|
2020-03-06 00:00:00 +00:00
|
|
|
|
LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
|
|
|
|
|
const char *Name, size_t NameLen,
|
2017-07-21 11:15:36 +00:00
|
|
|
|
LLVMMetadataRef File, unsigned LineNo, uint64_t SizeInBits,
|
2017-02-04 10:51:10 +00:00
|
|
|
|
uint32_t AlignInBits, uint64_t OffsetInBits, LLVMRustDIFlags Flags,
|
2017-07-21 11:15:36 +00:00
|
|
|
|
LLVMMetadataRef Ty) {
|
2020-03-06 00:00:00 +00:00
|
|
|
|
return wrap(Builder->createMemberType(unwrapDI<DIDescriptor>(Scope),
|
|
|
|
|
StringRef(Name, NameLen),
|
2016-12-31 17:01:23 +00:00
|
|
|
|
unwrapDI<DIFile>(File), LineNo,
|
|
|
|
|
SizeInBits, AlignInBits, OffsetInBits,
|
|
|
|
|
fromRust(Flags), unwrapDI<DIType>(Ty)));
|
2013-06-14 18:38:29 +00:00
|
|
|
|
}
|
2013-07-02 16:10:24 +00:00
|
|
|
|
|
2017-11-29 21:42:25 +00:00
|
|
|
|
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantMemberType(
|
|
|
|
|
LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
|
2020-03-06 00:00:00 +00:00
|
|
|
|
const char *Name, size_t NameLen, LLVMMetadataRef File, unsigned LineNo,
|
|
|
|
|
uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, LLVMValueRef Discriminant,
|
2017-11-29 21:42:25 +00:00
|
|
|
|
LLVMRustDIFlags Flags, LLVMMetadataRef Ty) {
|
|
|
|
|
llvm::ConstantInt* D = nullptr;
|
|
|
|
|
if (Discriminant) {
|
|
|
|
|
D = unwrap<llvm::ConstantInt>(Discriminant);
|
|
|
|
|
}
|
2020-03-06 00:00:00 +00:00
|
|
|
|
return wrap(Builder->createVariantMemberType(unwrapDI<DIDescriptor>(Scope),
|
|
|
|
|
StringRef(Name, NameLen),
|
2017-11-29 21:42:25 +00:00
|
|
|
|
unwrapDI<DIFile>(File), LineNo,
|
|
|
|
|
SizeInBits, AlignInBits, OffsetInBits, D,
|
|
|
|
|
fromRust(Flags), unwrapDI<DIType>(Ty)));
|
|
|
|
|
}
|
|
|
|
|
|
2017-07-21 11:15:36 +00:00
|
|
|
|
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateLexicalBlock(
|
|
|
|
|
LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
|
|
|
|
|
LLVMMetadataRef File, unsigned Line, unsigned Col) {
|
2016-12-30 11:22:11 +00:00
|
|
|
|
return wrap(Builder->createLexicalBlock(unwrapDI<DIDescriptor>(Scope),
|
|
|
|
|
unwrapDI<DIFile>(File), Line, Col));
|
2013-06-14 18:38:29 +00:00
|
|
|
|
}
|
2013-07-02 16:10:24 +00:00
|
|
|
|
|
2017-07-21 11:15:36 +00:00
|
|
|
|
extern "C" LLVMMetadataRef
|
2016-12-30 11:22:11 +00:00
|
|
|
|
LLVMRustDIBuilderCreateLexicalBlockFile(LLVMRustDIBuilderRef Builder,
|
2017-07-21 11:15:36 +00:00
|
|
|
|
LLVMMetadataRef Scope,
|
|
|
|
|
LLVMMetadataRef File) {
|
2016-12-30 11:22:11 +00:00
|
|
|
|
return wrap(Builder->createLexicalBlockFile(unwrapDI<DIDescriptor>(Scope),
|
|
|
|
|
unwrapDI<DIFile>(File)));
|
2016-08-25 02:34:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-07-21 11:15:36 +00:00
|
|
|
|
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticVariable(
|
2020-03-06 00:00:00 +00:00
|
|
|
|
LLVMRustDIBuilderRef Builder, LLVMMetadataRef Context,
|
|
|
|
|
const char *Name, size_t NameLen,
|
|
|
|
|
const char *LinkageName, size_t LinkageNameLen,
|
|
|
|
|
LLVMMetadataRef File, unsigned LineNo,
|
2017-07-21 11:15:36 +00:00
|
|
|
|
LLVMMetadataRef Ty, bool IsLocalToUnit, LLVMValueRef V,
|
|
|
|
|
LLVMMetadataRef Decl = nullptr, uint32_t AlignInBits = 0) {
|
2017-03-16 20:10:04 +00:00
|
|
|
|
llvm::GlobalVariable *InitVal = cast<llvm::GlobalVariable>(unwrap(V));
|
2016-12-11 09:08:20 +00:00
|
|
|
|
|
2016-12-30 11:22:11 +00:00
|
|
|
|
llvm::DIExpression *InitExpr = nullptr;
|
|
|
|
|
if (llvm::ConstantInt *IntVal = llvm::dyn_cast<llvm::ConstantInt>(InitVal)) {
|
|
|
|
|
InitExpr = Builder->createConstantValueExpression(
|
|
|
|
|
IntVal->getValue().getSExtValue());
|
|
|
|
|
} else if (llvm::ConstantFP *FPVal =
|
|
|
|
|
llvm::dyn_cast<llvm::ConstantFP>(InitVal)) {
|
|
|
|
|
InitExpr = Builder->createConstantValueExpression(
|
|
|
|
|
FPVal->getValueAPF().bitcastToAPInt().getZExtValue());
|
|
|
|
|
}
|
2016-12-11 09:08:20 +00:00
|
|
|
|
|
2017-03-16 20:10:04 +00:00
|
|
|
|
llvm::DIGlobalVariableExpression *VarExpr = Builder->createGlobalVariableExpression(
|
2020-03-06 00:00:00 +00:00
|
|
|
|
unwrapDI<DIDescriptor>(Context), StringRef(Name, NameLen),
|
|
|
|
|
StringRef(LinkageName, LinkageNameLen),
|
2016-12-31 17:01:23 +00:00
|
|
|
|
unwrapDI<DIFile>(File), LineNo, unwrapDI<DIType>(Ty), IsLocalToUnit,
|
2019-12-31 13:23:53 +00:00
|
|
|
|
/* isDefined */ true,
|
2018-11-07 12:34:43 +00:00
|
|
|
|
InitExpr, unwrapDIPtr<MDNode>(Decl),
|
|
|
|
|
/* templateParams */ nullptr,
|
|
|
|
|
AlignInBits);
|
2017-03-16 20:10:04 +00:00
|
|
|
|
|
|
|
|
|
InitVal->setMetadata("dbg", VarExpr);
|
|
|
|
|
|
|
|
|
|
return wrap(VarExpr);
|
2014-02-21 01:44:29 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-07-21 11:15:36 +00:00
|
|
|
|
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariable(
|
|
|
|
|
LLVMRustDIBuilderRef Builder, unsigned Tag, LLVMMetadataRef Scope,
|
2020-03-06 00:00:00 +00:00
|
|
|
|
const char *Name, size_t NameLen,
|
|
|
|
|
LLVMMetadataRef File, unsigned LineNo,
|
2017-07-21 11:15:36 +00:00
|
|
|
|
LLVMMetadataRef Ty, bool AlwaysPreserve, LLVMRustDIFlags Flags,
|
2017-02-04 10:51:10 +00:00
|
|
|
|
unsigned ArgNo, uint32_t AlignInBits) {
|
2016-12-30 11:22:11 +00:00
|
|
|
|
if (Tag == 0x100) { // DW_TAG_auto_variable
|
|
|
|
|
return wrap(Builder->createAutoVariable(
|
2020-03-06 00:00:00 +00:00
|
|
|
|
unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
|
|
|
|
|
unwrapDI<DIFile>(File), LineNo,
|
2018-06-29 08:28:51 +00:00
|
|
|
|
unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags), AlignInBits));
|
2016-12-30 11:22:11 +00:00
|
|
|
|
} else {
|
|
|
|
|
return wrap(Builder->createParameterVariable(
|
2020-03-06 00:00:00 +00:00
|
|
|
|
unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), ArgNo,
|
|
|
|
|
unwrapDI<DIFile>(File), LineNo,
|
|
|
|
|
unwrapDI<DIType>(Ty), AlwaysPreserve, fromRust(Flags)));
|
2016-12-30 11:22:11 +00:00
|
|
|
|
}
|
2013-06-14 18:38:29 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-07-21 11:15:36 +00:00
|
|
|
|
extern "C" LLVMMetadataRef
|
2016-12-30 11:22:11 +00:00
|
|
|
|
LLVMRustDIBuilderCreateArrayType(LLVMRustDIBuilderRef Builder, uint64_t Size,
|
2017-07-21 11:15:36 +00:00
|
|
|
|
uint32_t AlignInBits, LLVMMetadataRef Ty,
|
|
|
|
|
LLVMMetadataRef Subscripts) {
|
2016-12-30 11:22:11 +00:00
|
|
|
|
return wrap(
|
|
|
|
|
Builder->createArrayType(Size, AlignInBits, unwrapDI<DIType>(Ty),
|
|
|
|
|
DINodeArray(unwrapDI<MDTuple>(Subscripts))));
|
2013-06-14 18:38:29 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-07-21 11:15:36 +00:00
|
|
|
|
extern "C" LLVMMetadataRef
|
2016-12-30 11:22:11 +00:00
|
|
|
|
LLVMRustDIBuilderGetOrCreateSubrange(LLVMRustDIBuilderRef Builder, int64_t Lo,
|
|
|
|
|
int64_t Count) {
|
|
|
|
|
return wrap(Builder->getOrCreateSubrange(Lo, Count));
|
2013-06-14 18:38:29 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-07-21 11:15:36 +00:00
|
|
|
|
extern "C" LLVMMetadataRef
|
2016-12-30 11:22:11 +00:00
|
|
|
|
LLVMRustDIBuilderGetOrCreateArray(LLVMRustDIBuilderRef Builder,
|
2017-07-21 11:15:36 +00:00
|
|
|
|
LLVMMetadataRef *Ptr, unsigned Count) {
|
2016-12-30 11:22:11 +00:00
|
|
|
|
Metadata **DataValue = unwrap(Ptr);
|
|
|
|
|
return wrap(
|
|
|
|
|
Builder->getOrCreateArray(ArrayRef<Metadata *>(DataValue, Count)).get());
|
2013-06-14 18:38:29 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-08-01 23:35:09 +00:00
|
|
|
|
extern "C" LLVMValueRef LLVMRustDIBuilderInsertDeclareAtEnd(
|
2017-07-21 11:15:36 +00:00
|
|
|
|
LLVMRustDIBuilderRef Builder, LLVMValueRef V, LLVMMetadataRef VarInfo,
|
2022-01-03 10:25:33 +00:00
|
|
|
|
uint64_t *AddrOps, unsigned AddrOpsCount, LLVMMetadataRef DL,
|
2013-06-11 07:57:25 +00:00
|
|
|
|
LLVMBasicBlockRef InsertAtEnd) {
|
2016-12-30 11:22:11 +00:00
|
|
|
|
return wrap(Builder->insertDeclare(
|
2016-12-31 17:01:23 +00:00
|
|
|
|
unwrap(V), unwrap<DILocalVariable>(VarInfo),
|
2022-01-03 10:25:33 +00:00
|
|
|
|
Builder->createExpression(llvm::ArrayRef<uint64_t>(AddrOps, AddrOpsCount)),
|
2020-10-29 16:45:15 +00:00
|
|
|
|
DebugLoc(cast<MDNode>(unwrap(DL))),
|
2016-12-30 11:22:11 +00:00
|
|
|
|
unwrap(InsertAtEnd)));
|
2013-06-11 07:57:25 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-03-05 00:00:00 +00:00
|
|
|
|
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerator(
|
|
|
|
|
LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen,
|
|
|
|
|
int64_t Value, bool IsUnsigned) {
|
2020-03-06 00:00:00 +00:00
|
|
|
|
return wrap(Builder->createEnumerator(StringRef(Name, NameLen), Value, IsUnsigned));
|
2013-07-02 08:33:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-07-21 11:15:36 +00:00
|
|
|
|
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerationType(
|
2020-03-06 00:00:00 +00:00
|
|
|
|
LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
|
|
|
|
|
const char *Name, size_t NameLen,
|
2017-07-21 11:15:36 +00:00
|
|
|
|
LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
|
|
|
|
|
uint32_t AlignInBits, LLVMMetadataRef Elements,
|
2019-01-16 17:59:03 +00:00
|
|
|
|
LLVMMetadataRef ClassTy, bool IsScoped) {
|
2016-12-30 11:22:11 +00:00
|
|
|
|
return wrap(Builder->createEnumerationType(
|
2020-03-06 00:00:00 +00:00
|
|
|
|
unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
|
|
|
|
|
unwrapDI<DIFile>(File), LineNumber,
|
2016-12-30 11:22:11 +00:00
|
|
|
|
SizeInBits, AlignInBits, DINodeArray(unwrapDI<MDTuple>(Elements)),
|
2019-01-16 17:59:03 +00:00
|
|
|
|
unwrapDI<DIType>(ClassTy), "", IsScoped));
|
2013-07-02 16:10:24 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-07-21 11:15:36 +00:00
|
|
|
|
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateUnionType(
|
2020-03-06 00:00:00 +00:00
|
|
|
|
LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
|
|
|
|
|
const char *Name, size_t NameLen,
|
2017-07-21 11:15:36 +00:00
|
|
|
|
LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits,
|
|
|
|
|
uint32_t AlignInBits, LLVMRustDIFlags Flags, LLVMMetadataRef Elements,
|
2020-03-06 00:00:00 +00:00
|
|
|
|
unsigned RunTimeLang, const char *UniqueId, size_t UniqueIdLen) {
|
2016-12-30 11:22:11 +00:00
|
|
|
|
return wrap(Builder->createUnionType(
|
2020-03-06 00:00:00 +00:00
|
|
|
|
unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIFile>(File),
|
|
|
|
|
LineNumber, SizeInBits, AlignInBits, fromRust(Flags),
|
|
|
|
|
DINodeArray(unwrapDI<MDTuple>(Elements)), RunTimeLang,
|
|
|
|
|
StringRef(UniqueId, UniqueIdLen)));
|
2013-07-28 07:48:16 +00:00
|
|
|
|
}
|
2013-08-09 20:47:00 +00:00
|
|
|
|
|
2017-07-21 11:15:36 +00:00
|
|
|
|
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateTemplateTypeParameter(
|
2020-03-06 00:00:00 +00:00
|
|
|
|
LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
|
2020-05-21 17:53:41 +00:00
|
|
|
|
const char *Name, size_t NameLen, LLVMMetadataRef Ty) {
|
2020-06-26 01:52:41 +00:00
|
|
|
|
bool IsDefault = false; // FIXME: should we ever set this true?
|
|
|
|
|
return wrap(Builder->createTemplateTypeParameter(
|
|
|
|
|
unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), unwrapDI<DIType>(Ty), IsDefault));
|
2016-12-30 11:22:11 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-03-06 00:00:00 +00:00
|
|
|
|
extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateNameSpace(
|
|
|
|
|
LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope,
|
|
|
|
|
const char *Name, size_t NameLen, bool ExportSymbols) {
|
2016-12-30 11:22:11 +00:00
|
|
|
|
return wrap(Builder->createNameSpace(
|
2020-03-06 00:00:00 +00:00
|
|
|
|
unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen), ExportSymbols
|
|
|
|
|
));
|
2013-09-05 11:29:30 +00:00
|
|
|
|
}
|
2013-09-11 14:37:43 +00:00
|
|
|
|
|
2016-12-30 11:22:11 +00:00
|
|
|
|
extern "C" void
|
2018-10-12 13:34:14 +00:00
|
|
|
|
LLVMRustDICompositeTypeReplaceArrays(LLVMRustDIBuilderRef Builder,
|
|
|
|
|
LLVMMetadataRef CompositeTy,
|
|
|
|
|
LLVMMetadataRef Elements,
|
|
|
|
|
LLVMMetadataRef Params) {
|
2016-12-31 17:01:23 +00:00
|
|
|
|
DICompositeType *Tmp = unwrapDI<DICompositeType>(CompositeTy);
|
2018-10-12 13:34:14 +00:00
|
|
|
|
Builder->replaceArrays(Tmp, DINodeArray(unwrap<MDTuple>(Elements)),
|
|
|
|
|
DINodeArray(unwrap<MDTuple>(Params)));
|
2013-09-11 14:37:43 +00:00
|
|
|
|
}
|
2013-10-11 23:56:11 +00:00
|
|
|
|
|
2020-02-10 20:52:20 +00:00
|
|
|
|
extern "C" LLVMMetadataRef
|
2021-01-13 19:55:49 +00:00
|
|
|
|
LLVMRustDIBuilderCreateDebugLocation(unsigned Line, unsigned Column,
|
2020-11-03 21:47:16 +00:00
|
|
|
|
LLVMMetadataRef ScopeRef,
|
2017-07-21 11:15:36 +00:00
|
|
|
|
LLVMMetadataRef InlinedAt) {
|
2020-11-03 21:47:16 +00:00
|
|
|
|
MDNode *Scope = unwrapDIPtr<MDNode>(ScopeRef);
|
|
|
|
|
DILocation *Loc = DILocation::get(
|
|
|
|
|
Scope->getContext(), Line, Column, Scope,
|
|
|
|
|
unwrapDIPtr<MDNode>(InlinedAt));
|
|
|
|
|
return wrap(Loc);
|
2015-01-30 18:25:07 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-01-03 10:25:33 +00:00
|
|
|
|
extern "C" uint64_t LLVMRustDIBuilderCreateOpDeref() {
|
2016-12-30 11:22:11 +00:00
|
|
|
|
return dwarf::DW_OP_deref;
|
2016-08-01 23:35:09 +00:00
|
|
|
|
}
|
|
|
|
|
|
2022-01-03 10:25:33 +00:00
|
|
|
|
extern "C" uint64_t LLVMRustDIBuilderCreateOpPlusUconst() {
|
2018-01-20 05:43:53 +00:00
|
|
|
|
return dwarf::DW_OP_plus_uconst;
|
|
|
|
|
}
|
2016-08-01 23:35:09 +00:00
|
|
|
|
|
2016-12-31 17:01:23 +00:00
|
|
|
|
extern "C" void LLVMRustWriteTypeToString(LLVMTypeRef Ty, RustStringRef Str) {
|
|
|
|
|
RawRustStringOstream OS(Str);
|
|
|
|
|
unwrap<llvm::Type>(Ty)->print(OS);
|
2013-10-11 23:56:11 +00:00
|
|
|
|
}
|
Implement LTO
This commit implements LTO for rust leveraging LLVM's passes. What this means
is:
* When compiling an rlib, in addition to insdering foo.o into the archive, also
insert foo.bc (the LLVM bytecode) of the optimized module.
* When the compiler detects the -Z lto option, it will attempt to perform LTO on
a staticlib or binary output. The compiler will emit an error if a dylib or
rlib output is being generated.
* The actual act of performing LTO is as follows:
1. Force all upstream libraries to have an rlib version available.
2. Load the bytecode of each upstream library from the rlib.
3. Link all this bytecode into the current LLVM module (just using llvm
apis)
4. Run an internalization pass which internalizes all symbols except those
found reachable for the local crate of compilation.
5. Run the LLVM LTO pass manager over this entire module
6a. If assembling an archive, then add all upstream rlibs into the output
archive. This ignores all of the object/bitcode/metadata files rust
generated and placed inside the rlibs.
6b. If linking a binary, create copies of all upstream rlibs, remove the
rust-generated object-file, and then link everything as usual.
As I have explained in #10741, this process is excruciatingly slow, so this is
*not* turned on by default, and it is also why I have decided to hide it behind
a -Z flag for now. The good news is that the binary sizes are about as small as
they can be as a result of LTO, so it's definitely working.
Closes #10741
Closes #10740
2013-12-03 07:19:29 +00:00
|
|
|
|
|
2016-12-31 17:01:23 +00:00
|
|
|
|
extern "C" void LLVMRustWriteValueToString(LLVMValueRef V,
|
|
|
|
|
RustStringRef Str) {
|
|
|
|
|
RawRustStringOstream OS(Str);
|
2017-05-18 15:43:52 +00:00
|
|
|
|
if (!V) {
|
|
|
|
|
OS << "(null)";
|
|
|
|
|
} else {
|
|
|
|
|
OS << "(";
|
|
|
|
|
unwrap<llvm::Value>(V)->getType()->print(OS);
|
|
|
|
|
OS << ":";
|
|
|
|
|
unwrap<llvm::Value>(V)->print(OS);
|
|
|
|
|
OS << ")";
|
|
|
|
|
}
|
2014-01-15 19:39:08 +00:00
|
|
|
|
}
|
|
|
|
|
|
2014-05-10 08:30:55 +00:00
|
|
|
|
// LLVMArrayType function does not support 64-bit ElementCount
|
2016-12-31 17:01:23 +00:00
|
|
|
|
extern "C" LLVMTypeRef LLVMRustArrayType(LLVMTypeRef ElementTy,
|
2016-12-30 11:22:11 +00:00
|
|
|
|
uint64_t ElementCount) {
|
2016-12-31 17:01:23 +00:00
|
|
|
|
return wrap(ArrayType::get(unwrap(ElementTy), ElementCount));
|
2014-05-10 08:30:55 +00:00
|
|
|
|
}
|
2014-09-12 15:17:58 +00:00
|
|
|
|
|
|
|
|
|
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Twine, LLVMTwineRef)
|
|
|
|
|
|
2016-12-31 17:01:23 +00:00
|
|
|
|
extern "C" void LLVMRustWriteTwineToString(LLVMTwineRef T, RustStringRef Str) {
|
|
|
|
|
RawRustStringOstream OS(Str);
|
|
|
|
|
unwrap(T)->print(OS);
|
2014-09-12 15:17:58 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-12-30 11:22:11 +00:00
|
|
|
|
extern "C" void LLVMRustUnpackOptimizationDiagnostic(
|
2016-12-31 17:01:23 +00:00
|
|
|
|
LLVMDiagnosticInfoRef DI, RustStringRef PassNameOut,
|
2017-07-21 12:29:23 +00:00
|
|
|
|
LLVMValueRef *FunctionOut, unsigned* Line, unsigned* Column,
|
|
|
|
|
RustStringRef FilenameOut, RustStringRef MessageOut) {
|
2016-12-30 11:22:11 +00:00
|
|
|
|
// Undefined to call this not on an optimization diagnostic!
|
2016-12-31 17:01:23 +00:00
|
|
|
|
llvm::DiagnosticInfoOptimizationBase *Opt =
|
|
|
|
|
static_cast<llvm::DiagnosticInfoOptimizationBase *>(unwrap(DI));
|
2016-12-30 11:22:11 +00:00
|
|
|
|
|
2016-12-31 17:01:23 +00:00
|
|
|
|
RawRustStringOstream PassNameOS(PassNameOut);
|
|
|
|
|
PassNameOS << Opt->getPassName();
|
|
|
|
|
*FunctionOut = wrap(&Opt->getFunction());
|
2017-07-21 12:29:23 +00:00
|
|
|
|
|
|
|
|
|
RawRustStringOstream FilenameOS(FilenameOut);
|
|
|
|
|
DiagnosticLocation loc = Opt->getLocation();
|
|
|
|
|
if (loc.isValid()) {
|
|
|
|
|
*Line = loc.getLine();
|
|
|
|
|
*Column = loc.getColumn();
|
2019-01-16 17:59:03 +00:00
|
|
|
|
FilenameOS << loc.getAbsolutePath();
|
2017-07-21 12:29:23 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-12-31 17:01:23 +00:00
|
|
|
|
RawRustStringOstream MessageOS(MessageOut);
|
|
|
|
|
MessageOS << Opt->getMsg();
|
2014-09-12 15:17:58 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-06-09 13:37:59 +00:00
|
|
|
|
enum class LLVMRustDiagnosticLevel {
|
|
|
|
|
Error,
|
|
|
|
|
Warning,
|
|
|
|
|
Note,
|
|
|
|
|
Remark,
|
|
|
|
|
};
|
|
|
|
|
|
2016-12-31 17:01:23 +00:00
|
|
|
|
extern "C" void
|
2020-06-09 13:37:59 +00:00
|
|
|
|
LLVMRustUnpackInlineAsmDiagnostic(LLVMDiagnosticInfoRef DI,
|
|
|
|
|
LLVMRustDiagnosticLevel *LevelOut,
|
|
|
|
|
unsigned *CookieOut,
|
2021-07-28 19:31:47 +00:00
|
|
|
|
LLVMTwineRef *MessageOut) {
|
2016-12-30 11:22:11 +00:00
|
|
|
|
// Undefined to call this not on an inline assembly diagnostic!
|
2016-12-31 17:01:23 +00:00
|
|
|
|
llvm::DiagnosticInfoInlineAsm *IA =
|
|
|
|
|
static_cast<llvm::DiagnosticInfoInlineAsm *>(unwrap(DI));
|
2015-01-22 18:43:39 +00:00
|
|
|
|
|
2016-12-31 17:01:23 +00:00
|
|
|
|
*CookieOut = IA->getLocCookie();
|
|
|
|
|
*MessageOut = wrap(&IA->getMsgStr());
|
2020-06-09 13:37:59 +00:00
|
|
|
|
|
|
|
|
|
switch (IA->getSeverity()) {
|
|
|
|
|
case DS_Error:
|
|
|
|
|
*LevelOut = LLVMRustDiagnosticLevel::Error;
|
|
|
|
|
break;
|
|
|
|
|
case DS_Warning:
|
|
|
|
|
*LevelOut = LLVMRustDiagnosticLevel::Warning;
|
|
|
|
|
break;
|
|
|
|
|
case DS_Note:
|
|
|
|
|
*LevelOut = LLVMRustDiagnosticLevel::Note;
|
|
|
|
|
break;
|
|
|
|
|
case DS_Remark:
|
|
|
|
|
*LevelOut = LLVMRustDiagnosticLevel::Remark;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
report_fatal_error("Invalid LLVMRustDiagnosticLevel value!");
|
|
|
|
|
}
|
2015-01-22 18:43:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-12-31 17:01:23 +00:00
|
|
|
|
extern "C" void LLVMRustWriteDiagnosticInfoToString(LLVMDiagnosticInfoRef DI,
|
|
|
|
|
RustStringRef Str) {
|
|
|
|
|
RawRustStringOstream OS(Str);
|
|
|
|
|
DiagnosticPrinterRawOStream DP(OS);
|
|
|
|
|
unwrap(DI)->print(DP);
|
2014-09-12 15:17:58 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-08-01 23:35:09 +00:00
|
|
|
|
enum class LLVMRustDiagnosticKind {
|
2016-12-30 11:22:11 +00:00
|
|
|
|
Other,
|
|
|
|
|
InlineAsm,
|
|
|
|
|
StackSize,
|
|
|
|
|
DebugMetadataVersion,
|
|
|
|
|
SampleProfile,
|
|
|
|
|
OptimizationRemark,
|
|
|
|
|
OptimizationRemarkMissed,
|
|
|
|
|
OptimizationRemarkAnalysis,
|
|
|
|
|
OptimizationRemarkAnalysisFPCommute,
|
|
|
|
|
OptimizationRemarkAnalysisAliasing,
|
|
|
|
|
OptimizationRemarkOther,
|
|
|
|
|
OptimizationFailure,
|
2018-03-12 17:11:59 +00:00
|
|
|
|
PGOProfile,
|
2018-07-17 23:20:51 +00:00
|
|
|
|
Linker,
|
2020-09-29 11:20:56 +00:00
|
|
|
|
Unsupported,
|
2021-07-28 19:31:47 +00:00
|
|
|
|
SrcMgr,
|
2016-08-01 23:35:09 +00:00
|
|
|
|
};
|
|
|
|
|
|
2016-12-31 17:01:23 +00:00
|
|
|
|
static LLVMRustDiagnosticKind toRust(DiagnosticKind Kind) {
|
|
|
|
|
switch (Kind) {
|
2016-12-30 11:22:11 +00:00
|
|
|
|
case DK_InlineAsm:
|
|
|
|
|
return LLVMRustDiagnosticKind::InlineAsm;
|
|
|
|
|
case DK_StackSize:
|
|
|
|
|
return LLVMRustDiagnosticKind::StackSize;
|
|
|
|
|
case DK_DebugMetadataVersion:
|
|
|
|
|
return LLVMRustDiagnosticKind::DebugMetadataVersion;
|
|
|
|
|
case DK_SampleProfile:
|
|
|
|
|
return LLVMRustDiagnosticKind::SampleProfile;
|
|
|
|
|
case DK_OptimizationRemark:
|
2021-11-12 00:00:00 +00:00
|
|
|
|
case DK_MachineOptimizationRemark:
|
2016-12-30 11:22:11 +00:00
|
|
|
|
return LLVMRustDiagnosticKind::OptimizationRemark;
|
|
|
|
|
case DK_OptimizationRemarkMissed:
|
2021-11-12 00:00:00 +00:00
|
|
|
|
case DK_MachineOptimizationRemarkMissed:
|
2016-12-30 11:22:11 +00:00
|
|
|
|
return LLVMRustDiagnosticKind::OptimizationRemarkMissed;
|
|
|
|
|
case DK_OptimizationRemarkAnalysis:
|
2021-11-12 00:00:00 +00:00
|
|
|
|
case DK_MachineOptimizationRemarkAnalysis:
|
2016-12-30 11:22:11 +00:00
|
|
|
|
return LLVMRustDiagnosticKind::OptimizationRemarkAnalysis;
|
|
|
|
|
case DK_OptimizationRemarkAnalysisFPCommute:
|
|
|
|
|
return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisFPCommute;
|
|
|
|
|
case DK_OptimizationRemarkAnalysisAliasing:
|
|
|
|
|
return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisAliasing;
|
2018-03-12 17:11:59 +00:00
|
|
|
|
case DK_PGOProfile:
|
|
|
|
|
return LLVMRustDiagnosticKind::PGOProfile;
|
2018-07-17 23:20:51 +00:00
|
|
|
|
case DK_Linker:
|
|
|
|
|
return LLVMRustDiagnosticKind::Linker;
|
2020-09-29 11:20:56 +00:00
|
|
|
|
case DK_Unsupported:
|
|
|
|
|
return LLVMRustDiagnosticKind::Unsupported;
|
2021-07-28 19:31:47 +00:00
|
|
|
|
#if LLVM_VERSION_GE(13, 0)
|
|
|
|
|
case DK_SrcMgr:
|
|
|
|
|
return LLVMRustDiagnosticKind::SrcMgr;
|
|
|
|
|
#endif
|
2016-12-30 11:22:11 +00:00
|
|
|
|
default:
|
2016-12-31 17:01:23 +00:00
|
|
|
|
return (Kind >= DK_FirstRemark && Kind <= DK_LastRemark)
|
2016-12-30 11:22:11 +00:00
|
|
|
|
? LLVMRustDiagnosticKind::OptimizationRemarkOther
|
|
|
|
|
: LLVMRustDiagnosticKind::Other;
|
2016-08-01 23:35:09 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-12-30 11:22:11 +00:00
|
|
|
|
extern "C" LLVMRustDiagnosticKind
|
2016-12-31 17:01:23 +00:00
|
|
|
|
LLVMRustGetDiagInfoKind(LLVMDiagnosticInfoRef DI) {
|
|
|
|
|
return toRust((DiagnosticKind)unwrap(DI)->getKind());
|
2014-09-12 15:17:58 +00:00
|
|
|
|
}
|
2020-06-09 13:37:59 +00:00
|
|
|
|
|
2016-08-02 21:25:19 +00:00
|
|
|
|
// This is kept distinct from LLVMGetTypeKind, because when
|
|
|
|
|
// a new type kind is added, the Rust-side enum must be
|
|
|
|
|
// updated or UB will result.
|
|
|
|
|
extern "C" LLVMTypeKind LLVMRustGetTypeKind(LLVMTypeRef Ty) {
|
|
|
|
|
switch (unwrap(Ty)->getTypeID()) {
|
|
|
|
|
case Type::VoidTyID:
|
|
|
|
|
return LLVMVoidTypeKind;
|
|
|
|
|
case Type::HalfTyID:
|
|
|
|
|
return LLVMHalfTypeKind;
|
|
|
|
|
case Type::FloatTyID:
|
|
|
|
|
return LLVMFloatTypeKind;
|
|
|
|
|
case Type::DoubleTyID:
|
|
|
|
|
return LLVMDoubleTypeKind;
|
|
|
|
|
case Type::X86_FP80TyID:
|
|
|
|
|
return LLVMX86_FP80TypeKind;
|
|
|
|
|
case Type::FP128TyID:
|
|
|
|
|
return LLVMFP128TypeKind;
|
|
|
|
|
case Type::PPC_FP128TyID:
|
|
|
|
|
return LLVMPPC_FP128TypeKind;
|
|
|
|
|
case Type::LabelTyID:
|
|
|
|
|
return LLVMLabelTypeKind;
|
|
|
|
|
case Type::MetadataTyID:
|
|
|
|
|
return LLVMMetadataTypeKind;
|
|
|
|
|
case Type::IntegerTyID:
|
|
|
|
|
return LLVMIntegerTypeKind;
|
|
|
|
|
case Type::FunctionTyID:
|
|
|
|
|
return LLVMFunctionTypeKind;
|
|
|
|
|
case Type::StructTyID:
|
|
|
|
|
return LLVMStructTypeKind;
|
|
|
|
|
case Type::ArrayTyID:
|
|
|
|
|
return LLVMArrayTypeKind;
|
|
|
|
|
case Type::PointerTyID:
|
|
|
|
|
return LLVMPointerTypeKind;
|
2020-06-26 01:52:41 +00:00
|
|
|
|
case Type::FixedVectorTyID:
|
|
|
|
|
return LLVMVectorTypeKind;
|
2016-08-02 21:25:19 +00:00
|
|
|
|
case Type::X86_MMXTyID:
|
|
|
|
|
return LLVMX86_MMXTypeKind;
|
|
|
|
|
case Type::TokenTyID:
|
|
|
|
|
return LLVMTokenTypeKind;
|
2020-06-26 01:52:41 +00:00
|
|
|
|
case Type::ScalableVectorTyID:
|
|
|
|
|
return LLVMScalableVectorTypeKind;
|
|
|
|
|
case Type::BFloatTyID:
|
|
|
|
|
return LLVMBFloatTypeKind;
|
2020-11-03 21:47:16 +00:00
|
|
|
|
case Type::X86_AMXTyID:
|
|
|
|
|
return LLVMX86_AMXTypeKind;
|
2016-08-02 21:25:19 +00:00
|
|
|
|
}
|
2017-11-20 16:47:29 +00:00
|
|
|
|
report_fatal_error("Unhandled TypeID.");
|
2016-08-02 21:25:19 +00:00
|
|
|
|
}
|
2014-09-12 15:17:58 +00:00
|
|
|
|
|
2014-09-27 08:33:36 +00:00
|
|
|
|
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SMDiagnostic, LLVMSMDiagnosticRef)
|
|
|
|
|
|
2021-03-23 22:23:28 +00:00
|
|
|
|
#if LLVM_VERSION_LT(13, 0)
|
|
|
|
|
using LLVMInlineAsmDiagHandlerTy = LLVMContext::InlineAsmDiagHandlerTy;
|
|
|
|
|
#else
|
|
|
|
|
using LLVMInlineAsmDiagHandlerTy = void*;
|
|
|
|
|
#endif
|
|
|
|
|
|
2016-08-01 23:35:09 +00:00
|
|
|
|
extern "C" void LLVMRustSetInlineAsmDiagnosticHandler(
|
2021-03-23 22:23:28 +00:00
|
|
|
|
LLVMContextRef C, LLVMInlineAsmDiagHandlerTy H, void *CX) {
|
|
|
|
|
// Diagnostic handlers were unified in LLVM change 5de2d189e6ad, so starting
|
|
|
|
|
// with LLVM 13 this function is gone.
|
|
|
|
|
#if LLVM_VERSION_LT(13, 0)
|
2016-12-30 11:22:11 +00:00
|
|
|
|
unwrap(C)->setInlineAsmDiagnosticHandler(H, CX);
|
2021-03-23 22:23:28 +00:00
|
|
|
|
#endif
|
2014-09-27 08:33:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-07-28 19:31:47 +00:00
|
|
|
|
extern "C" LLVMSMDiagnosticRef LLVMRustGetSMDiagnostic(
|
|
|
|
|
LLVMDiagnosticInfoRef DI, unsigned *Cookie) {
|
|
|
|
|
#if LLVM_VERSION_GE(13, 0)
|
|
|
|
|
llvm::DiagnosticInfoSrcMgr *SM = static_cast<llvm::DiagnosticInfoSrcMgr *>(unwrap(DI));
|
|
|
|
|
*Cookie = SM->getLocCookie();
|
|
|
|
|
return wrap(&SM->getSMDiag());
|
|
|
|
|
#else
|
|
|
|
|
report_fatal_error("Shouldn't get called on older versions");
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-26 19:07:59 +00:00
|
|
|
|
extern "C" bool LLVMRustUnpackSMDiagnostic(LLVMSMDiagnosticRef DRef,
|
|
|
|
|
RustStringRef MessageOut,
|
|
|
|
|
RustStringRef BufferOut,
|
2020-06-09 13:37:59 +00:00
|
|
|
|
LLVMRustDiagnosticLevel* LevelOut,
|
2020-05-26 19:07:59 +00:00
|
|
|
|
unsigned* LocOut,
|
|
|
|
|
unsigned* RangesOut,
|
|
|
|
|
size_t* NumRanges) {
|
|
|
|
|
SMDiagnostic& D = *unwrap(DRef);
|
|
|
|
|
RawRustStringOstream MessageOS(MessageOut);
|
|
|
|
|
MessageOS << D.getMessage();
|
|
|
|
|
|
2020-06-09 13:37:59 +00:00
|
|
|
|
switch (D.getKind()) {
|
|
|
|
|
case SourceMgr::DK_Error:
|
|
|
|
|
*LevelOut = LLVMRustDiagnosticLevel::Error;
|
|
|
|
|
break;
|
|
|
|
|
case SourceMgr::DK_Warning:
|
|
|
|
|
*LevelOut = LLVMRustDiagnosticLevel::Warning;
|
|
|
|
|
break;
|
|
|
|
|
case SourceMgr::DK_Note:
|
|
|
|
|
*LevelOut = LLVMRustDiagnosticLevel::Note;
|
|
|
|
|
break;
|
|
|
|
|
case SourceMgr::DK_Remark:
|
|
|
|
|
*LevelOut = LLVMRustDiagnosticLevel::Remark;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
report_fatal_error("Invalid LLVMRustDiagnosticLevel value!");
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-26 19:07:59 +00:00
|
|
|
|
if (D.getLoc() == SMLoc())
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
const SourceMgr &LSM = *D.getSourceMgr();
|
|
|
|
|
const MemoryBuffer *LBuf = LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(D.getLoc()));
|
|
|
|
|
LLVMRustStringWriteImpl(BufferOut, LBuf->getBufferStart(), LBuf->getBufferSize());
|
|
|
|
|
|
|
|
|
|
*LocOut = D.getLoc().getPointer() - LBuf->getBufferStart();
|
|
|
|
|
|
|
|
|
|
*NumRanges = std::min(*NumRanges, D.getRanges().size());
|
|
|
|
|
size_t LineStart = *LocOut - (size_t)D.getColumnNo();
|
|
|
|
|
for (size_t i = 0; i < *NumRanges; i++) {
|
|
|
|
|
RangesOut[i * 2] = LineStart + D.getRanges()[i].first;
|
|
|
|
|
RangesOut[i * 2 + 1] = LineStart + D.getRanges()[i].second;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
2014-09-27 08:33:36 +00:00
|
|
|
|
}
|
2015-06-30 15:56:56 +00:00
|
|
|
|
|
2016-12-31 17:01:23 +00:00
|
|
|
|
extern "C" LLVMValueRef LLVMRustBuildCleanupPad(LLVMBuilderRef B,
|
2016-12-30 11:22:11 +00:00
|
|
|
|
LLVMValueRef ParentPad,
|
2016-12-31 17:01:23 +00:00
|
|
|
|
unsigned ArgCount,
|
2016-12-30 11:22:11 +00:00
|
|
|
|
LLVMValueRef *LLArgs,
|
|
|
|
|
const char *Name) {
|
|
|
|
|
Value **Args = unwrap(LLArgs);
|
2016-12-30 12:21:21 +00:00
|
|
|
|
if (ParentPad == nullptr) {
|
2016-12-31 17:01:23 +00:00
|
|
|
|
Type *Ty = Type::getTokenTy(unwrap(B)->getContext());
|
2016-12-30 11:22:11 +00:00
|
|
|
|
ParentPad = wrap(Constant::getNullValue(Ty));
|
|
|
|
|
}
|
2016-12-31 17:01:23 +00:00
|
|
|
|
return wrap(unwrap(B)->CreateCleanupPad(
|
|
|
|
|
unwrap(ParentPad), ArrayRef<Value *>(Args, ArgCount), Name));
|
2015-10-24 01:18:44 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-12-31 17:01:23 +00:00
|
|
|
|
extern "C" LLVMValueRef LLVMRustBuildCleanupRet(LLVMBuilderRef B,
|
2016-12-30 11:22:11 +00:00
|
|
|
|
LLVMValueRef CleanupPad,
|
|
|
|
|
LLVMBasicBlockRef UnwindBB) {
|
|
|
|
|
CleanupPadInst *Inst = cast<CleanupPadInst>(unwrap(CleanupPad));
|
2016-12-31 17:01:23 +00:00
|
|
|
|
return wrap(unwrap(B)->CreateCleanupRet(Inst, unwrap(UnwindBB)));
|
2015-10-24 01:18:44 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
extern "C" LLVMValueRef
|
2016-12-31 17:01:23 +00:00
|
|
|
|
LLVMRustBuildCatchPad(LLVMBuilderRef B, LLVMValueRef ParentPad,
|
|
|
|
|
unsigned ArgCount, LLVMValueRef *LLArgs, const char *Name) {
|
2016-12-30 11:22:11 +00:00
|
|
|
|
Value **Args = unwrap(LLArgs);
|
2016-12-31 17:01:23 +00:00
|
|
|
|
return wrap(unwrap(B)->CreateCatchPad(
|
|
|
|
|
unwrap(ParentPad), ArrayRef<Value *>(Args, ArgCount), Name));
|
2015-10-24 01:18:44 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-12-31 17:01:23 +00:00
|
|
|
|
extern "C" LLVMValueRef LLVMRustBuildCatchRet(LLVMBuilderRef B,
|
2016-12-30 11:22:11 +00:00
|
|
|
|
LLVMValueRef Pad,
|
|
|
|
|
LLVMBasicBlockRef BB) {
|
2016-12-31 17:01:23 +00:00
|
|
|
|
return wrap(unwrap(B)->CreateCatchRet(cast<CatchPadInst>(unwrap(Pad)),
|
2016-12-30 11:22:11 +00:00
|
|
|
|
unwrap(BB)));
|
2015-10-24 01:18:44 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-12-31 17:01:23 +00:00
|
|
|
|
extern "C" LLVMValueRef LLVMRustBuildCatchSwitch(LLVMBuilderRef B,
|
2016-12-30 11:22:11 +00:00
|
|
|
|
LLVMValueRef ParentPad,
|
|
|
|
|
LLVMBasicBlockRef BB,
|
|
|
|
|
unsigned NumHandlers,
|
|
|
|
|
const char *Name) {
|
2016-12-30 12:21:21 +00:00
|
|
|
|
if (ParentPad == nullptr) {
|
2016-12-31 17:01:23 +00:00
|
|
|
|
Type *Ty = Type::getTokenTy(unwrap(B)->getContext());
|
2016-12-30 11:22:11 +00:00
|
|
|
|
ParentPad = wrap(Constant::getNullValue(Ty));
|
|
|
|
|
}
|
2016-12-31 17:01:23 +00:00
|
|
|
|
return wrap(unwrap(B)->CreateCatchSwitch(unwrap(ParentPad), unwrap(BB),
|
2016-12-30 11:22:11 +00:00
|
|
|
|
NumHandlers, Name));
|
2015-10-24 01:18:44 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-12-30 11:22:11 +00:00
|
|
|
|
extern "C" void LLVMRustAddHandler(LLVMValueRef CatchSwitchRef,
|
|
|
|
|
LLVMBasicBlockRef Handler) {
|
|
|
|
|
Value *CatchSwitch = unwrap(CatchSwitchRef);
|
|
|
|
|
cast<CatchSwitchInst>(CatchSwitch)->addHandler(unwrap(Handler));
|
2015-10-24 01:18:44 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-12-30 11:22:11 +00:00
|
|
|
|
extern "C" OperandBundleDef *LLVMRustBuildOperandBundleDef(const char *Name,
|
|
|
|
|
LLVMValueRef *Inputs,
|
|
|
|
|
unsigned NumInputs) {
|
2015-10-24 01:18:44 +00:00
|
|
|
|
return new OperandBundleDef(Name, makeArrayRef(unwrap(Inputs), NumInputs));
|
|
|
|
|
}
|
|
|
|
|
|
2016-12-30 11:22:11 +00:00
|
|
|
|
extern "C" void LLVMRustFreeOperandBundleDef(OperandBundleDef *Bundle) {
|
2015-10-24 01:18:44 +00:00
|
|
|
|
delete Bundle;
|
|
|
|
|
}
|
|
|
|
|
|
2021-08-03 22:09:57 +00:00
|
|
|
|
extern "C" LLVMValueRef LLVMRustBuildCall(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
|
2016-12-30 11:22:11 +00:00
|
|
|
|
LLVMValueRef *Args, unsigned NumArgs,
|
2020-03-10 00:00:00 +00:00
|
|
|
|
OperandBundleDef *Bundle) {
|
2020-06-26 01:52:41 +00:00
|
|
|
|
Value *Callee = unwrap(Fn);
|
2021-08-03 22:09:57 +00:00
|
|
|
|
FunctionType *FTy = unwrap<FunctionType>(Ty);
|
2016-12-31 17:01:23 +00:00
|
|
|
|
unsigned Len = Bundle ? 1 : 0;
|
|
|
|
|
ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, Len);
|
2016-12-30 11:22:11 +00:00
|
|
|
|
return wrap(unwrap(B)->CreateCall(
|
2020-06-26 01:52:41 +00:00
|
|
|
|
FTy, Callee, makeArrayRef(unwrap(Args), NumArgs), Bundles));
|
2015-10-24 01:18:44 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-07-02 18:27:15 +00:00
|
|
|
|
extern "C" LLVMValueRef LLVMRustGetInstrProfIncrementIntrinsic(LLVMModuleRef M) {
|
2020-06-04 04:19:34 +00:00
|
|
|
|
return wrap(llvm::Intrinsic::getDeclaration(unwrap(M),
|
|
|
|
|
(llvm::Intrinsic::ID)llvm::Intrinsic::instrprof_increment));
|
|
|
|
|
}
|
|
|
|
|
|
2018-11-02 22:38:16 +00:00
|
|
|
|
extern "C" LLVMValueRef LLVMRustBuildMemCpy(LLVMBuilderRef B,
|
|
|
|
|
LLVMValueRef Dst, unsigned DstAlign,
|
|
|
|
|
LLVMValueRef Src, unsigned SrcAlign,
|
|
|
|
|
LLVMValueRef Size, bool IsVolatile) {
|
2019-12-31 13:32:01 +00:00
|
|
|
|
return wrap(unwrap(B)->CreateMemCpy(
|
|
|
|
|
unwrap(Dst), MaybeAlign(DstAlign),
|
|
|
|
|
unwrap(Src), MaybeAlign(SrcAlign),
|
|
|
|
|
unwrap(Size), IsVolatile));
|
2018-11-02 22:38:16 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
extern "C" LLVMValueRef LLVMRustBuildMemMove(LLVMBuilderRef B,
|
|
|
|
|
LLVMValueRef Dst, unsigned DstAlign,
|
|
|
|
|
LLVMValueRef Src, unsigned SrcAlign,
|
|
|
|
|
LLVMValueRef Size, bool IsVolatile) {
|
2019-12-31 13:32:01 +00:00
|
|
|
|
return wrap(unwrap(B)->CreateMemMove(
|
|
|
|
|
unwrap(Dst), MaybeAlign(DstAlign),
|
|
|
|
|
unwrap(Src), MaybeAlign(SrcAlign),
|
|
|
|
|
unwrap(Size), IsVolatile));
|
2018-11-02 22:38:16 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-01-05 21:32:15 +00:00
|
|
|
|
extern "C" LLVMValueRef LLVMRustBuildMemSet(LLVMBuilderRef B,
|
|
|
|
|
LLVMValueRef Dst, unsigned DstAlign,
|
|
|
|
|
LLVMValueRef Val,
|
|
|
|
|
LLVMValueRef Size, bool IsVolatile) {
|
2020-03-02 21:37:55 +00:00
|
|
|
|
return wrap(unwrap(B)->CreateMemSet(
|
|
|
|
|
unwrap(Dst), unwrap(Val), unwrap(Size), MaybeAlign(DstAlign), IsVolatile));
|
2020-01-05 21:32:15 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-10-24 01:18:44 +00:00
|
|
|
|
extern "C" LLVMValueRef
|
2021-08-03 22:09:57 +00:00
|
|
|
|
LLVMRustBuildInvoke(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
|
|
|
|
|
LLVMValueRef *Args, unsigned NumArgs,
|
|
|
|
|
LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch,
|
|
|
|
|
OperandBundleDef *Bundle, const char *Name) {
|
2020-06-26 01:52:41 +00:00
|
|
|
|
Value *Callee = unwrap(Fn);
|
2021-08-03 22:09:57 +00:00
|
|
|
|
FunctionType *FTy = unwrap<FunctionType>(Ty);
|
2016-12-31 17:01:23 +00:00
|
|
|
|
unsigned Len = Bundle ? 1 : 0;
|
|
|
|
|
ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, Len);
|
2020-06-26 01:52:41 +00:00
|
|
|
|
return wrap(unwrap(B)->CreateInvoke(FTy, Callee, unwrap(Then), unwrap(Catch),
|
2016-12-30 11:22:11 +00:00
|
|
|
|
makeArrayRef(unwrap(Args), NumArgs),
|
|
|
|
|
Bundles, Name));
|
2015-10-24 01:18:44 +00:00
|
|
|
|
}
|
2016-02-04 17:40:28 +00:00
|
|
|
|
|
2016-12-30 11:22:11 +00:00
|
|
|
|
extern "C" void LLVMRustPositionBuilderAtStart(LLVMBuilderRef B,
|
|
|
|
|
LLVMBasicBlockRef BB) {
|
2016-12-31 17:01:23 +00:00
|
|
|
|
auto Point = unwrap(BB)->getFirstInsertionPt();
|
|
|
|
|
unwrap(B)->SetInsertPoint(unwrap(BB), Point);
|
2016-02-04 17:40:28 +00:00
|
|
|
|
}
|
2016-03-28 15:57:31 +00:00
|
|
|
|
|
2016-12-30 11:22:11 +00:00
|
|
|
|
extern "C" void LLVMRustSetComdat(LLVMModuleRef M, LLVMValueRef V,
|
2019-12-04 20:00:28 +00:00
|
|
|
|
const char *Name, size_t NameLen) {
|
2016-12-30 11:22:11 +00:00
|
|
|
|
Triple TargetTriple(unwrap(M)->getTargetTriple());
|
|
|
|
|
GlobalObject *GV = unwrap<GlobalObject>(V);
|
2020-11-23 20:56:07 +00:00
|
|
|
|
if (TargetTriple.supportsCOMDAT()) {
|
2019-12-04 20:00:28 +00:00
|
|
|
|
StringRef NameRef(Name, NameLen);
|
|
|
|
|
GV->setComdat(unwrap(M)->getOrInsertComdat(NameRef));
|
2016-12-30 11:22:11 +00:00
|
|
|
|
}
|
2016-03-28 15:57:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
extern "C" void LLVMRustUnsetComdat(LLVMValueRef V) {
|
2016-12-30 11:22:11 +00:00
|
|
|
|
GlobalObject *GV = unwrap<GlobalObject>(V);
|
|
|
|
|
GV->setComdat(nullptr);
|
2016-03-28 15:57:31 +00:00
|
|
|
|
}
|
2016-09-01 18:52:33 +00:00
|
|
|
|
|
|
|
|
|
enum class LLVMRustLinkage {
|
2016-12-30 11:22:11 +00:00
|
|
|
|
ExternalLinkage = 0,
|
|
|
|
|
AvailableExternallyLinkage = 1,
|
|
|
|
|
LinkOnceAnyLinkage = 2,
|
|
|
|
|
LinkOnceODRLinkage = 3,
|
|
|
|
|
WeakAnyLinkage = 4,
|
|
|
|
|
WeakODRLinkage = 5,
|
|
|
|
|
AppendingLinkage = 6,
|
|
|
|
|
InternalLinkage = 7,
|
|
|
|
|
PrivateLinkage = 8,
|
|
|
|
|
ExternalWeakLinkage = 9,
|
|
|
|
|
CommonLinkage = 10,
|
2016-09-01 18:52:33 +00:00
|
|
|
|
};
|
|
|
|
|
|
2016-12-31 17:01:23 +00:00
|
|
|
|
static LLVMRustLinkage toRust(LLVMLinkage Linkage) {
|
|
|
|
|
switch (Linkage) {
|
2016-12-30 11:22:11 +00:00
|
|
|
|
case LLVMExternalLinkage:
|
|
|
|
|
return LLVMRustLinkage::ExternalLinkage;
|
|
|
|
|
case LLVMAvailableExternallyLinkage:
|
|
|
|
|
return LLVMRustLinkage::AvailableExternallyLinkage;
|
|
|
|
|
case LLVMLinkOnceAnyLinkage:
|
|
|
|
|
return LLVMRustLinkage::LinkOnceAnyLinkage;
|
|
|
|
|
case LLVMLinkOnceODRLinkage:
|
|
|
|
|
return LLVMRustLinkage::LinkOnceODRLinkage;
|
|
|
|
|
case LLVMWeakAnyLinkage:
|
|
|
|
|
return LLVMRustLinkage::WeakAnyLinkage;
|
|
|
|
|
case LLVMWeakODRLinkage:
|
|
|
|
|
return LLVMRustLinkage::WeakODRLinkage;
|
|
|
|
|
case LLVMAppendingLinkage:
|
|
|
|
|
return LLVMRustLinkage::AppendingLinkage;
|
|
|
|
|
case LLVMInternalLinkage:
|
|
|
|
|
return LLVMRustLinkage::InternalLinkage;
|
|
|
|
|
case LLVMPrivateLinkage:
|
|
|
|
|
return LLVMRustLinkage::PrivateLinkage;
|
|
|
|
|
case LLVMExternalWeakLinkage:
|
|
|
|
|
return LLVMRustLinkage::ExternalWeakLinkage;
|
|
|
|
|
case LLVMCommonLinkage:
|
|
|
|
|
return LLVMRustLinkage::CommonLinkage;
|
|
|
|
|
default:
|
2017-11-20 16:47:29 +00:00
|
|
|
|
report_fatal_error("Invalid LLVMRustLinkage value!");
|
2016-12-30 11:22:11 +00:00
|
|
|
|
}
|
2016-09-01 18:52:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-12-31 17:01:23 +00:00
|
|
|
|
static LLVMLinkage fromRust(LLVMRustLinkage Linkage) {
|
|
|
|
|
switch (Linkage) {
|
2016-12-30 11:22:11 +00:00
|
|
|
|
case LLVMRustLinkage::ExternalLinkage:
|
|
|
|
|
return LLVMExternalLinkage;
|
|
|
|
|
case LLVMRustLinkage::AvailableExternallyLinkage:
|
|
|
|
|
return LLVMAvailableExternallyLinkage;
|
|
|
|
|
case LLVMRustLinkage::LinkOnceAnyLinkage:
|
|
|
|
|
return LLVMLinkOnceAnyLinkage;
|
|
|
|
|
case LLVMRustLinkage::LinkOnceODRLinkage:
|
|
|
|
|
return LLVMLinkOnceODRLinkage;
|
|
|
|
|
case LLVMRustLinkage::WeakAnyLinkage:
|
|
|
|
|
return LLVMWeakAnyLinkage;
|
|
|
|
|
case LLVMRustLinkage::WeakODRLinkage:
|
|
|
|
|
return LLVMWeakODRLinkage;
|
|
|
|
|
case LLVMRustLinkage::AppendingLinkage:
|
|
|
|
|
return LLVMAppendingLinkage;
|
|
|
|
|
case LLVMRustLinkage::InternalLinkage:
|
|
|
|
|
return LLVMInternalLinkage;
|
|
|
|
|
case LLVMRustLinkage::PrivateLinkage:
|
|
|
|
|
return LLVMPrivateLinkage;
|
|
|
|
|
case LLVMRustLinkage::ExternalWeakLinkage:
|
|
|
|
|
return LLVMExternalWeakLinkage;
|
|
|
|
|
case LLVMRustLinkage::CommonLinkage:
|
|
|
|
|
return LLVMCommonLinkage;
|
|
|
|
|
}
|
2017-11-20 16:47:29 +00:00
|
|
|
|
report_fatal_error("Invalid LLVMRustLinkage value!");
|
2016-09-01 18:52:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
extern "C" LLVMRustLinkage LLVMRustGetLinkage(LLVMValueRef V) {
|
2016-12-31 17:01:23 +00:00
|
|
|
|
return toRust(LLVMGetLinkage(V));
|
2016-09-01 18:52:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-12-30 11:22:11 +00:00
|
|
|
|
extern "C" void LLVMRustSetLinkage(LLVMValueRef V,
|
|
|
|
|
LLVMRustLinkage RustLinkage) {
|
2016-12-31 17:01:23 +00:00
|
|
|
|
LLVMSetLinkage(V, fromRust(RustLinkage));
|
2016-09-01 18:52:33 +00:00
|
|
|
|
}
|
2016-11-16 22:36:08 +00:00
|
|
|
|
|
2021-07-31 00:00:00 +00:00
|
|
|
|
extern "C" LLVMValueRef LLVMRustConstInBoundsGEP2(LLVMTypeRef Ty,
|
|
|
|
|
LLVMValueRef ConstantVal,
|
|
|
|
|
LLVMValueRef *ConstantIndices,
|
|
|
|
|
unsigned NumIndices) {
|
|
|
|
|
ArrayRef<Constant *> IdxList(unwrap<Constant>(ConstantIndices, NumIndices),
|
|
|
|
|
NumIndices);
|
|
|
|
|
Constant *Val = unwrap<Constant>(ConstantVal);
|
|
|
|
|
return wrap(ConstantExpr::getInBoundsGetElementPtr(unwrap(Ty), Val, IdxList));
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-25 22:32:46 +00:00
|
|
|
|
// Returns true if both high and low were successfully set. Fails in case constant wasn’t any of
|
|
|
|
|
// the common sizes (1, 8, 16, 32, 64, 128 bits)
|
|
|
|
|
extern "C" bool LLVMRustConstInt128Get(LLVMValueRef CV, bool sext, uint64_t *high, uint64_t *low)
|
|
|
|
|
{
|
|
|
|
|
auto C = unwrap<llvm::ConstantInt>(CV);
|
|
|
|
|
if (C->getBitWidth() > 128) { return false; }
|
|
|
|
|
APInt AP;
|
|
|
|
|
if (sext) {
|
|
|
|
|
AP = C->getValue().sextOrSelf(128);
|
|
|
|
|
} else {
|
|
|
|
|
AP = C->getValue().zextOrSelf(128);
|
|
|
|
|
}
|
|
|
|
|
*low = AP.getLoBits(64).getZExtValue();
|
|
|
|
|
*high = AP.getHiBits(64).getZExtValue();
|
|
|
|
|
return true;
|
2016-09-01 18:52:33 +00:00
|
|
|
|
}
|
2016-11-16 22:36:08 +00:00
|
|
|
|
|
2016-11-28 22:44:51 +00:00
|
|
|
|
enum class LLVMRustVisibility {
|
2016-12-30 11:22:11 +00:00
|
|
|
|
Default = 0,
|
|
|
|
|
Hidden = 1,
|
|
|
|
|
Protected = 2,
|
2016-11-28 22:44:51 +00:00
|
|
|
|
};
|
|
|
|
|
|
2016-12-31 17:01:23 +00:00
|
|
|
|
static LLVMRustVisibility toRust(LLVMVisibility Vis) {
|
|
|
|
|
switch (Vis) {
|
2016-12-30 11:22:11 +00:00
|
|
|
|
case LLVMDefaultVisibility:
|
|
|
|
|
return LLVMRustVisibility::Default;
|
|
|
|
|
case LLVMHiddenVisibility:
|
|
|
|
|
return LLVMRustVisibility::Hidden;
|
|
|
|
|
case LLVMProtectedVisibility:
|
|
|
|
|
return LLVMRustVisibility::Protected;
|
|
|
|
|
}
|
2017-11-20 16:47:29 +00:00
|
|
|
|
report_fatal_error("Invalid LLVMRustVisibility value!");
|
2016-11-28 22:44:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
2016-12-31 17:01:23 +00:00
|
|
|
|
static LLVMVisibility fromRust(LLVMRustVisibility Vis) {
|
|
|
|
|
switch (Vis) {
|
2016-12-30 11:22:11 +00:00
|
|
|
|
case LLVMRustVisibility::Default:
|
|
|
|
|
return LLVMDefaultVisibility;
|
|
|
|
|
case LLVMRustVisibility::Hidden:
|
|
|
|
|
return LLVMHiddenVisibility;
|
|
|
|
|
case LLVMRustVisibility::Protected:
|
|
|
|
|
return LLVMProtectedVisibility;
|
|
|
|
|
}
|
2017-11-20 16:47:29 +00:00
|
|
|
|
report_fatal_error("Invalid LLVMRustVisibility value!");
|
2016-11-28 22:44:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
extern "C" LLVMRustVisibility LLVMRustGetVisibility(LLVMValueRef V) {
|
2016-12-31 17:01:23 +00:00
|
|
|
|
return toRust(LLVMGetVisibility(V));
|
2016-11-28 22:44:51 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-02-10 17:29:39 +00:00
|
|
|
|
// Oh hey, a binding that makes sense for once? (because LLVM’s own do not)
|
|
|
|
|
extern "C" LLVMValueRef LLVMRustBuildIntCast(LLVMBuilderRef B, LLVMValueRef Val,
|
|
|
|
|
LLVMTypeRef DestTy, bool isSigned) {
|
|
|
|
|
return wrap(unwrap(B)->CreateIntCast(unwrap(Val), unwrap(DestTy), isSigned, ""));
|
|
|
|
|
}
|
|
|
|
|
|
2016-12-30 11:22:11 +00:00
|
|
|
|
extern "C" void LLVMRustSetVisibility(LLVMValueRef V,
|
|
|
|
|
LLVMRustVisibility RustVisibility) {
|
2016-12-31 17:01:23 +00:00
|
|
|
|
LLVMSetVisibility(V, fromRust(RustVisibility));
|
2016-11-28 22:44:51 +00:00
|
|
|
|
}
|
2017-07-23 15:14:38 +00:00
|
|
|
|
|
2021-03-27 22:11:24 +00:00
|
|
|
|
extern "C" void LLVMRustSetDSOLocal(LLVMValueRef Global, bool is_dso_local) {
|
|
|
|
|
unwrap<GlobalValue>(Global)->setDSOLocal(is_dso_local);
|
|
|
|
|
}
|
|
|
|
|
|
2017-07-23 15:14:38 +00:00
|
|
|
|
struct LLVMRustModuleBuffer {
|
|
|
|
|
std::string data;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
extern "C" LLVMRustModuleBuffer*
|
|
|
|
|
LLVMRustModuleBufferCreate(LLVMModuleRef M) {
|
2019-12-31 13:08:25 +00:00
|
|
|
|
auto Ret = std::make_unique<LLVMRustModuleBuffer>();
|
2017-07-23 15:14:38 +00:00
|
|
|
|
{
|
|
|
|
|
raw_string_ostream OS(Ret->data);
|
|
|
|
|
{
|
|
|
|
|
legacy::PassManager PM;
|
|
|
|
|
PM.add(createBitcodeWriterPass(OS));
|
|
|
|
|
PM.run(*unwrap(M));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return Ret.release();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
extern "C" void
|
|
|
|
|
LLVMRustModuleBufferFree(LLVMRustModuleBuffer *Buffer) {
|
|
|
|
|
delete Buffer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
extern "C" const void*
|
|
|
|
|
LLVMRustModuleBufferPtr(const LLVMRustModuleBuffer *Buffer) {
|
|
|
|
|
return Buffer->data.data();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
extern "C" size_t
|
|
|
|
|
LLVMRustModuleBufferLen(const LLVMRustModuleBuffer *Buffer) {
|
|
|
|
|
return Buffer->data.length();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
extern "C" uint64_t
|
|
|
|
|
LLVMRustModuleCost(LLVMModuleRef M) {
|
2017-12-08 10:23:23 +00:00
|
|
|
|
auto f = unwrap(M)->functions();
|
|
|
|
|
return std::distance(std::begin(f), std::end(f));
|
2017-07-23 15:14:38 +00:00
|
|
|
|
}
|
2018-03-13 15:46:55 +00:00
|
|
|
|
|
|
|
|
|
// Vector reductions:
|
|
|
|
|
extern "C" LLVMValueRef
|
|
|
|
|
LLVMRustBuildVectorReduceFAdd(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) {
|
|
|
|
|
return wrap(unwrap(B)->CreateFAddReduce(unwrap(Acc),unwrap(Src)));
|
|
|
|
|
}
|
|
|
|
|
extern "C" LLVMValueRef
|
|
|
|
|
LLVMRustBuildVectorReduceFMul(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) {
|
|
|
|
|
return wrap(unwrap(B)->CreateFMulReduce(unwrap(Acc),unwrap(Src)));
|
|
|
|
|
}
|
|
|
|
|
extern "C" LLVMValueRef
|
|
|
|
|
LLVMRustBuildVectorReduceAdd(LLVMBuilderRef B, LLVMValueRef Src) {
|
|
|
|
|
return wrap(unwrap(B)->CreateAddReduce(unwrap(Src)));
|
|
|
|
|
}
|
|
|
|
|
extern "C" LLVMValueRef
|
|
|
|
|
LLVMRustBuildVectorReduceMul(LLVMBuilderRef B, LLVMValueRef Src) {
|
|
|
|
|
return wrap(unwrap(B)->CreateMulReduce(unwrap(Src)));
|
|
|
|
|
}
|
|
|
|
|
extern "C" LLVMValueRef
|
|
|
|
|
LLVMRustBuildVectorReduceAnd(LLVMBuilderRef B, LLVMValueRef Src) {
|
|
|
|
|
return wrap(unwrap(B)->CreateAndReduce(unwrap(Src)));
|
|
|
|
|
}
|
|
|
|
|
extern "C" LLVMValueRef
|
|
|
|
|
LLVMRustBuildVectorReduceOr(LLVMBuilderRef B, LLVMValueRef Src) {
|
|
|
|
|
return wrap(unwrap(B)->CreateOrReduce(unwrap(Src)));
|
|
|
|
|
}
|
|
|
|
|
extern "C" LLVMValueRef
|
|
|
|
|
LLVMRustBuildVectorReduceXor(LLVMBuilderRef B, LLVMValueRef Src) {
|
|
|
|
|
return wrap(unwrap(B)->CreateXorReduce(unwrap(Src)));
|
|
|
|
|
}
|
|
|
|
|
extern "C" LLVMValueRef
|
|
|
|
|
LLVMRustBuildVectorReduceMin(LLVMBuilderRef B, LLVMValueRef Src, bool IsSigned) {
|
|
|
|
|
return wrap(unwrap(B)->CreateIntMinReduce(unwrap(Src), IsSigned));
|
|
|
|
|
}
|
|
|
|
|
extern "C" LLVMValueRef
|
|
|
|
|
LLVMRustBuildVectorReduceMax(LLVMBuilderRef B, LLVMValueRef Src, bool IsSigned) {
|
|
|
|
|
return wrap(unwrap(B)->CreateIntMaxReduce(unwrap(Src), IsSigned));
|
|
|
|
|
}
|
|
|
|
|
extern "C" LLVMValueRef
|
|
|
|
|
LLVMRustBuildVectorReduceFMin(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) {
|
2020-11-03 21:47:16 +00:00
|
|
|
|
Instruction *I = unwrap(B)->CreateFPMinReduce(unwrap(Src));
|
|
|
|
|
I->setHasNoNaNs(NoNaN);
|
|
|
|
|
return wrap(I);
|
2018-03-13 15:46:55 +00:00
|
|
|
|
}
|
|
|
|
|
extern "C" LLVMValueRef
|
|
|
|
|
LLVMRustBuildVectorReduceFMax(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) {
|
2020-11-03 21:47:16 +00:00
|
|
|
|
Instruction *I = unwrap(B)->CreateFPMaxReduce(unwrap(Src));
|
|
|
|
|
I->setHasNoNaNs(NoNaN);
|
|
|
|
|
return wrap(I);
|
2018-03-13 15:46:55 +00:00
|
|
|
|
}
|
2018-03-14 21:12:38 +00:00
|
|
|
|
|
2018-03-21 20:49:22 +00:00
|
|
|
|
extern "C" LLVMValueRef
|
|
|
|
|
LLVMRustBuildMinNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) {
|
|
|
|
|
return wrap(unwrap(B)->CreateMinNum(unwrap(LHS),unwrap(RHS)));
|
|
|
|
|
}
|
|
|
|
|
extern "C" LLVMValueRef
|
|
|
|
|
LLVMRustBuildMaxNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) {
|
|
|
|
|
return wrap(unwrap(B)->CreateMaxNum(unwrap(LHS),unwrap(RHS)));
|
|
|
|
|
}
|
2021-03-08 20:42:54 +00:00
|
|
|
|
|
|
|
|
|
// This struct contains all necessary info about a symbol exported from a DLL.
|
|
|
|
|
struct LLVMRustCOFFShortExport {
|
|
|
|
|
const char* name;
|
2021-09-11 00:34:09 +00:00
|
|
|
|
bool ordinal_present;
|
|
|
|
|
// The value of `ordinal` is only meaningful if `ordinal_present` is true.
|
|
|
|
|
uint16_t ordinal;
|
2021-03-08 20:42:54 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Machine must be a COFF machine type, as defined in PE specs.
|
|
|
|
|
extern "C" LLVMRustResult LLVMRustWriteImportLibrary(
|
|
|
|
|
const char* ImportName,
|
|
|
|
|
const char* Path,
|
|
|
|
|
const LLVMRustCOFFShortExport* Exports,
|
|
|
|
|
size_t NumExports,
|
|
|
|
|
uint16_t Machine,
|
|
|
|
|
bool MinGW)
|
|
|
|
|
{
|
|
|
|
|
std::vector<llvm::object::COFFShortExport> ConvertedExports;
|
|
|
|
|
ConvertedExports.reserve(NumExports);
|
|
|
|
|
|
|
|
|
|
for (size_t i = 0; i < NumExports; ++i) {
|
2021-09-11 00:34:09 +00:00
|
|
|
|
bool ordinal_present = Exports[i].ordinal_present;
|
|
|
|
|
uint16_t ordinal = ordinal_present ? Exports[i].ordinal : 0;
|
2021-03-08 20:42:54 +00:00
|
|
|
|
ConvertedExports.push_back(llvm::object::COFFShortExport{
|
|
|
|
|
Exports[i].name, // Name
|
|
|
|
|
std::string{}, // ExtName
|
|
|
|
|
std::string{}, // SymbolName
|
|
|
|
|
std::string{}, // AliasTarget
|
2021-09-11 00:34:09 +00:00
|
|
|
|
ordinal, // Ordinal
|
|
|
|
|
ordinal_present, // Noname
|
2021-03-08 20:42:54 +00:00
|
|
|
|
false, // Data
|
|
|
|
|
false, // Private
|
|
|
|
|
false // Constant
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto Error = llvm::object::writeImportLibrary(
|
|
|
|
|
ImportName,
|
|
|
|
|
Path,
|
|
|
|
|
ConvertedExports,
|
|
|
|
|
static_cast<llvm::COFF::MachineTypes>(Machine),
|
|
|
|
|
MinGW);
|
|
|
|
|
if (Error) {
|
|
|
|
|
std::string errorString;
|
|
|
|
|
llvm::raw_string_ostream stream(errorString);
|
|
|
|
|
stream << Error;
|
|
|
|
|
stream.flush();
|
|
|
|
|
LLVMRustSetLastError(errorString.c_str());
|
|
|
|
|
return LLVMRustResult::Failure;
|
|
|
|
|
} else {
|
|
|
|
|
return LLVMRustResult::Success;
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-11-12 00:00:00 +00:00
|
|
|
|
|
|
|
|
|
// Transfers ownership of DiagnosticHandler unique_ptr to the caller.
|
|
|
|
|
extern "C" DiagnosticHandler *
|
|
|
|
|
LLVMRustContextGetDiagnosticHandler(LLVMContextRef C) {
|
|
|
|
|
std::unique_ptr<DiagnosticHandler> DH = unwrap(C)->getDiagnosticHandler();
|
|
|
|
|
return DH.release();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Sets unique_ptr to object of DiagnosticHandler to provide custom diagnostic
|
|
|
|
|
// handling. Ownership of the handler is moved to the LLVMContext.
|
|
|
|
|
extern "C" void LLVMRustContextSetDiagnosticHandler(LLVMContextRef C,
|
|
|
|
|
DiagnosticHandler *DH) {
|
|
|
|
|
unwrap(C)->setDiagnosticHandler(std::unique_ptr<DiagnosticHandler>(DH));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
using LLVMDiagnosticHandlerTy = DiagnosticHandler::DiagnosticHandlerTy;
|
|
|
|
|
|
|
|
|
|
// Configures a diagnostic handler that invokes provided callback when a
|
|
|
|
|
// backend needs to emit a diagnostic.
|
|
|
|
|
//
|
|
|
|
|
// When RemarkAllPasses is true, remarks are enabled for all passes. Otherwise
|
|
|
|
|
// the RemarkPasses array specifies individual passes for which remarks will be
|
|
|
|
|
// enabled.
|
|
|
|
|
extern "C" void LLVMRustContextConfigureDiagnosticHandler(
|
|
|
|
|
LLVMContextRef C, LLVMDiagnosticHandlerTy DiagnosticHandlerCallback,
|
|
|
|
|
void *DiagnosticHandlerContext, bool RemarkAllPasses,
|
|
|
|
|
const char * const * RemarkPasses, size_t RemarkPassesLen) {
|
|
|
|
|
|
|
|
|
|
class RustDiagnosticHandler final : public DiagnosticHandler {
|
|
|
|
|
public:
|
|
|
|
|
RustDiagnosticHandler(LLVMDiagnosticHandlerTy DiagnosticHandlerCallback,
|
|
|
|
|
void *DiagnosticHandlerContext,
|
|
|
|
|
bool RemarkAllPasses,
|
|
|
|
|
std::vector<std::string> RemarkPasses)
|
|
|
|
|
: DiagnosticHandlerCallback(DiagnosticHandlerCallback),
|
|
|
|
|
DiagnosticHandlerContext(DiagnosticHandlerContext),
|
|
|
|
|
RemarkAllPasses(RemarkAllPasses),
|
|
|
|
|
RemarkPasses(RemarkPasses) {}
|
|
|
|
|
|
|
|
|
|
virtual bool handleDiagnostics(const DiagnosticInfo &DI) override {
|
|
|
|
|
if (DiagnosticHandlerCallback) {
|
|
|
|
|
DiagnosticHandlerCallback(DI, DiagnosticHandlerContext);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool isAnalysisRemarkEnabled(StringRef PassName) const override {
|
|
|
|
|
return isRemarkEnabled(PassName);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool isMissedOptRemarkEnabled(StringRef PassName) const override {
|
|
|
|
|
return isRemarkEnabled(PassName);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool isPassedOptRemarkEnabled(StringRef PassName) const override {
|
|
|
|
|
return isRemarkEnabled(PassName);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool isAnyRemarkEnabled() const override {
|
|
|
|
|
return RemarkAllPasses || !RemarkPasses.empty();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
bool isRemarkEnabled(StringRef PassName) const {
|
|
|
|
|
if (RemarkAllPasses)
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
for (auto &Pass : RemarkPasses)
|
|
|
|
|
if (Pass == PassName)
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LLVMDiagnosticHandlerTy DiagnosticHandlerCallback = nullptr;
|
|
|
|
|
void *DiagnosticHandlerContext = nullptr;
|
|
|
|
|
|
|
|
|
|
bool RemarkAllPasses = false;
|
|
|
|
|
std::vector<std::string> RemarkPasses;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
std::vector<std::string> Passes;
|
|
|
|
|
for (size_t I = 0; I != RemarkPassesLen; ++I)
|
|
|
|
|
Passes.push_back(RemarkPasses[I]);
|
|
|
|
|
|
|
|
|
|
unwrap(C)->setDiagnosticHandler(std::make_unique<RustDiagnosticHandler>(
|
|
|
|
|
DiagnosticHandlerCallback, DiagnosticHandlerContext, RemarkAllPasses, Passes));
|
|
|
|
|
}
|
2022-03-01 00:53:25 +00:00
|
|
|
|
|
|
|
|
|
extern "C" void LLVMRustGetMangledName(LLVMValueRef V, RustStringRef Str) {
|
|
|
|
|
RawRustStringOstream OS(Str);
|
|
|
|
|
GlobalValue *GV = unwrap<GlobalValue>(V);
|
|
|
|
|
Mangler().getNameWithPrefix(OS, GV, true);
|
|
|
|
|
}
|