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:
bors 2018-04-26 16:00:48 +00:00
commit 949010d23e
251 changed files with 2268 additions and 2087 deletions

44
src/Cargo.lock generated
View File

@ -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",
]

View File

@ -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" }

View File

@ -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::*;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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};

View File

@ -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
});

View File

@ -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,

View File

@ -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;

View File

@ -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 {

View File

@ -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::*;

View File

@ -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.
///

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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))

View File

@ -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};

View File

@ -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();

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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,

View File

@ -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};

View File

@ -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};

View File

@ -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;

View File

@ -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" }

View File

@ -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};

View File

@ -12,6 +12,7 @@
extern crate rustc;
extern crate rustc_errors;
extern crate rustc_target;
extern crate syntax;
extern crate syntax_pos;

View File

@ -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

View File

@ -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(),
}
}
}

View File

@ -21,3 +21,4 @@ crate-type = ["dylib"]
[dependencies]
bitflags = "1.0"
log = "0.4"

View File

@ -12,3 +12,4 @@
#![allow(unused_extern_crates)]
extern crate bitflags;
extern crate log;

View File

@ -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"

View File

@ -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;

View File

@ -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" }

View File

@ -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"));
},

View File

@ -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;

View File

@ -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" }

View File

@ -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;

View File

@ -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";

View File

@ -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;

View File

@ -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;

View File

@ -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" }

View File

@ -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};

View File

@ -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};

View File

@ -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;

View File

@ -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 {

View File

@ -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;

View File

@ -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};

View File

@ -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};

View File

@ -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" }

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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]

View File

@ -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};

View File

@ -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;

View File

@ -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("\" ");

View File

@ -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;

View File

@ -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 {

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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" }

View File

@ -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;

View File

@ -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(' ');

View File

@ -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 = []

View 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/

View File

@ -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);
}

View File

@ -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() {

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);

View File

@ -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);
}

View 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(())
}
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);

View File

@ -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() {

View File

@ -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);
}

View File

@ -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);

View File

@ -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);
}

View File

@ -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 {

View File

@ -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)
}
};

View File

@ -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;

View File

@ -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 {

View 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)
}
}

View 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;

View File

@ -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 {

View File

@ -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.

View File

@ -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();

View File

@ -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();

View File

@ -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