diff --git a/configure b/configure index a7e24a506fb..d4bd16167d3 100755 --- a/configure +++ b/configure @@ -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 diff --git a/mk/platform.mk b/mk/platform.mk index c2644621c57..d601cab7221 100644 --- a/mk/platform.mk +++ b/mk/platform.mk @@ -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) diff --git a/src/compiler-rt b/src/compiler-rt index ac3d1cda612..8598065bd96 160000 --- a/src/compiler-rt +++ b/src/compiler-rt @@ -1 +1 @@ -Subproject commit ac3d1cda612edccb6f1da53cbf7716e248405f3b +Subproject commit 8598065bd965d9713bfafb6c1e766d63a7b17b89 diff --git a/src/etc/mklldeps.py b/src/etc/mklldeps.py index 8381e4f7040..24b007576aa 100644 --- a/src/etc/mklldeps.py +++ b/src/etc/mklldeps.py @@ -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\"") diff --git a/src/librustc_back/target/aarch64_linux_android.rs b/src/librustc_back/target/aarch64_linux_android.rs index 307823137a7..7f54dab5b53 100644 --- a/src/librustc_back/target/aarch64_linux_android.rs +++ b/src/librustc_back/target/aarch64_linux_android.rs @@ -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(), diff --git a/src/librustc_back/target/aarch64_unknown_linux_gnu.rs b/src/librustc_back/target/aarch64_unknown_linux_gnu.rs index 14d0c8bedec..cca965f9d4f 100644 --- a/src/librustc_back/target/aarch64_unknown_linux_gnu.rs +++ b/src/librustc_back/target/aarch64_unknown_linux_gnu.rs @@ -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(), diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs index a2c808cbcb6..085ea240a50 100644 --- a/src/librustc_llvm/build.rs +++ b/src/librustc_llvm/build.rs @@ -13,7 +13,7 @@ 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)); diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index e757201c886..6905abc2902 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -226,7 +226,7 @@ pub fn apply_llfn(&self, idx: usize, llfn: ValueRef) { 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 @@ pub fn LLVMRemoveInstrAttribute(Instr: ValueRef, 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 @@ pub fn LLVMBuildAtomicStore(B: BuilderRef, Alignment: c_uint) -> ValueRef; - pub fn LLVMBuildAtomicCmpXchg(B: BuilderRef, + pub fn LLVMRustBuildAtomicCmpXchg(B: BuilderRef, LHS: ValueRef, CMP: ValueRef, RHS: ValueRef, @@ -1591,9 +1591,6 @@ pub fn LLVMBuildAtomicFence(B: BuilderRef, /// 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 @@ pub fn LLVMRustBuildOperandBundleDef(Name: *const c_char, 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 diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index 4b9d5dd9e8d..87815c63f79 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -24,6 +24,7 @@ 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, ) diff --git a/src/librustc_trans/builder.rs b/src/librustc_trans/builder.rs index e88257dcd4c..7495f2b753b 100644 --- a/src/librustc_trans/builder.rs +++ b/src/librustc_trans/builder.rs @@ -1083,7 +1083,7 @@ pub fn atomic_cmpxchg(&self, dst: ValueRef, 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) } } diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs index a8f8474e940..792169b08a4 100644 --- a/src/librustc_trans/context.rs +++ b/src/librustc_trans/context.rs @@ -34,6 +34,7 @@ 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 @@ fn next(&mut self) -> Option<(CrateContext<'a, 'tcx>, bool)> { } } +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 @@ fn new<'a>(shared: &SharedCrateContext<'a, '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 }; diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs index 46813d957dc..387f24378ce 100644 --- a/src/librustc_trans/debuginfo/metadata.rs +++ b/src/librustc_trans/debuginfo/metadata.rs @@ -18,7 +18,9 @@ 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::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_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); diff --git a/src/librustc_trans/debuginfo/mod.rs b/src/librustc_trans/debuginfo/mod.rs index 8c5b3ed54c2..ed20d949d55 100644 --- a/src/librustc_trans/debuginfo/mod.rs +++ b/src/librustc_trans/debuginfo/mod.rs @@ -18,7 +18,7 @@ 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 @@ 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 diff --git a/src/librustc_trans/debuginfo/namespace.rs b/src/librustc_trans/debuginfo/namespace.rs index 167229ddfd9..736a8c1c7d7 100644 --- a/src/librustc_trans/debuginfo/namespace.rs +++ b/src/librustc_trans/debuginfo/namespace.rs @@ -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 { diff --git a/src/llvm b/src/llvm index 7ca76af03bb..d1cc48989b1 160000 --- a/src/llvm +++ b/src/llvm @@ -1 +1 @@ -Subproject commit 7ca76af03bb04659562890d6b4f223fffe0d748f +Subproject commit d1cc48989b13780f21c408fef17dceb104a09c9d diff --git a/src/rustllvm/ArchiveWrapper.cpp b/src/rustllvm/ArchiveWrapper.cpp index 1e7b04c814c..3d48024c879 100644 --- a/src/rustllvm/ArchiveWrapper.cpp +++ b/src/rustllvm/ArchiveWrapper.cpp @@ -43,11 +43,19 @@ LLVMRustOpenArchive(char *path) { return nullptr; } +#if LLVM_VERSION_MINOR <= 8 ErrorOr> archive_or = +#else + Expected> 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* 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 Members; +#else + std::vector 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 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 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 diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index 3564f338a02..a1276060271 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -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 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(PM); + llvm::legacy::FunctionPassManager *P = unwrap(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(PMR); + llvm::legacy::PassManager *PM = unwrap(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(PMR); + llvm::legacy::PassManager *PM = unwrap(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 ref(symbols, len); passes.add(llvm::createInternalizePass(ref)); +#else + auto PreserveFunctions = [=](const GlobalValue &GV) { + for (size_t i=0; igetDataLayout()); } + +extern "C" void +LLVMRustSetModulePIELevel(LLVMModuleRef M) { +#if LLVM_VERSION_MINOR >= 9 + unwrap(M)->setPIELevel(PIELevel::Level::Large); +#endif +} diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index fadd95c9a72..bc38245d351 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -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(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, diff --git a/src/rustllvm/llvm-auto-clean-trigger b/src/rustllvm/llvm-auto-clean-trigger index 1953fc5a6b4..e871763a48d 100644 --- a/src/rustllvm/llvm-auto-clean-trigger +++ b/src/rustllvm/llvm-auto-clean-trigger @@ -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 diff --git a/src/test/run-make/execution-engine/Makefile b/src/test/run-make/execution-engine/Makefile deleted file mode 100644 index 4c818cd99e2..00000000000 --- a/src/test/run-make/execution-engine/Makefile +++ /dev/null @@ -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 diff --git a/src/test/run-make/execution-engine/test.rs b/src/test/run-make/execution-engine/test.rs deleted file mode 100644 index b58295d47f2..00000000000 --- a/src/test/run-make/execution-engine/test.rs +++ /dev/null @@ -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 or the MIT license -// , 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, - 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)> { - 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 - } -} diff --git a/src/test/run-pass/backtrace.rs b/src/test/run-pass/backtrace.rs index ad38dc8f452..f1ce17c0736 100644 --- a/src/test/run-pass/backtrace.rs +++ b/src/test/run-pass/backtrace.rs @@ -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) {