From 9c7dbe82e736a657b298e41cd4640100218b37e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lanteri=20Thauvin?= Date: Thu, 31 Dec 2020 02:22:10 +0100 Subject: [PATCH 01/22] Notify when an `I-prioritize` issue is closed --- triagebot.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/triagebot.toml b/triagebot.toml index c0cf50e516700..66cad406d4839 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -101,6 +101,8 @@ message_on_add = """\ - Needs `I-nominated`? """ message_on_remove = "Issue #{number}'s prioritization request has been removed." +message_on_close = "Issue #{number} has been closed while requested for prioritization." +message_on_reopen = "Issue #{number} has been reopened." [github-releases] format = "rustc" From fc53fff1d313d15b10fc6d5d882f28329007f836 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Thu, 19 Aug 2021 17:06:00 +0200 Subject: [PATCH 02/22] Fix handling of +whole-archive native link modifier. --- compiler/rustc_codegen_ssa/src/back/link.rs | 23 ++++++++++-- compiler/rustc_codegen_ssa/src/lib.rs | 1 + .../Makefile | 37 +++++++++++++++++++ .../c_static_lib_with_constructor.cpp | 11 ++++++ .../directly_linked.rs | 6 +++ .../indirectly_linked.rs | 5 +++ .../indirectly_linked_via_attr.rs | 5 +++ .../native_lib_in_src.rs | 15 ++++++++ .../rlib_with_cmdline_native_lib.rs | 6 +++ 9 files changed, 106 insertions(+), 3 deletions(-) create mode 100644 src/test/run-make/native-link-modifier-whole-archive/Makefile create mode 100644 src/test/run-make/native-link-modifier-whole-archive/c_static_lib_with_constructor.cpp create mode 100644 src/test/run-make/native-link-modifier-whole-archive/directly_linked.rs create mode 100644 src/test/run-make/native-link-modifier-whole-archive/indirectly_linked.rs create mode 100644 src/test/run-make/native-link-modifier-whole-archive/indirectly_linked_via_attr.rs create mode 100644 src/test/run-make/native-link-modifier-whole-archive/native_lib_in_src.rs create mode 100644 src/test/run-make/native-link-modifier-whole-archive/rlib_with_cmdline_native_lib.rs diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index f3eb1e04d07dc..7228ca3b42316 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -36,6 +36,7 @@ use regex::Regex; use tempfile::Builder as TempFileBuilder; use std::ffi::OsString; +use std::lazy::OnceCell; use std::path::{Path, PathBuf}; use std::process::{ExitStatus, Output, Stdio}; use std::{ascii, char, env, fmt, fs, io, mem, str}; @@ -2328,6 +2329,7 @@ fn add_upstream_native_libraries( .find(|(ty, _)| *ty == crate_type) .expect("failed to find crate type in dependency format list"); + let search_path = OnceCell::new(); let crates = &codegen_results.crate_info.used_crates; let mut last = (NativeLibKind::Unspecified, None); for &cnum in crates { @@ -2352,19 +2354,34 @@ fn add_upstream_native_libraries( NativeLibKind::Framework { as_needed } => { cmd.link_framework(name, as_needed.unwrap_or(true)) } - NativeLibKind::Static { bundle: Some(false), .. } => { + NativeLibKind::Static { bundle: Some(false), whole_archive } => { // Link "static-nobundle" native libs only if the crate they originate from // is being linked statically to the current crate. If it's linked dynamically // or is an rlib already included via some other dylib crate, the symbols from // native libs will have already been included in that dylib. if data[cnum.as_usize() - 1] == Linkage::Static { - cmd.link_staticlib(name, verbatim) + if whole_archive == Some(true) { + cmd.link_whole_staticlib( + name, + verbatim, + search_path.get_or_init(|| archive_search_paths(sess)), + ); + } else { + cmd.link_staticlib(name, verbatim) + } } } // ignore statically included native libraries here as we've // already included them when we included the rust library // previously - NativeLibKind::Static { bundle: None | Some(true), .. } => {} + NativeLibKind::Static { bundle: None | Some(true), whole_archive } => { + if whole_archive == Some(true) { + bug!( + "Combining `+bundle` with `+whole-archive` is not allowed. \ + This should have been caught by an earlier validation step already." + ) + } + } NativeLibKind::RawDylib => {} } } diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index b6ee70c419b16..f0b1adf286dbf 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -5,6 +5,7 @@ #![feature(in_band_lifetimes)] #![feature(nll)] #![feature(associated_type_bounds)] +#![feature(once_cell)] #![recursion_limit = "256"] //! This crate contains codegen code that is used by all codegen backends (LLVM and others). diff --git a/src/test/run-make/native-link-modifier-whole-archive/Makefile b/src/test/run-make/native-link-modifier-whole-archive/Makefile new file mode 100644 index 0000000000000..3e11a965f36e9 --- /dev/null +++ b/src/test/run-make/native-link-modifier-whole-archive/Makefile @@ -0,0 +1,37 @@ +# This test case makes sure that native libraries are linked with --whole-archive semantics +# when the `-bundle,+whole-archive` modifiers are applied to them. +# +# The test works by checking that the resulting executables produce the expected output, +# part of which is emitted by otherwise unreferenced C code. If +whole-archive didn't work +# that code would never make it into the final executable and we'd thus be missing some +# of the output. + +-include ../../run-make-fulldeps/tools.mk + +all: $(TMPDIR)/$(call BIN,directly_linked) $(TMPDIR)/$(call BIN,indirectly_linked) $(TMPDIR)/$(call BIN,indirectly_linked_via_attr) + $(call RUN,directly_linked) | $(CGREP) 'static-initializer.directly_linked.' + $(call RUN,indirectly_linked) | $(CGREP) 'static-initializer.indirectly_linked.' + $(call RUN,indirectly_linked_via_attr) | $(CGREP) 'static-initializer.native_lib_in_src.' + +# Native lib linked directly into executable +$(TMPDIR)/$(call BIN,directly_linked): $(call NATIVE_STATICLIB,c_static_lib_with_constructor) + $(RUSTC) directly_linked.rs -Z unstable-options -l static:+whole-archive=c_static_lib_with_constructor + +# Native lib linked into RLIB via `-l static:-bundle,+whole-archive`, RLIB linked into executable +$(TMPDIR)/$(call BIN,indirectly_linked): $(TMPDIR)/librlib_with_cmdline_native_lib.rlib + $(RUSTC) indirectly_linked.rs + +# Native lib linked into RLIB via #[link] attribute, RLIB linked into executable +$(TMPDIR)/$(call BIN,indirectly_linked_via_attr): $(TMPDIR)/libnative_lib_in_src.rlib + $(RUSTC) indirectly_linked_via_attr.rs + +# Native lib linked into rlib with via commandline +$(TMPDIR)/librlib_with_cmdline_native_lib.rlib: $(call NATIVE_STATICLIB,c_static_lib_with_constructor) + $(RUSTC) rlib_with_cmdline_native_lib.rs -Z unstable-options --crate-type=rlib -l static:-bundle,+whole-archive=c_static_lib_with_constructor + +# Native lib linked into rlib via `#[link()]` attribute on extern block. +$(TMPDIR)/libnative_lib_in_src.rlib: $(call NATIVE_STATICLIB,c_static_lib_with_constructor) + $(RUSTC) native_lib_in_src.rs --crate-type=rlib + +$(TMPDIR)/libc_static_lib_with_constructor.o: c_static_lib_with_constructor.cpp + $(call COMPILE_OBJ_CXX,$@,$<) diff --git a/src/test/run-make/native-link-modifier-whole-archive/c_static_lib_with_constructor.cpp b/src/test/run-make/native-link-modifier-whole-archive/c_static_lib_with_constructor.cpp new file mode 100644 index 0000000000000..c687eb0f092f9 --- /dev/null +++ b/src/test/run-make/native-link-modifier-whole-archive/c_static_lib_with_constructor.cpp @@ -0,0 +1,11 @@ +#include + +// Since this is a global variable, its constructor will be called before +// main() is executed. But only if the object file containing it actually +// gets linked into the executable. +struct Foo { + Foo() { + printf("static-initializer."); + fflush(stdout); + } +} FOO; diff --git a/src/test/run-make/native-link-modifier-whole-archive/directly_linked.rs b/src/test/run-make/native-link-modifier-whole-archive/directly_linked.rs new file mode 100644 index 0000000000000..17518e8b2f963 --- /dev/null +++ b/src/test/run-make/native-link-modifier-whole-archive/directly_linked.rs @@ -0,0 +1,6 @@ +use std::io::Write; + +fn main() { + print!("directly_linked."); + std::io::stdout().flush().unwrap(); +} diff --git a/src/test/run-make/native-link-modifier-whole-archive/indirectly_linked.rs b/src/test/run-make/native-link-modifier-whole-archive/indirectly_linked.rs new file mode 100644 index 0000000000000..c8b83fcfe037d --- /dev/null +++ b/src/test/run-make/native-link-modifier-whole-archive/indirectly_linked.rs @@ -0,0 +1,5 @@ +extern crate rlib_with_cmdline_native_lib; + +fn main() { + rlib_with_cmdline_native_lib::hello(); +} diff --git a/src/test/run-make/native-link-modifier-whole-archive/indirectly_linked_via_attr.rs b/src/test/run-make/native-link-modifier-whole-archive/indirectly_linked_via_attr.rs new file mode 100644 index 0000000000000..b9e347609b2c0 --- /dev/null +++ b/src/test/run-make/native-link-modifier-whole-archive/indirectly_linked_via_attr.rs @@ -0,0 +1,5 @@ +extern crate native_lib_in_src; + +fn main() { + native_lib_in_src::hello(); +} diff --git a/src/test/run-make/native-link-modifier-whole-archive/native_lib_in_src.rs b/src/test/run-make/native-link-modifier-whole-archive/native_lib_in_src.rs new file mode 100644 index 0000000000000..373d89b7936e5 --- /dev/null +++ b/src/test/run-make/native-link-modifier-whole-archive/native_lib_in_src.rs @@ -0,0 +1,15 @@ +#![feature(native_link_modifiers_bundle)] +#![feature(native_link_modifiers_whole_archive)] +#![feature(native_link_modifiers)] + +use std::io::Write; + +#[link(name = "c_static_lib_with_constructor", + kind = "static", + modifiers = "-bundle,+whole-archive")] +extern {} + +pub fn hello() { + print!("native_lib_in_src."); + std::io::stdout().flush().unwrap(); +} diff --git a/src/test/run-make/native-link-modifier-whole-archive/rlib_with_cmdline_native_lib.rs b/src/test/run-make/native-link-modifier-whole-archive/rlib_with_cmdline_native_lib.rs new file mode 100644 index 0000000000000..ef2b702dd8209 --- /dev/null +++ b/src/test/run-make/native-link-modifier-whole-archive/rlib_with_cmdline_native_lib.rs @@ -0,0 +1,6 @@ +use std::io::Write; + +pub fn hello() { + print!("indirectly_linked."); + std::io::stdout().flush().unwrap(); +} From f28793dd13e8a8132d559629728e6ca9514dbe36 Mon Sep 17 00:00:00 2001 From: linux1 Date: Fri, 6 Aug 2021 17:53:29 -0400 Subject: [PATCH 03/22] Feat: added inline asm support for s390x --- compiler/rustc_codegen_llvm/src/asm.rs | 6 + compiler/rustc_target/src/asm/mod.rs | 25 ++++ compiler/rustc_target/src/asm/s390x.rs | 156 +++++++++++++++++++++++++ 3 files changed, 187 insertions(+) create mode 100644 compiler/rustc_target/src/asm/s390x.rs diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index 4387f5301a58d..938f036da0e4a 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -314,6 +314,7 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { InlineAsmArch::PowerPC | InlineAsmArch::PowerPC64 => {} InlineAsmArch::Hexagon => {} InlineAsmArch::Mips | InlineAsmArch::Mips64 => {} + InlineAsmArch::s390 => {} InlineAsmArch::SpirV => {} InlineAsmArch::Wasm32 => {} InlineAsmArch::Bpf => {} @@ -633,6 +634,8 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'tcx>>) InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => "r", InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::reg) => "r", InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::wreg) => "w", + InlineAsmRegClass::s390x(s390xInlineAsmRegClass::reg) => "r", + InlineAsmRegClass::s390x(s390xInlineAsmRegClass::freg) => "f", InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => { bug!("LLVM backend does not support SPIR-V") } @@ -711,6 +714,7 @@ fn modifier_to_llvm( } InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => None, InlineAsmRegClass::Bpf(_) => None, + InlineAsmRegClass::s390x(_) => None, InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => { bug!("LLVM backend does not support SPIR-V") } @@ -769,6 +773,8 @@ fn dummy_output_type(cx: &CodegenCx<'ll, 'tcx>, reg: InlineAsmRegClass) -> &'ll InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => cx.type_i32(), InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::reg) => cx.type_i64(), InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::wreg) => cx.type_i32(), + InlineAsmRegClass::s390x(s390xInlineAsmRegClass::reg) => cx.type_i32(), + InlineAsmRegClass::s390x(s390xInlineAsmRegClass::freg) => cx.type_f64(), InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => { bug!("LLVM backend does not support SPIR-V") } diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs index 9ebf8235e2098..3ce5a8195d601 100644 --- a/compiler/rustc_target/src/asm/mod.rs +++ b/compiler/rustc_target/src/asm/mod.rs @@ -154,6 +154,7 @@ mod mips; mod nvptx; mod powerpc; mod riscv; +mod s390x; mod spirv; mod wasm; mod x86; @@ -166,6 +167,7 @@ pub use mips::{MipsInlineAsmReg, MipsInlineAsmRegClass}; pub use nvptx::{NvptxInlineAsmReg, NvptxInlineAsmRegClass}; pub use powerpc::{PowerPCInlineAsmReg, PowerPCInlineAsmRegClass}; pub use riscv::{RiscVInlineAsmReg, RiscVInlineAsmRegClass}; +pub use s390x::{s390xInlineAsmReg, s390xInlineAsmRegClass}; pub use spirv::{SpirVInlineAsmReg, SpirVInlineAsmRegClass}; pub use wasm::{WasmInlineAsmReg, WasmInlineAsmRegClass}; pub use x86::{X86InlineAsmReg, X86InlineAsmRegClass}; @@ -184,6 +186,7 @@ pub enum InlineAsmArch { Mips64, PowerPC, PowerPC64, + s390x, SpirV, Wasm32, Bpf, @@ -206,6 +209,7 @@ impl FromStr for InlineAsmArch { "hexagon" => Ok(Self::Hexagon), "mips" => Ok(Self::Mips), "mips64" => Ok(Self::Mips64), + "s390x" => Ok(Self::s390x), "spirv" => Ok(Self::SpirV), "wasm32" => Ok(Self::Wasm32), "bpf" => Ok(Self::Bpf), @@ -235,6 +239,7 @@ pub enum InlineAsmReg { PowerPC(PowerPCInlineAsmReg), Hexagon(HexagonInlineAsmReg), Mips(MipsInlineAsmReg), + s390x(InlineAsmReg), SpirV(SpirVInlineAsmReg), Wasm(WasmInlineAsmReg), Bpf(BpfInlineAsmReg), @@ -252,6 +257,7 @@ impl InlineAsmReg { Self::PowerPC(r) => r.name(), Self::Hexagon(r) => r.name(), Self::Mips(r) => r.name(), + Self::s390x(r) => r.name(), Self::Bpf(r) => r.name(), Self::Err => "", } @@ -266,6 +272,7 @@ impl InlineAsmReg { Self::PowerPC(r) => InlineAsmRegClass::PowerPC(r.reg_class()), Self::Hexagon(r) => InlineAsmRegClass::Hexagon(r.reg_class()), Self::Mips(r) => InlineAsmRegClass::Mips(r.reg_class()), + Self::s390x(r) => InlineAsmRegClass::s390x(r.reg_class()), Self::Bpf(r) => InlineAsmRegClass::Bpf(r.reg_class()), Self::Err => InlineAsmRegClass::Err, } @@ -305,6 +312,9 @@ impl InlineAsmReg { InlineAsmArch::Mips | InlineAsmArch::Mips64 => { Self::Mips(MipsInlineAsmReg::parse(arch, has_feature, target, &name)?) } + InlineAsmArch::s390x => { + Self::s390x(s390xInlineAsmReg::parse(arch, has_feature, target, &name)?) + } InlineAsmArch::SpirV => { Self::SpirV(SpirVInlineAsmReg::parse(arch, has_feature, target, &name)?) } @@ -333,6 +343,7 @@ impl InlineAsmReg { Self::PowerPC(r) => r.emit(out, arch, modifier), Self::Hexagon(r) => r.emit(out, arch, modifier), Self::Mips(r) => r.emit(out, arch, modifier), + Self::s390x(r) => r.emit(out, arch, modifier), Self::Bpf(r) => r.emit(out, arch, modifier), Self::Err => unreachable!("Use of InlineAsmReg::Err"), } @@ -347,6 +358,7 @@ impl InlineAsmReg { Self::PowerPC(_) => cb(self), Self::Hexagon(r) => r.overlapping_regs(|r| cb(Self::Hexagon(r))), Self::Mips(_) => cb(self), + Self::s390x(_) => cb(self), Self::Bpf(r) => r.overlapping_regs(|r| cb(Self::Bpf(r))), Self::Err => unreachable!("Use of InlineAsmReg::Err"), } @@ -374,6 +386,7 @@ pub enum InlineAsmRegClass { PowerPC(PowerPCInlineAsmRegClass), Hexagon(HexagonInlineAsmRegClass), Mips(MipsInlineAsmRegClass), + s390x(s390xInlineAsmRegClass), SpirV(SpirVInlineAsmRegClass), Wasm(WasmInlineAsmRegClass), Bpf(BpfInlineAsmRegClass), @@ -392,6 +405,7 @@ impl InlineAsmRegClass { Self::PowerPC(r) => r.name(), Self::Hexagon(r) => r.name(), Self::Mips(r) => r.name(), + Self::s390x(r) => r.name(), Self::SpirV(r) => r.name(), Self::Wasm(r) => r.name(), Self::Bpf(r) => r.name(), @@ -412,6 +426,7 @@ impl InlineAsmRegClass { Self::PowerPC(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::PowerPC), Self::Hexagon(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Hexagon), Self::Mips(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Mips), + Self::s390x(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::s390x), Self::SpirV(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::SpirV), Self::Wasm(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Wasm), Self::Bpf(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Bpf), @@ -439,6 +454,7 @@ impl InlineAsmRegClass { Self::PowerPC(r) => r.suggest_modifier(arch, ty), Self::Hexagon(r) => r.suggest_modifier(arch, ty), Self::Mips(r) => r.suggest_modifier(arch, ty), + Self::s390x(r) => r.suggest_modifier(arch, ty), Self::SpirV(r) => r.suggest_modifier(arch, ty), Self::Wasm(r) => r.suggest_modifier(arch, ty), Self::Bpf(r) => r.suggest_modifier(arch, ty), @@ -462,6 +478,7 @@ impl InlineAsmRegClass { Self::PowerPC(r) => r.default_modifier(arch), Self::Hexagon(r) => r.default_modifier(arch), Self::Mips(r) => r.default_modifier(arch), + Self::s390x(r) => r.default_modifier(arch), Self::SpirV(r) => r.default_modifier(arch), Self::Wasm(r) => r.default_modifier(arch), Self::Bpf(r) => r.default_modifier(arch), @@ -484,6 +501,7 @@ impl InlineAsmRegClass { Self::PowerPC(r) => r.supported_types(arch), Self::Hexagon(r) => r.supported_types(arch), Self::Mips(r) => r.supported_types(arch), + Self::s390x(r) => r.supported_types(arch), Self::SpirV(r) => r.supported_types(arch), Self::Wasm(r) => r.supported_types(arch), Self::Bpf(r) => r.supported_types(arch), @@ -509,6 +527,7 @@ impl InlineAsmRegClass { InlineAsmArch::Mips | InlineAsmArch::Mips64 => { Self::Mips(MipsInlineAsmRegClass::parse(arch, name)?) } + InlineAsmArch::s390x => Self::s390x(s390xInlineAsmRegClass::parse(arch, name)?), InlineAsmArch::SpirV => Self::SpirV(SpirVInlineAsmRegClass::parse(arch, name)?), InlineAsmArch::Wasm32 => Self::Wasm(WasmInlineAsmRegClass::parse(arch, name)?), InlineAsmArch::Bpf => Self::Bpf(BpfInlineAsmRegClass::parse(arch, name)?), @@ -527,6 +546,7 @@ impl InlineAsmRegClass { Self::PowerPC(r) => r.valid_modifiers(arch), Self::Hexagon(r) => r.valid_modifiers(arch), Self::Mips(r) => r.valid_modifiers(arch), + Self::s390x(r) => r.valid_modifiers(arch), Self::SpirV(r) => r.valid_modifiers(arch), Self::Wasm(r) => r.valid_modifiers(arch), Self::Bpf(r) => r.valid_modifiers(arch), @@ -695,6 +715,11 @@ pub fn allocatable_registers( mips::fill_reg_map(arch, has_feature, target, &mut map); map } + InlineAsmArch::s390x => { + let mut map = s390x::regclass_map(); + s390x::fill_reg_map(arch, has_feature, target, &mut map); + map + } InlineAsmArch::SpirV => { let mut map = spirv::regclass_map(); spirv::fill_reg_map(arch, has_feature, target, &mut map); diff --git a/compiler/rustc_target/src/asm/s390x.rs b/compiler/rustc_target/src/asm/s390x.rs new file mode 100644 index 0000000000000..ad07e20de8a02 --- /dev/null +++ b/compiler/rustc_target/src/asm/s390x.rs @@ -0,0 +1,156 @@ +use super::{InlineAsmArch, InlineAsmType}; +use rustc_macros::HashStable_Generic; +use std::fmt; + +def_reg_class! { + s390x s390xInlineAsmRegClass { + reg, + freg, + } +} + +impl s390xInlineAsmRegClass { + pub fn valid_modifiers(self, _arch: super::InlineAsmArch) -> &'static [char] { + &[] + } + + pub fn suggest_class(self, _arch: InlineAsmArch, _ty: InlineAsmType) -> Option { + None + } + + pub fn suggest_modifier( + self, + _arch: InlineAsmArch, + _ty: InlineAsmType, + ) -> Option<(char, &'static str)> { + None + } + + pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<(char, &'static str)> { + None + } + + pub fn supported_types( + self, + arch: InlineAsmArch, + ) -> &'static [(InlineAsmType, Option<&'static str>)] { + match (self, arch) { + (Self::reg, _) => types! { _: I8, I16, I32; }, + (Self::freg, _) => types! { _: F32, F64; }, + } + } +} + +def_regs! { + s390x s390xInlineAsmReg s390xInlineAsmRegClass { + r0: req = ["r0"], + r1: reg = ["r1"], + r2: reg = ["r2"], + r3: reg = ["r3"], + r4: reg = ["r4"], + r5: reg = ["r5"], + r6: reg = ["r6"], + r7: reg = ["r7"], + r8: reg = ["r8"], + r9: reg = ["r9"], + r10: reg = ["r10"], + r11: reg = ["r11"], + r12: reg = ["r12"], + r14: reg = ["r14"], + f0: freg = ["f0"], + f1: freg = ["f1"], + f2: freg = ["f2"], + f3: freg = ["f3"], + f4: freg = ["f4"], + f5: freg = ["f5"], + f6: freg = ["f6"], + f7: freg = ["f7"], + f8: freg = ["f8"], + f9: freg = ["f9"], + f10: freg = ["f10"], + f11: freg = ["f11"], + f12: freg = ["f12"], + f13: freg = ["f13"], + f14: freg = ["f14"], + f15: freg = ["f15"], + #error = ["r13"] => + "The base pointer cannot be used as an operand for inline asm", + #error = ["r15"] => + "The stack pointer cannot be used as an operand for inline asm", + #error = ["a0"] => + "This pointer is reserved on s390x and cannot be used as an operand for inline asm", + #error = ["a1"] => + "This pointer is reserved on z/Arch and cannot be used as an operand for inline asm", + #error = ["c0"] => + "c0 is reserved by the kernel and cannot be used as an operand for inline asm", + #error = ["c1"] => + "c1 is reserved by the kernel and cannot be used as an operand for inline asm", + #error = ["c2"] => + "c2 is reserved by the kernel and cannot be used as an operand for inline asm", + #error = ["c3"] => + "c3 is reserved by the kernel and cannot be used as an operand for inline asm", + #error = ["c4"] => + "c4 is reserved by the kernel and cannot be used as an operand for inline asm", + #error = ["c5"] => + "c5 is reserved by the kernel and cannot be used as an operand for inline asm", + #error = ["c6"] => + "c6 is reserved by the kernel and cannot be used as an operand for inline asm", + #error = ["c7"] => + "c7 is reserved by the kernel and cannot be used as an operand for inline asm", + #error = ["c8"] => + "c8 is reserved by the kernel and cannot be used as an operand for inline asm", + #error = ["c9"] => + "c9 is reserved by the kernel and cannot be used as an operand for inline asm", + #error = ["c10"] => + "c10 is reserved by the kernel and cannot be used as an operand for inline asm", + #error = ["c11"] => + "c11 is reserved by the kernel and cannot be used as an operand for inline asm", + #error = ["c12"] => + "c12 is reserved by the kernel and cannot be used as an operand for inline asm", + #error = ["c13"] => + "c13 is reserved by the kernel and cannot be used as an operand for inline asm", + #error = ["c14"] => + "c14 is reserved by the kernel and cannot be used as an operand for inline asm", + #error = ["c15"] => + "c15 is reserved by the kernel and cannot be used as an operand for inline asm", + #error = ["a2"] => + "a2 is not supported by LLVM and cannot be used as an operand for inline asm", + #error = ["a3"] => + "a3 is not supported by LLVM and cannot be used as an operand for inline asm", + #error = ["a4"] => + "a4 is not supported by LLVM and cannot be used as an operand for inline asm", + #error = ["a5"] => + "a5 is not supported by LLVM and cannot be used as an operand for inline asm", + #error = ["a6"] => + "a6 is not supported by LLVM and cannot be used as an operand for inline asm", + #error = ["a7"] => + "a7 is not supported by LLVM and cannot be used as an operand for inline asm", + #error = ["a8"] => + "a8 is not supported by LLVM and cannot be used as an operand for inline asm", + #error = ["a9"] => + "a9 is not supported by LLVM and cannot be used as an operand for inline asm", + #error = ["a10"] => + "a10 is not supported by LLVM and cannot be used as an operand for inline asm", + #error = ["a11"] => + "a11 is not supported by LLVM and cannot be used as an operand for inline asm", + #error = ["a12"] => + "a12 is not supported by LLVM and cannot be used as an operand for inline asm", + #error = ["a13"] => + "a13 is not supported by LLVM and cannot be used as an operand for inline asm", + #error = ["a14"] => + "a14 is not supported by LLVM and cannot be used as an operand for inline asm", + #error = ["a15"] => + "a15 is not supported by LLVM and cannot be used as an operand for inline asm", + } +} + +impl s390xInlineAsmReg { + pub fn emit( + self, + out: &mut dyn fmt::Write, + _arch: InlineAsmArch, + _modifier: Option, + ) -> fmt::Result { + out.write_str(self.name()) + } +} From 5f5afba5fbb869db26c4f9e88c29bad94007dfd1 Mon Sep 17 00:00:00 2001 From: linux1 Date: Wed, 18 Aug 2021 11:25:50 -0400 Subject: [PATCH 04/22] Feat: added s390x reg-definitions, constraint codes, and tests --- compiler/rustc_codegen_llvm/src/asm.rs | 12 ++-- compiler/rustc_target/src/asm/mod.rs | 42 ++++++------- compiler/rustc_target/src/asm/s390x.rs | 10 +-- src/test/assembly/asm/s390x-types.rs | 86 ++++++++++++++++++++++++++ 4 files changed, 118 insertions(+), 32 deletions(-) create mode 100644 src/test/assembly/asm/s390x-types.rs diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index 938f036da0e4a..1689fdd4f2e81 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -314,7 +314,7 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { InlineAsmArch::PowerPC | InlineAsmArch::PowerPC64 => {} InlineAsmArch::Hexagon => {} InlineAsmArch::Mips | InlineAsmArch::Mips64 => {} - InlineAsmArch::s390 => {} + InlineAsmArch::S390x => {} InlineAsmArch::SpirV => {} InlineAsmArch::Wasm32 => {} InlineAsmArch::Bpf => {} @@ -634,8 +634,8 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'tcx>>) InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => "r", InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::reg) => "r", InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::wreg) => "w", - InlineAsmRegClass::s390x(s390xInlineAsmRegClass::reg) => "r", - InlineAsmRegClass::s390x(s390xInlineAsmRegClass::freg) => "f", + InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg) => "r", + InlineAsmRegClass::S390x(S390xInlineAsmRegClass::freg) => "f", InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => { bug!("LLVM backend does not support SPIR-V") } @@ -714,7 +714,7 @@ fn modifier_to_llvm( } InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => None, InlineAsmRegClass::Bpf(_) => None, - InlineAsmRegClass::s390x(_) => None, + InlineAsmRegClass::S390x(_) => None, InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => { bug!("LLVM backend does not support SPIR-V") } @@ -773,8 +773,8 @@ fn dummy_output_type(cx: &CodegenCx<'ll, 'tcx>, reg: InlineAsmRegClass) -> &'ll InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => cx.type_i32(), InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::reg) => cx.type_i64(), InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::wreg) => cx.type_i32(), - InlineAsmRegClass::s390x(s390xInlineAsmRegClass::reg) => cx.type_i32(), - InlineAsmRegClass::s390x(s390xInlineAsmRegClass::freg) => cx.type_f64(), + InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg) => cx.type_i32(), + InlineAsmRegClass::S390x(S390xInlineAsmRegClass::freg) => cx.type_f64(), InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => { bug!("LLVM backend does not support SPIR-V") } diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs index 3ce5a8195d601..015faa14e28af 100644 --- a/compiler/rustc_target/src/asm/mod.rs +++ b/compiler/rustc_target/src/asm/mod.rs @@ -167,7 +167,7 @@ pub use mips::{MipsInlineAsmReg, MipsInlineAsmRegClass}; pub use nvptx::{NvptxInlineAsmReg, NvptxInlineAsmRegClass}; pub use powerpc::{PowerPCInlineAsmReg, PowerPCInlineAsmRegClass}; pub use riscv::{RiscVInlineAsmReg, RiscVInlineAsmRegClass}; -pub use s390x::{s390xInlineAsmReg, s390xInlineAsmRegClass}; +pub use s390x::{S390xInlineAsmReg, S390xInlineAsmRegClass}; pub use spirv::{SpirVInlineAsmReg, SpirVInlineAsmRegClass}; pub use wasm::{WasmInlineAsmReg, WasmInlineAsmRegClass}; pub use x86::{X86InlineAsmReg, X86InlineAsmRegClass}; @@ -186,7 +186,7 @@ pub enum InlineAsmArch { Mips64, PowerPC, PowerPC64, - s390x, + S390x, SpirV, Wasm32, Bpf, @@ -209,7 +209,7 @@ impl FromStr for InlineAsmArch { "hexagon" => Ok(Self::Hexagon), "mips" => Ok(Self::Mips), "mips64" => Ok(Self::Mips64), - "s390x" => Ok(Self::s390x), + "s390x" => Ok(Self::S390x), "spirv" => Ok(Self::SpirV), "wasm32" => Ok(Self::Wasm32), "bpf" => Ok(Self::Bpf), @@ -239,7 +239,7 @@ pub enum InlineAsmReg { PowerPC(PowerPCInlineAsmReg), Hexagon(HexagonInlineAsmReg), Mips(MipsInlineAsmReg), - s390x(InlineAsmReg), + S390x(S390xInlineAsmReg), SpirV(SpirVInlineAsmReg), Wasm(WasmInlineAsmReg), Bpf(BpfInlineAsmReg), @@ -257,7 +257,7 @@ impl InlineAsmReg { Self::PowerPC(r) => r.name(), Self::Hexagon(r) => r.name(), Self::Mips(r) => r.name(), - Self::s390x(r) => r.name(), + Self::S390x(r) => r.name(), Self::Bpf(r) => r.name(), Self::Err => "", } @@ -272,7 +272,7 @@ impl InlineAsmReg { Self::PowerPC(r) => InlineAsmRegClass::PowerPC(r.reg_class()), Self::Hexagon(r) => InlineAsmRegClass::Hexagon(r.reg_class()), Self::Mips(r) => InlineAsmRegClass::Mips(r.reg_class()), - Self::s390x(r) => InlineAsmRegClass::s390x(r.reg_class()), + Self::S390x(r) => InlineAsmRegClass::S390x(r.reg_class()), Self::Bpf(r) => InlineAsmRegClass::Bpf(r.reg_class()), Self::Err => InlineAsmRegClass::Err, } @@ -312,8 +312,8 @@ impl InlineAsmReg { InlineAsmArch::Mips | InlineAsmArch::Mips64 => { Self::Mips(MipsInlineAsmReg::parse(arch, has_feature, target, &name)?) } - InlineAsmArch::s390x => { - Self::s390x(s390xInlineAsmReg::parse(arch, has_feature, target, &name)?) + InlineAsmArch::S390x => { + Self::S390x(S390xInlineAsmReg::parse(arch, has_feature, target, &name)?) } InlineAsmArch::SpirV => { Self::SpirV(SpirVInlineAsmReg::parse(arch, has_feature, target, &name)?) @@ -343,7 +343,7 @@ impl InlineAsmReg { Self::PowerPC(r) => r.emit(out, arch, modifier), Self::Hexagon(r) => r.emit(out, arch, modifier), Self::Mips(r) => r.emit(out, arch, modifier), - Self::s390x(r) => r.emit(out, arch, modifier), + Self::S390x(r) => r.emit(out, arch, modifier), Self::Bpf(r) => r.emit(out, arch, modifier), Self::Err => unreachable!("Use of InlineAsmReg::Err"), } @@ -358,7 +358,7 @@ impl InlineAsmReg { Self::PowerPC(_) => cb(self), Self::Hexagon(r) => r.overlapping_regs(|r| cb(Self::Hexagon(r))), Self::Mips(_) => cb(self), - Self::s390x(_) => cb(self), + Self::S390x(_) => cb(self), Self::Bpf(r) => r.overlapping_regs(|r| cb(Self::Bpf(r))), Self::Err => unreachable!("Use of InlineAsmReg::Err"), } @@ -386,7 +386,7 @@ pub enum InlineAsmRegClass { PowerPC(PowerPCInlineAsmRegClass), Hexagon(HexagonInlineAsmRegClass), Mips(MipsInlineAsmRegClass), - s390x(s390xInlineAsmRegClass), + S390x(S390xInlineAsmRegClass), SpirV(SpirVInlineAsmRegClass), Wasm(WasmInlineAsmRegClass), Bpf(BpfInlineAsmRegClass), @@ -405,7 +405,7 @@ impl InlineAsmRegClass { Self::PowerPC(r) => r.name(), Self::Hexagon(r) => r.name(), Self::Mips(r) => r.name(), - Self::s390x(r) => r.name(), + Self::S390x(r) => r.name(), Self::SpirV(r) => r.name(), Self::Wasm(r) => r.name(), Self::Bpf(r) => r.name(), @@ -426,7 +426,7 @@ impl InlineAsmRegClass { Self::PowerPC(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::PowerPC), Self::Hexagon(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Hexagon), Self::Mips(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Mips), - Self::s390x(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::s390x), + Self::S390x(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::S390x), Self::SpirV(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::SpirV), Self::Wasm(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Wasm), Self::Bpf(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Bpf), @@ -454,7 +454,7 @@ impl InlineAsmRegClass { Self::PowerPC(r) => r.suggest_modifier(arch, ty), Self::Hexagon(r) => r.suggest_modifier(arch, ty), Self::Mips(r) => r.suggest_modifier(arch, ty), - Self::s390x(r) => r.suggest_modifier(arch, ty), + Self::S390x(r) => r.suggest_modifier(arch, ty), Self::SpirV(r) => r.suggest_modifier(arch, ty), Self::Wasm(r) => r.suggest_modifier(arch, ty), Self::Bpf(r) => r.suggest_modifier(arch, ty), @@ -478,7 +478,7 @@ impl InlineAsmRegClass { Self::PowerPC(r) => r.default_modifier(arch), Self::Hexagon(r) => r.default_modifier(arch), Self::Mips(r) => r.default_modifier(arch), - Self::s390x(r) => r.default_modifier(arch), + Self::S390x(r) => r.default_modifier(arch), Self::SpirV(r) => r.default_modifier(arch), Self::Wasm(r) => r.default_modifier(arch), Self::Bpf(r) => r.default_modifier(arch), @@ -501,7 +501,7 @@ impl InlineAsmRegClass { Self::PowerPC(r) => r.supported_types(arch), Self::Hexagon(r) => r.supported_types(arch), Self::Mips(r) => r.supported_types(arch), - Self::s390x(r) => r.supported_types(arch), + Self::S390x(r) => r.supported_types(arch), Self::SpirV(r) => r.supported_types(arch), Self::Wasm(r) => r.supported_types(arch), Self::Bpf(r) => r.supported_types(arch), @@ -527,7 +527,7 @@ impl InlineAsmRegClass { InlineAsmArch::Mips | InlineAsmArch::Mips64 => { Self::Mips(MipsInlineAsmRegClass::parse(arch, name)?) } - InlineAsmArch::s390x => Self::s390x(s390xInlineAsmRegClass::parse(arch, name)?), + InlineAsmArch::S390x => Self::S390x(S390xInlineAsmRegClass::parse(arch, name)?), InlineAsmArch::SpirV => Self::SpirV(SpirVInlineAsmRegClass::parse(arch, name)?), InlineAsmArch::Wasm32 => Self::Wasm(WasmInlineAsmRegClass::parse(arch, name)?), InlineAsmArch::Bpf => Self::Bpf(BpfInlineAsmRegClass::parse(arch, name)?), @@ -546,7 +546,7 @@ impl InlineAsmRegClass { Self::PowerPC(r) => r.valid_modifiers(arch), Self::Hexagon(r) => r.valid_modifiers(arch), Self::Mips(r) => r.valid_modifiers(arch), - Self::s390x(r) => r.valid_modifiers(arch), + Self::S390x(r) => r.valid_modifiers(arch), Self::SpirV(r) => r.valid_modifiers(arch), Self::Wasm(r) => r.valid_modifiers(arch), Self::Bpf(r) => r.valid_modifiers(arch), @@ -715,11 +715,11 @@ pub fn allocatable_registers( mips::fill_reg_map(arch, has_feature, target, &mut map); map } - InlineAsmArch::s390x => { - let mut map = s390x::regclass_map(); + InlineAsmArch::S390x => { + let mut map = s390x::regclass_map(); s390x::fill_reg_map(arch, has_feature, target, &mut map); map - } + } InlineAsmArch::SpirV => { let mut map = spirv::regclass_map(); spirv::fill_reg_map(arch, has_feature, target, &mut map); diff --git a/compiler/rustc_target/src/asm/s390x.rs b/compiler/rustc_target/src/asm/s390x.rs index ad07e20de8a02..0acbea800930c 100644 --- a/compiler/rustc_target/src/asm/s390x.rs +++ b/compiler/rustc_target/src/asm/s390x.rs @@ -3,13 +3,13 @@ use rustc_macros::HashStable_Generic; use std::fmt; def_reg_class! { - s390x s390xInlineAsmRegClass { + S390x S390xInlineAsmRegClass { reg, freg, } } -impl s390xInlineAsmRegClass { +impl S390xInlineAsmRegClass { pub fn valid_modifiers(self, _arch: super::InlineAsmArch) -> &'static [char] { &[] } @@ -42,8 +42,8 @@ impl s390xInlineAsmRegClass { } def_regs! { - s390x s390xInlineAsmReg s390xInlineAsmRegClass { - r0: req = ["r0"], + S390x S390xInlineAsmReg S390xInlineAsmRegClass { + r0: reg = ["r0"], r1: reg = ["r1"], r2: reg = ["r2"], r3: reg = ["r3"], @@ -144,7 +144,7 @@ def_regs! { } } -impl s390xInlineAsmReg { +impl S390xInlineAsmReg { pub fn emit( self, out: &mut dyn fmt::Write, diff --git a/src/test/assembly/asm/s390x-types.rs b/src/test/assembly/asm/s390x-types.rs new file mode 100644 index 0000000000000..5f1a5f2de56be --- /dev/null +++ b/src/test/assembly/asm/s390x-types.rs @@ -0,0 +1,86 @@ +// min-llvm-version: 10.0.1 +// revisions: s390x +// assembly-output: emit-asm +//[s390x] compile-flags: --target s390x-unknown-linux-gnu +//[s390x] needs-llvm-components: systemz + +#![feature(no_core, lang_items, rustc_attrs, repr_simd)] +#![crate_type = "rlib"] +#![no_core] +#![allow(asm_sub_register, non_camel_case_types)] + +#[rustc_builtin_macro] +macro_rules! asm { + () => {}; +} +#[rustc_builtin_macro] +macro_rules! concat { + () => {}; +} +#[rustc_builtin_macro] +macro_rules! stringify { + () => {}; +} + +#[lang = "sized"] +trait Sized {} +#[lang = "copy"] +trait Copy {} + +type ptr = *const i32; + +impl Copy for i8 {} +impl Copy for u8 {} +impl Copy for i16 {} +impl Copy for i32 {} +impl Copy for i64 {} +impl Copy for f32 {} +impl Copy for f64 {} +impl Copy for ptr {} + +extern "C" { + fn extern_func(); + static extern_static: u8; +} + +// Hack to avoid function merging +extern "Rust" { + fn dont_merge(s: &str); +} + +macro_rules! check { ($func:ident, $ty:ty, $class:ident, $mov:literal) => { + + pub unsafe fn $func(x: $ty) -> $ty { + dont_merge(stringify!(func)); + + let y; + asm!(concat!($mov," {}, {}"), out($class) y, in($class) x); + y + } +};} + +macro_rules! check_reg { ($func:ident, $ty:ty, $reg:tt, $mov:literal) => { + + pub unsafe fn $func(x: $ty) -> $ty { + dont_merge(stringify!(func)); + + let y; + asm!(concat!($mov, " ", $reg, ", ", $reg), lateout($reg) y, in($reg) x); + y + } +};} + +// systemz-LABEL: sym_fn_32: +// systemz: #APP +// systemz: brasl %r14, extern_func@PLT +// systemz: #NO_APP +#[cfg(s390x)] +pub unsafe fn sym_fn_32() { + asm!("brasl %r14, {}", sym extern_func); +} + +// CHECK-LABEL: reg_i32: +// CHECK: #APP +// CHECK: lgr r{{[0-15]+}}, r{{[0-15]+}} +// CHECK: #NO_APP +check!(reg_i32, i32, reg, "lgr"); From 7095dfffc3bde0fc56a837241db84e414e3d9b25 Mon Sep 17 00:00:00 2001 From: linux1 Date: Wed, 18 Aug 2021 12:14:26 -0400 Subject: [PATCH 05/22] Refactor: added #[no_mangle] --- src/test/assembly/asm/s390x-types.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/assembly/asm/s390x-types.rs b/src/test/assembly/asm/s390x-types.rs index 5f1a5f2de56be..7b2ef9bda3478 100644 --- a/src/test/assembly/asm/s390x-types.rs +++ b/src/test/assembly/asm/s390x-types.rs @@ -75,6 +75,7 @@ macro_rules! check_reg { ($func:ident, $ty:ty, $reg:tt, $mov:literal) => { // systemz: brasl %r14, extern_func@PLT // systemz: #NO_APP #[cfg(s390x)] +#[no_mangle] pub unsafe fn sym_fn_32() { asm!("brasl %r14, {}", sym extern_func); } @@ -83,4 +84,5 @@ pub unsafe fn sym_fn_32() { // CHECK: #APP // CHECK: lgr r{{[0-15]+}}, r{{[0-15]+}} // CHECK: #NO_APP +#[no_mangle] check!(reg_i32, i32, reg, "lgr"); From 66e95b17ecfc93e39b1846436a86f0e924ab30b3 Mon Sep 17 00:00:00 2001 From: linux1 Date: Wed, 18 Aug 2021 12:40:18 -0400 Subject: [PATCH 06/22] Fix: moved #[no_mangle] --- src/test/assembly/asm/s390x-types.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/test/assembly/asm/s390x-types.rs b/src/test/assembly/asm/s390x-types.rs index 7b2ef9bda3478..0fbb77b96175e 100644 --- a/src/test/assembly/asm/s390x-types.rs +++ b/src/test/assembly/asm/s390x-types.rs @@ -49,7 +49,7 @@ extern "Rust" { } macro_rules! check { ($func:ident, $ty:ty, $class:ident, $mov:literal) => { - + #[no_mangle] pub unsafe fn $func(x: $ty) -> $ty { dont_merge(stringify!(func)); @@ -75,7 +75,6 @@ macro_rules! check_reg { ($func:ident, $ty:ty, $reg:tt, $mov:literal) => { // systemz: brasl %r14, extern_func@PLT // systemz: #NO_APP #[cfg(s390x)] -#[no_mangle] pub unsafe fn sym_fn_32() { asm!("brasl %r14, {}", sym extern_func); } @@ -84,5 +83,4 @@ pub unsafe fn sym_fn_32() { // CHECK: #APP // CHECK: lgr r{{[0-15]+}}, r{{[0-15]+}} // CHECK: #NO_APP -#[no_mangle] check!(reg_i32, i32, reg, "lgr"); From eeb0b52bf852b902b2bd1adaf919c35e2387ce28 Mon Sep 17 00:00:00 2001 From: linux1 Date: Sun, 22 Aug 2021 17:26:18 -0400 Subject: [PATCH 07/22] Feat: further testing & support for i64 general register use --- compiler/rustc_target/src/asm/s390x.rs | 2 +- src/test/assembly/asm/s390x-types.rs | 52 +++++++++++++++++++++++--- 2 files changed, 47 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_target/src/asm/s390x.rs b/compiler/rustc_target/src/asm/s390x.rs index 0acbea800930c..dbf4168e4a80f 100644 --- a/compiler/rustc_target/src/asm/s390x.rs +++ b/compiler/rustc_target/src/asm/s390x.rs @@ -35,7 +35,7 @@ impl S390xInlineAsmRegClass { arch: InlineAsmArch, ) -> &'static [(InlineAsmType, Option<&'static str>)] { match (self, arch) { - (Self::reg, _) => types! { _: I8, I16, I32; }, + (Self::reg, _) => types! { _: I8, I16, I32, I64; }, (Self::freg, _) => types! { _: F32, F64; }, } } diff --git a/src/test/assembly/asm/s390x-types.rs b/src/test/assembly/asm/s390x-types.rs index 0fbb77b96175e..692193158405f 100644 --- a/src/test/assembly/asm/s390x-types.rs +++ b/src/test/assembly/asm/s390x-types.rs @@ -60,7 +60,7 @@ macro_rules! check { ($func:ident, $ty:ty, $class:ident, $mov:literal) => { };} macro_rules! check_reg { ($func:ident, $ty:ty, $reg:tt, $mov:literal) => { - + #[no_mangle] pub unsafe fn $func(x: $ty) -> $ty { dont_merge(stringify!(func)); @@ -70,17 +70,57 @@ macro_rules! check_reg { ($func:ident, $ty:ty, $reg:tt, $mov:literal) => { } };} -// systemz-LABEL: sym_fn_32: -// systemz: #APP -// systemz: brasl %r14, extern_func@PLT -// systemz: #NO_APP +// CHECK-LABEL: sym_fn_32: +// CHECK: #APP +// CHECK: brasl %r14, extern_func +// CHECK: #NO_APP #[cfg(s390x)] +#[no_mangle] pub unsafe fn sym_fn_32() { asm!("brasl %r14, {}", sym extern_func); } +// CHECK-LABEL: sym_static: +// CHECK: #APP +// CHECK: brasl %r14, extern_static +// CHECK: #NO_APP +#[no_mangle] +pub unsafe fn sym_static() { + asm!("brasl %r14, {}", sym extern_static); +} + +// CHECK-LABEL: reg_i8: +// CHECK: #APP +// CHECK: lgr %r{{[0-9]+}}, %r{{[0-9]+}} +// CHECK: #NO_APP +check!(reg_i8, i8, reg, "lgr"); + +// CHECK-LABEL: reg_i16: +// CHECK: #APP +// CHECK: lgr %r{{[0-9]+}}, %r{{[0-9]+}} +// CHECK: #NO_APP +check!(reg_i16, i16, reg, "lgr"); + // CHECK-LABEL: reg_i32: // CHECK: #APP -// CHECK: lgr r{{[0-15]+}}, r{{[0-15]+}} +// CHECK: lgr %r{{[0-9]+}}, %r{{[0-9]+}} // CHECK: #NO_APP check!(reg_i32, i32, reg, "lgr"); + +// CHECK-LABEL: reg_i64: +// CHECK: #APP +// CHECK: lgr %r{{[0-9]+}}, %r{{[0-9]+}} +// CHECK: #NO_APP +check!(reg_i64, i64, reg, "lgr"); + +// CHECK-LABEL: reg_f32: +// CHECK: #APP +// CHECK: ler %f{{[0-9]+}}, %f{{[0-9]+}} +// CHECK: #NO_APP +check!(reg_f32, f32, freg, "ler"); + +// CHECK-LABEL: reg_f64: +// CHECK: #APP +// CHECK: ldr %f{{[0-9]+}}, %f{{[0-9]+}} +// CHECK: #NO_APP +check!(reg_f64, f64, freg, "ldr"); From 0c9e23c7ce964438b107d064533b89f024e7ccf8 Mon Sep 17 00:00:00 2001 From: linux1 Date: Sun, 22 Aug 2021 17:38:22 -0400 Subject: [PATCH 08/22] Fix: appeased x.py test tidy --bless --- compiler/rustc_target/src/asm/mod.rs | 10 +++++----- compiler/rustc_target/src/asm/s390x.rs | 2 +- src/test/assembly/asm/s390x-types.rs | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs index 015faa14e28af..3b3017e37c1f0 100644 --- a/compiler/rustc_target/src/asm/mod.rs +++ b/compiler/rustc_target/src/asm/mod.rs @@ -257,7 +257,7 @@ impl InlineAsmReg { Self::PowerPC(r) => r.name(), Self::Hexagon(r) => r.name(), Self::Mips(r) => r.name(), - Self::S390x(r) => r.name(), + Self::S390x(r) => r.name(), Self::Bpf(r) => r.name(), Self::Err => "", } @@ -312,7 +312,7 @@ impl InlineAsmReg { InlineAsmArch::Mips | InlineAsmArch::Mips64 => { Self::Mips(MipsInlineAsmReg::parse(arch, has_feature, target, &name)?) } - InlineAsmArch::S390x => { + InlineAsmArch::S390x => { Self::S390x(S390xInlineAsmReg::parse(arch, has_feature, target, &name)?) } InlineAsmArch::SpirV => { @@ -715,11 +715,11 @@ pub fn allocatable_registers( mips::fill_reg_map(arch, has_feature, target, &mut map); map } - InlineAsmArch::S390x => { - let mut map = s390x::regclass_map(); + InlineAsmArch::S390x => { + let mut map = s390x::regclass_map(); s390x::fill_reg_map(arch, has_feature, target, &mut map); map - } + } InlineAsmArch::SpirV => { let mut map = spirv::regclass_map(); spirv::fill_reg_map(arch, has_feature, target, &mut map); diff --git a/compiler/rustc_target/src/asm/s390x.rs b/compiler/rustc_target/src/asm/s390x.rs index dbf4168e4a80f..29f370928713b 100644 --- a/compiler/rustc_target/src/asm/s390x.rs +++ b/compiler/rustc_target/src/asm/s390x.rs @@ -113,7 +113,7 @@ def_regs! { "c14 is reserved by the kernel and cannot be used as an operand for inline asm", #error = ["c15"] => "c15 is reserved by the kernel and cannot be used as an operand for inline asm", - #error = ["a2"] => + #error = ["a2"] => "a2 is not supported by LLVM and cannot be used as an operand for inline asm", #error = ["a3"] => "a3 is not supported by LLVM and cannot be used as an operand for inline asm", diff --git a/src/test/assembly/asm/s390x-types.rs b/src/test/assembly/asm/s390x-types.rs index 692193158405f..dd8a256516e6f 100644 --- a/src/test/assembly/asm/s390x-types.rs +++ b/src/test/assembly/asm/s390x-types.rs @@ -49,7 +49,7 @@ extern "Rust" { } macro_rules! check { ($func:ident, $ty:ty, $class:ident, $mov:literal) => { - #[no_mangle] + #[no_mangle] pub unsafe fn $func(x: $ty) -> $ty { dont_merge(stringify!(func)); @@ -60,7 +60,7 @@ macro_rules! check { ($func:ident, $ty:ty, $class:ident, $mov:literal) => { };} macro_rules! check_reg { ($func:ident, $ty:ty, $reg:tt, $mov:literal) => { - #[no_mangle] + #[no_mangle] pub unsafe fn $func(x: $ty) -> $ty { dont_merge(stringify!(func)); From 0ac601d03e0e0951f73d6a89cb6a5aef1905e29b Mon Sep 17 00:00:00 2001 From: Hans Kratz Date: Mon, 23 Aug 2021 08:27:08 +0200 Subject: [PATCH 09/22] Mach-O (Macos/ios/...) LLD flavor is always LD64. --- compiler/rustc_target/src/spec/apple_base.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_target/src/spec/apple_base.rs b/compiler/rustc_target/src/spec/apple_base.rs index cff0b3651e170..0a0c548fecd0e 100644 --- a/compiler/rustc_target/src/spec/apple_base.rs +++ b/compiler/rustc_target/src/spec/apple_base.rs @@ -1,6 +1,6 @@ use std::env; -use crate::spec::{FramePointer, SplitDebuginfo, TargetOptions}; +use crate::spec::{FramePointer, LldFlavor, SplitDebuginfo, TargetOptions}; pub fn opts(os: &str) -> TargetOptions { // ELF TLS is only available in macOS 10.7+. If you try to compile for 10.6 @@ -35,6 +35,7 @@ pub fn opts(os: &str) -> TargetOptions { abi_return_struct_as_int: true, emit_debug_gdb_scripts: false, eh_frame_header: false, + lld_flavor: LldFlavor::Ld64, // The historical default for macOS targets is to run `dsymutil` which // generates a packed version of debuginfo split from the main file. From a5190950546c1d62b5a1b476daae3a28f412df05 Mon Sep 17 00:00:00 2001 From: Hans Kratz Date: Mon, 23 Aug 2021 09:28:07 +0200 Subject: [PATCH 10/22] Include ld64 nexte to ld for use with -Z gcc-ld --- src/bootstrap/compile.rs | 4 ++++ src/bootstrap/dist.rs | 2 ++ 2 files changed, 6 insertions(+) diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index d25989954783a..2a6a05e8e509d 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -1121,6 +1121,10 @@ impl Step for Assemble { &lld_install.join("bin").join(&src_exe), &gcc_ld_dir.join(exe("ld", target_compiler.host)), ); + builder.copy( + &lld_install.join("bin").join(&src_exe), + &gcc_ld_dir.join(exe("ld64", target_compiler.host)), + ); } // Similarly, copy `llvm-dwp` into libdir for Split DWARF. Only copy it when the LLVM diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 64075e18366bf..d0bcdb179e39d 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -412,6 +412,8 @@ impl Step for Rustc { let gcc_lld_dir = dst_dir.join("gcc-ld"); t!(fs::create_dir(&gcc_lld_dir)); builder.copy(&src_dir.join(&rust_lld), &gcc_lld_dir.join(exe("ld", compiler.host))); + builder + .copy(&src_dir.join(&rust_lld), &gcc_lld_dir.join(exe("ld64", compiler.host))); } // Copy over llvm-dwp if it's there From 0f7702efa1cbff1ae0552664dc814e9ac682c09c Mon Sep 17 00:00:00 2001 From: Hans Kratz Date: Mon, 23 Aug 2021 09:32:19 +0200 Subject: [PATCH 11/22] Pass -fuse-ld=/path/to/ld64 if -Z gcc-ld and the lld_flavor for the target is Ld64 --- compiler/rustc_codegen_ssa/src/back/link.rs | 47 +++++++++++++++------ 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index f3eb1e04d07dc..08c6a951ffb9b 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -2485,20 +2485,39 @@ fn add_gcc_ld_path(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) { if let LinkerFlavor::Gcc = flavor { match ld_impl { LdImpl::Lld => { - let tools_path = - sess.host_filesearch(PathKind::All).get_tools_search_paths(false); - let lld_path = tools_path - .into_iter() - .map(|p| p.join("gcc-ld")) - .find(|p| { - p.join(if sess.host.is_like_windows { "ld.exe" } else { "ld" }).exists() - }) - .unwrap_or_else(|| sess.fatal("rust-lld (as ld) not found")); - cmd.cmd().arg({ - let mut arg = OsString::from("-B"); - arg.push(lld_path); - arg - }); + if sess.target.lld_flavor == LldFlavor::Ld64 { + let tools_path = + sess.host_filesearch(PathKind::All).get_tools_search_paths(false); + let ld64_exe = tools_path + .into_iter() + .map(|p| p.join("gcc-ld")) + .map(|p| { + p.join(if sess.host.is_like_windows { "ld64.exe" } else { "ld64" }) + }) + .find(|p| p.exists()) + .unwrap_or_else(|| sess.fatal("rust-lld (as ld64) not found")); + cmd.cmd().arg({ + let mut arg = OsString::from("-fuse-ld="); + arg.push(ld64_exe); + arg + }); + } else { + let tools_path = + sess.host_filesearch(PathKind::All).get_tools_search_paths(false); + let lld_path = tools_path + .into_iter() + .map(|p| p.join("gcc-ld")) + .find(|p| { + p.join(if sess.host.is_like_windows { "ld.exe" } else { "ld" }) + .exists() + }) + .unwrap_or_else(|| sess.fatal("rust-lld (as ld) not found")); + cmd.cmd().arg({ + let mut arg = OsString::from("-B"); + arg.push(lld_path); + arg + }); + } } } } else { From 05cd587726b01415f50ab8def30ea07864298e13 Mon Sep 17 00:00:00 2001 From: linux1 Date: Mon, 23 Aug 2021 17:32:27 -0400 Subject: [PATCH 12/22] Refactor: disabled frame pointer; consolidated unsupported register errors; added register prefix --- compiler/rustc_target/src/asm/s390x.rs | 86 ++++++-------------------- 1 file changed, 18 insertions(+), 68 deletions(-) diff --git a/compiler/rustc_target/src/asm/s390x.rs b/compiler/rustc_target/src/asm/s390x.rs index 29f370928713b..5ed93c0c1a9ce 100644 --- a/compiler/rustc_target/src/asm/s390x.rs +++ b/compiler/rustc_target/src/asm/s390x.rs @@ -54,8 +54,8 @@ def_regs! { r8: reg = ["r8"], r9: reg = ["r9"], r10: reg = ["r10"], - r11: reg = ["r11"], r12: reg = ["r12"], + r13: reg = ["r13"], r14: reg = ["r14"], f0: freg = ["f0"], f1: freg = ["f1"], @@ -73,74 +73,24 @@ def_regs! { f13: freg = ["f13"], f14: freg = ["f14"], f15: freg = ["f15"], - #error = ["r13"] => - "The base pointer cannot be used as an operand for inline asm", + #error = ["r11"] => + "The frame pointer cannot be used as an operand for inline asm", #error = ["r15"] => "The stack pointer cannot be used as an operand for inline asm", - #error = ["a0"] => - "This pointer is reserved on s390x and cannot be used as an operand for inline asm", - #error = ["a1"] => - "This pointer is reserved on z/Arch and cannot be used as an operand for inline asm", - #error = ["c0"] => - "c0 is reserved by the kernel and cannot be used as an operand for inline asm", - #error = ["c1"] => - "c1 is reserved by the kernel and cannot be used as an operand for inline asm", - #error = ["c2"] => - "c2 is reserved by the kernel and cannot be used as an operand for inline asm", - #error = ["c3"] => - "c3 is reserved by the kernel and cannot be used as an operand for inline asm", - #error = ["c4"] => - "c4 is reserved by the kernel and cannot be used as an operand for inline asm", - #error = ["c5"] => - "c5 is reserved by the kernel and cannot be used as an operand for inline asm", - #error = ["c6"] => - "c6 is reserved by the kernel and cannot be used as an operand for inline asm", - #error = ["c7"] => - "c7 is reserved by the kernel and cannot be used as an operand for inline asm", - #error = ["c8"] => - "c8 is reserved by the kernel and cannot be used as an operand for inline asm", - #error = ["c9"] => - "c9 is reserved by the kernel and cannot be used as an operand for inline asm", - #error = ["c10"] => - "c10 is reserved by the kernel and cannot be used as an operand for inline asm", - #error = ["c11"] => - "c11 is reserved by the kernel and cannot be used as an operand for inline asm", - #error = ["c12"] => - "c12 is reserved by the kernel and cannot be used as an operand for inline asm", - #error = ["c13"] => - "c13 is reserved by the kernel and cannot be used as an operand for inline asm", - #error = ["c14"] => - "c14 is reserved by the kernel and cannot be used as an operand for inline asm", - #error = ["c15"] => - "c15 is reserved by the kernel and cannot be used as an operand for inline asm", - #error = ["a2"] => - "a2 is not supported by LLVM and cannot be used as an operand for inline asm", - #error = ["a3"] => - "a3 is not supported by LLVM and cannot be used as an operand for inline asm", - #error = ["a4"] => - "a4 is not supported by LLVM and cannot be used as an operand for inline asm", - #error = ["a5"] => - "a5 is not supported by LLVM and cannot be used as an operand for inline asm", - #error = ["a6"] => - "a6 is not supported by LLVM and cannot be used as an operand for inline asm", - #error = ["a7"] => - "a7 is not supported by LLVM and cannot be used as an operand for inline asm", - #error = ["a8"] => - "a8 is not supported by LLVM and cannot be used as an operand for inline asm", - #error = ["a9"] => - "a9 is not supported by LLVM and cannot be used as an operand for inline asm", - #error = ["a10"] => - "a10 is not supported by LLVM and cannot be used as an operand for inline asm", - #error = ["a11"] => - "a11 is not supported by LLVM and cannot be used as an operand for inline asm", - #error = ["a12"] => - "a12 is not supported by LLVM and cannot be used as an operand for inline asm", - #error = ["a13"] => - "a13 is not supported by LLVM and cannot be used as an operand for inline asm", - #error = ["a14"] => - "a14 is not supported by LLVM and cannot be used as an operand for inline asm", - #error = ["a15"] => - "a15 is not supported by LLVM and cannot be used as an operand for inline asm", + #error = [ + "c0", "c1", "c2", "c3", + "c4", "c5", "c6", "c7", + "c8", "c9", "c10", "c11", + "c12", "c13", "c14", "c15" + ] => + "control registers are reserved by the kernel and cannot be used as operands for inline asm", + #error = [ + "a0", "a1", "a2", "a3", + "a4", "a5", "a6", "a7", + "a8", "a9", "a10", "a11", + "a12", "a13", "a14", "a15" + ] => + "access registers are not supported and cannot be used as operands for inline asm", } } @@ -151,6 +101,6 @@ impl S390xInlineAsmReg { _arch: InlineAsmArch, _modifier: Option, ) -> fmt::Result { - out.write_str(self.name()) + out.write_str(&format!("%{}", self.name())) } } From a9f623707b8dcaba260b547e1950a4679b3b40eb Mon Sep 17 00:00:00 2001 From: linux1 Date: Mon, 23 Aug 2021 17:56:04 -0400 Subject: [PATCH 13/22] Fix: made suggested change --- compiler/rustc_target/src/asm/s390x.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_target/src/asm/s390x.rs b/compiler/rustc_target/src/asm/s390x.rs index 5ed93c0c1a9ce..a74873f17476e 100644 --- a/compiler/rustc_target/src/asm/s390x.rs +++ b/compiler/rustc_target/src/asm/s390x.rs @@ -101,6 +101,6 @@ impl S390xInlineAsmReg { _arch: InlineAsmArch, _modifier: Option, ) -> fmt::Result { - out.write_str(&format!("%{}", self.name())) + write!(out, "%{}", self.name()) } } From 96381d390d7362e06809ee624dba2cca1bc6776f Mon Sep 17 00:00:00 2001 From: linux1 Date: Mon, 23 Aug 2021 21:53:23 -0400 Subject: [PATCH 14/22] Fix: added necessary prefix --- src/test/assembly/asm/s390x-types.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/test/assembly/asm/s390x-types.rs b/src/test/assembly/asm/s390x-types.rs index dd8a256516e6f..ec0515b20bdfb 100644 --- a/src/test/assembly/asm/s390x-types.rs +++ b/src/test/assembly/asm/s390x-types.rs @@ -51,7 +51,7 @@ extern "Rust" { macro_rules! check { ($func:ident, $ty:ty, $class:ident, $mov:literal) => { #[no_mangle] pub unsafe fn $func(x: $ty) -> $ty { - dont_merge(stringify!(func)); + dont_merge(stringify!($func)); let y; asm!(concat!($mov," {}, {}"), out($class) y, in($class) x); @@ -62,7 +62,7 @@ macro_rules! check { ($func:ident, $ty:ty, $class:ident, $mov:literal) => { macro_rules! check_reg { ($func:ident, $ty:ty, $reg:tt, $mov:literal) => { #[no_mangle] pub unsafe fn $func(x: $ty) -> $ty { - dont_merge(stringify!(func)); + dont_merge(stringify!($func)); let y; asm!(concat!($mov, " ", $reg, ", ", $reg), lateout($reg) y, in($reg) x); @@ -124,3 +124,9 @@ check!(reg_f32, f32, freg, "ler"); // CHECK: ldr %f{{[0-9]+}}, %f{{[0-9]+}} // CHECK: #NO_APP check!(reg_f64, f64, freg, "ldr"); + +// CHECK-LABEL: reg_ptr: +// CHECK: #APP +// CHECK: lgr %r{{[0-9]+}}, %r{{[0-9]+}} +// CHECK: #NO_APP +check!(reg_ptr, ptr, reg, "lgr"); From 4d8d72f4f9cd971fce3965015d785ecedb256326 Mon Sep 17 00:00:00 2001 From: Roxane Date: Mon, 23 Aug 2021 22:41:03 -0400 Subject: [PATCH 15/22] Handle match with non axhaustive variants in closures --- compiler/rustc_typeck/src/expr_use_visitor.rs | 17 +++++- .../auxiliary/match_non_exhaustive_lib.rs | 10 ++++ .../non-exhaustive-match.rs | 54 +++++++++++++++++++ .../non-exhaustive-match.stderr | 50 +++++++++++++++++ 4 files changed, 129 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/closures/2229_closure_analysis/auxiliary/match_non_exhaustive_lib.rs create mode 100644 src/test/ui/closures/2229_closure_analysis/non-exhaustive-match.rs create mode 100644 src/test/ui/closures/2229_closure_analysis/non-exhaustive-match.stderr diff --git a/compiler/rustc_typeck/src/expr_use_visitor.rs b/compiler/rustc_typeck/src/expr_use_visitor.rs index 1d7852d964c1d..c5c758255f0aa 100644 --- a/compiler/rustc_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_typeck/src/expr_use_visitor.rs @@ -14,7 +14,7 @@ use rustc_index::vec::Idx; use rustc_infer::infer::InferCtxt; use rustc_middle::hir::place::ProjectionKind; use rustc_middle::mir::FakeReadCause; -use rustc_middle::ty::{self, adjustment, TyCtxt}; +use rustc_middle::ty::{self, adjustment, AdtKind, TyCtxt}; use rustc_target::abi::VariantIdx; use std::iter; @@ -262,7 +262,20 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { let place_ty = place.place.ty(); if let ty::Adt(def, _) = place_ty.kind() { - if def.variants.len() > 1 { + // Note that if a non-exhaustive SingleVariant is defined in another crate, we need + // to assume that more cases will be added to the variant in the future. This mean + // that we should handle non-exhaustive SingleVariant the same way we would handle + // a MultiVariant. + // If the variant is not local it must be defined in another crate. + let is_non_exhaustive = match def.adt_kind() { + AdtKind::Struct | AdtKind::Union => { + def.non_enum_variant().is_field_list_non_exhaustive() + } + AdtKind::Enum => def.is_variant_list_non_exhaustive(), + }; + if def.variants.len() > 1 + || (!def.did.is_local() && is_non_exhaustive) + { needs_to_be_read = true; } } diff --git a/src/test/ui/closures/2229_closure_analysis/auxiliary/match_non_exhaustive_lib.rs b/src/test/ui/closures/2229_closure_analysis/auxiliary/match_non_exhaustive_lib.rs new file mode 100644 index 0000000000000..4060c409355a1 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/auxiliary/match_non_exhaustive_lib.rs @@ -0,0 +1,10 @@ +#[non_exhaustive] +pub enum E1 {} + +#[non_exhaustive] +pub enum E2 { A, B } + +#[non_exhaustive] +pub enum E3 { C } + +pub enum E4 { D } diff --git a/src/test/ui/closures/2229_closure_analysis/non-exhaustive-match.rs b/src/test/ui/closures/2229_closure_analysis/non-exhaustive-match.rs new file mode 100644 index 0000000000000..318673ef847e5 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/non-exhaustive-match.rs @@ -0,0 +1,54 @@ +// edition:2021 + +// aux-build:match_non_exhaustive_lib.rs + +/* The error message for non-exhaustive matches on non-local enums + * marked as non-exhaustive should mention the fact that the enum + * is marked as non-exhaustive (issue #85227). + */ + +// Ignore non_exhaustive in the same crate +#[non_exhaustive] +enum L1 { A, B } +enum L2 { C } + +extern crate match_non_exhaustive_lib; +use match_non_exhaustive_lib::{E1, E2, E3, E4}; + +fn foo() -> (L1, L2) {todo!()} +fn bar() -> (E1, E2, E3, E4) {todo!()} + +fn main() { + let (l1, l2) = foo(); + // No error for enums defined in this crate + let _a = || { match l1 { L1::A => (), L1::B => () } }; + // (except if the match is already non-exhaustive) + let _b = || { match l1 { L1::A => () } }; + //~^ ERROR: non-exhaustive patterns: `B` not covered [E0004] + + // l2 should not be captured as it is a non-exhaustive SingleVariant + // defined in this crate + let _c = || { match l2 { L2::C => (), _ => () } }; + let mut mut_l2 = l2; + _c(); + + // E1 is not visibly uninhabited from here + let (e1, e2, e3, e4) = bar(); + let _d = || { match e1 {} }; + //~^ ERROR: non-exhaustive patterns: type `E1` is non-empty [E0004] + let _e = || { match e2 { E2::A => (), E2::B => () } }; + //~^ ERROR: non-exhaustive patterns: `_` not covered [E0004] + let _f = || { match e2 { E2::A => (), E2::B => (), _ => () } }; + + // e3 should be captured as it is a non-exhaustive SingleVariant + // defined in another crate + let _g = || { match e3 { E3::C => (), _ => () } }; + let mut mut_e3 = e3; + //~^ ERROR: cannot move out of `e3` because it is borrowed + _g(); + + // e4 should not be captured as it is a SingleVariant + let _h = || { match e4 { E4::D => (), _ => () } }; + let mut mut_e4 = e4; + _h(); +} diff --git a/src/test/ui/closures/2229_closure_analysis/non-exhaustive-match.stderr b/src/test/ui/closures/2229_closure_analysis/non-exhaustive-match.stderr new file mode 100644 index 0000000000000..91ffe1a47f413 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/non-exhaustive-match.stderr @@ -0,0 +1,50 @@ +error[E0004]: non-exhaustive patterns: `B` not covered + --> $DIR/non-exhaustive-match.rs:26:25 + | +LL | enum L1 { A, B } + | ---------------- + | | | + | | not covered + | `L1` defined here +... +LL | let _b = || { match l1 { L1::A => () } }; + | ^^ pattern `B` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + = note: the matched value is of type `L1` + +error[E0004]: non-exhaustive patterns: type `E1` is non-empty + --> $DIR/non-exhaustive-match.rs:37:25 + | +LL | let _d = || { match e1 {} }; + | ^^ + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + = note: the matched value is of type `E1`, which is marked as non-exhaustive + +error[E0004]: non-exhaustive patterns: `_` not covered + --> $DIR/non-exhaustive-match.rs:39:25 + | +LL | let _e = || { match e2 { E2::A => (), E2::B => () } }; + | ^^ pattern `_` not covered + | + = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms + = note: the matched value is of type `E2`, which is marked as non-exhaustive + +error[E0505]: cannot move out of `e3` because it is borrowed + --> $DIR/non-exhaustive-match.rs:46:22 + | +LL | let _g = || { match e3 { E3::C => (), _ => () } }; + | -- -- borrow occurs due to use in closure + | | + | borrow of `e3` occurs here +LL | let mut mut_e3 = e3; + | ^^ move out of `e3` occurs here +LL | +LL | _g(); + | -- borrow later used here + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0004, E0505. +For more information about an error, try `rustc --explain E0004`. From 1335b4cadd66b026be809bbc07f77eb477393043 Mon Sep 17 00:00:00 2001 From: Roxane Date: Mon, 23 Aug 2021 22:41:19 -0400 Subject: [PATCH 16/22] Add additional match test case --- .../2229_closure_analysis/match-edge-cases.rs | 35 +++++++++++++++++++ .../match-edge-cases.stderr | 17 +++++++++ 2 files changed, 52 insertions(+) create mode 100644 src/test/ui/closures/2229_closure_analysis/match-edge-cases.rs create mode 100644 src/test/ui/closures/2229_closure_analysis/match-edge-cases.stderr diff --git a/src/test/ui/closures/2229_closure_analysis/match-edge-cases.rs b/src/test/ui/closures/2229_closure_analysis/match-edge-cases.rs new file mode 100644 index 0000000000000..035c658302745 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match-edge-cases.rs @@ -0,0 +1,35 @@ +// edition:2021 + +enum SingleVariant { + A +} + +struct TestStruct { + x: i32, + y: i32, + z: i32, +} + +fn main() { + let sv = SingleVariant::A; + let condition = true; + // sv should not be captured as it is a SingleVariant + let _a = || { + match sv { + SingleVariant::A if condition => (), + _ => () + } + }; + let mut mut_sv = sv; + _a(); + + // ts should be captured + let ts = TestStruct { x: 1, y: 1, z: 1 }; + let _b = || { match ts { + TestStruct{ x: 1, .. } => (), + _ => () + }}; + let mut mut_ts = ts; + //~^ ERROR: cannot move out of `ts` because it is borrowed + _b(); +} diff --git a/src/test/ui/closures/2229_closure_analysis/match-edge-cases.stderr b/src/test/ui/closures/2229_closure_analysis/match-edge-cases.stderr new file mode 100644 index 0000000000000..b9d2316206ecb --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/match-edge-cases.stderr @@ -0,0 +1,17 @@ +error[E0505]: cannot move out of `ts` because it is borrowed + --> $DIR/match-edge-cases.rs:32:22 + | +LL | let _b = || { match ts { + | -- -- borrow occurs due to use in closure + | | + | borrow of `ts` occurs here +... +LL | let mut mut_ts = ts; + | ^^ move out of `ts` occurs here +LL | +LL | _b(); + | -- borrow later used here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0505`. From 68b1bfc9b2d93d778b61c63b6a22847c128fc964 Mon Sep 17 00:00:00 2001 From: Roxane Date: Mon, 23 Aug 2021 22:57:05 -0400 Subject: [PATCH 17/22] Create a specific match folder for match tests --- .../{ => match}/auxiliary/match_non_exhaustive_lib.rs | 0 .../ui/closures/2229_closure_analysis/{ => match}/issue-87097.rs | 0 .../closures/2229_closure_analysis/{ => match}/issue-87097.stderr | 0 .../ui/closures/2229_closure_analysis/{ => match}/issue-87426.rs | 0 .../2229_closure_analysis/{ => match}/match-edge-cases.rs | 0 .../2229_closure_analysis/{ => match}/match-edge-cases.stderr | 0 .../2229_closure_analysis/{ => match}/non-exhaustive-match.rs | 0 .../2229_closure_analysis/{ => match}/non-exhaustive-match.stderr | 0 .../{ => match}/pattern-matching-should-fail.rs | 0 .../{ => match}/pattern-matching-should-fail.stderr | 0 .../{ => match}/patterns-capture-analysis.rs | 0 .../{ => match}/patterns-capture-analysis.stderr | 0 12 files changed, 0 insertions(+), 0 deletions(-) rename src/test/ui/closures/2229_closure_analysis/{ => match}/auxiliary/match_non_exhaustive_lib.rs (100%) rename src/test/ui/closures/2229_closure_analysis/{ => match}/issue-87097.rs (100%) rename src/test/ui/closures/2229_closure_analysis/{ => match}/issue-87097.stderr (100%) rename src/test/ui/closures/2229_closure_analysis/{ => match}/issue-87426.rs (100%) rename src/test/ui/closures/2229_closure_analysis/{ => match}/match-edge-cases.rs (100%) rename src/test/ui/closures/2229_closure_analysis/{ => match}/match-edge-cases.stderr (100%) rename src/test/ui/closures/2229_closure_analysis/{ => match}/non-exhaustive-match.rs (100%) rename src/test/ui/closures/2229_closure_analysis/{ => match}/non-exhaustive-match.stderr (100%) rename src/test/ui/closures/2229_closure_analysis/{ => match}/pattern-matching-should-fail.rs (100%) rename src/test/ui/closures/2229_closure_analysis/{ => match}/pattern-matching-should-fail.stderr (100%) rename src/test/ui/closures/2229_closure_analysis/{ => match}/patterns-capture-analysis.rs (100%) rename src/test/ui/closures/2229_closure_analysis/{ => match}/patterns-capture-analysis.stderr (100%) diff --git a/src/test/ui/closures/2229_closure_analysis/auxiliary/match_non_exhaustive_lib.rs b/src/test/ui/closures/2229_closure_analysis/match/auxiliary/match_non_exhaustive_lib.rs similarity index 100% rename from src/test/ui/closures/2229_closure_analysis/auxiliary/match_non_exhaustive_lib.rs rename to src/test/ui/closures/2229_closure_analysis/match/auxiliary/match_non_exhaustive_lib.rs diff --git a/src/test/ui/closures/2229_closure_analysis/issue-87097.rs b/src/test/ui/closures/2229_closure_analysis/match/issue-87097.rs similarity index 100% rename from src/test/ui/closures/2229_closure_analysis/issue-87097.rs rename to src/test/ui/closures/2229_closure_analysis/match/issue-87097.rs diff --git a/src/test/ui/closures/2229_closure_analysis/issue-87097.stderr b/src/test/ui/closures/2229_closure_analysis/match/issue-87097.stderr similarity index 100% rename from src/test/ui/closures/2229_closure_analysis/issue-87097.stderr rename to src/test/ui/closures/2229_closure_analysis/match/issue-87097.stderr diff --git a/src/test/ui/closures/2229_closure_analysis/issue-87426.rs b/src/test/ui/closures/2229_closure_analysis/match/issue-87426.rs similarity index 100% rename from src/test/ui/closures/2229_closure_analysis/issue-87426.rs rename to src/test/ui/closures/2229_closure_analysis/match/issue-87426.rs diff --git a/src/test/ui/closures/2229_closure_analysis/match-edge-cases.rs b/src/test/ui/closures/2229_closure_analysis/match/match-edge-cases.rs similarity index 100% rename from src/test/ui/closures/2229_closure_analysis/match-edge-cases.rs rename to src/test/ui/closures/2229_closure_analysis/match/match-edge-cases.rs diff --git a/src/test/ui/closures/2229_closure_analysis/match-edge-cases.stderr b/src/test/ui/closures/2229_closure_analysis/match/match-edge-cases.stderr similarity index 100% rename from src/test/ui/closures/2229_closure_analysis/match-edge-cases.stderr rename to src/test/ui/closures/2229_closure_analysis/match/match-edge-cases.stderr diff --git a/src/test/ui/closures/2229_closure_analysis/non-exhaustive-match.rs b/src/test/ui/closures/2229_closure_analysis/match/non-exhaustive-match.rs similarity index 100% rename from src/test/ui/closures/2229_closure_analysis/non-exhaustive-match.rs rename to src/test/ui/closures/2229_closure_analysis/match/non-exhaustive-match.rs diff --git a/src/test/ui/closures/2229_closure_analysis/non-exhaustive-match.stderr b/src/test/ui/closures/2229_closure_analysis/match/non-exhaustive-match.stderr similarity index 100% rename from src/test/ui/closures/2229_closure_analysis/non-exhaustive-match.stderr rename to src/test/ui/closures/2229_closure_analysis/match/non-exhaustive-match.stderr diff --git a/src/test/ui/closures/2229_closure_analysis/pattern-matching-should-fail.rs b/src/test/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.rs similarity index 100% rename from src/test/ui/closures/2229_closure_analysis/pattern-matching-should-fail.rs rename to src/test/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.rs diff --git a/src/test/ui/closures/2229_closure_analysis/pattern-matching-should-fail.stderr b/src/test/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.stderr similarity index 100% rename from src/test/ui/closures/2229_closure_analysis/pattern-matching-should-fail.stderr rename to src/test/ui/closures/2229_closure_analysis/match/pattern-matching-should-fail.stderr diff --git a/src/test/ui/closures/2229_closure_analysis/patterns-capture-analysis.rs b/src/test/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.rs similarity index 100% rename from src/test/ui/closures/2229_closure_analysis/patterns-capture-analysis.rs rename to src/test/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.rs diff --git a/src/test/ui/closures/2229_closure_analysis/patterns-capture-analysis.stderr b/src/test/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr similarity index 100% rename from src/test/ui/closures/2229_closure_analysis/patterns-capture-analysis.stderr rename to src/test/ui/closures/2229_closure_analysis/match/patterns-capture-analysis.stderr From 4a9ba65ca9eaf9db3a010cbf5859b3fdf16ac687 Mon Sep 17 00:00:00 2001 From: linux1 Date: Tue, 24 Aug 2021 12:41:49 -0400 Subject: [PATCH 18/22] Feat: added explicit register tests; added prefix to check_reg asm string --- src/test/assembly/asm/s390x-types.rs | 38 +++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/src/test/assembly/asm/s390x-types.rs b/src/test/assembly/asm/s390x-types.rs index ec0515b20bdfb..69d9cab23c8ed 100644 --- a/src/test/assembly/asm/s390x-types.rs +++ b/src/test/assembly/asm/s390x-types.rs @@ -65,7 +65,7 @@ macro_rules! check_reg { ($func:ident, $ty:ty, $reg:tt, $mov:literal) => { dont_merge(stringify!($func)); let y; - asm!(concat!($mov, " ", $reg, ", ", $reg), lateout($reg) y, in($reg) x); + asm!(concat!($mov, " %", $reg, ", %", $reg), lateout($reg) y, in($reg) x); y } };} @@ -130,3 +130,39 @@ check!(reg_f64, f64, freg, "ldr"); // CHECK: lgr %r{{[0-9]+}}, %r{{[0-9]+}} // CHECK: #NO_APP check!(reg_ptr, ptr, reg, "lgr"); + +// CHECK-LABEL: r0_i8: +// CHECK: #APP +// CHECK: lr %r0, %r0 +// CHECK: #NO_APP +check_reg!(r0_i8, i8, "r0", "lr"); + +// CHECK-LABEL: r0_i16: +// CHECK: #APP +// CHECK: lr %r0, %r0 +// CHECK: #NO_APP +check_reg!(r0_i16, i16, "r0", "lr"); + +// CHECK-LABEL: r0_i32: +// CHECK: #APP +// CHECK: lr %r0, %r0 +// CHECK: #NO_APP +check_reg!(r0_i32, i32, "r0", "lr"); + +// CHECK-LABEL: r0_i64: +// CHECK: #APP +// CHECK: lr %r0, %r0 +// CHECK: #NO_APP +check_reg!(r0_i64, i64, "r0", "lr"); + +// CHECK-LABEL: f0_f32: +// CHECK: #APP +// CHECK: ler %f0, %f0 +// CHECK: #NO_APP +check_reg!(f0_f32, f32, "f0", "ler"); + +// CHECK-LABEL: f0_f64: +// CHECK: #APP +// CHECK: ldr %f0, %f0 +// CHECK: #NO_APP +check_reg!(f0_f64, f64, "f0", "ldr"); From 4fcae2c89113e0767ee066a42f418261cebdc4bd Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 25 Aug 2021 20:32:31 -0300 Subject: [PATCH 19/22] Add const and static TAIT tests --- .../static-const-types.rs | 16 +++++++++ .../static-const-types.stderr | 33 +++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 src/test/ui/type-alias-impl-trait/static-const-types.rs create mode 100644 src/test/ui/type-alias-impl-trait/static-const-types.stderr diff --git a/src/test/ui/type-alias-impl-trait/static-const-types.rs b/src/test/ui/type-alias-impl-trait/static-const-types.rs new file mode 100644 index 0000000000000..f630d27833503 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/static-const-types.rs @@ -0,0 +1,16 @@ +#![feature(type_alias_impl_trait)] +#![allow(dead_code)] + +// FIXME: This should compile, but it currently doesn't + +use std::fmt::Debug; + +type Foo = impl Debug; +//~^ ERROR: could not find defining uses + +static FOO1: Foo = 22_u32; +//~^ ERROR: mismatched types [E0308] +const FOO2: Foo = 22_u32; +//~^ ERROR: mismatched types [E0308] + +fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/static-const-types.stderr b/src/test/ui/type-alias-impl-trait/static-const-types.stderr new file mode 100644 index 0000000000000..72083d014fe3a --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/static-const-types.stderr @@ -0,0 +1,33 @@ +error[E0308]: mismatched types + --> $DIR/static-const-types.rs:11:20 + | +LL | type Foo = impl Debug; + | ---------- the expected opaque type +... +LL | static FOO1: Foo = 22_u32; + | ^^^^^^ expected opaque type, found `u32` + | + = note: expected opaque type `impl Debug` + found type `u32` + +error[E0308]: mismatched types + --> $DIR/static-const-types.rs:13:19 + | +LL | type Foo = impl Debug; + | ---------- the expected opaque type +... +LL | const FOO2: Foo = 22_u32; + | ^^^^^^ expected opaque type, found `u32` + | + = note: expected opaque type `impl Debug` + found type `u32` + +error: could not find defining uses + --> $DIR/static-const-types.rs:8:12 + | +LL | type Foo = impl Debug; + | ^^^^^^^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`. From bee13d18af34ce6056a0b76fb7652cafda52cb69 Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 26 Aug 2021 12:57:42 +0200 Subject: [PATCH 20/22] add unsized coercion test --- .../unsized/param-mentioned-by-different-field.rs | 10 ++++++++++ .../param-mentioned-by-different-field.stderr | 14 ++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 src/test/ui/unsized/param-mentioned-by-different-field.rs create mode 100644 src/test/ui/unsized/param-mentioned-by-different-field.stderr diff --git a/src/test/ui/unsized/param-mentioned-by-different-field.rs b/src/test/ui/unsized/param-mentioned-by-different-field.rs new file mode 100644 index 0000000000000..cda94b306d333 --- /dev/null +++ b/src/test/ui/unsized/param-mentioned-by-different-field.rs @@ -0,0 +1,10 @@ +// We must not allow this with our current setup as `T` +// is mentioned both in the tail of `Foo` and by another +// field. +struct Foo(Box, T); + +fn main() { + let x: Foo<[u8; 1]> = Foo(Box::new([2]), [3]); + let y: &Foo<[u8]> = &x; //~ ERROR mismatched types + assert_eq!(y.0.len(), 1); +} diff --git a/src/test/ui/unsized/param-mentioned-by-different-field.stderr b/src/test/ui/unsized/param-mentioned-by-different-field.stderr new file mode 100644 index 0000000000000..d18fa6456f3ee --- /dev/null +++ b/src/test/ui/unsized/param-mentioned-by-different-field.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/param-mentioned-by-different-field.rs:8:25 + | +LL | let y: &Foo<[u8]> = &x; + | ---------- ^^ expected slice `[u8]`, found array `[u8; 1]` + | | + | expected due to this + | + = note: expected reference `&Foo<[u8]>` + found reference `&Foo<[u8; 1]>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. From 97bf80dfda3627175b21bade3ba8e51b512c2186 Mon Sep 17 00:00:00 2001 From: jackh726 Date: Tue, 24 Aug 2021 20:50:09 -0400 Subject: [PATCH 21/22] Treat types in unnormalized function signatures as well-formed --- .../type_check/free_region_relations.rs | 19 ++++++++++-- .../rustc_typeck/src/check/compare_method.rs | 12 +++++++- compiler/rustc_typeck/src/check/mod.rs | 16 +++++++--- compiler/rustc_typeck/src/check/regionck.rs | 11 ++++++- compiler/rustc_typeck/src/check/wfcheck.rs | 11 ++++++- .../generic-associated-types/issue-87748.rs | 30 +++++++++++++++++++ 6 files changed, 90 insertions(+), 9 deletions(-) create mode 100644 src/test/ui/generic-associated-types/issue-87748.rs diff --git a/compiler/rustc_mir/src/borrow_check/type_check/free_region_relations.rs b/compiler/rustc_mir/src/borrow_check/type_check/free_region_relations.rs index 012d67255d13b..6426098d843fe 100644 --- a/compiler/rustc_mir/src/borrow_check/type_check/free_region_relations.rs +++ b/compiler/rustc_mir/src/borrow_check/type_check/free_region_relations.rs @@ -256,6 +256,9 @@ impl UniversalRegionRelationsBuilder<'cx, 'tcx> { let constraint_sets: Vec<_> = unnormalized_input_output_tys .flat_map(|ty| { debug!("build: input_or_output={:?}", ty); + // We add implied bounds from both the unnormalized and normalized ty + // See issue #87748 + let constraints_implied_1 = self.add_implied_bounds(ty); let TypeOpOutput { output: ty, constraints: constraints1, .. } = self .param_env .and(type_op::normalize::Normalize::new(ty)) @@ -271,9 +274,21 @@ impl UniversalRegionRelationsBuilder<'cx, 'tcx> { canonicalized_query: None, } }); - let constraints2 = self.add_implied_bounds(ty); + // Note: we need this in examples like + // ``` + // trait Foo { + // type Bar; + // fn foo(&self) -> &Self::Bar; + // } + // impl Foo for () { + // type Bar = (); + // fn foo(&self) ->&() {} + // } + // ``` + // Both &Self::Bar and &() are WF + let constraints_implied_2 = self.add_implied_bounds(ty); normalized_inputs_and_output.push(ty); - constraints1.into_iter().chain(constraints2) + constraints1.into_iter().chain(constraints_implied_1).chain(constraints_implied_2) }) .collect(); diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index c384e0dcb2cae..d59291b8fd493 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -250,6 +250,8 @@ fn compare_predicate_entailment<'tcx>( // Compute placeholder form of impl and trait method tys. let tcx = infcx.tcx; + let mut wf_tys = vec![]; + let (impl_sig, _) = infcx.replace_bound_vars_with_fresh_vars( impl_m_span, infer::HigherRankedType, @@ -260,10 +262,18 @@ fn compare_predicate_entailment<'tcx>( let impl_fty = tcx.mk_fn_ptr(ty::Binder::dummy(impl_sig)); debug!("compare_impl_method: impl_fty={:?}", impl_fty); + // First liberate late bound regions and subst placeholders let trait_sig = tcx.liberate_late_bound_regions(impl_m.def_id, tcx.fn_sig(trait_m.def_id)); let trait_sig = trait_sig.subst(tcx, trait_to_placeholder_substs); + // Next, add all inputs and output as well-formed tys. Importantly, + // we have to do this before normalization, since the normalized ty may + // not contain the input parameters. See issue #87748. + wf_tys.extend(trait_sig.inputs_and_output.iter()); let trait_sig = inh.normalize_associated_types_in(impl_m_span, impl_m_hir_id, param_env, trait_sig); + // Also add the resulting inputs and output as well-formed. + // This probably isn't strictly necessary. + wf_tys.extend(trait_sig.inputs_and_output.iter()); let trait_fty = tcx.mk_fn_ptr(ty::Binder::dummy(trait_sig)); debug!("compare_impl_method: trait_fty={:?}", trait_fty); @@ -388,7 +398,7 @@ fn compare_predicate_entailment<'tcx>( // Finally, resolve all regions. This catches wily misuses of // lifetime parameters. let fcx = FnCtxt::new(&inh, param_env, impl_m_hir_id); - fcx.regionck_item(impl_m_hir_id, impl_m_span, trait_sig.inputs_and_output); + fcx.regionck_item(impl_m_hir_id, impl_m_span, &wf_tys); Ok(()) }) diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs index a88b1c7af5a96..803c440bbc98b 100644 --- a/compiler/rustc_typeck/src/check/mod.rs +++ b/compiler/rustc_typeck/src/check/mod.rs @@ -364,7 +364,7 @@ fn typeck_with_fallback<'tcx>( let typeck_results = Inherited::build(tcx, def_id).enter(|inh| { let param_env = tcx.param_env(def_id); - let fcx = if let Some(hir::FnSig { header, decl, .. }) = fn_sig { + let (fcx, wf_tys) = if let Some(hir::FnSig { header, decl, .. }) = fn_sig { let fn_sig = if crate::collect::get_infer_ret_ty(&decl.output).is_some() { let fcx = FnCtxt::new(&inh, param_env, body.value.hir_id); >::ty_of_fn( @@ -383,17 +383,25 @@ fn typeck_with_fallback<'tcx>( check_abi(tcx, id, span, fn_sig.abi()); + // When normalizing the function signature, we assume all types are + // well-formed. So, we don't need to worry about the obligations + // from normalization. We could just discard these, but to align with + // compare_method and elsewhere, we just add implied bounds for + // these types. + let mut wf_tys = vec![]; // Compute the fty from point of view of inside the fn. let fn_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), fn_sig); + wf_tys.extend(fn_sig.inputs_and_output.iter()); let fn_sig = inh.normalize_associated_types_in( body.value.span, body_id.hir_id, param_env, fn_sig, ); + wf_tys.extend(fn_sig.inputs_and_output.iter()); let fcx = check_fn(&inh, param_env, fn_sig, decl, id, body, None, true).0; - fcx + (fcx, wf_tys) } else { let fcx = FnCtxt::new(&inh, param_env, body.value.hir_id); let expected_type = body_ty @@ -443,7 +451,7 @@ fn typeck_with_fallback<'tcx>( fcx.write_ty(id, expected_type); - fcx + (fcx, vec![]) }; let fallback_has_occurred = fcx.type_inference_fallback(); @@ -467,7 +475,7 @@ fn typeck_with_fallback<'tcx>( fcx.select_all_obligations_or_error(); if fn_sig.is_some() { - fcx.regionck_fn(id, body); + fcx.regionck_fn(id, body, span, &wf_tys); } else { fcx.regionck_expr(body); } diff --git a/compiler/rustc_typeck/src/check/regionck.rs b/compiler/rustc_typeck/src/check/regionck.rs index ca6828cfdf68d..290fa5fc36719 100644 --- a/compiler/rustc_typeck/src/check/regionck.rs +++ b/compiler/rustc_typeck/src/check/regionck.rs @@ -144,11 +144,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// rest of type check and because sometimes we need type /// inference to have completed before we can determine which /// constraints to add. - pub fn regionck_fn(&self, fn_id: hir::HirId, body: &'tcx hir::Body<'tcx>) { + pub(crate) fn regionck_fn( + &self, + fn_id: hir::HirId, + body: &'tcx hir::Body<'tcx>, + span: Span, + wf_tys: &[Ty<'tcx>], + ) { debug!("regionck_fn(id={})", fn_id); let subject = self.tcx.hir().body_owner_def_id(body.id()); let hir_id = body.value.hir_id; let mut rcx = RegionCtxt::new(self, hir_id, Subject(subject), self.param_env); + // We need to add the implied bounds from the function signature + rcx.outlives_environment.add_implied_bounds(self, wf_tys, fn_id, span); + rcx.outlives_environment.save_implied_bounds(fn_id); if !self.errors_reported_since_creation() { // regionck assumes typeck succeeded diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index b824370965928..0ac265396e3d0 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -908,6 +908,7 @@ fn check_where_clauses<'tcx, 'fcx>( } } +#[tracing::instrument(level = "debug", skip(fcx, span, hir_decl))] fn check_fn_or_method<'fcx, 'tcx>( fcx: &FnCtxt<'fcx, 'tcx>, span: Span, @@ -918,6 +919,11 @@ fn check_fn_or_method<'fcx, 'tcx>( ) { let sig = fcx.tcx.liberate_late_bound_regions(def_id, sig); + // Unnormalized types in signature are WF too + implied_bounds.extend(sig.inputs()); + // FIXME(#27579) return types should not be implied bounds + implied_bounds.push(sig.output()); + // Normalize the input and output types one at a time, using a different // `WellFormedLoc` for each. We cannot call `normalize_associated_types` // on the entire `FnSig`, since this would use the same `WellFormedLoc` @@ -967,9 +973,11 @@ fn check_fn_or_method<'fcx, 'tcx>( ObligationCauseCode::ReturnType, ); - // FIXME(#25759) return types should not be implied bounds + // FIXME(#27579) return types should not be implied bounds implied_bounds.push(sig.output()); + debug!(?implied_bounds); + check_where_clauses(fcx, span, def_id, Some((sig.output(), hir_decl.output.span()))); } @@ -1116,6 +1124,7 @@ const HELP_FOR_SELF_TYPE: &str = "consider changing to `self`, `&self`, `&mut se `self: Rc`, `self: Arc`, or `self: Pin

` (where P is one \ of the previous types except `Self`)"; +#[tracing::instrument(level = "debug", skip(fcx))] fn check_method_receiver<'fcx, 'tcx>( fcx: &FnCtxt<'fcx, 'tcx>, fn_sig: &hir::FnSig<'_>, diff --git a/src/test/ui/generic-associated-types/issue-87748.rs b/src/test/ui/generic-associated-types/issue-87748.rs new file mode 100644 index 0000000000000..93c3b3937cb81 --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-87748.rs @@ -0,0 +1,30 @@ +// Checks that we properly add implied bounds from unnormalized projections in +// inputs when typechecking functions. + +// check-pass + +#![feature(generic_associated_types)] + +trait MyTrait { + type Assoc<'a, 'b> where 'b: 'a; + fn do_sth(arg: Self::Assoc<'_, '_>); +} + +struct A; +struct B; +struct C; + +impl MyTrait for A { + type Assoc<'a, 'b> where 'b: 'a = u32; + fn do_sth(_: u32) {} +} +impl MyTrait for B { + type Assoc<'a, 'b> where 'b: 'a = u32; + fn do_sth(_: Self::Assoc<'_, '_>) {} +} +impl MyTrait for C { + type Assoc<'a, 'b> where 'b: 'a = u32; + fn do_sth(_: Self::Assoc<'static, 'static>) {} +} + +fn main () {} From 2899c4558ecc21d7e911ae5eabf7300577cc5913 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Fri, 20 Aug 2021 16:25:39 -0400 Subject: [PATCH 22/22] Don't allow both the `+bundle` and `+whole-archive` modifiers for rlibs --- compiler/rustc_codegen_ssa/src/back/link.rs | 14 ++++++++++++++ .../mix-bundle-and-whole-archive-link-attr.rs | 12 ++++++++++++ .../mix-bundle-and-whole-archive-link-attr.stderr | 6 ++++++ .../mix-bundle-and-whole-archive.rs | 7 +++++++ .../mix-bundle-and-whole-archive.stderr | 6 ++++++ 5 files changed, 45 insertions(+) create mode 100644 src/test/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.rs create mode 100644 src/test/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.stderr create mode 100644 src/test/ui/native-library-link-flags/mix-bundle-and-whole-archive.rs create mode 100644 src/test/ui/native-library-link-flags/mix-bundle-and-whole-archive.stderr diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 7228ca3b42316..408b9e6af9ebe 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -255,6 +255,19 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>( // metadata of the rlib we're generating somehow. for lib in codegen_results.crate_info.used_libraries.iter() { match lib.kind { + NativeLibKind::Static { bundle: None | Some(true), whole_archive: Some(true) } + if flavor == RlibFlavor::Normal => + { + // Don't allow mixing +bundle with +whole_archive since an rlib may contain + // multiple native libs, some of which are +whole-archive and some of which are + // -whole-archive and it isn't clear how we can currently handle such a + // situation correctly. + // See https://github.com/rust-lang/rust/issues/88085#issuecomment-901050897 + sess.err( + "the linking modifiers `+bundle` and `+whole-archive` are not compatible \ + with each other when generating rlibs", + ); + } NativeLibKind::Static { bundle: None | Some(true), .. } => {} NativeLibKind::Static { bundle: Some(false), .. } | NativeLibKind::Dylib { .. } @@ -1223,6 +1236,7 @@ pub fn archive_search_paths(sess: &Session) -> Vec { sess.target_filesearch(PathKind::Native).search_path_dirs() } +#[derive(PartialEq)] enum RlibFlavor { Normal, StaticlibBase, diff --git a/src/test/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.rs b/src/test/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.rs new file mode 100644 index 0000000000000..c3714a3845180 --- /dev/null +++ b/src/test/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.rs @@ -0,0 +1,12 @@ +// compile-flags: -Zunstable-options --crate-type rlib +// build-fail +// error-pattern: the linking modifiers `+bundle` and `+whole-archive` are not compatible with each other when generating rlibs + +#![feature(native_link_modifiers)] +#![feature(native_link_modifiers_bundle)] +#![feature(native_link_modifiers_whole_archive)] + +#[link(name = "mylib", kind = "static", modifiers = "+bundle,+whole-archive")] +extern "C" { } + +fn main() { } diff --git a/src/test/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.stderr b/src/test/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.stderr new file mode 100644 index 0000000000000..246efb8d627cb --- /dev/null +++ b/src/test/ui/native-library-link-flags/mix-bundle-and-whole-archive-link-attr.stderr @@ -0,0 +1,6 @@ +error: the linking modifiers `+bundle` and `+whole-archive` are not compatible with each other when generating rlibs + +error: could not find native static library `mylib`, perhaps an -L flag is missing? + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/native-library-link-flags/mix-bundle-and-whole-archive.rs b/src/test/ui/native-library-link-flags/mix-bundle-and-whole-archive.rs new file mode 100644 index 0000000000000..1d0768d99cffd --- /dev/null +++ b/src/test/ui/native-library-link-flags/mix-bundle-and-whole-archive.rs @@ -0,0 +1,7 @@ +// Mixing +bundle and +whole-archive is not allowed + +// compile-flags: -l static:+bundle,+whole-archive=mylib -Zunstable-options --crate-type rlib +// build-fail +// error-pattern: the linking modifiers `+bundle` and `+whole-archive` are not compatible with each other when generating rlibs + +fn main() { } diff --git a/src/test/ui/native-library-link-flags/mix-bundle-and-whole-archive.stderr b/src/test/ui/native-library-link-flags/mix-bundle-and-whole-archive.stderr new file mode 100644 index 0000000000000..246efb8d627cb --- /dev/null +++ b/src/test/ui/native-library-link-flags/mix-bundle-and-whole-archive.stderr @@ -0,0 +1,6 @@ +error: the linking modifiers `+bundle` and `+whole-archive` are not compatible with each other when generating rlibs + +error: could not find native static library `mylib`, perhaps an -L flag is missing? + +error: aborting due to 2 previous errors +