mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-21 22:34:05 +00:00
Auto merge of #34743 - badboy:llvm-upgrade, r=eddyb
LLVM upgrade As discussed in https://internals.rust-lang.org/t/need-help-with-emscripten-port/3154/46 I'm trying to update the used LLVM checkout in Rust. I basically took @shepmaster's code and applied it on top (though I did the commits manually, the [original commits have better descriptions](https://github.com/rust-lang/rust/compare/master...avr-rust:avr-support). With these changes I was able to build rustc. `make check` throws one last error on `run-pass/issue-28950.rs`. Output: https://gist.github.com/badboy/bcdd3bbde260860b6159aa49070a9052 I took the metadata changes as is and they seem to work, though it now uses the module in another step. I'm not sure if this is the best and correct way. Things to do: * [x] ~~Make `run-pass/issue-28950.rs` pass~~ unrelated * [x] Find out how the `PositionIndependentExecutable` setting is now used * [x] Is the `llvm::legacy` still the right way to do these things? cc @brson @alexcrichton
This commit is contained in:
commit
2c1612c62a
6
configure
vendored
6
configure
vendored
@ -1020,6 +1020,12 @@ then
|
||||
err "bad LLVM version: $LLVM_VERSION, need >=3.7"
|
||||
;;
|
||||
esac
|
||||
|
||||
if "$CFG_LLVM_ROOT/bin/llvm-mc" -help | grep -- "-relocation-model"; then
|
||||
msg "found older llvm-mc"
|
||||
CFG_LLVM_MC_HAS_RELOCATION_MODEL=1
|
||||
putvar CFG_LLVM_MC_HAS_RELOCATION_MODEL
|
||||
fi
|
||||
fi
|
||||
|
||||
# Even when the user overrides the choice of CC, still try to detect
|
||||
|
@ -221,12 +221,19 @@ define CFG_MAKE_TOOLCHAIN
|
||||
LLVM_MC_RELOCATION_MODEL="default"
|
||||
endif
|
||||
|
||||
# LLVM changed this flag in 3.9
|
||||
ifdef CFG_LLVM_MC_HAS_RELOCATION_MODEL
|
||||
LLVM_MC_RELOC_FLAG := -relocation-model=$$(LLVM_MC_RELOCATION_MODEL)
|
||||
else
|
||||
LLVM_MC_RELOC_FLAG := -position-independent
|
||||
endif
|
||||
|
||||
# We're using llvm-mc as our assembler because it supports
|
||||
# .cfi pseudo-ops on mac
|
||||
CFG_ASSEMBLE_$(1)=$$(CPP_$(1)) -E $$(2) | \
|
||||
$$(LLVM_MC_$$(CFG_BUILD)) \
|
||||
-assemble \
|
||||
-relocation-model=$$(LLVM_MC_RELOCATION_MODEL) \
|
||||
$$(LLVM_MC_RELOC_FLAG) \
|
||||
-filetype=obj \
|
||||
-triple=$(1) \
|
||||
-o=$$(1)
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit ac3d1cda612edccb6f1da53cbf7716e248405f3b
|
||||
Subproject commit 8598065bd965d9713bfafb6c1e766d63a7b17b89
|
@ -77,6 +77,13 @@ for lib in out.strip().replace("\n", ' ').split(' '):
|
||||
lib = lib.strip()[2:]
|
||||
elif lib[0] == '-':
|
||||
lib = lib.strip()[1:]
|
||||
# If this actually points at a literal file then we're on MSVC which now
|
||||
# prints full paths, so get just the name of the library and strip off the
|
||||
# trailing ".lib"
|
||||
elif os.path.exists(lib):
|
||||
lib = os.path.basename(lib)[:-4]
|
||||
elif lib[-4:] == '.lib':
|
||||
lib = lib[:-4]
|
||||
f.write("#[link(name = \"" + lib + "\"")
|
||||
if not llvm_shared and 'LLVM' in lib:
|
||||
f.write(", kind = \"static\"")
|
||||
|
@ -20,7 +20,7 @@ pub fn target() -> TargetResult {
|
||||
llvm_target: "aarch64-linux-android".to_string(),
|
||||
target_endian: "little".to_string(),
|
||||
target_pointer_width: "64".to_string(),
|
||||
data_layout: "e-m:e-i64:64-i128:128-n32:64-S128".to_string(),
|
||||
data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
|
||||
arch: "aarch64".to_string(),
|
||||
target_os: "android".to_string(),
|
||||
target_env: "".to_string(),
|
||||
|
@ -18,7 +18,7 @@ pub fn target() -> TargetResult {
|
||||
target_endian: "little".to_string(),
|
||||
target_pointer_width: "64".to_string(),
|
||||
target_env: "gnu".to_string(),
|
||||
data_layout: "e-m:e-i64:64-i128:128-n32:64-S128".to_string(),
|
||||
data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(),
|
||||
arch: "aarch64".to_string(),
|
||||
target_os: "linux".to_string(),
|
||||
target_vendor: "unknown".to_string(),
|
||||
|
@ -13,7 +13,7 @@ extern crate build_helper;
|
||||
|
||||
use std::process::Command;
|
||||
use std::env;
|
||||
use std::path::PathBuf;
|
||||
use std::path::{PathBuf, Path};
|
||||
|
||||
use build_helper::output;
|
||||
|
||||
@ -135,8 +135,17 @@ fn main() {
|
||||
&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_right_matches(".lib")
|
||||
} else if lib.ends_with(".lib") {
|
||||
// Some MSVC libraries just come up with `.lib` tacked on, so chop
|
||||
// that off
|
||||
lib.trim_right_matches(".lib")
|
||||
} else {
|
||||
continue;
|
||||
continue
|
||||
};
|
||||
|
||||
// Don't need or want this library, but LLVM's CMake build system
|
||||
@ -145,7 +154,7 @@ fn main() {
|
||||
// library and it otherwise may just pull in extra dependencies on
|
||||
// libedit which we don't want
|
||||
if name == "LLVMLineEditor" {
|
||||
continue;
|
||||
continue
|
||||
}
|
||||
|
||||
let kind = if name.starts_with("LLVM") {
|
||||
@ -165,7 +174,9 @@ fn main() {
|
||||
let mut cmd = Command::new(&llvm_config);
|
||||
cmd.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..]);
|
||||
} else if is_crossed {
|
||||
if lib.starts_with("-L") {
|
||||
println!("cargo:rustc-link-search=native={}",
|
||||
lib[2..].replace(&host, &target));
|
||||
|
@ -226,7 +226,7 @@ impl Attributes {
|
||||
|
||||
pub fn apply_callsite(&self, idx: usize, callsite: ValueRef) {
|
||||
unsafe {
|
||||
LLVMAddCallSiteAttribute(callsite, idx as c_uint, self.regular.bits());
|
||||
LLVMRustAddCallSiteAttribute(callsite, idx as c_uint, self.regular.bits());
|
||||
if self.dereferenceable_bytes != 0 {
|
||||
LLVMAddDereferenceableCallSiteAttr(callsite, idx as c_uint,
|
||||
self.dereferenceable_bytes);
|
||||
@ -1056,7 +1056,7 @@ extern {
|
||||
pub fn LLVMSetInstrParamAlignment(Instr: ValueRef,
|
||||
index: c_uint,
|
||||
align: c_uint);
|
||||
pub fn LLVMAddCallSiteAttribute(Instr: ValueRef,
|
||||
pub fn LLVMRustAddCallSiteAttribute(Instr: ValueRef,
|
||||
index: c_uint,
|
||||
Val: uint64_t);
|
||||
pub fn LLVMAddDereferenceableCallSiteAttr(Instr: ValueRef,
|
||||
@ -1561,7 +1561,7 @@ extern {
|
||||
Alignment: c_uint)
|
||||
-> ValueRef;
|
||||
|
||||
pub fn LLVMBuildAtomicCmpXchg(B: BuilderRef,
|
||||
pub fn LLVMRustBuildAtomicCmpXchg(B: BuilderRef,
|
||||
LHS: ValueRef,
|
||||
CMP: ValueRef,
|
||||
RHS: ValueRef,
|
||||
@ -1591,9 +1591,6 @@ extern {
|
||||
|
||||
/// Creates target data from a target layout string.
|
||||
pub fn LLVMCreateTargetData(StringRep: *const c_char) -> TargetDataRef;
|
||||
/// Adds the target data to the given pass manager. The pass manager
|
||||
/// references the target data only weakly.
|
||||
pub fn LLVMAddTargetData(TD: TargetDataRef, PM: PassManagerRef);
|
||||
/// Number of bytes clobbered when doing a Store to *T.
|
||||
pub fn LLVMStoreSizeOfType(TD: TargetDataRef, Ty: TypeRef)
|
||||
-> c_ulonglong;
|
||||
@ -2155,6 +2152,7 @@ extern {
|
||||
|
||||
pub fn LLVMRustSetComdat(M: ModuleRef, V: ValueRef, Name: *const c_char);
|
||||
pub fn LLVMRustUnsetComdat(V: ValueRef);
|
||||
pub fn LLVMRustSetModulePIELevel(M: ModuleRef);
|
||||
}
|
||||
|
||||
// LLVM requires symbols from this library, but apparently they're not printed
|
||||
|
@ -24,6 +24,7 @@ use util::fs::link_or_copy;
|
||||
use errors::{self, Handler, Level, DiagnosticBuilder};
|
||||
use errors::emitter::Emitter;
|
||||
use syntax_pos::MultiSpan;
|
||||
use context::{is_pie_binary, get_reloc_model};
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::ffi::{CStr, CString};
|
||||
@ -154,32 +155,11 @@ fn get_llvm_opt_size(optimize: config::OptLevel) -> llvm::CodeGenOptSize {
|
||||
}
|
||||
|
||||
pub fn create_target_machine(sess: &Session) -> TargetMachineRef {
|
||||
let reloc_model_arg = match sess.opts.cg.relocation_model {
|
||||
Some(ref s) => &s[..],
|
||||
None => &sess.target.target.options.relocation_model[..],
|
||||
};
|
||||
let reloc_model = match reloc_model_arg {
|
||||
"pic" => llvm::RelocPIC,
|
||||
"static" => llvm::RelocStatic,
|
||||
"default" => llvm::RelocDefault,
|
||||
"dynamic-no-pic" => llvm::RelocDynamicNoPic,
|
||||
_ => {
|
||||
sess.err(&format!("{:?} is not a valid relocation mode",
|
||||
sess.opts
|
||||
.cg
|
||||
.relocation_model));
|
||||
sess.abort_if_errors();
|
||||
bug!();
|
||||
}
|
||||
};
|
||||
let reloc_model = get_reloc_model(sess);
|
||||
|
||||
let opt_level = get_llvm_opt_level(sess.opts.optimize);
|
||||
let use_softfp = sess.opts.cg.soft_float;
|
||||
|
||||
let any_library = sess.crate_types.borrow().iter().any(|ty| {
|
||||
*ty != config::CrateTypeExecutable
|
||||
});
|
||||
|
||||
let ffunction_sections = sess.target.target.options.function_sections;
|
||||
let fdata_sections = ffunction_sections;
|
||||
|
||||
@ -220,7 +200,7 @@ pub fn create_target_machine(sess: &Session) -> TargetMachineRef {
|
||||
reloc_model,
|
||||
opt_level,
|
||||
use_softfp,
|
||||
!any_library && reloc_model == llvm::RelocPIC,
|
||||
is_pie_binary(sess),
|
||||
ffunction_sections,
|
||||
fdata_sections,
|
||||
)
|
||||
|
@ -1083,7 +1083,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
failure_order: AtomicOrdering,
|
||||
weak: llvm::Bool) -> ValueRef {
|
||||
unsafe {
|
||||
llvm::LLVMBuildAtomicCmpXchg(self.llbuilder, dst, cmp, src,
|
||||
llvm::LLVMRustBuildAtomicCmpXchg(self.llbuilder, dst, cmp, src,
|
||||
order, failure_order, weak)
|
||||
}
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ use rustc::ty::subst::{Substs, VecPerParamSpace};
|
||||
use rustc::ty::{self, Ty, TyCtxt};
|
||||
use session::config::NoDebugInfo;
|
||||
use session::Session;
|
||||
use session::config;
|
||||
use symbol_map::SymbolMap;
|
||||
use util::sha2::Sha256;
|
||||
use util::nodemap::{NodeMap, NodeSet, DefIdMap, FnvHashMap, FnvHashSet};
|
||||
@ -322,6 +323,38 @@ impl<'a, 'tcx> Iterator for CrateContextMaybeIterator<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_reloc_model(sess: &Session) -> llvm::RelocMode {
|
||||
let reloc_model_arg = match sess.opts.cg.relocation_model {
|
||||
Some(ref s) => &s[..],
|
||||
None => &sess.target.target.options.relocation_model[..],
|
||||
};
|
||||
|
||||
match reloc_model_arg {
|
||||
"pic" => llvm::RelocPIC,
|
||||
"static" => llvm::RelocStatic,
|
||||
"default" => llvm::RelocDefault,
|
||||
"dynamic-no-pic" => llvm::RelocDynamicNoPic,
|
||||
_ => {
|
||||
sess.err(&format!("{:?} is not a valid relocation mode",
|
||||
sess.opts
|
||||
.cg
|
||||
.relocation_model));
|
||||
sess.abort_if_errors();
|
||||
bug!();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn is_any_library(sess: &Session) -> bool {
|
||||
sess.crate_types.borrow().iter().any(|ty| {
|
||||
*ty != config::CrateTypeExecutable
|
||||
})
|
||||
}
|
||||
|
||||
pub fn is_pie_binary(sess: &Session) -> bool {
|
||||
!is_any_library(sess) && get_reloc_model(sess) == llvm::RelocPIC
|
||||
}
|
||||
|
||||
unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (ContextRef, ModuleRef) {
|
||||
let llcx = llvm::LLVMContextCreate();
|
||||
let mod_name = CString::new(mod_name).unwrap();
|
||||
@ -337,7 +370,25 @@ unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (ContextR
|
||||
let data_layout = str::from_utf8(CStr::from_ptr(data_layout).to_bytes())
|
||||
.ok().expect("got a non-UTF8 data-layout from LLVM");
|
||||
|
||||
if sess.target.target.data_layout != data_layout {
|
||||
// Unfortunately LLVM target specs change over time, and right now we
|
||||
// don't have proper support to work with any more than one
|
||||
// `data_layout` than the one that is in the rust-lang/rust repo. If
|
||||
// this compiler is configured against a custom LLVM, we may have a
|
||||
// differing data layout, even though we should update our own to use
|
||||
// that one.
|
||||
//
|
||||
// As an interim hack, if CFG_LLVM_ROOT is not an empty string then we
|
||||
// disable this check entirely as we may be configured with something
|
||||
// that has a different target layout.
|
||||
//
|
||||
// Unsure if this will actually cause breakage when rustc is configured
|
||||
// as such.
|
||||
//
|
||||
// FIXME(#34960)
|
||||
let cfg_llvm_root = option_env!("CFG_LLVM_ROOT").unwrap_or("");
|
||||
let custom_llvm_used = cfg_llvm_root.trim() != "";
|
||||
|
||||
if !custom_llvm_used && sess.target.target.data_layout != data_layout {
|
||||
bug!("data-layout for builtin `{}` target, `{}`, \
|
||||
differs from LLVM default, `{}`",
|
||||
sess.target.target.llvm_target,
|
||||
@ -352,6 +403,11 @@ unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (ContextR
|
||||
let llvm_target = sess.target.target.llvm_target.as_bytes();
|
||||
let llvm_target = CString::new(llvm_target).unwrap();
|
||||
llvm::LLVMRustSetNormalizedTarget(llmod, llvm_target.as_ptr());
|
||||
|
||||
if is_pie_binary(sess) {
|
||||
llvm::LLVMRustSetModulePIELevel(llmod);
|
||||
}
|
||||
|
||||
(llcx, llmod)
|
||||
}
|
||||
|
||||
@ -558,7 +614,9 @@ impl<'tcx> LocalCrateContext<'tcx> {
|
||||
&llmod_id[..]);
|
||||
|
||||
let dbg_cx = if shared.tcx.sess.opts.debuginfo != NoDebugInfo {
|
||||
Some(debuginfo::CrateDebugContext::new(llmod))
|
||||
let dctx = debuginfo::CrateDebugContext::new(llmod);
|
||||
debuginfo::metadata::compile_unit_metadata(shared, &dctx, shared.tcx.sess);
|
||||
Some(dctx)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
@ -18,7 +18,9 @@ use super::utils::{debug_context, DIB, span_start, bytes_to_bits, size_and_align
|
||||
fn_should_be_ignored, is_node_local_to_unit};
|
||||
use super::namespace::mangled_name_of_item;
|
||||
use super::type_names::{compute_debuginfo_type_name, push_debuginfo_type_name};
|
||||
use super::{declare_local, VariableKind, VariableAccess};
|
||||
use super::{declare_local, VariableKind, VariableAccess, CrateDebugContext};
|
||||
use context::SharedCrateContext;
|
||||
use session::Session;
|
||||
|
||||
use llvm::{self, ValueRef};
|
||||
use llvm::debuginfo::{DIType, DIFile, DIScope, DIDescriptor, DICompositeType};
|
||||
@ -48,7 +50,6 @@ use syntax::ast;
|
||||
use syntax::parse::token;
|
||||
use syntax_pos::{self, Span};
|
||||
|
||||
|
||||
// From DWARF 5.
|
||||
// See http://www.dwarfstd.org/ShowIssue.php?issue=140129.1
|
||||
const DW_LANG_RUST: c_uint = 0x1c;
|
||||
@ -67,7 +68,6 @@ pub const UNKNOWN_LINE_NUMBER: c_uint = 0;
|
||||
pub const UNKNOWN_COLUMN_NUMBER: c_uint = 0;
|
||||
|
||||
// ptr::null() doesn't work :(
|
||||
pub const NO_FILE_METADATA: DIFile = (0 as DIFile);
|
||||
pub const NO_SCOPE_METADATA: DIScope = (0 as DIScope);
|
||||
|
||||
const FLAGS_NONE: c_uint = 0;
|
||||
@ -615,7 +615,7 @@ fn subroutine_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||
unsafe {
|
||||
llvm::LLVMDIBuilderCreateSubroutineType(
|
||||
DIB(cx),
|
||||
NO_FILE_METADATA,
|
||||
unknown_file_metadata(cx),
|
||||
create_DIArray(DIB(cx), &signature_metadata[..]))
|
||||
},
|
||||
false);
|
||||
@ -652,6 +652,7 @@ fn trait_pointer_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||
let (containing_scope, _) = get_namespace_and_span_for_item(cx, def_id);
|
||||
|
||||
let trait_llvm_type = type_of::type_of(cx, trait_object_type);
|
||||
let file_metadata = unknown_file_metadata(cx);
|
||||
|
||||
composite_type_metadata(cx,
|
||||
trait_llvm_type,
|
||||
@ -659,7 +660,7 @@ fn trait_pointer_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||
unique_type_id,
|
||||
&[],
|
||||
containing_scope,
|
||||
NO_FILE_METADATA,
|
||||
file_metadata,
|
||||
syntax_pos::DUMMY_SP)
|
||||
}
|
||||
|
||||
@ -981,14 +982,17 @@ fn pointer_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||
return ptr_metadata;
|
||||
}
|
||||
|
||||
pub fn compile_unit_metadata(cx: &CrateContext) -> DIDescriptor {
|
||||
let work_dir = &cx.sess().working_dir;
|
||||
let compile_unit_name = match cx.sess().local_crate_source_file {
|
||||
None => fallback_path(cx),
|
||||
pub fn compile_unit_metadata(scc: &SharedCrateContext,
|
||||
debug_context: &CrateDebugContext,
|
||||
sess: &Session)
|
||||
-> DIDescriptor {
|
||||
let work_dir = &sess.working_dir;
|
||||
let compile_unit_name = match sess.local_crate_source_file {
|
||||
None => fallback_path(scc),
|
||||
Some(ref abs_path) => {
|
||||
if abs_path.is_relative() {
|
||||
cx.sess().warn("debuginfo: Invalid path to crate's local root source file!");
|
||||
fallback_path(cx)
|
||||
sess.warn("debuginfo: Invalid path to crate's local root source file!");
|
||||
fallback_path(scc)
|
||||
} else {
|
||||
match abs_path.strip_prefix(work_dir) {
|
||||
Ok(ref p) if p.is_relative() => {
|
||||
@ -998,7 +1002,7 @@ pub fn compile_unit_metadata(cx: &CrateContext) -> DIDescriptor {
|
||||
path2cstr(&Path::new(".").join(p))
|
||||
}
|
||||
}
|
||||
_ => fallback_path(cx)
|
||||
_ => fallback_path(scc)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1015,19 +1019,19 @@ pub fn compile_unit_metadata(cx: &CrateContext) -> DIDescriptor {
|
||||
let split_name = "\0";
|
||||
return unsafe {
|
||||
llvm::LLVMDIBuilderCreateCompileUnit(
|
||||
debug_context(cx).builder,
|
||||
debug_context.builder,
|
||||
DW_LANG_RUST,
|
||||
compile_unit_name,
|
||||
work_dir.as_ptr(),
|
||||
producer.as_ptr(),
|
||||
cx.sess().opts.optimize != config::OptLevel::No,
|
||||
sess.opts.optimize != config::OptLevel::No,
|
||||
flags.as_ptr() as *const _,
|
||||
0,
|
||||
split_name.as_ptr() as *const _)
|
||||
};
|
||||
|
||||
fn fallback_path(cx: &CrateContext) -> CString {
|
||||
CString::new(cx.link_meta().crate_name.clone()).unwrap()
|
||||
fn fallback_path(scc: &SharedCrateContext) -> CString {
|
||||
CString::new(scc.link_meta().crate_name.clone()).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
@ -1624,7 +1628,7 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||
DIB(cx),
|
||||
containing_scope,
|
||||
name.as_ptr(),
|
||||
NO_FILE_METADATA,
|
||||
file_metadata,
|
||||
UNKNOWN_LINE_NUMBER,
|
||||
bytes_to_bits(discriminant_size),
|
||||
bytes_to_bits(discriminant_align),
|
||||
@ -1770,7 +1774,7 @@ fn set_members_of_composite_type(cx: &CrateContext,
|
||||
DIB(cx),
|
||||
composite_type_metadata,
|
||||
member_name.as_ptr(),
|
||||
NO_FILE_METADATA,
|
||||
unknown_file_metadata(cx),
|
||||
UNKNOWN_LINE_NUMBER,
|
||||
bytes_to_bits(member_size),
|
||||
bytes_to_bits(member_align),
|
||||
@ -1813,7 +1817,7 @@ fn create_struct_stub(cx: &CrateContext,
|
||||
DIB(cx),
|
||||
containing_scope,
|
||||
name.as_ptr(),
|
||||
NO_FILE_METADATA,
|
||||
unknown_file_metadata(cx),
|
||||
UNKNOWN_LINE_NUMBER,
|
||||
bytes_to_bits(struct_size),
|
||||
bytes_to_bits(struct_align),
|
||||
@ -1853,7 +1857,7 @@ pub fn create_global_var_metadata(cx: &CrateContext,
|
||||
let loc = span_start(cx, span);
|
||||
(file_metadata(cx, &loc.file.name, &loc.file.abs_path), loc.line as c_uint)
|
||||
} else {
|
||||
(NO_FILE_METADATA, UNKNOWN_LINE_NUMBER)
|
||||
(unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER)
|
||||
};
|
||||
|
||||
let is_local_to_unit = is_node_local_to_unit(cx, node_id);
|
||||
|
@ -18,7 +18,7 @@ use self::utils::{DIB, span_start, create_DIArray, is_node_local_to_unit};
|
||||
use self::namespace::mangled_name_of_item;
|
||||
use self::type_names::compute_debuginfo_type_name;
|
||||
use self::metadata::{type_metadata, diverging_type_metadata};
|
||||
use self::metadata::{file_metadata, scope_metadata, TypeMap, compile_unit_metadata};
|
||||
use self::metadata::{file_metadata, scope_metadata, TypeMap};
|
||||
use self::source_loc::InternalDebugLocation::{self, UnknownLocation};
|
||||
|
||||
use llvm;
|
||||
@ -50,7 +50,7 @@ pub mod gdb;
|
||||
mod utils;
|
||||
mod namespace;
|
||||
mod type_names;
|
||||
mod metadata;
|
||||
pub mod metadata;
|
||||
mod create_scope_map;
|
||||
mod source_loc;
|
||||
|
||||
@ -168,7 +168,6 @@ pub fn finalize(cx: &CrateContext) {
|
||||
}
|
||||
|
||||
debug!("finalize");
|
||||
let _ = compile_unit_metadata(cx);
|
||||
|
||||
if gdb::needs_gdb_debug_scripts_section(cx) {
|
||||
// Add a .debug_gdb_scripts section to this compile-unit. This will
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
// Namespace Handling.
|
||||
|
||||
use super::metadata::{file_metadata, NO_FILE_METADATA, UNKNOWN_LINE_NUMBER};
|
||||
use super::metadata::{file_metadata, unknown_file_metadata, UNKNOWN_LINE_NUMBER};
|
||||
use super::utils::{DIB, debug_context, span_start};
|
||||
|
||||
use llvm;
|
||||
@ -74,7 +74,7 @@ pub fn item_namespace(ccx: &CrateContext, def_id: DefId) -> DIScope {
|
||||
let loc = span_start(ccx, span);
|
||||
(file_metadata(ccx, &loc.file.name, &loc.file.abs_path), loc.line as c_uint)
|
||||
} else {
|
||||
(NO_FILE_METADATA, UNKNOWN_LINE_NUMBER)
|
||||
(unknown_file_metadata(ccx), UNKNOWN_LINE_NUMBER)
|
||||
};
|
||||
|
||||
let scope = unsafe {
|
||||
|
2
src/llvm
2
src/llvm
@ -1 +1 @@
|
||||
Subproject commit 7ca76af03bb04659562890d6b4f223fffe0d748f
|
||||
Subproject commit d1cc48989b13780f21c408fef17dceb104a09c9d
|
@ -43,11 +43,19 @@ LLVMRustOpenArchive(char *path) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#if LLVM_VERSION_MINOR <= 8
|
||||
ErrorOr<std::unique_ptr<Archive>> archive_or =
|
||||
#else
|
||||
Expected<std::unique_ptr<Archive>> archive_or =
|
||||
#endif
|
||||
Archive::create(buf_or.get()->getMemBufferRef());
|
||||
|
||||
if (!archive_or) {
|
||||
#if LLVM_VERSION_MINOR <= 8
|
||||
LLVMRustSetLastError(archive_or.getError().message().c_str());
|
||||
#else
|
||||
LLVMRustSetLastError(toString(archive_or.takeError()).c_str());
|
||||
#endif
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -65,22 +73,39 @@ LLVMRustDestroyArchive(RustArchive *ar) {
|
||||
struct RustArchiveIterator {
|
||||
Archive::child_iterator cur;
|
||||
Archive::child_iterator end;
|
||||
#if LLVM_VERSION_MINOR >= 9
|
||||
Error err;
|
||||
#endif
|
||||
};
|
||||
|
||||
extern "C" RustArchiveIterator*
|
||||
LLVMRustArchiveIteratorNew(RustArchive *ra) {
|
||||
Archive *ar = ra->getBinary();
|
||||
RustArchiveIterator *rai = new RustArchiveIterator();
|
||||
#if LLVM_VERSION_MINOR <= 8
|
||||
rai->cur = ar->child_begin();
|
||||
#else
|
||||
rai->cur = ar->child_begin(rai->err);
|
||||
if (rai->err) {
|
||||
LLVMRustSetLastError(toString(std::move(rai->err)).c_str());
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
rai->end = ar->child_end();
|
||||
return rai;
|
||||
}
|
||||
|
||||
extern "C" const Archive::Child*
|
||||
LLVMRustArchiveIteratorNext(RustArchiveIterator *rai) {
|
||||
#if LLVM_VERSION_MINOR >= 9
|
||||
if (rai->err) {
|
||||
LLVMRustSetLastError(toString(std::move(rai->err)).c_str());
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
if (rai->cur == rai->end)
|
||||
return NULL;
|
||||
#if LLVM_VERSION_MINOR >= 8
|
||||
#if LLVM_VERSION_MINOR == 8
|
||||
const ErrorOr<Archive::Child>* cur = rai->cur.operator->();
|
||||
if (!*cur) {
|
||||
LLVMRustSetLastError(cur->getError().message().c_str());
|
||||
@ -150,19 +175,40 @@ LLVMRustWriteArchive(char *Dst,
|
||||
const LLVMRustArchiveMember **NewMembers,
|
||||
bool WriteSymbtab,
|
||||
Archive::Kind Kind) {
|
||||
|
||||
#if LLVM_VERSION_MINOR <= 8
|
||||
std::vector<NewArchiveIterator> Members;
|
||||
#else
|
||||
std::vector<NewArchiveMember> Members;
|
||||
#endif
|
||||
|
||||
for (size_t i = 0; i < NumMembers; i++) {
|
||||
auto Member = NewMembers[i];
|
||||
assert(Member->name);
|
||||
if (Member->filename) {
|
||||
#if LLVM_VERSION_MINOR >= 8
|
||||
#if LLVM_VERSION_MINOR >= 9
|
||||
Expected<NewArchiveMember> MOrErr = NewArchiveMember::getFile(Member->filename, true);
|
||||
if (!MOrErr) {
|
||||
LLVMRustSetLastError(toString(MOrErr.takeError()).c_str());
|
||||
return -1;
|
||||
}
|
||||
Members.push_back(std::move(*MOrErr));
|
||||
#elif LLVM_VERSION_MINOR == 8
|
||||
Members.push_back(NewArchiveIterator(Member->filename));
|
||||
#else
|
||||
Members.push_back(NewArchiveIterator(Member->filename, Member->name));
|
||||
#endif
|
||||
} else {
|
||||
#if LLVM_VERSION_MINOR <= 8
|
||||
Members.push_back(NewArchiveIterator(Member->child, Member->name));
|
||||
#else
|
||||
Expected<NewArchiveMember> MOrErr = NewArchiveMember::getOldMember(Member->child, true);
|
||||
if (!MOrErr) {
|
||||
LLVMRustSetLastError(toString(MOrErr.takeError()).c_str());
|
||||
return -1;
|
||||
}
|
||||
Members.push_back(std::move(*MOrErr));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#if LLVM_VERSION_MINOR >= 8
|
||||
|
@ -167,12 +167,35 @@ LLVMRustCreateTargetMachine(const char *triple,
|
||||
const char *cpu,
|
||||
const char *feature,
|
||||
CodeModel::Model CM,
|
||||
Reloc::Model RM,
|
||||
LLVMRelocMode Reloc,
|
||||
CodeGenOpt::Level OptLevel,
|
||||
bool UseSoftFloat,
|
||||
bool PositionIndependentExecutable,
|
||||
bool FunctionSections,
|
||||
bool DataSections) {
|
||||
|
||||
#if LLVM_VERSION_MINOR <= 8
|
||||
Reloc::Model RM;
|
||||
#else
|
||||
Optional<Reloc::Model> RM;
|
||||
#endif
|
||||
switch (Reloc){
|
||||
case LLVMRelocStatic:
|
||||
RM = Reloc::Static;
|
||||
break;
|
||||
case LLVMRelocPIC:
|
||||
RM = Reloc::PIC_;
|
||||
break;
|
||||
case LLVMRelocDynamicNoPic:
|
||||
RM = Reloc::DynamicNoPIC;
|
||||
break;
|
||||
default:
|
||||
#if LLVM_VERSION_MINOR <= 8
|
||||
RM = Reloc::Default;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
std::string Error;
|
||||
Triple Trip(Triple::normalize(triple));
|
||||
const llvm::Target *TheTarget = TargetRegistry::lookupTarget(Trip.getTriple(),
|
||||
@ -188,7 +211,10 @@ LLVMRustCreateTargetMachine(const char *triple,
|
||||
}
|
||||
|
||||
TargetOptions Options;
|
||||
#if LLVM_VERSION_MINOR <= 8
|
||||
Options.PositionIndependentExecutable = PositionIndependentExecutable;
|
||||
#endif
|
||||
|
||||
Options.FloatABIType = FloatABI::Default;
|
||||
if (UseSoftFloat) {
|
||||
Options.FloatABIType = FloatABI::Soft;
|
||||
@ -267,7 +293,7 @@ LLVMRustAddLibraryInfo(LLVMPassManagerRef PMB,
|
||||
// similar code in clang's BackendUtil.cpp file.
|
||||
extern "C" void
|
||||
LLVMRustRunFunctionPassManager(LLVMPassManagerRef PM, LLVMModuleRef M) {
|
||||
FunctionPassManager *P = unwrap<FunctionPassManager>(PM);
|
||||
llvm::legacy::FunctionPassManager *P = unwrap<llvm::legacy::FunctionPassManager>(PM);
|
||||
P->doInitialization();
|
||||
for (Module::iterator I = unwrap(M)->begin(),
|
||||
E = unwrap(M)->end(); I != E; ++I)
|
||||
@ -294,7 +320,7 @@ LLVMRustWriteOutputFile(LLVMTargetMachineRef Target,
|
||||
LLVMModuleRef M,
|
||||
const char *path,
|
||||
TargetMachine::CodeGenFileType FileType) {
|
||||
PassManager *PM = unwrap<PassManager>(PMR);
|
||||
llvm::legacy::PassManager *PM = unwrap<llvm::legacy::PassManager>(PMR);
|
||||
|
||||
std::string ErrorInfo;
|
||||
std::error_code EC;
|
||||
@ -320,7 +346,7 @@ extern "C" void
|
||||
LLVMRustPrintModule(LLVMPassManagerRef PMR,
|
||||
LLVMModuleRef M,
|
||||
const char* path) {
|
||||
PassManager *PM = unwrap<PassManager>(PMR);
|
||||
llvm::legacy::PassManager *PM = unwrap<llvm::legacy::PassManager>(PMR);
|
||||
std::string ErrorInfo;
|
||||
|
||||
std::error_code EC;
|
||||
@ -358,9 +384,24 @@ LLVMRustAddAlwaysInlinePass(LLVMPassManagerBuilderRef PMB, bool AddLifetimes) {
|
||||
|
||||
extern "C" void
|
||||
LLVMRustRunRestrictionPass(LLVMModuleRef M, char **symbols, size_t len) {
|
||||
PassManager passes;
|
||||
llvm::legacy::PassManager passes;
|
||||
|
||||
#if LLVM_VERSION_MINOR <= 8
|
||||
ArrayRef<const char*> ref(symbols, len);
|
||||
passes.add(llvm::createInternalizePass(ref));
|
||||
#else
|
||||
auto PreserveFunctions = [=](const GlobalValue &GV) {
|
||||
for (size_t i=0; i<len; i++) {
|
||||
if (GV.getName() == symbols[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
passes.add(llvm::createInternalizePass(PreserveFunctions));
|
||||
#endif
|
||||
|
||||
passes.run(*unwrap(M));
|
||||
}
|
||||
|
||||
@ -396,3 +437,10 @@ extern "C" LLVMTargetDataRef
|
||||
LLVMRustGetModuleDataLayout(LLVMModuleRef M) {
|
||||
return wrap(&unwrap(M)->getDataLayout());
|
||||
}
|
||||
|
||||
extern "C" void
|
||||
LLVMRustSetModulePIELevel(LLVMModuleRef M) {
|
||||
#if LLVM_VERSION_MINOR >= 9
|
||||
unwrap(M)->setPIELevel(PIELevel::Level::Large);
|
||||
#endif
|
||||
}
|
||||
|
@ -99,7 +99,7 @@ extern "C" LLVMTypeRef LLVMMetadataTypeInContext(LLVMContextRef C) {
|
||||
return wrap(Type::getMetadataTy(*unwrap(C)));
|
||||
}
|
||||
|
||||
extern "C" void LLVMAddCallSiteAttribute(LLVMValueRef Instr, unsigned index, uint64_t Val) {
|
||||
extern "C" void LLVMRustAddCallSiteAttribute(LLVMValueRef Instr, unsigned index, uint64_t Val) {
|
||||
CallSite Call = CallSite(unwrap<Instruction>(Instr));
|
||||
AttrBuilder B;
|
||||
B.addRawValue(Val);
|
||||
@ -203,7 +203,7 @@ extern "C" LLVMValueRef LLVMBuildAtomicStore(LLVMBuilderRef B,
|
||||
return wrap(unwrap(B)->Insert(si));
|
||||
}
|
||||
|
||||
extern "C" LLVMValueRef LLVMBuildAtomicCmpXchg(LLVMBuilderRef B,
|
||||
extern "C" LLVMValueRef LLVMRustBuildAtomicCmpXchg(LLVMBuilderRef B,
|
||||
LLVMValueRef target,
|
||||
LLVMValueRef old,
|
||||
LLVMValueRef source,
|
||||
|
@ -1,4 +1,4 @@
|
||||
# If this file is modified, then llvm will be forcibly cleaned and then rebuilt.
|
||||
# The actual contents of this file do not matter, but to trigger a change on the
|
||||
# build bots then the contents should be changed so git updates the mtime.
|
||||
2016-06-23
|
||||
2016-07-25b
|
||||
|
@ -1,21 +0,0 @@
|
||||
-include ../tools.mk
|
||||
|
||||
# FIXME: ignore freebsd
|
||||
# This is a basic test of LLVM ExecutionEngine functionality using compiled
|
||||
# Rust code built using the `rustc` crate.
|
||||
|
||||
ifeq ($(filter executionengine,$(LLVM_COMPONENTS)),executionengine)
|
||||
|
||||
ifneq ($(shell uname),FreeBSD)
|
||||
all:
|
||||
$(RUSTC) test.rs
|
||||
$(call RUN,test $(RUSTC))
|
||||
else
|
||||
all:
|
||||
|
||||
endif
|
||||
|
||||
else
|
||||
all:
|
||||
|
||||
endif
|
@ -1,282 +0,0 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(rustc_private)]
|
||||
#![feature(libc)]
|
||||
|
||||
extern crate libc;
|
||||
extern crate rustc;
|
||||
extern crate rustc_driver;
|
||||
extern crate rustc_lint;
|
||||
extern crate rustc_llvm as llvm;
|
||||
extern crate rustc_metadata;
|
||||
extern crate rustc_resolve;
|
||||
extern crate rustc_errors;
|
||||
extern crate rustc_errors as errors;
|
||||
extern crate rustc_trans;
|
||||
#[macro_use] extern crate syntax;
|
||||
|
||||
use std::ffi::{CStr, CString};
|
||||
use std::mem::transmute;
|
||||
use std::path::PathBuf;
|
||||
use std::rc::Rc;
|
||||
use std::thread::Builder;
|
||||
|
||||
use rustc::dep_graph::DepGraph;
|
||||
use rustc::hir::map as ast_map;
|
||||
use rustc::middle::cstore::LinkagePreference;
|
||||
use rustc::ty;
|
||||
use rustc::session::config::{self, basic_options, build_configuration, Input, Options};
|
||||
use rustc::session::build_session;
|
||||
use rustc_driver::{driver, abort_on_err};
|
||||
use rustc_resolve::MakeGlobMap;
|
||||
use rustc_metadata::cstore::CStore;
|
||||
use rustc_trans::ModuleSource;
|
||||
use libc::c_void;
|
||||
|
||||
use rustc_errors::registry::Registry;
|
||||
|
||||
fn main() {
|
||||
// Currently trips an assertion on i686-msvc, presumably because the support
|
||||
// in LLVM is a little young.
|
||||
if cfg!(target_env = "msvc") && cfg!(target_arch = "x86") {
|
||||
return
|
||||
}
|
||||
|
||||
let program = r#"
|
||||
#[no_mangle]
|
||||
pub static TEST_STATIC: i32 = 42;
|
||||
"#;
|
||||
|
||||
let program2 = r#"
|
||||
#[no_mangle]
|
||||
pub fn test_add(a: i32, b: i32) -> i32 { a + b }
|
||||
"#;
|
||||
|
||||
let mut path = match std::env::args().nth(2) {
|
||||
Some(path) => PathBuf::from(&path),
|
||||
None => panic!("missing rustc path")
|
||||
};
|
||||
|
||||
// Remove two segments from rustc path to get sysroot.
|
||||
path.pop();
|
||||
path.pop();
|
||||
|
||||
let mut ee = ExecutionEngine::new(program, path);
|
||||
|
||||
let test_static = match ee.get_global("TEST_STATIC") {
|
||||
Some(g) => g as *const i32,
|
||||
None => panic!("failed to get global")
|
||||
};
|
||||
|
||||
assert_eq!(unsafe { *test_static }, 42);
|
||||
|
||||
ee.add_module(program2);
|
||||
|
||||
let test_add: fn(i32, i32) -> i32;
|
||||
|
||||
test_add = match ee.get_function("test_add") {
|
||||
Some(f) => unsafe { transmute(f) },
|
||||
None => panic!("failed to get function")
|
||||
};
|
||||
|
||||
assert_eq!(test_add(1, 2), 3);
|
||||
}
|
||||
|
||||
struct ExecutionEngine {
|
||||
ee: llvm::ExecutionEngineRef,
|
||||
modules: Vec<llvm::ModuleRef>,
|
||||
sysroot: PathBuf,
|
||||
}
|
||||
|
||||
impl ExecutionEngine {
|
||||
pub fn new(program: &str, sysroot: PathBuf) -> ExecutionEngine {
|
||||
let (llmod, deps) = compile_program(program, sysroot.clone())
|
||||
.expect("failed to compile program");
|
||||
|
||||
let ee = unsafe { llvm::LLVMBuildExecutionEngine(llmod) };
|
||||
|
||||
if ee.is_null() {
|
||||
panic!("Failed to create ExecutionEngine: {}", llvm_error());
|
||||
}
|
||||
|
||||
let ee = ExecutionEngine{
|
||||
ee: ee,
|
||||
modules: vec![llmod],
|
||||
sysroot: sysroot,
|
||||
};
|
||||
|
||||
ee.load_deps(&deps);
|
||||
ee
|
||||
}
|
||||
|
||||
pub fn add_module(&mut self, program: &str) {
|
||||
let (llmod, deps) = compile_program(program, self.sysroot.clone())
|
||||
.expect("failed to compile program in add_module");
|
||||
|
||||
unsafe { llvm::LLVMExecutionEngineAddModule(self.ee, llmod); }
|
||||
|
||||
self.modules.push(llmod);
|
||||
self.load_deps(&deps);
|
||||
}
|
||||
|
||||
/// Returns a raw pointer to the named function.
|
||||
pub fn get_function(&mut self, name: &str) -> Option<*const c_void> {
|
||||
let s = CString::new(name.as_bytes()).unwrap();
|
||||
|
||||
for &m in &self.modules {
|
||||
let fv = unsafe { llvm::LLVMGetNamedFunction(m, s.as_ptr()) };
|
||||
|
||||
if !fv.is_null() {
|
||||
let fp = unsafe { llvm::LLVMGetPointerToGlobal(self.ee, fv) };
|
||||
|
||||
assert!(!fp.is_null());
|
||||
return Some(fp);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
/// Returns a raw pointer to the named global item.
|
||||
pub fn get_global(&mut self, name: &str) -> Option<*const c_void> {
|
||||
let s = CString::new(name.as_bytes()).unwrap();
|
||||
|
||||
for &m in &self.modules {
|
||||
let gv = unsafe { llvm::LLVMGetNamedGlobal(m, s.as_ptr()) };
|
||||
|
||||
if !gv.is_null() {
|
||||
let gp = unsafe { llvm::LLVMGetPointerToGlobal(self.ee, gv) };
|
||||
|
||||
assert!(!gp.is_null());
|
||||
return Some(gp);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
/// Loads all dependencies of compiled code.
|
||||
/// Expects a series of paths to dynamic library files.
|
||||
fn load_deps(&self, deps: &[PathBuf]) {
|
||||
for path in deps {
|
||||
let s = match path.as_os_str().to_str() {
|
||||
Some(s) => s,
|
||||
None => panic!(
|
||||
"Could not convert crate path to UTF-8 string: {:?}", path)
|
||||
};
|
||||
let cs = CString::new(s).unwrap();
|
||||
|
||||
let res = unsafe { llvm::LLVMRustLoadDynamicLibrary(cs.as_ptr()) };
|
||||
|
||||
if res == 0 {
|
||||
panic!("Failed to load crate {:?}: {}",
|
||||
path.display(), llvm_error());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for ExecutionEngine {
|
||||
fn drop(&mut self) {
|
||||
unsafe { llvm::LLVMDisposeExecutionEngine(self.ee) };
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns last error from LLVM wrapper code.
|
||||
fn llvm_error() -> String {
|
||||
String::from_utf8_lossy(
|
||||
unsafe { CStr::from_ptr(llvm::LLVMRustGetLastError()).to_bytes() })
|
||||
.into_owned()
|
||||
}
|
||||
|
||||
fn build_exec_options(sysroot: PathBuf) -> Options {
|
||||
let mut opts = basic_options();
|
||||
|
||||
// librustc derives sysroot from the executable name.
|
||||
// Since we are not rustc, we must specify it.
|
||||
opts.maybe_sysroot = Some(sysroot);
|
||||
|
||||
// Prefer faster build time
|
||||
opts.optimize = config::OptLevel::No;
|
||||
|
||||
// Don't require a `main` function
|
||||
opts.crate_types = vec![config::CrateTypeDylib];
|
||||
|
||||
opts
|
||||
}
|
||||
|
||||
/// Compiles input up to phase 4, translation to LLVM.
|
||||
///
|
||||
/// Returns the LLVM `ModuleRef` and a series of paths to dynamic libraries
|
||||
/// for crates used in the given input.
|
||||
fn compile_program(input: &str, sysroot: PathBuf)
|
||||
-> Option<(llvm::ModuleRef, Vec<PathBuf>)> {
|
||||
let input = Input::Str {
|
||||
name: driver::anon_src(),
|
||||
input: input.to_string(),
|
||||
};
|
||||
let thread = Builder::new().name("compile_program".to_string());
|
||||
|
||||
let handle = thread.spawn(move || {
|
||||
let opts = build_exec_options(sysroot);
|
||||
let dep_graph = DepGraph::new(opts.build_dep_graph());
|
||||
let cstore = Rc::new(CStore::new(&dep_graph));
|
||||
let sess = build_session(opts,
|
||||
&dep_graph,
|
||||
None,
|
||||
Registry::new(&rustc::DIAGNOSTICS),
|
||||
cstore.clone());
|
||||
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
|
||||
|
||||
let cfg = build_configuration(&sess);
|
||||
|
||||
let id = "input".to_string();
|
||||
|
||||
let krate = panictry!(driver::phase_1_parse_input(&sess, cfg, &input));
|
||||
|
||||
let driver::ExpansionResult { defs, analysis, resolutions, mut hir_forest, .. } = {
|
||||
driver::phase_2_configure_and_expand(
|
||||
&sess, &cstore, krate, &id, None, MakeGlobMap::No, |_| Ok(()),
|
||||
).expect("phase_2 returned `None`")
|
||||
};
|
||||
|
||||
let arenas = ty::CtxtArenas::new();
|
||||
let ast_map = ast_map::map_crate(&mut hir_forest, defs);
|
||||
|
||||
abort_on_err(driver::phase_3_run_analysis_passes(
|
||||
&sess, ast_map, analysis, resolutions, &arenas, &id,
|
||||
|tcx, mir_map, analysis, _| {
|
||||
|
||||
let trans = driver::phase_4_translate_to_llvm(tcx, mir_map.unwrap(), analysis);
|
||||
|
||||
let crates = tcx.sess.cstore.used_crates(LinkagePreference::RequireDynamic);
|
||||
|
||||
// Collect crates used in the session.
|
||||
// Reverse order finds dependencies first.
|
||||
let deps = crates.into_iter().rev()
|
||||
.filter_map(|(_, p)| p).collect();
|
||||
|
||||
assert_eq!(trans.modules.len(), 1);
|
||||
let llmod = match trans.modules[0].source {
|
||||
ModuleSource::Preexisting(_) => unimplemented!(),
|
||||
ModuleSource::Translated(llvm) => llvm.llmod,
|
||||
};
|
||||
|
||||
// Workaround because raw pointers do not impl Send
|
||||
let modp = llmod as usize;
|
||||
|
||||
(modp, deps)
|
||||
}), &sess)
|
||||
}).unwrap();
|
||||
|
||||
match handle.join() {
|
||||
Ok((llmod, deps)) => Some((llmod as llvm::ModuleRef, deps)),
|
||||
Err(_) => None
|
||||
}
|
||||
}
|
@ -46,19 +46,7 @@ fn template(me: &str) -> Command {
|
||||
}
|
||||
|
||||
fn expected(fn_name: &str) -> String {
|
||||
// FIXME(#32481)
|
||||
//
|
||||
// On windows, we read the function name from debuginfo using some
|
||||
// system APIs. For whatever reason, these APIs seem to use the
|
||||
// "name" field, which is only the "relative" name, not the full
|
||||
// name with namespace info, so we just see `foo` and not
|
||||
// `backtrace::foo` as we see on linux (which uses the linkage
|
||||
// name).
|
||||
if cfg!(windows) && cfg!(target_env = "msvc") {
|
||||
format!(" - {}", fn_name)
|
||||
} else {
|
||||
format!(" - backtrace::{}", fn_name)
|
||||
}
|
||||
format!(" - backtrace::{}", fn_name)
|
||||
}
|
||||
|
||||
fn runtest(me: &str) {
|
||||
|
Loading…
Reference in New Issue
Block a user