diff --git a/src/doc/unstable-book/src/SUMMARY.md b/src/doc/unstable-book/src/SUMMARY.md index 456a683dc33c8..754ceadbccd56 100644 --- a/src/doc/unstable-book/src/SUMMARY.md +++ b/src/doc/unstable-book/src/SUMMARY.md @@ -7,6 +7,7 @@ - [abi_msp430_interrupt](language-features/abi-msp430-interrupt.md) - [abi_ptx](language-features/abi-ptx.md) - [abi_sysv64](language-features/abi-sysv64.md) + - [abi_thiscall](language-features/abi-thiscall.md) - [abi_unadjusted](language-features/abi-unadjusted.md) - [abi_vectorcall](language-features/abi-vectorcall.md) - [abi_x86_interrupt](language-features/abi-x86-interrupt.md) diff --git a/src/doc/unstable-book/src/language-features/abi-thiscall.md b/src/doc/unstable-book/src/language-features/abi-thiscall.md new file mode 100644 index 0000000000000..73bc6eacf42ce --- /dev/null +++ b/src/doc/unstable-book/src/language-features/abi-thiscall.md @@ -0,0 +1,12 @@ +# `abi_thiscall` + +The tracking issue for this feature is: [#42202] + +[#42202]: https://github.com/rust-lang/rust/issues/42202 + +------------------------ + +The MSVC ABI on x86 Windows uses the `thiscall` calling convention for C++ +instance methods by default; it is identical to the usual (C) calling +convention on x86 Windows except that the first parameter of the method, +the `this` pointer, is passed in the ECX register. diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs index 7138db01339f6..d0bdf266332de 100644 --- a/src/librustc/ich/impls_syntax.rs +++ b/src/librustc/ich/impls_syntax.rs @@ -63,6 +63,7 @@ impl_stable_hash_for!(enum ::syntax::abi::Abi { Stdcall, Fastcall, Vectorcall, + Thiscall, Aapcs, Win64, SysV64, diff --git a/src/librustc_back/target/arm_base.rs b/src/librustc_back/target/arm_base.rs index ad132c27cb841..416e5a0e13a88 100644 --- a/src/librustc_back/target/arm_base.rs +++ b/src/librustc_back/target/arm_base.rs @@ -12,5 +12,5 @@ use syntax::abi::Abi; // All the calling conventions trigger an assertion(Unsupported calling convention) in llvm on arm pub fn abi_blacklist() -> Vec { - vec![Abi::Stdcall, Abi::Fastcall, Abi::Vectorcall, Abi::Win64, Abi::SysV64] + vec![Abi::Stdcall, Abi::Fastcall, Abi::Vectorcall, Abi::Thiscall, Abi::Win64, Abi::SysV64] } diff --git a/src/librustc_llvm/ffi.rs b/src/librustc_llvm/ffi.rs index 5cb5a62c93b35..d7b575d90a68b 100644 --- a/src/librustc_llvm/ffi.rs +++ b/src/librustc_llvm/ffi.rs @@ -49,6 +49,7 @@ pub enum CallConv { X86FastcallCallConv = 65, ArmAapcsCallConv = 67, Msp430Intr = 69, + X86_ThisCall = 70, PtxKernel = 71, X86_64_SysV = 78, X86_64_Win64 = 79, diff --git a/src/librustc_trans/abi.rs b/src/librustc_trans/abi.rs index a6b0eb473eb8e..9b94a3b2f234b 100644 --- a/src/librustc_trans/abi.rs +++ b/src/librustc_trans/abi.rs @@ -642,6 +642,7 @@ impl<'a, 'tcx> FnType<'tcx> { Stdcall => llvm::X86StdcallCallConv, Fastcall => llvm::X86FastcallCallConv, Vectorcall => llvm::X86_VectorCall, + Thiscall => llvm::X86_ThisCall, C => llvm::CCallConv, Unadjusted => llvm::CCallConv, Win64 => llvm::X86_64_Win64, diff --git a/src/libsyntax/abi.rs b/src/libsyntax/abi.rs index 30641515a41dd..ed2eb20990695 100644 --- a/src/libsyntax/abi.rs +++ b/src/libsyntax/abi.rs @@ -20,6 +20,7 @@ pub enum Abi { Stdcall, Fastcall, Vectorcall, + Thiscall, Aapcs, Win64, SysV64, @@ -55,6 +56,7 @@ const AbiDatas: &'static [AbiData] = &[ 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::Thiscall, name: "thiscall", 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 }, diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index e1b7d4681ad16..f9fe072ef878a 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -352,6 +352,9 @@ declare_features! ( // Allows use of the :vis macro fragment specifier (active, macro_vis_matcher, "1.18.0", Some(41022)), + + // rustc internal + (active, abi_thiscall, "1.19.0", None), ); declare_features! ( @@ -1051,6 +1054,10 @@ impl<'a> PostExpansionVisitor<'a> { gate_feature_post!(&self, abi_vectorcall, span, "vectorcall is experimental and subject to change"); }, + Abi::Thiscall => { + gate_feature_post!(&self, abi_thiscall, span, + "thiscall is experimental and subject to change"); + }, Abi::RustCall => { gate_feature_post!(&self, unboxed_closures, span, "rust-call ABI is subject to change"); diff --git a/src/test/compile-fail/feature-gate-abi.rs b/src/test/compile-fail/feature-gate-abi.rs index b77c9fab7169f..45c715f51fe48 100644 --- a/src/test/compile-fail/feature-gate-abi.rs +++ b/src/test/compile-fail/feature-gate-abi.rs @@ -11,6 +11,7 @@ // gate-test-intrinsics // gate-test-platform_intrinsics // gate-test-abi_vectorcall +// gate-test-abi_thiscall // gate-test-abi_ptx // gate-test-abi_x86_interrupt @@ -22,6 +23,7 @@ extern "rust-call" fn f4() {} //~ ERROR rust-call ABI is subject to change extern "msp430-interrupt" fn f5() {} //~ ERROR msp430-interrupt ABI is experimental extern "ptx-kernel" fn f6() {} //~ ERROR PTX ABIs are experimental and subject to change extern "x86-interrupt" fn f7() {} //~ ERROR x86-interrupt ABI is experimental +extern "thiscall" fn f8() {} //~ ERROR thiscall is experimental and subject to change // Methods in trait definition trait Tr { @@ -32,6 +34,7 @@ trait Tr { extern "msp430-interrupt" fn m5(); //~ ERROR msp430-interrupt ABI is experimental extern "ptx-kernel" fn m6(); //~ ERROR PTX ABIs are experimental and subject to change extern "x86-interrupt" fn m7(); //~ ERROR x86-interrupt ABI is experimental + extern "thiscall" fn m8(); //~ ERROR thiscall is experimental and subject to change extern "rust-intrinsic" fn dm1() {} //~ ERROR intrinsics are subject to change extern "platform-intrinsic" fn dm2() {} //~ ERROR platform intrinsics are experimental @@ -40,6 +43,7 @@ trait Tr { extern "msp430-interrupt" fn dm5() {} //~ ERROR msp430-interrupt ABI is experimental extern "ptx-kernel" fn dm6() {} //~ ERROR PTX ABIs are experimental and subject to change extern "x86-interrupt" fn dm7() {} //~ ERROR x86-interrupt ABI is experimental + extern "thiscall" fn dm8() {} //~ ERROR thiscall is experimental and subject to change } struct S; @@ -53,6 +57,7 @@ impl Tr for S { extern "msp430-interrupt" fn m5() {} //~ ERROR msp430-interrupt ABI is experimental extern "ptx-kernel" fn m6() {} //~ ERROR PTX ABIs are experimental and subject to change extern "x86-interrupt" fn m7() {} //~ ERROR x86-interrupt ABI is experimental + extern "thiscall" fn m8() {} //~ ERROR thiscall is experimental and subject to change } // Methods in inherent impl @@ -64,6 +69,7 @@ impl S { extern "msp430-interrupt" fn im5() {} //~ ERROR msp430-interrupt ABI is experimental extern "ptx-kernel" fn im6() {} //~ ERROR PTX ABIs are experimental and subject to change extern "x86-interrupt" fn im7() {} //~ ERROR x86-interrupt ABI is experimental + extern "thiscall" fn im8() {} //~ ERROR thiscall is experimental and subject to change } // Function pointer types @@ -74,6 +80,7 @@ type A4 = extern "rust-call" fn(); //~ ERROR rust-call ABI is subject to change type A5 = extern "msp430-interrupt" fn(); //~ ERROR msp430-interrupt ABI is experimental type A6 = extern "ptx-kernel" fn (); //~ ERROR PTX ABIs are experimental and subject to change type A7 = extern "x86-interrupt" fn(); //~ ERROR x86-interrupt ABI is experimental +type A8 = extern "thiscall" fn(); //~ ERROR thiscall is experimental and subject to change // Foreign modules extern "rust-intrinsic" {} //~ ERROR intrinsics are subject to change @@ -83,5 +90,6 @@ extern "rust-call" {} //~ ERROR rust-call ABI is subject to change extern "msp430-interrupt" {} //~ ERROR msp430-interrupt ABI is experimental extern "ptx-kernel" {} //~ ERROR PTX ABIs are experimental and subject to change extern "x86-interrupt" {} //~ ERROR x86-interrupt ABI is experimental +extern "thiscall" {} //~ ERROR thiscall is experimental and subject to change fn main() {} diff --git a/src/test/run-pass/extern-thiscall.rs b/src/test/run-pass/extern-thiscall.rs new file mode 100644 index 0000000000000..a669f29d098a0 --- /dev/null +++ b/src/test/run-pass/extern-thiscall.rs @@ -0,0 +1,35 @@ +// 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. + +// ignore-arm +// ignore-aarch64 + +#![feature(abi_thiscall)] + +trait A { + extern "thiscall" fn test1(i: i32); +} + +struct S; + +impl A for S { + extern "thiscall" fn test1(i: i32) { + assert_eq!(i, 1); + } +} + +extern "thiscall" fn test2(i: i32) { + assert_eq!(i, 2); +} + +fn main() { + ::test1(1); + test2(2); +} diff --git a/src/test/ui/codemap_tests/unicode.stderr b/src/test/ui/codemap_tests/unicode.stderr index eef8793511529..0828fd28b5878 100644 --- a/src/test/ui/codemap_tests/unicode.stderr +++ b/src/test/ui/codemap_tests/unicode.stderr @@ -1,4 +1,4 @@ -error: invalid ABI: expected one of [cdecl, stdcall, fastcall, vectorcall, aapcs, win64, sysv64, ptx-kernel, msp430-interrupt, x86-interrupt, Rust, C, system, rust-intrinsic, rust-call, platform-intrinsic, unadjusted], found `路濫狼á́́` +error: invalid ABI: expected one of [cdecl, stdcall, fastcall, vectorcall, thiscall, aapcs, win64, sysv64, ptx-kernel, msp430-interrupt, x86-interrupt, Rust, C, system, rust-intrinsic, rust-call, platform-intrinsic, unadjusted], found `路濫狼á́́` --> $DIR/unicode.rs:11:8 | 11 | extern "路濫狼á́́" fn foo() {}