From 621be609b5b54b818e8b496023a10784ea9cbb8a Mon Sep 17 00:00:00 2001 From: Seth Pellegrino Date: Tue, 23 May 2023 15:08:23 -0700 Subject: [PATCH 01/11] feat: `riscv-interrupt-{m,s}` calling conventions Similar to prior support added for the mips430, avr, and x86 targets this change implements the rough equivalent of clang's [`__attribute__((interrupt))`][clang-attr] for riscv targets, enabling e.g. ```rust static mut CNT: usize = 0; pub extern "riscv-interrupt-m" fn isr_m() { unsafe { CNT += 1; } } ``` to produce highly effective assembly like: ```asm pub extern "riscv-interrupt-m" fn isr_m() { 420003a0: 1141 addi sp,sp,-16 unsafe { CNT += 1; 420003a2: c62a sw a0,12(sp) 420003a4: c42e sw a1,8(sp) 420003a6: 3fc80537 lui a0,0x3fc80 420003aa: 63c52583 lw a1,1596(a0) # 3fc8063c <_ZN12esp_riscv_rt3CNT17hcec3e3a214887d53E.0> 420003ae: 0585 addi a1,a1,1 420003b0: 62b52e23 sw a1,1596(a0) } } 420003b4: 4532 lw a0,12(sp) 420003b6: 45a2 lw a1,8(sp) 420003b8: 0141 addi sp,sp,16 420003ba: 30200073 mret ``` (disassembly via `riscv64-unknown-elf-objdump -C -S --disassemble ./esp32c3-hal/target/riscv32imc-unknown-none-elf/release/examples/gpio_interrupt`) This outcome is superior to hand-coded interrupt routines which, lacking visibility into any non-assembly body of the interrupt handler, have to be very conservative and save the [entire CPU state to the stack frame][full-frame-save]. By instead asking LLVM to only save the registers that it uses, we defer the decision to the tool with the best context: it can more accurately account for the cost of spills if it knows that every additional register used is already at the cost of an implicit spill. At the LLVM level, this is apparently [implemented by] marking every register as "[callee-save]," matching the semantics of an interrupt handler nicely (it has to leave the CPU state just as it found it after its `{m|s}ret`). This approach is not suitable for every interrupt handler, as it makes no attempt to e.g. save the state in a user-accessible stack frame. For a full discussion of those challenges and tradeoffs, please refer to [the interrupt calling conventions RFC][rfc]. Inside rustc, this implementation differs from prior art because LLVM does not expose the "all-saved" function flavor as a calling convention directly, instead preferring to use an attribute that allows for differentiating between "machine-mode" and "superivsor-mode" interrupts. Finally, some effort has been made to guide those who may not yet be aware of the differences between machine-mode and supervisor-mode interrupts as to why no `riscv-interrupt` calling convention is exposed through rustc, and similarly for why `riscv-interrupt-u` makes no appearance (as it would complicate future LLVM upgrades). [clang-attr]: https://clang.llvm.org/docs/AttributeReference.html#interrupt-risc-v [full-frame-save]: https://github.com/esp-rs/esp-riscv-rt/blob/9281af2ecffe13e40992917316f36920c26acaf3/src/lib.rs#L440-L469 [implemented by]: https://github.com/llvm/llvm-project/blob/b7fb2a3fec7c187d58a6d338ab512d9173bca987/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp#L61-L67 [callee-save]: https://github.com/llvm/llvm-project/blob/973f1fe7a8591c7af148e573491ab68cc15b6ecf/llvm/lib/Target/RISCV/RISCVCallingConv.td#L30-L37 [rfc]: https://github.com/rust-lang/rfcs/pull/3246 --- src/abi/mod.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/abi/mod.rs b/src/abi/mod.rs index 2c038f22ca99b..b7f56a2986cfc 100644 --- a/src/abi/mod.rs +++ b/src/abi/mod.rs @@ -48,7 +48,9 @@ pub(crate) fn conv_to_call_conv(sess: &Session, c: Conv, default_call_conv: Call default_call_conv } - Conv::X86Intr => sess.fatal("x86-interrupt call conv not yet implemented"), + Conv::X86Intr | Conv::RiscvInterrupt { .. } => { + sess.fatal(format!("interrupt call conv {c:?} not yet implemented")) + } Conv::ArmAapcs => sess.fatal("aapcs call conv not yet implemented"), Conv::CCmseNonSecureCall => { From b1072412189eb27934ada08a13805fc5d3ce8f25 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Tue, 8 Aug 2023 18:28:20 +0800 Subject: [PATCH 02/11] rustc: Move `crate_types` from `Session` to `GlobalCtxt` Removes a piece of mutable state. Follow up to #114578. --- src/driver/jit.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/driver/jit.rs b/src/driver/jit.rs index 3ea3884214805..1c606494f383e 100644 --- a/src/driver/jit.rs +++ b/src/driver/jit.rs @@ -98,7 +98,7 @@ pub(crate) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! { tcx.sess.fatal("JIT mode doesn't work with `cargo check`"); } - if !tcx.sess.crate_types().contains(&rustc_session::config::CrateType::Executable) { + if !tcx.crate_types().contains(&rustc_session::config::CrateType::Executable) { tcx.sess.fatal("can't jit non-executable crate"); } From c4948dc37f9863aa45fda35f705a83c3744b073b Mon Sep 17 00:00:00 2001 From: dirreke Date: Mon, 14 Aug 2023 22:57:38 +0800 Subject: [PATCH 03/11] Upgrade Object and related deps --- Cargo.lock | 38 +++++++++++++++++++++++++++++++------- Cargo.toml | 4 ++-- 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index af8e43da4eafe..7d18679c68165 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -71,7 +71,7 @@ dependencies = [ "cranelift-control", "cranelift-entity", "cranelift-isle", - "gimli", + "gimli 0.27.2", "hashbrown 0.13.2", "log", "regalloc2", @@ -180,7 +180,7 @@ dependencies = [ "cranelift-control", "cranelift-module", "log", - "object", + "object 0.30.4", "target-lexicon", ] @@ -195,9 +195,9 @@ dependencies = [ [[package]] name = "equivalent" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88bffebc5d80432c9b140ee17875ff173a8ab62faad5b257da912bd2f6c1c0a1" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "fallible-iterator" @@ -216,6 +216,15 @@ dependencies = [ "stable_deref_trait", ] +[[package]] +name = "gimli" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" +dependencies = [ + "indexmap 2.0.0", +] + [[package]] name = "hashbrown" version = "0.12.3" @@ -236,6 +245,9 @@ name = "hashbrown" version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" +dependencies = [ + "ahash", +] [[package]] name = "indexmap" @@ -309,6 +321,18 @@ dependencies = [ "memchr", ] +[[package]] +name = "object" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ac5bbd07aea88c60a577a1ce218075ffd59208b2d7ca97adf9bfc5aeb21ebe" +dependencies = [ + "crc32fast", + "hashbrown 0.14.0", + "indexmap 2.0.0", + "memchr", +] + [[package]] name = "once_cell" version = "1.16.0" @@ -356,10 +380,10 @@ dependencies = [ "cranelift-module", "cranelift-native", "cranelift-object", - "gimli", - "indexmap 2.0.0", + "gimli 0.28.0", + "indexmap 1.9.3", "libloading", - "object", + "object 0.32.0", "smallvec", "target-lexicon", ] diff --git a/Cargo.toml b/Cargo.toml index 8ded81d7399b5..2c87d2600065a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,8 +15,8 @@ cranelift-native = { version = "0.98" } cranelift-jit = { version = "0.98", optional = true } cranelift-object = { version = "0.98" } target-lexicon = "0.12.0" -gimli = { version = "0.27.2", default-features = false, features = ["write"]} -object = { version = "0.30.3", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } +gimli = { version = "0.28.0", default-features = false, features = ["write"]} +object = { version = "0.32.0", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } indexmap = "2.0.0" libloading = { version = "0.7.3", optional = true } From 9ef3a4ff0e94e4e877a87b3497e582c89941deb1 Mon Sep 17 00:00:00 2001 From: dirreke Date: Mon, 14 Aug 2023 23:22:19 +0800 Subject: [PATCH 04/11] Update Cargo.lock --- Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 7d18679c68165..64ee5207b0184 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -381,7 +381,7 @@ dependencies = [ "cranelift-native", "cranelift-object", "gimli 0.28.0", - "indexmap 1.9.3", + "indexmap 2.0.0", "libloading", "object 0.32.0", "smallvec", From 0b283557e73f89c52b4a6965506f23379fd6e834 Mon Sep 17 00:00:00 2001 From: dirreke Date: Tue, 15 Aug 2023 00:03:27 +0800 Subject: [PATCH 05/11] reverse change in rustc_codegen_cranelift --- Cargo.lock | 36 ++++++------------------------------ Cargo.toml | 4 ++-- 2 files changed, 8 insertions(+), 32 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 64ee5207b0184..af8e43da4eafe 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -71,7 +71,7 @@ dependencies = [ "cranelift-control", "cranelift-entity", "cranelift-isle", - "gimli 0.27.2", + "gimli", "hashbrown 0.13.2", "log", "regalloc2", @@ -180,7 +180,7 @@ dependencies = [ "cranelift-control", "cranelift-module", "log", - "object 0.30.4", + "object", "target-lexicon", ] @@ -195,9 +195,9 @@ dependencies = [ [[package]] name = "equivalent" -version = "1.0.1" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +checksum = "88bffebc5d80432c9b140ee17875ff173a8ab62faad5b257da912bd2f6c1c0a1" [[package]] name = "fallible-iterator" @@ -216,15 +216,6 @@ dependencies = [ "stable_deref_trait", ] -[[package]] -name = "gimli" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" -dependencies = [ - "indexmap 2.0.0", -] - [[package]] name = "hashbrown" version = "0.12.3" @@ -245,9 +236,6 @@ name = "hashbrown" version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" -dependencies = [ - "ahash", -] [[package]] name = "indexmap" @@ -321,18 +309,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "object" -version = "0.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ac5bbd07aea88c60a577a1ce218075ffd59208b2d7ca97adf9bfc5aeb21ebe" -dependencies = [ - "crc32fast", - "hashbrown 0.14.0", - "indexmap 2.0.0", - "memchr", -] - [[package]] name = "once_cell" version = "1.16.0" @@ -380,10 +356,10 @@ dependencies = [ "cranelift-module", "cranelift-native", "cranelift-object", - "gimli 0.28.0", + "gimli", "indexmap 2.0.0", "libloading", - "object 0.32.0", + "object", "smallvec", "target-lexicon", ] diff --git a/Cargo.toml b/Cargo.toml index 2c87d2600065a..768d9df165242 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,8 +15,8 @@ cranelift-native = { version = "0.98" } cranelift-jit = { version = "0.98", optional = true } cranelift-object = { version = "0.98" } target-lexicon = "0.12.0" -gimli = { version = "0.28.0", default-features = false, features = ["write"]} -object = { version = "0.32.0", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } +gimli = { version = "0.27.2", default-features = false, features = ["write"]} +object = { version = "0.30.4", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } indexmap = "2.0.0" libloading = { version = "0.7.3", optional = true } From 8c6590a99b7def859208644da23238fdc7a8d9f3 Mon Sep 17 00:00:00 2001 From: dirreke Date: Tue, 15 Aug 2023 00:09:20 +0800 Subject: [PATCH 06/11] reverse change in rustc_codegen_cranelift --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 768d9df165242..8ded81d7399b5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,7 @@ cranelift-jit = { version = "0.98", optional = true } cranelift-object = { version = "0.98" } target-lexicon = "0.12.0" gimli = { version = "0.27.2", default-features = false, features = ["write"]} -object = { version = "0.30.4", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } +object = { version = "0.30.3", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } indexmap = "2.0.0" libloading = { version = "0.7.3", optional = true } From 18658cb0c9320d5a028246562ed40663ea72371b Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 19 Aug 2023 13:10:25 +0200 Subject: [PATCH 07/11] give some unwind-related terminators a more clear name --- src/base.rs | 4 ++-- src/constant.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/base.rs b/src/base.rs index 522dd7189fe63..ed371a04c5370 100644 --- a/src/base.rs +++ b/src/base.rs @@ -474,10 +474,10 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { *destination, ); } - TerminatorKind::Terminate => { + TerminatorKind::UnwindTerminate => { codegen_panic_cannot_unwind(fx, source_info); } - TerminatorKind::Resume => { + TerminatorKind::UnwindResume => { // FIXME implement unwinding fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); } diff --git a/src/constant.rs b/src/constant.rs index c31535742957c..7db5f79eead9e 100644 --- a/src/constant.rs +++ b/src/constant.rs @@ -550,8 +550,8 @@ pub(crate) fn mir_operand_get_const_val<'tcx>( match &bb_data.terminator().kind { TerminatorKind::Goto { .. } | TerminatorKind::SwitchInt { .. } - | TerminatorKind::Resume - | TerminatorKind::Terminate + | TerminatorKind::UnwindResume + | TerminatorKind::UnwindTerminate | TerminatorKind::Return | TerminatorKind::Unreachable | TerminatorKind::Drop { .. } From 3f4145e169f73392c3f5d0d8acf8840b2e8fc189 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 21 Aug 2023 09:57:10 +0200 Subject: [PATCH 08/11] when terminating during unwinding, show the reason why --- src/base.rs | 9 +++++---- src/constant.rs | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/base.rs b/src/base.rs index ed371a04c5370..9159bc3698755 100644 --- a/src/base.rs +++ b/src/base.rs @@ -474,8 +474,8 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { *destination, ); } - TerminatorKind::UnwindTerminate => { - codegen_panic_cannot_unwind(fx, source_info); + TerminatorKind::UnwindTerminate(reason) => { + codegen_unwind_terminate(fx, source_info, *reason); } TerminatorKind::UnwindResume => { // FIXME implement unwinding @@ -971,13 +971,14 @@ pub(crate) fn codegen_panic_nounwind<'tcx>( codegen_panic_inner(fx, rustc_hir::LangItem::PanicNounwind, &args, source_info.span); } -pub(crate) fn codegen_panic_cannot_unwind<'tcx>( +pub(crate) fn codegen_unwind_terminate<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, source_info: mir::SourceInfo, + reason: UnwindTerminateReason, ) { let args = []; - codegen_panic_inner(fx, rustc_hir::LangItem::PanicCannotUnwind, &args, source_info.span); + codegen_panic_inner(fx, reason.lang_item(), &args, source_info.span); } fn codegen_panic_inner<'tcx>( diff --git a/src/constant.rs b/src/constant.rs index 7db5f79eead9e..a934b0767f174 100644 --- a/src/constant.rs +++ b/src/constant.rs @@ -551,7 +551,7 @@ pub(crate) fn mir_operand_get_const_val<'tcx>( TerminatorKind::Goto { .. } | TerminatorKind::SwitchInt { .. } | TerminatorKind::UnwindResume - | TerminatorKind::UnwindTerminate + | TerminatorKind::UnwindTerminate(_) | TerminatorKind::Return | TerminatorKind::Unreachable | TerminatorKind::Drop { .. } From 25a2ba2ee4febf9c22f7add7e14a0a50b3fd984d Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sat, 26 Aug 2023 17:42:59 -0700 Subject: [PATCH 09/11] Use `preserve_mostcc` for `extern "rust-cold"` As experimentation in 115242 has shown looks better than `coldcc`. And *don't* use a different convention for cold on Windows, because that actually ends up making things worse. cc tracking issue 97544 --- src/abi/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/abi/mod.rs b/src/abi/mod.rs index b7f56a2986cfc..5d775b9b53229 100644 --- a/src/abi/mod.rs +++ b/src/abi/mod.rs @@ -39,7 +39,7 @@ fn clif_sig_from_fn_abi<'tcx>( pub(crate) fn conv_to_call_conv(sess: &Session, c: Conv, default_call_conv: CallConv) -> CallConv { match c { Conv::Rust | Conv::C => default_call_conv, - Conv::RustCold => CallConv::Cold, + Conv::Cold | Conv::PreserveMost | Conv::PreserveAll => CallConv::Cold, Conv::X86_64SysV => CallConv::SystemV, Conv::X86_64Win64 => CallConv::WindowsFastcall, From b88dfcfcd50d6260130c1c719cda9bef990715eb Mon Sep 17 00:00:00 2001 From: Katherine Philip Date: Mon, 28 Aug 2023 12:40:39 -0700 Subject: [PATCH 10/11] Don't ICE on layout computation failure --- src/common.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common.rs b/src/common.rs index 3081dcfa2b7a3..ec2da39398b2d 100644 --- a/src/common.rs +++ b/src/common.rs @@ -480,7 +480,7 @@ impl<'tcx> LayoutOfHelpers<'tcx> for RevealAllLayoutCx<'tcx> { if let LayoutError::SizeOverflow(_) | LayoutError::ReferencesError(_) = err { self.0.sess.span_fatal(span, err.to_string()) } else { - span_bug!(span, "failed to get layout for `{}`: {}", ty, err) + self.0.sess.span_fatal(span, format!("failed to get layout for `{}`: {}", ty, err)) } } } From 833592766f9e317e7166ffff1444ff70c6fdeda4 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 27 Aug 2023 18:12:34 +0200 Subject: [PATCH 11/11] const_eval and codegen: audit uses of is_zst --- src/unsize.rs | 4 +++- src/vtable.rs | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/unsize.rs b/src/unsize.rs index 6aeba13f63949..c6133f2b35cf0 100644 --- a/src/unsize.rs +++ b/src/unsize.rs @@ -88,7 +88,8 @@ fn unsize_ptr<'tcx>( let src_f = src_layout.field(fx, i); assert_eq!(src_layout.fields.offset(i).bytes(), 0); assert_eq!(dst_layout.fields.offset(i).bytes(), 0); - if src_f.is_zst() { + if src_f.is_1zst() { + // We are looking for the one non-1-ZST field; this is not it. continue; } assert_eq!(src_layout.size, src_f.size); @@ -151,6 +152,7 @@ pub(crate) fn coerce_unsized_into<'tcx>( let dst_f = dst.place_field(fx, FieldIdx::new(i)); if dst_f.layout().is_zst() { + // No data here, nothing to copy/coerce. continue; } diff --git a/src/vtable.rs b/src/vtable.rs index b309695c190f8..7598c6eee03ff 100644 --- a/src/vtable.rs +++ b/src/vtable.rs @@ -51,8 +51,8 @@ pub(crate) fn get_ptr_and_method_ref<'tcx>( 'descend_newtypes: while !arg.layout().ty.is_unsafe_ptr() && !arg.layout().ty.is_ref() { for i in 0..arg.layout().fields.count() { let field = arg.value_field(fx, FieldIdx::new(i)); - if !field.layout().is_zst() { - // we found the one non-zero-sized field that is allowed + if !field.layout().is_1zst() { + // we found the one non-1-ZST field that is allowed // now find *its* non-zero-sized field, or stop if it's a // pointer arg = field;