diff --git a/src/doc/book/ffi.md b/src/doc/book/ffi.md index c3896e4e9c557..c00e6c0a07012 100644 --- a/src/doc/book/ffi.md +++ b/src/doc/book/ffi.md @@ -478,6 +478,8 @@ are: * `aapcs` * `cdecl` * `fastcall` +* `vectorcall` +This is currently hidden behind the `abi_vectorcall` gate and is subject to change. * `Rust` * `rust-intrinsic` * `system` diff --git a/src/doc/reference.md b/src/doc/reference.md index e7cc1436824e4..1daf42d293dc8 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -2390,6 +2390,9 @@ The currently implemented features of the reference compiler are: * - `type_ascription` - Allows type ascription expressions `expr: Type`. +* - `abi_vectorcall` - Allows the usage of the vectorcall calling convention + (e.g. `extern "vectorcall" func fn_();`) + If a feature is promoted to a language feature, then all existing programs will start to receive compilation warnings about `#![feature]` directives which enabled the new feature (because the directive is no longer necessary). However, if a diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index e2217e367a08e..fc7fa299fb8fa 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -85,6 +85,7 @@ pub enum CallConv { X86StdcallCallConv = 64, X86FastcallCallConv = 65, X86_64_Win64 = 79, + X86_VectorCall = 80 } #[derive(Copy, Clone)] diff --git a/src/librustc_trans/trans/foreign.rs b/src/librustc_trans/trans/foreign.rs index 9012ecaa2134f..6d264fc7813e6 100644 --- a/src/librustc_trans/trans/foreign.rs +++ b/src/librustc_trans/trans/foreign.rs @@ -35,7 +35,8 @@ use std::cmp; use std::iter::once; use libc::c_uint; use syntax::abi::{Cdecl, Aapcs, C, Win64, Abi}; -use syntax::abi::{PlatformIntrinsic, RustIntrinsic, Rust, RustCall, Stdcall, Fastcall, System}; +use syntax::abi::{PlatformIntrinsic, RustIntrinsic, Rust, RustCall, Stdcall}; +use syntax::abi::{Fastcall, Vectorcall, System}; use syntax::attr; use syntax::codemap::Span; use syntax::parse::token::{InternedString, special_idents}; @@ -104,6 +105,7 @@ pub fn llvm_calling_convention(ccx: &CrateContext, Stdcall => llvm::X86StdcallCallConv, Fastcall => llvm::X86FastcallCallConv, + Vectorcall => llvm::X86_VectorCall, C => llvm::CCallConv, Win64 => llvm::X86_64_Win64, diff --git a/src/libsyntax/abi.rs b/src/libsyntax/abi.rs index ca44dec627e37..a16f232f4a1c1 100644 --- a/src/libsyntax/abi.rs +++ b/src/libsyntax/abi.rs @@ -39,6 +39,7 @@ pub enum Abi { Cdecl, Stdcall, Fastcall, + Vectorcall, Aapcs, Win64, @@ -85,6 +86,7 @@ const AbiDatas: &'static [AbiData] = &[ AbiData {abi: Cdecl, name: "cdecl" }, AbiData {abi: Stdcall, name: "stdcall" }, AbiData {abi: Fastcall, name: "fastcall" }, + AbiData {abi: Vectorcall, name: "vectorcall"}, AbiData {abi: Aapcs, name: "aapcs" }, AbiData {abi: Win64, name: "win64" }, diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 4ea0fd76fea4a..c168ea9ad75da 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -239,6 +239,9 @@ const KNOWN_FEATURES: &'static [(&'static str, &'static str, Option, Status // Allows cfg(target_thread_local) ("cfg_target_thread_local", "1.7.0", Some(29594), Active), + + // rustc internal + ("abi_vectorcall", "1.7.0", None, Active) ]; // (changing above list without updating src/doc/reference.md makes @cmr sad) @@ -862,6 +865,11 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { Abi::PlatformIntrinsic => { Some(("platform_intrinsics", "platform intrinsics are experimental and possibly buggy")) + }, + Abi::Vectorcall => { + Some(("abi_vectorcall", + "vectorcall is experimental and subject to change" + )) } _ => None }; @@ -1033,11 +1041,17 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> { "intrinsics are subject to change") } FnKind::ItemFn(_, _, _, _, abi, _) | - FnKind::Method(_, &ast::MethodSig { abi, .. }, _) if abi == Abi::RustCall => { - self.gate_feature("unboxed_closures", - span, - "rust-call ABI is subject to change") - } + FnKind::Method(_, &ast::MethodSig { abi, .. }, _) => match abi { + Abi::RustCall => { + self.gate_feature("unboxed_closures", span, + "rust-call ABI is subject to change"); + }, + Abi::Vectorcall => { + self.gate_feature("abi_vectorcall", span, + "vectorcall is experimental and subject to change"); + }, + _ => {} + }, _ => {} } visit::walk_fn(self, fn_kind, fn_decl, block, span); diff --git a/src/test/compile-fail/feature-gate-abi-vectorcall.rs b/src/test/compile-fail/feature-gate-abi-vectorcall.rs new file mode 100644 index 0000000000000..79f3c8dc77625 --- /dev/null +++ b/src/test/compile-fail/feature-gate-abi-vectorcall.rs @@ -0,0 +1,19 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +extern "vectorcall" { //~ ERROR vectorcall is experimental and subject to change + fn bar(); +} + +extern "vectorcall" fn baz() { //~ ERROR vectorcall is experimental and subject to change +} + +fn main() { +} diff --git a/src/test/run-pass/extern-vectorcall.rs b/src/test/run-pass/extern-vectorcall.rs new file mode 100644 index 0000000000000..e8a9f92a93d4a --- /dev/null +++ b/src/test/run-pass/extern-vectorcall.rs @@ -0,0 +1,32 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(abi_vectorcall)] + +trait A { + extern "vectorcall" fn test1(i: i32); +} + +struct S; + +impl A for S { + extern "vectorcall" fn test1(i: i32) { + assert_eq!(i, 1); + } +} + +extern "vectorcall" fn test2(i: i32) { + assert_eq!(i, 2); +} + +fn main() { + ::test1(1); + test2(2); +}