Skip to content

Commit 586a988

Browse files
authored
Auto merge of #36421 - TimNN:check-abis, r=alexcrichton
check target abi support This PR checks for each extern function / block whether the ABI / calling convention used is supported by the current target. This was achieved by adding an `abi_blacklist` field to the target specifications, listing the calling conventions unsupported for that target.
2 parents a7557e7 + 1422ac9 commit 586a988

25 files changed

+153
-49
lines changed

src/librustc_back/target/aarch64_apple_ios.rs

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ pub fn target() -> TargetResult {
2626
features: "+neon,+fp-armv8,+cyclone".to_string(),
2727
eliminate_frame_pointer: false,
2828
max_atomic_width: Some(128),
29+
abi_blacklist: super::arm_base::abi_blacklist(),
2930
.. base
3031
},
3132
})

src/librustc_back/target/aarch64_linux_android.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use target::{Target, TargetResult};
11+
use target::{Target, TargetOptions, TargetResult};
1212

1313
pub fn target() -> TargetResult {
1414
let mut base = super::android_base::opts();
@@ -25,6 +25,9 @@ pub fn target() -> TargetResult {
2525
target_os: "android".to_string(),
2626
target_env: "".to_string(),
2727
target_vendor: "unknown".to_string(),
28-
options: base,
28+
options: TargetOptions {
29+
abi_blacklist: super::arm_base::abi_blacklist(),
30+
.. base
31+
},
2932
})
3033
}

src/librustc_back/target/aarch64_unknown_linux_gnu.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use target::{Target, TargetResult};
11+
use target::{Target, TargetOptions, TargetResult};
1212

1313
pub fn target() -> TargetResult {
1414
let mut base = super::linux_base::opts();
@@ -22,6 +22,9 @@ pub fn target() -> TargetResult {
2222
arch: "aarch64".to_string(),
2323
target_os: "linux".to_string(),
2424
target_vendor: "unknown".to_string(),
25-
options: base,
25+
options: TargetOptions {
26+
abi_blacklist: super::arm_base::abi_blacklist(),
27+
.. base
28+
},
2629
})
2730
}

src/librustc_back/target/arm_base.rs

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
use syntax::abi::Abi;
12+
13+
// All the calling conventions trigger an assertion(Unsupported calling convention) in llvm on arm
14+
pub fn abi_blacklist() -> Vec<Abi> {
15+
vec![Abi::Stdcall, Abi::Fastcall, Abi::Vectorcall, Abi::Win64, Abi::SysV64]
16+
}

src/librustc_back/target/arm_linux_androideabi.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use target::{Target, TargetResult};
11+
use target::{Target, TargetOptions, TargetResult};
1212

1313
pub fn target() -> TargetResult {
1414
let mut base = super::android_base::opts();
@@ -24,6 +24,9 @@ pub fn target() -> TargetResult {
2424
target_os: "android".to_string(),
2525
target_env: "".to_string(),
2626
target_vendor: "unknown".to_string(),
27-
options: base,
27+
options: TargetOptions {
28+
abi_blacklist: super::arm_base::abi_blacklist(),
29+
.. base
30+
},
2831
})
2932
}

src/librustc_back/target/arm_unknown_linux_gnueabi.rs

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ pub fn target() -> TargetResult {
2525

2626
options: TargetOptions {
2727
features: "+v6".to_string(),
28+
abi_blacklist: super::arm_base::abi_blacklist(),
2829
.. base
2930
},
3031
})

src/librustc_back/target/arm_unknown_linux_gnueabihf.rs

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ pub fn target() -> TargetResult {
2525

2626
options: TargetOptions {
2727
features: "+v6,+vfp2".to_string(),
28+
abi_blacklist: super::arm_base::abi_blacklist(),
2829
.. base
2930
}
3031
})

src/librustc_back/target/arm_unknown_linux_musleabi.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use target::{Target, TargetResult};
11+
use target::{Target, TargetOptions, TargetResult};
1212

1313
pub fn target() -> TargetResult {
1414
let mut base = super::linux_musl_base::opts();
@@ -29,6 +29,9 @@ pub fn target() -> TargetResult {
2929
target_os: "linux".to_string(),
3030
target_env: "musl".to_string(),
3131
target_vendor: "unknown".to_string(),
32-
options: base,
32+
options: TargetOptions {
33+
abi_blacklist: super::arm_base::abi_blacklist(),
34+
.. base
35+
},
3336
})
3437
}

src/librustc_back/target/arm_unknown_linux_musleabihf.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use target::{Target, TargetResult};
11+
use target::{Target, TargetOptions, TargetResult};
1212

1313
pub fn target() -> TargetResult {
1414
let mut base = super::linux_musl_base::opts();
@@ -29,6 +29,9 @@ pub fn target() -> TargetResult {
2929
target_os: "linux".to_string(),
3030
target_env: "musl".to_string(),
3131
target_vendor: "unknown".to_string(),
32-
options: base,
32+
options: TargetOptions {
33+
abi_blacklist: super::arm_base::abi_blacklist(),
34+
.. base
35+
},
3336
})
3437
}

