diff --git a/cranelift/README.md b/cranelift/README.md index a716ed3903..acdb579d04 100644 --- a/cranelift/README.md +++ b/cranelift/README.md @@ -95,14 +95,16 @@ Planned uses Cranelift is designed to be a code generator for WebAssembly, but it is general enough to be useful elsewhere too. The initial planned uses that -affected its design are: +affected its design were: - - [WebAssembly compiler for the SpiderMonkey engine in - Firefox](spidermonkey.md#phase-1-webassembly). - - [Backend for the IonMonkey JavaScript JIT compiler in - Firefox](spidermonkey.md#phase-2-ionmonkey). - - [Debug build backend for the Rust compiler](rustc.md). - - [Wasmtime non-Web wasm engine](https://github.com/bytecodealliance/wasmtime). +- [Wasmtime non-Web wasm engine](https://github.com/bytecodealliance/wasmtime). +- [Debug build backend for the Rust compiler](rustc.md). +- WebAssembly compiler for the SpiderMonkey engine in Firefox + (currently not planned anymore; SpiderMonkey team may re-assess in + the future). +- Backend for the IonMonkey JavaScript JIT compiler in Firefox + (currently not planned anymore; SpiderMonkey team may re-assess in + the future). Building Cranelift ------------------ diff --git a/cranelift/codegen/meta/src/isa/x86.rs b/cranelift/codegen/meta/src/isa/x86.rs index 70e7645e91..e1acdfca20 100644 --- a/cranelift/codegen/meta/src/isa/x86.rs +++ b/cranelift/codegen/meta/src/isa/x86.rs @@ -170,17 +170,8 @@ fn define_settings(shared: &SettingGroup) -> SettingGroup { // back in the shared SettingGroup, and use it in x86 instruction predicates. let is_pic = shared.get_bool("is_pic"); - let emit_all_ones_funcaddrs = shared.get_bool("emit_all_ones_funcaddrs"); settings.add_predicate("is_pic", predicate!(is_pic)); settings.add_predicate("not_is_pic", predicate!(!is_pic)); - settings.add_predicate( - "all_ones_funcaddrs_and_not_is_pic", - predicate!(emit_all_ones_funcaddrs && !is_pic), - ); - settings.add_predicate( - "not_all_ones_funcaddrs_and_not_is_pic", - predicate!(!emit_all_ones_funcaddrs && !is_pic), - ); // Presets corresponding to x86 CPUs. diff --git a/cranelift/codegen/meta/src/shared/instructions.rs b/cranelift/codegen/meta/src/shared/instructions.rs index d7ceb2d034..de231f3157 100644 --- a/cranelift/codegen/meta/src/shared/instructions.rs +++ b/cranelift/codegen/meta/src/shared/instructions.rs @@ -332,24 +332,6 @@ fn define_control_flow( .is_terminator(true), ); - let rvals = &Operand::new("rvals", &entities.varargs).with_doc("return values"); - ig.push( - Inst::new( - "fallthrough_return", - r#" - Return from the function by fallthrough. - - This is a specialized instruction for use where one wants to append - a custom epilogue, which will then perform the real return. This - instruction has no encoding. - "#, - &formats.multiary, - ) - .operands_in(vec![rvals]) - .is_return(true) - .is_terminator(true), - ); - let FN = &Operand::new("FN", &entities.func_ref) .with_doc("function to call, declared by `function`"); let args = &Operand::new("args", &entities.varargs).with_doc("call arguments"); diff --git a/cranelift/codegen/meta/src/shared/settings.rs b/cranelift/codegen/meta/src/shared/settings.rs index 121c8fe74a..cf4473a1cd 100644 --- a/cranelift/codegen/meta/src/shared/settings.rs +++ b/cranelift/codegen/meta/src/shared/settings.rs @@ -88,8 +88,8 @@ pub(crate) fn define() -> SettingGroup { "avoid_div_traps", "Generate explicit checks around native division instructions to avoid their trapping.", r#" - This is primarily used by SpiderMonkey which doesn't install a signal - handler for SIGFPE, but expects a SIGILL trap for division by zero. + Generate explicit checks around native division instructions to + avoid their trapping. On ISAs like ARM where the native division instructions don't trap, this setting has no effect - explicit checks are always inserted. @@ -175,8 +175,6 @@ pub(crate) fn define() -> SettingGroup { vec!["none", "elf_gd", "macho", "coff"], ); - // Settings specific to the `baldrdash` calling convention. - settings.add_enum( "libcall_call_conv", "Defines the calling convention to use for LibCalls call expansion.", @@ -196,29 +194,10 @@ pub(crate) fn define() -> SettingGroup { "system_v", "windows_fastcall", "apple_aarch64", - "baldrdash_system_v", - "baldrdash_windows", - "baldrdash_2020", "probestack", ], ); - settings.add_num( - "baldrdash_prologue_words", - "Number of pointer-sized words pushed by the baldrdash prologue.", - r#" - Functions with the `baldrdash` calling convention don't generate their - own prologue and epilogue. They depend on externally generated code - that pushes a fixed number of words in the prologue and restores them - in the epilogue. - - This setting configures the number of pointer-sized words pushed on the - stack when the Cranelift-generated code is entered. This includes the - pushed return address on x86. - "#, - 0, - ); - settings.add_bool( "enable_llvm_abi_extensions", "Enable various ABI extensions defined by LLVM's behavior.", @@ -277,15 +256,6 @@ pub(crate) fn define() -> SettingGroup { false, ); - // BaldrMonkey requires that not-yet-relocated function addresses be encoded - // as all-ones bitpatterns. - settings.add_bool( - "emit_all_ones_funcaddrs", - "Emit not-yet-relocated function addresses as all-ones bit patterns.", - "", - false, - ); - // Stack probing options. settings.add_bool( diff --git a/cranelift/codegen/src/ir/extfunc.rs b/cranelift/codegen/src/ir/extfunc.rs index 1a623095a7..8baa6bff84 100644 --- a/cranelift/codegen/src/ir/extfunc.rs +++ b/cranelift/codegen/src/ir/extfunc.rs @@ -215,11 +215,6 @@ impl fmt::Display for AbiParam { /// particulars of the target's ABI, and the CLIF should be platform-independent, these attributes /// specify *how* to extend (according to the signedness of the original program) rather than /// *whether* to extend. -/// -/// For example, on x86-64, the SystemV ABI does not require extensions of narrow values, so these -/// `ArgumentExtension` attributes are ignored; but in the Baldrdash (SpiderMonkey) ABI on the same -/// platform, all narrow values *are* extended, so these attributes may lead to extra -/// zero/sign-extend instructions in the generated machine code. #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] #[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] pub enum ArgumentExtension { @@ -297,20 +292,6 @@ pub enum ArgumentPurpose { /// This is a pointer to a stack limit. It is used to check the current stack pointer /// against. Can only appear once in a signature. StackLimit, - - /// A callee TLS value. - /// - /// In the Baldrdash-2020 calling convention, the stack upon entry to the callee contains the - /// TLS-register values for the caller and the callee. This argument is used to provide the - /// value for the callee. - CalleeTLS, - - /// A caller TLS value. - /// - /// In the Baldrdash-2020 calling convention, the stack upon entry to the callee contains the - /// TLS-register values for the caller and the callee. This argument is used to provide the - /// value for the caller. - CallerTLS, } impl fmt::Display for ArgumentPurpose { @@ -325,8 +306,6 @@ impl fmt::Display for ArgumentPurpose { Self::VMContext => "vmctx", Self::SignatureId => "sigid", Self::StackLimit => "stack_limit", - Self::CalleeTLS => "callee_tls", - Self::CallerTLS => "caller_tls", }) } } @@ -447,9 +426,6 @@ mod tests { CallConv::Cold, CallConv::SystemV, CallConv::WindowsFastcall, - CallConv::BaldrdashSystemV, - CallConv::BaldrdashWindows, - CallConv::Baldrdash2020, ] { assert_eq!(Ok(cc), cc.to_string().parse()) } @@ -457,18 +433,15 @@ mod tests { #[test] fn signatures() { - let mut sig = Signature::new(CallConv::BaldrdashSystemV); - assert_eq!(sig.to_string(), "() baldrdash_system_v"); + let mut sig = Signature::new(CallConv::WindowsFastcall); + assert_eq!(sig.to_string(), "() windows_fastcall"); sig.params.push(AbiParam::new(I32)); - assert_eq!(sig.to_string(), "(i32) baldrdash_system_v"); + assert_eq!(sig.to_string(), "(i32) windows_fastcall"); sig.returns.push(AbiParam::new(F32)); - assert_eq!(sig.to_string(), "(i32) -> f32 baldrdash_system_v"); + assert_eq!(sig.to_string(), "(i32) -> f32 windows_fastcall"); sig.params.push(AbiParam::new(I32.by(4).unwrap())); - assert_eq!(sig.to_string(), "(i32, i32x4) -> f32 baldrdash_system_v"); + assert_eq!(sig.to_string(), "(i32, i32x4) -> f32 windows_fastcall"); sig.returns.push(AbiParam::new(B8)); - assert_eq!( - sig.to_string(), - "(i32, i32x4) -> f32, b8 baldrdash_system_v" - ); + assert_eq!(sig.to_string(), "(i32, i32x4) -> f32, b8 windows_fastcall"); } } diff --git a/cranelift/codegen/src/isa/aarch64/abi.rs b/cranelift/codegen/src/isa/aarch64/abi.rs index 1ef9e1a68f..0fcc181aa0 100644 --- a/cranelift/codegen/src/isa/aarch64/abi.rs +++ b/cranelift/codegen/src/isa/aarch64/abi.rs @@ -26,102 +26,11 @@ pub(crate) type AArch64ABICallee = ABICalleeImpl; /// Support for the AArch64 ABI from the caller side (at a callsite). pub(crate) type AArch64ABICaller = ABICallerImpl; -// Spidermonkey specific ABI convention. - -/// This is SpiderMonkey's `WasmTableCallSigReg`. -static BALDRDASH_SIG_REG: u8 = 10; - -/// This is SpiderMonkey's `WasmTlsReg`. -static BALDRDASH_TLS_REG: u8 = 23; - -/// Offset in stack-arg area to callee-TLS slot in Baldrdash-2020 calling convention. -static BALDRDASH_CALLEE_TLS_OFFSET: i64 = 0; -/// Offset in stack-arg area to caller-TLS slot in Baldrdash-2020 calling convention. -static BALDRDASH_CALLER_TLS_OFFSET: i64 = 8; - -// These two lists represent the registers the JIT may *not* use at any point in generated code. -// -// So these are callee-preserved from the JIT's point of view, and every register not in this list -// has to be caller-preserved by definition. -// -// Keep these lists in sync with the NonAllocatableMask set in Spidermonkey's -// Architecture-arm64.cpp. - -// Indexed by physical register number. -#[rustfmt::skip] -static BALDRDASH_JIT_CALLEE_SAVED_GPR: &[bool] = &[ - /* 0 = */ false, false, false, false, false, false, false, false, - /* 8 = */ false, false, false, false, false, false, false, false, - /* 16 = */ true /* x16 / ip1 */, true /* x17 / ip2 */, true /* x18 / TLS */, false, - /* 20 = */ false, false, false, false, - /* 24 = */ false, false, false, false, - // There should be 28, the pseudo stack pointer in this list, however the wasm stubs trash it - // gladly right now. - /* 28 = */ false, false, true /* x30 = FP */, false /* x31 = SP */ -]; - -#[rustfmt::skip] -static BALDRDASH_JIT_CALLEE_SAVED_FPU: &[bool] = &[ - /* 0 = */ false, false, false, false, false, false, false, false, - /* 8 = */ false, false, false, false, false, false, false, false, - /* 16 = */ false, false, false, false, false, false, false, false, - /* 24 = */ false, false, false, false, false, false, false, true /* v31 / d31 */ -]; - /// This is the limit for the size of argument and return-value areas on the /// stack. We place a reasonable limit here to avoid integer overflow issues /// with 32-bit arithmetic: for now, 128 MB. static STACK_ARG_RET_SIZE_LIMIT: u64 = 128 * 1024 * 1024; -/// Try to fill a Baldrdash register, returning it if it was found. -fn try_fill_baldrdash_reg(call_conv: isa::CallConv, param: &ir::AbiParam) -> Option { - if call_conv.extends_baldrdash() { - match ¶m.purpose { - &ir::ArgumentPurpose::VMContext => { - // This is SpiderMonkey's `WasmTlsReg`. - Some(ABIArg::reg( - xreg(BALDRDASH_TLS_REG).to_real_reg().unwrap(), - ir::types::I64, - param.extension, - param.purpose, - )) - } - &ir::ArgumentPurpose::SignatureId => { - // This is SpiderMonkey's `WasmTableCallSigReg`. - Some(ABIArg::reg( - xreg(BALDRDASH_SIG_REG).to_real_reg().unwrap(), - ir::types::I64, - param.extension, - param.purpose, - )) - } - &ir::ArgumentPurpose::CalleeTLS => { - // This is SpiderMonkey's callee TLS slot in the extended frame of Wasm's ABI-2020. - assert!(call_conv == isa::CallConv::Baldrdash2020); - Some(ABIArg::stack( - BALDRDASH_CALLEE_TLS_OFFSET, - ir::types::I64, - ir::ArgumentExtension::None, - param.purpose, - )) - } - &ir::ArgumentPurpose::CallerTLS => { - // This is SpiderMonkey's caller TLS slot in the extended frame of Wasm's ABI-2020. - assert!(call_conv == isa::CallConv::Baldrdash2020); - Some(ABIArg::stack( - BALDRDASH_CALLER_TLS_OFFSET, - ir::types::I64, - ir::ArgumentExtension::None, - param.purpose, - )) - } - _ => None, - } - } else { - None - } -} - impl Into for StackAMode { fn into(self) -> AMode { match self { @@ -135,26 +44,19 @@ impl Into for StackAMode { // Returns the size of stack space needed to store the // `int_reg` and `vec_reg`. fn saved_reg_stack_size( - call_conv: isa::CallConv, int_reg: &[Writable], vec_reg: &[Writable], ) -> (usize, usize) { // Round up to multiple of 2, to keep 16-byte stack alignment. let int_save_bytes = (int_reg.len() + (int_reg.len() & 1)) * 8; - // The Baldrdash ABIs require saving and restoring the whole 16-byte - // SIMD & FP registers, so the necessary stack space is always a - // multiple of the mandatory 16-byte stack alignment. However, the - // Procedure Call Standard for the Arm 64-bit Architecture (AAPCS64, - // including several related ABIs such as the one used by Windows) - // mandates saving only the bottom 8 bytes of the vector registers, - // so in that case we round up the number of registers to ensure proper - // stack alignment (similarly to the situation with `int_reg`). - let vec_reg_size = if call_conv.extends_baldrdash() { 16 } else { 8 }; - let vec_save_padding = if call_conv.extends_baldrdash() { - 0 - } else { - vec_reg.len() & 1 - }; + // The Procedure Call Standard for the Arm 64-bit Architecture + // (AAPCS64, including several related ABIs such as the one used by + // Windows) mandates saving only the bottom 8 bytes of the vector + // registers, so we round up the number of registers to ensure + // proper stack alignment (similarly to the situation with + // `int_reg`). + let vec_reg_size = 8; + let vec_save_padding = vec_reg.len() & 1; // FIXME: SVE: ABI is different to Neon, so do we treat all vec regs as Z-regs? let vec_save_bytes = (vec_reg.len() + vec_save_padding) * vec_reg_size; @@ -185,8 +87,6 @@ impl ABIMachineSpec for AArch64MachineDeps { add_ret_area_ptr: bool, ) -> CodegenResult<(Vec, i64, Option)> { let is_apple_cc = call_conv.extends_apple_aarch64(); - let is_baldrdash = call_conv.extends_baldrdash(); - let has_baldrdash_tls = call_conv == isa::CallConv::Baldrdash2020; // See AArch64 ABI (https://github.com/ARM-software/abi-aa/blob/2021Q1/aapcs64/aapcs64.rst#64parameter-passing), sections 6.4. // @@ -207,12 +107,6 @@ impl ABIMachineSpec for AArch64MachineDeps { let mut next_stack: u64 = 0; let mut ret = vec![]; - if args_or_rets == ArgsOrRets::Args && has_baldrdash_tls { - // Baldrdash ABI-2020 always has two stack-arg slots reserved, for the callee and - // caller TLS-register values, respectively. - next_stack = 16; - } - let (max_per_class_reg_vals, mut remaining_reg_vals) = match args_or_rets { ArgsOrRets::Args => (8, 16), // x0-x7 and v0-v7 @@ -222,12 +116,12 @@ impl ABIMachineSpec for AArch64MachineDeps { // we can return values in up to 8 integer and // 8 vector registers at once. // - // In Baldrdash and Wasmtime, we can only use one register for - // return value for all the register classes. That is, we can't - // return values in both one integer and one vector register; only - // one return value may be in a register. + // In Wasmtime, we can only use one register for return + // value for all the register classes. That is, we can't + // return values in both one integer and one vector + // register; only one return value may be in a register. ArgsOrRets::Rets => { - if is_baldrdash || call_conv.extends_wasmtime() { + if call_conv.extends_wasmtime() { (1, 1) // x0 or v0, but not both } else { (8, 16) // x0-x7 and v0-v7 @@ -235,23 +129,13 @@ impl ABIMachineSpec for AArch64MachineDeps { } }; - for i in 0..params.len() { - // Process returns backward, according to the SpiderMonkey ABI (which we - // adopt internally if `is_baldrdash` is set). - let param = match (args_or_rets, is_baldrdash) { - (ArgsOrRets::Args, _) => ¶ms[i], - (ArgsOrRets::Rets, false) => ¶ms[i], - (ArgsOrRets::Rets, true) => ¶ms[params.len() - 1 - i], - }; - + for param in params { // Validate "purpose". match ¶m.purpose { &ir::ArgumentPurpose::VMContext | &ir::ArgumentPurpose::Normal | &ir::ArgumentPurpose::StackLimit | &ir::ArgumentPurpose::SignatureId - | &ir::ArgumentPurpose::CallerTLS - | &ir::ArgumentPurpose::CalleeTLS | &ir::ArgumentPurpose::StructReturn | &ir::ArgumentPurpose::StructArgument(_) => {} _ => panic!( @@ -268,12 +152,6 @@ impl ABIMachineSpec for AArch64MachineDeps { let (rcs, reg_types) = Inst::rc_for_type(param.value_type)?; - if let Some(param) = try_fill_baldrdash_reg(call_conv, param) { - assert!(rcs[0] == RegClass::Int); - ret.push(param); - continue; - } - if let ir::ArgumentPurpose::StructArgument(size) = param.purpose { let offset = next_stack as i64; let size = size as u64; @@ -432,10 +310,6 @@ impl ABIMachineSpec for AArch64MachineDeps { next_stack += size; } - if args_or_rets == ArgsOrRets::Rets && is_baldrdash { - ret.reverse(); - } - let extra_arg = if add_ret_area_ptr { debug_assert!(args_or_rets == ArgsOrRets::Args); if next_xreg < max_per_class_reg_vals && remaining_reg_vals > 0 { @@ -470,15 +344,8 @@ impl ABIMachineSpec for AArch64MachineDeps { Ok((ret, next_stack as i64, extra_arg)) } - fn fp_to_arg_offset(call_conv: isa::CallConv, flags: &settings::Flags) -> i64 { - if call_conv.extends_baldrdash() { - let num_words = flags.baldrdash_prologue_words() as i64; - debug_assert!(num_words > 0, "baldrdash must set baldrdash_prologue_words"); - debug_assert_eq!(num_words % 2, 0, "stack must be 16-aligned"); - num_words * 8 - } else { - 16 // frame pointer + return address. - } + fn fp_to_arg_offset(_call_conv: isa::CallConv, _flags: &settings::Flags) -> i64 { + 16 // frame pointer + return address. } fn gen_load_stack(mem: StackAMode, into_reg: Writable, ty: Type) -> Inst { @@ -560,10 +427,6 @@ impl ABIMachineSpec for AArch64MachineDeps { insts } - fn gen_epilogue_placeholder() -> Inst { - Inst::EpiloguePlaceholder - } - fn gen_get_stack_addr(mem: StackAMode, into_reg: Writable, _ty: Type) -> Inst { // FIXME: Do something different for dynamic types? let mem = mem.into(); @@ -712,7 +575,7 @@ impl ABIMachineSpec for AArch64MachineDeps { // Returns stack bytes used as well as instructions. Does not adjust // nominal SP offset; abi_impl generic code will do that. fn gen_clobber_save( - call_conv: isa::CallConv, + _call_conv: isa::CallConv, setup_frame: bool, flags: &settings::Flags, clobbered_callee_saves: &[Writable], @@ -729,8 +592,7 @@ impl ABIMachineSpec for AArch64MachineDeps { } } - let (int_save_bytes, vec_save_bytes) = - saved_reg_stack_size(call_conv, &clobbered_int, &clobbered_vec); + let (int_save_bytes, vec_save_bytes) = saved_reg_stack_size(&clobbered_int, &clobbered_vec); let total_save_bytes = int_save_bytes + vec_save_bytes; let clobber_size = total_save_bytes as i32; let mut insts = SmallVec::new(); @@ -826,26 +688,13 @@ impl ABIMachineSpec for AArch64MachineDeps { } } - let store_vec_reg = |rd| { - if call_conv.extends_baldrdash() { - Inst::FpuStore128 { - rd, - mem: AMode::PreIndexed( - writable_stack_reg(), - SImm9::maybe_from_i64(-clobber_offset_change).unwrap(), - ), - flags: MemFlags::trusted(), - } - } else { - Inst::FpuStore64 { - rd, - mem: AMode::PreIndexed( - writable_stack_reg(), - SImm9::maybe_from_i64(-clobber_offset_change).unwrap(), - ), - flags: MemFlags::trusted(), - } - } + let store_vec_reg = |rd| Inst::FpuStore64 { + rd, + mem: AMode::PreIndexed( + writable_stack_reg(), + SImm9::maybe_from_i64(-clobber_offset_change).unwrap(), + ), + flags: MemFlags::trusted(), }; let iter = clobbered_vec.chunks_exact(2); @@ -867,37 +716,20 @@ impl ABIMachineSpec for AArch64MachineDeps { } let store_vec_reg_pair = |rt, rt2| { - if call_conv.extends_baldrdash() { - let clobber_offset_change = 32; + let clobber_offset_change = 16; - ( - Inst::FpuStoreP128 { - rt, - rt2, - mem: PairAMode::PreIndexed( - writable_stack_reg(), - SImm7Scaled::maybe_from_i64(-clobber_offset_change, I8X16).unwrap(), - ), - flags: MemFlags::trusted(), - }, - clobber_offset_change as u32, - ) - } else { - let clobber_offset_change = 16; - - ( - Inst::FpuStoreP64 { - rt, - rt2, - mem: PairAMode::PreIndexed( - writable_stack_reg(), - SImm7Scaled::maybe_from_i64(-clobber_offset_change, F64).unwrap(), - ), - flags: MemFlags::trusted(), - }, - clobber_offset_change as u32, - ) - } + ( + Inst::FpuStoreP64 { + rt, + rt2, + mem: PairAMode::PreIndexed( + writable_stack_reg(), + SImm7Scaled::maybe_from_i64(-clobber_offset_change, F64).unwrap(), + ), + flags: MemFlags::trusted(), + }, + clobber_offset_change as u32, + ) }; let mut iter = iter.rev(); @@ -938,7 +770,7 @@ impl ABIMachineSpec for AArch64MachineDeps { } fn gen_clobber_restore( - call_conv: isa::CallConv, + _call_conv: isa::CallConv, sig: &Signature, flags: &settings::Flags, clobbers: &[Writable], @@ -946,57 +778,26 @@ impl ABIMachineSpec for AArch64MachineDeps { _outgoing_args_size: u32, ) -> SmallVec<[Inst; 16]> { let mut insts = SmallVec::new(); - let (clobbered_int, clobbered_vec) = - get_regs_restored_in_epilogue(call_conv, flags, sig, clobbers); + let (clobbered_int, clobbered_vec) = get_regs_restored_in_epilogue(flags, sig, clobbers); // Free the fixed frame if necessary. if fixed_frame_storage_size > 0 { insts.extend(Self::gen_sp_reg_adjust(fixed_frame_storage_size as i32)); } - let load_vec_reg = |rd| { - if call_conv.extends_baldrdash() { - Inst::FpuLoad128 { - rd, - mem: AMode::PostIndexed( - writable_stack_reg(), - SImm9::maybe_from_i64(16).unwrap(), - ), - flags: MemFlags::trusted(), - } - } else { - Inst::FpuLoad64 { - rd, - mem: AMode::PostIndexed( - writable_stack_reg(), - SImm9::maybe_from_i64(16).unwrap(), - ), - flags: MemFlags::trusted(), - } - } + let load_vec_reg = |rd| Inst::FpuLoad64 { + rd, + mem: AMode::PostIndexed(writable_stack_reg(), SImm9::maybe_from_i64(16).unwrap()), + flags: MemFlags::trusted(), }; - let load_vec_reg_pair = |rt, rt2| { - if call_conv.extends_baldrdash() { - Inst::FpuLoadP128 { - rt, - rt2, - mem: PairAMode::PostIndexed( - writable_stack_reg(), - SImm7Scaled::maybe_from_i64(32, I8X16).unwrap(), - ), - flags: MemFlags::trusted(), - } - } else { - Inst::FpuLoadP64 { - rt, - rt2, - mem: PairAMode::PostIndexed( - writable_stack_reg(), - SImm7Scaled::maybe_from_i64(16, F64).unwrap(), - ), - flags: MemFlags::trusted(), - } - } + let load_vec_reg_pair = |rt, rt2| Inst::FpuLoadP64 { + rt, + rt2, + mem: PairAMode::PostIndexed( + writable_stack_reg(), + SImm7Scaled::maybe_from_i64(16, F64).unwrap(), + ), + flags: MemFlags::trusted(), }; let mut iter = clobbered_vec.chunks_exact(2); @@ -1053,19 +854,6 @@ impl ABIMachineSpec for AArch64MachineDeps { }); } - // If this is Baldrdash-2020, restore the callee (i.e., our) TLS - // register. We may have allocated it for something else and clobbered - // it, but the ABI expects us to leave the TLS register unchanged. - if call_conv == isa::CallConv::Baldrdash2020 { - let off = BALDRDASH_CALLEE_TLS_OFFSET + Self::fp_to_arg_offset(call_conv, flags); - insts.push(Inst::gen_load( - writable_xreg(BALDRDASH_TLS_REG), - AMode::UnsignedOffset(fp_reg(), UImm12Scaled::maybe_from_i64(off, I64).unwrap()), - I64, - MemFlags::trusted(), - )); - } - insts } @@ -1132,8 +920,6 @@ impl ABIMachineSpec for AArch64MachineDeps { src: Reg, size: usize, ) -> SmallVec<[Self::I; 8]> { - // Baldrdash should not use struct args. - assert!(!call_conv.extends_baldrdash()); let mut insts = SmallVec::new(); let arg0 = writable_xreg(0); let arg1 = writable_xreg(1); @@ -1174,36 +960,19 @@ impl ABIMachineSpec for AArch64MachineDeps { s.nominal_sp_to_fp } - fn get_regs_clobbered_by_call(call_conv_of_callee: isa::CallConv) -> PRegSet { - let mut clobbers = DEFAULT_AAPCS_CLOBBERS; - - if call_conv_of_callee.extends_baldrdash() { - // Every X-register except for x16, x17, x18 is - // caller-saved (clobbered by a call). - for i in 19..=28 { - clobbers.add(xreg_preg(i)); - } - clobbers.add(vreg_preg(31)); - } - - clobbers + fn get_regs_clobbered_by_call(_call_conv_of_callee: isa::CallConv) -> PRegSet { + DEFAULT_AAPCS_CLOBBERS } fn get_ext_mode( - call_conv: isa::CallConv, - specified: ir::ArgumentExtension, + _call_conv: isa::CallConv, + _specified: ir::ArgumentExtension, ) -> ir::ArgumentExtension { - if call_conv.extends_baldrdash() { - // Baldrdash (SpiderMonkey) always extends args and return values to the full register. - specified - } else { - // No other supported ABI on AArch64 does so. - ir::ArgumentExtension::None - } + ir::ArgumentExtension::None } fn get_clobbered_callee_saves( - call_conv: isa::CallConv, + _call_conv: isa::CallConv, flags: &settings::Flags, sig: &Signature, regs: &[Writable], @@ -1211,9 +980,7 @@ impl ABIMachineSpec for AArch64MachineDeps { let mut regs: Vec> = regs .iter() .cloned() - .filter(|r| { - is_reg_saved_in_prologue(call_conv, flags.enable_pinned_reg(), sig, r.to_reg()) - }) + .filter(|r| is_reg_saved_in_prologue(flags.enable_pinned_reg(), sig, r.to_reg())) .collect(); // Sort registers for deterministic code output. We can do an unstable @@ -1248,25 +1015,7 @@ fn legal_type_for_machine(ty: Type) -> bool { /// Is the given register saved in the prologue if clobbered, i.e., is it a /// callee-save? -fn is_reg_saved_in_prologue( - call_conv: isa::CallConv, - enable_pinned_reg: bool, - sig: &Signature, - r: RealReg, -) -> bool { - if call_conv.extends_baldrdash() { - match r.class() { - RegClass::Int => { - let enc = r.hw_enc() & 31; - return BALDRDASH_JIT_CALLEE_SAVED_GPR[enc as usize]; - } - RegClass::Float => { - let enc = r.hw_enc() & 31; - return BALDRDASH_JIT_CALLEE_SAVED_FPU[enc as usize]; - } - }; - } - +fn is_reg_saved_in_prologue(enable_pinned_reg: bool, sig: &Signature, r: RealReg) -> bool { // FIXME: We need to inspect whether a function is returning Z or P regs too. let save_z_regs = sig .params @@ -1307,7 +1056,6 @@ fn is_reg_saved_in_prologue( /// prologue and restored in the epilogue, given the set of all registers /// written by the function's body. fn get_regs_restored_in_epilogue( - call_conv: isa::CallConv, flags: &settings::Flags, sig: &Signature, regs: &[Writable], @@ -1315,7 +1063,7 @@ fn get_regs_restored_in_epilogue( let mut int_saves = vec![]; let mut vec_saves = vec![]; for ® in regs { - if is_reg_saved_in_prologue(call_conv, flags.enable_pinned_reg(), sig, reg.to_reg()) { + if is_reg_saved_in_prologue(flags.enable_pinned_reg(), sig, reg.to_reg()) { match reg.to_reg().class() { RegClass::Int => int_saves.push(reg), RegClass::Float => vec_saves.push(reg), diff --git a/cranelift/codegen/src/isa/aarch64/inst.isle b/cranelift/codegen/src/isa/aarch64/inst.isle index 58f5c0ea3e..a938241ea7 100644 --- a/cranelift/codegen/src/isa/aarch64/inst.isle +++ b/cranelift/codegen/src/isa/aarch64/inst.isle @@ -666,10 +666,6 @@ (Ret (rets VecReg)) - ;; A placeholder instruction, generating no code, meaning that a function epilogue must be - ;; inserted there. - (EpiloguePlaceholder) - ;; An unconditional branch. (Jump (dest BranchTarget)) @@ -707,7 +703,6 @@ ;; An instruction guaranteed to always be undefined and to trigger an illegal instruction at ;; runtime. (Udf - (use_allocated_encoding bool) (trap_code TrapCode)) ;; Compute the address (using a PC-relative offset) of a memory location, using the `ADR` @@ -2107,9 +2102,9 @@ ;; Helper for generating a `udf` instruction. -(decl udf (bool TrapCode) SideEffectNoResult) -(rule (udf use_allocated_encoding trap_code) - (SideEffectNoResult.Inst (MInst.Udf use_allocated_encoding trap_code))) +(decl udf (TrapCode) SideEffectNoResult) +(rule (udf trap_code) + (SideEffectNoResult.Inst (MInst.Udf trap_code))) ;; Immediate value helpers ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/cranelift/codegen/src/isa/aarch64/inst/emit.rs b/cranelift/codegen/src/isa/aarch64/inst/emit.rs index b504e675be..774508cdd6 100644 --- a/cranelift/codegen/src/isa/aarch64/inst/emit.rs +++ b/cranelift/codegen/src/isa/aarch64/inst/emit.rs @@ -618,8 +618,6 @@ pub struct EmitState { stack_map: Option, /// Current source-code location corresponding to instruction to be emitted. cur_srcloc: SourceLoc, - /// Is code generated for the SpiderMonkey WebAssembly convention. - is_baldrdash_target: bool, } impl MachInstEmitState for EmitState { @@ -629,7 +627,6 @@ impl MachInstEmitState for EmitState { nominal_sp_to_fp: abi.frame_size() as i64, stack_map: None, cur_srcloc: SourceLoc::default(), - is_baldrdash_target: abi.call_conv().extends_baldrdash(), } } @@ -2768,9 +2765,6 @@ impl MachInstEmit for Inst { &Inst::Ret { .. } => { sink.put4(0xd65f03c0); } - &Inst::EpiloguePlaceholder => { - // Noop; this is just a placeholder for epilogues. - } &Inst::Call { ref info } => { if let Some(s) = state.take_stack_map() { sink.add_stack_map(StackMapExtent::UpcomingBytes(4), s); @@ -2826,10 +2820,7 @@ impl MachInstEmit for Inst { )); sink.use_label_at_offset(off, label, LabelUse::Branch19); // udf - let trap = Inst::Udf { - use_allocated_encoding: !state.is_baldrdash_target, - trap_code, - }; + let trap = Inst::Udf { trap_code }; trap.emit(&[], sink, emit_info, state); // LABEL: sink.bind_label(label); @@ -2845,15 +2836,10 @@ impl MachInstEmit for Inst { &Inst::Brk => { sink.put4(0xd4200000); } - &Inst::Udf { - use_allocated_encoding, - trap_code, - } => { - let encoding = if use_allocated_encoding { - 0xc11f - } else { - 0xd4a00000 - }; + &Inst::Udf { trap_code } => { + // "CLIF" in hex, to make the trap recognizable during + // debugging. + let encoding = 0xc11f; sink.add_trap(trap_code); if let Some(s) = state.take_stack_map() { @@ -2985,11 +2971,7 @@ impl MachInstEmit for Inst { }; inst.emit(&[], sink, emit_info, state); sink.add_reloc(Reloc::Abs8, name, offset); - if emit_info.0.emit_all_ones_funcaddrs() { - sink.put8(u64::max_value()); - } else { - sink.put8(0); - } + sink.put8(0); } &Inst::LoadAddr { rd, ref mem } => { let rd = allocs.next_writable(rd); diff --git a/cranelift/codegen/src/isa/aarch64/inst/emit_tests.rs b/cranelift/codegen/src/isa/aarch64/inst/emit_tests.rs index 95971c52c3..eb458b8f1a 100644 --- a/cranelift/codegen/src/isa/aarch64/inst/emit_tests.rs +++ b/cranelift/codegen/src/isa/aarch64/inst/emit_tests.rs @@ -43,11 +43,10 @@ fn test_aarch64_binemit() { insns.push((Inst::Csdb, "9F2203D5", "csdb")); insns.push(( Inst::Udf { - use_allocated_encoding: false, trap_code: TrapCode::Interrupt, }, - "0000A0D4", - "udf", + "1FC10000", + "udf #0xc11f", )); insns.push(( Inst::AluRRR { diff --git a/cranelift/codegen/src/isa/aarch64/inst/mod.rs b/cranelift/codegen/src/isa/aarch64/inst/mod.rs index 74a094d9f5..e7e0cc9b8a 100644 --- a/cranelift/codegen/src/isa/aarch64/inst/mod.rs +++ b/cranelift/codegen/src/isa/aarch64/inst/mod.rs @@ -975,7 +975,7 @@ fn aarch64_get_operands VReg>(inst: &Inst, collector: &mut Operan collector.reg_use(ret); } } - &Inst::Jump { .. } | &Inst::EpiloguePlaceholder => {} + &Inst::Jump { .. } => {} &Inst::Call { ref info, .. } => { collector.reg_uses(&info.uses[..]); collector.reg_defs(&info.defs[..]); @@ -1062,14 +1062,6 @@ impl MachInst for Inst { } } - fn is_epilogue_placeholder(&self) -> bool { - if let Inst::EpiloguePlaceholder = self { - true - } else { - false - } - } - fn is_included_in_clobbers(&self) -> bool { // We exclude call instructions from the clobber-set when they are calls // from caller to callee with the same ABI. Such calls cannot possibly @@ -1090,7 +1082,7 @@ impl MachInst for Inst { fn is_term(&self) -> MachTerminator { match self { - &Inst::Ret { .. } | &Inst::EpiloguePlaceholder => MachTerminator::Ret, + &Inst::Ret { .. } => MachTerminator::Ret, &Inst::Jump { .. } => MachTerminator::Uncond, &Inst::CondBr { .. } => MachTerminator::Cond, &Inst::IndirectBr { .. } => MachTerminator::Indirect, @@ -2472,7 +2464,6 @@ impl Inst { format!("blr {}", rn) } &Inst::Ret { .. } => "ret".to_string(), - &Inst::EpiloguePlaceholder => "epilogue placeholder".to_string(), &Inst::Jump { ref dest } => { let dest = dest.pretty_print(0, allocs); format!("b {}", dest) @@ -2504,16 +2495,7 @@ impl Inst { format!("br {}", rn) } &Inst::Brk => "brk #0".to_string(), - &Inst::Udf { - use_allocated_encoding, - .. - } => { - if use_allocated_encoding { - "udf #0xc11f".to_string() - } else { - "udf".to_string() - } - } + &Inst::Udf { .. } => "udf #0xc11f".to_string(), &Inst::TrapIf { ref kind, .. } => match kind { &CondBrKind::Zero(reg) => { let reg = pretty_print_reg(reg, allocs); diff --git a/cranelift/codegen/src/isa/aarch64/lower.isle b/cranelift/codegen/src/isa/aarch64/lower.isle index f46a103fdd..6684d9d5a9 100644 --- a/cranelift/codegen/src/isa/aarch64/lower.isle +++ b/cranelift/codegen/src/isa/aarch64/lower.isle @@ -1524,14 +1524,12 @@ ;;;; Rules for `trap` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (rule (lower (trap trap_code)) - (let ((use_allocated_encoding bool (is_not_baldrdash_call_conv))) - (side_effect (udf use_allocated_encoding trap_code)))) + (side_effect (udf trap_code))) ;;;; Rules for `resumable_trap` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (rule (lower (resumable_trap trap_code)) - (let ((use_allocated_encoding bool (is_not_baldrdash_call_conv))) - (side_effect (udf use_allocated_encoding trap_code)))) + (side_effect (udf trap_code))) ;;;; Rules for `splat` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/cranelift/codegen/src/isa/aarch64/lower_inst.rs b/cranelift/codegen/src/isa/aarch64/lower_inst.rs index 3570286c04..65863ea135 100644 --- a/cranelift/codegen/src/isa/aarch64/lower_inst.rs +++ b/cranelift/codegen/src/isa/aarch64/lower_inst.rs @@ -463,7 +463,7 @@ pub(crate) fn lower_insn_to_regs>( } } - Opcode::FallthroughReturn | Opcode::Return => { + Opcode::Return => { for (i, input) in inputs.iter().enumerate() { // N.B.: according to the AArch64 ABI, the top bits of a register // (above the bits for the value's type) are undefined, so we diff --git a/cranelift/codegen/src/isa/call_conv.rs b/cranelift/codegen/src/isa/call_conv.rs index d9ee48f896..d70b2b49c2 100644 --- a/cranelift/codegen/src/isa/call_conv.rs +++ b/cranelift/codegen/src/isa/call_conv.rs @@ -20,13 +20,6 @@ pub enum CallConv { WindowsFastcall, /// Mac aarch64 calling convention, which is a tweaked aarch64 ABI. AppleAarch64, - /// SpiderMonkey WebAssembly convention on systems using natively SystemV. - BaldrdashSystemV, - /// SpiderMonkey WebAssembly convention on Windows. - BaldrdashWindows, - /// SpiderMonkey WebAssembly convention for "ABI-2020", with extra TLS - /// register slots in the frame. - Baldrdash2020, /// Specialized convention for the probestack function. Probestack, /// Wasmtime equivalent of SystemV, not ABI-stable. @@ -67,9 +60,6 @@ impl CallConv { LibcallCallConv::SystemV => Self::SystemV, LibcallCallConv::WindowsFastcall => Self::WindowsFastcall, LibcallCallConv::AppleAarch64 => Self::AppleAarch64, - LibcallCallConv::BaldrdashSystemV => Self::BaldrdashSystemV, - LibcallCallConv::BaldrdashWindows => Self::BaldrdashWindows, - LibcallCallConv::Baldrdash2020 => Self::Baldrdash2020, LibcallCallConv::Probestack => Self::Probestack, } } @@ -77,7 +67,7 @@ impl CallConv { /// Is the calling convention extending the Windows Fastcall ABI? pub fn extends_windows_fastcall(self) -> bool { match self { - Self::WindowsFastcall | Self::BaldrdashWindows | Self::WasmtimeFastcall => true, + Self::WindowsFastcall | Self::WasmtimeFastcall => true, _ => false, } } @@ -90,14 +80,6 @@ impl CallConv { } } - /// Is the calling convention extending the Baldrdash ABI? - pub fn extends_baldrdash(self) -> bool { - match self { - Self::BaldrdashSystemV | Self::BaldrdashWindows | Self::Baldrdash2020 => true, - _ => false, - } - } - /// Is the calling convention extending the Wasmtime ABI? pub fn extends_wasmtime(self) -> bool { match self { @@ -115,9 +97,6 @@ impl fmt::Display for CallConv { Self::SystemV => "system_v", Self::WindowsFastcall => "windows_fastcall", Self::AppleAarch64 => "apple_aarch64", - Self::BaldrdashSystemV => "baldrdash_system_v", - Self::BaldrdashWindows => "baldrdash_windows", - Self::Baldrdash2020 => "baldrdash_2020", Self::Probestack => "probestack", Self::WasmtimeSystemV => "wasmtime_system_v", Self::WasmtimeFastcall => "wasmtime_fastcall", @@ -135,9 +114,6 @@ impl str::FromStr for CallConv { "system_v" => Ok(Self::SystemV), "windows_fastcall" => Ok(Self::WindowsFastcall), "apple_aarch64" => Ok(Self::AppleAarch64), - "baldrdash_system_v" => Ok(Self::BaldrdashSystemV), - "baldrdash_windows" => Ok(Self::BaldrdashWindows), - "baldrdash_2020" => Ok(Self::Baldrdash2020), "probestack" => Ok(Self::Probestack), "wasmtime_system_v" => Ok(Self::WasmtimeSystemV), "wasmtime_fastcall" => Ok(Self::WasmtimeFastcall), diff --git a/cranelift/codegen/src/isa/s390x/abi.rs b/cranelift/codegen/src/isa/s390x/abi.rs index 1a4afbdb41..de95a733f2 100644 --- a/cranelift/codegen/src/isa/s390x/abi.rs +++ b/cranelift/codegen/src/isa/s390x/abi.rs @@ -445,10 +445,6 @@ impl ABIMachineSpec for S390xMachineDeps { insts } - fn gen_epilogue_placeholder() -> Inst { - Inst::EpiloguePlaceholder - } - fn gen_get_stack_addr(mem: StackAMode, into_reg: Writable, _ty: Type) -> Inst { let mem = mem.into(); Inst::LoadAddr { rd: into_reg, mem } diff --git a/cranelift/codegen/src/isa/s390x/inst.isle b/cranelift/codegen/src/isa/s390x/inst.isle index 60f8c7e80f..c3f8658cb3 100644 --- a/cranelift/codegen/src/isa/s390x/inst.isle +++ b/cranelift/codegen/src/isa/s390x/inst.isle @@ -772,10 +772,6 @@ (link Reg) (rets VecReg)) - ;; A placeholder instruction, generating no code, meaning that a function epilogue must be - ;; inserted there. - (EpiloguePlaceholder) - ;; An unconditional branch. (Jump (dest MachLabel)) diff --git a/cranelift/codegen/src/isa/s390x/inst/emit.rs b/cranelift/codegen/src/isa/s390x/inst/emit.rs index 6ef6ccbcbc..dbb99b9b08 100644 --- a/cranelift/codegen/src/isa/s390x/inst/emit.rs +++ b/cranelift/codegen/src/isa/s390x/inst/emit.rs @@ -1240,13 +1240,12 @@ impl EmitState { /// Constant state used during function compilation. pub struct EmitInfo { - flags: settings::Flags, isa_flags: s390x_settings::Flags, } impl EmitInfo { - pub(crate) fn new(flags: settings::Flags, isa_flags: s390x_settings::Flags) -> Self { - Self { flags, isa_flags } + pub(crate) fn new(isa_flags: s390x_settings::Flags) -> Self { + Self { isa_flags } } } @@ -2200,11 +2199,7 @@ impl MachInstEmit for Inst { let reg = writable_spilltmp_reg().to_reg(); put(sink, &enc_ri_b(opcode, reg, 12)); sink.add_reloc(Reloc::Abs8, name, offset); - if emit_info.flags.emit_all_ones_funcaddrs() { - sink.put8(u64::max_value()); - } else { - sink.put8(0); - } + sink.put8(0); let inst = Inst::Load64 { rd, mem: MemArg::reg(reg, MemFlags::trusted()), @@ -3120,9 +3115,6 @@ impl MachInstEmit for Inst { let opcode = 0x07; // BCR put(sink, &enc_rr(opcode, gpr(15), link)); } - &Inst::EpiloguePlaceholder => { - // Noop; this is just a placeholder for epilogues. - } &Inst::Jump { dest } => { let off = sink.cur_offset(); // Indicate that the jump uses a label, if so, so that a fixup can occur later. diff --git a/cranelift/codegen/src/isa/s390x/inst/emit_tests.rs b/cranelift/codegen/src/isa/s390x/inst/emit_tests.rs index 5dd423801f..ffb3feb1da 100644 --- a/cranelift/codegen/src/isa/s390x/inst/emit_tests.rs +++ b/cranelift/codegen/src/isa/s390x/inst/emit_tests.rs @@ -12551,7 +12551,7 @@ fn test_s390x_binemit() { isa_flag_builder.enable("arch13").unwrap(); let isa_flags = s390x_settings::Flags::new(&flags, isa_flag_builder); - let emit_info = EmitInfo::new(flags, isa_flags); + let emit_info = EmitInfo::new(isa_flags); for (insn, expected_encoding, expected_printing) in insns { println!( "S390x: {:?}, {}, {}", diff --git a/cranelift/codegen/src/isa/s390x/inst/mod.rs b/cranelift/codegen/src/isa/s390x/inst/mod.rs index ad5af092bc..24975c5ccf 100644 --- a/cranelift/codegen/src/isa/s390x/inst/mod.rs +++ b/cranelift/codegen/src/isa/s390x/inst/mod.rs @@ -200,7 +200,6 @@ impl Inst { | Inst::Call { .. } | Inst::CallInd { .. } | Inst::Ret { .. } - | Inst::EpiloguePlaceholder | Inst::Jump { .. } | Inst::CondBr { .. } | Inst::TrapIf { .. } @@ -847,7 +846,7 @@ fn s390x_get_operands VReg>(inst: &Inst, collector: &mut OperandC collector.reg_use(link); collector.reg_uses(&rets[..]); } - &Inst::Jump { .. } | &Inst::EpiloguePlaceholder => {} + &Inst::Jump { .. } => {} &Inst::IndirectBr { rn, .. } => { collector.reg_use(rn); } @@ -903,14 +902,6 @@ impl MachInst for Inst { } } - fn is_epilogue_placeholder(&self) -> bool { - if let Inst::EpiloguePlaceholder = self { - true - } else { - false - } - } - fn is_included_in_clobbers(&self) -> bool { // We exclude call instructions from the clobber-set when they are calls // from caller to callee with the same ABI. Such calls cannot possibly @@ -928,7 +919,7 @@ impl MachInst for Inst { fn is_term(&self) -> MachTerminator { match self { - &Inst::Ret { .. } | &Inst::EpiloguePlaceholder => MachTerminator::Ret, + &Inst::Ret { .. } => MachTerminator::Ret, &Inst::Jump { .. } => MachTerminator::Uncond, &Inst::CondBr { .. } => MachTerminator::Cond, &Inst::OneWayCondBr { .. } => { @@ -2778,7 +2769,6 @@ impl Inst { let link = pretty_print_reg(link, allocs); format!("br {}", link) } - &Inst::EpiloguePlaceholder => "epilogue placeholder".to_string(), &Inst::Jump { dest } => { let dest = dest.to_string(); format!("jg {}", dest) diff --git a/cranelift/codegen/src/isa/s390x/lower.isle b/cranelift/codegen/src/isa/s390x/lower.isle index 5978eeaa89..09aff638b0 100644 --- a/cranelift/codegen/src/isa/s390x/lower.isle +++ b/cranelift/codegen/src/isa/s390x/lower.isle @@ -3551,14 +3551,11 @@ (side_effect (trap_if_impl (mask_as_cond 3) trap_code))) -;;;; Rules for `return` and `fallthrough_return` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;; Rules for `return` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (rule (lower (return args)) (lower_return (range 0 (value_slice_len args)) args)) -(rule (lower (fallthrough_return args)) - (lower_return (range 0 (value_slice_len args)) args)) - (decl lower_return (Range ValueSlice) InstOutput) (rule (lower_return (range_empty) _) (output_none)) (rule (lower_return (range_unwrap head tail) args) diff --git a/cranelift/codegen/src/isa/s390x/lower.rs b/cranelift/codegen/src/isa/s390x/lower.rs index df93c47023..abd28679ce 100644 --- a/cranelift/codegen/src/isa/s390x/lower.rs +++ b/cranelift/codegen/src/isa/s390x/lower.rs @@ -177,7 +177,6 @@ impl LowerBackend for S390xBackend { | Opcode::Debugtrap | Opcode::Call | Opcode::CallIndirect - | Opcode::FallthroughReturn | Opcode::Return | Opcode::StackAddr | Opcode::FuncAddr diff --git a/cranelift/codegen/src/isa/s390x/mod.rs b/cranelift/codegen/src/isa/s390x/mod.rs index 3ecb85886b..f474eac058 100644 --- a/cranelift/codegen/src/isa/s390x/mod.rs +++ b/cranelift/codegen/src/isa/s390x/mod.rs @@ -55,9 +55,8 @@ impl S390xBackend { fn compile_vcode( &self, func: &Function, - flags: shared_settings::Flags, ) -> CodegenResult<(VCode, regalloc2::Output)> { - let emit_info = EmitInfo::new(flags.clone(), self.isa_flags.clone()); + let emit_info = EmitInfo::new(self.isa_flags.clone()); let abi = Box::new(abi::S390xABICallee::new(func, self)?); compile::compile::(func, self, abi, &self.machine_env, emit_info) } @@ -66,7 +65,7 @@ impl S390xBackend { impl TargetIsa for S390xBackend { fn compile_function(&self, func: &Function, want_disasm: bool) -> CodegenResult { let flags = self.flags(); - let (vcode, regalloc_result) = self.compile_vcode(func, flags.clone())?; + let (vcode, regalloc_result) = self.compile_vcode(func)?; let emit_result = vcode.emit(®alloc_result, want_disasm, flags.machine_code_cfg_info()); let frame_size = emit_result.frame_size; diff --git a/cranelift/codegen/src/isa/x64/abi.rs b/cranelift/codegen/src/isa/x64/abi.rs index 65954c8051..616ea12b45 100644 --- a/cranelift/codegen/src/isa/x64/abi.rs +++ b/cranelift/codegen/src/isa/x64/abi.rs @@ -20,60 +20,6 @@ use std::convert::TryFrom; /// with 32-bit arithmetic: for now, 128 MB. static STACK_ARG_RET_SIZE_LIMIT: u64 = 128 * 1024 * 1024; -/// Offset in stack-arg area to callee-TLS slot in Baldrdash-2020 calling convention. -static BALDRDASH_CALLEE_TLS_OFFSET: i64 = 0; -/// Offset in stack-arg area to caller-TLS slot in Baldrdash-2020 calling convention. -static BALDRDASH_CALLER_TLS_OFFSET: i64 = 8; - -/// Try to fill a Baldrdash register, returning it if it was found. -fn try_fill_baldrdash_reg(call_conv: CallConv, param: &ir::AbiParam) -> Option { - if call_conv.extends_baldrdash() { - match ¶m.purpose { - &ir::ArgumentPurpose::VMContext => { - // This is SpiderMonkey's `WasmTlsReg`. - Some(ABIArg::reg( - regs::r14().to_real_reg().unwrap(), - types::I64, - param.extension, - param.purpose, - )) - } - &ir::ArgumentPurpose::SignatureId => { - // This is SpiderMonkey's `WasmTableCallSigReg`. - Some(ABIArg::reg( - regs::r10().to_real_reg().unwrap(), - types::I64, - param.extension, - param.purpose, - )) - } - &ir::ArgumentPurpose::CalleeTLS => { - // This is SpiderMonkey's callee TLS slot in the extended frame of Wasm's ABI-2020. - assert!(call_conv == isa::CallConv::Baldrdash2020); - Some(ABIArg::stack( - BALDRDASH_CALLEE_TLS_OFFSET, - ir::types::I64, - ir::ArgumentExtension::None, - param.purpose, - )) - } - &ir::ArgumentPurpose::CallerTLS => { - // This is SpiderMonkey's caller TLS slot in the extended frame of Wasm's ABI-2020. - assert!(call_conv == isa::CallConv::Baldrdash2020); - Some(ABIArg::stack( - BALDRDASH_CALLER_TLS_OFFSET, - ir::types::I64, - ir::ArgumentExtension::None, - param.purpose, - )) - } - _ => None, - } - } else { - None - } -} - /// Support for the x64 ABI from the callee side (within a function body). pub(crate) type X64ABICallee = ABICalleeImpl; @@ -102,9 +48,7 @@ impl ABIMachineSpec for X64ABIMachineSpec { args_or_rets: ArgsOrRets, add_ret_area_ptr: bool, ) -> CodegenResult<(Vec, i64, Option)> { - let is_baldrdash = call_conv.extends_baldrdash(); let is_fastcall = call_conv.extends_windows_fastcall(); - let has_baldrdash_tls = call_conv == isa::CallConv::Baldrdash2020; let mut next_gpr = 0; let mut next_vreg = 0; @@ -121,29 +65,13 @@ impl ABIMachineSpec for X64ABIMachineSpec { next_stack = 32; } - if args_or_rets == ArgsOrRets::Args && has_baldrdash_tls { - // Baldrdash ABI-2020 always has two stack-arg slots reserved, for the callee and - // caller TLS-register values, respectively. - next_stack = 16; - } - - for i in 0..params.len() { - // Process returns backward, according to the SpiderMonkey ABI (which we - // adopt internally if `is_baldrdash` is set). - let param = match (args_or_rets, is_baldrdash) { - (ArgsOrRets::Args, _) => ¶ms[i], - (ArgsOrRets::Rets, false) => ¶ms[i], - (ArgsOrRets::Rets, true) => ¶ms[params.len() - 1 - i], - }; - + for param in params { // Validate "purpose". match ¶m.purpose { &ir::ArgumentPurpose::VMContext | &ir::ArgumentPurpose::Normal | &ir::ArgumentPurpose::StackLimit | &ir::ArgumentPurpose::SignatureId - | &ir::ArgumentPurpose::CalleeTLS - | &ir::ArgumentPurpose::CallerTLS | &ir::ArgumentPurpose::StructReturn | &ir::ArgumentPurpose::StructArgument(_) => {} _ => panic!( @@ -152,11 +80,6 @@ impl ABIMachineSpec for X64ABIMachineSpec { ), } - if let Some(param) = try_fill_baldrdash_reg(call_conv, param) { - ret.push(param); - continue; - } - if let ir::ArgumentPurpose::StructArgument(size) = param.purpose { let offset = next_stack as i64; let size = size as u64; @@ -269,10 +192,6 @@ impl ABIMachineSpec for X64ABIMachineSpec { }); } - if args_or_rets == ArgsOrRets::Rets && is_baldrdash { - ret.reverse(); - } - let extra_arg = if add_ret_area_ptr { debug_assert!(args_or_rets == ArgsOrRets::Args); if let Some(reg) = get_intreg_for_arg(&call_conv, next_gpr, next_param_idx) { @@ -306,14 +225,8 @@ impl ABIMachineSpec for X64ABIMachineSpec { Ok((ret, next_stack as i64, extra_arg)) } - fn fp_to_arg_offset(call_conv: isa::CallConv, flags: &settings::Flags) -> i64 { - if call_conv.extends_baldrdash() { - let num_words = flags.baldrdash_prologue_words() as i64; - debug_assert!(num_words > 0, "baldrdash must set baldrdash_prologue_words"); - num_words * 8 - } else { - 16 // frame pointer + return address. - } + fn fp_to_arg_offset(_call_conv: isa::CallConv, _flags: &settings::Flags) -> i64 { + 16 // frame pointer + return address. } fn gen_load_stack(mem: StackAMode, into_reg: Writable, ty: Type) -> Self::I { @@ -361,10 +274,6 @@ impl ABIMachineSpec for X64ABIMachineSpec { Inst::ret(rets) } - fn gen_epilogue_placeholder() -> Self::I { - Inst::epilogue_placeholder() - } - fn gen_add_imm(into_reg: Writable, from_reg: Reg, imm: u32) -> SmallInstVec { let mut ret = SmallVec::new(); if from_reg != into_reg.to_reg() { @@ -396,10 +305,10 @@ impl ABIMachineSpec for X64ABIMachineSpec { } fn get_stacklimit_reg() -> Reg { - debug_assert!( - !is_callee_save_systemv(regs::r10().to_real_reg().unwrap(), false) - && !is_callee_save_baldrdash(regs::r10().to_real_reg().unwrap()) - ); + debug_assert!(!is_callee_save_systemv( + regs::r10().to_real_reg().unwrap(), + false + )); // As per comment on trait definition, we must return a caller-save // register here. @@ -621,17 +530,6 @@ impl ABIMachineSpec for X64ABIMachineSpec { )); } - // If this is Baldrdash-2020, restore the callee (i.e., our) TLS - // register. We may have allocated it for something else and clobbered - // it, but the ABI expects us to leave the TLS register unchanged. - if call_conv == isa::CallConv::Baldrdash2020 { - let off = BALDRDASH_CALLEE_TLS_OFFSET + Self::fp_to_arg_offset(call_conv, flags); - insts.push(Inst::mov64_m_r( - Amode::imm_reg(off as u32, regs::rbp()), - Writable::from_reg(regs::r14()), - )); - } - insts } @@ -684,8 +582,6 @@ impl ABIMachineSpec for X64ABIMachineSpec { src: Reg, size: usize, ) -> SmallVec<[Self::I; 8]> { - // Baldrdash should not use struct args. - assert!(!call_conv.extends_baldrdash()); let mut insts = SmallVec::new(); let arg0 = get_intreg_for_arg(&call_conv, 0, 0).unwrap(); let arg1 = get_intreg_for_arg(&call_conv, 1, 1).unwrap(); @@ -741,33 +637,18 @@ impl ABIMachineSpec for X64ABIMachineSpec { } fn get_regs_clobbered_by_call(call_conv_of_callee: isa::CallConv) -> PRegSet { - let mut clobbers = if call_conv_of_callee.extends_windows_fastcall() { + if call_conv_of_callee.extends_windows_fastcall() { WINDOWS_CLOBBERS } else { SYSV_CLOBBERS - }; - - if call_conv_of_callee.extends_baldrdash() { - clobbers.add(regs::gpr_preg(regs::ENC_R12)); - clobbers.add(regs::gpr_preg(regs::ENC_R13)); - clobbers.add(regs::gpr_preg(regs::ENC_R15)); - clobbers.add(regs::gpr_preg(regs::ENC_RBX)); } - - clobbers } fn get_ext_mode( - call_conv: isa::CallConv, - specified: ir::ArgumentExtension, + _call_conv: isa::CallConv, + _specified: ir::ArgumentExtension, ) -> ir::ArgumentExtension { - if call_conv.extends_baldrdash() { - // Baldrdash (SpiderMonkey) always extends args and return values to the full register. - specified - } else { - // No other supported ABI on x64 does so. - ir::ArgumentExtension::None - } + ir::ArgumentExtension::None } fn get_clobbered_callee_saves( @@ -777,14 +658,6 @@ impl ABIMachineSpec for X64ABIMachineSpec { regs: &[Writable], ) -> Vec> { let mut regs: Vec> = match call_conv { - CallConv::BaldrdashSystemV | CallConv::Baldrdash2020 => regs - .iter() - .cloned() - .filter(|r| is_callee_save_baldrdash(r.to_reg())) - .collect(), - CallConv::BaldrdashWindows => { - todo!("baldrdash windows"); - } CallConv::Fast | CallConv::Cold | CallConv::SystemV | CallConv::WasmtimeSystemV => regs .iter() .cloned() @@ -905,10 +778,7 @@ fn get_intreg_for_retval( 1 => Some(regs::rdx()), _ => None, }, - CallConv::BaldrdashSystemV - | CallConv::Baldrdash2020 - | CallConv::WasmtimeSystemV - | CallConv::WasmtimeFastcall => { + CallConv::WasmtimeSystemV | CallConv::WasmtimeFastcall => { if intreg_idx == 0 && retval_idx == 0 { Some(regs::rax()) } else { @@ -920,7 +790,7 @@ fn get_intreg_for_retval( 1 => Some(regs::rdx()), // The Rust ABI for i128s needs this. _ => None, }, - CallConv::BaldrdashWindows | CallConv::Probestack => todo!(), + CallConv::Probestack => todo!(), CallConv::AppleAarch64 | CallConv::WasmtimeAppleAarch64 => unreachable!(), } } @@ -936,10 +806,7 @@ fn get_fltreg_for_retval( 1 => Some(regs::xmm1()), _ => None, }, - CallConv::BaldrdashSystemV - | CallConv::Baldrdash2020 - | CallConv::WasmtimeFastcall - | CallConv::WasmtimeSystemV => { + CallConv::WasmtimeFastcall | CallConv::WasmtimeSystemV => { if fltreg_idx == 0 && retval_idx == 0 { Some(regs::xmm0()) } else { @@ -950,7 +817,7 @@ fn get_fltreg_for_retval( 0 => Some(regs::xmm0()), _ => None, }, - CallConv::BaldrdashWindows | CallConv::Probestack => todo!(), + CallConv::Probestack => todo!(), CallConv::AppleAarch64 | CallConv::WasmtimeAppleAarch64 => unreachable!(), } } @@ -970,22 +837,6 @@ fn is_callee_save_systemv(r: RealReg, enable_pinned_reg: bool) -> bool { } } -fn is_callee_save_baldrdash(r: RealReg) -> bool { - use regs::*; - match r.class() { - RegClass::Int => { - if r.hw_enc() == ENC_R14 { - // r14 is the WasmTlsReg and is preserved implicitly. - false - } else { - // Defer to native for the other ones. - is_callee_save_systemv(r, /* enable_pinned_reg = */ true) - } - } - RegClass::Float => false, - } -} - fn is_callee_save_fastcall(r: RealReg, enable_pinned_reg: bool) -> bool { use regs::*; match r.class() { diff --git a/cranelift/codegen/src/isa/x64/inst.isle b/cranelift/codegen/src/isa/x64/inst.isle index 519688813f..382e8f5b41 100644 --- a/cranelift/codegen/src/isa/x64/inst.isle +++ b/cranelift/codegen/src/isa/x64/inst.isle @@ -331,14 +331,9 @@ ;; Return. (Ret (rets VecReg)) - ;; A placeholder instruction, generating no code, meaning that a function - ;; epilogue must be inserted there. - (EpiloguePlaceholder) - ;; Jump to a known target: jmp simm32. (JmpKnown (dst MachLabel)) - ;; One-way conditional branch: jcond cond target. ;; ;; This instruction is useful when we have conditional jumps depending on diff --git a/cranelift/codegen/src/isa/x64/inst/emit.rs b/cranelift/codegen/src/isa/x64/inst/emit.rs index 9552993ee0..9cb4f93765 100644 --- a/cranelift/codegen/src/isa/x64/inst/emit.rs +++ b/cranelift/codegen/src/isa/x64/inst/emit.rs @@ -2646,11 +2646,7 @@ pub(crate) fn emit( sink.put1(0x48 | ((enc_dst >> 3) & 1)); sink.put1(0xB8 | (enc_dst & 7)); emit_reloc(sink, Reloc::Abs8, name, *offset); - if info.flags.emit_all_ones_funcaddrs() { - sink.put8(u64::max_value()); - } else { - sink.put8(0); - } + sink.put8(0); } } @@ -2918,10 +2914,6 @@ pub(crate) fn emit( } } - Inst::EpiloguePlaceholder => { - // Generate no code. - } - Inst::ElfTlsGetAddr { ref symbol } => { // N.B.: Must be exactly this byte sequence; the linker requires it, // because it must know how to rewrite the bytes. diff --git a/cranelift/codegen/src/isa/x64/inst/mod.rs b/cranelift/codegen/src/isa/x64/inst/mod.rs index 4ceda3198b..924fef0c86 100644 --- a/cranelift/codegen/src/isa/x64/inst/mod.rs +++ b/cranelift/codegen/src/isa/x64/inst/mod.rs @@ -77,7 +77,6 @@ impl Inst { | Inst::CvtFloatToUintSeq { .. } | Inst::CvtUint64ToFloatSeq { .. } | Inst::Div { .. } - | Inst::EpiloguePlaceholder | Inst::Fence { .. } | Inst::Hlt | Inst::Imm { .. } @@ -725,10 +724,6 @@ impl Inst { Inst::Ret { rets } } - pub(crate) fn epilogue_placeholder() -> Inst { - Inst::EpiloguePlaceholder - } - pub(crate) fn jmp_known(dst: MachLabel) -> Inst { Inst::JmpKnown { dst } } @@ -1629,8 +1624,6 @@ impl PrettyPrint for Inst { Inst::Ret { .. } => "ret".to_string(), - Inst::EpiloguePlaceholder => "epilogue placeholder".to_string(), - Inst::JmpKnown { dst } => { format!("{} {}", ljustify("jmp".to_string()), dst.to_string()) } @@ -2170,8 +2163,7 @@ fn x64_get_operands VReg>(inst: &Inst, collector: &mut OperandCol } } - Inst::EpiloguePlaceholder - | Inst::JmpKnown { .. } + Inst::JmpKnown { .. } | Inst::JmpIf { .. } | Inst::JmpCond { .. } | Inst::Nop { .. } @@ -2247,18 +2239,10 @@ impl MachInst for Inst { } } - fn is_epilogue_placeholder(&self) -> bool { - if let Self::EpiloguePlaceholder = self { - true - } else { - false - } - } - fn is_term(&self) -> MachTerminator { match self { // Interesting cases. - &Self::Ret { .. } | &Self::EpiloguePlaceholder => MachTerminator::Ret, + &Self::Ret { .. } => MachTerminator::Ret, &Self::JmpKnown { .. } => MachTerminator::Uncond, &Self::JmpCond { .. } => MachTerminator::Cond, &Self::JmpTableSeq { .. } => MachTerminator::Indirect, diff --git a/cranelift/codegen/src/isa/x64/lower.isle b/cranelift/codegen/src/isa/x64/lower.isle index 24e0672018..7b0cd26a13 100644 --- a/cranelift/codegen/src/isa/x64/lower.isle +++ b/cranelift/codegen/src/isa/x64/lower.isle @@ -1475,15 +1475,12 @@ (rule (lower (resumable_trap code)) (side_effect (x64_ud2 code))) -;;;; Rules for `return` and `fallthrough_return` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;; Rules for `return` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; N.B.: the Ret itself is generated by the ABI. (rule (lower (return args)) (lower_return (range 0 (value_slice_len args)) args)) -(rule (lower (fallthrough_return args)) - (lower_return (range 0 (value_slice_len args)) args)) - (decl lower_return (Range ValueSlice) InstOutput) (rule (lower_return (range_empty) _) (output_none)) (rule (lower_return (range_unwrap head tail) args) diff --git a/cranelift/codegen/src/isa/x64/lower.rs b/cranelift/codegen/src/isa/x64/lower.rs index 2fd5c2e8dd..18ed87b6ad 100644 --- a/cranelift/codegen/src/isa/x64/lower.rs +++ b/cranelift/codegen/src/isa/x64/lower.rs @@ -6,8 +6,8 @@ pub(super) mod isle; use crate::data_value::DataValue; use crate::ir::{ condcodes::{CondCode, FloatCC, IntCC}, - types, AbiParam, ArgumentPurpose, ExternalName, Inst as IRInst, InstructionData, LibCall, - Opcode, Signature, Type, + types, AbiParam, ExternalName, Inst as IRInst, InstructionData, LibCall, Opcode, Signature, + Type, }; use crate::isa::x64::abi::*; use crate::isa::x64::inst::args::*; @@ -577,7 +577,6 @@ fn make_libcall_sig>( ctx: &mut C, insn: IRInst, call_conv: CallConv, - ptr_ty: Type, ) -> Signature { let mut sig = Signature::new(call_conv); for i in 0..ctx.num_inputs(insn) { @@ -586,11 +585,6 @@ fn make_libcall_sig>( for i in 0..ctx.num_outputs(insn) { sig.returns.push(AbiParam::new(ctx.output_ty(insn, i))); } - if call_conv.extends_baldrdash() { - // Adds the special VMContext parameter to the signature. - sig.params - .push(AbiParam::special(ptr_ty, ArgumentPurpose::VMContext)); - } sig } @@ -613,26 +607,19 @@ fn emit_vm_call>( // TODO avoid recreating signatures for every single Libcall function. let call_conv = CallConv::for_libcall(flags, CallConv::triple_default(triple)); - let sig = make_libcall_sig(ctx, insn, call_conv, types::I64); + let sig = make_libcall_sig(ctx, insn, call_conv); let caller_conv = ctx.abi().call_conv(); let mut abi = X64ABICaller::from_func(&sig, &extname, dist, caller_conv, flags)?; abi.emit_stack_pre_adjust(ctx); - let vm_context = if call_conv.extends_baldrdash() { 1 } else { 0 }; - assert_eq!(inputs.len() + vm_context, abi.num_args()); + assert_eq!(inputs.len(), abi.num_args()); for (i, input) in inputs.iter().enumerate() { let arg_reg = put_input_in_reg(ctx, *input); abi.emit_copy_regs_to_arg(ctx, i, ValueRegs::one(arg_reg)); } - if call_conv.extends_baldrdash() { - let vm_context_vreg = ctx - .get_vm_context() - .expect("should have a VMContext to pass to libcall funcs"); - abi.emit_copy_regs_to_arg(ctx, inputs.len(), ValueRegs::one(vm_context_vreg)); - } abi.emit_call(ctx); for (i, output) in outputs.iter().enumerate() { @@ -923,7 +910,6 @@ fn lower_insn_to_regs>( | Opcode::Fence | Opcode::FuncAddr | Opcode::SymbolValue - | Opcode::FallthroughReturn | Opcode::Return | Opcode::Call | Opcode::CallIndirect diff --git a/cranelift/codegen/src/machinst/abi.rs b/cranelift/codegen/src/machinst/abi.rs index db9936efe8..8a26964ab3 100644 --- a/cranelift/codegen/src/machinst/abi.rs +++ b/cranelift/codegen/src/machinst/abi.rs @@ -89,11 +89,6 @@ pub trait ABICallee { /// Generate a return instruction. fn gen_ret(&self) -> Self::I; - /// Generate an epilogue placeholder. The returned instruction should return `true` from - /// `is_epilogue_placeholder()`; this is used to indicate to the lowering driver when - /// the epilogue should be inserted. - fn gen_epilogue_placeholder(&self) -> Self::I; - // ----------------------------------------------------------------- // Every function above this line may only be called pre-regalloc. // Every function below this line may only be called post-regalloc. @@ -159,9 +154,7 @@ pub trait ABICallee { /// Returns the full frame size for the given function, after prologue /// emission has run. This comprises the spill slots and stack-storage slots /// (but not storage for clobbered callee-save registers, arguments pushed - /// at callsites within this function, or other ephemeral pushes). This is - /// used for ABI variants where the client generates prologue/epilogue code, - /// as in Baldrdash (SpiderMonkey integration). + /// at callsites within this function, or other ephemeral pushes). fn frame_size(&self) -> u32; /// Returns the size of arguments expected on the stack. diff --git a/cranelift/codegen/src/machinst/abi_impl.rs b/cranelift/codegen/src/machinst/abi_impl.rs index 622813894f..3ab06f397e 100644 --- a/cranelift/codegen/src/machinst/abi_impl.rs +++ b/cranelift/codegen/src/machinst/abi_impl.rs @@ -97,31 +97,9 @@ //! //! # Multi-value Returns //! -//! Note that we support multi-value returns in two ways. First, we allow for -//! multiple return-value registers. Second, if teh appropriate flag is set, we -//! support the SpiderMonkey Wasm ABI. For details of the multi-value return -//! ABI, see: -//! -//! -//! -//! In brief: -//! - Return values are processed in *reverse* order. -//! - The first return value in this order (so the last return) goes into the -//! ordinary return register. -//! - Any further returns go in a struct-return area, allocated upwards (in -//! address order) during the reverse traversal. -//! - This struct-return area is provided by the caller, and a pointer to its -//! start is passed as an invisible last (extra) argument. Normally the caller -//! will allocate this area on the stack. When we generate calls, we place it -//! just above the on-stack argument area. -//! - So, for example, a function returning 4 i64's (v0, v1, v2, v3), with no -//! formal arguments, would: -//! - Accept a pointer `P` to the struct return area as a hidden argument in the -//! first argument register on entry. -//! - Return v3 in the one and only return-value register. -//! - Return v2 in memory at `[P]`. -//! - Return v1 in memory at `[P+8]`. -//! - Return v0 in memory at `[P+16]`. +//! We support multi-value returns by using multiple return-value +//! registers. In some cases this is an extension of the base system +//! ABI. See each platform's `abi.rs` implementation for details. use super::abi::*; use crate::binemit::StackMap; @@ -212,14 +190,6 @@ pub enum ABIArg { } impl ABIArg { - /// Get the purpose of this arg. - fn get_purpose(&self) -> ir::ArgumentPurpose { - match self { - &ABIArg::Slots { purpose, .. } => purpose, - &ABIArg::StructArg { purpose, .. } => purpose, - } - } - /// Is this a StructArg? fn is_struct_arg(&self) -> bool { match self { @@ -367,10 +337,6 @@ pub trait ABIMachineSpec { /// Generate a return instruction. fn gen_ret(rets: Vec) -> Self::I; - /// Generate an "epilogue placeholder" instruction, recognized by lowering - /// when using the Baldrdash ABI. - fn gen_epilogue_placeholder() -> Self::I; - /// Generate an add-with-immediate. Note that even if this uses a scratch /// register, it must satisfy two requirements: /// @@ -734,8 +700,7 @@ pub struct ABICalleeImpl { /// Total number of spillslots, including for 'dynamic' types, from regalloc. spillslots: Option, /// Storage allocated for the fixed part of the stack frame. This is - /// usually the same as the total frame size below, except in the case - /// of the baldrdash calling convention. + /// usually the same as the total frame size below. fixed_frame_storage_size: u32, /// "Total frame size", as defined by "distance between FP and nominal SP". /// Some items are pushed below nominal SP, so the function may actually use @@ -803,7 +768,6 @@ impl ABICalleeImpl { call_conv == isa::CallConv::SystemV || call_conv == isa::CallConv::Fast || call_conv == isa::CallConv::Cold - || call_conv.extends_baldrdash() || call_conv.extends_windows_fastcall() || call_conv == isa::CallConv::AppleAarch64 || call_conv == isa::CallConv::WasmtimeSystemV @@ -1164,14 +1128,8 @@ impl ABICallee for ABICalleeImpl { insts } - fn arg_is_needed_in_body(&self, idx: usize) -> bool { - match self.sig.args[idx].get_purpose() { - // Special Baldrdash-specific pseudo-args that are present only to - // fill stack slots. Won't ever be used as ordinary values in the - // body. - ir::ArgumentPurpose::CalleeTLS | ir::ArgumentPurpose::CallerTLS => false, - _ => true, - } + fn arg_is_needed_in_body(&self, _idx: usize) -> bool { + true } fn gen_copy_regs_to_retval( @@ -1296,10 +1254,6 @@ impl ABICallee for ABICalleeImpl { M::gen_ret(rets) } - fn gen_epilogue_placeholder(&self) -> Self::I { - M::gen_epilogue_placeholder() - } - fn set_num_spillslots(&mut self, slots: usize) { self.spillslots = Some(slots); } @@ -1400,14 +1354,7 @@ impl ABICallee for ABICalleeImpl { fn gen_prologue(&mut self) -> SmallInstVec { let bytes = M::word_bytes(); - let mut total_stacksize = self.stackslots_size + bytes * self.spillslots.unwrap() as u32; - if self.call_conv.extends_baldrdash() { - debug_assert!( - !self.flags.enable_probestack(), - "baldrdash does not expect cranelift to emit stack probes" - ); - total_stacksize += self.flags.baldrdash_prologue_words() as u32 * bytes; - } + let total_stacksize = self.stackslots_size + bytes * self.spillslots.unwrap() as u32; let mask = M::stack_align(self.call_conv) - 1; let total_stacksize = (total_stacksize + mask) & !mask; // 16-align the stack. let clobbered_callee_saves = M::get_clobbered_callee_saves( @@ -1418,36 +1365,34 @@ impl ABICallee for ABICalleeImpl { ); let mut insts = smallvec![]; - if !self.call_conv.extends_baldrdash() { - self.fixed_frame_storage_size += total_stacksize; - self.setup_frame = self.flags.preserve_frame_pointers() - || M::is_frame_setup_needed( - self.is_leaf, - self.stack_args_size(), - clobbered_callee_saves.len(), - self.fixed_frame_storage_size, - ); - - insts.extend( - M::gen_debug_frame_info(self.call_conv, &self.flags, &self.isa_flags).into_iter(), + self.fixed_frame_storage_size += total_stacksize; + self.setup_frame = self.flags.preserve_frame_pointers() + || M::is_frame_setup_needed( + self.is_leaf, + self.stack_args_size(), + clobbered_callee_saves.len(), + self.fixed_frame_storage_size, ); - if self.setup_frame { - // set up frame - insts.extend(M::gen_prologue_frame_setup(&self.flags).into_iter()); - } + insts.extend( + M::gen_debug_frame_info(self.call_conv, &self.flags, &self.isa_flags).into_iter(), + ); - // Leaf functions with zero stack don't need a stack check if one's - // specified, otherwise always insert the stack check. - if total_stacksize > 0 || !self.is_leaf { - if let Some((reg, stack_limit_load)) = &self.stack_limit { - insts.extend(stack_limit_load.clone()); - self.insert_stack_check(*reg, total_stacksize, &mut insts); - } - if let Some(min_frame) = &self.probestack_min_frame { - if total_stacksize >= *min_frame { - insts.extend(M::gen_probestack(total_stacksize)); - } + if self.setup_frame { + // set up frame + insts.extend(M::gen_prologue_frame_setup(&self.flags).into_iter()); + } + + // Leaf functions with zero stack don't need a stack check if one's + // specified, otherwise always insert the stack check. + if total_stacksize > 0 || !self.is_leaf { + if let Some((reg, stack_limit_load)) = &self.stack_limit { + insts.extend(stack_limit_load.clone()); + self.insert_stack_check(*reg, total_stacksize, &mut insts); + } + if let Some(min_frame) = &self.probestack_min_frame { + if total_stacksize >= *min_frame { + insts.extend(M::gen_probestack(total_stacksize)); } } } @@ -1497,17 +1442,15 @@ impl ABICallee for ABICalleeImpl { // the CFG, so early returns in the middle of function bodies would cause an incorrect // offset for the rest of the body. - if !self.call_conv.extends_baldrdash() { - if self.setup_frame { - insts.extend(M::gen_epilogue_frame_restore(&self.flags)); - } - - // This `ret` doesn't need any return registers attached - // because we are post-regalloc and don't need to - // represent the implicit uses anymore. - insts.push(M::gen_ret(vec![])); + if self.setup_frame { + insts.extend(M::gen_epilogue_frame_restore(&self.flags)); } + // This `ret` doesn't need any return registers attached + // because we are post-regalloc and don't need to + // represent the implicit uses anymore. + insts.push(M::gen_ret(vec![])); + trace!("Epilogue: {:?}", insts); insts } diff --git a/cranelift/codegen/src/machinst/blockorder.rs b/cranelift/codegen/src/machinst/blockorder.rs index 8ce06abc7a..79503ae4c4 100644 --- a/cranelift/codegen/src/machinst/blockorder.rs +++ b/cranelift/codegen/src/machinst/blockorder.rs @@ -223,7 +223,6 @@ impl BlockLoweringOrder { // Cache the block successors to avoid re-examining branches below. let mut block_succs: SmallVec<[(Inst, usize, Block); 128]> = SmallVec::new(); let mut block_succ_range = SecondaryMap::with_default((0, 0)); - let mut fallthrough_return_block = None; for block in f.layout.blocks() { let block_succ_start = block_succs.len(); let mut succ_idx = 0; @@ -241,11 +240,6 @@ impl BlockLoweringOrder { // Implicit output edge for any return. block_out_count[block] += 1; } - if f.dfg[inst].opcode() == Opcode::FallthroughReturn { - // Fallthrough return block must come last. - debug_assert!(fallthrough_return_block == None); - fallthrough_return_block = Some(block); - } } } // Implicit input edge for entry block. @@ -396,17 +390,11 @@ impl BlockLoweringOrder { }); } - let mut deferred_last = None; while !stack.is_empty() { let stack_entry = stack.last_mut().unwrap(); let range = stack_entry.succs; if stack_entry.cur_succ == range.0 { - let orig_block = stack_entry.this.orig_block(); - if orig_block.is_some() && orig_block == fallthrough_return_block { - deferred_last = Some((stack_entry.this, range)); - } else { - postorder.push((stack_entry.this, range)); - } + postorder.push((stack_entry.this, range)); stack.pop(); } else { // Heuristic: chase the children in reverse. This puts the first @@ -431,10 +419,7 @@ impl BlockLoweringOrder { } postorder.reverse(); - let mut rpo = postorder; - if let Some(d) = deferred_last { - rpo.push(d); - } + let rpo = postorder; // Step 3: now that we have RPO, build the BlockIndex/BB fwd/rev maps. let mut lowered_order = vec![]; diff --git a/cranelift/codegen/src/machinst/buffer.rs b/cranelift/codegen/src/machinst/buffer.rs index b7ec06d2f6..44a7b9be30 100644 --- a/cranelift/codegen/src/machinst/buffer.rs +++ b/cranelift/codegen/src/machinst/buffer.rs @@ -1672,7 +1672,6 @@ mod test { buf.bind_label(label(1)); let inst = Inst::Udf { - use_allocated_encoding: true, trap_code: TrapCode::Interrupt, }; inst.emit(&[], &mut buf, &info, &mut state); diff --git a/cranelift/codegen/src/machinst/isle.rs b/cranelift/codegen/src/machinst/isle.rs index f463f6e883..7d46b8ba79 100644 --- a/cranelift/codegen/src/machinst/isle.rs +++ b/cranelift/codegen/src/machinst/isle.rs @@ -615,11 +615,6 @@ macro_rules! isle_prelude_methods { } } - #[inline] - fn is_not_baldrdash_call_conv(&mut self) -> Option { - Some(!self.lower_ctx.abi().call_conv().extends_baldrdash()) - } - #[inline] fn func_ref_data(&mut self, func_ref: FuncRef) -> (SigRef, ExternalName, RelocDistance) { let funcdata = &self.lower_ctx.dfg().ext_funcs[func_ref]; diff --git a/cranelift/codegen/src/machinst/lower.rs b/cranelift/codegen/src/machinst/lower.rs index ff7d84c8d7..77291dd0f9 100644 --- a/cranelift/codegen/src/machinst/lower.rs +++ b/cranelift/codegen/src/machinst/lower.rs @@ -475,11 +475,6 @@ fn alloc_vregs( Ok(regs) } -enum GenerateReturn { - Yes, - No, -} - impl<'func, I: VCodeInst> Lower<'func, I> { /// Prepare a new lowering context for the given IR function. pub fn new( @@ -752,7 +747,7 @@ impl<'func, I: VCodeInst> Lower<'func, I> { } } - fn gen_retval_setup(&mut self, gen_ret_inst: GenerateReturn) { + fn gen_retval_setup(&mut self) { let retval_regs = self.retval_regs.clone(); for (i, regs) in retval_regs.into_iter().enumerate() { let regs = writable_value_regs(regs); @@ -765,10 +760,7 @@ impl<'func, I: VCodeInst> Lower<'func, I> { self.emit(insn); } } - let inst = match gen_ret_inst { - GenerateReturn::Yes => self.vcode.abi().gen_ret(), - GenerateReturn::No => self.vcode.abi().gen_epilogue_placeholder(), - }; + let inst = self.vcode.abi().gen_ret(); self.emit(inst); // Hack: generate a virtual instruction that uses vmctx in @@ -867,13 +859,7 @@ impl<'func, I: VCodeInst> Lower<'func, I> { } if data.opcode().is_return() { // Return: handle specially, using ABI-appropriate sequence. - let gen_ret = if data.opcode() == Opcode::Return { - GenerateReturn::Yes - } else { - debug_assert!(data.opcode() == Opcode::FallthroughReturn); - GenerateReturn::No - }; - self.gen_retval_setup(gen_ret); + self.gen_retval_setup(); } let loc = self.srcloc(inst); diff --git a/cranelift/codegen/src/machinst/mod.rs b/cranelift/codegen/src/machinst/mod.rs index 953aa83ea8..fc7bb0abfa 100644 --- a/cranelift/codegen/src/machinst/mod.rs +++ b/cranelift/codegen/src/machinst/mod.rs @@ -96,9 +96,6 @@ pub trait MachInst: Clone + Debug { /// (ret/uncond/cond) and target if applicable. fn is_term(&self) -> MachTerminator; - /// Returns true if the instruction is an epilogue placeholder. - fn is_epilogue_placeholder(&self) -> bool; - /// Should this instruction be included in the clobber-set? fn is_included_in_clobbers(&self) -> bool { true diff --git a/cranelift/codegen/src/prelude.isle b/cranelift/codegen/src/prelude.isle index 381327b1cb..785d7652b8 100644 --- a/cranelift/codegen/src/prelude.isle +++ b/cranelift/codegen/src/prelude.isle @@ -717,9 +717,6 @@ (decl avoid_div_traps () Type) (extern extractor avoid_div_traps avoid_div_traps) -(decl pure is_not_baldrdash_call_conv () bool) -(extern constructor is_not_baldrdash_call_conv is_not_baldrdash_call_conv) - ;;;; Helpers for accessing instruction data ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Accessor for `FuncRef`. diff --git a/cranelift/codegen/src/settings.rs b/cranelift/codegen/src/settings.rs index cfacb4e27e..9c3c7b2262 100644 --- a/cranelift/codegen/src/settings.rs +++ b/cranelift/codegen/src/settings.rs @@ -524,7 +524,6 @@ mod tests { opt_level = "none" tls_model = "none" libcall_call_conv = "isa_default" -baldrdash_prologue_words = 0 probestack_size_log2 = 12 regalloc_checker = false regalloc_verbose_logs = false @@ -544,7 +543,6 @@ enable_llvm_abi_extensions = false unwind_info = true preserve_frame_pointers = false machine_code_cfg_info = false -emit_all_ones_funcaddrs = false enable_probestack = true probestack_func_adjusts_sp = false enable_jump_tables = true @@ -554,7 +552,6 @@ enable_table_access_spectre_mitigation = true ); assert_eq!(f.opt_level(), super::OptLevel::None); assert_eq!(f.enable_simd(), false); - assert_eq!(f.baldrdash_prologue_words(), 0); } #[test] diff --git a/cranelift/docs/ir.md b/cranelift/docs/ir.md index 31d0e83867..aae0041ffa 100644 --- a/cranelift/docs/ir.md +++ b/cranelift/docs/ir.md @@ -405,7 +405,10 @@ retlist : paramlist param : type [paramext] [paramspecial] paramext : "uext" | "sext" paramspecial : "sret" | "link" | "fp" | "csr" | "vmctx" | "sigid" | "stack_limit" -callconv : "fast" | "cold" | "system_v" | "fastcall" | "baldrdash_system_v" | "baldrdash_windows" +callconv : "fast" | "cold" | "system_v" | "windows_fastcall" + | "wasmtime_system_v" | "wasmtime_fastcall" + | "apple_aarch64" | "wasmtime_apple_aarch64" + | "probestack" ``` A function's calling convention determines exactly how arguments and return @@ -430,8 +433,6 @@ system, a function's calling convention is only fully determined by a | cold | not-ABI-stable convention for infrequently executed code | | system_v | System V-style convention used on many platforms | | fastcall | Windows "fastcall" convention, also used for x64 and ARM | -| baldrdash_system_v | SpiderMonkey WebAssembly convention on platforms natively using SystemV. | -| baldrdash_windows | SpiderMonkey WebAssembly convention on platforms natively using Windows. | The "not-ABI-stable" conventions do not follow an external specification and may change between versions of Cranelift. @@ -682,7 +683,7 @@ H = dynamic Base, min MinBytes, bound BoundGV, offset_guard OffsetGuardBytes #### Heap examples -The SpiderMonkey VM prefers to use fixed heaps with a 4 GB bound and 2 GB of +Some Wasm VMs prefer to use fixed heaps with a 4 GB bound and 2 GB of offset-guard pages when running WebAssembly code on 64-bit CPUs. The combination of a 4 GB fixed bound and 1-byte bounds checks means that no code needs to be generated for bounds checks at all: @@ -690,7 +691,7 @@ generated for bounds checks at all: ``` test verifier -function %add_members(i32, i64 vmctx) -> f32 baldrdash_system_v { +function %add_members(i32, i64 vmctx) -> f32 { gv0 = vmctx gv1 = load.i64 notrap aligned gv0+64 heap0 = static gv1, min 0x1000, bound 0x1_0000_0000, offset_guard 0x8000_0000 @@ -711,7 +712,7 @@ KB offset-guard page still has opportunities for sharing bounds checking code: ``` test verifier -function %add_members(i32, i32 vmctx) -> f32 baldrdash_system_v { +function %add_members(i32, i32 vmctx) -> f32 { gv0 = vmctx gv1 = load.i32 notrap aligned gv0+64 heap0 = static gv1, min 0x1000, bound 0x10_0000, offset_guard 0x1000 @@ -735,7 +736,7 @@ full bounds checking is required for each access: ``` test verifier -function %add_members(i32, i64 vmctx) -> f32 baldrdash_system_v { +function %add_members(i32, i64 vmctx) -> f32 { gv0 = vmctx gv1 = load.i64 notrap aligned gv0+64 gv2 = load.i32 notrap aligned gv0+72 diff --git a/cranelift/filetests/filetests/isa/aarch64/call.clif b/cranelift/filetests/filetests/isa/aarch64/call.clif index 597266f79c..2c1ce3986b 100644 --- a/cranelift/filetests/filetests/isa/aarch64/call.clif +++ b/cranelift/filetests/filetests/isa/aarch64/call.clif @@ -20,7 +20,7 @@ block0(v0: i64): ; ret function %f2(i32) -> i64 { - fn0 = %g(i32 uext) -> i64 baldrdash_system_v + fn0 = %g(i32 uext) -> i64 block0(v0: i32): v1 = call fn0(v0) @@ -29,41 +29,22 @@ block0(v0: i32): ; stp fp, lr, [sp, #-16]! ; mov fp, sp -; stp x27, x28, [sp, #-16]! -; stp x25, x26, [sp, #-16]! -; stp x23, x24, [sp, #-16]! -; stp x21, x22, [sp, #-16]! -; stp x19, x20, [sp, #-16]! -; stp d14, d15, [sp, #-16]! -; stp d12, d13, [sp, #-16]! -; stp d10, d11, [sp, #-16]! -; stp d8, d9, [sp, #-16]! ; block0: -; mov w0, w0 ; ldr x5, 8 ; b 12 ; data TestCase { length: 1, ascii: [103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] } + 0 ; blr x5 -; ldp d8, d9, [sp], #16 -; ldp d10, d11, [sp], #16 -; ldp d12, d13, [sp], #16 -; ldp d14, d15, [sp], #16 -; ldp x19, x20, [sp], #16 -; ldp x21, x22, [sp], #16 -; ldp x23, x24, [sp], #16 -; ldp x25, x26, [sp], #16 -; ldp x27, x28, [sp], #16 ; ldp fp, lr, [sp], #16 ; ret -function %f3(i32) -> i32 uext baldrdash_system_v { +function %f3(i32) -> i32 uext { block0(v0: i32): return v0 } ; block0: -; mov w0, w0 +; ret function %f4(i32) -> i64 { - fn0 = %g(i32 sext) -> i64 baldrdash_system_v + fn0 = %g(i32 sext) -> i64 block0(v0: i32): v1 = call fn0(v0) @@ -72,38 +53,19 @@ block0(v0: i32): ; stp fp, lr, [sp, #-16]! ; mov fp, sp -; stp x27, x28, [sp, #-16]! -; stp x25, x26, [sp, #-16]! -; stp x23, x24, [sp, #-16]! -; stp x21, x22, [sp, #-16]! -; stp x19, x20, [sp, #-16]! -; stp d14, d15, [sp, #-16]! -; stp d12, d13, [sp, #-16]! -; stp d10, d11, [sp, #-16]! -; stp d8, d9, [sp, #-16]! ; block0: -; sxtw x0, w0 ; ldr x5, 8 ; b 12 ; data TestCase { length: 1, ascii: [103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] } + 0 ; blr x5 -; ldp d8, d9, [sp], #16 -; ldp d10, d11, [sp], #16 -; ldp d12, d13, [sp], #16 -; ldp d14, d15, [sp], #16 -; ldp x19, x20, [sp], #16 -; ldp x21, x22, [sp], #16 -; ldp x23, x24, [sp], #16 -; ldp x25, x26, [sp], #16 -; ldp x27, x28, [sp], #16 ; ldp fp, lr, [sp], #16 ; ret -function %f5(i32) -> i32 sext baldrdash_system_v { +function %f5(i32) -> i32 sext { block0(v0: i32): return v0 } ; block0: -; sxtw x0, w0 +; ret function %f6(i8) -> i64 { fn0 = %g(i32, i32, i32, i32, i32, i32, i32, i32, i8 sext) -> i64 diff --git a/cranelift/filetests/filetests/isa/aarch64/multivalue-ret.clif b/cranelift/filetests/filetests/isa/aarch64/multivalue-ret.clif index d6782da015..1d93513ba3 100644 --- a/cranelift/filetests/filetests/isa/aarch64/multivalue-ret.clif +++ b/cranelift/filetests/filetests/isa/aarch64/multivalue-ret.clif @@ -2,7 +2,6 @@ test compile precise-output set unwind_info=false target aarch64 -;; Test default (non-SpiderMonkey) ABI. function %f() -> i64, i64 { block1: v0 = iconst.i64 1 diff --git a/cranelift/filetests/filetests/isa/s390x/multivalue-ret.clif b/cranelift/filetests/filetests/isa/s390x/multivalue-ret.clif index 72e076df19..bbbdbba837 100644 --- a/cranelift/filetests/filetests/isa/s390x/multivalue-ret.clif +++ b/cranelift/filetests/filetests/isa/s390x/multivalue-ret.clif @@ -1,7 +1,6 @@ test compile precise-output target s390x -;; Test default (non-SpiderMonkey) ABI. function %f1() -> i64, i64, i64, i64 { block1: v0 = iconst.i64 1 diff --git a/cranelift/filetests/filetests/parser/call.clif b/cranelift/filetests/filetests/parser/call.clif index 35e43822d1..9f3ad6eb94 100644 --- a/cranelift/filetests/filetests/parser/call.clif +++ b/cranelift/filetests/filetests/parser/call.clif @@ -10,13 +10,13 @@ block1: ; nextln: return ; nextln: } -function %r1() -> i32, f32 baldrdash_system_v { +function %r1() -> i32, f32 { block1: v1 = iconst.i32 3 v2 = f32const 0.0 return v1, v2 } -; sameln: function %r1() -> i32, f32 baldrdash_system_v { +; sameln: function %r1() -> i32, f32 ; nextln: block1: ; nextln: v1 = iconst.i32 3 ; nextln: v2 = f32const 0.0 @@ -25,13 +25,13 @@ block1: function %signatures() { sig10 = () - sig11 = (i32, f64) -> i32, b1 baldrdash_system_v + sig11 = (i32, f64) -> i32, b1 fn5 = %foo sig11 fn8 = %bar(i32) -> b1 } ; sameln: function %signatures() fast { ; check: sig10 = () fast -; check: sig11 = (i32, f64) -> i32, b1 baldrdash_system_v +; check: sig11 = (i32, f64) -> i32, b1 ; check: sig12 = (i32) -> b1 fast ; not: fn0 ; check: fn5 = %foo sig11 diff --git a/cranelift/interpreter/src/step.rs b/cranelift/interpreter/src/step.rs index 1cc704a994..62310dc347 100644 --- a/cranelift/interpreter/src/step.rs +++ b/cranelift/interpreter/src/step.rs @@ -272,7 +272,6 @@ where CraneliftTrap::User(trap_code()), ), Opcode::Return => ControlFlow::Return(args()?), - Opcode::FallthroughReturn => ControlFlow::Return(args()?), Opcode::Call => { if let InstructionData::Call { func_ref, .. } = inst { let function = state diff --git a/cranelift/reader/src/parser.rs b/cranelift/reader/src/parser.rs index 7c854149ae..e2f1df77fb 100644 --- a/cranelift/reader/src/parser.rs +++ b/cranelift/reader/src/parser.rs @@ -3175,14 +3175,14 @@ mod tests { assert_eq!(sig.returns.len(), 0); assert_eq!(sig.call_conv, CallConv::SystemV); - let sig2 = Parser::new("(i8 uext, f32, f64, i32 sret) -> i32 sext, f64 baldrdash_system_v") + let sig2 = Parser::new("(i8 uext, f32, f64, i32 sret) -> i32 sext, f64 system_v") .parse_signature() .unwrap(); assert_eq!( sig2.to_string(), - "(i8 uext, f32, f64, i32 sret) -> i32 sext, f64 baldrdash_system_v" + "(i8 uext, f32, f64, i32 sret) -> i32 sext, f64 system_v" ); - assert_eq!(sig2.call_conv, CallConv::BaldrdashSystemV); + assert_eq!(sig2.call_conv, CallConv::SystemV); // Old-style signature without a calling convention. assert_eq!( diff --git a/cranelift/spidermonkey.md b/cranelift/spidermonkey.md deleted file mode 100644 index 516aa84a81..0000000000 --- a/cranelift/spidermonkey.md +++ /dev/null @@ -1,40 +0,0 @@ -Cranelift in SpiderMonkey -========================= - -[SpiderMonkey](https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey) -is the JavaScript and WebAssembly engine in Firefox. Cranelift is -designed to be used in SpiderMonkey with the goal of enabling better -code generation for ARM's 32-bit and 64-bit architectures, and building -a framework for improved low-level code optimizations in the future. - -Phase 1: WebAssembly --------------------- - -SpiderMonkey currently has two WebAssembly compilers: The tier 1 -baseline compiler (not shown below) and the tier 2 compiler using the -IonMonkey JavaScript compiler's optimizations and register allocation. - -![Cranelift in SpiderMonkey phase 1](media/spidermonkey1.png) - -In phase 1, Cranelift aims to replace the IonMonkey-based tier 2 -compiler for WebAssembly only. It will still be orchestrated by the -BaldrMonkey engine and compile WebAssembly modules on multiple threads. -Cranelift translates binary wasm functions directly into its own -intermediate representation, and it generates binary machine code -without depending on SpiderMonkey's macro assembler. - -Phase 2: IonMonkey ------------------- - -The IonMonkey JIT compiler is designed to compile JavaScript code. It -uses two separate intermediate representations to do that: - - - MIR is used for optimizations that are specific to JavaScript JIT - compilation. It has good support for JS types and the special tricks - needed to make JS fast. - - LIR is used for register allocation. - -![Cranelift in SpiderMonkey phase 2](media/spidermonkey2.png) - -Cranelift has its own register allocator, so the LIR representation can -be skipped when using Cranelift as a backend for IonMonkey. diff --git a/cranelift/src/souper_harvest.rs b/cranelift/src/souper_harvest.rs index 4a7d5c3961..4aa7567f06 100644 --- a/cranelift/src/souper_harvest.rs +++ b/cranelift/src/souper_harvest.rs @@ -2,7 +2,7 @@ use crate::utils::parse_sets_and_triple; use anyhow::{Context as _, Result}; use clap::Parser; use cranelift_codegen::Context; -use cranelift_wasm::{DummyEnvironment, ReturnMode}; +use cranelift_wasm::DummyEnvironment; use rayon::iter::{IntoParallelIterator, ParallelIterator}; use std::path::{Path, PathBuf}; use std::{fs, io}; @@ -61,11 +61,7 @@ pub fn run(options: &Options) -> Result<()> { .context("failed to read input file")?; let funcs = if &contents[..WASM_MAGIC.len()] == WASM_MAGIC { - let mut dummy_environ = DummyEnvironment::new( - fisa.isa.unwrap().frontend_config(), - ReturnMode::NormalReturns, - false, - ); + let mut dummy_environ = DummyEnvironment::new(fisa.isa.unwrap().frontend_config(), false); cranelift_wasm::translate_module(&contents, &mut dummy_environ) .context("failed to translate Wasm module to clif")?; dummy_environ diff --git a/cranelift/src/wasm.rs b/cranelift/src/wasm.rs index f35f62b043..f526e0c8a2 100644 --- a/cranelift/src/wasm.rs +++ b/cranelift/src/wasm.rs @@ -17,7 +17,7 @@ use cranelift_codegen::settings::FlagsOrIsa; use cranelift_codegen::timing; use cranelift_codegen::Context; use cranelift_entity::EntityRef; -use cranelift_wasm::{translate_module, DummyEnvironment, FuncIndex, ReturnMode}; +use cranelift_wasm::{translate_module, DummyEnvironment, FuncIndex}; use std::io::Read; use std::path::Path; use std::path::PathBuf; @@ -186,8 +186,7 @@ fn handle_module(options: &Options, path: &Path, name: &str, fisa: FlagsOrIsa) - }; let debug_info = options.value_ranges; - let mut dummy_environ = - DummyEnvironment::new(isa.frontend_config(), ReturnMode::NormalReturns, debug_info); + let mut dummy_environ = DummyEnvironment::new(isa.frontend_config(), debug_info); translate_module(&module_binary, &mut dummy_environ)?; vcprintln!(options.verbose, use_color, terminal, Color::Green, "ok"); diff --git a/cranelift/wasm/src/code_translator.rs b/cranelift/wasm/src/code_translator.rs index 9c1e7360b8..be9323043a 100644 --- a/cranelift/wasm/src/code_translator.rs +++ b/cranelift/wasm/src/code_translator.rs @@ -72,7 +72,7 @@ //! ("Relax verification to allow I8X16 to act as a default vector type") use super::{hash_map, HashMap}; -use crate::environ::{FuncEnvironment, GlobalVariable, ReturnMode}; +use crate::environ::{FuncEnvironment, GlobalVariable}; use crate::state::{ControlStackFrame, ElseData, FuncTranslationState}; use crate::translation_utils::{ block_with_params, blocktype_params_results, f32_translation, f64_translation, @@ -531,23 +531,14 @@ pub fn translate_operator( state.reachable = false; } Operator::Return => { - let (return_count, br_destination) = { + let return_count = { let frame = &mut state.control_stack[0]; - if environ.return_mode() == ReturnMode::FallthroughReturn { - frame.set_branched_to_exit(); - } - let return_count = frame.num_return_values(); - (return_count, frame.br_destination()) + frame.num_return_values() }; { let return_args = state.peekn_mut(return_count); bitcast_wasm_returns(environ, return_args, builder); - match environ.return_mode() { - ReturnMode::NormalReturns => builder.ins().return_(return_args), - ReturnMode::FallthroughReturn => { - canonicalise_then_jump(builder, br_destination, return_args) - } - }; + builder.ins().return_(return_args); } state.popn(return_count); state.reachable = false; diff --git a/cranelift/wasm/src/environ/dummy.rs b/cranelift/wasm/src/environ/dummy.rs index 9492f79512..70833483ae 100644 --- a/cranelift/wasm/src/environ/dummy.rs +++ b/cranelift/wasm/src/environ/dummy.rs @@ -5,9 +5,7 @@ //! [wasmtime-environ]: https://crates.io/crates/wasmtime-environ //! [Wasmtime]: https://github.com/bytecodealliance/wasmtime -use crate::environ::{ - FuncEnvironment, GlobalVariable, ModuleEnvironment, ReturnMode, TargetEnvironment, -}; +use crate::environ::{FuncEnvironment, GlobalVariable, ModuleEnvironment, TargetEnvironment}; use crate::func_translator::FuncTranslator; use crate::state::FuncTranslationState; use crate::WasmType; @@ -150,9 +148,6 @@ pub struct DummyEnvironment { /// Vector of wasm bytecode size for each function. pub func_bytecode_sizes: Vec, - /// How to return from functions. - return_mode: ReturnMode, - /// Instructs to collect debug data during translation. debug_info: bool, @@ -168,12 +163,11 @@ pub struct DummyEnvironment { impl DummyEnvironment { /// Creates a new `DummyEnvironment` instance. - pub fn new(config: TargetFrontendConfig, return_mode: ReturnMode, debug_info: bool) -> Self { + pub fn new(config: TargetFrontendConfig, debug_info: bool) -> Self { Self { info: DummyModuleInfo::new(config), trans: FuncTranslator::new(), func_bytecode_sizes: Vec::new(), - return_mode, debug_info, module_name: None, function_names: SecondaryMap::new(), @@ -184,11 +178,7 @@ impl DummyEnvironment { /// Return a `DummyFuncEnvironment` for translating functions within this /// `DummyEnvironment`. pub fn func_env(&self) -> DummyFuncEnvironment { - DummyFuncEnvironment::new( - &self.info, - self.return_mode, - self.expected_reachability.clone(), - ) + DummyFuncEnvironment::new(&self.info, self.expected_reachability.clone()) } fn get_func_type(&self, func_index: FuncIndex) -> TypeIndex { @@ -222,8 +212,6 @@ impl DummyEnvironment { pub struct DummyFuncEnvironment<'dummy_environment> { pub mod_info: &'dummy_environment DummyModuleInfo, - return_mode: ReturnMode, - /// Expected reachability data (before/after for each op) to assert. This is used for testing. expected_reachability: Option, } @@ -231,12 +219,10 @@ pub struct DummyFuncEnvironment<'dummy_environment> { impl<'dummy_environment> DummyFuncEnvironment<'dummy_environment> { pub fn new( mod_info: &'dummy_environment DummyModuleInfo, - return_mode: ReturnMode, expected_reachability: Option, ) -> Self { Self { mod_info, - return_mode, expected_reachability, } } @@ -268,10 +254,6 @@ impl<'dummy_environment> TargetEnvironment for DummyFuncEnvironment<'dummy_envir } impl<'dummy_environment> FuncEnvironment for DummyFuncEnvironment<'dummy_environment> { - fn return_mode(&self) -> ReturnMode { - self.return_mode - } - fn make_global( &mut self, func: &mut ir::Function, @@ -863,11 +845,8 @@ impl<'data> ModuleEnvironment<'data> for DummyEnvironment { self.func_bytecode_sizes .push(body.get_binary_reader().bytes_remaining()); let func = { - let mut func_environ = DummyFuncEnvironment::new( - &self.info, - self.return_mode, - self.expected_reachability.clone(), - ); + let mut func_environ = + DummyFuncEnvironment::new(&self.info, self.expected_reachability.clone()); let func_index = FuncIndex::new(self.get_num_func_imports() + self.info.function_bodies.len()); let name = get_func_name(func_index); diff --git a/cranelift/wasm/src/environ/mod.rs b/cranelift/wasm/src/environ/mod.rs index 16a89a1d7a..03b6cec371 100644 --- a/cranelift/wasm/src/environ/mod.rs +++ b/cranelift/wasm/src/environ/mod.rs @@ -6,5 +6,5 @@ mod spec; pub use crate::environ::dummy::DummyEnvironment; pub use crate::environ::spec::{ - FuncEnvironment, GlobalVariable, ModuleEnvironment, ReturnMode, TargetEnvironment, + FuncEnvironment, GlobalVariable, ModuleEnvironment, TargetEnvironment, }; diff --git a/cranelift/wasm/src/environ/spec.rs b/cranelift/wasm/src/environ/spec.rs index db1d043383..bfdaa2b426 100644 --- a/cranelift/wasm/src/environ/spec.rs +++ b/cranelift/wasm/src/environ/spec.rs @@ -41,15 +41,6 @@ pub enum GlobalVariable { Custom, } -/// How to return from functions. -#[derive(Copy, Clone, PartialEq, Eq, Debug)] -pub enum ReturnMode { - /// Use normal return instructions as needed. - NormalReturns, - /// Use a single fallthrough return at the end of the function. - FallthroughReturn, -} - /// Environment affecting the translation of a WebAssembly. pub trait TargetEnvironment { /// Get the information needed to produce Cranelift IR for the given target. @@ -102,13 +93,6 @@ pub trait FuncEnvironment: TargetEnvironment { signature.returns[index].purpose == ir::ArgumentPurpose::Normal } - /// Should the code be structured to use a single `fallthrough_return` instruction at the end - /// of the function body, rather than `return` instructions as needed? This is used by VMs - /// to append custom epilogues. - fn return_mode(&self) -> ReturnMode { - ReturnMode::NormalReturns - } - /// Called after the locals for a function have been parsed, and the number /// of variables defined by this function is provided. fn after_locals(&mut self, num_locals_defined: usize) { diff --git a/cranelift/wasm/src/func_translator.rs b/cranelift/wasm/src/func_translator.rs index 87c5b591d9..4404324b04 100644 --- a/cranelift/wasm/src/func_translator.rs +++ b/cranelift/wasm/src/func_translator.rs @@ -5,7 +5,7 @@ //! WebAssembly module and the runtime environment. use crate::code_translator::{bitcast_wasm_returns, translate_operator}; -use crate::environ::{FuncEnvironment, ReturnMode}; +use crate::environ::FuncEnvironment; use crate::state::FuncTranslationState; use crate::translation_utils::get_vmctx_value_label; use crate::WasmResult; @@ -253,13 +253,8 @@ fn parse_function_body( // generate a return instruction that doesn't match the signature. if state.reachable { if !builder.is_unreachable() { - match environ.return_mode() { - ReturnMode::NormalReturns => { - bitcast_wasm_returns(environ, &mut state.stack, builder); - builder.ins().return_(&state.stack) - } - ReturnMode::FallthroughReturn => builder.ins().fallthrough_return(&state.stack), - }; + bitcast_wasm_returns(environ, &mut state.stack, builder); + builder.ins().return_(&state.stack); } } @@ -279,7 +274,7 @@ fn cur_srcloc(reader: &BinaryReader) -> ir::SourceLoc { #[cfg(test)] mod tests { - use super::{FuncTranslator, ReturnMode}; + use super::FuncTranslator; use crate::environ::DummyEnvironment; use cranelift_codegen::ir::types::I32; use cranelift_codegen::{ir, isa, settings, Context}; @@ -310,7 +305,6 @@ mod tests { default_call_conv: isa::CallConv::Fast, pointer_width: PointerWidth::U64, }, - ReturnMode::NormalReturns, false, ); @@ -349,7 +343,6 @@ mod tests { default_call_conv: isa::CallConv::Fast, pointer_width: PointerWidth::U64, }, - ReturnMode::NormalReturns, false, ); @@ -393,7 +386,6 @@ mod tests { default_call_conv: isa::CallConv::Fast, pointer_width: PointerWidth::U64, }, - ReturnMode::NormalReturns, false, ); diff --git a/cranelift/wasm/src/lib.rs b/cranelift/wasm/src/lib.rs index 5ae2224158..1121598629 100644 --- a/cranelift/wasm/src/lib.rs +++ b/cranelift/wasm/src/lib.rs @@ -57,8 +57,7 @@ mod state; mod translation_utils; pub use crate::environ::{ - DummyEnvironment, FuncEnvironment, GlobalVariable, ModuleEnvironment, ReturnMode, - TargetEnvironment, + DummyEnvironment, FuncEnvironment, GlobalVariable, ModuleEnvironment, TargetEnvironment, }; pub use crate::func_translator::FuncTranslator; pub use crate::module_translator::translate_module; diff --git a/cranelift/wasm/tests/wasm_testsuite.rs b/cranelift/wasm/tests/wasm_testsuite.rs index fa07a7ba2c..d69c75526f 100644 --- a/cranelift/wasm/tests/wasm_testsuite.rs +++ b/cranelift/wasm/tests/wasm_testsuite.rs @@ -2,7 +2,7 @@ use cranelift_codegen::isa::{CallConv, TargetFrontendConfig}; use cranelift_codegen::print_errors::pretty_verifier_error; use cranelift_codegen::settings::{self, Flags}; use cranelift_codegen::verifier; -use cranelift_wasm::{translate_module, DummyEnvironment, FuncIndex, ReturnMode}; +use cranelift_wasm::{translate_module, DummyEnvironment, FuncIndex}; use std::fs; use std::path::Path; use target_lexicon::PointerWidth; @@ -28,18 +28,10 @@ fn testsuite() { let path = path.path(); println!("=== {} ===", path.display()); let data = read_module(&path); - handle_module(data, &flags, ReturnMode::NormalReturns); + handle_module(data, &flags); } } -#[test] -fn use_fallthrough_return() { - let flags = Flags::new(settings::builder()); - let path = Path::new("./wasmtests/use_fallthrough_return.wat"); - let data = read_module(&path); - handle_module(data, &flags, ReturnMode::FallthroughReturn); -} - #[test] fn use_name_section() { let data = wat::parse_str( @@ -51,13 +43,11 @@ fn use_name_section() { ) .unwrap(); - let return_mode = ReturnMode::NormalReturns; let mut dummy_environ = DummyEnvironment::new( TargetFrontendConfig { default_call_conv: CallConv::SystemV, pointer_width: PointerWidth::U32, }, - return_mode, false, ); @@ -84,13 +74,12 @@ fn read_module(path: &Path) -> Vec { } } -fn handle_module(data: Vec, flags: &Flags, return_mode: ReturnMode) { +fn handle_module(data: Vec, flags: &Flags) { let mut dummy_environ = DummyEnvironment::new( TargetFrontendConfig { default_call_conv: CallConv::SystemV, pointer_width: PointerWidth::U64, }, - return_mode, false, ); @@ -107,7 +96,6 @@ fn handle_module(data: Vec, flags: &Flags, return_mode: ReturnMode) { fn reachability_is_correct() { let tests = vec![ ( - ReturnMode::NormalReturns, r#" (module (func (param i32) (loop @@ -127,7 +115,6 @@ fn reachability_is_correct() { ], ), ( - ReturnMode::NormalReturns, r#" (module (func (param i32) (loop @@ -145,7 +132,6 @@ fn reachability_is_correct() { ], ), ( - ReturnMode::NormalReturns, r#" (module (func (param i32) (result i32) i32.const 1 @@ -158,30 +144,15 @@ fn reachability_is_correct() { (false, false), // End ], ), - ( - ReturnMode::FallthroughReturn, - r#" - (module (func (param i32) (result i32) - i32.const 1 - return - i32.const 42))"#, - vec![ - (true, true), // I32Const - (true, false), // Return - (false, false), // I32Const - (false, true), // End - ], - ), ]; - for (return_mode, wat, expected_reachability) in tests { + for (wat, expected_reachability) in tests { println!("testing wat:\n{}", wat); let mut env = DummyEnvironment::new( TargetFrontendConfig { default_call_conv: CallConv::SystemV, pointer_width: PointerWidth::U64, }, - return_mode, false, ); env.test_expected_reachability(expected_reachability); diff --git a/cranelift/wasm/wasmtests/use_fallthrough_return.wat b/cranelift/wasm/wasmtests/use_fallthrough_return.wat deleted file mode 100644 index 44eab2b3f6..0000000000 --- a/cranelift/wasm/wasmtests/use_fallthrough_return.wat +++ /dev/null @@ -1,10 +0,0 @@ -(module - (memory 1) - (func $main (param i32) - (if - (get_local 0) - (then (return)) - (else (unreachable)) - ) - ) -) diff --git a/crates/wasmtime/src/engine.rs b/crates/wasmtime/src/engine.rs index 847d474998..8d49c4751d 100644 --- a/crates/wasmtime/src/engine.rs +++ b/crates/wasmtime/src/engine.rs @@ -351,9 +351,7 @@ impl Engine { // Features wasmtime doesn't use should all be disabled, since // otherwise if they are enabled it could change the behavior of // generated code. - "baldrdash_prologue_words" => *value == FlagValue::Num(0), "enable_llvm_abi_extensions" => *value == FlagValue::Bool(false), - "emit_all_ones_funcaddrs" => *value == FlagValue::Bool(false), "enable_pinned_reg" => *value == FlagValue::Bool(false), "enable_probestack" => *value == FlagValue::Bool(false), "use_colocated_libcalls" => *value == FlagValue::Bool(false), diff --git a/tests/all/debug/gdb.rs b/tests/all/debug/gdb.rs index c67edddf8e..6f5bbdb338 100644 --- a/tests/all/debug/gdb.rs +++ b/tests/all/debug/gdb.rs @@ -57,6 +57,7 @@ fn check_gdb_output(output: &str, directives: &str) -> Result<()> { pub fn test_debug_dwarf_gdb() -> Result<()> { let output = gdb_with_script( &[ + "--disable-cache", "-g", "tests/all/debug/testsuite/fib-wasm.wasm", "--invoke", diff --git a/tests/all/debug/lldb.rs b/tests/all/debug/lldb.rs index dada5deee8..08fc344f88 100644 --- a/tests/all/debug/lldb.rs +++ b/tests/all/debug/lldb.rs @@ -62,6 +62,7 @@ fn check_lldb_output(output: &str, directives: &str) -> Result<()> { pub fn test_debug_dwarf_lldb() -> Result<()> { let output = lldb_with_script( &[ + "--disable-cache", "-g", "tests/all/debug/testsuite/fib-wasm.wasm", "--invoke", @@ -102,6 +103,7 @@ check: exited with status pub fn test_debug_dwarf5_lldb() -> Result<()> { let output = lldb_with_script( &[ + "--disable-cache", "-g", "tests/all/debug/testsuite/fib-wasm-dwarf5.wasm", "--invoke", @@ -142,6 +144,7 @@ check: exited with status pub fn test_debug_dwarf_ref() -> Result<()> { let output = lldb_with_script( &[ + "--disable-cache", "-g", "--opt-level", "0",