Skip to content

Commit

Permalink
check target abi support
Browse files Browse the repository at this point in the history
  • Loading branch information
TimNN committed Oct 24, 2016
1 parent ac468b6 commit 9eb0fd9
Show file tree
Hide file tree
Showing 19 changed files with 139 additions and 47 deletions.
1 change: 1 addition & 0 deletions src/librustc_back/target/aarch64_apple_ios.rs
Expand Up @@ -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
},
})
Expand Down
7 changes: 5 additions & 2 deletions src/librustc_back/target/aarch64_linux_android.rs
Expand Up @@ -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();
Expand All @@ -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
},
})
}
7 changes: 5 additions & 2 deletions src/librustc_back/target/aarch64_unknown_linux_gnu.rs
Expand Up @@ -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();
Expand All @@ -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 changes: 16 additions & 0 deletions src/librustc_back/target/arm_base.rs
@@ -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]
}
7 changes: 5 additions & 2 deletions src/librustc_back/target/arm_linux_androideabi.rs
Expand Up @@ -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();
Expand All @@ -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
},
})
}
1 change: 1 addition & 0 deletions src/librustc_back/target/arm_unknown_linux_gnueabi.rs
Expand Up @@ -25,6 +25,7 @@ pub fn target() -> TargetResult {

options: TargetOptions {
features: "+v6".to_string(),
abi_blacklist: super::arm_base::abi_blacklist(),
.. base
},
})
Expand Down
1 change: 1 addition & 0 deletions src/librustc_back/target/arm_unknown_linux_gnueabihf.rs
Expand Up @@ -25,6 +25,7 @@ pub fn target() -> TargetResult {

options: TargetOptions {
features: "+v6,+vfp2".to_string(),
abi_blacklist: super::arm_base::abi_blacklist(),
.. base
}
})
Expand Down
7 changes: 5 additions & 2 deletions src/librustc_back/target/arm_unknown_linux_musleabi.rs
Expand Up @@ -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();
Expand All @@ -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
},
})
}
7 changes: 5 additions & 2 deletions src/librustc_back/target/arm_unknown_linux_musleabihf.rs
Expand Up @@ -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();
Expand All @@ -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
},
})
}
1 change: 1 addition & 0 deletions src/librustc_back/target/armv7_apple_ios.rs
Expand Up @@ -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
}
})
Expand Down
7 changes: 5 additions & 2 deletions src/librustc_back/target/armv7_linux_androideabi.rs
Expand Up @@ -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();
Expand All @@ -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
},
})
}
1 change: 1 addition & 0 deletions src/librustc_back/target/armv7_unknown_linux_gnueabihf.rs
Expand Up @@ -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
}
})
Expand Down
7 changes: 5 additions & 2 deletions src/librustc_back/target/armv7_unknown_linux_musleabihf.rs
Expand Up @@ -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();
Expand All @@ -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
},
})
}
1 change: 1 addition & 0 deletions src/librustc_back/target/armv7s_apple_ios.rs
Expand Up @@ -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
}
})
Expand Down
34 changes: 33 additions & 1 deletion src/librustc_back/target/mod.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -408,6 +413,7 @@ impl Default for TargetOptions {
obj_is_bitcode: false,
max_atomic_width: None,
panic_strategy: PanicStrategy::Unwind,
abi_blacklist: vec![],
}
}
}
Expand All @@ -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
Expand Down Expand Up @@ -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)
}

Expand Down Expand Up @@ -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)
}
}
Expand Down
1 change: 1 addition & 0 deletions src/librustc_back/target/thumb_base.rs
Expand Up @@ -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()
}
}
20 changes: 16 additions & 4 deletions src/librustc_typeck/check/mod.rs
Expand Up @@ -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);
Expand All @@ -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>
}
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand All @@ -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.
Expand All @@ -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) |
Expand Down
10 changes: 10 additions & 0 deletions src/librustc_typeck/diagnostics.rs
Expand Up @@ -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! {
Expand Down

0 comments on commit 9eb0fd9

Please sign in to comment.