src/librustc_back/target/armv7_apple_ios.rs

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ pub fn target() -> TargetResult {
2525
options: TargetOptions {
2626
features: "+v7,+vfp3,+neon".to_string(),
2727
max_atomic_width: Some(64),
28+
abi_blacklist: super::arm_base::abi_blacklist(),
2829
.. base
2930
}
3031
})

src/librustc_back/target/armv7_linux_androideabi.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use target::{Target, TargetResult};
11+
use target::{Target, TargetOptions, TargetResult};
1212

1313
pub fn target() -> TargetResult {
1414
let mut base = super::android_base::opts();
@@ -24,6 +24,9 @@ pub fn target() -> TargetResult {
2424
target_os: "android".to_string(),
2525
target_env: "".to_string(),
2626
target_vendor: "unknown".to_string(),
27-
options: base,
27+
options: TargetOptions {
28+
abi_blacklist: super::arm_base::abi_blacklist(),
29+
.. base
30+
},
2831
})
2932
}

src/librustc_back/target/armv7_unknown_linux_gnueabihf.rs

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ pub fn target() -> TargetResult {
2727
features: "+v7,+vfp3,+d16,+thumb2,-neon".to_string(),
2828
cpu: "generic".to_string(),
2929
max_atomic_width: Some(64),
30+
abi_blacklist: super::arm_base::abi_blacklist(),
3031
.. base
3132
}
3233
})

src/librustc_back/target/armv7_unknown_linux_musleabihf.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use target::{Target, TargetResult};
11+
use target::{Target, TargetOptions, TargetResult};
1212

1313
pub fn target() -> TargetResult {
1414
let mut base = super::linux_musl_base::opts();
@@ -30,6 +30,9 @@ pub fn target() -> TargetResult {
3030
target_os: "linux".to_string(),
3131
target_env: "musl".to_string(),
3232
target_vendor: "unknown".to_string(),
33-
options: base,
33+
options: TargetOptions {
34+
abi_blacklist: super::arm_base::abi_blacklist(),
35+
.. base
36+
},
3437
})
3538
}

src/librustc_back/target/armv7s_apple_ios.rs

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ pub fn target() -> TargetResult {
2525
options: TargetOptions {
2626
features: "+v7,+vfp4,+neon".to_string(),
2727
max_atomic_width: Some(64),
28+
abi_blacklist: super::arm_base::abi_blacklist(),
2829
.. base
2930
}
3031
})

src/librustc_back/target/mod.rs

+33-1
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,14 @@ use serialize::json::{Json, ToJson};
4848
use std::collections::BTreeMap;
4949
use std::default::Default;
5050
use std::io::prelude::*;
51-
use syntax::abi::Abi;
51+
use syntax::abi::{Abi, lookup as lookup_abi};
5252

5353
use PanicStrategy;
5454

5555
mod android_base;
5656
mod apple_base;
5757
mod apple_ios_base;
58+
mod arm_base;
5859
mod bitrig_base;
5960
mod dragonfly_base;
6061
mod freebsd_base;
@@ -361,6 +362,10 @@ pub struct TargetOptions {
361362

362363
/// Panic strategy: "unwind" or "abort"
363364
pub panic_strategy: PanicStrategy,
365+
366+
/// A blacklist of ABIs unsupported by the current target. Note that generic
367+
/// ABIs are considered to be supported on all platforms and cannot be blacklisted.
368+
pub abi_blacklist: Vec<Abi>,
364369
}
365370

366371
impl Default for TargetOptions {
@@ -411,6 +416,7 @@ impl Default for TargetOptions {
411416
obj_is_bitcode: false,
412417
max_atomic_width: None,
413418
panic_strategy: PanicStrategy::Unwind,
419+
abi_blacklist: vec![],
414420
}
415421
}
416422
}
@@ -436,6 +442,10 @@ impl Target {
436442
self.options.max_atomic_width.unwrap_or(self.target_pointer_width.parse().unwrap())
437443
}
438444

