check target abi support
This commit is contained in:
parent
ac468b67bf
commit
9eb0fd98c6
src
librustc_back/target
aarch64_apple_ios.rsaarch64_linux_android.rsaarch64_unknown_linux_gnu.rsarm_base.rsarm_linux_androideabi.rsarm_unknown_linux_gnueabi.rsarm_unknown_linux_gnueabihf.rsarm_unknown_linux_musleabi.rsarm_unknown_linux_musleabihf.rsarmv7_apple_ios.rsarmv7_linux_androideabi.rsarmv7_unknown_linux_gnueabihf.rsarmv7_unknown_linux_musleabihf.rsarmv7s_apple_ios.rsmod.rsthumb_base.rs
librustc_typeck
libsyntax
@ -26,6 +26,7 @@ pub fn target() -> TargetResult {
|
||||
features: "+neon,+fp-armv8,+cyclone".to_string(),
|
||||
eliminate_frame_pointer: false,
|
||||
max_atomic_width: Some(128),
|
||||
abi_blacklist: super::arm_base::abi_blacklist(),
|
||||
.. base
|
||||
},
|
||||
})
|
||||
|
@ -8,7 +8,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use target::{Target, TargetResult};
|
||||
use target::{Target, TargetOptions, TargetResult};
|
||||
|
||||
pub fn target() -> TargetResult {
|
||||
let mut base = super::android_base::opts();
|
||||
@ -25,6 +25,9 @@ pub fn target() -> TargetResult {
|
||||
target_os: "android".to_string(),
|
||||
target_env: "".to_string(),
|
||||
target_vendor: "unknown".to_string(),
|
||||
options: base,
|
||||
options: TargetOptions {
|
||||
abi_blacklist: super::arm_base::abi_blacklist(),
|
||||
.. base
|
||||
},
|
||||
})
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use target::{Target, TargetResult};
|
||||
use target::{Target, TargetOptions, TargetResult};
|
||||
|
||||
pub fn target() -> TargetResult {
|
||||
let mut base = super::linux_base::opts();
|
||||
@ -22,6 +22,9 @@ pub fn target() -> TargetResult {
|
||||
arch: "aarch64".to_string(),
|
||||
target_os: "linux".to_string(),
|
||||
target_vendor: "unknown".to_string(),
|
||||
options: base,
|
||||
options: TargetOptions {
|
||||
abi_blacklist: super::arm_base::abi_blacklist(),
|
||||
.. base
|
||||
},
|
||||
})
|
||||
}
|
||||
|
16
src/librustc_back/target/arm_base.rs
Normal file
16
src/librustc_back/target/arm_base.rs
Normal file
@ -0,0 +1,16 @@
|
||||
// Copyright 2016 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 syntax::abi::Abi;
|
||||
|
||||
// All the calling conventions trigger an assertion(Unsupported calling convention) in llvm on arm
|
||||
pub fn abi_blacklist() -> Vec<Abi> {
|
||||
vec![Abi::Stdcall, Abi::Fastcall, Abi::Vectorcall, Abi::Win64, Abi::SysV64]
|
||||
}
|
@ -8,7 +8,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use target::{Target, TargetResult};
|
||||
use target::{Target, TargetOptions, TargetResult};
|
||||
|
||||
pub fn target() -> TargetResult {
|
||||
let mut base = super::android_base::opts();
|
||||
@ -24,6 +24,9 @@ pub fn target() -> TargetResult {
|
||||
target_os: "android".to_string(),
|
||||
target_env: "".to_string(),
|
||||
target_vendor: "unknown".to_string(),
|
||||
options: base,
|
||||
options: TargetOptions {
|
||||
abi_blacklist: super::arm_base::abi_blacklist(),
|
||||
.. base
|
||||
},
|
||||
})
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ pub fn target() -> TargetResult {
|
||||
|
||||
options: TargetOptions {
|
||||
features: "+v6".to_string(),
|
||||
abi_blacklist: super::arm_base::abi_blacklist(),
|
||||
.. base
|
||||
},
|
||||
})
|
||||
|
@ -25,6 +25,7 @@ pub fn target() -> TargetResult {
|
||||
|
||||
options: TargetOptions {
|
||||
features: "+v6,+vfp2".to_string(),
|
||||
abi_blacklist: super::arm_base::abi_blacklist(),
|
||||
.. base
|
||||
}
|
||||
})
|
||||
|
@ -8,7 +8,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use target::{Target, TargetResult};
|
||||
use target::{Target, TargetOptions, TargetResult};
|
||||
|
||||
pub fn target() -> TargetResult {
|
||||
let mut base = super::linux_musl_base::opts();
|
||||
@ -29,6 +29,9 @@ pub fn target() -> TargetResult {
|
||||
target_os: "linux".to_string(),
|
||||
target_env: "musl".to_string(),
|
||||
target_vendor: "unknown".to_string(),
|
||||
options: base,
|
||||
options: TargetOptions {
|
||||
abi_blacklist: super::arm_base::abi_blacklist(),
|
||||
.. base
|
||||
},
|
||||
})
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use target::{Target, TargetResult};
|
||||
use target::{Target, TargetOptions, TargetResult};
|
||||
|
||||
pub fn target() -> TargetResult {
|
||||
let mut base = super::linux_musl_base::opts();
|
||||
@ -29,6 +29,9 @@ pub fn target() -> TargetResult {
|
||||
target_os: "linux".to_string(),
|
||||
target_env: "musl".to_string(),
|
||||
target_vendor: "unknown".to_string(),
|
||||
options: base,
|
||||
options: TargetOptions {
|
||||
abi_blacklist: super::arm_base::abi_blacklist(),
|
||||
.. base
|
||||
},
|
||||
})
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ pub fn target() -> TargetResult {
|
||||
options: TargetOptions {
|
||||
features: "+v7,+vfp3,+neon".to_string(),
|
||||
max_atomic_width: Some(64),
|
||||
abi_blacklist: super::arm_base::abi_blacklist(),
|
||||
.. base
|
||||
}
|
||||
})
|
||||
|
@ -8,7 +8,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use target::{Target, TargetResult};
|
||||
use target::{Target, TargetOptions, TargetResult};
|
||||
|
||||
pub fn target() -> TargetResult {
|
||||
let mut base = super::android_base::opts();
|
||||
@ -24,6 +24,9 @@ pub fn target() -> TargetResult {
|
||||
target_os: "android".to_string(),
|
||||
target_env: "".to_string(),
|
||||
target_vendor: "unknown".to_string(),
|
||||
options: base,
|
||||
options: TargetOptions {
|
||||
abi_blacklist: super::arm_base::abi_blacklist(),
|
||||
.. base
|
||||
},
|
||||
})
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ pub fn target() -> TargetResult {
|
||||
features: "+v7,+vfp3,+d16,+thumb2,-neon".to_string(),
|
||||
cpu: "generic".to_string(),
|
||||
max_atomic_width: Some(64),
|
||||
abi_blacklist: super::arm_base::abi_blacklist(),
|
||||
.. base
|
||||
}
|
||||
})
|
||||
|
@ -8,7 +8,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use target::{Target, TargetResult};
|
||||
use target::{Target, TargetOptions, TargetResult};
|
||||
|
||||
pub fn target() -> TargetResult {
|
||||
let mut base = super::linux_musl_base::opts();
|
||||
@ -30,6 +30,9 @@ pub fn target() -> TargetResult {
|
||||
target_os: "linux".to_string(),
|
||||
target_env: "musl".to_string(),
|
||||
target_vendor: "unknown".to_string(),
|
||||
options: base,
|
||||
options: TargetOptions {
|
||||
abi_blacklist: super::arm_base::abi_blacklist(),
|
||||
.. base
|
||||
},
|
||||
})
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ pub fn target() -> TargetResult {
|
||||
options: TargetOptions {
|
||||
features: "+v7,+vfp4,+neon".to_string(),
|
||||
max_atomic_width: Some(64),
|
||||
abi_blacklist: super::arm_base::abi_blacklist(),
|
||||
.. base
|
||||
}
|
||||
})
|
||||
|
@ -48,13 +48,14 @@ use serialize::json::{Json, ToJson};
|
||||
use std::collections::BTreeMap;
|
||||
use std::default::Default;
|
||||
use std::io::prelude::*;
|
||||
use syntax::abi::Abi;
|
||||
use syntax::abi::{Abi, lookup as lookup_abi};
|
||||
|
||||
use PanicStrategy;
|
||||
|
||||
mod android_base;
|
||||
mod apple_base;
|
||||
mod apple_ios_base;
|
||||
mod arm_base;
|
||||
mod bitrig_base;
|
||||
mod dragonfly_base;
|
||||
mod freebsd_base;
|
||||
@ -358,6 +359,10 @@ pub struct TargetOptions {
|
||||
|
||||
/// Panic strategy: "unwind" or "abort"
|
||||
pub panic_strategy: PanicStrategy,
|
||||
|
||||
/// A blacklist of ABIs unsupported by the current target. Note that generic
|
||||
/// ABIs are considered to be supported on all platforms and cannot be blacklisted.
|
||||
pub abi_blacklist: Vec<Abi>,
|
||||
}
|
||||
|
||||
impl Default for TargetOptions {
|
||||
@ -408,6 +413,7 @@ impl Default for TargetOptions {
|
||||
obj_is_bitcode: false,
|
||||
max_atomic_width: None,
|
||||
panic_strategy: PanicStrategy::Unwind,
|
||||
abi_blacklist: vec![],
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -433,6 +439,10 @@ impl Target {
|
||||
self.options.max_atomic_width.unwrap_or(self.target_pointer_width.parse().unwrap())
|
||||
}
|
||||
|
||||
pub fn is_abi_supported(&self, abi: Abi) -> bool {
|
||||
abi.generic() || !self.options.abi_blacklist.contains(&abi)
|
||||
}
|
||||
|
||||
/// Load a target descriptor from a JSON object.
|
||||
pub fn from_json(obj: Json) -> TargetResult {
|
||||
// While ugly, this code must remain this way to retain
|
||||
@ -564,6 +574,22 @@ impl Target {
|
||||
key!(max_atomic_width, Option<u64>);
|
||||
try!(key!(panic_strategy, PanicStrategy));
|
||||
|
||||
if let Some(array) = obj.find("abi-blacklist").and_then(Json::as_array) {
|
||||
for name in array.iter().filter_map(|abi| abi.as_string()) {
|
||||
match lookup_abi(name) {
|
||||
Some(abi) => {
|
||||
if abi.generic() {
|
||||
return Err(format!("The ABI \"{}\" is considered to be supported on \
|
||||
all targets and cannot be blacklisted", abi))
|
||||
}
|
||||
|
||||
base.options.abi_blacklist.push(abi)
|
||||
}
|
||||
None => return Err(format!("Unknown ABI \"{}\" in target specification", name))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(base)
|
||||
}
|
||||
|
||||
@ -707,6 +733,12 @@ impl ToJson for Target {
|
||||
target_option_val!(max_atomic_width);
|
||||
target_option_val!(panic_strategy);
|
||||
|
||||
if default.abi_blacklist != self.options.abi_blacklist {
|
||||
d.insert("abi-blacklist".to_string(), self.options.abi_blacklist.iter()
|
||||
.map(Abi::name).map(|name| name.to_json())
|
||||
.collect::<Vec<_>>().to_json());
|
||||
}
|
||||
|
||||
Json::Object(d)
|
||||
}
|
||||
}
|
||||
|
@ -52,6 +52,7 @@ pub fn opts() -> TargetOptions {
|
||||
// Similarly, one almost always never wants to use relocatable code because of the extra
|
||||
// costs it involves.
|
||||
relocation_model: "static".to_string(),
|
||||
abi_blacklist: super::arm_base::abi_blacklist(),
|
||||
.. Default::default()
|
||||
}
|
||||
}
|
||||
|
@ -531,13 +531,16 @@ pub fn check_drop_impls(ccx: &CrateCtxt) -> CompileResult {
|
||||
fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
decl: &'tcx hir::FnDecl,
|
||||
body: &'tcx hir::Block,
|
||||
fn_id: ast::NodeId) {
|
||||
fn_id: ast::NodeId,
|
||||
span: Span) {
|
||||
let raw_fty = ccx.tcx.lookup_item_type(ccx.tcx.map.local_def_id(fn_id)).ty;
|
||||
let fn_ty = match raw_fty.sty {
|
||||
ty::TyFnDef(.., f) => f,
|
||||
_ => span_bug!(body.span, "check_bare_fn: function type expected")
|
||||
};
|
||||
|
||||
check_abi(ccx, span, fn_ty.abi);
|
||||
|
||||
ccx.inherited(fn_id).enter(|inh| {
|
||||
// Compute the fty from point of view of inside fn.
|
||||
let fn_scope = inh.tcx.region_maps.call_site_extent(fn_id, body.id);
|
||||
@ -561,6 +564,13 @@ fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
|
||||
});
|
||||
}
|
||||
|
||||
fn check_abi<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, span: Span, abi: Abi) {
|
||||
if !ccx.tcx.sess.target.target.is_abi_supported(abi) {
|
||||
struct_span_err!(ccx.tcx.sess, span, E0570,
|
||||
"The ABI `{}` is not supported for the current target", abi).emit()
|
||||
}
|
||||
}
|
||||
|
||||
struct GatherLocalsVisitor<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
||||
fcx: &'a FnCtxt<'a, 'gcx, 'tcx>
|
||||
}
|
||||
@ -767,6 +777,8 @@ pub fn check_item_type<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) {
|
||||
check_bounds_are_used(ccx, generics, pty_ty);
|
||||
}
|
||||
hir::ItemForeignMod(ref m) => {
|
||||
check_abi(ccx, it.span, m.abi);
|
||||
|
||||
if m.abi == Abi::RustIntrinsic {
|
||||
for item in &m.items {
|
||||
intrinsic::check_intrinsic_type(ccx, item);
|
||||
@ -804,7 +816,7 @@ pub fn check_item_body<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) {
|
||||
let _indenter = indenter();
|
||||
match it.node {
|
||||
hir::ItemFn(ref decl, .., ref body) => {
|
||||
check_bare_fn(ccx, &decl, &body, it.id);
|
||||
check_bare_fn(ccx, &decl, &body, it.id, it.span);
|
||||
}
|
||||
hir::ItemImpl(.., ref impl_items) => {
|
||||
debug!("ItemImpl {} with id {}", it.name, it.id);
|
||||
@ -815,7 +827,7 @@ pub fn check_item_body<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) {
|
||||
check_const(ccx, &expr, impl_item.id)
|
||||
}
|
||||
hir::ImplItemKind::Method(ref sig, ref body) => {
|
||||
check_bare_fn(ccx, &sig.decl, body, impl_item.id);
|
||||
check_bare_fn(ccx, &sig.decl, body, impl_item.id, impl_item.span);
|
||||
}
|
||||
hir::ImplItemKind::Type(_) => {
|
||||
// Nothing to do here.
|
||||
@ -830,7 +842,7 @@ pub fn check_item_body<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) {
|
||||
check_const(ccx, &expr, trait_item.id)
|
||||
}
|
||||
hir::MethodTraitItem(ref sig, Some(ref body)) => {
|
||||
check_bare_fn(ccx, &sig.decl, body, trait_item.id);
|
||||
check_bare_fn(ccx, &sig.decl, body, trait_item.id, trait_item.span);
|
||||
}
|
||||
hir::MethodTraitItem(_, None) |
|
||||
hir::ConstTraitItem(_, None) |
|
||||
|
@ -4156,6 +4156,16 @@ let s = Simba { mother: 1, father: 0 }; // ok!
|
||||
```
|
||||
"##,
|
||||
|
||||
E0570: r##"
|
||||
The requested ABI is unsupported by the current target.
|
||||
|
||||
The rust compiler maintains for each target a blacklist of ABIs unsupported on
|
||||
that target. If an ABI is present in such a list this usually means that the
|
||||
target / ABI combination is currently unsupported by llvm.
|
||||
|
||||
If necessary, you can circumvent this check using custom target specifications.
|
||||
"##,
|
||||
|
||||
}
|
||||
|
||||
register_diagnostics! {
|
||||
|
@ -33,7 +33,7 @@ pub enum Abi {
|
||||
// NB: This ordering MUST match the AbiDatas array below.
|
||||
// (This is ensured by the test indices_are_correct().)
|
||||
|
||||
// Single platform ABIs come first (`for_arch()` relies on this)
|
||||
// Single platform ABIs
|
||||
Cdecl,
|
||||
Stdcall,
|
||||
Fastcall,
|
||||
@ -42,7 +42,7 @@ pub enum Abi {
|
||||
Win64,
|
||||
SysV64,
|
||||
|
||||
// Multiplatform ABIs second
|
||||
// Multiplatform / generic ABIs
|
||||
Rust,
|
||||
C,
|
||||
System,
|
||||
@ -65,41 +65,31 @@ pub enum Architecture {
|
||||
pub struct AbiData {
|
||||
abi: Abi,
|
||||
|
||||
// Name of this ABI as we like it called.
|
||||
/// Name of this ABI as we like it called.
|
||||
name: &'static str,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum AbiArchitecture {
|
||||
/// Not a real ABI (e.g., intrinsic)
|
||||
Rust,
|
||||
/// An ABI that specifies cross-platform defaults (e.g., "C")
|
||||
All,
|
||||
/// Multiple architectures (bitset)
|
||||
Archs(u32)
|
||||
/// A generic ABI is supported on all platforms.
|
||||
generic: bool,
|
||||
}
|
||||
|
||||
#[allow(non_upper_case_globals)]
|
||||
const AbiDatas: &'static [AbiData] = &[
|
||||
// Platform-specific ABIs
|
||||
AbiData {abi: Abi::Cdecl, name: "cdecl" },
|
||||
AbiData {abi: Abi::Stdcall, name: "stdcall" },
|
||||
AbiData {abi: Abi::Fastcall, name: "fastcall" },
|
||||
AbiData {abi: Abi::Vectorcall, name: "vectorcall"},
|
||||
AbiData {abi: Abi::Aapcs, name: "aapcs" },
|
||||
AbiData {abi: Abi::Win64, name: "win64" },
|
||||
AbiData {abi: Abi::SysV64, name: "sysv64" },
|
||||
AbiData {abi: Abi::Cdecl, name: "cdecl", generic: false },
|
||||
AbiData {abi: Abi::Stdcall, name: "stdcall", generic: false },
|
||||
AbiData {abi: Abi::Fastcall, name: "fastcall", generic: false },
|
||||
AbiData {abi: Abi::Vectorcall, name: "vectorcall", generic: false},
|
||||
AbiData {abi: Abi::Aapcs, name: "aapcs", generic: false },
|
||||
AbiData {abi: Abi::Win64, name: "win64", generic: false },
|
||||
AbiData {abi: Abi::SysV64, name: "sysv64", generic: false },
|
||||
|
||||
// Cross-platform ABIs
|
||||
//
|
||||
// NB: Do not adjust this ordering without
|
||||
// adjusting the indices below.
|
||||
AbiData {abi: Abi::Rust, name: "Rust" },
|
||||
AbiData {abi: Abi::C, name: "C" },
|
||||
AbiData {abi: Abi::System, name: "system" },
|
||||
AbiData {abi: Abi::RustIntrinsic, name: "rust-intrinsic" },
|
||||
AbiData {abi: Abi::RustCall, name: "rust-call" },
|
||||
AbiData {abi: Abi::PlatformIntrinsic, name: "platform-intrinsic" }
|
||||
AbiData {abi: Abi::Rust, name: "Rust", generic: true },
|
||||
AbiData {abi: Abi::C, name: "C", generic: true },
|
||||
AbiData {abi: Abi::System, name: "system", generic: true },
|
||||
AbiData {abi: Abi::RustIntrinsic, name: "rust-intrinsic", generic: true },
|
||||
AbiData {abi: Abi::RustCall, name: "rust-call", generic: true },
|
||||
AbiData {abi: Abi::PlatformIntrinsic, name: "platform-intrinsic", generic: true },
|
||||
];
|
||||
|
||||
/// Returns the ABI with the given name (if any).
|
||||
@ -125,6 +115,10 @@ impl Abi {
|
||||
pub fn name(&self) -> &'static str {
|
||||
self.data().name
|
||||
}
|
||||
|
||||
pub fn generic(&self) -> bool {
|
||||
self.data().generic
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Abi {
|
||||
|
Loading…
x
Reference in New Issue
Block a user