Move rustllvm
into rustc_llvm
This commit is contained in:
parent
d92155bf6a
commit
10d3f8a484
17 changed files with 23 additions and 27 deletions
16
compiler/rustc_llvm/Cargo.toml
Normal file
16
compiler/rustc_llvm/Cargo.toml
Normal file
|
@ -0,0 +1,16 @@
|
|||
[package]
|
||||
authors = ["The Rust Project Developers"]
|
||||
name = "rustc_llvm"
|
||||
version = "0.0.0"
|
||||
edition = "2018"
|
||||
|
||||
[features]
|
||||
static-libstdcpp = []
|
||||
emscripten = []
|
||||
|
||||
[dependencies]
|
||||
libc = "0.2.73"
|
||||
|
||||
[build-dependencies]
|
||||
build_helper = { path = "../../src/build_helper" }
|
||||
cc = "1.0.58"
|
322
compiler/rustc_llvm/build.rs
Normal file
322
compiler/rustc_llvm/build.rs
Normal file
|
@ -0,0 +1,322 @@
|
|||
use std::env;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::Command;
|
||||
|
||||
use build_helper::{output, tracked_env_var_os};
|
||||
|
||||
fn detect_llvm_link() -> (&'static str, &'static str) {
|
||||
// Force the link mode we want, preferring static by default, but
|
||||
// possibly overridden by `configure --enable-llvm-link-shared`.
|
||||
if tracked_env_var_os("LLVM_LINK_SHARED").is_some() {
|
||||
("dylib", "--link-shared")
|
||||
} else {
|
||||
("static", "--link-static")
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
if tracked_env_var_os("RUST_CHECK").is_some() {
|
||||
// If we're just running `check`, there's no need for LLVM to be built.
|
||||
return;
|
||||
}
|
||||
|
||||
build_helper::restore_library_path();
|
||||
|
||||
let target = env::var("TARGET").expect("TARGET was not set");
|
||||
let llvm_config =
|
||||
tracked_env_var_os("LLVM_CONFIG").map(|x| Some(PathBuf::from(x))).unwrap_or_else(|| {
|
||||
if let Some(dir) = tracked_env_var_os("CARGO_TARGET_DIR").map(PathBuf::from) {
|
||||
let to_test = dir
|
||||
.parent()
|
||||
.unwrap()
|
||||
.parent()
|
||||
.unwrap()
|
||||
.join(&target)
|
||||
.join("llvm/bin/llvm-config");
|
||||
if Command::new(&to_test).output().is_ok() {
|
||||
return Some(to_test);
|
||||
}
|
||||
}
|
||||
None
|
||||
});
|
||||
|
||||
if let Some(llvm_config) = &llvm_config {
|
||||
println!("cargo:rerun-if-changed={}", llvm_config.display());
|
||||
}
|
||||
let llvm_config = llvm_config.unwrap_or_else(|| PathBuf::from("llvm-config"));
|
||||
|
||||
// Test whether we're cross-compiling LLVM. This is a pretty rare case
|
||||
// currently where we're producing an LLVM for a different platform than
|
||||
// what this build script is currently running on.
|
||||
//
|
||||
// In that case, there's no guarantee that we can actually run the target,
|
||||
// so the build system works around this by giving us the LLVM_CONFIG for
|
||||
// the host platform. This only really works if the host LLVM and target
|
||||
// LLVM are compiled the same way, but for us that's typically the case.
|
||||
//
|
||||
// We *want* detect this cross compiling situation by asking llvm-config
|
||||
// what its host-target is. If that's not the TARGET, then we're cross
|
||||
// compiling. Unfortunately `llvm-config` seems either be buggy, or we're
|
||||
// misconfiguring it, because the `i686-pc-windows-gnu` build of LLVM will
|
||||
// report itself with a `--host-target` of `x86_64-pc-windows-gnu`. This
|
||||
// tricks us into thinking we're doing a cross build when we aren't, so
|
||||
// havoc ensues.
|
||||
//
|
||||
// In any case, if we're cross compiling, this generally just means that we
|
||||
// can't trust all the output of llvm-config because it might be targeted
|
||||
// for the host rather than the target. As a result a bunch of blocks below
|
||||
// are gated on `if !is_crossed`
|
||||
let target = env::var("TARGET").expect("TARGET was not set");
|
||||
let host = env::var("HOST").expect("HOST was not set");
|
||||
let is_crossed = target != host;
|
||||
|
||||
let mut optional_components = vec![
|
||||
"x86",
|
||||
"arm",
|
||||
"aarch64",
|
||||
"amdgpu",
|
||||
"avr",
|
||||
"mips",
|
||||
"powerpc",
|
||||
"systemz",
|
||||
"jsbackend",
|
||||
"webassembly",
|
||||
"msp430",
|
||||
"sparc",
|
||||
"nvptx",
|
||||
"hexagon",
|
||||
];
|
||||
|
||||
let mut version_cmd = Command::new(&llvm_config);
|
||||
version_cmd.arg("--version");
|
||||
let version_output = output(&mut version_cmd);
|
||||
let mut parts = version_output.split('.').take(2).filter_map(|s| s.parse::<u32>().ok());
|
||||
let (major, _minor) = if let (Some(major), Some(minor)) = (parts.next(), parts.next()) {
|
||||
(major, minor)
|
||||
} else {
|
||||
(6, 0)
|
||||
};
|
||||
|
||||
if major > 6 {
|
||||
optional_components.push("riscv");
|
||||
}
|
||||
|
||||
let required_components = &[
|
||||
"ipo",
|
||||
"bitreader",
|
||||
"bitwriter",
|
||||
"linker",
|
||||
"asmparser",
|
||||
"lto",
|
||||
"coverage",
|
||||
"instrumentation",
|
||||
];
|
||||
|
||||
let components = output(Command::new(&llvm_config).arg("--components"));
|
||||
let mut components = components.split_whitespace().collect::<Vec<_>>();
|
||||
components.retain(|c| optional_components.contains(c) || required_components.contains(c));
|
||||
|
||||
for component in required_components {
|
||||
if !components.contains(component) {
|
||||
panic!("require llvm component {} but wasn't found", component);
|
||||
}
|
||||
}
|
||||
|
||||
for component in components.iter() {
|
||||
println!("cargo:rustc-cfg=llvm_component=\"{}\"", component);
|
||||
}
|
||||
|
||||
if major >= 9 {
|
||||
println!("cargo:rustc-cfg=llvm_has_msp430_asm_parser");
|
||||
}
|
||||
|
||||
// Link in our own LLVM shims, compiled with the same flags as LLVM
|
||||
let mut cmd = Command::new(&llvm_config);
|
||||
cmd.arg("--cxxflags");
|
||||
let cxxflags = output(&mut cmd);
|
||||
let mut cfg = cc::Build::new();
|
||||
cfg.warnings(false);
|
||||
for flag in cxxflags.split_whitespace() {
|
||||
// Ignore flags like `-m64` when we're doing a cross build
|
||||
if is_crossed && flag.starts_with("-m") {
|
||||
continue;
|
||||
}
|
||||
|
||||
if flag.starts_with("-flto") {
|
||||
continue;
|
||||
}
|
||||
|
||||
// -Wdate-time is not supported by the netbsd cross compiler
|
||||
if is_crossed && target.contains("netbsd") && flag.contains("date-time") {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Include path contains host directory, replace it with target
|
||||
if is_crossed && flag.starts_with("-I") {
|
||||
cfg.flag(&flag.replace(&host, &target));
|
||||
continue;
|
||||
}
|
||||
|
||||
cfg.flag(flag);
|
||||
}
|
||||
|
||||
for component in &components {
|
||||
let mut flag = String::from("LLVM_COMPONENT_");
|
||||
flag.push_str(&component.to_uppercase());
|
||||
cfg.define(&flag, None);
|
||||
}
|
||||
|
||||
if tracked_env_var_os("LLVM_RUSTLLVM").is_some() {
|
||||
cfg.define("LLVM_RUSTLLVM", None);
|
||||
}
|
||||
|
||||
if tracked_env_var_os("LLVM_NDEBUG").is_some() {
|
||||
cfg.define("NDEBUG", None);
|
||||
cfg.debug(false);
|
||||
}
|
||||
|
||||
build_helper::rerun_if_changed_anything_in_dir(Path::new("llvm-wrapper"));
|
||||
cfg.file("llvm-wrapper/PassWrapper.cpp")
|
||||
.file("llvm-wrapper/RustWrapper.cpp")
|
||||
.file("llvm-wrapper/ArchiveWrapper.cpp")
|
||||
.file("llvm-wrapper/CoverageMappingWrapper.cpp")
|
||||
.file("llvm-wrapper/Linker.cpp")
|
||||
.cpp(true)
|
||||
.cpp_link_stdlib(None) // we handle this below
|
||||
.compile("llvm-wrapper");
|
||||
|
||||
let (llvm_kind, llvm_link_arg) = detect_llvm_link();
|
||||
|
||||
// Link in all LLVM libraries, if we're using the "wrong" llvm-config then
|
||||
// we don't pick up system libs because unfortunately they're for the host
|
||||
// of llvm-config, not the target that we're attempting to link.
|
||||
let mut cmd = Command::new(&llvm_config);
|
||||
cmd.arg(llvm_link_arg).arg("--libs");
|
||||
|
||||
if !is_crossed {
|
||||
cmd.arg("--system-libs");
|
||||
} else if target.contains("windows-gnu") {
|
||||
println!("cargo:rustc-link-lib=shell32");
|
||||
println!("cargo:rustc-link-lib=uuid");
|
||||
} else if target.contains("netbsd") || target.contains("haiku") {
|
||||
println!("cargo:rustc-link-lib=z");
|
||||
}
|
||||
cmd.args(&components);
|
||||
|
||||
for lib in output(&mut cmd).split_whitespace() {
|
||||
let name = if lib.starts_with("-l") {
|
||||
&lib[2..]
|
||||
} else if lib.starts_with('-') {
|
||||
&lib[1..]
|
||||
} else if Path::new(lib).exists() {
|
||||
// On MSVC llvm-config will print the full name to libraries, but
|
||||
// we're only interested in the name part
|
||||
let name = Path::new(lib).file_name().unwrap().to_str().unwrap();
|
||||
name.trim_end_matches(".lib")
|
||||
} else if lib.ends_with(".lib") {
|
||||
// Some MSVC libraries just come up with `.lib` tacked on, so chop
|
||||
// that off
|
||||
lib.trim_end_matches(".lib")
|
||||
} else {
|
||||
continue;
|
||||
};
|
||||
|
||||
// Don't need or want this library, but LLVM's CMake build system
|
||||
// doesn't provide a way to disable it, so filter it here even though we
|
||||
// may or may not have built it. We don't reference anything from this
|
||||
// library and it otherwise may just pull in extra dependencies on
|
||||
// libedit which we don't want
|
||||
if name == "LLVMLineEditor" {
|
||||
continue;
|
||||
}
|
||||
|
||||
let kind = if name.starts_with("LLVM") { llvm_kind } else { "dylib" };
|
||||
println!("cargo:rustc-link-lib={}={}", kind, name);
|
||||
}
|
||||
|
||||
// LLVM ldflags
|
||||
//
|
||||
// If we're a cross-compile of LLVM then unfortunately we can't trust these
|
||||
// ldflags (largely where all the LLVM libs are located). Currently just
|
||||
// hack around this by replacing the host triple with the target and pray
|
||||
// that those -L directories are the same!
|
||||
let mut cmd = Command::new(&llvm_config);
|
||||
cmd.arg(llvm_link_arg).arg("--ldflags");
|
||||
for lib in output(&mut cmd).split_whitespace() {
|
||||
if is_crossed {
|
||||
if lib.starts_with("-LIBPATH:") {
|
||||
println!("cargo:rustc-link-search=native={}", lib[9..].replace(&host, &target));
|
||||
} else if lib.starts_with("-L") {
|
||||
println!("cargo:rustc-link-search=native={}", lib[2..].replace(&host, &target));
|
||||
}
|
||||
} else if lib.starts_with("-LIBPATH:") {
|
||||
println!("cargo:rustc-link-search=native={}", &lib[9..]);
|
||||
} else if lib.starts_with("-l") {
|
||||
println!("cargo:rustc-link-lib={}", &lib[2..]);
|
||||
} else if lib.starts_with("-L") {
|
||||
println!("cargo:rustc-link-search=native={}", &lib[2..]);
|
||||
}
|
||||
}
|
||||
|
||||
// Some LLVM linker flags (-L and -l) may be needed even when linking
|
||||
// rustc_llvm, for example when using static libc++, we may need to
|
||||
// manually specify the library search path and -ldl -lpthread as link
|
||||
// dependencies.
|
||||
let llvm_linker_flags = tracked_env_var_os("LLVM_LINKER_FLAGS");
|
||||
if let Some(s) = llvm_linker_flags {
|
||||
for lib in s.into_string().unwrap().split_whitespace() {
|
||||
if lib.starts_with("-l") {
|
||||
println!("cargo:rustc-link-lib={}", &lib[2..]);
|
||||
} else if lib.starts_with("-L") {
|
||||
println!("cargo:rustc-link-search=native={}", &lib[2..]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let llvm_static_stdcpp = tracked_env_var_os("LLVM_STATIC_STDCPP");
|
||||
let llvm_use_libcxx = tracked_env_var_os("LLVM_USE_LIBCXX");
|
||||
|
||||
let stdcppname = if target.contains("openbsd") {
|
||||
if target.contains("sparc64") { "estdc++" } else { "c++" }
|
||||
} else if target.contains("freebsd") {
|
||||
"c++"
|
||||
} else if target.contains("darwin") {
|
||||
"c++"
|
||||
} else if target.contains("netbsd") && llvm_static_stdcpp.is_some() {
|
||||
// NetBSD uses a separate library when relocation is required
|
||||
"stdc++_pic"
|
||||
} else if llvm_use_libcxx.is_some() {
|
||||
"c++"
|
||||
} else {
|
||||
"stdc++"
|
||||
};
|
||||
|
||||
// RISC-V requires libatomic for sub-word atomic operations
|
||||
if target.starts_with("riscv") {
|
||||
println!("cargo:rustc-link-lib=atomic");
|
||||
}
|
||||
|
||||
// C++ runtime library
|
||||
if !target.contains("msvc") {
|
||||
if let Some(s) = llvm_static_stdcpp {
|
||||
assert!(!cxxflags.contains("stdlib=libc++"));
|
||||
let path = PathBuf::from(s);
|
||||
println!("cargo:rustc-link-search=native={}", path.parent().unwrap().display());
|
||||
if target.contains("windows") {
|
||||
println!("cargo:rustc-link-lib=static-nobundle={}", stdcppname);
|
||||
} else {
|
||||
println!("cargo:rustc-link-lib=static={}", stdcppname);
|
||||
}
|
||||
} else if cxxflags.contains("stdlib=libc++") {
|
||||
println!("cargo:rustc-link-lib=c++");
|
||||
} else {
|
||||
println!("cargo:rustc-link-lib={}", stdcppname);
|
||||
}
|
||||
}
|
||||
|
||||
// Libstdc++ depends on pthread which Rust doesn't link on MinGW
|
||||
// since nothing else requires it.
|
||||
if target.contains("windows-gnu") {
|
||||
println!("cargo:rustc-link-lib=static-nobundle=pthread");
|
||||
}
|
||||
}
|
6
compiler/rustc_llvm/llvm-wrapper/.editorconfig
Normal file
6
compiler/rustc_llvm/llvm-wrapper/.editorconfig
Normal file
|
@ -0,0 +1,6 @@
|
|||
[*.{h,cpp}]
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 2
|
226
compiler/rustc_llvm/llvm-wrapper/ArchiveWrapper.cpp
Normal file
226
compiler/rustc_llvm/llvm-wrapper/ArchiveWrapper.cpp
Normal file
|
@ -0,0 +1,226 @@
|
|||
#include "LLVMWrapper.h"
|
||||
|
||||
#include "llvm/Object/Archive.h"
|
||||
#include "llvm/Object/ArchiveWriter.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::object;
|
||||
|
||||
struct RustArchiveMember {
|
||||
const char *Filename;
|
||||
const char *Name;
|
||||
Archive::Child Child;
|
||||
|
||||
RustArchiveMember()
|
||||
: Filename(nullptr), Name(nullptr),
|
||||
Child(nullptr, nullptr, nullptr)
|
||||
{
|
||||
}
|
||||
~RustArchiveMember() {}
|
||||
};
|
||||
|
||||
struct RustArchiveIterator {
|
||||
bool First;
|
||||
Archive::child_iterator Cur;
|
||||
Archive::child_iterator End;
|
||||
std::unique_ptr<Error> Err;
|
||||
|
||||
RustArchiveIterator(Archive::child_iterator Cur, Archive::child_iterator End,
|
||||
std::unique_ptr<Error> Err)
|
||||
: First(true),
|
||||
Cur(Cur),
|
||||
End(End),
|
||||
Err(std::move(Err)) {}
|
||||
};
|
||||
|
||||
enum class LLVMRustArchiveKind {
|
||||
GNU,
|
||||
BSD,
|
||||
DARWIN,
|
||||
COFF,
|
||||
};
|
||||
|
||||
static Archive::Kind fromRust(LLVMRustArchiveKind Kind) {
|
||||
switch (Kind) {
|
||||
case LLVMRustArchiveKind::GNU:
|
||||
return Archive::K_GNU;
|
||||
case LLVMRustArchiveKind::BSD:
|
||||
return Archive::K_BSD;
|
||||
case LLVMRustArchiveKind::DARWIN:
|
||||
return Archive::K_DARWIN;
|
||||
case LLVMRustArchiveKind::COFF:
|
||||
return Archive::K_COFF;
|
||||
default:
|
||||
report_fatal_error("Bad ArchiveKind.");
|
||||
}
|
||||
}
|
||||
|
||||
typedef OwningBinary<Archive> *LLVMRustArchiveRef;
|
||||
typedef RustArchiveMember *LLVMRustArchiveMemberRef;
|
||||
typedef Archive::Child *LLVMRustArchiveChildRef;
|
||||
typedef Archive::Child const *LLVMRustArchiveChildConstRef;
|
||||
typedef RustArchiveIterator *LLVMRustArchiveIteratorRef;
|
||||
|
||||
extern "C" LLVMRustArchiveRef LLVMRustOpenArchive(char *Path) {
|
||||
ErrorOr<std::unique_ptr<MemoryBuffer>> BufOr =
|
||||
MemoryBuffer::getFile(Path, -1, false);
|
||||
if (!BufOr) {
|
||||
LLVMRustSetLastError(BufOr.getError().message().c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Expected<std::unique_ptr<Archive>> ArchiveOr =
|
||||
Archive::create(BufOr.get()->getMemBufferRef());
|
||||
|
||||
if (!ArchiveOr) {
|
||||
LLVMRustSetLastError(toString(ArchiveOr.takeError()).c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
OwningBinary<Archive> *Ret = new OwningBinary<Archive>(
|
||||
std::move(ArchiveOr.get()), std::move(BufOr.get()));
|
||||
|
||||
return Ret;
|
||||
}
|
||||
|
||||
extern "C" void LLVMRustDestroyArchive(LLVMRustArchiveRef RustArchive) {
|
||||
delete RustArchive;
|
||||
}
|
||||
|
||||
extern "C" LLVMRustArchiveIteratorRef
|
||||
LLVMRustArchiveIteratorNew(LLVMRustArchiveRef RustArchive) {
|
||||
Archive *Archive = RustArchive->getBinary();
|
||||
#if LLVM_VERSION_GE(10, 0)
|
||||
std::unique_ptr<Error> Err = std::make_unique<Error>(Error::success());
|
||||
#else
|
||||
std::unique_ptr<Error> Err = llvm::make_unique<Error>(Error::success());
|
||||
#endif
|
||||
auto Cur = Archive->child_begin(*Err);
|
||||
if (*Err) {
|
||||
LLVMRustSetLastError(toString(std::move(*Err)).c_str());
|
||||
return nullptr;
|
||||
}
|
||||
auto End = Archive->child_end();
|
||||
return new RustArchiveIterator(Cur, End, std::move(Err));
|
||||
}
|
||||
|
||||
extern "C" LLVMRustArchiveChildConstRef
|
||||
LLVMRustArchiveIteratorNext(LLVMRustArchiveIteratorRef RAI) {
|
||||
if (RAI->Cur == RAI->End)
|
||||
return nullptr;
|
||||
|
||||
// Advancing the iterator validates the next child, and this can
|
||||
// uncover an error. LLVM requires that we check all Errors,
|
||||
// so we only advance the iterator if we actually need to fetch
|
||||
// the next child.
|
||||
// This means we must not advance the iterator in the *first* call,
|
||||
// but instead advance it *before* fetching the child in all later calls.
|
||||
if (!RAI->First) {
|
||||
++RAI->Cur;
|
||||
if (*RAI->Err) {
|
||||
LLVMRustSetLastError(toString(std::move(*RAI->Err)).c_str());
|
||||
return nullptr;
|
||||
}
|
||||
} else {
|
||||
RAI->First = false;
|
||||
}
|
||||
|
||||
if (RAI->Cur == RAI->End)
|
||||
return nullptr;
|
||||
|
||||
const Archive::Child &Child = *RAI->Cur.operator->();
|
||||
Archive::Child *Ret = new Archive::Child(Child);
|
||||
|
||||
return Ret;
|
||||
}
|
||||
|
||||
extern "C" void LLVMRustArchiveChildFree(LLVMRustArchiveChildRef Child) {
|
||||
delete Child;
|
||||
}
|
||||
|
||||
extern "C" void LLVMRustArchiveIteratorFree(LLVMRustArchiveIteratorRef RAI) {
|
||||
delete RAI;
|
||||
}
|
||||
|
||||
extern "C" const char *
|
||||
LLVMRustArchiveChildName(LLVMRustArchiveChildConstRef Child, size_t *Size) {
|
||||
Expected<StringRef> NameOrErr = Child->getName();
|
||||
if (!NameOrErr) {
|
||||
// rustc_codegen_llvm currently doesn't use this error string, but it might be
|
||||
// useful in the future, and in the mean time this tells LLVM that the
|
||||
// error was not ignored and that it shouldn't abort the process.
|
||||
LLVMRustSetLastError(toString(NameOrErr.takeError()).c_str());
|
||||
return nullptr;
|
||||
}
|
||||
StringRef Name = NameOrErr.get();
|
||||
*Size = Name.size();
|
||||
return Name.data();
|
||||
}
|
||||
|
||||
extern "C" const char *LLVMRustArchiveChildData(LLVMRustArchiveChildRef Child,
|
||||
size_t *Size) {
|
||||
StringRef Buf;
|
||||
Expected<StringRef> BufOrErr = Child->getBuffer();
|
||||
if (!BufOrErr) {
|
||||
LLVMRustSetLastError(toString(BufOrErr.takeError()).c_str());
|
||||
return nullptr;
|
||||
}
|
||||
Buf = BufOrErr.get();
|
||||
*Size = Buf.size();
|
||||
return Buf.data();
|
||||
}
|
||||
|
||||
extern "C" LLVMRustArchiveMemberRef
|
||||
LLVMRustArchiveMemberNew(char *Filename, char *Name,
|
||||
LLVMRustArchiveChildRef Child) {
|
||||
RustArchiveMember *Member = new RustArchiveMember;
|
||||
Member->Filename = Filename;
|
||||
Member->Name = Name;
|
||||
if (Child)
|
||||
Member->Child = *Child;
|
||||
return Member;
|
||||
}
|
||||
|
||||
extern "C" void LLVMRustArchiveMemberFree(LLVMRustArchiveMemberRef Member) {
|
||||
delete Member;
|
||||
}
|
||||
|
||||
extern "C" LLVMRustResult
|
||||
LLVMRustWriteArchive(char *Dst, size_t NumMembers,
|
||||
const LLVMRustArchiveMemberRef *NewMembers,
|
||||
bool WriteSymbtab, LLVMRustArchiveKind RustKind) {
|
||||
|
||||
std::vector<NewArchiveMember> Members;
|
||||
auto Kind = fromRust(RustKind);
|
||||
|
||||
for (size_t I = 0; I < NumMembers; I++) {
|
||||
auto Member = NewMembers[I];
|
||||
assert(Member->Name);
|
||||
if (Member->Filename) {
|
||||
Expected<NewArchiveMember> MOrErr =
|
||||
NewArchiveMember::getFile(Member->Filename, true);
|
||||
if (!MOrErr) {
|
||||
LLVMRustSetLastError(toString(MOrErr.takeError()).c_str());
|
||||
return LLVMRustResult::Failure;
|
||||
}
|
||||
MOrErr->MemberName = sys::path::filename(MOrErr->MemberName);
|
||||
Members.push_back(std::move(*MOrErr));
|
||||
} else {
|
||||
Expected<NewArchiveMember> MOrErr =
|
||||
NewArchiveMember::getOldMember(Member->Child, true);
|
||||
if (!MOrErr) {
|
||||
LLVMRustSetLastError(toString(MOrErr.takeError()).c_str());
|
||||
return LLVMRustResult::Failure;
|
||||
}
|
||||
Members.push_back(std::move(*MOrErr));
|
||||
}
|
||||
}
|
||||
|
||||
auto Result = writeArchive(Dst, Members, WriteSymbtab, Kind, true, false);
|
||||
if (!Result)
|
||||
return LLVMRustResult::Success;
|
||||
LLVMRustSetLastError(toString(std::move(Result)).c_str());
|
||||
|
||||
return LLVMRustResult::Failure;
|
||||
}
|
70
compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp
Normal file
70
compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp
Normal file
|
@ -0,0 +1,70 @@
|
|||
#include "LLVMWrapper.h"
|
||||
#include "llvm/ProfileData/Coverage/CoverageMapping.h"
|
||||
#include "llvm/ProfileData/Coverage/CoverageMappingWriter.h"
|
||||
#include "llvm/ProfileData/InstrProf.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/Support/LEB128.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
extern "C" void LLVMRustCoverageWriteFilenamesSectionToBuffer(
|
||||
const char* const Filenames[],
|
||||
size_t FilenamesLen,
|
||||
RustStringRef BufferOut) {
|
||||
// LLVM 11's CoverageFilenamesSectionWriter uses its new `Version4` format,
|
||||
// so we're manually writing the `Version3` format ourselves.
|
||||
RawRustStringOstream OS(BufferOut);
|
||||
encodeULEB128(FilenamesLen, OS);
|
||||
for (size_t i = 0; i < FilenamesLen; i++) {
|
||||
StringRef Filename(Filenames[i]);
|
||||
encodeULEB128(Filename.size(), OS);
|
||||
OS << Filename;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void LLVMRustCoverageWriteMappingToBuffer(
|
||||
const unsigned *VirtualFileMappingIDs,
|
||||
unsigned NumVirtualFileMappingIDs,
|
||||
const coverage::CounterExpression *Expressions,
|
||||
unsigned NumExpressions,
|
||||
coverage::CounterMappingRegion *MappingRegions,
|
||||
unsigned NumMappingRegions,
|
||||
RustStringRef BufferOut) {
|
||||
auto CoverageMappingWriter = coverage::CoverageMappingWriter(
|
||||
makeArrayRef(VirtualFileMappingIDs, NumVirtualFileMappingIDs),
|
||||
makeArrayRef(Expressions, NumExpressions),
|
||||
makeMutableArrayRef(MappingRegions, NumMappingRegions));
|
||||
RawRustStringOstream OS(BufferOut);
|
||||
CoverageMappingWriter.write(OS);
|
||||
}
|
||||
|
||||
extern "C" LLVMValueRef LLVMRustCoverageCreatePGOFuncNameVar(LLVMValueRef F, const char *FuncName) {
|
||||
StringRef FuncNameRef(FuncName);
|
||||
return wrap(createPGOFuncNameVar(*cast<Function>(unwrap(F)), FuncNameRef));
|
||||
}
|
||||
|
||||
extern "C" uint64_t LLVMRustCoverageComputeHash(const char *Name) {
|
||||
StringRef NameRef(Name);
|
||||
return IndexedInstrProf::ComputeHash(NameRef);
|
||||
}
|
||||
|
||||
extern "C" void LLVMRustCoverageWriteSectionNameToString(LLVMModuleRef M,
|
||||
RustStringRef Str) {
|
||||
Triple TargetTriple(unwrap(M)->getTargetTriple());
|
||||
auto name = getInstrProfSectionName(IPSK_covmap,
|
||||
TargetTriple.getObjectFormat());
|
||||
RawRustStringOstream OS(Str);
|
||||
OS << name;
|
||||
}
|
||||
|
||||
extern "C" void LLVMRustCoverageWriteMappingVarNameToString(RustStringRef Str) {
|
||||
auto name = getCoverageMappingVarName();
|
||||
RawRustStringOstream OS(Str);
|
||||
OS << name;
|
||||
}
|
||||
|
||||
extern "C" uint32_t LLVMRustCoverageMappingVersion() {
|
||||
return coverage::CovMapVersion::Version3;
|
||||
}
|
115
compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h
Normal file
115
compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h
Normal file
|
@ -0,0 +1,115 @@
|
|||
#include "llvm-c/BitReader.h"
|
||||
#include "llvm-c/Core.h"
|
||||
#include "llvm-c/Object.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/DenseSet.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/Triple.h"
|
||||
#include "llvm/Analysis/Lint.h"
|
||||
#include "llvm/Analysis/Passes.h"
|
||||
#include "llvm/IR/IRBuilder.h"
|
||||
#include "llvm/IR/InlineAsm.h"
|
||||
#include "llvm/IR/LLVMContext.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/DynamicLibrary.h"
|
||||
#include "llvm/Support/FormattedStream.h"
|
||||
#include "llvm/Support/Host.h"
|
||||
#include "llvm/Support/Memory.h"
|
||||
#include "llvm/Support/SourceMgr.h"
|
||||
#include "llvm/Support/TargetRegistry.h"
|
||||
#include "llvm/Support/TargetSelect.h"
|
||||
#include "llvm/Support/Timer.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include "llvm/Target/TargetOptions.h"
|
||||
#include "llvm/Transforms/IPO.h"
|
||||
#include "llvm/Transforms/Instrumentation.h"
|
||||
#include "llvm/Transforms/Scalar.h"
|
||||
#include "llvm/Transforms/Vectorize.h"
|
||||
|
||||
#define LLVM_VERSION_GE(major, minor) \
|
||||
(LLVM_VERSION_MAJOR > (major) || \
|
||||
LLVM_VERSION_MAJOR == (major) && LLVM_VERSION_MINOR >= (minor))
|
||||
|
||||
#define LLVM_VERSION_EQ(major, minor) \
|
||||
(LLVM_VERSION_MAJOR == (major) && LLVM_VERSION_MINOR == (minor))
|
||||
|
||||
#define LLVM_VERSION_LE(major, minor) \
|
||||
(LLVM_VERSION_MAJOR < (major) || \
|
||||
LLVM_VERSION_MAJOR == (major) && LLVM_VERSION_MINOR <= (minor))
|
||||
|
||||
#define LLVM_VERSION_LT(major, minor) (!LLVM_VERSION_GE((major), (minor)))
|
||||
|
||||
#include "llvm/IR/LegacyPassManager.h"
|
||||
|
||||
#include "llvm/Bitcode/BitcodeReader.h"
|
||||
#include "llvm/Bitcode/BitcodeWriter.h"
|
||||
|
||||
#include "llvm/IR/DIBuilder.h"
|
||||
#include "llvm/IR/DebugInfo.h"
|
||||
#include "llvm/IR/IRPrintingPasses.h"
|
||||
#include "llvm/Linker/Linker.h"
|
||||
|
||||
extern "C" void LLVMRustSetLastError(const char *);
|
||||
|
||||
enum class LLVMRustResult { Success, Failure };
|
||||
|
||||
enum LLVMRustAttribute {
|
||||
AlwaysInline = 0,
|
||||
ByVal = 1,
|
||||
Cold = 2,
|
||||
InlineHint = 3,
|
||||
MinSize = 4,
|
||||
Naked = 5,
|
||||
NoAlias = 6,
|
||||
NoCapture = 7,
|
||||
NoInline = 8,
|
||||
NonNull = 9,
|
||||
NoRedZone = 10,
|
||||
NoReturn = 11,
|
||||
NoUnwind = 12,
|
||||
OptimizeForSize = 13,
|
||||
ReadOnly = 14,
|
||||
SExt = 15,
|
||||
StructRet = 16,
|
||||
UWTable = 17,
|
||||
ZExt = 18,
|
||||
InReg = 19,
|
||||
SanitizeThread = 20,
|
||||
SanitizeAddress = 21,
|
||||
SanitizeMemory = 22,
|
||||
NonLazyBind = 23,
|
||||
OptimizeNone = 24,
|
||||
ReturnsTwice = 25,
|
||||
ReadNone = 26,
|
||||
InaccessibleMemOnly = 27,
|
||||
};
|
||||
|
||||
typedef struct OpaqueRustString *RustStringRef;
|
||||
typedef struct LLVMOpaqueTwine *LLVMTwineRef;
|
||||
typedef struct LLVMOpaqueSMDiagnostic *LLVMSMDiagnosticRef;
|
||||
|
||||
extern "C" void LLVMRustStringWriteImpl(RustStringRef Str, const char *Ptr,
|
||||
size_t Size);
|
||||
|
||||
class RawRustStringOstream : public llvm::raw_ostream {
|
||||
RustStringRef Str;
|
||||
uint64_t Pos;
|
||||
|
||||
void write_impl(const char *Ptr, size_t Size) override {
|
||||
LLVMRustStringWriteImpl(Str, Ptr, Size);
|
||||
Pos += Size;
|
||||
}
|
||||
|
||||
uint64_t current_pos() const override { return Pos; }
|
||||
|
||||
public:
|
||||
explicit RawRustStringOstream(RustStringRef Str) : Str(Str), Pos(0) {}
|
||||
|
||||
~RawRustStringOstream() {
|
||||
// LLVM requires this.
|
||||
flush();
|
||||
}
|
||||
};
|
48
compiler/rustc_llvm/llvm-wrapper/Linker.cpp
Normal file
48
compiler/rustc_llvm/llvm-wrapper/Linker.cpp
Normal file
|
@ -0,0 +1,48 @@
|
|||
#include "llvm/Linker/Linker.h"
|
||||
|
||||
#include "LLVMWrapper.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
struct RustLinker {
|
||||
Linker L;
|
||||
LLVMContext &Ctx;
|
||||
|
||||
RustLinker(Module &M) :
|
||||
L(M),
|
||||
Ctx(M.getContext())
|
||||
{}
|
||||
};
|
||||
|
||||
extern "C" RustLinker*
|
||||
LLVMRustLinkerNew(LLVMModuleRef DstRef) {
|
||||
Module *Dst = unwrap(DstRef);
|
||||
|
||||
return new RustLinker(*Dst);
|
||||
}
|
||||
|
||||
extern "C" void
|
||||
LLVMRustLinkerFree(RustLinker *L) {
|
||||
delete L;
|
||||
}
|
||||
|
||||
extern "C" bool
|
||||
LLVMRustLinkerAdd(RustLinker *L, char *BC, size_t Len) {
|
||||
std::unique_ptr<MemoryBuffer> Buf =
|
||||
MemoryBuffer::getMemBufferCopy(StringRef(BC, Len));
|
||||
|
||||
Expected<std::unique_ptr<Module>> SrcOrError =
|
||||
llvm::getLazyBitcodeModule(Buf->getMemBufferRef(), L->Ctx);
|
||||
if (!SrcOrError) {
|
||||
LLVMRustSetLastError(toString(SrcOrError.takeError()).c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
auto Src = std::move(*SrcOrError);
|
||||
|
||||
if (L->L.linkInModule(std::move(Src))) {
|
||||
LLVMRustSetLastError("");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
1655
compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
Normal file
1655
compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
Normal file
File diff suppressed because it is too large
Load diff
16
compiler/rustc_llvm/llvm-wrapper/README
Normal file
16
compiler/rustc_llvm/llvm-wrapper/README
Normal file
|
@ -0,0 +1,16 @@
|
|||
This directory currently contains some LLVM support code. This will generally
|
||||
be sent upstream to LLVM in time; for now it lives here.
|
||||
|
||||
NOTE: the LLVM C++ ABI is subject to between-version breakage and must *never*
|
||||
be exposed to Rust. To allow for easy auditing of that, all Rust-exposed types
|
||||
must be typedef-ed as "LLVMXyz", or "LLVMRustXyz" if they were defined here.
|
||||
|
||||
Functions that return a failure status and leave the error in
|
||||
the LLVM last error should return an LLVMRustResult rather than an
|
||||
int or anything to avoid confusion.
|
||||
|
||||
When translating enums, add a single `Other` variant as the first
|
||||
one to allow for new variants to be added. It should abort when used
|
||||
as an input.
|
||||
|
||||
All other types must not be typedef-ed as such.
|
1721
compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
Normal file
1721
compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
Normal file
File diff suppressed because it is too large
Load diff
173
compiler/rustc_llvm/src/lib.rs
Normal file
173
compiler/rustc_llvm/src/lib.rs
Normal file
|
@ -0,0 +1,173 @@
|
|||
#![feature(nll)]
|
||||
#![feature(static_nobundle)]
|
||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
|
||||
|
||||
// NOTE: This crate only exists to allow linking on mingw targets.
|
||||
|
||||
use libc::{c_char, size_t};
|
||||
use std::cell::RefCell;
|
||||
use std::slice;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct RustString {
|
||||
pub bytes: RefCell<Vec<u8>>,
|
||||
}
|
||||
|
||||
impl RustString {
|
||||
pub fn len(&self) -> usize {
|
||||
self.bytes.borrow().len()
|
||||
}
|
||||
}
|
||||
|
||||
/// Appending to a Rust string -- used by RawRustStringOstream.
|
||||
#[no_mangle]
|
||||
#[allow(improper_ctypes_definitions)]
|
||||
pub unsafe extern "C" fn LLVMRustStringWriteImpl(
|
||||
sr: &RustString,
|
||||
ptr: *const c_char,
|
||||
size: size_t,
|
||||
) {
|
||||
let slice = slice::from_raw_parts(ptr as *const u8, size as usize);
|
||||
|
||||
sr.bytes.borrow_mut().extend_from_slice(slice);
|
||||
}
|
||||
|
||||
/// Initialize targets enabled by the build script via `cfg(llvm_component = "...")`.
|
||||
/// N.B., this function can't be moved to `rustc_codegen_llvm` because of the `cfg`s.
|
||||
pub fn initialize_available_targets() {
|
||||
macro_rules! init_target(
|
||||
($cfg:meta, $($method:ident),*) => { {
|
||||
#[cfg($cfg)]
|
||||
fn init() {
|
||||
extern {
|
||||
$(fn $method();)*
|
||||
}
|
||||
unsafe {
|
||||
$($method();)*
|
||||
}
|
||||
}
|
||||
#[cfg(not($cfg))]
|
||||
fn init() { }
|
||||
init();
|
||||
} }
|
||||
);
|
||||
init_target!(
|
||||
llvm_component = "x86",
|
||||
LLVMInitializeX86TargetInfo,
|
||||
LLVMInitializeX86Target,
|
||||
LLVMInitializeX86TargetMC,
|
||||
LLVMInitializeX86AsmPrinter,
|
||||
LLVMInitializeX86AsmParser
|
||||
);
|
||||
init_target!(
|
||||
llvm_component = "arm",
|
||||
LLVMInitializeARMTargetInfo,
|
||||
LLVMInitializeARMTarget,
|
||||
LLVMInitializeARMTargetMC,
|
||||
LLVMInitializeARMAsmPrinter,
|
||||
LLVMInitializeARMAsmParser
|
||||
);
|
||||
init_target!(
|
||||
llvm_component = "aarch64",
|
||||
LLVMInitializeAArch64TargetInfo,
|
||||
LLVMInitializeAArch64Target,
|
||||
LLVMInitializeAArch64TargetMC,
|
||||
LLVMInitializeAArch64AsmPrinter,
|
||||
LLVMInitializeAArch64AsmParser
|
||||
);
|
||||
init_target!(
|
||||
llvm_component = "amdgpu",
|
||||
LLVMInitializeAMDGPUTargetInfo,
|
||||
LLVMInitializeAMDGPUTarget,
|
||||
LLVMInitializeAMDGPUTargetMC,
|
||||
LLVMInitializeAMDGPUAsmPrinter,
|
||||
LLVMInitializeAMDGPUAsmParser
|
||||
);
|
||||
init_target!(
|
||||
llvm_component = "avr",
|
||||
LLVMInitializeAVRTargetInfo,
|
||||
LLVMInitializeAVRTarget,
|
||||
LLVMInitializeAVRTargetMC,
|
||||
LLVMInitializeAVRAsmPrinter,
|
||||
LLVMInitializeAVRAsmParser
|
||||
);
|
||||
init_target!(
|
||||
llvm_component = "mips",
|
||||
LLVMInitializeMipsTargetInfo,
|
||||
LLVMInitializeMipsTarget,
|
||||
LLVMInitializeMipsTargetMC,
|
||||
LLVMInitializeMipsAsmPrinter,
|
||||
LLVMInitializeMipsAsmParser
|
||||
);
|
||||
init_target!(
|
||||
llvm_component = "powerpc",
|
||||
LLVMInitializePowerPCTargetInfo,
|
||||
LLVMInitializePowerPCTarget,
|
||||
LLVMInitializePowerPCTargetMC,
|
||||
LLVMInitializePowerPCAsmPrinter,
|
||||
LLVMInitializePowerPCAsmParser
|
||||
);
|
||||
init_target!(
|
||||
llvm_component = "systemz",
|
||||
LLVMInitializeSystemZTargetInfo,
|
||||
LLVMInitializeSystemZTarget,
|
||||
LLVMInitializeSystemZTargetMC,
|
||||
LLVMInitializeSystemZAsmPrinter,
|
||||
LLVMInitializeSystemZAsmParser
|
||||
);
|
||||
init_target!(
|
||||
llvm_component = "jsbackend",
|
||||
LLVMInitializeJSBackendTargetInfo,
|
||||
LLVMInitializeJSBackendTarget,
|
||||
LLVMInitializeJSBackendTargetMC
|
||||
);
|
||||
init_target!(
|
||||
llvm_component = "msp430",
|
||||
LLVMInitializeMSP430TargetInfo,
|
||||
LLVMInitializeMSP430Target,
|
||||
LLVMInitializeMSP430TargetMC,
|
||||
LLVMInitializeMSP430AsmPrinter
|
||||
);
|
||||
init_target!(
|
||||
all(llvm_component = "msp430", llvm_has_msp430_asm_parser),
|
||||
LLVMInitializeMSP430AsmParser
|
||||
);
|
||||
init_target!(
|
||||
llvm_component = "riscv",
|
||||
LLVMInitializeRISCVTargetInfo,
|
||||
LLVMInitializeRISCVTarget,
|
||||
LLVMInitializeRISCVTargetMC,
|
||||
LLVMInitializeRISCVAsmPrinter,
|
||||
LLVMInitializeRISCVAsmParser
|
||||
);
|
||||
init_target!(
|
||||
llvm_component = "sparc",
|
||||
LLVMInitializeSparcTargetInfo,
|
||||
LLVMInitializeSparcTarget,
|
||||
LLVMInitializeSparcTargetMC,
|
||||
LLVMInitializeSparcAsmPrinter,
|
||||
LLVMInitializeSparcAsmParser
|
||||
);
|
||||
init_target!(
|
||||
llvm_component = "nvptx",
|
||||
LLVMInitializeNVPTXTargetInfo,
|
||||
LLVMInitializeNVPTXTarget,
|
||||
LLVMInitializeNVPTXTargetMC,
|
||||
LLVMInitializeNVPTXAsmPrinter
|
||||
);
|
||||
init_target!(
|
||||
llvm_component = "hexagon",
|
||||
LLVMInitializeHexagonTargetInfo,
|
||||
LLVMInitializeHexagonTarget,
|
||||
LLVMInitializeHexagonTargetMC,
|
||||
LLVMInitializeHexagonAsmPrinter,
|
||||
LLVMInitializeHexagonAsmParser
|
||||
);
|
||||
init_target!(
|
||||
llvm_component = "webassembly",
|
||||
LLVMInitializeWebAssemblyTargetInfo,
|
||||
LLVMInitializeWebAssemblyTarget,
|
||||
LLVMInitializeWebAssemblyTargetMC,
|
||||
LLVMInitializeWebAssemblyAsmPrinter
|
||||
);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue