Auto merge of #50228 - irinagpopa:backstory-v2, r=nikomatsakis
Rename rustc_back to rustc_target and move ABI code to it. Fixes #45226.
This commit is contained in:
commit
949010d23e
44
src/Cargo.lock
generated
44
src/Cargo.lock
generated
@ -1728,10 +1728,10 @@ dependencies = [
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc_macro 0.0.0",
|
||||
"rustc_apfloat 0.0.0",
|
||||
"rustc_back 0.0.0",
|
||||
"rustc_const_math 0.0.0",
|
||||
"rustc_data_structures 0.0.0",
|
||||
"rustc_errors 0.0.0",
|
||||
"rustc_target 0.0.0",
|
||||
"serialize 0.0.0",
|
||||
"syntax 0.0.0",
|
||||
"syntax_pos 0.0.0",
|
||||
@ -1818,8 +1818,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
name = "rustc-main"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"rustc_back 0.0.0",
|
||||
"rustc_driver 0.0.0",
|
||||
"rustc_target 0.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1833,6 +1833,7 @@ version = "0.0.0"
|
||||
dependencies = [
|
||||
"rustc 0.0.0",
|
||||
"rustc_errors 0.0.0",
|
||||
"rustc_target 0.0.0",
|
||||
"syntax 0.0.0",
|
||||
"syntax_pos 0.0.0",
|
||||
]
|
||||
@ -1857,16 +1858,6 @@ dependencies = [
|
||||
"core 0.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_back"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serialize 0.0.0",
|
||||
"syntax 0.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_borrowck"
|
||||
version = "0.0.0"
|
||||
@ -1895,6 +1886,7 @@ name = "rustc_cratesio_shim"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1906,6 +1898,7 @@ dependencies = [
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parking_lot_core 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc_cratesio_shim 0.0.0",
|
||||
"serialize 0.0.0",
|
||||
"stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
@ -1921,7 +1914,6 @@ dependencies = [
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc 0.0.0",
|
||||
"rustc_allocator 0.0.0",
|
||||
"rustc_back 0.0.0",
|
||||
"rustc_borrowck 0.0.0",
|
||||
"rustc_data_structures 0.0.0",
|
||||
"rustc_errors 0.0.0",
|
||||
@ -1934,6 +1926,7 @@ dependencies = [
|
||||
"rustc_privacy 0.0.0",
|
||||
"rustc_resolve 0.0.0",
|
||||
"rustc_save_analysis 0.0.0",
|
||||
"rustc_target 0.0.0",
|
||||
"rustc_traits 0.0.0",
|
||||
"rustc_trans_utils 0.0.0",
|
||||
"rustc_typeck 0.0.0",
|
||||
@ -1976,6 +1969,7 @@ dependencies = [
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc 0.0.0",
|
||||
"rustc_mir 0.0.0",
|
||||
"rustc_target 0.0.0",
|
||||
"syntax 0.0.0",
|
||||
"syntax_pos 0.0.0",
|
||||
]
|
||||
@ -2011,9 +2005,9 @@ dependencies = [
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc_macro 0.0.0",
|
||||
"rustc 0.0.0",
|
||||
"rustc_back 0.0.0",
|
||||
"rustc_data_structures 0.0.0",
|
||||
"rustc_errors 0.0.0",
|
||||
"rustc_target 0.0.0",
|
||||
"serialize 0.0.0",
|
||||
"syntax 0.0.0",
|
||||
"syntax_ext 0.0.0",
|
||||
@ -2032,10 +2026,10 @@ dependencies = [
|
||||
"log_settings 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc 0.0.0",
|
||||
"rustc_apfloat 0.0.0",
|
||||
"rustc_back 0.0.0",
|
||||
"rustc_const_math 0.0.0",
|
||||
"rustc_data_structures 0.0.0",
|
||||
"rustc_errors 0.0.0",
|
||||
"rustc_target 0.0.0",
|
||||
"serialize 0.0.0",
|
||||
"syntax 0.0.0",
|
||||
"syntax_pos 0.0.0",
|
||||
@ -2116,11 +2110,22 @@ dependencies = [
|
||||
"rustc 0.0.0",
|
||||
"rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc_data_structures 0.0.0",
|
||||
"rustc_target 0.0.0",
|
||||
"rustc_typeck 0.0.0",
|
||||
"syntax 0.0.0",
|
||||
"syntax_pos 0.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_target"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc_cratesio_shim 0.0.0",
|
||||
"serialize 0.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_traits"
|
||||
version = "0.0.0"
|
||||
@ -2138,7 +2143,6 @@ dependencies = [
|
||||
name = "rustc_trans"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cc 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"env_logger 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -2150,7 +2154,6 @@ dependencies = [
|
||||
"rustc-demangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc_allocator 0.0.0",
|
||||
"rustc_apfloat 0.0.0",
|
||||
"rustc_back 0.0.0",
|
||||
"rustc_const_math 0.0.0",
|
||||
"rustc_data_structures 0.0.0",
|
||||
"rustc_errors 0.0.0",
|
||||
@ -2158,6 +2161,7 @@ dependencies = [
|
||||
"rustc_llvm 0.0.0",
|
||||
"rustc_mir 0.0.0",
|
||||
"rustc_platform_intrinsics 0.0.0",
|
||||
"rustc_target 0.0.0",
|
||||
"rustc_trans_utils 0.0.0",
|
||||
"serialize 0.0.0",
|
||||
"syntax 0.0.0",
|
||||
@ -2173,10 +2177,10 @@ dependencies = [
|
||||
"flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc 0.0.0",
|
||||
"rustc_back 0.0.0",
|
||||
"rustc_data_structures 0.0.0",
|
||||
"rustc_incremental 0.0.0",
|
||||
"rustc_mir 0.0.0",
|
||||
"rustc_target 0.0.0",
|
||||
"syntax 0.0.0",
|
||||
"syntax_pos 0.0.0",
|
||||
]
|
||||
@ -2205,6 +2209,7 @@ dependencies = [
|
||||
"rustc_data_structures 0.0.0",
|
||||
"rustc_errors 0.0.0",
|
||||
"rustc_platform_intrinsics 0.0.0",
|
||||
"rustc_target 0.0.0",
|
||||
"syntax 0.0.0",
|
||||
"syntax_pos 0.0.0",
|
||||
]
|
||||
@ -2543,9 +2548,9 @@ version = "0.0.0"
|
||||
dependencies = [
|
||||
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc_cratesio_shim 0.0.0",
|
||||
"rustc_data_structures 0.0.0",
|
||||
"rustc_errors 0.0.0",
|
||||
"rustc_target 0.0.0",
|
||||
"scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serialize 0.0.0",
|
||||
"syntax_pos 0.0.0",
|
||||
@ -2559,6 +2564,7 @@ dependencies = [
|
||||
"proc_macro 0.0.0",
|
||||
"rustc_data_structures 0.0.0",
|
||||
"rustc_errors 0.0.0",
|
||||
"rustc_target 0.0.0",
|
||||
"syntax 0.0.0",
|
||||
"syntax_pos 0.0.0",
|
||||
]
|
||||
|
@ -18,7 +18,7 @@ lazy_static = "1.0.0"
|
||||
log = { version = "0.4", features = ["release_max_level_info", "std"] }
|
||||
proc_macro = { path = "../libproc_macro" }
|
||||
rustc_apfloat = { path = "../librustc_apfloat" }
|
||||
rustc_back = { path = "../librustc_back" }
|
||||
rustc_target = { path = "../librustc_target" }
|
||||
rustc_const_math = { path = "../librustc_const_math" }
|
||||
rustc_data_structures = { path = "../librustc_data_structures" }
|
||||
rustc_errors = { path = "../librustc_errors" }
|
||||
|
@ -41,7 +41,7 @@
|
||||
//! This order consistency is required in a few places in rustc, for
|
||||
//! example generator inference, and possibly also HIR borrowck.
|
||||
|
||||
use syntax::abi::Abi;
|
||||
use rustc_target::spec::abi::Abi;
|
||||
use syntax::ast::{NodeId, CRATE_NODE_ID, Name, Attribute};
|
||||
use syntax_pos::Span;
|
||||
use hir::*;
|
||||
|
@ -25,7 +25,7 @@ use hir as ast;
|
||||
use hir::map::{self, Node};
|
||||
use hir::{Expr, FnDecl};
|
||||
use hir::intravisit::FnKind;
|
||||
use syntax::abi;
|
||||
use rustc_target::spec::abi;
|
||||
use syntax::ast::{Attribute, Name, NodeId};
|
||||
use syntax_pos::Span;
|
||||
|
||||
|
@ -21,7 +21,7 @@ use hir::def_id::{CRATE_DEF_INDEX, DefId, LocalDefId, DefIndexAddressSpace};
|
||||
|
||||
use middle::cstore::CrateStore;
|
||||
|
||||
use syntax::abi::Abi;
|
||||
use rustc_target::spec::abi::Abi;
|
||||
use syntax::ast::{self, Name, NodeId, CRATE_NODE_ID};
|
||||
use syntax::codemap::Spanned;
|
||||
use syntax::ext::base::MacroKind;
|
||||
|
@ -34,7 +34,7 @@ use mir::mono::Linkage;
|
||||
|
||||
use syntax_pos::{Span, DUMMY_SP};
|
||||
use syntax::codemap::{self, Spanned};
|
||||
use syntax::abi::Abi;
|
||||
use rustc_target::spec::abi::Abi;
|
||||
use syntax::ast::{self, Name, NodeId, DUMMY_NODE_ID, AsmDialect};
|
||||
use syntax::ast::{Attribute, Lit, StrStyle, FloatTy, IntTy, UintTy, MetaItem};
|
||||
use syntax::attr::InlineAttr;
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
pub use self::AnnNode::*;
|
||||
|
||||
use syntax::abi::Abi;
|
||||
use rustc_target::spec::abi::Abi;
|
||||
use syntax::ast;
|
||||
use syntax::codemap::{CodeMap, Spanned};
|
||||
use syntax::parse::{token, ParseSess};
|
||||
|
@ -20,7 +20,7 @@ impl_stable_hash_for!(enum ::session::search_paths::PathKind {
|
||||
All
|
||||
});
|
||||
|
||||
impl_stable_hash_for!(enum ::rustc_back::PanicStrategy {
|
||||
impl_stable_hash_for!(enum ::rustc_target::spec::PanicStrategy {
|
||||
Abort,
|
||||
Unwind
|
||||
});
|
||||
|
@ -82,7 +82,7 @@ impl_stable_hash_for!(enum ::syntax::ext::base::MacroKind {
|
||||
});
|
||||
|
||||
|
||||
impl_stable_hash_for!(enum ::syntax::abi::Abi {
|
||||
impl_stable_hash_for!(enum ::rustc_target::spec::abi::Abi {
|
||||
Cdecl,
|
||||
Stdcall,
|
||||
Fastcall,
|
||||
|
@ -81,7 +81,7 @@ extern crate graphviz;
|
||||
#[macro_use] extern crate lazy_static;
|
||||
#[cfg(windows)]
|
||||
extern crate libc;
|
||||
extern crate rustc_back;
|
||||
extern crate rustc_target;
|
||||
#[macro_use] extern crate rustc_data_structures;
|
||||
extern crate serialize;
|
||||
extern crate rustc_const_math;
|
||||
|
@ -657,7 +657,8 @@ impl<'a, 'tcx> LateContext<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> LayoutOf<Ty<'tcx>> for &'a LateContext<'a, 'tcx> {
|
||||
impl<'a, 'tcx> LayoutOf for &'a LateContext<'a, 'tcx> {
|
||||
type Ty = Ty<'tcx>;
|
||||
type TyLayout = Result<TyLayout<'tcx>, LayoutError<'tcx>>;
|
||||
|
||||
fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout {
|
||||
|
@ -37,7 +37,7 @@ use syntax::ast;
|
||||
use syntax::ext::base::SyntaxExtension;
|
||||
use syntax::symbol::Symbol;
|
||||
use syntax_pos::Span;
|
||||
use rustc_back::target::Target;
|
||||
use rustc_target::spec::Target;
|
||||
use rustc_data_structures::sync::{MetadataRef, Lrc};
|
||||
|
||||
pub use self::NativeLibraryKind::*;
|
||||
|
@ -69,7 +69,7 @@ use ty::TyCtxt;
|
||||
use middle::cstore::{self, DepKind};
|
||||
use middle::cstore::LinkagePreference::{self, RequireStatic, RequireDynamic};
|
||||
use util::nodemap::FxHashMap;
|
||||
use rustc_back::PanicStrategy;
|
||||
use rustc_target::spec::PanicStrategy;
|
||||
|
||||
/// A list of dependencies for a certain crate type.
|
||||
///
|
||||
|
@ -13,7 +13,7 @@ use hir::def_id::DefId;
|
||||
use ty::{self, Ty, TyCtxt};
|
||||
use ty::layout::{LayoutError, Pointer, SizeSkeleton};
|
||||
|
||||
use syntax::abi::Abi::RustIntrinsic;
|
||||
use rustc_target::spec::abi::Abi::RustIntrinsic;
|
||||
use syntax_pos::Span;
|
||||
use hir::intravisit::{self, Visitor, NestedVisitorMap};
|
||||
use hir;
|
||||
|
@ -26,7 +26,7 @@ use middle::privacy;
|
||||
use session::config;
|
||||
use util::nodemap::{NodeSet, FxHashSet};
|
||||
|
||||
use syntax::abi::Abi;
|
||||
use rustc_target::spec::abi::Abi;
|
||||
use syntax::ast;
|
||||
use syntax::attr;
|
||||
use hir;
|
||||
|
@ -13,7 +13,7 @@
|
||||
use session::config;
|
||||
use middle::lang_items;
|
||||
|
||||
use rustc_back::PanicStrategy;
|
||||
use rustc_target::spec::PanicStrategy;
|
||||
use syntax::ast;
|
||||
use syntax::symbol::Symbol;
|
||||
use syntax_pos::Span;
|
||||
|
@ -22,8 +22,8 @@ use session::{early_error, early_warn, Session};
|
||||
use session::search_paths::SearchPaths;
|
||||
|
||||
use ich::StableHashingContext;
|
||||
use rustc_back::{LinkerFlavor, PanicStrategy, RelroLevel};
|
||||
use rustc_back::target::{Target, TargetTriple};
|
||||
use rustc_target::spec::{LinkerFlavor, PanicStrategy, RelroLevel};
|
||||
use rustc_target::spec::{Target, TargetTriple};
|
||||
use rustc_data_structures::stable_hasher::ToStableHashKey;
|
||||
use lint;
|
||||
use middle::cstore;
|
||||
@ -770,7 +770,7 @@ macro_rules! options {
|
||||
pub const parse_sanitizer: Option<&'static str> =
|
||||
Some("one of: `address`, `leak`, `memory` or `thread`");
|
||||
pub const parse_linker_flavor: Option<&'static str> =
|
||||
Some(::rustc_back::LinkerFlavor::one_of());
|
||||
Some(::rustc_target::spec::LinkerFlavor::one_of());
|
||||
pub const parse_optimization_fuel: Option<&'static str> =
|
||||
Some("crate=integer");
|
||||
pub const parse_unpretty: Option<&'static str> =
|
||||
@ -782,7 +782,7 @@ macro_rules! options {
|
||||
#[allow(dead_code)]
|
||||
mod $mod_set {
|
||||
use super::{$struct_name, Passes, SomePasses, AllPasses, Sanitizer, Lto};
|
||||
use rustc_back::{LinkerFlavor, PanicStrategy, RelroLevel};
|
||||
use rustc_target::spec::{LinkerFlavor, PanicStrategy, RelroLevel};
|
||||
use std::path::PathBuf;
|
||||
|
||||
$(
|
||||
@ -2323,8 +2323,7 @@ mod dep_tracking {
|
||||
use super::{CrateType, DebugInfoLevel, ErrorOutputType, Lto, OptLevel, OutputTypes,
|
||||
Passes, Sanitizer};
|
||||
use syntax::feature_gate::UnstableFeatures;
|
||||
use rustc_back::{PanicStrategy, RelroLevel};
|
||||
use rustc_back::target::TargetTriple;
|
||||
use rustc_target::spec::{PanicStrategy, RelroLevel, TargetTriple};
|
||||
use syntax::edition::Edition;
|
||||
|
||||
pub trait DepTrackingHash {
|
||||
@ -2456,7 +2455,7 @@ mod tests {
|
||||
use std::iter::FromIterator;
|
||||
use std::path::PathBuf;
|
||||
use super::{Externs, OutputType, OutputTypes};
|
||||
use rustc_back::{PanicStrategy, RelroLevel};
|
||||
use rustc_target::spec::{PanicStrategy, RelroLevel};
|
||||
use syntax::symbol::Symbol;
|
||||
use syntax::edition::{Edition, DEFAULT_EDITION};
|
||||
use syntax;
|
||||
|
@ -41,8 +41,8 @@ use syntax::{ast, codemap};
|
||||
use syntax::feature_gate::AttributeType;
|
||||
use syntax_pos::{MultiSpan, Span};
|
||||
|
||||
use rustc_back::{LinkerFlavor, PanicStrategy};
|
||||
use rustc_back::target::{Target, TargetTriple};
|
||||
use rustc_target::spec::{LinkerFlavor, PanicStrategy};
|
||||
use rustc_target::spec::{Target, TargetTriple};
|
||||
use rustc_data_structures::flock;
|
||||
use jobserver::Client;
|
||||
|
||||
|
@ -1091,7 +1091,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
tcx.mk_infer(ty::TyVar(ty::TyVid { index: 0 })),
|
||||
false,
|
||||
hir::Unsafety::Normal,
|
||||
::syntax::abi::Abi::Rust
|
||||
::rustc_target::spec::abi::Abi::Rust
|
||||
)
|
||||
} else {
|
||||
tcx.mk_fn_sig(
|
||||
@ -1099,7 +1099,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
tcx.mk_infer(ty::TyVar(ty::TyVid { index: 0 })),
|
||||
false,
|
||||
hir::Unsafety::Normal,
|
||||
::syntax::abi::Abi::Rust
|
||||
::rustc_target::spec::abi::Abi::Rust
|
||||
)
|
||||
};
|
||||
format!("{}", ty::Binder::bind(sig))
|
||||
|
@ -51,7 +51,7 @@ use std::cmp;
|
||||
use std::fmt;
|
||||
use std::mem;
|
||||
use std::rc::Rc;
|
||||
use syntax::abi::Abi;
|
||||
use rustc_target::spec::abi::Abi;
|
||||
use hir;
|
||||
use util::nodemap::{FxHashMap, FxHashSet};
|
||||
|
||||
|
@ -70,7 +70,7 @@ use std::ops::Deref;
|
||||
use std::iter;
|
||||
use std::sync::mpsc;
|
||||
use std::sync::Arc;
|
||||
use syntax::abi;
|
||||
use rustc_target::spec::abi;
|
||||
use syntax::ast::{self, NodeId};
|
||||
use syntax::attr;
|
||||
use syntax::codemap::MultiSpan;
|
||||
@ -1204,7 +1204,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
f: F) -> R
|
||||
where F: for<'b> FnOnce(TyCtxt<'b, 'tcx, 'tcx>) -> R
|
||||
{
|
||||
let data_layout = TargetDataLayout::parse(s);
|
||||
let data_layout = TargetDataLayout::parse(&s.target.target).unwrap_or_else(|err| {
|
||||
s.fatal(&err);
|
||||
});
|
||||
let interners = CtxtInterners::new(&arenas.interner);
|
||||
let common_types = CommonTypes::new(&interners);
|
||||
let dep_graph = hir.dep_graph.clone();
|
||||
|
@ -11,7 +11,7 @@
|
||||
use hir::def_id::DefId;
|
||||
use ty::{self, BoundRegion, Region, Ty, TyCtxt};
|
||||
use std::fmt;
|
||||
use syntax::abi;
|
||||
use rustc_target::spec::abi;
|
||||
use syntax::ast;
|
||||
use errors::DiagnosticBuilder;
|
||||
use syntax_pos::Span;
|
||||
|
@ -12,7 +12,7 @@ use hir::def_id::DefId;
|
||||
use ty::{self, Ty, TypeFoldable, Substs, TyCtxt};
|
||||
use ty::subst::Kind;
|
||||
use traits;
|
||||
use syntax::abi::Abi;
|
||||
use rustc_target::spec::abi::Abi;
|
||||
use util::ppaux;
|
||||
|
||||
use std::fmt;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -45,7 +45,7 @@ use util::nodemap::{DefIdSet, DefIdMap, ItemLocalSet};
|
||||
use util::common::{profq_msg, ErrorReported, ProfileQueriesMsg};
|
||||
|
||||
use rustc_data_structures::indexed_set::IdxSetBuf;
|
||||
use rustc_back::PanicStrategy;
|
||||
use rustc_target::spec::PanicStrategy;
|
||||
use rustc_data_structures::indexed_vec::IndexVec;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::stable_hasher::StableVec;
|
||||
|
@ -22,7 +22,7 @@ use mir::interpret::{GlobalId, Value, PrimVal};
|
||||
use util::common::ErrorReported;
|
||||
use std::rc::Rc;
|
||||
use std::iter;
|
||||
use syntax::abi;
|
||||
use rustc_target::spec::abi;
|
||||
use hir as ast;
|
||||
use rustc_data_structures::accumulate_vec::AccumulateVec;
|
||||
|
||||
|
@ -44,7 +44,7 @@ CloneTypeFoldableAndLiftImpls! {
|
||||
::hir::MatchSource,
|
||||
::hir::Mutability,
|
||||
::hir::Unsafety,
|
||||
::syntax::abi::Abi,
|
||||
::rustc_target::spec::abi::Abi,
|
||||
::mir::Local,
|
||||
::mir::Promoted,
|
||||
::traits::Reveal,
|
||||
|
@ -22,7 +22,7 @@ use util::captures::Captures;
|
||||
|
||||
use std::iter;
|
||||
use std::cmp::Ordering;
|
||||
use syntax::abi;
|
||||
use rustc_target::spec::abi;
|
||||
use syntax::ast::{self, Name};
|
||||
use syntax::symbol::{keywords, InternedString};
|
||||
|
||||
|
@ -22,7 +22,7 @@ use ty::fold::TypeVisitor;
|
||||
use ty::subst::UnpackedKind;
|
||||
use ty::maps::TyCtxtAt;
|
||||
use ty::TypeVariants::*;
|
||||
use ty::layout::Integer;
|
||||
use ty::layout::{Integer, IntegerExt};
|
||||
use util::common::ErrorReported;
|
||||
use middle::lang_items;
|
||||
use mir::interpret::{Value, PrimVal};
|
||||
|
@ -28,7 +28,7 @@ use std::fmt;
|
||||
use std::usize;
|
||||
|
||||
use rustc_data_structures::indexed_vec::Idx;
|
||||
use syntax::abi::Abi;
|
||||
use rustc_target::spec::abi::Abi;
|
||||
use syntax::ast::CRATE_NODE_ID;
|
||||
use syntax::symbol::{Symbol, InternedString};
|
||||
use hir;
|
||||
|
@ -11,5 +11,6 @@ test = false
|
||||
[dependencies]
|
||||
rustc = { path = "../librustc" }
|
||||
rustc_errors = { path = "../librustc_errors" }
|
||||
rustc_target = { path = "../librustc_target" }
|
||||
syntax = { path = "../libsyntax" }
|
||||
syntax_pos = { path = "../libsyntax_pos" }
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
use rustc::middle::allocator::AllocatorKind;
|
||||
use rustc_errors;
|
||||
use syntax::abi::Abi;
|
||||
use rustc_target::spec::abi::Abi;
|
||||
use syntax::ast::{Attribute, Crate, LitKind, StrStyle};
|
||||
use syntax::ast::{Arg, Constness, Generics, Mac, Mutability, Ty, Unsafety};
|
||||
use syntax::ast::{self, Expr, Ident, Item, ItemKind, TyKind, VisibilityKind};
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
extern crate rustc;
|
||||
extern crate rustc_errors;
|
||||
extern crate rustc_target;
|
||||
extern crate syntax;
|
||||
extern crate syntax_pos;
|
||||
|
||||
|
@ -1,6 +0,0 @@
|
||||
`librustc_back` contains some very low-level details that are
|
||||
specific to different LLVM targets and so forth.
|
||||
|
||||
For more information about how trans works, see the [rustc guide].
|
||||
|
||||
[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/trans.html
|
@ -1,170 +0,0 @@
|
||||
// Copyright 2012-2013 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.
|
||||
|
||||
//! Some stuff used by rustc that doesn't have many dependencies
|
||||
//!
|
||||
//! Originally extracted from rustc::back, which was nominally the
|
||||
//! compiler 'backend', though LLVM is rustc's backend, so rustc_back
|
||||
//! is really just odds-and-ends relating to code gen and linking.
|
||||
//! This crate mostly exists to make rustc smaller, so we might put
|
||||
//! more 'stuff' here in the future. It does not have a dependency on
|
||||
//! rustc_llvm.
|
||||
//!
|
||||
//! FIXME: Split this into two crates: one that has deps on syntax, and
|
||||
//! one that doesn't; the one that doesn't might get decent parallel
|
||||
//! build speedups.
|
||||
|
||||
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
|
||||
html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
|
||||
html_root_url = "https://doc.rust-lang.org/nightly/")]
|
||||
|
||||
#![feature(box_syntax)]
|
||||
#![feature(const_fn)]
|
||||
#![feature(fs_read_write)]
|
||||
|
||||
extern crate syntax;
|
||||
extern crate rand;
|
||||
extern crate serialize;
|
||||
#[macro_use] extern crate log;
|
||||
|
||||
extern crate serialize as rustc_serialize; // used by deriving
|
||||
|
||||
pub mod target;
|
||||
|
||||
use std::str::FromStr;
|
||||
|
||||
use serialize::json::{Json, ToJson};
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Hash,
|
||||
RustcEncodable, RustcDecodable)]
|
||||
pub enum LinkerFlavor {
|
||||
Em,
|
||||
Gcc,
|
||||
Ld,
|
||||
Msvc,
|
||||
Lld(LldFlavor),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Hash,
|
||||
RustcEncodable, RustcDecodable)]
|
||||
pub enum LldFlavor {
|
||||
Wasm,
|
||||
Ld64,
|
||||
Ld,
|
||||
Link,
|
||||
}
|
||||
|
||||
impl ToJson for LinkerFlavor {
|
||||
fn to_json(&self) -> Json {
|
||||
self.desc().to_json()
|
||||
}
|
||||
}
|
||||
macro_rules! flavor_mappings {
|
||||
($((($($flavor:tt)*), $string:expr),)*) => (
|
||||
impl LinkerFlavor {
|
||||
pub const fn one_of() -> &'static str {
|
||||
concat!("one of: ", $($string, " ",)+)
|
||||
}
|
||||
|
||||
pub fn from_str(s: &str) -> Option<Self> {
|
||||
Some(match s {
|
||||
$($string => $($flavor)*,)+
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn desc(&self) -> &str {
|
||||
match *self {
|
||||
$($($flavor)* => $string,)+
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
flavor_mappings! {
|
||||
((LinkerFlavor::Em), "em"),
|
||||
((LinkerFlavor::Gcc), "gcc"),
|
||||
((LinkerFlavor::Ld), "ld"),
|
||||
((LinkerFlavor::Msvc), "msvc"),
|
||||
((LinkerFlavor::Lld(LldFlavor::Wasm)), "wasm-ld"),
|
||||
((LinkerFlavor::Lld(LldFlavor::Ld64)), "ld64.lld"),
|
||||
((LinkerFlavor::Lld(LldFlavor::Ld)), "ld.lld"),
|
||||
((LinkerFlavor::Lld(LldFlavor::Link)), "lld-link"),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)]
|
||||
pub enum PanicStrategy {
|
||||
Unwind,
|
||||
Abort,
|
||||
}
|
||||
|
||||
impl PanicStrategy {
|
||||
pub fn desc(&self) -> &str {
|
||||
match *self {
|
||||
PanicStrategy::Unwind => "unwind",
|
||||
PanicStrategy::Abort => "abort",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToJson for PanicStrategy {
|
||||
fn to_json(&self) -> Json {
|
||||
match *self {
|
||||
PanicStrategy::Abort => "abort".to_json(),
|
||||
PanicStrategy::Unwind => "unwind".to_json(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)]
|
||||
pub enum RelroLevel {
|
||||
Full,
|
||||
Partial,
|
||||
Off,
|
||||
None,
|
||||
}
|
||||
|
||||
impl RelroLevel {
|
||||
pub fn desc(&self) -> &str {
|
||||
match *self {
|
||||
RelroLevel::Full => "full",
|
||||
RelroLevel::Partial => "partial",
|
||||
RelroLevel::Off => "off",
|
||||
RelroLevel::None => "none",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for RelroLevel {
|
||||
type Err = ();
|
||||
|
||||
fn from_str(s: &str) -> Result<RelroLevel, ()> {
|
||||
match s {
|
||||
"full" => Ok(RelroLevel::Full),
|
||||
"partial" => Ok(RelroLevel::Partial),
|
||||
"off" => Ok(RelroLevel::Off),
|
||||
"none" => Ok(RelroLevel::None),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToJson for RelroLevel {
|
||||
fn to_json(&self) -> Json {
|
||||
match *self {
|
||||
RelroLevel::Full => "full".to_json(),
|
||||
RelroLevel::Partial => "partial".to_json(),
|
||||
RelroLevel::Off => "off".to_json(),
|
||||
RelroLevel::None => "None".to_json(),
|
||||
}
|
||||
}
|
||||
}
|
@ -21,3 +21,4 @@ crate-type = ["dylib"]
|
||||
|
||||
[dependencies]
|
||||
bitflags = "1.0"
|
||||
log = "0.4"
|
||||
|
@ -12,3 +12,4 @@
|
||||
#![allow(unused_extern_crates)]
|
||||
|
||||
extern crate bitflags;
|
||||
extern crate log;
|
||||
|
@ -11,6 +11,7 @@ crate-type = ["dylib"]
|
||||
[dependencies]
|
||||
ena = "0.9.1"
|
||||
log = "0.4"
|
||||
rustc_cratesio_shim = { path = "../librustc_cratesio_shim" }
|
||||
serialize = { path = "../libserialize" }
|
||||
cfg-if = "0.1.2"
|
||||
stable_deref_trait = "1.0.0"
|
||||
|
@ -45,6 +45,10 @@ extern crate parking_lot;
|
||||
extern crate cfg_if;
|
||||
extern crate stable_deref_trait;
|
||||
|
||||
// See librustc_cratesio_shim/Cargo.toml for a comment explaining this.
|
||||
#[allow(unused_extern_crates)]
|
||||
extern crate rustc_cratesio_shim;
|
||||
|
||||
pub use rustc_serialize::hex::ToHex;
|
||||
|
||||
pub mod array_vec;
|
||||
|
@ -15,7 +15,7 @@ log = "0.4"
|
||||
env_logger = { version = "0.5", default-features = false }
|
||||
rustc = { path = "../librustc" }
|
||||
rustc_allocator = { path = "../librustc_allocator" }
|
||||
rustc_back = { path = "../librustc_back" }
|
||||
rustc_target = { path = "../librustc_target" }
|
||||
rustc_borrowck = { path = "../librustc_borrowck" }
|
||||
rustc_data_structures = { path = "../librustc_data_structures" }
|
||||
rustc_errors = { path = "../librustc_errors" }
|
||||
|
@ -35,7 +35,7 @@ extern crate env_logger;
|
||||
extern crate libc;
|
||||
extern crate rustc;
|
||||
extern crate rustc_allocator;
|
||||
extern crate rustc_back;
|
||||
extern crate rustc_target;
|
||||
extern crate rustc_borrowck;
|
||||
extern crate rustc_data_structures;
|
||||
extern crate rustc_errors as errors;
|
||||
@ -1021,7 +1021,7 @@ impl RustcDefaultCalls {
|
||||
for req in &sess.opts.prints {
|
||||
match *req {
|
||||
TargetList => {
|
||||
let mut targets = rustc_back::target::get_targets().collect::<Vec<String>>();
|
||||
let mut targets = rustc_target::spec::get_targets().collect::<Vec<String>>();
|
||||
targets.sort();
|
||||
println!("{}", targets.join("\n"));
|
||||
},
|
||||
|
@ -31,7 +31,7 @@ use rustc::session::config::{OutputFilenames, OutputTypes};
|
||||
use rustc_data_structures::sync::{self, Lrc};
|
||||
use syntax;
|
||||
use syntax::ast;
|
||||
use syntax::abi::Abi;
|
||||
use rustc_target::spec::abi::Abi;
|
||||
use syntax::codemap::{CodeMap, FilePathMapping, FileName};
|
||||
use errors;
|
||||
use errors::emitter::Emitter;
|
||||
|
@ -13,5 +13,6 @@ test = false
|
||||
log = "0.4"
|
||||
rustc = { path = "../librustc" }
|
||||
rustc_mir = { path = "../librustc_mir"}
|
||||
rustc_target = { path = "../librustc_target" }
|
||||
syntax = { path = "../libsyntax" }
|
||||
syntax_pos = { path = "../libsyntax_pos" }
|
||||
|
@ -13,7 +13,7 @@ use rustc::ty;
|
||||
use lint::{LateContext, LintContext, LintArray};
|
||||
use lint::{LintPass, LateLintPass};
|
||||
|
||||
use syntax::abi::Abi;
|
||||
use rustc_target::spec::abi::Abi;
|
||||
use syntax::ast;
|
||||
use syntax::attr;
|
||||
use syntax_pos::Span;
|
||||
|
@ -1169,7 +1169,7 @@ impl LintPass for MutableTransmutes {
|
||||
|
||||
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutableTransmutes {
|
||||
fn check_expr(&mut self, cx: &LateContext, expr: &hir::Expr) {
|
||||
use syntax::abi::Abi::RustIntrinsic;
|
||||
use rustc_target::spec::abi::Abi::RustIntrinsic;
|
||||
|
||||
let msg = "mutating transmuted &mut T from &T may cause undefined behavior, \
|
||||
consider instead using an UnsafeCell";
|
||||
|
@ -37,6 +37,7 @@ extern crate rustc;
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
extern crate rustc_mir;
|
||||
extern crate rustc_target;
|
||||
extern crate syntax_pos;
|
||||
|
||||
use rustc::lint;
|
||||
|
@ -13,7 +13,7 @@
|
||||
use rustc::hir::map as hir_map;
|
||||
use rustc::ty::subst::Substs;
|
||||
use rustc::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt};
|
||||
use rustc::ty::layout::{self, LayoutOf};
|
||||
use rustc::ty::layout::{self, IntegerExt, LayoutOf};
|
||||
use util::nodemap::FxHashSet;
|
||||
use lint::{LateContext, LintContext, LintArray};
|
||||
use lint::{LintPass, LateLintPass};
|
||||
@ -22,7 +22,7 @@ use std::cmp;
|
||||
use std::{i8, i16, i32, i64, u8, u16, u32, u64, f32, f64};
|
||||
|
||||
use syntax::{ast, attr};
|
||||
use syntax::abi::Abi;
|
||||
use rustc_target::spec::abi::Abi;
|
||||
use syntax_pos::Span;
|
||||
use syntax::codemap;
|
||||
|
||||
|
@ -13,7 +13,7 @@ flate2 = "1.0"
|
||||
log = "0.4"
|
||||
proc_macro = { path = "../libproc_macro" }
|
||||
rustc = { path = "../librustc" }
|
||||
rustc_back = { path = "../librustc_back" }
|
||||
rustc_target = { path = "../librustc_target" }
|
||||
rustc_data_structures = { path = "../librustc_data_structures" }
|
||||
rustc_errors = { path = "../librustc_errors" }
|
||||
serialize = { path = "../libserialize" }
|
||||
|
@ -21,8 +21,7 @@ use rustc::middle::allocator::AllocatorKind;
|
||||
use rustc::middle::cstore::DepKind;
|
||||
use rustc::session::{Session, CrateDisambiguator};
|
||||
use rustc::session::config::{Sanitizer, self};
|
||||
use rustc_back::PanicStrategy;
|
||||
use rustc_back::target::TargetTriple;
|
||||
use rustc_target::spec::{PanicStrategy, TargetTriple};
|
||||
use rustc::session::search_paths::PathKind;
|
||||
use rustc::middle;
|
||||
use rustc::middle::cstore::{validate_crate_name, ExternCrate, ExternCrateSource};
|
||||
|
@ -18,7 +18,7 @@ use rustc::hir::map::definitions::DefPathTable;
|
||||
use rustc::hir::svh::Svh;
|
||||
use rustc::middle::cstore::{DepKind, ExternCrate, MetadataLoader};
|
||||
use rustc::session::{Session, CrateDisambiguator};
|
||||
use rustc_back::PanicStrategy;
|
||||
use rustc_target::spec::PanicStrategy;
|
||||
use rustc_data_structures::indexed_vec::IndexVec;
|
||||
use rustc::util::nodemap::{FxHashMap, NodeMap};
|
||||
|
||||
|
@ -38,7 +38,7 @@ extern crate proc_macro;
|
||||
|
||||
#[macro_use]
|
||||
extern crate rustc;
|
||||
extern crate rustc_back;
|
||||
extern crate rustc_target;
|
||||
#[macro_use]
|
||||
extern crate rustc_data_structures;
|
||||
|
||||
|
@ -11,7 +11,7 @@
|
||||
use rustc::hir::itemlikevisit::ItemLikeVisitor;
|
||||
use rustc::hir;
|
||||
use rustc::ty::TyCtxt;
|
||||
use syntax::abi::Abi;
|
||||
use rustc_target::spec::abi::Abi;
|
||||
|
||||
pub fn collect<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Vec<String> {
|
||||
let mut collector = Collector {
|
||||
|
@ -236,7 +236,7 @@ use rustc::util::nodemap::FxHashMap;
|
||||
use errors::DiagnosticBuilder;
|
||||
use syntax::symbol::Symbol;
|
||||
use syntax_pos::Span;
|
||||
use rustc_back::target::{Target, TargetTriple};
|
||||
use rustc_target::spec::{Target, TargetTriple};
|
||||
|
||||
use std::cmp;
|
||||
use std::collections::HashSet;
|
||||
|
@ -14,7 +14,7 @@ use rustc::middle::cstore::{self, NativeLibrary};
|
||||
use rustc::session::Session;
|
||||
use rustc::ty::TyCtxt;
|
||||
use rustc::util::nodemap::FxHashSet;
|
||||
use syntax::abi::Abi;
|
||||
use rustc_target::spec::abi::Abi;
|
||||
use syntax::attr;
|
||||
use syntax::codemap::Span;
|
||||
use syntax::feature_gate::{self, GateIssue};
|
||||
|
@ -19,8 +19,7 @@ use rustc::middle::lang_items;
|
||||
use rustc::mir;
|
||||
use rustc::session::CrateDisambiguator;
|
||||
use rustc::ty::{self, Ty, ReprOptions};
|
||||
use rustc_back::PanicStrategy;
|
||||
use rustc_back::target::TargetTriple;
|
||||
use rustc_target::spec::{PanicStrategy, TargetTriple};
|
||||
|
||||
use rustc_serialize as serialize;
|
||||
use syntax::{ast, attr};
|
||||
|
@ -15,7 +15,7 @@ graphviz = { path = "../libgraphviz" }
|
||||
log = "0.4"
|
||||
log_settings = "0.1.1"
|
||||
rustc = { path = "../librustc" }
|
||||
rustc_back = { path = "../librustc_back" }
|
||||
rustc_target = { path = "../librustc_target" }
|
||||
rustc_const_math = { path = "../librustc_const_math" }
|
||||
rustc_data_structures = { path = "../librustc_data_structures" }
|
||||
rustc_errors = { path = "../librustc_errors" }
|
||||
|
@ -16,7 +16,7 @@ use hair::*;
|
||||
use rustc::ty;
|
||||
use rustc::mir::*;
|
||||
|
||||
use syntax::abi::Abi;
|
||||
use rustc_target::spec::abi::Abi;
|
||||
|
||||
impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
/// Compile `expr`, storing the result into `destination`, which
|
||||
|
@ -20,12 +20,12 @@ use rustc::mir::visit::{MutVisitor, TyContext};
|
||||
use rustc::ty::{self, Ty, TyCtxt};
|
||||
use rustc::ty::subst::Substs;
|
||||
use rustc::util::nodemap::NodeMap;
|
||||
use rustc_back::PanicStrategy;
|
||||
use rustc_target::spec::PanicStrategy;
|
||||
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
|
||||
use shim;
|
||||
use std::mem;
|
||||
use std::u32;
|
||||
use syntax::abi::Abi;
|
||||
use rustc_target::spec::abi::Abi;
|
||||
use syntax::ast;
|
||||
use syntax::attr::{self, UnwindAttr};
|
||||
use syntax::symbol::keywords;
|
||||
|
@ -22,6 +22,7 @@ use rustc::hir::def_id::{DefId, LOCAL_CRATE};
|
||||
use rustc::hir::map::blocks::FnLikeNode;
|
||||
use rustc::middle::region;
|
||||
use rustc::infer::InferCtxt;
|
||||
use rustc::ty::layout::IntegerExt;
|
||||
use rustc::ty::subst::Subst;
|
||||
use rustc::ty::{self, Ty, TyCtxt, layout};
|
||||
use rustc::ty::subst::Substs;
|
||||
|
@ -5,7 +5,7 @@ use rustc::hir::def::Def;
|
||||
use rustc::hir::map::definitions::DefPathData;
|
||||
use rustc::middle::const_val::{ConstVal, ErrKind};
|
||||
use rustc::mir;
|
||||
use rustc::ty::layout::{self, Size, Align, HasDataLayout, LayoutOf, TyLayout};
|
||||
use rustc::ty::layout::{self, Size, Align, HasDataLayout, IntegerExt, LayoutOf, TyLayout};
|
||||
use rustc::ty::subst::{Subst, Substs};
|
||||
use rustc::ty::{self, Ty, TyCtxt};
|
||||
use rustc::ty::maps::TyCtxtAt;
|
||||
@ -162,7 +162,8 @@ impl<'c, 'b, 'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> layout::HasTyCtxt<'tcx>
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> LayoutOf<Ty<'tcx>> for &'a EvalContext<'a, 'mir, 'tcx, M> {
|
||||
impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> LayoutOf for &'a EvalContext<'a, 'mir, 'tcx, M> {
|
||||
type Ty = Ty<'tcx>;
|
||||
type TyLayout = EvalResult<'tcx, TyLayout<'tcx>>;
|
||||
|
||||
fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout {
|
||||
@ -171,8 +172,9 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> LayoutOf<Ty<'tcx>> for &'a EvalCont
|
||||
}
|
||||
}
|
||||
|
||||
impl<'c, 'b, 'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> LayoutOf<Ty<'tcx>>
|
||||
impl<'c, 'b, 'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> LayoutOf
|
||||
for &'c &'b mut EvalContext<'a, 'mir, 'tcx, M> {
|
||||
type Ty = Ty<'tcx>;
|
||||
type TyLayout = EvalResult<'tcx, TyLayout<'tcx>>;
|
||||
|
||||
#[inline]
|
||||
|
@ -2,7 +2,7 @@ use rustc::mir;
|
||||
use rustc::ty::{self, Ty};
|
||||
use rustc::ty::layout::LayoutOf;
|
||||
use syntax::codemap::Span;
|
||||
use syntax::abi::Abi;
|
||||
use rustc_target::spec::abi::Abi;
|
||||
|
||||
use rustc::mir::interpret::{EvalResult, PrimVal, Value};
|
||||
use super::{EvalContext, Place, Machine, ValTy};
|
||||
|
@ -49,7 +49,7 @@ extern crate rustc_errors;
|
||||
#[macro_use]
|
||||
extern crate syntax;
|
||||
extern crate syntax_pos;
|
||||
extern crate rustc_back;
|
||||
extern crate rustc_target;
|
||||
extern crate rustc_const_math;
|
||||
extern crate core; // for NonZero
|
||||
extern crate log_settings;
|
||||
|
@ -339,7 +339,7 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
|
||||
}
|
||||
|
||||
let abi = sig.abi();
|
||||
if abi != ::syntax::abi::Abi::Rust {
|
||||
if abi != ::rustc_target::spec::abi::Abi::Rust {
|
||||
output.push_str("extern \"");
|
||||
output.push_str(abi.name());
|
||||
output.push_str("\" ");
|
||||
|
@ -20,7 +20,7 @@ use rustc::mir::interpret::{Value, PrimVal};
|
||||
|
||||
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
|
||||
|
||||
use syntax::abi::Abi;
|
||||
use rustc_target::spec::abi::Abi;
|
||||
use syntax::ast;
|
||||
use syntax_pos::Span;
|
||||
|
||||
|
@ -72,7 +72,8 @@ struct ConstPropagator<'b, 'a, 'tcx:'a+'b> {
|
||||
param_env: ParamEnv<'tcx>,
|
||||
}
|
||||
|
||||
impl<'a, 'b, 'tcx> LayoutOf<ty::Ty<'tcx>> for &'a ConstPropagator<'a, 'b, 'tcx> {
|
||||
impl<'a, 'b, 'tcx> LayoutOf for &'a ConstPropagator<'a, 'b, 'tcx> {
|
||||
type Ty = ty::Ty<'tcx>;
|
||||
type TyLayout = Result<TyLayout<'tcx>, LayoutError<'tcx>>;
|
||||
|
||||
fn layout_of(self, ty: ty::Ty<'tcx>) -> Self::TyLayout {
|
||||
|
@ -28,7 +28,7 @@ use transform::{MirPass, MirSource};
|
||||
use super::simplify::{remove_dead_blocks, CfgSimplifier};
|
||||
|
||||
use syntax::{attr};
|
||||
use syntax::abi::Abi;
|
||||
use rustc_target::spec::abi::Abi;
|
||||
|
||||
const DEFAULT_THRESHOLD: usize = 50;
|
||||
const HINT_THRESHOLD: usize = 100;
|
||||
|
@ -29,7 +29,7 @@ use rustc::mir::*;
|
||||
use rustc::mir::traversal::ReversePostorder;
|
||||
use rustc::mir::visit::{PlaceContext, Visitor};
|
||||
use rustc::middle::lang_items;
|
||||
use syntax::abi::Abi;
|
||||
use rustc_target::spec::abi::Abi;
|
||||
use syntax::attr;
|
||||
use syntax::ast::LitKind;
|
||||
use syntax::feature_gate::UnstableFeatures;
|
||||
|
@ -8,7 +8,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use syntax::abi::{Abi};
|
||||
use rustc_target::spec::abi::{Abi};
|
||||
use syntax::ast;
|
||||
use syntax_pos::Span;
|
||||
|
||||
|
@ -12,6 +12,7 @@ crate-type = ["dylib"]
|
||||
log = "0.4"
|
||||
rustc = { path = "../librustc" }
|
||||
rustc_data_structures = { path = "../librustc_data_structures" }
|
||||
rustc_target = { path = "../librustc_target" }
|
||||
rustc_typeck = { path = "../librustc_typeck" }
|
||||
syntax = { path = "../libsyntax" }
|
||||
syntax_pos = { path = "../libsyntax_pos" }
|
||||
|
@ -22,6 +22,7 @@ extern crate rustc;
|
||||
extern crate log;
|
||||
extern crate rustc_data_structures;
|
||||
extern crate rustc_serialize;
|
||||
extern crate rustc_target;
|
||||
extern crate rustc_typeck;
|
||||
#[macro_use]
|
||||
extern crate syntax;
|
||||
|
@ -237,7 +237,7 @@ impl Sig for ast::Ty {
|
||||
if f.unsafety == ast::Unsafety::Unsafe {
|
||||
text.push_str("unsafe ");
|
||||
}
|
||||
if f.abi != ::syntax::abi::Abi::Rust {
|
||||
if f.abi != ::rustc_target::spec::abi::Abi::Rust {
|
||||
text.push_str("extern");
|
||||
text.push_str(&f.abi.to_string());
|
||||
text.push(' ');
|
||||
@ -388,7 +388,7 @@ impl Sig for ast::Item {
|
||||
if unsafety == ast::Unsafety::Unsafe {
|
||||
text.push_str("unsafe ");
|
||||
}
|
||||
if abi != ::syntax::abi::Abi::Rust {
|
||||
if abi != ::rustc_target::spec::abi::Abi::Rust {
|
||||
text.push_str("extern");
|
||||
text.push_str(&abi.to_string());
|
||||
text.push(' ');
|
||||
@ -931,7 +931,7 @@ fn make_method_signature(
|
||||
if m.unsafety == ast::Unsafety::Unsafe {
|
||||
text.push_str("unsafe ");
|
||||
}
|
||||
if m.abi != ::syntax::abi::Abi::Rust {
|
||||
if m.abi != ::rustc_target::spec::abi::Abi::Rust {
|
||||
text.push_str("extern");
|
||||
text.push_str(&m.abi.to_string());
|
||||
text.push(' ');
|
||||
|
@ -1,18 +1,18 @@
|
||||
[package]
|
||||
authors = ["The Rust Project Developers"]
|
||||
name = "rustc_back"
|
||||
name = "rustc_target"
|
||||
version = "0.0.0"
|
||||
|
||||
[lib]
|
||||
name = "rustc_back"
|
||||
name = "rustc_target"
|
||||
path = "lib.rs"
|
||||
crate-type = ["dylib"]
|
||||
|
||||
[dependencies]
|
||||
syntax = { path = "../libsyntax" }
|
||||
serialize = { path = "../libserialize" }
|
||||
bitflags = "1.0"
|
||||
log = "0.4"
|
||||
rand = "0.4"
|
||||
rustc_cratesio_shim = { path = "../librustc_cratesio_shim" }
|
||||
serialize = { path = "../libserialize" }
|
||||
|
||||
[features]
|
||||
jemalloc = []
|
6
src/librustc_target/README.md
Normal file
6
src/librustc_target/README.md
Normal file
@ -0,0 +1,6 @@
|
||||
`librustc_target` contains some very low-level details that are
|
||||
specific to different compilation targets and so forth.
|
||||
|
||||
For more information about how rustc works, see the [rustc guide].
|
||||
|
||||
[rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/
|
@ -8,11 +8,14 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use abi::{FnType, ArgType, LayoutExt, Reg, RegKind, Uniform};
|
||||
use context::CodegenCx;
|
||||
use abi::call::{FnType, ArgType, Reg, RegKind, Uniform};
|
||||
use abi::{HasDataLayout, LayoutOf, TyLayout, TyLayoutMethods};
|
||||
|
||||
fn is_homogeneous_aggregate<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgType<'tcx>)
|
||||
-> Option<Uniform> {
|
||||
fn is_homogeneous_aggregate<'a, Ty, C>(cx: C, arg: &mut ArgType<'a, Ty>)
|
||||
-> Option<Uniform>
|
||||
where Ty: TyLayoutMethods<'a, C> + Copy,
|
||||
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
|
||||
{
|
||||
arg.layout.homogeneous_aggregate(cx).and_then(|unit| {
|
||||
let size = arg.layout.size;
|
||||
|
||||
@ -38,7 +41,10 @@ fn is_homogeneous_aggregate<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgTyp
|
||||
})
|
||||
}
|
||||
|
||||
fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, ret: &mut ArgType<'tcx>) {
|
||||
fn classify_ret_ty<'a, Ty, C>(cx: C, ret: &mut ArgType<'a, Ty>)
|
||||
where Ty: TyLayoutMethods<'a, C> + Copy,
|
||||
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
|
||||
{
|
||||
if !ret.layout.is_aggregate() {
|
||||
ret.extend_integer_width_to(32);
|
||||
return;
|
||||
@ -69,7 +75,10 @@ fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, ret: &mut ArgType<'tcx>)
|
||||
ret.make_indirect();
|
||||
}
|
||||
|
||||
fn classify_arg_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgType<'tcx>) {
|
||||
fn classify_arg_ty<'a, Ty, C>(cx: C, arg: &mut ArgType<'a, Ty>)
|
||||
where Ty: TyLayoutMethods<'a, C> + Copy,
|
||||
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
|
||||
{
|
||||
if !arg.layout.is_aggregate() {
|
||||
arg.extend_integer_width_to(32);
|
||||
return;
|
||||
@ -100,7 +109,10 @@ fn classify_arg_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgType<'tcx>)
|
||||
arg.make_indirect();
|
||||
}
|
||||
|
||||
pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, fty: &mut FnType<'tcx>) {
|
||||
pub fn compute_abi_info<'a, Ty, C>(cx: C, fty: &mut FnType<'a, Ty>)
|
||||
where Ty: TyLayoutMethods<'a, C> + Copy,
|
||||
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
|
||||
{
|
||||
if !fty.ret.is_ignore() {
|
||||
classify_ret_ty(cx, &mut fty.ret);
|
||||
}
|
@ -8,12 +8,15 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use abi::{FnType, ArgType, LayoutExt, Reg, RegKind, Uniform};
|
||||
use context::CodegenCx;
|
||||
use llvm::CallConv;
|
||||
use abi::call::{Conv, FnType, ArgType, Reg, RegKind, Uniform};
|
||||
use abi::{HasDataLayout, LayoutOf, TyLayout, TyLayoutMethods};
|
||||
use spec::HasTargetSpec;
|
||||
|
||||
fn is_homogeneous_aggregate<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgType<'tcx>)
|
||||
-> Option<Uniform> {
|
||||
fn is_homogeneous_aggregate<'a, Ty, C>(cx: C, arg: &mut ArgType<'a, Ty>)
|
||||
-> Option<Uniform>
|
||||
where Ty: TyLayoutMethods<'a, C> + Copy,
|
||||
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
|
||||
{
|
||||
arg.layout.homogeneous_aggregate(cx).and_then(|unit| {
|
||||
let size = arg.layout.size;
|
||||
|
||||
@ -39,7 +42,10 @@ fn is_homogeneous_aggregate<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgTyp
|
||||
})
|
||||
}
|
||||
|
||||
fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, ret: &mut ArgType<'tcx>, vfp: bool) {
|
||||
fn classify_ret_ty<'a, Ty, C>(cx: C, ret: &mut ArgType<'a, Ty>, vfp: bool)
|
||||
where Ty: TyLayoutMethods<'a, C> + Copy,
|
||||
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
|
||||
{
|
||||
if !ret.layout.is_aggregate() {
|
||||
ret.extend_integer_width_to(32);
|
||||
return;
|
||||
@ -71,7 +77,10 @@ fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, ret: &mut ArgType<'tcx>,
|
||||
ret.make_indirect();
|
||||
}
|
||||
|
||||
fn classify_arg_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgType<'tcx>, vfp: bool) {
|
||||
fn classify_arg_ty<'a, Ty, C>(cx: C, arg: &mut ArgType<'a, Ty>, vfp: bool)
|
||||
where Ty: TyLayoutMethods<'a, C> + Copy,
|
||||
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
|
||||
{
|
||||
if !arg.layout.is_aggregate() {
|
||||
arg.extend_integer_width_to(32);
|
||||
return;
|
||||
@ -92,11 +101,14 @@ fn classify_arg_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgType<'tcx>,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, fty: &mut FnType<'tcx>) {
|
||||
pub fn compute_abi_info<'a, Ty, C>(cx: C, fty: &mut FnType<'a, Ty>)
|
||||
where Ty: TyLayoutMethods<'a, C> + Copy,
|
||||
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout + HasTargetSpec
|
||||
{
|
||||
// If this is a target with a hard-float ABI, and the function is not explicitly
|
||||
// `extern "aapcs"`, then we must use the VFP registers for homogeneous aggregates.
|
||||
let vfp = cx.sess().target.target.llvm_target.ends_with("hf")
|
||||
&& fty.cconv != CallConv::ArmAapcsCallConv
|
||||
let vfp = cx.target_spec().llvm_target.ends_with("hf")
|
||||
&& fty.conv != Conv::ArmAapcs
|
||||
&& !fty.variadic;
|
||||
|
||||
if !fty.ret.is_ignore() {
|
@ -8,15 +8,18 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use abi::{FnType, ArgType, LayoutExt, Uniform};
|
||||
use context::CodegenCx;
|
||||
use abi::call::{FnType, ArgType, Uniform};
|
||||
use abi::{HasDataLayout, LayoutOf, TyLayout, TyLayoutMethods};
|
||||
|
||||
// Data layout: e-p:32:32-i64:64-v128:32:128-n32-S128
|
||||
|
||||
// See the https://github.com/kripken/emscripten-fastcomp-clang repository.
|
||||
// The class `EmscriptenABIInfo` in `/lib/CodeGen/TargetInfo.cpp` contains the ABI definitions.
|
||||
|
||||
fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, ret: &mut ArgType<'tcx>) {
|
||||
fn classify_ret_ty<'a, Ty, C>(cx: C, ret: &mut ArgType<'a, Ty>)
|
||||
where Ty: TyLayoutMethods<'a, C> + Copy,
|
||||
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
|
||||
{
|
||||
if ret.layout.is_aggregate() {
|
||||
if let Some(unit) = ret.layout.homogeneous_aggregate(cx) {
|
||||
let size = ret.layout.size;
|
||||
@ -33,13 +36,16 @@ fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, ret: &mut ArgType<'tcx>)
|
||||
}
|
||||
}
|
||||
|
||||
fn classify_arg_ty(arg: &mut ArgType) {
|
||||
fn classify_arg_ty<Ty>(arg: &mut ArgType<Ty>) {
|
||||
if arg.layout.is_aggregate() {
|
||||
arg.make_indirect_byval();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, fty: &mut FnType<'tcx>) {
|
||||
pub fn compute_abi_info<'a, Ty, C>(cx: C, fty: &mut FnType<'a, Ty>)
|
||||
where Ty: TyLayoutMethods<'a, C> + Copy,
|
||||
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
|
||||
{
|
||||
if !fty.ret.is_ignore() {
|
||||
classify_ret_ty(cx, &mut fty.ret);
|
||||
}
|
@ -10,9 +10,9 @@
|
||||
|
||||
#![allow(non_upper_case_globals)]
|
||||
|
||||
use abi::{FnType, ArgType, LayoutExt};
|
||||
use abi::call::{FnType, ArgType};
|
||||
|
||||
fn classify_ret_ty(ret: &mut ArgType) {
|
||||
fn classify_ret_ty<Ty>(ret: &mut ArgType<Ty>) {
|
||||
if ret.layout.is_aggregate() && ret.layout.size.bits() > 64 {
|
||||
ret.make_indirect();
|
||||
} else {
|
||||
@ -20,7 +20,7 @@ fn classify_ret_ty(ret: &mut ArgType) {
|
||||
}
|
||||
}
|
||||
|
||||
fn classify_arg_ty(arg: &mut ArgType) {
|
||||
fn classify_arg_ty<Ty>(arg: &mut ArgType<Ty>) {
|
||||
if arg.layout.is_aggregate() && arg.layout.size.bits() > 64 {
|
||||
arg.make_indirect();
|
||||
} else {
|
||||
@ -28,7 +28,7 @@ fn classify_arg_ty(arg: &mut ArgType) {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn compute_abi_info(fty: &mut FnType) {
|
||||
pub fn compute_abi_info<Ty>(fty: &mut FnType<Ty>) {
|
||||
if !fty.ret.is_ignore() {
|
||||
classify_ret_ty(&mut fty.ret);
|
||||
}
|
@ -8,24 +8,24 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use abi::{ArgType, FnType, LayoutExt, Reg, Uniform};
|
||||
use context::CodegenCx;
|
||||
use abi::call::{ArgType, FnType, Reg, Uniform};
|
||||
use abi::{HasDataLayout, LayoutOf, Size, TyLayoutMethods};
|
||||
|
||||
use rustc::ty::layout::Size;
|
||||
|
||||
fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
|
||||
ret: &mut ArgType<'tcx>,
|
||||
offset: &mut Size) {
|
||||
fn classify_ret_ty<'a, Ty, C>(cx: C, ret: &mut ArgType<Ty>, offset: &mut Size)
|
||||
where Ty: TyLayoutMethods<'a, C>, C: LayoutOf<Ty = Ty> + HasDataLayout
|
||||
{
|
||||
if !ret.layout.is_aggregate() {
|
||||
ret.extend_integer_width_to(32);
|
||||
} else {
|
||||
ret.make_indirect();
|
||||
*offset += cx.tcx.data_layout.pointer_size;
|
||||
*offset += cx.data_layout().pointer_size;
|
||||
}
|
||||
}
|
||||
|
||||
fn classify_arg_ty(cx: &CodegenCx, arg: &mut ArgType, offset: &mut Size) {
|
||||
let dl = &cx.tcx.data_layout;
|
||||
fn classify_arg_ty<'a, Ty, C>(cx: C, arg: &mut ArgType<Ty>, offset: &mut Size)
|
||||
where Ty: TyLayoutMethods<'a, C>, C: LayoutOf<Ty = Ty> + HasDataLayout
|
||||
{
|
||||
let dl = cx.data_layout();
|
||||
let size = arg.layout.size;
|
||||
let align = arg.layout.align.max(dl.i32_align).min(dl.i64_align);
|
||||
|
||||
@ -44,7 +44,9 @@ fn classify_arg_ty(cx: &CodegenCx, arg: &mut ArgType, offset: &mut Size) {
|
||||
*offset = offset.abi_align(align) + size.abi_align(align);
|
||||
}
|
||||
|
||||
pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, fty: &mut FnType<'tcx>) {
|
||||
pub fn compute_abi_info<'a, Ty, C>(cx: C, fty: &mut FnType<Ty>)
|
||||
where Ty: TyLayoutMethods<'a, C>, C: LayoutOf<Ty = Ty> + HasDataLayout
|
||||
{
|
||||
let mut offset = Size::from_bytes(0);
|
||||
if !fty.ret.is_ignore() {
|
||||
classify_ret_ty(cx, &mut fty.ret, &mut offset);
|
@ -8,14 +8,13 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use abi::{ArgAttribute, ArgType, CastTarget, FnType, LayoutExt, PassMode, Reg, RegKind, Uniform};
|
||||
use context::CodegenCx;
|
||||
use rustc::ty::layout::{self, Size};
|
||||
use abi::call::{ArgAttribute, ArgType, CastTarget, FnType, PassMode, Reg, RegKind, Uniform};
|
||||
use abi::{self, HasDataLayout, LayoutOf, Size, TyLayout, TyLayoutMethods};
|
||||
|
||||
fn extend_integer_width_mips(arg: &mut ArgType, bits: u64) {
|
||||
fn extend_integer_width_mips<Ty>(arg: &mut ArgType<Ty>, bits: u64) {
|
||||
// Always sign extend u32 values on 64-bit mips
|
||||
if let layout::Abi::Scalar(ref scalar) = arg.layout.abi {
|
||||
if let layout::Int(i, signed) = scalar.value {
|
||||
if let abi::Abi::Scalar(ref scalar) = arg.layout.abi {
|
||||
if let abi::Int(i, signed) = scalar.value {
|
||||
if !signed && i.size().bits() == 32 {
|
||||
if let PassMode::Direct(ref mut attrs) = arg.mode {
|
||||
attrs.set(ArgAttribute::SExt);
|
||||
@ -28,18 +27,24 @@ fn extend_integer_width_mips(arg: &mut ArgType, bits: u64) {
|
||||
arg.extend_integer_width_to(bits);
|
||||
}
|
||||
|
||||
fn float_reg<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, ret: &ArgType<'tcx>, i: usize) -> Option<Reg> {
|
||||
fn float_reg<'a, Ty, C>(cx: C, ret: &ArgType<'a, Ty>, i: usize) -> Option<Reg>
|
||||
where Ty: TyLayoutMethods<'a, C> + Copy,
|
||||
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
|
||||
{
|
||||
match ret.layout.field(cx, i).abi {
|
||||
layout::Abi::Scalar(ref scalar) => match scalar.value {
|
||||
layout::F32 => Some(Reg::f32()),
|
||||
layout::F64 => Some(Reg::f64()),
|
||||
abi::Abi::Scalar(ref scalar) => match scalar.value {
|
||||
abi::F32 => Some(Reg::f32()),
|
||||
abi::F64 => Some(Reg::f64()),
|
||||
_ => None
|
||||
},
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, ret: &mut ArgType<'tcx>) {
|
||||
fn classify_ret_ty<'a, Ty, C>(cx: C, ret: &mut ArgType<'a, Ty>)
|
||||
where Ty: TyLayoutMethods<'a, C> + Copy,
|
||||
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
|
||||
{
|
||||
if !ret.layout.is_aggregate() {
|
||||
extend_integer_width_mips(ret, 64);
|
||||
return;
|
||||
@ -52,7 +57,7 @@ fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, ret: &mut ArgType<'tcx>)
|
||||
// use of float registers to structures (not unions) containing exactly one or two
|
||||
// float fields.
|
||||
|
||||
if let layout::FieldPlacement::Arbitrary { .. } = ret.layout.fields {
|
||||
if let abi::FieldPlacement::Arbitrary { .. } = ret.layout.fields {
|
||||
if ret.layout.fields.count() == 1 {
|
||||
if let Some(reg) = float_reg(cx, ret, 0) {
|
||||
ret.cast_to(reg);
|
||||
@ -78,27 +83,30 @@ fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, ret: &mut ArgType<'tcx>)
|
||||
}
|
||||
}
|
||||
|
||||
fn classify_arg_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgType<'tcx>) {
|
||||
fn classify_arg_ty<'a, Ty, C>(cx: C, arg: &mut ArgType<'a, Ty>)
|
||||
where Ty: TyLayoutMethods<'a, C> + Copy,
|
||||
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
|
||||
{
|
||||
if !arg.layout.is_aggregate() {
|
||||
extend_integer_width_mips(arg, 64);
|
||||
return;
|
||||
}
|
||||
|
||||
let dl = &cx.tcx.data_layout;
|
||||
let dl = cx.data_layout();
|
||||
let size = arg.layout.size;
|
||||
let mut prefix = [None; 8];
|
||||
let mut prefix_index = 0;
|
||||
|
||||
match arg.layout.fields {
|
||||
layout::FieldPlacement::Array { .. } => {
|
||||
abi::FieldPlacement::Array { .. } => {
|
||||
// Arrays are passed indirectly
|
||||
arg.make_indirect();
|
||||
return;
|
||||
}
|
||||
layout::FieldPlacement::Union(_) => {
|
||||
abi::FieldPlacement::Union(_) => {
|
||||
// Unions and are always treated as a series of 64-bit integer chunks
|
||||
},
|
||||
layout::FieldPlacement::Arbitrary { .. } => {
|
||||
abi::FieldPlacement::Arbitrary { .. } => {
|
||||
// Structures are split up into a series of 64-bit integer chunks, but any aligned
|
||||
// doubles not part of another aggregate are passed as floats.
|
||||
let mut last_offset = Size::from_bytes(0);
|
||||
@ -108,8 +116,8 @@ fn classify_arg_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgType<'tcx>)
|
||||
let offset = arg.layout.fields.offset(i);
|
||||
|
||||
// We only care about aligned doubles
|
||||
if let layout::Abi::Scalar(ref scalar) = field.abi {
|
||||
if let layout::F64 = scalar.value {
|
||||
if let abi::Abi::Scalar(ref scalar) = field.abi {
|
||||
if let abi::F64 = scalar.value {
|
||||
if offset.is_abi_aligned(dl.f64_align) {
|
||||
// Insert enough integers to cover [last_offset, offset)
|
||||
assert!(last_offset.is_abi_aligned(dl.f64_align));
|
||||
@ -143,7 +151,10 @@ fn classify_arg_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgType<'tcx>)
|
||||
});
|
||||
}
|
||||
|
||||
pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, fty: &mut FnType<'tcx>) {
|
||||
pub fn compute_abi_info<'a, Ty, C>(cx: C, fty: &mut FnType<'a, Ty>)
|
||||
where Ty: TyLayoutMethods<'a, C> + Copy,
|
||||
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
|
||||
{
|
||||
if !fty.ret.is_ignore() {
|
||||
classify_ret_ty(cx, &mut fty.ret);
|
||||
}
|
511
src/librustc_target/abi/call/mod.rs
Normal file
511
src/librustc_target/abi/call/mod.rs
Normal file
@ -0,0 +1,511 @@
|
||||
// Copyright 2017 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.
|
||||
|
||||
use abi::{self, Abi, Align, FieldPlacement, Size};
|
||||
use abi::{HasDataLayout, LayoutOf, TyLayout, TyLayoutMethods};
|
||||
use spec::HasTargetSpec;
|
||||
|
||||
mod aarch64;
|
||||
mod arm;
|
||||
mod asmjs;
|
||||
mod hexagon;
|
||||
mod mips;
|
||||
mod mips64;
|
||||
mod msp430;
|
||||
mod nvptx;
|
||||
mod nvptx64;
|
||||
mod powerpc;
|
||||
mod powerpc64;
|
||||
mod s390x;
|
||||
mod sparc;
|
||||
mod sparc64;
|
||||
mod x86;
|
||||
mod x86_64;
|
||||
mod x86_win64;
|
||||
mod wasm32;
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
pub enum PassMode {
|
||||
/// Ignore the argument (useful for empty struct).
|
||||
Ignore,
|
||||
/// Pass the argument directly.
|
||||
Direct(ArgAttributes),
|
||||
/// Pass a pair's elements directly in two arguments.
|
||||
Pair(ArgAttributes, ArgAttributes),
|
||||
/// Pass the argument after casting it, to either
|
||||
/// a single uniform or a pair of registers.
|
||||
Cast(CastTarget),
|
||||
/// Pass the argument indirectly via a hidden pointer.
|
||||
Indirect(ArgAttributes),
|
||||
}
|
||||
|
||||
// Hack to disable non_upper_case_globals only for the bitflags! and not for the rest
|
||||
// of this module
|
||||
pub use self::attr_impl::ArgAttribute;
|
||||
|
||||
#[allow(non_upper_case_globals)]
|
||||
#[allow(unused)]
|
||||
mod attr_impl {
|
||||
// The subset of llvm::Attribute needed for arguments, packed into a bitfield.
|
||||
bitflags! {
|
||||
#[derive(Default)]
|
||||
pub struct ArgAttribute: u16 {
|
||||
const ByVal = 1 << 0;
|
||||
const NoAlias = 1 << 1;
|
||||
const NoCapture = 1 << 2;
|
||||
const NonNull = 1 << 3;
|
||||
const ReadOnly = 1 << 4;
|
||||
const SExt = 1 << 5;
|
||||
const StructRet = 1 << 6;
|
||||
const ZExt = 1 << 7;
|
||||
const InReg = 1 << 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A compact representation of LLVM attributes (at least those relevant for this module)
|
||||
/// that can be manipulated without interacting with LLVM's Attribute machinery.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
pub struct ArgAttributes {
|
||||
pub regular: ArgAttribute,
|
||||
pub pointee_size: Size,
|
||||
pub pointee_align: Option<Align>
|
||||
}
|
||||
|
||||
impl ArgAttributes {
|
||||
pub fn new() -> Self {
|
||||
ArgAttributes {
|
||||
regular: ArgAttribute::default(),
|
||||
pointee_size: Size::from_bytes(0),
|
||||
pointee_align: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set(&mut self, attr: ArgAttribute) -> &mut Self {
|
||||
self.regular = self.regular | attr;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn contains(&self, attr: ArgAttribute) -> bool {
|
||||
self.regular.contains(attr)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
pub enum RegKind {
|
||||
Integer,
|
||||
Float,
|
||||
Vector
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
pub struct Reg {
|
||||
pub kind: RegKind,
|
||||
pub size: Size,
|
||||
}
|
||||
|
||||
macro_rules! reg_ctor {
|
||||
($name:ident, $kind:ident, $bits:expr) => {
|
||||
pub fn $name() -> Reg {
|
||||
Reg {
|
||||
kind: RegKind::$kind,
|
||||
size: Size::from_bits($bits)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Reg {
|
||||
reg_ctor!(i8, Integer, 8);
|
||||
reg_ctor!(i16, Integer, 16);
|
||||
reg_ctor!(i32, Integer, 32);
|
||||
reg_ctor!(i64, Integer, 64);
|
||||
|
||||
reg_ctor!(f32, Float, 32);
|
||||
reg_ctor!(f64, Float, 64);
|
||||
}
|
||||
|
||||
impl Reg {
|
||||
pub fn align<C: HasDataLayout>(&self, cx: C) -> Align {
|
||||
let dl = cx.data_layout();
|
||||
match self.kind {
|
||||
RegKind::Integer => {
|
||||
match self.size.bits() {
|
||||
1 => dl.i1_align,
|
||||
2...8 => dl.i8_align,
|
||||
9...16 => dl.i16_align,
|
||||
17...32 => dl.i32_align,
|
||||
33...64 => dl.i64_align,
|
||||
65...128 => dl.i128_align,
|
||||
_ => panic!("unsupported integer: {:?}", self)
|
||||
}
|
||||
}
|
||||
RegKind::Float => {
|
||||
match self.size.bits() {
|
||||
32 => dl.f32_align,
|
||||
64 => dl.f64_align,
|
||||
_ => panic!("unsupported float: {:?}", self)
|
||||
}
|
||||
}
|
||||
RegKind::Vector => dl.vector_align(self.size)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An argument passed entirely registers with the
|
||||
/// same kind (e.g. HFA / HVA on PPC64 and AArch64).
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
pub struct Uniform {
|
||||
pub unit: Reg,
|
||||
|
||||
/// The total size of the argument, which can be:
|
||||
/// * equal to `unit.size` (one scalar/vector)
|
||||
/// * a multiple of `unit.size` (an array of scalar/vectors)
|
||||
/// * if `unit.kind` is `Integer`, the last element
|
||||
/// can be shorter, i.e. `{ i64, i64, i32 }` for
|
||||
/// 64-bit integers with a total size of 20 bytes
|
||||
pub total: Size,
|
||||
}
|
||||
|
||||
impl From<Reg> for Uniform {
|
||||
fn from(unit: Reg) -> Uniform {
|
||||
Uniform {
|
||||
unit,
|
||||
total: unit.size
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Uniform {
|
||||
pub fn align<C: HasDataLayout>(&self, cx: C) -> Align {
|
||||
self.unit.align(cx)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
pub struct CastTarget {
|
||||
pub prefix: [Option<RegKind>; 8],
|
||||
pub prefix_chunk: Size,
|
||||
pub rest: Uniform,
|
||||
}
|
||||
|
||||
impl From<Reg> for CastTarget {
|
||||
fn from(unit: Reg) -> CastTarget {
|
||||
CastTarget::from(Uniform::from(unit))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Uniform> for CastTarget {
|
||||
fn from(uniform: Uniform) -> CastTarget {
|
||||
CastTarget {
|
||||
prefix: [None; 8],
|
||||
prefix_chunk: Size::from_bytes(0),
|
||||
rest: uniform
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CastTarget {
|
||||
pub fn pair(a: Reg, b: Reg) -> CastTarget {
|
||||
CastTarget {
|
||||
prefix: [Some(a.kind), None, None, None, None, None, None, None],
|
||||
prefix_chunk: a.size,
|
||||
rest: Uniform::from(b)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn size<C: HasDataLayout>(&self, cx: C) -> Size {
|
||||
(self.prefix_chunk * self.prefix.iter().filter(|x| x.is_some()).count() as u64)
|
||||
.abi_align(self.rest.align(cx)) + self.rest.total
|
||||
}
|
||||
|
||||
pub fn align<C: HasDataLayout>(&self, cx: C) -> Align {
|
||||
self.prefix.iter()
|
||||
.filter_map(|x| x.map(|kind| Reg { kind: kind, size: self.prefix_chunk }.align(cx)))
|
||||
.fold(cx.data_layout().aggregate_align.max(self.rest.align(cx)),
|
||||
|acc, align| acc.max(align))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Ty> TyLayout<'a, Ty> {
|
||||
fn is_aggregate(&self) -> bool {
|
||||
match self.abi {
|
||||
Abi::Uninhabited |
|
||||
Abi::Scalar(_) |
|
||||
Abi::Vector { .. } => false,
|
||||
Abi::ScalarPair(..) |
|
||||
Abi::Aggregate { .. } => true
|
||||
}
|
||||
}
|
||||
|
||||
fn homogeneous_aggregate<C>(&self, cx: C) -> Option<Reg>
|
||||
where Ty: TyLayoutMethods<'a, C> + Copy, C: LayoutOf<Ty = Ty, TyLayout = Self> + Copy
|
||||
{
|
||||
match self.abi {
|
||||
Abi::Uninhabited => None,
|
||||
|
||||
// The primitive for this algorithm.
|
||||
Abi::Scalar(ref scalar) => {
|
||||
let kind = match scalar.value {
|
||||
abi::Int(..) |
|
||||
abi::Pointer => RegKind::Integer,
|
||||
abi::F32 |
|
||||
abi::F64 => RegKind::Float
|
||||
};
|
||||
Some(Reg {
|
||||
kind,
|
||||
size: self.size
|
||||
})
|
||||
}
|
||||
|
||||
Abi::Vector { .. } => {
|
||||
Some(Reg {
|
||||
kind: RegKind::Vector,
|
||||
size: self.size
|
||||
})
|
||||
}
|
||||
|
||||
Abi::ScalarPair(..) |
|
||||
Abi::Aggregate { .. } => {
|
||||
let mut total = Size::from_bytes(0);
|
||||
let mut result = None;
|
||||
|
||||
let is_union = match self.fields {
|
||||
FieldPlacement::Array { count, .. } => {
|
||||
if count > 0 {
|
||||
return self.field(cx, 0).homogeneous_aggregate(cx);
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
FieldPlacement::Union(_) => true,
|
||||
FieldPlacement::Arbitrary { .. } => false
|
||||
};
|
||||
|
||||
for i in 0..self.fields.count() {
|
||||
if !is_union && total != self.fields.offset(i) {
|
||||
return None;
|
||||
}
|
||||
|
||||
let field = self.field(cx, i);
|
||||
match (result, field.homogeneous_aggregate(cx)) {
|
||||
// The field itself must be a homogeneous aggregate.
|
||||
(_, None) => return None,
|
||||
// If this is the first field, record the unit.
|
||||
(None, Some(unit)) => {
|
||||
result = Some(unit);
|
||||
}
|
||||
// For all following fields, the unit must be the same.
|
||||
(Some(prev_unit), Some(unit)) => {
|
||||
if prev_unit != unit {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Keep track of the offset (without padding).
|
||||
let size = field.size;
|
||||
if is_union {
|
||||
total = total.max(size);
|
||||
} else {
|
||||
total += size;
|
||||
}
|
||||
}
|
||||
|
||||
// There needs to be no padding.
|
||||
if total != self.size {
|
||||
None
|
||||
} else {
|
||||
result
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Information about how to pass an argument to,
|
||||
/// or return a value from, a function, under some ABI.
|
||||
#[derive(Debug)]
|
||||
pub struct ArgType<'a, Ty> {
|
||||
pub layout: TyLayout<'a, Ty>,
|
||||
|
||||
/// Dummy argument, which is emitted before the real argument.
|
||||
pub pad: Option<Reg>,
|
||||
|
||||
pub mode: PassMode,
|
||||
}
|
||||
|
||||
impl<'a, Ty> ArgType<'a, Ty> {
|
||||
pub fn new(layout: TyLayout<'a, Ty>) -> Self {
|
||||
ArgType {
|
||||
layout,
|
||||
pad: None,
|
||||
mode: PassMode::Direct(ArgAttributes::new()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn make_indirect(&mut self) {
|
||||
assert_eq!(self.mode, PassMode::Direct(ArgAttributes::new()));
|
||||
|
||||
// Start with fresh attributes for the pointer.
|
||||
let mut attrs = ArgAttributes::new();
|
||||
|
||||
// For non-immediate arguments the callee gets its own copy of
|
||||
// the value on the stack, so there are no aliases. It's also
|
||||
// program-invisible so can't possibly capture
|
||||
attrs.set(ArgAttribute::NoAlias)
|
||||
.set(ArgAttribute::NoCapture)
|
||||
.set(ArgAttribute::NonNull);
|
||||
attrs.pointee_size = self.layout.size;
|
||||
// FIXME(eddyb) We should be doing this, but at least on
|
||||
// i686-pc-windows-msvc, it results in wrong stack offsets.
|
||||
// attrs.pointee_align = Some(self.layout.align);
|
||||
|
||||
self.mode = PassMode::Indirect(attrs);
|
||||
}
|
||||
|
||||
pub fn make_indirect_byval(&mut self) {
|
||||
self.make_indirect();
|
||||
match self.mode {
|
||||
PassMode::Indirect(ref mut attrs) => {
|
||||
attrs.set(ArgAttribute::ByVal);
|
||||
}
|
||||
_ => unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn extend_integer_width_to(&mut self, bits: u64) {
|
||||
// Only integers have signedness
|
||||
if let Abi::Scalar(ref scalar) = self.layout.abi {
|
||||
if let abi::Int(i, signed) = scalar.value {
|
||||
if i.size().bits() < bits {
|
||||
if let PassMode::Direct(ref mut attrs) = self.mode {
|
||||
attrs.set(if signed {
|
||||
ArgAttribute::SExt
|
||||
} else {
|
||||
ArgAttribute::ZExt
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cast_to<T: Into<CastTarget>>(&mut self, target: T) {
|
||||
assert_eq!(self.mode, PassMode::Direct(ArgAttributes::new()));
|
||||
self.mode = PassMode::Cast(target.into());
|
||||
}
|
||||
|
||||
pub fn pad_with(&mut self, reg: Reg) {
|
||||
self.pad = Some(reg);
|
||||
}
|
||||
|
||||
pub fn is_indirect(&self) -> bool {
|
||||
match self.mode {
|
||||
PassMode::Indirect(_) => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_ignore(&self) -> bool {
|
||||
self.mode == PassMode::Ignore
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
||||
pub enum Conv {
|
||||
C,
|
||||
|
||||
ArmAapcs,
|
||||
|
||||
Msp430Intr,
|
||||
|
||||
PtxKernel,
|
||||
|
||||
X86Fastcall,
|
||||
X86Intr,
|
||||
X86Stdcall,
|
||||
X86ThisCall,
|
||||
X86VectorCall,
|
||||
|
||||
X86_64SysV,
|
||||
X86_64Win64,
|
||||
}
|
||||
|
||||
/// Metadata describing how the arguments to a native function
|
||||
/// should be passed in order to respect the native ABI.
|
||||
///
|
||||
/// I will do my best to describe this structure, but these
|
||||
/// comments are reverse-engineered and may be inaccurate. -NDM
|
||||
#[derive(Debug)]
|
||||
pub struct FnType<'a, Ty> {
|
||||
/// The LLVM types of each argument.
|
||||
pub args: Vec<ArgType<'a, Ty>>,
|
||||
|
||||
/// LLVM return type.
|
||||
pub ret: ArgType<'a, Ty>,
|
||||
|
||||
pub variadic: bool,
|
||||
|
||||
pub conv: Conv,
|
||||
}
|
||||
|
||||
impl<'a, Ty> FnType<'a, Ty> {
|
||||
pub fn adjust_for_cabi<C>(&mut self, cx: C, abi: ::spec::abi::Abi) -> Result<(), String>
|
||||
where Ty: TyLayoutMethods<'a, C> + Copy,
|
||||
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout + HasTargetSpec
|
||||
{
|
||||
match &cx.target_spec().arch[..] {
|
||||
"x86" => {
|
||||
let flavor = if abi == ::spec::abi::Abi::Fastcall {
|
||||
x86::Flavor::Fastcall
|
||||
} else {
|
||||
x86::Flavor::General
|
||||
};
|
||||
x86::compute_abi_info(cx, self, flavor);
|
||||
},
|
||||
"x86_64" => if abi == ::spec::abi::Abi::SysV64 {
|
||||
x86_64::compute_abi_info(cx, self);
|
||||
} else if abi == ::spec::abi::Abi::Win64 || cx.target_spec().options.is_like_windows {
|
||||
x86_win64::compute_abi_info(self);
|
||||
} else {
|
||||
x86_64::compute_abi_info(cx, self);
|
||||
},
|
||||
"aarch64" => aarch64::compute_abi_info(cx, self),
|
||||
"arm" => arm::compute_abi_info(cx, self),
|
||||
"mips" => mips::compute_abi_info(cx, self),
|
||||
"mips64" => mips64::compute_abi_info(cx, self),
|
||||
"powerpc" => powerpc::compute_abi_info(cx, self),
|
||||
"powerpc64" => powerpc64::compute_abi_info(cx, self),
|
||||
"s390x" => s390x::compute_abi_info(cx, self),
|
||||
"asmjs" => asmjs::compute_abi_info(cx, self),
|
||||
"wasm32" => {
|
||||
if cx.target_spec().llvm_target.contains("emscripten") {
|
||||
asmjs::compute_abi_info(cx, self)
|
||||
} else {
|
||||
wasm32::compute_abi_info(self)
|
||||
}
|
||||
}
|
||||
"msp430" => msp430::compute_abi_info(self),
|
||||
"sparc" => sparc::compute_abi_info(cx, self),
|
||||
"sparc64" => sparc64::compute_abi_info(cx, self),
|
||||
"nvptx" => nvptx::compute_abi_info(self),
|
||||
"nvptx64" => nvptx64::compute_abi_info(self),
|
||||
"hexagon" => hexagon::compute_abi_info(self),
|
||||
a => return Err(format!("unrecognized arch \"{}\" in target specification", a))
|
||||
}
|
||||
|
||||
if let PassMode::Indirect(ref mut attrs) = self.ret.mode {
|
||||
attrs.set(ArgAttribute::StructRet);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
@ -11,7 +11,7 @@
|
||||
// Reference: MSP430 Embedded Application Binary Interface
|
||||
// http://www.ti.com/lit/an/slaa534/slaa534.pdf
|
||||
|
||||
use abi::{ArgType, FnType, LayoutExt};
|
||||
use abi::call::{ArgType, FnType};
|
||||
|
||||
// 3.5 Structures or Unions Passed and Returned by Reference
|
||||
//
|
||||
@ -19,7 +19,7 @@ use abi::{ArgType, FnType, LayoutExt};
|
||||
// returned by reference. To pass a structure or union by reference, the caller
|
||||
// places its address in the appropriate location: either in a register or on
|
||||
// the stack, according to its position in the argument list. (..)"
|
||||
fn classify_ret_ty(ret: &mut ArgType) {
|
||||
fn classify_ret_ty<Ty>(ret: &mut ArgType<Ty>) {
|
||||
if ret.layout.is_aggregate() && ret.layout.size.bits() > 32 {
|
||||
ret.make_indirect();
|
||||
} else {
|
||||
@ -27,7 +27,7 @@ fn classify_ret_ty(ret: &mut ArgType) {
|
||||
}
|
||||
}
|
||||
|
||||
fn classify_arg_ty(arg: &mut ArgType) {
|
||||
fn classify_arg_ty<Ty>(arg: &mut ArgType<Ty>) {
|
||||
if arg.layout.is_aggregate() && arg.layout.size.bits() > 32 {
|
||||
arg.make_indirect();
|
||||
} else {
|
||||
@ -35,7 +35,7 @@ fn classify_arg_ty(arg: &mut ArgType) {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn compute_abi_info(fty: &mut FnType) {
|
||||
pub fn compute_abi_info<Ty>(fty: &mut FnType<Ty>) {
|
||||
if !fty.ret.is_ignore() {
|
||||
classify_ret_ty(&mut fty.ret);
|
||||
}
|
@ -11,9 +11,9 @@
|
||||
// Reference: PTX Writer's Guide to Interoperability
|
||||
// http://docs.nvidia.com/cuda/ptx-writers-guide-to-interoperability
|
||||
|
||||
use abi::{ArgType, FnType, LayoutExt};
|
||||
use abi::call::{ArgType, FnType};
|
||||
|
||||
fn classify_ret_ty(ret: &mut ArgType) {
|
||||
fn classify_ret_ty<Ty>(ret: &mut ArgType<Ty>) {
|
||||
if ret.layout.is_aggregate() && ret.layout.size.bits() > 32 {
|
||||
ret.make_indirect();
|
||||
} else {
|
||||
@ -21,7 +21,7 @@ fn classify_ret_ty(ret: &mut ArgType) {
|
||||
}
|
||||
}
|
||||
|
||||
fn classify_arg_ty(arg: &mut ArgType) {
|
||||
fn classify_arg_ty<Ty>(arg: &mut ArgType<Ty>) {
|
||||
if arg.layout.is_aggregate() && arg.layout.size.bits() > 32 {
|
||||
arg.make_indirect();
|
||||
} else {
|
||||
@ -29,7 +29,7 @@ fn classify_arg_ty(arg: &mut ArgType) {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn compute_abi_info(fty: &mut FnType) {
|
||||
pub fn compute_abi_info<Ty>(fty: &mut FnType<Ty>) {
|
||||
if !fty.ret.is_ignore() {
|
||||
classify_ret_ty(&mut fty.ret);
|
||||
}
|
@ -11,9 +11,9 @@
|
||||
// Reference: PTX Writer's Guide to Interoperability
|
||||
// http://docs.nvidia.com/cuda/ptx-writers-guide-to-interoperability
|
||||
|
||||
use abi::{ArgType, FnType, LayoutExt};
|
||||
use abi::call::{ArgType, FnType};
|
||||
|
||||
fn classify_ret_ty(ret: &mut ArgType) {
|
||||
fn classify_ret_ty<Ty>(ret: &mut ArgType<Ty>) {
|
||||
if ret.layout.is_aggregate() && ret.layout.size.bits() > 64 {
|
||||
ret.make_indirect();
|
||||
} else {
|
||||
@ -21,7 +21,7 @@ fn classify_ret_ty(ret: &mut ArgType) {
|
||||
}
|
||||
}
|
||||
|
||||
fn classify_arg_ty(arg: &mut ArgType) {
|
||||
fn classify_arg_ty<Ty>(arg: &mut ArgType<Ty>) {
|
||||
if arg.layout.is_aggregate() && arg.layout.size.bits() > 64 {
|
||||
arg.make_indirect();
|
||||
} else {
|
||||
@ -29,7 +29,7 @@ fn classify_arg_ty(arg: &mut ArgType) {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn compute_abi_info(fty: &mut FnType) {
|
||||
pub fn compute_abi_info<Ty>(fty: &mut FnType<Ty>) {
|
||||
if !fty.ret.is_ignore() {
|
||||
classify_ret_ty(&mut fty.ret);
|
||||
}
|
@ -8,24 +8,24 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use abi::{ArgType, FnType, LayoutExt, Reg, Uniform};
|
||||
use context::CodegenCx;
|
||||
use abi::call::{ArgType, FnType, Reg, Uniform};
|
||||
use abi::{HasDataLayout, LayoutOf, Size, TyLayoutMethods};
|
||||
|
||||
use rustc::ty::layout::Size;
|
||||
|
||||
fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
|
||||
ret: &mut ArgType<'tcx>,
|
||||
offset: &mut Size) {
|
||||
fn classify_ret_ty<'a, Ty, C>(cx: C, ret: &mut ArgType<Ty>, offset: &mut Size)
|
||||
where Ty: TyLayoutMethods<'a, C>, C: LayoutOf<Ty = Ty> + HasDataLayout
|
||||
{
|
||||
if !ret.layout.is_aggregate() {
|
||||
ret.extend_integer_width_to(32);
|
||||
} else {
|
||||
ret.make_indirect();
|
||||
*offset += cx.tcx.data_layout.pointer_size;
|
||||
*offset += cx.data_layout().pointer_size;
|
||||
}
|
||||
}
|
||||
|
||||
fn classify_arg_ty(cx: &CodegenCx, arg: &mut ArgType, offset: &mut Size) {
|
||||
let dl = &cx.tcx.data_layout;
|
||||
fn classify_arg_ty<'a, Ty, C>(cx: C, arg: &mut ArgType<Ty>, offset: &mut Size)
|
||||
where Ty: TyLayoutMethods<'a, C>, C: LayoutOf<Ty = Ty> + HasDataLayout
|
||||
{
|
||||
let dl = cx.data_layout();
|
||||
let size = arg.layout.size;
|
||||
let align = arg.layout.align.max(dl.i32_align).min(dl.i64_align);
|
||||
|
||||
@ -44,7 +44,9 @@ fn classify_arg_ty(cx: &CodegenCx, arg: &mut ArgType, offset: &mut Size) {
|
||||
*offset = offset.abi_align(align) + size.abi_align(align);
|
||||
}
|
||||
|
||||
pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, fty: &mut FnType<'tcx>) {
|
||||
pub fn compute_abi_info<'a, Ty, C>(cx: C, fty: &mut FnType<Ty>)
|
||||
where Ty: TyLayoutMethods<'a, C>, C: LayoutOf<Ty = Ty> + HasDataLayout
|
||||
{
|
||||
let mut offset = Size::from_bytes(0);
|
||||
if !fty.ret.is_ignore() {
|
||||
classify_ret_ty(cx, &mut fty.ret, &mut offset);
|
@ -12,9 +12,8 @@
|
||||
// Alignment of 128 bit types is not currently handled, this will
|
||||
// need to be fixed when PowerPC vector support is added.
|
||||
|
||||
use abi::{FnType, ArgType, LayoutExt, Reg, RegKind, Uniform};
|
||||
use context::CodegenCx;
|
||||
use rustc::ty::layout;
|
||||
use abi::call::{FnType, ArgType, Reg, RegKind, Uniform};
|
||||
use abi::{Align, Endian, HasDataLayout, LayoutOf, TyLayout, TyLayoutMethods};
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
enum ABI {
|
||||
@ -23,10 +22,11 @@ enum ABI {
|
||||
}
|
||||
use self::ABI::*;
|
||||
|
||||
fn is_homogeneous_aggregate<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
|
||||
arg: &mut ArgType<'tcx>,
|
||||
abi: ABI)
|
||||
-> Option<Uniform> {
|
||||
fn is_homogeneous_aggregate<'a, Ty, C>(cx: C, arg: &mut ArgType<'a, Ty>, abi: ABI)
|
||||
-> Option<Uniform>
|
||||
where Ty: TyLayoutMethods<'a, C> + Copy,
|
||||
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
|
||||
{
|
||||
arg.layout.homogeneous_aggregate(cx).and_then(|unit| {
|
||||
// ELFv1 only passes one-member aggregates transparently.
|
||||
// ELFv2 passes up to eight uniquely addressable members.
|
||||
@ -52,7 +52,10 @@ fn is_homogeneous_aggregate<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
|
||||
})
|
||||
}
|
||||
|
||||
fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, ret: &mut ArgType<'tcx>, abi: ABI) {
|
||||
fn classify_ret_ty<'a, Ty, C>(cx: C, ret: &mut ArgType<'a, Ty>, abi: ABI)
|
||||
where Ty: TyLayoutMethods<'a, C> + Copy,
|
||||
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
|
||||
{
|
||||
if !ret.layout.is_aggregate() {
|
||||
ret.extend_integer_width_to(64);
|
||||
return;
|
||||
@ -92,7 +95,10 @@ fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, ret: &mut ArgType<'tcx>,
|
||||
ret.make_indirect();
|
||||
}
|
||||
|
||||
fn classify_arg_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgType<'tcx>, abi: ABI) {
|
||||
fn classify_arg_ty<'a, Ty, C>(cx: C, arg: &mut ArgType<'a, Ty>, abi: ABI)
|
||||
where Ty: TyLayoutMethods<'a, C> + Copy,
|
||||
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
|
||||
{
|
||||
if !arg.layout.is_aggregate() {
|
||||
arg.extend_integer_width_to(64);
|
||||
return;
|
||||
@ -112,7 +118,7 @@ fn classify_arg_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgType<'tcx>,
|
||||
if size.bits() <= 64 {
|
||||
(Reg { kind: RegKind::Integer, size }, size)
|
||||
} else {
|
||||
let align = layout::Align::from_bits(64, 64).unwrap();
|
||||
let align = Align::from_bits(64, 64).unwrap();
|
||||
(Reg::i64(), size.abi_align(align))
|
||||
}
|
||||
},
|
||||
@ -128,11 +134,13 @@ fn classify_arg_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgType<'tcx>,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, fty: &mut FnType<'tcx>) {
|
||||
let abi = match cx.sess().target.target.target_endian.as_str() {
|
||||
"big" => ELFv1,
|
||||
"little" => ELFv2,
|
||||
_ => unimplemented!(),
|
||||
pub fn compute_abi_info<'a, Ty, C>(cx: C, fty: &mut FnType<'a, Ty>)
|
||||
where Ty: TyLayoutMethods<'a, C> + Copy,
|
||||
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
|
||||
{
|
||||
let abi = match cx.data_layout().endian {
|
||||
Endian::Big => ELFv1,
|
||||
Endian::Little => ELFv2,
|
||||
};
|
||||
|
||||
if !fty.ret.is_ignore() {
|
@ -11,12 +11,12 @@
|
||||
// FIXME: The assumes we're using the non-vector ABI, i.e. compiling
|
||||
// for a pre-z13 machine or using -mno-vx.
|
||||
|
||||
use abi::{FnType, ArgType, LayoutExt, Reg};
|
||||
use context::CodegenCx;
|
||||
use abi::call::{FnType, ArgType, Reg};
|
||||
use abi::{self, HasDataLayout, LayoutOf, TyLayout, TyLayoutMethods};
|
||||
|
||||
use rustc::ty::layout::{self, TyLayout};
|
||||
|
||||
fn classify_ret_ty(ret: &mut ArgType) {
|
||||
fn classify_ret_ty<'a, Ty, C>(ret: &mut ArgType<Ty>)
|
||||
where Ty: TyLayoutMethods<'a, C>, C: LayoutOf<Ty = Ty> + HasDataLayout
|
||||
{
|
||||
if !ret.layout.is_aggregate() && ret.layout.size.bits() <= 64 {
|
||||
ret.extend_integer_width_to(64);
|
||||
} else {
|
||||
@ -24,16 +24,18 @@ fn classify_ret_ty(ret: &mut ArgType) {
|
||||
}
|
||||
}
|
||||
|
||||
fn is_single_fp_element<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
|
||||
layout: TyLayout<'tcx>) -> bool {
|
||||
fn is_single_fp_element<'a, Ty, C>(cx: C, layout: TyLayout<'a, Ty>) -> bool
|
||||
where Ty: TyLayoutMethods<'a, C>,
|
||||
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
|
||||
{
|
||||
match layout.abi {
|
||||
layout::Abi::Scalar(ref scalar) => {
|
||||
abi::Abi::Scalar(ref scalar) => {
|
||||
match scalar.value {
|
||||
layout::F32 | layout::F64 => true,
|
||||
abi::F32 | abi::F64 => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
layout::Abi::Aggregate { .. } => {
|
||||
abi::Abi::Aggregate { .. } => {
|
||||
if layout.fields.count() == 1 && layout.fields.offset(0).bytes() == 0 {
|
||||
is_single_fp_element(cx, layout.field(cx, 0))
|
||||
} else {
|
||||
@ -44,7 +46,10 @@ fn is_single_fp_element<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
|
||||
}
|
||||
}
|
||||
|
||||
fn classify_arg_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgType<'tcx>) {
|
||||
fn classify_arg_ty<'a, Ty, C>(cx: C, arg: &mut ArgType<'a, Ty>)
|
||||
where Ty: TyLayoutMethods<'a, C> + Copy,
|
||||
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
|
||||
{
|
||||
if !arg.layout.is_aggregate() && arg.layout.size.bits() <= 64 {
|
||||
arg.extend_integer_width_to(64);
|
||||
return;
|
||||
@ -67,7 +72,10 @@ fn classify_arg_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgType<'tcx>)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, fty: &mut FnType<'tcx>) {
|
||||
pub fn compute_abi_info<'a, Ty, C>(cx: C, fty: &mut FnType<'a, Ty>)
|
||||
where Ty: TyLayoutMethods<'a, C> + Copy,
|
||||
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
|
||||
{
|
||||
if !fty.ret.is_ignore() {
|
||||
classify_ret_ty(&mut fty.ret);
|
||||
}
|
@ -8,24 +8,24 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use abi::{ArgType, FnType, LayoutExt, Reg, Uniform};
|
||||
use context::CodegenCx;
|
||||
use abi::call::{ArgType, FnType, Reg, Uniform};
|
||||
use abi::{HasDataLayout, LayoutOf, Size, TyLayoutMethods};
|
||||
|
||||
use rustc::ty::layout::Size;
|
||||
|
||||
fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
|
||||
ret: &mut ArgType<'tcx>,
|
||||
offset: &mut Size) {
|
||||
fn classify_ret_ty<'a, Ty, C>(cx: C, ret: &mut ArgType<Ty>, offset: &mut Size)
|
||||
where Ty: TyLayoutMethods<'a, C>, C: LayoutOf<Ty = Ty> + HasDataLayout
|
||||
{
|
||||
if !ret.layout.is_aggregate() {
|
||||
ret.extend_integer_width_to(32);
|
||||
} else {
|
||||
ret.make_indirect();
|
||||
*offset += cx.tcx.data_layout.pointer_size;
|
||||
*offset += cx.data_layout().pointer_size;
|
||||
}
|
||||
}
|
||||
|
||||
fn classify_arg_ty(cx: &CodegenCx, arg: &mut ArgType, offset: &mut Size) {
|
||||
let dl = &cx.tcx.data_layout;
|
||||
fn classify_arg_ty<'a, Ty, C>(cx: C, arg: &mut ArgType<Ty>, offset: &mut Size)
|
||||
where Ty: TyLayoutMethods<'a, C>, C: LayoutOf<Ty = Ty> + HasDataLayout
|
||||
{
|
||||
let dl = cx.data_layout();
|
||||
let size = arg.layout.size;
|
||||
let align = arg.layout.align.max(dl.i32_align).min(dl.i64_align);
|
||||
|
||||
@ -44,7 +44,9 @@ fn classify_arg_ty(cx: &CodegenCx, arg: &mut ArgType, offset: &mut Size) {
|
||||
*offset = offset.abi_align(align) + size.abi_align(align);
|
||||
}
|
||||
|
||||
pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, fty: &mut FnType<'tcx>) {
|
||||
pub fn compute_abi_info<'a, Ty, C>(cx: C, fty: &mut FnType<Ty>)
|
||||
where Ty: TyLayoutMethods<'a, C>, C: LayoutOf<Ty = Ty> + HasDataLayout
|
||||
{
|
||||
let mut offset = Size::from_bytes(0);
|
||||
if !fty.ret.is_ignore() {
|
||||
classify_ret_ty(cx, &mut fty.ret, &mut offset);
|
@ -10,11 +10,14 @@
|
||||
|
||||
// FIXME: This needs an audit for correctness and completeness.
|
||||
|
||||
use abi::{FnType, ArgType, LayoutExt, Reg, RegKind, Uniform};
|
||||
use context::CodegenCx;
|
||||
use abi::call::{FnType, ArgType, Reg, RegKind, Uniform};
|
||||
use abi::{HasDataLayout, LayoutOf, TyLayout, TyLayoutMethods};
|
||||
|
||||
fn is_homogeneous_aggregate<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgType<'tcx>)
|
||||
-> Option<Uniform> {
|
||||
fn is_homogeneous_aggregate<'a, Ty, C>(cx: C, arg: &mut ArgType<'a, Ty>)
|
||||
-> Option<Uniform>
|
||||
where Ty: TyLayoutMethods<'a, C> + Copy,
|
||||
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
|
||||
{
|
||||
arg.layout.homogeneous_aggregate(cx).and_then(|unit| {
|
||||
// Ensure we have at most eight uniquely addressable members.
|
||||
if arg.layout.size > unit.size.checked_mul(8, cx).unwrap() {
|
||||
@ -38,7 +41,10 @@ fn is_homogeneous_aggregate<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgTyp
|
||||
})
|
||||
}
|
||||
|
||||
fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, ret: &mut ArgType<'tcx>) {
|
||||
fn classify_ret_ty<'a, Ty, C>(cx: C, ret: &mut ArgType<'a, Ty>)
|
||||
where Ty: TyLayoutMethods<'a, C> + Copy,
|
||||
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
|
||||
{
|
||||
if !ret.layout.is_aggregate() {
|
||||
ret.extend_integer_width_to(64);
|
||||
return;
|
||||
@ -72,7 +78,10 @@ fn classify_ret_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, ret: &mut ArgType<'tcx>)
|
||||
ret.make_indirect();
|
||||
}
|
||||
|
||||
fn classify_arg_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgType<'tcx>) {
|
||||
fn classify_arg_ty<'a, Ty, C>(cx: C, arg: &mut ArgType<'a, Ty>)
|
||||
where Ty: TyLayoutMethods<'a, C> + Copy,
|
||||
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
|
||||
{
|
||||
if !arg.layout.is_aggregate() {
|
||||
arg.extend_integer_width_to(64);
|
||||
return;
|
||||
@ -95,7 +104,10 @@ fn classify_arg_ty<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &mut ArgType<'tcx>)
|
||||
});
|
||||
}
|
||||
|
||||
pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, fty: &mut FnType<'tcx>) {
|
||||
pub fn compute_abi_info<'a, Ty, C>(cx: C, fty: &mut FnType<'a, Ty>)
|
||||
where Ty: TyLayoutMethods<'a, C> + Copy,
|
||||
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
|
||||
{
|
||||
if !fty.ret.is_ignore() {
|
||||
classify_ret_ty(cx, &mut fty.ret);
|
||||
}
|
@ -8,20 +8,19 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use abi::{FnType, ArgType};
|
||||
use context::CodegenCx;
|
||||
use abi::call::{FnType, ArgType};
|
||||
|
||||
fn classify_ret_ty<'a, 'tcx>(_cx: &CodegenCx<'a, 'tcx>, ret: &mut ArgType<'tcx>) {
|
||||
fn classify_ret_ty<Ty>(ret: &mut ArgType<Ty>) {
|
||||
ret.extend_integer_width_to(32);
|
||||
}
|
||||
|
||||
fn classify_arg_ty(arg: &mut ArgType) {
|
||||
fn classify_arg_ty<Ty>(arg: &mut ArgType<Ty>) {
|
||||
arg.extend_integer_width_to(32);
|
||||
}
|
||||
|
||||
pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, fty: &mut FnType<'tcx>) {
|
||||
pub fn compute_abi_info<Ty>(fty: &mut FnType<Ty>) {
|
||||
if !fty.ret.is_ignore() {
|
||||
classify_ret_ty(cx, &mut fty.ret);
|
||||
classify_ret_ty(&mut fty.ret);
|
||||
}
|
||||
|
||||
for arg in &mut fty.args {
|
@ -8,10 +8,9 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use abi::{ArgAttribute, FnType, LayoutExt, PassMode, Reg, RegKind};
|
||||
use common::CodegenCx;
|
||||
|
||||
use rustc::ty::layout::{self, TyLayout};
|
||||
use abi::call::{ArgAttribute, FnType, PassMode, Reg, RegKind};
|
||||
use abi::{self, HasDataLayout, LayoutOf, TyLayout, TyLayoutMethods};
|
||||
use spec::HasTargetSpec;
|
||||
|
||||
#[derive(PartialEq)]
|
||||
pub enum Flavor {
|
||||
@ -19,16 +18,18 @@ pub enum Flavor {
|
||||
Fastcall
|
||||
}
|
||||
|
||||
fn is_single_fp_element<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
|
||||
layout: TyLayout<'tcx>) -> bool {
|
||||
fn is_single_fp_element<'a, Ty, C>(cx: C, layout: TyLayout<'a, Ty>) -> bool
|
||||
where Ty: TyLayoutMethods<'a, C> + Copy,
|
||||
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
|
||||
{
|
||||
match layout.abi {
|
||||
layout::Abi::Scalar(ref scalar) => {
|
||||
abi::Abi::Scalar(ref scalar) => {
|
||||
match scalar.value {
|
||||
layout::F32 | layout::F64 => true,
|
||||
abi::F32 | abi::F64 => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
layout::Abi::Aggregate { .. } => {
|
||||
abi::Abi::Aggregate { .. } => {
|
||||
if layout.fields.count() == 1 && layout.fields.offset(0).bytes() == 0 {
|
||||
is_single_fp_element(cx, layout.field(cx, 0))
|
||||
} else {
|
||||
@ -39,9 +40,10 @@ fn is_single_fp_element<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
|
||||
fty: &mut FnType<'tcx>,
|
||||
flavor: Flavor) {
|
||||
pub fn compute_abi_info<'a, Ty, C>(cx: C, fty: &mut FnType<'a, Ty>, flavor: Flavor)
|
||||
where Ty: TyLayoutMethods<'a, C> + Copy,
|
||||
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout + HasTargetSpec
|
||||
{
|
||||
if !fty.ret.is_ignore() {
|
||||
if fty.ret.layout.is_aggregate() {
|
||||
// Returning a structure. Most often, this will use
|
||||
@ -51,7 +53,7 @@ pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
|
||||
// Some links:
|
||||
// http://www.angelcode.com/dev/callconv/callconv.html
|
||||
// Clang's ABI handling is in lib/CodeGen/TargetInfo.cpp
|
||||
let t = &cx.sess().target.target;
|
||||
let t = cx.target_spec();
|
||||
if t.options.abi_return_struct_as_int {
|
||||
// According to Clang, everyone but MSVC returns single-element
|
||||
// float aggregates directly in a floating-point register.
|
||||
@ -106,7 +108,7 @@ pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
|
||||
PassMode::Direct(ref mut attrs) => attrs,
|
||||
PassMode::Pair(..) |
|
||||
PassMode::Cast(_) => {
|
||||
bug!("x86 shouldn't be passing arguments by {:?}", arg.mode)
|
||||
unreachable!("x86 shouldn't be passing arguments by {:?}", arg.mode)
|
||||
}
|
||||
};
|
||||
|
@ -11,10 +11,8 @@
|
||||
// The classification code for the x86_64 ABI is taken from the clay language
|
||||
// https://github.com/jckarter/clay/blob/master/compiler/src/externals.cpp
|
||||
|
||||
use abi::{ArgType, CastTarget, FnType, LayoutExt, Reg, RegKind};
|
||||
use context::CodegenCx;
|
||||
|
||||
use rustc::ty::layout::{self, TyLayout, Size};
|
||||
use abi::call::{ArgType, CastTarget, FnType, Reg, RegKind};
|
||||
use abi::{self, Abi, HasDataLayout, LayoutOf, Size, TyLayout, TyLayoutMethods};
|
||||
|
||||
/// Classification of "eightbyte" components.
|
||||
// NB: the order of the variants is from general to specific,
|
||||
@ -33,13 +31,16 @@ struct Memory;
|
||||
const LARGEST_VECTOR_SIZE: usize = 512;
|
||||
const MAX_EIGHTBYTES: usize = LARGEST_VECTOR_SIZE / 64;
|
||||
|
||||
fn classify_arg<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &ArgType<'tcx>)
|
||||
-> Result<[Option<Class>; MAX_EIGHTBYTES], Memory> {
|
||||
fn classify<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
|
||||
layout: TyLayout<'tcx>,
|
||||
cls: &mut [Option<Class>],
|
||||
off: Size)
|
||||
-> Result<(), Memory> {
|
||||
fn classify_arg<'a, Ty, C>(cx: C, arg: &ArgType<'a, Ty>)
|
||||
-> Result<[Option<Class>; MAX_EIGHTBYTES], Memory>
|
||||
where Ty: TyLayoutMethods<'a, C> + Copy,
|
||||
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
|
||||
{
|
||||
fn classify<'a, Ty, C>(cx: C, layout: TyLayout<'a, Ty>,
|
||||
cls: &mut [Option<Class>], off: Size) -> Result<(), Memory>
|
||||
where Ty: TyLayoutMethods<'a, C> + Copy,
|
||||
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
|
||||
{
|
||||
if !off.is_abi_aligned(layout.align) {
|
||||
if !layout.is_zst() {
|
||||
return Err(Memory);
|
||||
@ -48,31 +49,31 @@ fn classify_arg<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, arg: &ArgType<'tcx>)
|
||||
}
|
||||
|
||||
let mut c = match layout.abi {
|
||||
layout::Abi::Uninhabited => return Ok(()),
|
||||
Abi::Uninhabited => return Ok(()),
|
||||
|
||||
layout::Abi::Scalar(ref scalar) => {
|
||||
Abi::Scalar(ref scalar) => {
|
||||
match scalar.value {
|
||||
layout::Int(..) |
|
||||
layout::Pointer => Class::Int,
|
||||
layout::F32 |
|
||||
layout::F64 => Class::Sse
|
||||
abi::Int(..) |
|
||||
abi::Pointer => Class::Int,
|
||||
abi::F32 |
|
||||
abi::F64 => Class::Sse
|
||||
}
|
||||
}
|
||||
|
||||
layout::Abi::Vector { .. } => Class::Sse,
|
||||
Abi::Vector { .. } => Class::Sse,
|
||||
|
||||
layout::Abi::ScalarPair(..) |
|
||||
layout::Abi::Aggregate { .. } => {
|
||||
Abi::ScalarPair(..) |
|
||||
Abi::Aggregate { .. } => {
|
||||
match layout.variants {
|
||||
layout::Variants::Single { .. } => {
|
||||
abi::Variants::Single { .. } => {
|
||||
for i in 0..layout.fields.count() {
|
||||
let field_off = off + layout.fields.offset(i);
|
||||
classify(cx, layout.field(cx, i), cls, field_off)?;
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
layout::Variants::Tagged { .. } |
|
||||
layout::Variants::NicheFilling { .. } => return Err(Memory),
|
||||
abi::Variants::Tagged { .. } |
|
||||
abi::Variants::NicheFilling { .. } => return Err(Memory),
|
||||
}
|
||||
}
|
||||
|
||||
@ -160,7 +161,7 @@ fn reg_component(cls: &[Option<Class>], i: &mut usize, size: Size) -> Option<Reg
|
||||
}
|
||||
})
|
||||
}
|
||||
Some(c) => bug!("reg_component: unhandled class {:?}", c)
|
||||
Some(c) => unreachable!("reg_component: unhandled class {:?}", c)
|
||||
}
|
||||
}
|
||||
|
||||
@ -178,11 +179,14 @@ fn cast_target(cls: &[Option<Class>], size: Size) -> CastTarget {
|
||||
target
|
||||
}
|
||||
|
||||
pub fn compute_abi_info<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, fty: &mut FnType<'tcx>) {
|
||||
pub fn compute_abi_info<'a, Ty, C>(cx: C, fty: &mut FnType<'a, Ty>)
|
||||
where Ty: TyLayoutMethods<'a, C> + Copy,
|
||||
C: LayoutOf<Ty = Ty, TyLayout = TyLayout<'a, Ty>> + HasDataLayout
|
||||
{
|
||||
let mut int_regs = 6; // RDI, RSI, RDX, RCX, R8, R9
|
||||
let mut sse_regs = 8; // XMM0-7
|
||||
|
||||
let mut x86_64_ty = |arg: &mut ArgType<'tcx>, is_arg: bool| {
|
||||
let mut x86_64_ty = |arg: &mut ArgType<'a, Ty>, is_arg: bool| {
|
||||
let mut cls_or_mem = classify_arg(cx, arg);
|
||||
|
||||
let mut needed_int = 0;
|
@ -8,18 +8,17 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use abi::{ArgType, FnType, Reg};
|
||||
|
||||
use rustc::ty::layout;
|
||||
use abi::call::{ArgType, FnType, Reg};
|
||||
use abi::Abi;
|
||||
|
||||
// Win64 ABI: http://msdn.microsoft.com/en-us/library/zthk2dkh.aspx
|
||||
|
||||
pub fn compute_abi_info(fty: &mut FnType) {
|
||||
let fixup = |a: &mut ArgType| {
|
||||
pub fn compute_abi_info<Ty>(fty: &mut FnType<Ty>) {
|
||||
let fixup = |a: &mut ArgType<Ty>| {
|
||||
match a.layout.abi {
|
||||
layout::Abi::Uninhabited => {}
|
||||
layout::Abi::ScalarPair(..) |
|
||||
layout::Abi::Aggregate { .. } => {
|
||||
Abi::Uninhabited => {}
|
||||
Abi::ScalarPair(..) |
|
||||
Abi::Aggregate { .. } => {
|
||||
match a.layout.size.bits() {
|
||||
8 => a.cast_to(Reg::i8()),
|
||||
16 => a.cast_to(Reg::i16()),
|
||||
@ -28,11 +27,11 @@ pub fn compute_abi_info(fty: &mut FnType) {
|
||||
_ => a.make_indirect()
|
||||
}
|
||||
}
|
||||
layout::Abi::Vector { .. } => {
|
||||
Abi::Vector { .. } => {
|
||||
// FIXME(eddyb) there should be a size cap here
|
||||
// (probably what clang calls "illegal vectors").
|
||||
}
|
||||
layout::Abi::Scalar(_) => {
|
||||
Abi::Scalar(_) => {
|
||||
if a.layout.size.bytes() > 8 {
|
||||
a.make_indirect();
|
||||
} else {
|
823
src/librustc_target/abi/mod.rs
Normal file
823
src/librustc_target/abi/mod.rs
Normal file
@ -0,0 +1,823 @@
|
||||
// Copyright 2017 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.
|
||||
|
||||
pub use self::Integer::*;
|
||||
pub use self::Primitive::*;
|
||||
|
||||
use spec::Target;
|
||||
|
||||
use std::cmp;
|
||||
use std::ops::{Add, Deref, Sub, Mul, AddAssign, RangeInclusive};
|
||||
|
||||
pub mod call;
|
||||
|
||||
/// Parsed [Data layout](http://llvm.org/docs/LangRef.html#data-layout)
|
||||
/// for a target, which contains everything needed to compute layouts.
|
||||
pub struct TargetDataLayout {
|
||||
pub endian: Endian,
|
||||
pub i1_align: Align,
|
||||
pub i8_align: Align,
|
||||
pub i16_align: Align,
|
||||
pub i32_align: Align,
|
||||
pub i64_align: Align,
|
||||
pub i128_align: Align,
|
||||
pub f32_align: Align,
|
||||
pub f64_align: Align,
|
||||
pub pointer_size: Size,
|
||||
pub pointer_align: Align,
|
||||
pub aggregate_align: Align,
|
||||
|
||||
/// Alignments for vector types.
|
||||
pub vector_align: Vec<(Size, Align)>
|
||||
}
|
||||
|
||||
impl Default for TargetDataLayout {
|
||||
/// Creates an instance of `TargetDataLayout`.
|
||||
fn default() -> TargetDataLayout {
|
||||
TargetDataLayout {
|
||||
endian: Endian::Big,
|
||||
i1_align: Align::from_bits(8, 8).unwrap(),
|
||||
i8_align: Align::from_bits(8, 8).unwrap(),
|
||||
i16_align: Align::from_bits(16, 16).unwrap(),
|
||||
i32_align: Align::from_bits(32, 32).unwrap(),
|
||||
i64_align: Align::from_bits(32, 64).unwrap(),
|
||||
i128_align: Align::from_bits(32, 64).unwrap(),
|
||||
f32_align: Align::from_bits(32, 32).unwrap(),
|
||||
f64_align: Align::from_bits(64, 64).unwrap(),
|
||||
pointer_size: Size::from_bits(64),
|
||||
pointer_align: Align::from_bits(64, 64).unwrap(),
|
||||
aggregate_align: Align::from_bits(0, 64).unwrap(),
|
||||
vector_align: vec![
|
||||
(Size::from_bits(64), Align::from_bits(64, 64).unwrap()),
|
||||
(Size::from_bits(128), Align::from_bits(128, 128).unwrap())
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TargetDataLayout {
|
||||
pub fn parse(target: &Target) -> Result<TargetDataLayout, String> {
|
||||
// Parse a bit count from a string.
|
||||
let parse_bits = |s: &str, kind: &str, cause: &str| {
|
||||
s.parse::<u64>().map_err(|err| {
|
||||
format!("invalid {} `{}` for `{}` in \"data-layout\": {}",
|
||||
kind, s, cause, err)
|
||||
})
|
||||
};
|
||||
|
||||
// Parse a size string.
|
||||
let size = |s: &str, cause: &str| {
|
||||
parse_bits(s, "size", cause).map(Size::from_bits)
|
||||
};
|
||||
|
||||
// Parse an alignment string.
|
||||
let align = |s: &[&str], cause: &str| {
|
||||
if s.is_empty() {
|
||||
return Err(format!("missing alignment for `{}` in \"data-layout\"", cause));
|
||||
}
|
||||
let abi = parse_bits(s[0], "alignment", cause)?;
|
||||
let pref = s.get(1).map_or(Ok(abi), |pref| parse_bits(pref, "alignment", cause))?;
|
||||
Align::from_bits(abi, pref).map_err(|err| {
|
||||
format!("invalid alignment for `{}` in \"data-layout\": {}",
|
||||
cause, err)
|
||||
})
|
||||
};
|
||||
|
||||
let mut dl = TargetDataLayout::default();
|
||||
let mut i128_align_src = 64;
|
||||
for spec in target.data_layout.split("-") {
|
||||
match &spec.split(":").collect::<Vec<_>>()[..] {
|
||||
&["e"] => dl.endian = Endian::Little,
|
||||
&["E"] => dl.endian = Endian::Big,
|
||||
&["a", ref a..] => dl.aggregate_align = align(a, "a")?,
|
||||
&["f32", ref a..] => dl.f32_align = align(a, "f32")?,
|
||||
&["f64", ref a..] => dl.f64_align = align(a, "f64")?,
|
||||
&[p @ "p", s, ref a..] | &[p @ "p0", s, ref a..] => {
|
||||
dl.pointer_size = size(s, p)?;
|
||||
dl.pointer_align = align(a, p)?;
|
||||
}
|
||||
&[s, ref a..] if s.starts_with("i") => {
|
||||
let bits = match s[1..].parse::<u64>() {
|
||||
Ok(bits) => bits,
|
||||
Err(_) => {
|
||||
size(&s[1..], "i")?; // For the user error.
|
||||
continue;
|
||||
}
|
||||
};
|
||||
let a = align(a, s)?;
|
||||
match bits {
|
||||
1 => dl.i1_align = a,
|
||||
8 => dl.i8_align = a,
|
||||
16 => dl.i16_align = a,
|
||||
32 => dl.i32_align = a,
|
||||
64 => dl.i64_align = a,
|
||||
_ => {}
|
||||
}
|
||||
if bits >= i128_align_src && bits <= 128 {
|
||||
// Default alignment for i128 is decided by taking the alignment of
|
||||
// largest-sized i{64...128}.
|
||||
i128_align_src = bits;
|
||||
dl.i128_align = a;
|
||||
}
|
||||
}
|
||||
&[s, ref a..] if s.starts_with("v") => {
|
||||
let v_size = size(&s[1..], "v")?;
|
||||
let a = align(a, s)?;
|
||||
if let Some(v) = dl.vector_align.iter_mut().find(|v| v.0 == v_size) {
|
||||
v.1 = a;
|
||||
continue;
|
||||
}
|
||||
// No existing entry, add a new one.
|
||||
dl.vector_align.push((v_size, a));
|
||||
}
|
||||
_ => {} // Ignore everything else.
|
||||
}
|
||||
}
|
||||
|
||||
// Perform consistency checks against the Target information.
|
||||
let endian_str = match dl.endian {
|
||||
Endian::Little => "little",
|
||||
Endian::Big => "big"
|
||||
};
|
||||
if endian_str != target.target_endian {
|
||||
return Err(format!("inconsistent target specification: \"data-layout\" claims \
|
||||
architecture is {}-endian, while \"target-endian\" is `{}`",
|
||||
endian_str, target.target_endian));
|
||||
}
|
||||
|
||||
if dl.pointer_size.bits().to_string() != target.target_pointer_width {
|
||||
return Err(format!("inconsistent target specification: \"data-layout\" claims \
|
||||
pointers are {}-bit, while \"target-pointer-width\" is `{}`",
|
||||
dl.pointer_size.bits(), target.target_pointer_width));
|
||||
}
|
||||
|
||||
Ok(dl)
|
||||
}
|
||||
|
||||
/// Return exclusive upper bound on object size.
|
||||
///
|
||||
/// The theoretical maximum object size is defined as the maximum positive `isize` value.
|
||||
/// This ensures that the `offset` semantics remain well-defined by allowing it to correctly
|
||||
/// index every address within an object along with one byte past the end, along with allowing
|
||||
/// `isize` to store the difference between any two pointers into an object.
|
||||
///
|
||||
/// The upper bound on 64-bit currently needs to be lower because LLVM uses a 64-bit integer
|
||||
/// to represent object size in bits. It would need to be 1 << 61 to account for this, but is
|
||||
/// currently conservatively bounded to 1 << 47 as that is enough to cover the current usable
|
||||
/// address space on 64-bit ARMv8 and x86_64.
|
||||
pub fn obj_size_bound(&self) -> u64 {
|
||||
match self.pointer_size.bits() {
|
||||
16 => 1 << 15,
|
||||
32 => 1 << 31,
|
||||
64 => 1 << 47,
|
||||
bits => panic!("obj_size_bound: unknown pointer bit size {}", bits)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ptr_sized_integer(&self) -> Integer {
|
||||
match self.pointer_size.bits() {
|
||||
16 => I16,
|
||||
32 => I32,
|
||||
64 => I64,
|
||||
bits => panic!("ptr_sized_integer: unknown pointer bit size {}", bits)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn vector_align(&self, vec_size: Size) -> Align {
|
||||
for &(size, align) in &self.vector_align {
|
||||
if size == vec_size {
|
||||
return align;
|
||||
}
|
||||
}
|
||||
// Default to natural alignment, which is what LLVM does.
|
||||
// That is, use the size, rounded up to a power of 2.
|
||||
let align = vec_size.bytes().next_power_of_two();
|
||||
Align::from_bytes(align, align).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait HasDataLayout: Copy {
|
||||
fn data_layout(&self) -> &TargetDataLayout;
|
||||
}
|
||||
|
||||
impl<'a> HasDataLayout for &'a TargetDataLayout {
|
||||
fn data_layout(&self) -> &TargetDataLayout {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// Endianness of the target, which must match cfg(target-endian).
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum Endian {
|
||||
Little,
|
||||
Big
|
||||
}
|
||||
|
||||
/// Size of a type in bytes.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
||||
pub struct Size {
|
||||
raw: u64
|
||||
}
|
||||
|
||||
impl Size {
|
||||
pub fn from_bits(bits: u64) -> Size {
|
||||
// Avoid potential overflow from `bits + 7`.
|
||||
Size::from_bytes(bits / 8 + ((bits % 8) + 7) / 8)
|
||||
}
|
||||
|
||||
pub fn from_bytes(bytes: u64) -> Size {
|
||||
if bytes >= (1 << 61) {
|
||||
panic!("Size::from_bytes: {} bytes in bits doesn't fit in u64", bytes)
|
||||
}
|
||||
Size {
|
||||
raw: bytes
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bytes(self) -> u64 {
|
||||
self.raw
|
||||
}
|
||||
|
||||
pub fn bits(self) -> u64 {
|
||||
self.bytes() * 8
|
||||
}
|
||||
|
||||
pub fn abi_align(self, align: Align) -> Size {
|
||||
let mask = align.abi() - 1;
|
||||
Size::from_bytes((self.bytes() + mask) & !mask)
|
||||
}
|
||||
|
||||
pub fn is_abi_aligned(self, align: Align) -> bool {
|
||||
let mask = align.abi() - 1;
|
||||
self.bytes() & mask == 0
|
||||
}
|
||||
|
||||
pub fn checked_add<C: HasDataLayout>(self, offset: Size, cx: C) -> Option<Size> {
|
||||
let dl = cx.data_layout();
|
||||
|
||||
// Each Size is less than dl.obj_size_bound(), so the sum is
|
||||
// also less than 1 << 62 (and therefore can't overflow).
|
||||
let bytes = self.bytes() + offset.bytes();
|
||||
|
||||
if bytes < dl.obj_size_bound() {
|
||||
Some(Size::from_bytes(bytes))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn checked_mul<C: HasDataLayout>(self, count: u64, cx: C) -> Option<Size> {
|
||||
let dl = cx.data_layout();
|
||||
|
||||
match self.bytes().checked_mul(count) {
|
||||
Some(bytes) if bytes < dl.obj_size_bound() => {
|
||||
Some(Size::from_bytes(bytes))
|
||||
}
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Panicking addition, subtraction and multiplication for convenience.
|
||||
// Avoid during layout computation, return `LayoutError` instead.
|
||||
|
||||
impl Add for Size {
|
||||
type Output = Size;
|
||||
fn add(self, other: Size) -> Size {
|
||||
// Each Size is less than 1 << 61, so the sum is
|
||||
// less than 1 << 62 (and therefore can't overflow).
|
||||
Size::from_bytes(self.bytes() + other.bytes())
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub for Size {
|
||||
type Output = Size;
|
||||
fn sub(self, other: Size) -> Size {
|
||||
// Each Size is less than 1 << 61, so an underflow
|
||||
// would result in a value larger than 1 << 61,
|
||||
// which Size::from_bytes will catch for us.
|
||||
Size::from_bytes(self.bytes() - other.bytes())
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul<u64> for Size {
|
||||
type Output = Size;
|
||||
fn mul(self, count: u64) -> Size {
|
||||
match self.bytes().checked_mul(count) {
|
||||
Some(bytes) => Size::from_bytes(bytes),
|
||||
None => {
|
||||
panic!("Size::mul: {} * {} doesn't fit in u64", self.bytes(), count)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AddAssign for Size {
|
||||
fn add_assign(&mut self, other: Size) {
|
||||
*self = *self + other;
|
||||
}
|
||||
}
|
||||
|
||||
/// Alignment of a type in bytes, both ABI-mandated and preferred.
|
||||
/// Each field is a power of two, giving the alignment a maximum value of
|
||||
/// 2<sup>(2<sup>8</sup> - 1)</sup>, which is limited by LLVM to a i32,
|
||||
/// with a maximum capacity of 2<sup>31</sup> - 1 or 2147483647.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
|
||||
pub struct Align {
|
||||
abi_pow2: u8,
|
||||
pref_pow2: u8,
|
||||
}
|
||||
|
||||
impl Align {
|
||||
pub fn from_bits(abi: u64, pref: u64) -> Result<Align, String> {
|
||||
Align::from_bytes(Size::from_bits(abi).bytes(),
|
||||
Size::from_bits(pref).bytes())
|
||||
}
|
||||
|
||||
pub fn from_bytes(abi: u64, pref: u64) -> Result<Align, String> {
|
||||
let log2 = |align: u64| {
|
||||
// Treat an alignment of 0 bytes like 1-byte alignment.
|
||||
if align == 0 {
|
||||
return Ok(0);
|
||||
}
|
||||
|
||||
let mut bytes = align;
|
||||
let mut pow: u8 = 0;
|
||||
while (bytes & 1) == 0 {
|
||||
pow += 1;
|
||||
bytes >>= 1;
|
||||
}
|
||||
if bytes != 1 {
|
||||
Err(format!("`{}` is not a power of 2", align))
|
||||
} else if pow > 30 {
|
||||
Err(format!("`{}` is too large", align))
|
||||
} else {
|
||||
Ok(pow)
|
||||
}
|
||||
};
|
||||
|
||||
Ok(Align {
|
||||
abi_pow2: log2(abi)?,
|
||||
pref_pow2: log2(pref)?,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn abi(self) -> u64 {
|
||||
1 << self.abi_pow2
|
||||
}
|
||||
|
||||
pub fn pref(self) -> u64 {
|
||||
1 << self.pref_pow2
|
||||
}
|
||||
|
||||
pub fn abi_bits(self) -> u64 {
|
||||
self.abi() * 8
|
||||
}
|
||||
|
||||
pub fn pref_bits(self) -> u64 {
|
||||
self.pref() * 8
|
||||
}
|
||||
|
||||
pub fn min(self, other: Align) -> Align {
|
||||
Align {
|
||||
abi_pow2: cmp::min(self.abi_pow2, other.abi_pow2),
|
||||
pref_pow2: cmp::min(self.pref_pow2, other.pref_pow2),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn max(self, other: Align) -> Align {
|
||||
Align {
|
||||
abi_pow2: cmp::max(self.abi_pow2, other.abi_pow2),
|
||||
pref_pow2: cmp::max(self.pref_pow2, other.pref_pow2),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Integers, also used for enum discriminants.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
||||
pub enum Integer {
|
||||
I8,
|
||||
I16,
|
||||
I32,
|
||||
I64,
|
||||
I128,
|
||||
}
|
||||
|
||||
impl Integer {
|
||||
pub fn size(&self) -> Size {
|
||||
match *self {
|
||||
I8 => Size::from_bytes(1),
|
||||
I16 => Size::from_bytes(2),
|
||||
I32 => Size::from_bytes(4),
|
||||
I64 => Size::from_bytes(8),
|
||||
I128 => Size::from_bytes(16),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn align<C: HasDataLayout>(&self, cx: C) -> Align {
|
||||
let dl = cx.data_layout();
|
||||
|
||||
match *self {
|
||||
I8 => dl.i8_align,
|
||||
I16 => dl.i16_align,
|
||||
I32 => dl.i32_align,
|
||||
I64 => dl.i64_align,
|
||||
I128 => dl.i128_align,
|
||||
}
|
||||
}
|
||||
|
||||
/// Find the smallest Integer type which can represent the signed value.
|
||||
pub fn fit_signed(x: i128) -> Integer {
|
||||
match x {
|
||||
-0x0000_0000_0000_0080...0x0000_0000_0000_007f => I8,
|
||||
-0x0000_0000_0000_8000...0x0000_0000_0000_7fff => I16,
|
||||
-0x0000_0000_8000_0000...0x0000_0000_7fff_ffff => I32,
|
||||
-0x8000_0000_0000_0000...0x7fff_ffff_ffff_ffff => I64,
|
||||
_ => I128
|
||||
}
|
||||
}
|
||||
|
||||
/// Find the smallest Integer type which can represent the unsigned value.
|
||||
pub fn fit_unsigned(x: u128) -> Integer {
|
||||
match x {
|
||||
0...0x0000_0000_0000_00ff => I8,
|
||||
0...0x0000_0000_0000_ffff => I16,
|
||||
0...0x0000_0000_ffff_ffff => I32,
|
||||
0...0xffff_ffff_ffff_ffff => I64,
|
||||
_ => I128,
|
||||
}
|
||||
}
|
||||
|
||||
/// Find the smallest integer with the given alignment.
|
||||
pub fn for_abi_align<C: HasDataLayout>(cx: C, align: Align) -> Option<Integer> {
|
||||
let dl = cx.data_layout();
|
||||
|
||||
let wanted = align.abi();
|
||||
for &candidate in &[I8, I16, I32, I64, I128] {
|
||||
if wanted == candidate.align(dl).abi() && wanted == candidate.size().bytes() {
|
||||
return Some(candidate);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
/// Find the largest integer with the given alignment or less.
|
||||
pub fn approximate_abi_align<C: HasDataLayout>(cx: C, align: Align) -> Integer {
|
||||
let dl = cx.data_layout();
|
||||
|
||||
let wanted = align.abi();
|
||||
// FIXME(eddyb) maybe include I128 in the future, when it works everywhere.
|
||||
for &candidate in &[I64, I32, I16] {
|
||||
if wanted >= candidate.align(dl).abi() && wanted >= candidate.size().bytes() {
|
||||
return candidate;
|
||||
}
|
||||
}
|
||||
I8
|
||||
}
|
||||
}
|
||||
|
||||
/// Fundamental unit of memory access and layout.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||
pub enum Primitive {
|
||||
/// The `bool` is the signedness of the `Integer` type.
|
||||
///
|
||||
/// One would think we would not care about such details this low down,
|
||||
/// but some ABIs are described in terms of C types and ISAs where the
|
||||
/// integer arithmetic is done on {sign,zero}-extended registers, e.g.
|
||||
/// a negative integer passed by zero-extension will appear positive in
|
||||
/// the callee, and most operations on it will produce the wrong values.
|
||||
Int(Integer, bool),
|
||||
F32,
|
||||
F64,
|
||||
Pointer
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Primitive {
|
||||
pub fn size<C: HasDataLayout>(self, cx: C) -> Size {
|
||||
let dl = cx.data_layout();
|
||||
|
||||
match self {
|
||||
Int(i, _) => i.size(),
|
||||
F32 => Size::from_bits(32),
|
||||
F64 => Size::from_bits(64),
|
||||
Pointer => dl.pointer_size
|
||||
}
|
||||
}
|
||||
|
||||
pub fn align<C: HasDataLayout>(self, cx: C) -> Align {
|
||||
let dl = cx.data_layout();
|
||||
|
||||
match self {
|
||||
Int(i, _) => i.align(dl),
|
||||
F32 => dl.f32_align,
|
||||
F64 => dl.f64_align,
|
||||
Pointer => dl.pointer_align
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Information about one scalar component of a Rust type.
|
||||
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
|
||||
pub struct Scalar {
|
||||
pub value: Primitive,
|
||||
|
||||
/// Inclusive wrap-around range of valid values, that is, if
|
||||
/// min > max, it represents min..=u128::MAX followed by 0..=max.
|
||||
// FIXME(eddyb) always use the shortest range, e.g. by finding
|
||||
// the largest space between two consecutive valid values and
|
||||
// taking everything else as the (shortest) valid range.
|
||||
pub valid_range: RangeInclusive<u128>,
|
||||
}
|
||||
|
||||
impl Scalar {
|
||||
pub fn is_bool(&self) -> bool {
|
||||
if let Int(I8, _) = self.value {
|
||||
self.valid_range == (0..=1)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Describes how the fields of a type are located in memory.
|
||||
#[derive(PartialEq, Eq, Hash, Debug)]
|
||||
pub enum FieldPlacement {
|
||||
/// All fields start at no offset. The `usize` is the field count.
|
||||
Union(usize),
|
||||
|
||||
/// Array/vector-like placement, with all fields of identical types.
|
||||
Array {
|
||||
stride: Size,
|
||||
count: u64
|
||||
},
|
||||
|
||||
/// Struct-like placement, with precomputed offsets.
|
||||
///
|
||||
/// Fields are guaranteed to not overlap, but note that gaps
|
||||
/// before, between and after all the fields are NOT always
|
||||
/// padding, and as such their contents may not be discarded.
|
||||
/// For example, enum variants leave a gap at the start,
|
||||
/// where the discriminant field in the enum layout goes.
|
||||
Arbitrary {
|
||||
/// Offsets for the first byte of each field,
|
||||
/// ordered to match the source definition order.
|
||||
/// This vector does not go in increasing order.
|
||||
// FIXME(eddyb) use small vector optimization for the common case.
|
||||
offsets: Vec<Size>,
|
||||
|
||||
/// Maps source order field indices to memory order indices,
|
||||
/// depending how fields were permuted.
|
||||
// FIXME(camlorn) also consider small vector optimization here.
|
||||
memory_index: Vec<u32>
|
||||
}
|
||||
}
|
||||
|
||||
impl FieldPlacement {
|
||||
pub fn count(&self) -> usize {
|
||||
match *self {
|
||||
FieldPlacement::Union(count) => count,
|
||||
FieldPlacement::Array { count, .. } => {
|
||||
let usize_count = count as usize;
|
||||
assert_eq!(usize_count as u64, count);
|
||||
usize_count
|
||||
}
|
||||
FieldPlacement::Arbitrary { ref offsets, .. } => offsets.len()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn offset(&self, i: usize) -> Size {
|
||||
match *self {
|
||||
FieldPlacement::Union(_) => Size::from_bytes(0),
|
||||
FieldPlacement::Array { stride, count } => {
|
||||
let i = i as u64;
|
||||
assert!(i < count);
|
||||
stride * i
|
||||
}
|
||||
FieldPlacement::Arbitrary { ref offsets, .. } => offsets[i]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn memory_index(&self, i: usize) -> usize {
|
||||
match *self {
|
||||
FieldPlacement::Union(_) |
|
||||
FieldPlacement::Array { .. } => i,
|
||||
FieldPlacement::Arbitrary { ref memory_index, .. } => {
|
||||
let r = memory_index[i];
|
||||
assert_eq!(r as usize as u32, r);
|
||||
r as usize
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Get source indices of the fields by increasing offsets.
|
||||
#[inline]
|
||||
pub fn index_by_increasing_offset<'a>(&'a self) -> impl Iterator<Item=usize>+'a {
|
||||
let mut inverse_small = [0u8; 64];
|
||||
let mut inverse_big = vec![];
|
||||
let use_small = self.count() <= inverse_small.len();
|
||||
|
||||
// We have to write this logic twice in order to keep the array small.
|
||||
if let FieldPlacement::Arbitrary { ref memory_index, .. } = *self {
|
||||
if use_small {
|
||||
for i in 0..self.count() {
|
||||
inverse_small[memory_index[i] as usize] = i as u8;
|
||||
}
|
||||
} else {
|
||||
inverse_big = vec![0; self.count()];
|
||||
for i in 0..self.count() {
|
||||
inverse_big[memory_index[i] as usize] = i as u32;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(0..self.count()).map(move |i| {
|
||||
match *self {
|
||||
FieldPlacement::Union(_) |
|
||||
FieldPlacement::Array { .. } => i,
|
||||
FieldPlacement::Arbitrary { .. } => {
|
||||
if use_small { inverse_small[i] as usize }
|
||||
else { inverse_big[i] as usize }
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Describes how values of the type are passed by target ABIs,
|
||||
/// in terms of categories of C types there are ABI rules for.
|
||||
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
|
||||
pub enum Abi {
|
||||
Uninhabited,
|
||||
Scalar(Scalar),
|
||||
ScalarPair(Scalar, Scalar),
|
||||
Vector {
|
||||
element: Scalar,
|
||||
count: u64
|
||||
},
|
||||
Aggregate {
|
||||
/// If true, the size is exact, otherwise it's only a lower bound.
|
||||
sized: bool,
|
||||
}
|
||||
}
|
||||
|
||||
impl Abi {
|
||||
/// Returns true if the layout corresponds to an unsized type.
|
||||
pub fn is_unsized(&self) -> bool {
|
||||
match *self {
|
||||
Abi::Uninhabited |
|
||||
Abi::Scalar(_) |
|
||||
Abi::ScalarPair(..) |
|
||||
Abi::Vector { .. } => false,
|
||||
Abi::Aggregate { sized } => !sized
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if this is a single signed integer scalar
|
||||
pub fn is_signed(&self) -> bool {
|
||||
match *self {
|
||||
Abi::Scalar(ref scal) => match scal.value {
|
||||
Primitive::Int(_, signed) => signed,
|
||||
_ => false,
|
||||
},
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Hash, Debug)]
|
||||
pub enum Variants {
|
||||
/// Single enum variants, structs/tuples, unions, and all non-ADTs.
|
||||
Single {
|
||||
index: usize
|
||||
},
|
||||
|
||||
/// General-case enums: for each case there is a struct, and they all have
|
||||
/// all space reserved for the discriminant, and their first field starts
|
||||
/// at a non-0 offset, after where the discriminant would go.
|
||||
Tagged {
|
||||
discr: Scalar,
|
||||
variants: Vec<LayoutDetails>,
|
||||
},
|
||||
|
||||
/// Multiple cases distinguished by a niche (values invalid for a type):
|
||||
/// the variant `dataful_variant` contains a niche at an arbitrary
|
||||
/// offset (field 0 of the enum), which for a variant with discriminant
|
||||
/// `d` is set to `(d - niche_variants.start).wrapping_add(niche_start)`.
|
||||
///
|
||||
/// For example, `Option<(usize, &T)>` is represented such that
|
||||
/// `None` has a null pointer for the second tuple field, and
|
||||
/// `Some` is the identity function (with a non-null reference).
|
||||
NicheFilling {
|
||||
dataful_variant: usize,
|
||||
niche_variants: RangeInclusive<usize>,
|
||||
niche: Scalar,
|
||||
niche_start: u128,
|
||||
variants: Vec<LayoutDetails>,
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Hash, Debug)]
|
||||
pub struct LayoutDetails {
|
||||
pub variants: Variants,
|
||||
pub fields: FieldPlacement,
|
||||
pub abi: Abi,
|
||||
pub align: Align,
|
||||
pub size: Size
|
||||
}
|
||||
|
||||
impl LayoutDetails {
|
||||
pub fn scalar<C: HasDataLayout>(cx: C, scalar: Scalar) -> Self {
|
||||
let size = scalar.value.size(cx);
|
||||
let align = scalar.value.align(cx);
|
||||
LayoutDetails {
|
||||
variants: Variants::Single { index: 0 },
|
||||
fields: FieldPlacement::Union(0),
|
||||
abi: Abi::Scalar(scalar),
|
||||
size,
|
||||
align,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn uninhabited(field_count: usize) -> Self {
|
||||
let align = Align::from_bytes(1, 1).unwrap();
|
||||
LayoutDetails {
|
||||
variants: Variants::Single { index: 0 },
|
||||
fields: FieldPlacement::Union(field_count),
|
||||
abi: Abi::Uninhabited,
|
||||
align,
|
||||
size: Size::from_bytes(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The details of the layout of a type, alongside the type itself.
|
||||
/// Provides various type traversal APIs (e.g. recursing into fields).
|
||||
///
|
||||
/// Note that the details are NOT guaranteed to always be identical
|
||||
/// to those obtained from `layout_of(ty)`, as we need to produce
|
||||
/// layouts for which Rust types do not exist, such as enum variants
|
||||
/// or synthetic fields of enums (i.e. discriminants) and fat pointers.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct TyLayout<'a, Ty> {
|
||||
pub ty: Ty,
|
||||
pub details: &'a LayoutDetails
|
||||
}
|
||||
|
||||
impl<'a, Ty> Deref for TyLayout<'a, Ty> {
|
||||
type Target = &'a LayoutDetails;
|
||||
fn deref(&self) -> &&'a LayoutDetails {
|
||||
&self.details
|
||||
}
|
||||
}
|
||||
|
||||
pub trait LayoutOf {
|
||||
type Ty;
|
||||
type TyLayout;
|
||||
|
||||
fn layout_of(self, ty: Self::Ty) -> Self::TyLayout;
|
||||
}
|
||||
|
||||
pub trait TyLayoutMethods<'a, C: LayoutOf<Ty = Self>>: Sized {
|
||||
fn for_variant(this: TyLayout<'a, Self>, cx: C, variant_index: usize) -> TyLayout<'a, Self>;
|
||||
fn field(this: TyLayout<'a, Self>, cx: C, i: usize) -> C::TyLayout;
|
||||
}
|
||||
|
||||
impl<'a, Ty> TyLayout<'a, Ty> {
|
||||
pub fn for_variant<C>(self, cx: C, variant_index: usize) -> Self
|
||||
where Ty: TyLayoutMethods<'a, C>, C: LayoutOf<Ty = Ty> {
|
||||
Ty::for_variant(self, cx, variant_index)
|
||||
}
|
||||
pub fn field<C>(self, cx: C, i: usize) -> C::TyLayout
|
||||
where Ty: TyLayoutMethods<'a, C>, C: LayoutOf<Ty = Ty> {
|
||||
Ty::field(self, cx, i)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Ty> TyLayout<'a, Ty> {
|
||||
/// Returns true if the layout corresponds to an unsized type.
|
||||
pub fn is_unsized(&self) -> bool {
|
||||
self.abi.is_unsized()
|
||||
}
|
||||
|
||||
/// Returns true if the type is a ZST and not unsized.
|
||||
pub fn is_zst(&self) -> bool {
|
||||
match self.abi {
|
||||
Abi::Uninhabited => true,
|
||||
Abi::Scalar(_) |
|
||||
Abi::ScalarPair(..) |
|
||||
Abi::Vector { .. } => false,
|
||||
Abi::Aggregate { sized } => sized && self.size.bytes() == 0
|
||||
}
|
||||
}
|
||||
|
||||
pub fn size_and_align(&self) -> (Size, Align) {
|
||||
(self.size, self.align)
|
||||
}
|
||||
}
|
46
src/librustc_target/lib.rs
Normal file
46
src/librustc_target/lib.rs
Normal file
@ -0,0 +1,46 @@
|
||||
// Copyright 2012-2013 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.
|
||||
|
||||
//! Some stuff used by rustc that doesn't have many dependencies
|
||||
//!
|
||||
//! Originally extracted from rustc::back, which was nominally the
|
||||
//! compiler 'backend', though LLVM is rustc's backend, so rustc_target
|
||||
//! is really just odds-and-ends relating to code gen and linking.
|
||||
//! This crate mostly exists to make rustc smaller, so we might put
|
||||
//! more 'stuff' here in the future. It does not have a dependency on
|
||||
//! rustc_llvm.
|
||||
//!
|
||||
//! FIXME: Split this into two crates: one that has deps on syntax, and
|
||||
//! one that doesn't; the one that doesn't might get decent parallel
|
||||
//! build speedups.
|
||||
|
||||
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
|
||||
html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
|
||||
html_root_url = "https://doc.rust-lang.org/nightly/")]
|
||||
|
||||
#![feature(box_syntax)]
|
||||
#![feature(const_fn)]
|
||||
#![feature(fs_read_write)]
|
||||
#![feature(inclusive_range)]
|
||||
#![feature(slice_patterns)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate bitflags;
|
||||
extern crate serialize;
|
||||
#[macro_use] extern crate log;
|
||||
|
||||
extern crate serialize as rustc_serialize; // used by deriving
|
||||
|
||||
// See librustc_cratesio_shim/Cargo.toml for a comment explaining this.
|
||||
#[allow(unused_extern_crates)]
|
||||
extern crate rustc_cratesio_shim;
|
||||
|
||||
pub mod abi;
|
||||
pub mod spec;
|
@ -8,8 +8,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use LinkerFlavor;
|
||||
use target::{Target, TargetOptions, TargetResult};
|
||||
use spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
|
||||
use super::apple_ios_base::{opts, Arch};
|
||||
|
||||
pub fn target() -> TargetResult {
|
@ -8,8 +8,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use LinkerFlavor;
|
||||
use target::{Target, TargetOptions, TargetResult};
|
||||
use spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
|
||||
|
||||
// See https://developer.android.com/ndk/guides/abis.html#arm64-v8a
|
||||
// for target ABI requirements.
|
@ -8,8 +8,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use LinkerFlavor;
|
||||
use target::{Target, TargetResult};
|
||||
use spec::{LinkerFlavor, Target, TargetResult};
|
||||
|
||||
pub fn target() -> TargetResult {
|
||||
let mut base = super::cloudabi_base::opts();
|
@ -8,8 +8,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use LinkerFlavor;
|
||||
use target::{Target, TargetOptions, TargetResult};
|
||||
use spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
|
||||
|
||||
pub fn target() -> TargetResult {
|
||||
let mut base = super::freebsd_base::opts();
|
@ -8,8 +8,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use LinkerFlavor;
|
||||
use target::{Target, TargetOptions, TargetResult};
|
||||
use spec::{LinkerFlavor, Target, TargetOptions, TargetResult};
|
||||
|
||||
pub fn target() -> TargetResult {
|
||||
let mut base = super::fuchsia_base::opts();
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user