Move some functions out of rustc_codegen_llvm and fix metadata_only backend

This commit is contained in:
bjorn3 2018-06-15 19:02:41 +02:00
parent 4f0ca9248f
commit 6ceb1637b2
12 changed files with 265 additions and 139 deletions

View File

@ -114,6 +114,10 @@ fn main() {
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 {
// The stage0 compiler has a special sysroot distinct from what we
// actually downloaded, so we just always pass the `--sysroot` option.

View File

@ -182,11 +182,13 @@ pub fn std_cargo(builder: &Builder,
// missing
// We also only build the runtimes when --enable-sanitizers (or its
// config.toml equivalent) is used
let llvm_config = builder.ensure(native::Llvm {
target: builder.config.build,
emscripten: false,
});
cargo.env("LLVM_CONFIG", llvm_config);
if !builder.config.rust_codegen_backends.is_empty() {
let llvm_config = builder.ensure(native::Llvm {
target: builder.config.build,
emscripten: false,
});
cargo.env("LLVM_CONFIG", llvm_config);
}
}
cargo.arg("--features").arg(features)
@ -675,7 +677,9 @@ impl Step for CodegenBackend {
.arg(builder.src.join("src/librustc_codegen_llvm/Cargo.toml"));
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)
.join(".tmp.stamp");

View File

@ -56,6 +56,7 @@ use builder::{Builder, MemFlags};
use callee;
use common::{C_bool, C_bytes_in_context, C_i32, C_usize};
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 consts;
use context::{self, CodegenCx};
@ -67,7 +68,7 @@ use monomorphize::Instance;
use monomorphize::partitioning::{self, PartitioningStrategy, CodegenUnit, CodegenUnitExt};
use rustc_codegen_utils::symbol_names_test;
use time_graph;
use mono_item::{MonoItem, BaseMonoItemExt, MonoItemExt, DefPathBasedNames};
use mono_item::{MonoItem, BaseMonoItemExt, MonoItemExt};
use type_::Type;
use type_of::LayoutLlvmExt;
use rustc::util::nodemap::{FxHashMap, FxHashSet, DefIdSet};
@ -92,8 +93,6 @@ use syntax::ast;
use mir::operand::OperandValue;
pub use rustc_codegen_utils::check_for_rustc_errors_attr;
pub struct StatRecorder<'a, 'tcx: 'a> {
cx: &'a CodegenCx<'a, 'tcx>,
name: Option<String>,
@ -715,7 +714,7 @@ pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
rx: mpsc::Receiver<Box<Any + Send>>)
-> 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 unsafe { !llvm::LLVMRustThinLTOAvailable() } {

View File

@ -12,9 +12,7 @@
//! Code that is useful in various codegen modules.
use llvm;
use llvm::{ValueRef, ContextRef, TypeKind};
use llvm::{True, False, Bool, OperandBundleDef};
use llvm::{self, ValueRef, ContextRef, TypeKind, True, False, Bool, OperandBundleDef};
use rustc::hir::def_id::DefId;
use rustc::middle::lang_items::LangItem;
use abi;
@ -29,6 +27,8 @@ use rustc::ty::{self, Ty, TyCtxt};
use rustc::ty::layout::{HasDataLayout, LayoutOf};
use rustc::hir;
use meth;
use libc::{c_uint, c_char};
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)
}
}
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)
}
}
}

View File

@ -79,6 +79,7 @@ use rustc::ty::{self, TyCtxt};
use rustc::util::nodemap::{FxHashSet, FxHashMap};
use rustc_mir::monomorphize;
use rustc_codegen_utils::codegen_backend::CodegenBackend;
use rustc_codegen_utils::time_graph;
mod diagnostics;
@ -114,7 +115,6 @@ mod llvm_util;
mod metadata;
mod meth;
mod mir;
mod time_graph;
mod mono_item;
mod type_;
mod type_of;
@ -368,7 +368,7 @@ struct CodegenResults {
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 {
panic_runtime: Option<CrateNum>,
compiler_builtins: Option<CrateNum>,

View File

@ -20,6 +20,8 @@ use syntax::feature_gate::UnstableFeatures;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Once;
pub use rustc_codegen_utils::llvm_target_features::*;
static POISONED: AtomicBool = AtomicBool::new(false);
static INIT: Once = Once::new();
@ -79,108 +81,6 @@ unsafe fn configure_llvm(sess: &Session) {
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 {
let arch = if sess.target.target.arch == "x86_64" {
"x86"
@ -216,20 +116,6 @@ pub fn target_features(sess: &Session) -> Vec<Symbol> {
.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() {
// Can be called without initializing LLVM
unsafe {

View File

@ -33,7 +33,7 @@ use std::fmt;
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 trait MonoItemExt<'a, 'tcx>: fmt::Debug + BaseMonoItemExt<'a, 'tcx> {

View File

@ -26,7 +26,7 @@ use std::io::prelude::*;
use std::io::{self, Cursor};
use std::fs::File;
use std::path::Path;
use std::sync::mpsc;
use std::sync::{mpsc, Arc};
use rustc_data_structures::owning_ref::OwningRef;
use rustc_data_structures::sync::Lrc;
@ -44,7 +44,6 @@ use rustc::middle::cstore::EncodedMetadata;
use rustc::middle::cstore::MetadataLoader;
use rustc::dep_graph::DepGraph;
use rustc_target::spec::Target;
use rustc_data_structures::fx::FxHashMap;
use rustc_mir::monomorphize::collector;
use link::{build_link_meta, out_filename};
@ -203,10 +202,17 @@ impl CodegenBackend for MetadataOnlyCodegenBackend {
::symbol_names::provide(providers);
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>(
&self,
@ -225,7 +231,7 @@ impl CodegenBackend for MetadataOnlyCodegenBackend {
collector::MonoItemCollectionMode::Eager
).0.iter()
);
::rustc::middle::dependency_format::calculate(tcx);
//::rustc::middle::dependency_format::calculate(tcx);
let _ = tcx.link_args(LOCAL_CRATE);
let _ = tcx.native_libraries(LOCAL_CRATE);
for mono_item in

View File

@ -47,6 +47,8 @@ pub mod link;
pub mod codegen_backend;
pub mod symbol_names;
pub mod symbol_names_test;
pub mod time_graph;
pub mod llvm_target_features;
/// check for the #[rustc_error] annotation, which forces an
/// error in codegen. This is used to write compile-fail tests

View 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,
_ => &[],
}
}

View File

@ -375,10 +375,20 @@ fn get_codegen_sysroot(backend_name: &str) -> fn() -> Box<CodegenBackend> {
match file {
Some(ref s) => return load_backend_from_dylib(s),
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 `{}`",
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;
}
}
}