445+
pub fn is_abi_supported(&self, abi: Abi) -> bool {
446+
abi.generic() || !self.options.abi_blacklist.contains(&abi)
447+
}
448+
439449
/// Load a target descriptor from a JSON object.
440450
pub fn from_json(obj: Json) -> TargetResult {
441451
// While ugly, this code must remain this way to retain
@@ -567,6 +577,22 @@ impl Target {
567577
key!(max_atomic_width, Option<u64>);
568578
try!(key!(panic_strategy, PanicStrategy));
569579

580+
if let Some(array) = obj.find("abi-blacklist").and_then(Json::as_array) {
581+
for name in array.iter().filter_map(|abi| abi.as_string()) {
582+
match lookup_abi(name) {
583+
Some(abi) => {
584+
if abi.generic() {
585+
return Err(format!("The ABI \"{}\" is considered to be supported on \
586+
all targets and cannot be blacklisted", abi))
587+
}
588+
589+
base.options.abi_blacklist.push(abi)
590+
}
591+
None => return Err(format!("Unknown ABI \"{}\" in target specification", name))
592+
}
593+
}
594+
}
595+
570596
Ok(base)
571597
}
572598

@@ -710,6 +736,12 @@ impl ToJson for Target {
710736
target_option_val!(max_atomic_width);
711737
target_option_val!(panic_strategy);
712738

739+
if default.abi_blacklist != self.options.abi_blacklist {
740+
d.insert("abi-blacklist".to_string(), self.options.abi_blacklist.iter()
741+
.map(Abi::name).map(|name| name.to_json())
742+
.collect::<Vec<_>>().to_json());
743+
}
744+
713745
Json::Object(d)
714746
}
715747
}

src/librustc_back/target/thumb_base.rs

+1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ pub fn opts() -> TargetOptions {
5252
// Similarly, one almost always never wants to use relocatable code because of the extra
5353
// costs it involves.
5454
relocation_model: "static".to_string(),
55+
abi_blacklist: super::arm_base::abi_blacklist(),
5556
.. Default::default()
5657
}
5758
}

src/librustc_typeck/check/mod.rs

+16-4
Original file line numberDiff line numberDiff line change
@@ -531,13 +531,16 @@ pub fn check_drop_impls(ccx: &CrateCtxt) -> CompileResult {
531531
fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
532532
decl: &'tcx hir::FnDecl,
533533
body: &'tcx hir::Block,
534-
fn_id: ast::NodeId) {
534+
fn_id: ast::NodeId,
535+
span: Span) {
535536
let raw_fty = ccx.tcx.lookup_item_type(ccx.tcx.map.local_def_id(fn_id)).ty;
536537
let fn_ty = match raw_fty.sty {
537538
ty::TyFnDef(.., f) => f,
538539
_ => span_bug!(body.span, "check_bare_fn: function type expected")
539540
};
540541

542+
check_abi(ccx, span, fn_ty.abi);
543+
541544
ccx.inherited(fn_id).enter(|inh| {
542545
// Compute the fty from point of view of inside fn.
543546
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>,
561564
});
562565
}
563566

567+
fn check_abi<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, span: Span, abi: Abi) {
568+
if !ccx.tcx.sess.target.target.is_abi_supported(abi) {
569+
struct_span_err!(ccx.tcx.sess, span, E0570,
570+
"The ABI `{}` is not supported for the current target", abi).emit()
571+
}
572+
}
573+
564574
struct GatherLocalsVisitor<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
565575
fcx: &'a FnCtxt<'a, 'gcx, 'tcx>
566576
}
@@ -767,6 +777,8 @@ pub fn check_item_type<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) {
767777
check_bounds_are_used(ccx, generics, pty_ty);
768778
}
769779
hir::ItemForeignMod(ref m) => {
780+
check_abi(ccx, it.span, m.abi);
781+
770782
if m.abi == Abi::RustIntrinsic {
771783
for item in &m.items {
772784
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) {
804816
let _indenter = indenter();
805817
match it.node {
806818
hir::ItemFn(ref decl, .., ref body) => {
807-
check_bare_fn(ccx, &decl, &body, it.id);
819+
check_bare_fn(ccx, &decl, &body, it.id, it.span);
808820
}
809821
hir::ItemImpl(.., ref impl_items) => {
810822
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) {
815827
check_const(ccx, &expr, impl_item.id)
816828
}
817829
hir::ImplItemKind::Method(ref sig, ref body) => {
818-
check_bare_fn(ccx, &sig.decl, body, impl_item.id);
830+
check_bare_fn(ccx, &sig.decl, body, impl_item.id, impl_item.span);
819831
}
820832
hir::ImplItemKind::Type(_) => {
821833
// Nothing to do here.
@@ -830,7 +842,7 @@ pub fn check_item_body<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) {
830842
check_const(ccx, &expr, trait_item.id)
831843
}
832844
hir::MethodTraitItem(ref sig, Some(ref body)) => {
833-
check_bare_fn(ccx, &sig.decl, body, trait_item.id);
845+
check_bare_fn(ccx, &sig.decl, body, trait_item.id, trait_item.span);
834846
}
835847
hir::MethodTraitItem(_, None) |
836848
hir::ConstTraitItem(_, None) |

src/librustc_typeck/diagnostics.rs

+10
Original file line numberDiff line numberDiff line change
@@ -4156,6 +4156,16 @@ let s = Simba { mother: 1, father: 0 }; // ok!
41564156
```
41574157
"##,
41584158

4159+
E0570: r##"
4160+
The requested ABI is unsupported by the current target.
4161+
4162+
The rust compiler maintains for each target a blacklist of ABIs unsupported on
4163+
that target. If an ABI is present in such a list this usually means that the
4164+
target / ABI combination is currently unsupported by llvm.
4165+
4166+
If necessary, you can circumvent this check using custom target specifications.
4167+
"##,
4168+
41594169
}
41604170

41614171
register_diagnostics! {

0 commit comments

Comments
 (0)