Move some functions out of rustc_codegen_llvm and fix metadata_only backend
This commit is contained in:
parent
4f0ca9248f
commit
6ceb1637b2
12 changed files with 265 additions and 139 deletions
|
@ -114,6 +114,10 @@ fn main() {
|
||||||
|
|
||||||
cmd.env("RUSTC_BREAK_ON_ICE", "1");
|
cmd.env("RUSTC_BREAK_ON_ICE", "1");
|
||||||
|
|
||||||
|
if args.iter().find(|s| **s == OsString::from("___")).is_some() {
|
||||||
|
cmd.arg("-Zcodegen-backend=metadata_only");
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(target) = target {
|
if let Some(target) = target {
|
||||||
// The stage0 compiler has a special sysroot distinct from what we
|
// The stage0 compiler has a special sysroot distinct from what we
|
||||||
// actually downloaded, so we just always pass the `--sysroot` option.
|
// actually downloaded, so we just always pass the `--sysroot` option.
|
||||||
|
|
|
@ -182,11 +182,13 @@ pub fn std_cargo(builder: &Builder,
|
||||||
// missing
|
// missing
|
||||||
// We also only build the runtimes when --enable-sanitizers (or its
|
// We also only build the runtimes when --enable-sanitizers (or its
|
||||||
// config.toml equivalent) is used
|
// config.toml equivalent) is used
|
||||||
let llvm_config = builder.ensure(native::Llvm {
|
if !builder.config.rust_codegen_backends.is_empty() {
|
||||||
target: builder.config.build,
|
let llvm_config = builder.ensure(native::Llvm {
|
||||||
emscripten: false,
|
target: builder.config.build,
|
||||||
});
|
emscripten: false,
|
||||||
cargo.env("LLVM_CONFIG", llvm_config);
|
});
|
||||||
|
cargo.env("LLVM_CONFIG", llvm_config);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cargo.arg("--features").arg(features)
|
cargo.arg("--features").arg(features)
|
||||||
|
@ -675,7 +677,9 @@ impl Step for CodegenBackend {
|
||||||
.arg(builder.src.join("src/librustc_codegen_llvm/Cargo.toml"));
|
.arg(builder.src.join("src/librustc_codegen_llvm/Cargo.toml"));
|
||||||
rustc_cargo_env(builder, &mut cargo);
|
rustc_cargo_env(builder, &mut cargo);
|
||||||
|
|
||||||
features += &build_codegen_backend(&builder, &mut cargo, &compiler, target, backend);
|
if !backend.is_empty() {
|
||||||
|
features += &build_codegen_backend(&builder, &mut cargo, &compiler, target, backend);
|
||||||
|
}
|
||||||
|
|
||||||
let tmp_stamp = builder.cargo_out(compiler, Mode::Codegen, target)
|
let tmp_stamp = builder.cargo_out(compiler, Mode::Codegen, target)
|
||||||
.join(".tmp.stamp");
|
.join(".tmp.stamp");
|
||||||
|
|
|
@ -56,6 +56,7 @@ use builder::{Builder, MemFlags};
|
||||||
use callee;
|
use callee;
|
||||||
use common::{C_bool, C_bytes_in_context, C_i32, C_usize};
|
use common::{C_bool, C_bytes_in_context, C_i32, C_usize};
|
||||||
use rustc_mir::monomorphize::collector::{self, MonoItemCollectionMode};
|
use rustc_mir::monomorphize::collector::{self, MonoItemCollectionMode};
|
||||||
|
use rustc_mir::monomorphize::item::DefPathBasedNames;
|
||||||
use common::{self, C_struct_in_context, C_array, val_ty};
|
use common::{self, C_struct_in_context, C_array, val_ty};
|
||||||
use consts;
|
use consts;
|
||||||
use context::{self, CodegenCx};
|
use context::{self, CodegenCx};
|
||||||
|
@ -67,7 +68,7 @@ use monomorphize::Instance;
|
||||||
use monomorphize::partitioning::{self, PartitioningStrategy, CodegenUnit, CodegenUnitExt};
|
use monomorphize::partitioning::{self, PartitioningStrategy, CodegenUnit, CodegenUnitExt};
|
||||||
use rustc_codegen_utils::symbol_names_test;
|
use rustc_codegen_utils::symbol_names_test;
|
||||||
use time_graph;
|
use time_graph;
|
||||||
use mono_item::{MonoItem, BaseMonoItemExt, MonoItemExt, DefPathBasedNames};
|
use mono_item::{MonoItem, BaseMonoItemExt, MonoItemExt};
|
||||||
use type_::Type;
|
use type_::Type;
|
||||||
use type_of::LayoutLlvmExt;
|
use type_of::LayoutLlvmExt;
|
||||||
use rustc::util::nodemap::{FxHashMap, FxHashSet, DefIdSet};
|
use rustc::util::nodemap::{FxHashMap, FxHashSet, DefIdSet};
|
||||||
|
@ -92,8 +93,6 @@ use syntax::ast;
|
||||||
|
|
||||||
use mir::operand::OperandValue;
|
use mir::operand::OperandValue;
|
||||||
|
|
||||||
pub use rustc_codegen_utils::check_for_rustc_errors_attr;
|
|
||||||
|
|
||||||
pub struct StatRecorder<'a, 'tcx: 'a> {
|
pub struct StatRecorder<'a, 'tcx: 'a> {
|
||||||
cx: &'a CodegenCx<'a, 'tcx>,
|
cx: &'a CodegenCx<'a, 'tcx>,
|
||||||
name: Option<String>,
|
name: Option<String>,
|
||||||
|
@ -715,7 +714,7 @@ pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
rx: mpsc::Receiver<Box<Any + Send>>)
|
rx: mpsc::Receiver<Box<Any + Send>>)
|
||||||
-> OngoingCodegen {
|
-> OngoingCodegen {
|
||||||
|
|
||||||
check_for_rustc_errors_attr(tcx);
|
::rustc_codegen_utils::check_for_rustc_errors_attr(tcx);
|
||||||
|
|
||||||
if let Some(true) = tcx.sess.opts.debugging_opts.thinlto {
|
if let Some(true) = tcx.sess.opts.debugging_opts.thinlto {
|
||||||
if unsafe { !llvm::LLVMRustThinLTOAvailable() } {
|
if unsafe { !llvm::LLVMRustThinLTOAvailable() } {
|
||||||
|
|
|
@ -12,9 +12,7 @@
|
||||||
|
|
||||||
//! Code that is useful in various codegen modules.
|
//! Code that is useful in various codegen modules.
|
||||||
|
|
||||||
use llvm;
|
use llvm::{self, ValueRef, ContextRef, TypeKind, True, False, Bool, OperandBundleDef};
|
||||||
use llvm::{ValueRef, ContextRef, TypeKind};
|
|
||||||
use llvm::{True, False, Bool, OperandBundleDef};
|
|
||||||
use rustc::hir::def_id::DefId;
|
use rustc::hir::def_id::DefId;
|
||||||
use rustc::middle::lang_items::LangItem;
|
use rustc::middle::lang_items::LangItem;
|
||||||
use abi;
|
use abi;
|
||||||
|
@ -29,6 +27,8 @@ use rustc::ty::{self, Ty, TyCtxt};
|
||||||
use rustc::ty::layout::{HasDataLayout, LayoutOf};
|
use rustc::ty::layout::{HasDataLayout, LayoutOf};
|
||||||
use rustc::hir;
|
use rustc::hir;
|
||||||
|
|
||||||
|
use meth;
|
||||||
|
|
||||||
use libc::{c_uint, c_char};
|
use libc::{c_uint, c_char};
|
||||||
use std::iter;
|
use std::iter;
|
||||||
|
|
||||||
|
@ -448,3 +448,101 @@ pub fn ty_fn_sig<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
|
||||||
_ => bug!("unexpected type {:?} to ty_fn_sig", ty)
|
_ => bug!("unexpected type {:?} to ty_fn_sig", ty)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn size_and_align_of_dst<'a, 'tcx>(bx: &Builder<'a, 'tcx>, t: Ty<'tcx>, info: ValueRef)
|
||||||
|
-> (ValueRef, ValueRef) {
|
||||||
|
debug!("calculate size of DST: {}; with lost info: {:?}",
|
||||||
|
t, Value(info));
|
||||||
|
if bx.cx.type_is_sized(t) {
|
||||||
|
let (size, align) = bx.cx.size_and_align_of(t);
|
||||||
|
debug!("size_and_align_of_dst t={} info={:?} size: {:?} align: {:?}",
|
||||||
|
t, Value(info), size, align);
|
||||||
|
let size = C_usize(bx.cx, size.bytes());
|
||||||
|
let align = C_usize(bx.cx, align.abi());
|
||||||
|
return (size, align);
|
||||||
|
}
|
||||||
|
assert!(!info.is_null());
|
||||||
|
match t.sty {
|
||||||
|
ty::TyDynamic(..) => {
|
||||||
|
// load size/align from vtable
|
||||||
|
(meth::SIZE.get_usize(bx, info), meth::ALIGN.get_usize(bx, info))
|
||||||
|
}
|
||||||
|
ty::TySlice(_) | ty::TyStr => {
|
||||||
|
let unit = t.sequence_element_type(bx.tcx());
|
||||||
|
// The info in this case is the length of the str, so the size is that
|
||||||
|
// times the unit size.
|
||||||
|
let (size, align) = bx.cx.size_and_align_of(unit);
|
||||||
|
(bx.mul(info, C_usize(bx.cx, size.bytes())),
|
||||||
|
C_usize(bx.cx, align.abi()))
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
let cx = bx.cx;
|
||||||
|
// First get the size of all statically known fields.
|
||||||
|
// Don't use size_of because it also rounds up to alignment, which we
|
||||||
|
// want to avoid, as the unsized field's alignment could be smaller.
|
||||||
|
assert!(!t.is_simd());
|
||||||
|
let layout = cx.layout_of(t);
|
||||||
|
debug!("DST {} layout: {:?}", t, layout);
|
||||||
|
|
||||||
|
let i = layout.fields.count() - 1;
|
||||||
|
let sized_size = layout.fields.offset(i).bytes();
|
||||||
|
let sized_align = layout.align.abi();
|
||||||
|
debug!("DST {} statically sized prefix size: {} align: {}",
|
||||||
|
t, sized_size, sized_align);
|
||||||
|
let sized_size = C_usize(cx, sized_size);
|
||||||
|
let sized_align = C_usize(cx, sized_align);
|
||||||
|
|
||||||
|
// Recurse to get the size of the dynamically sized field (must be
|
||||||
|
// the last field).
|
||||||
|
let field_ty = layout.field(cx, i).ty;
|
||||||
|
let (unsized_size, mut unsized_align) = size_and_align_of_dst(bx, field_ty, info);
|
||||||
|
|
||||||
|
// FIXME (#26403, #27023): We should be adding padding
|
||||||
|
// to `sized_size` (to accommodate the `unsized_align`
|
||||||
|
// required of the unsized field that follows) before
|
||||||
|
// summing it with `sized_size`. (Note that since #26403
|
||||||
|
// is unfixed, we do not yet add the necessary padding
|
||||||
|
// here. But this is where the add would go.)
|
||||||
|
|
||||||
|
// Return the sum of sizes and max of aligns.
|
||||||
|
let size = bx.add(sized_size, unsized_size);
|
||||||
|
|
||||||
|
// Packed types ignore the alignment of their fields.
|
||||||
|
if let ty::TyAdt(def, _) = t.sty {
|
||||||
|
if def.repr.packed() {
|
||||||
|
unsized_align = sized_align;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Choose max of two known alignments (combined value must
|
||||||
|
// be aligned according to more restrictive of the two).
|
||||||
|
let align = match (const_to_opt_u128(sized_align, false),
|
||||||
|
const_to_opt_u128(unsized_align, false)) {
|
||||||
|
(Some(sized_align), Some(unsized_align)) => {
|
||||||
|
// If both alignments are constant, (the sized_align should always be), then
|
||||||
|
// pick the correct alignment statically.
|
||||||
|
C_usize(cx, ::std::cmp::max(sized_align, unsized_align) as u64)
|
||||||
|
}
|
||||||
|
_ => bx.select(bx.icmp(llvm::IntUGT, sized_align, unsized_align),
|
||||||
|
sized_align,
|
||||||
|
unsized_align)
|
||||||
|
};
|
||||||
|
|
||||||
|
// Issue #27023: must add any necessary padding to `size`
|
||||||
|
// (to make it a multiple of `align`) before returning it.
|
||||||
|
//
|
||||||
|
// Namely, the returned size should be, in C notation:
|
||||||
|
//
|
||||||
|
// `size + ((size & (align-1)) ? align : 0)`
|
||||||
|
//
|
||||||
|
// emulated via the semi-standard fast bit trick:
|
||||||
|
//
|
||||||
|
// `(size + (align-1)) & -align`
|
||||||
|
|
||||||
|
let addend = bx.sub(align, C_usize(bx.cx, 1));
|
||||||
|
let size = bx.and(bx.add(size, addend), bx.neg(align));
|
||||||
|
|
||||||
|
(size, align)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -79,6 +79,7 @@ use rustc::ty::{self, TyCtxt};
|
||||||
use rustc::util::nodemap::{FxHashSet, FxHashMap};
|
use rustc::util::nodemap::{FxHashSet, FxHashMap};
|
||||||
use rustc_mir::monomorphize;
|
use rustc_mir::monomorphize;
|
||||||
use rustc_codegen_utils::codegen_backend::CodegenBackend;
|
use rustc_codegen_utils::codegen_backend::CodegenBackend;
|
||||||
|
use rustc_codegen_utils::time_graph;
|
||||||
|
|
||||||
mod diagnostics;
|
mod diagnostics;
|
||||||
|
|
||||||
|
@ -114,7 +115,6 @@ mod llvm_util;
|
||||||
mod metadata;
|
mod metadata;
|
||||||
mod meth;
|
mod meth;
|
||||||
mod mir;
|
mod mir;
|
||||||
mod time_graph;
|
|
||||||
mod mono_item;
|
mod mono_item;
|
||||||
mod type_;
|
mod type_;
|
||||||
mod type_of;
|
mod type_of;
|
||||||
|
@ -368,7 +368,7 @@ struct CodegenResults {
|
||||||
crate_info: CrateInfo,
|
crate_info: CrateInfo,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Misc info we load from metadata to persist beyond the tcx
|
/// Misc info we load from metadata to persist beyond the tcx
|
||||||
struct CrateInfo {
|
struct CrateInfo {
|
||||||
panic_runtime: Option<CrateNum>,
|
panic_runtime: Option<CrateNum>,
|
||||||
compiler_builtins: Option<CrateNum>,
|
compiler_builtins: Option<CrateNum>,
|
||||||
|
|
|
@ -20,6 +20,8 @@ use syntax::feature_gate::UnstableFeatures;
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use std::sync::Once;
|
use std::sync::Once;
|
||||||
|
|
||||||
|
pub use rustc_codegen_utils::llvm_target_features::*;
|
||||||
|
|
||||||
static POISONED: AtomicBool = AtomicBool::new(false);
|
static POISONED: AtomicBool = AtomicBool::new(false);
|
||||||
static INIT: Once = Once::new();
|
static INIT: Once = Once::new();
|
||||||
|
|
||||||
|
@ -79,108 +81,6 @@ unsafe fn configure_llvm(sess: &Session) {
|
||||||
llvm_args.as_ptr());
|
llvm_args.as_ptr());
|
||||||
}
|
}
|
||||||
|
|
||||||
// WARNING: the features after applying `to_llvm_feature` must be known
|
|
||||||
// to LLVM or the feature detection code will walk past the end of the feature
|
|
||||||
// array, leading to crashes.
|
|
||||||
|
|
||||||
const ARM_WHITELIST: &[(&str, Option<&str>)] = &[
|
|
||||||
("mclass", Some("arm_target_feature")),
|
|
||||||
("neon", Some("arm_target_feature")),
|
|
||||||
("v7", Some("arm_target_feature")),
|
|
||||||
("vfp2", Some("arm_target_feature")),
|
|
||||||
("vfp3", Some("arm_target_feature")),
|
|
||||||
("vfp4", Some("arm_target_feature")),
|
|
||||||
];
|
|
||||||
|
|
||||||
const AARCH64_WHITELIST: &[(&str, Option<&str>)] = &[
|
|
||||||
("fp", Some("aarch64_target_feature")),
|
|
||||||
("neon", Some("aarch64_target_feature")),
|
|
||||||
("sve", Some("aarch64_target_feature")),
|
|
||||||
("crc", Some("aarch64_target_feature")),
|
|
||||||
("crypto", Some("aarch64_target_feature")),
|
|
||||||
("ras", Some("aarch64_target_feature")),
|
|
||||||
("lse", Some("aarch64_target_feature")),
|
|
||||||
("rdm", Some("aarch64_target_feature")),
|
|
||||||
("fp16", Some("aarch64_target_feature")),
|
|
||||||
("rcpc", Some("aarch64_target_feature")),
|
|
||||||
("dotprod", Some("aarch64_target_feature")),
|
|
||||||
("v8.1a", Some("aarch64_target_feature")),
|
|
||||||
("v8.2a", Some("aarch64_target_feature")),
|
|
||||||
("v8.3a", Some("aarch64_target_feature")),
|
|
||||||
];
|
|
||||||
|
|
||||||
const X86_WHITELIST: &[(&str, Option<&str>)] = &[
|
|
||||||
("aes", None),
|
|
||||||
("avx", None),
|
|
||||||
("avx2", None),
|
|
||||||
("avx512bw", Some("avx512_target_feature")),
|
|
||||||
("avx512cd", Some("avx512_target_feature")),
|
|
||||||
("avx512dq", Some("avx512_target_feature")),
|
|
||||||
("avx512er", Some("avx512_target_feature")),
|
|
||||||
("avx512f", Some("avx512_target_feature")),
|
|
||||||
("avx512ifma", Some("avx512_target_feature")),
|
|
||||||
("avx512pf", Some("avx512_target_feature")),
|
|
||||||
("avx512vbmi", Some("avx512_target_feature")),
|
|
||||||
("avx512vl", Some("avx512_target_feature")),
|
|
||||||
("avx512vpopcntdq", Some("avx512_target_feature")),
|
|
||||||
("bmi1", None),
|
|
||||||
("bmi2", None),
|
|
||||||
("fma", None),
|
|
||||||
("fxsr", None),
|
|
||||||
("lzcnt", None),
|
|
||||||
("mmx", Some("mmx_target_feature")),
|
|
||||||
("pclmulqdq", None),
|
|
||||||
("popcnt", None),
|
|
||||||
("rdrand", None),
|
|
||||||
("rdseed", None),
|
|
||||||
("sha", None),
|
|
||||||
("sse", None),
|
|
||||||
("sse2", None),
|
|
||||||
("sse3", None),
|
|
||||||
("sse4.1", None),
|
|
||||||
("sse4.2", None),
|
|
||||||
("sse4a", Some("sse4a_target_feature")),
|
|
||||||
("ssse3", None),
|
|
||||||
("tbm", Some("tbm_target_feature")),
|
|
||||||
("xsave", None),
|
|
||||||
("xsavec", None),
|
|
||||||
("xsaveopt", None),
|
|
||||||
("xsaves", None),
|
|
||||||
];
|
|
||||||
|
|
||||||
const HEXAGON_WHITELIST: &[(&str, Option<&str>)] = &[
|
|
||||||
("hvx", Some("hexagon_target_feature")),
|
|
||||||
("hvx-double", Some("hexagon_target_feature")),
|
|
||||||
];
|
|
||||||
|
|
||||||
const POWERPC_WHITELIST: &[(&str, Option<&str>)] = &[
|
|
||||||
("altivec", Some("powerpc_target_feature")),
|
|
||||||
("power8-altivec", Some("powerpc_target_feature")),
|
|
||||||
("power9-altivec", Some("powerpc_target_feature")),
|
|
||||||
("power8-vector", Some("powerpc_target_feature")),
|
|
||||||
("power9-vector", Some("powerpc_target_feature")),
|
|
||||||
("vsx", Some("powerpc_target_feature")),
|
|
||||||
];
|
|
||||||
|
|
||||||
const MIPS_WHITELIST: &[(&str, Option<&str>)] = &[
|
|
||||||
("fp64", Some("mips_target_feature")),
|
|
||||||
("msa", Some("mips_target_feature")),
|
|
||||||
];
|
|
||||||
|
|
||||||
/// When rustdoc is running, provide a list of all known features so that all their respective
|
|
||||||
/// primtives may be documented.
|
|
||||||
///
|
|
||||||
/// IMPORTANT: If you're adding another whitelist to the above lists, make sure to add it to this
|
|
||||||
/// iterator!
|
|
||||||
pub fn all_known_features() -> impl Iterator<Item=(&'static str, Option<&'static str>)> {
|
|
||||||
ARM_WHITELIST.iter().cloned()
|
|
||||||
.chain(AARCH64_WHITELIST.iter().cloned())
|
|
||||||
.chain(X86_WHITELIST.iter().cloned())
|
|
||||||
.chain(HEXAGON_WHITELIST.iter().cloned())
|
|
||||||
.chain(POWERPC_WHITELIST.iter().cloned())
|
|
||||||
.chain(MIPS_WHITELIST.iter().cloned())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_llvm_feature<'a>(sess: &Session, s: &'a str) -> &'a str {
|
pub fn to_llvm_feature<'a>(sess: &Session, s: &'a str) -> &'a str {
|
||||||
let arch = if sess.target.target.arch == "x86_64" {
|
let arch = if sess.target.target.arch == "x86_64" {
|
||||||
"x86"
|
"x86"
|
||||||
|
@ -216,20 +116,6 @@ pub fn target_features(sess: &Session) -> Vec<Symbol> {
|
||||||
.map(|feature| Symbol::intern(feature)).collect()
|
.map(|feature| Symbol::intern(feature)).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn target_feature_whitelist(sess: &Session)
|
|
||||||
-> &'static [(&'static str, Option<&'static str>)]
|
|
||||||
{
|
|
||||||
match &*sess.target.target.arch {
|
|
||||||
"arm" => ARM_WHITELIST,
|
|
||||||
"aarch64" => AARCH64_WHITELIST,
|
|
||||||
"x86" | "x86_64" => X86_WHITELIST,
|
|
||||||
"hexagon" => HEXAGON_WHITELIST,
|
|
||||||
"mips" | "mips64" => MIPS_WHITELIST,
|
|
||||||
"powerpc" | "powerpc64" => POWERPC_WHITELIST,
|
|
||||||
_ => &[],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn print_version() {
|
pub fn print_version() {
|
||||||
// Can be called without initializing LLVM
|
// Can be called without initializing LLVM
|
||||||
unsafe {
|
unsafe {
|
||||||
|
|
|
@ -33,7 +33,7 @@ use std::fmt;
|
||||||
|
|
||||||
pub use rustc::mir::mono::MonoItem;
|
pub use rustc::mir::mono::MonoItem;
|
||||||
|
|
||||||
pub use rustc_mir::monomorphize::item::*;
|
use rustc_mir::monomorphize::item::*;
|
||||||
pub use rustc_mir::monomorphize::item::MonoItemExt as BaseMonoItemExt;
|
pub use rustc_mir::monomorphize::item::MonoItemExt as BaseMonoItemExt;
|
||||||
|
|
||||||
pub trait MonoItemExt<'a, 'tcx>: fmt::Debug + BaseMonoItemExt<'a, 'tcx> {
|
pub trait MonoItemExt<'a, 'tcx>: fmt::Debug + BaseMonoItemExt<'a, 'tcx> {
|
||||||
|
|
|
@ -26,7 +26,7 @@ use std::io::prelude::*;
|
||||||
use std::io::{self, Cursor};
|
use std::io::{self, Cursor};
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::sync::mpsc;
|
use std::sync::{mpsc, Arc};
|
||||||
|
|
||||||
use rustc_data_structures::owning_ref::OwningRef;
|
use rustc_data_structures::owning_ref::OwningRef;
|
||||||
use rustc_data_structures::sync::Lrc;
|
use rustc_data_structures::sync::Lrc;
|
||||||
|
@ -44,7 +44,6 @@ use rustc::middle::cstore::EncodedMetadata;
|
||||||
use rustc::middle::cstore::MetadataLoader;
|
use rustc::middle::cstore::MetadataLoader;
|
||||||
use rustc::dep_graph::DepGraph;
|
use rustc::dep_graph::DepGraph;
|
||||||
use rustc_target::spec::Target;
|
use rustc_target::spec::Target;
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
|
||||||
use rustc_mir::monomorphize::collector;
|
use rustc_mir::monomorphize::collector;
|
||||||
use link::{build_link_meta, out_filename};
|
use link::{build_link_meta, out_filename};
|
||||||
|
|
||||||
|
@ -203,10 +202,17 @@ impl CodegenBackend for MetadataOnlyCodegenBackend {
|
||||||
::symbol_names::provide(providers);
|
::symbol_names::provide(providers);
|
||||||
|
|
||||||
providers.target_features_whitelist = |_tcx, _cnum| {
|
providers.target_features_whitelist = |_tcx, _cnum| {
|
||||||
Lrc::new(FxHashMap()) // Just a dummy
|
Lrc::new(::llvm_target_features::all_known_features()
|
||||||
|
.map(|(a, b)| (a.to_string(), b.map(|s| s.to_string())))
|
||||||
|
.collect())
|
||||||
};
|
};
|
||||||
|
providers.is_reachable_non_generic = |_tcx, _defid| true;
|
||||||
|
providers.exported_symbols = |_tcx, _crate| Arc::new(Vec::new());
|
||||||
|
providers.wasm_custom_sections = |_tcx, _crate| Lrc::new(Vec::new());
|
||||||
|
}
|
||||||
|
fn provide_extern(&self, providers: &mut Providers) {
|
||||||
|
providers.is_reachable_non_generic = |_tcx, _defid| true;
|
||||||
}
|
}
|
||||||
fn provide_extern(&self, _providers: &mut Providers) {}
|
|
||||||
|
|
||||||
fn codegen_crate<'a, 'tcx>(
|
fn codegen_crate<'a, 'tcx>(
|
||||||
&self,
|
&self,
|
||||||
|
@ -225,7 +231,7 @@ impl CodegenBackend for MetadataOnlyCodegenBackend {
|
||||||
collector::MonoItemCollectionMode::Eager
|
collector::MonoItemCollectionMode::Eager
|
||||||
).0.iter()
|
).0.iter()
|
||||||
);
|
);
|
||||||
::rustc::middle::dependency_format::calculate(tcx);
|
//::rustc::middle::dependency_format::calculate(tcx);
|
||||||
let _ = tcx.link_args(LOCAL_CRATE);
|
let _ = tcx.link_args(LOCAL_CRATE);
|
||||||
let _ = tcx.native_libraries(LOCAL_CRATE);
|
let _ = tcx.native_libraries(LOCAL_CRATE);
|
||||||
for mono_item in
|
for mono_item in
|
||||||
|
|
|
@ -47,6 +47,8 @@ pub mod link;
|
||||||
pub mod codegen_backend;
|
pub mod codegen_backend;
|
||||||
pub mod symbol_names;
|
pub mod symbol_names;
|
||||||
pub mod symbol_names_test;
|
pub mod symbol_names_test;
|
||||||
|
pub mod time_graph;
|
||||||
|
pub mod llvm_target_features;
|
||||||
|
|
||||||
/// check for the #[rustc_error] annotation, which forces an
|
/// check for the #[rustc_error] annotation, which forces an
|
||||||
/// error in codegen. This is used to write compile-fail tests
|
/// error in codegen. This is used to write compile-fail tests
|
||||||
|
|
117
src/librustc_codegen_utils/llvm_target_features.rs
Normal file
117
src/librustc_codegen_utils/llvm_target_features.rs
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
use rustc::session::Session;
|
||||||
|
|
||||||
|
// WARNING: the features after applying `to_llvm_feature` must be known
|
||||||
|
// to LLVM or the feature detection code will walk past the end of the feature
|
||||||
|
// array, leading to crashes.
|
||||||
|
|
||||||
|
const ARM_WHITELIST: &[(&str, Option<&str>)] = &[
|
||||||
|
("mclass", Some("arm_target_feature")),
|
||||||
|
("neon", Some("arm_target_feature")),
|
||||||
|
("v7", Some("arm_target_feature")),
|
||||||
|
("vfp2", Some("arm_target_feature")),
|
||||||
|
("vfp3", Some("arm_target_feature")),
|
||||||
|
("vfp4", Some("arm_target_feature")),
|
||||||
|
];
|
||||||
|
|
||||||
|
const AARCH64_WHITELIST: &[(&str, Option<&str>)] = &[
|
||||||
|
("fp", Some("aarch64_target_feature")),
|
||||||
|
("neon", Some("aarch64_target_feature")),
|
||||||
|
("sve", Some("aarch64_target_feature")),
|
||||||
|
("crc", Some("aarch64_target_feature")),
|
||||||
|
("crypto", Some("aarch64_target_feature")),
|
||||||
|
("ras", Some("aarch64_target_feature")),
|
||||||
|
("lse", Some("aarch64_target_feature")),
|
||||||
|
("rdm", Some("aarch64_target_feature")),
|
||||||
|
("fp16", Some("aarch64_target_feature")),
|
||||||
|
("rcpc", Some("aarch64_target_feature")),
|
||||||
|
("dotprod", Some("aarch64_target_feature")),
|
||||||
|
("v8.1a", Some("aarch64_target_feature")),
|
||||||
|
("v8.2a", Some("aarch64_target_feature")),
|
||||||
|
("v8.3a", Some("aarch64_target_feature")),
|
||||||
|
];
|
||||||
|
|
||||||
|
const X86_WHITELIST: &[(&str, Option<&str>)] = &[
|
||||||
|
("aes", None),
|
||||||
|
("avx", None),
|
||||||
|
("avx2", None),
|
||||||
|
("avx512bw", Some("avx512_target_feature")),
|
||||||
|
("avx512cd", Some("avx512_target_feature")),
|
||||||
|
("avx512dq", Some("avx512_target_feature")),
|
||||||
|
("avx512er", Some("avx512_target_feature")),
|
||||||
|
("avx512f", Some("avx512_target_feature")),
|
||||||
|
("avx512ifma", Some("avx512_target_feature")),
|
||||||
|
("avx512pf", Some("avx512_target_feature")),
|
||||||
|
("avx512vbmi", Some("avx512_target_feature")),
|
||||||
|
("avx512vl", Some("avx512_target_feature")),
|
||||||
|
("avx512vpopcntdq", Some("avx512_target_feature")),
|
||||||
|
("bmi1", None),
|
||||||
|
("bmi2", None),
|
||||||
|
("fma", None),
|
||||||
|
("fxsr", None),
|
||||||
|
("lzcnt", None),
|
||||||
|
("mmx", Some("mmx_target_feature")),
|
||||||
|
("pclmulqdq", None),
|
||||||
|
("popcnt", None),
|
||||||
|
("rdrand", None),
|
||||||
|
("rdseed", None),
|
||||||
|
("sha", None),
|
||||||
|
("sse", None),
|
||||||
|
("sse2", None),
|
||||||
|
("sse3", None),
|
||||||
|
("sse4.1", None),
|
||||||
|
("sse4.2", None),
|
||||||
|
("sse4a", Some("sse4a_target_feature")),
|
||||||
|
("ssse3", None),
|
||||||
|
("tbm", Some("tbm_target_feature")),
|
||||||
|
("xsave", None),
|
||||||
|
("xsavec", None),
|
||||||
|
("xsaveopt", None),
|
||||||
|
("xsaves", None),
|
||||||
|
];
|
||||||
|
|
||||||
|
const HEXAGON_WHITELIST: &[(&str, Option<&str>)] = &[
|
||||||
|
("hvx", Some("hexagon_target_feature")),
|
||||||
|
("hvx-double", Some("hexagon_target_feature")),
|
||||||
|
];
|
||||||
|
|
||||||
|
const POWERPC_WHITELIST: &[(&str, Option<&str>)] = &[
|
||||||
|
("altivec", Some("powerpc_target_feature")),
|
||||||
|
("power8-altivec", Some("powerpc_target_feature")),
|
||||||
|
("power9-altivec", Some("powerpc_target_feature")),
|
||||||
|
("power8-vector", Some("powerpc_target_feature")),
|
||||||
|
("power9-vector", Some("powerpc_target_feature")),
|
||||||
|
("vsx", Some("powerpc_target_feature")),
|
||||||
|
];
|
||||||
|
|
||||||
|
const MIPS_WHITELIST: &[(&str, Option<&str>)] = &[
|
||||||
|
("fp64", Some("mips_target_feature")),
|
||||||
|
("msa", Some("mips_target_feature")),
|
||||||
|
];
|
||||||
|
|
||||||
|
/// When rustdoc is running, provide a list of all known features so that all their respective
|
||||||
|
/// primtives may be documented.
|
||||||
|
///
|
||||||
|
/// IMPORTANT: If you're adding another whitelist to the above lists, make sure to add it to this
|
||||||
|
/// iterator!
|
||||||
|
pub fn all_known_features() -> impl Iterator<Item=(&'static str, Option<&'static str>)> {
|
||||||
|
ARM_WHITELIST.iter().cloned()
|
||||||
|
.chain(AARCH64_WHITELIST.iter().cloned())
|
||||||
|
.chain(X86_WHITELIST.iter().cloned())
|
||||||
|
.chain(HEXAGON_WHITELIST.iter().cloned())
|
||||||
|
.chain(POWERPC_WHITELIST.iter().cloned())
|
||||||
|
.chain(MIPS_WHITELIST.iter().cloned())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn target_feature_whitelist(sess: &Session)
|
||||||
|
-> &'static [(&'static str, Option<&'static str>)]
|
||||||
|
{
|
||||||
|
match &*sess.target.target.arch {
|
||||||
|
"arm" => ARM_WHITELIST,
|
||||||
|
"aarch64" => AARCH64_WHITELIST,
|
||||||
|
"x86" | "x86_64" => X86_WHITELIST,
|
||||||
|
"hexagon" => HEXAGON_WHITELIST,
|
||||||
|
"mips" | "mips64" => MIPS_WHITELIST,
|
||||||
|
"powerpc" | "powerpc64" => POWERPC_WHITELIST,
|
||||||
|
_ => &[],
|
||||||
|
}
|
||||||
|
}
|
|
@ -375,10 +375,20 @@ fn get_codegen_sysroot(backend_name: &str) -> fn() -> Box<CodegenBackend> {
|
||||||
match file {
|
match file {
|
||||||
Some(ref s) => return load_backend_from_dylib(s),
|
Some(ref s) => return load_backend_from_dylib(s),
|
||||||
None => {
|
None => {
|
||||||
let err = format!("failed to load default codegen backend for `{}`, \
|
if !::rustc::session::config::nightly_options::is_nightly_build() {
|
||||||
|
let err = format!("failed to load default codegen backend for `{}`, \
|
||||||
no appropriate codegen dylib found in `{}`",
|
no appropriate codegen dylib found in `{}`",
|
||||||
backend_name, sysroot.display());
|
backend_name, sysroot.display());
|
||||||
early_error(ErrorOutputType::default(), &err);
|
early_error(ErrorOutputType::default(), &err);
|
||||||
|
} else {
|
||||||
|
let warn = format!("no codegen-backend `{}`, \
|
||||||
|
no appropriate dylib in `{}`. \
|
||||||
|
Falling back to metadata_only codegen backend. \
|
||||||
|
**This is suitable for dev purposes only**",
|
||||||
|
backend_name, sysroot.display());
|
||||||
|
early_warn(ErrorOutputType::default(), &warn);
|
||||||
|
return rustc_codegen_utils::codegen_backend::MetadataOnlyCodegenBackend::new;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue