diff --git a/cranelift/codegen/src/ir/framelayout.rs b/cranelift/codegen/src/ir/framelayout.rs index 983b209279e7..f4cb5bb909f3 100644 --- a/cranelift/codegen/src/ir/framelayout.rs +++ b/cranelift/codegen/src/ir/framelayout.rs @@ -6,8 +6,12 @@ use std::boxed::Box; use crate::HashMap; +#[cfg(feature = "enable-serde")] +use serde::{Deserialize, Serialize}; + /// Change in the frame layout information. #[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] +#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] pub enum FrameLayoutChange { /// Base CallFrameAddress (CFA) pointer moved to different register/offset. CallFrameAddressAt { diff --git a/cranelift/codegen/src/isa/call_conv.rs b/cranelift/codegen/src/isa/call_conv.rs index 2b3b2a5f3517..3b880c2983f7 100644 --- a/cranelift/codegen/src/isa/call_conv.rs +++ b/cranelift/codegen/src/isa/call_conv.rs @@ -4,8 +4,12 @@ use core::fmt; use core::str; use target_lexicon::{CallingConvention, Triple}; +#[cfg(feature = "enable-serde")] +use serde::{Deserialize, Serialize}; + /// Calling convention identifiers. #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))] pub enum CallConv { /// Best performance, not ABI-stable Fast, diff --git a/crates/debug/src/frame.rs b/crates/debug/src/frame.rs new file mode 100644 index 000000000000..c7273d449064 --- /dev/null +++ b/crates/debug/src/frame.rs @@ -0,0 +1,140 @@ +use crate::transform::map_reg; +use std::collections::HashMap; +use wasmtime_environ::entity::EntityRef; +use wasmtime_environ::isa::{CallConv, TargetIsa}; +use wasmtime_environ::wasm::DefinedFuncIndex; +use wasmtime_environ::{FrameLayoutChange, FrameLayouts}; + +use gimli::write::{ + Address, CallFrameInstruction, CommonInformationEntry as CIEEntry, Error, + FrameDescriptionEntry as FDEEntry, FrameTable, +}; +use gimli::{Encoding, Format, Register, X86_64}; + +fn to_cfi( + isa: &dyn TargetIsa, + change: &FrameLayoutChange, + cfa_def_reg: &mut Register, + cfa_def_offset: &mut i32, +) -> Option { + Some(match change { + FrameLayoutChange::CallFrameAddressAt { reg, offset } => { + let mapped = match map_reg(isa, *reg) { + Ok(r) => r, + Err(_) => return None, + }; + let offset = (*offset) as i32; + if mapped != *cfa_def_reg && offset != *cfa_def_offset { + *cfa_def_reg = mapped; + *cfa_def_offset = offset; + CallFrameInstruction::Cfa(mapped, offset) + } else if offset != *cfa_def_offset { + *cfa_def_offset = offset; + CallFrameInstruction::CfaOffset(offset) + } else if mapped != *cfa_def_reg { + *cfa_def_reg = mapped; + CallFrameInstruction::CfaRegister(mapped) + } else { + return None; + } + } + FrameLayoutChange::RegAt { reg, cfa_offset } => { + assert!(cfa_offset % -8 == 0); + let cfa_offset = *cfa_offset as i32; + let mapped = match map_reg(isa, *reg) { + Ok(r) => r, + Err(_) => return None, + }; + CallFrameInstruction::Offset(mapped, cfa_offset) + } + FrameLayoutChange::ReturnAddressAt { cfa_offset } => { + assert!(cfa_offset % -8 == 0); + let cfa_offset = *cfa_offset as i32; + CallFrameInstruction::Offset(X86_64::RA, cfa_offset) + } + FrameLayoutChange::Preserve => CallFrameInstruction::RememberState, + FrameLayoutChange::Restore => CallFrameInstruction::RestoreState, + }) +} + +pub fn get_debug_frame_bytes( + funcs: &[(*const u8, usize)], + isa: &dyn TargetIsa, + layouts: &FrameLayouts, +) -> Result, Error> { + // FIXME Only x86-64 at this moment. + if isa.name() != "x86" || isa.pointer_bits() != 64 { + return Ok(None); + } + + let address_size = isa.pointer_bytes(); + let encoding = Encoding { + format: Format::Dwarf64, + version: 4, + address_size, + }; + + let mut frames = FrameTable::default(); + + let mut cached_cies = HashMap::new(); + + for (i, f) in funcs.into_iter().enumerate() { + let layout = &layouts[DefinedFuncIndex::new(i)]; + + // FIXME Can only process functions with SystemV-like prologue. + if layout.call_conv != CallConv::Fast + && layout.call_conv != CallConv::Cold + && layout.call_conv != CallConv::SystemV + { + continue; + } + + // Caching CIE with similar initial_commands. + let (cie_id, mut cfa_def_reg, mut cfa_def_offset) = { + use std::collections::hash_map::Entry; + match cached_cies.entry(&layout.initial_commands) { + Entry::Occupied(o) => *o.get(), + Entry::Vacant(v) => { + // cfa_def_reg and cfa_def_offset initialized with some random values. + let mut cfa_def_reg = X86_64::RA; + let mut cfa_def_offset = 0i32; + + // TODO adjust code_alignment_factor and data_alignment_factor based on ISA. + let mut cie = CIEEntry::new( + encoding, + /* code_alignment_factor = */ 1, + /* data_alignment_factor = */ -8, + /* return_address_register = */ X86_64::RA, + ); + for cmd in layout.initial_commands.iter() { + if let Some(instr) = to_cfi(isa, cmd, &mut cfa_def_reg, &mut cfa_def_offset) + { + cie.add_instruction(instr); + } + } + let cie_id = frames.add_cie(cie); + *v.insert((cie_id, cfa_def_reg, cfa_def_offset)) + } + } + }; + + let f_len = f.1 as u32; + let mut fde = FDEEntry::new( + Address::Symbol { + symbol: i, + addend: 0, + }, + f_len, + ); + + for (offset, cmd) in layout.commands.into_iter() { + if let Some(instr) = to_cfi(isa, cmd, &mut cfa_def_reg, &mut cfa_def_offset) { + fde.add_instruction(*offset as u32, instr); + } + } + + frames.add_fde(cie_id, fde); + } + + Ok(Some(frames)) +} diff --git a/crates/debug/src/lib.rs b/crates/debug/src/lib.rs index 1d212bdf28f3..2ca0e747c12d 100644 --- a/crates/debug/src/lib.rs +++ b/crates/debug/src/lib.rs @@ -2,17 +2,19 @@ #![allow(clippy::cast_ptr_alignment)] +use crate::frame::get_debug_frame_bytes; use anyhow::Error; use faerie::{Artifact, Decl}; use more_asserts::assert_gt; use target_lexicon::BinaryFormat; use wasmtime_environ::isa::TargetIsa; -use wasmtime_environ::{ModuleAddressMap, ModuleVmctxInfo, ValueLabelsRanges}; +use wasmtime_environ::{FrameLayouts, ModuleAddressMap, ModuleVmctxInfo, ValueLabelsRanges}; pub use crate::read_debuginfo::{read_debuginfo, DebugInfoData, WasmFileInfo}; pub use crate::transform::transform_dwarf; pub use crate::write_debuginfo::{emit_dwarf, ResolvedSymbol, SymbolResolver}; +mod frame; mod gc; mod read_debuginfo; mod transform; @@ -33,10 +35,21 @@ pub fn emit_debugsections( debuginfo_data: &DebugInfoData, at: &ModuleAddressMap, ranges: &ValueLabelsRanges, + frame_layouts: &FrameLayouts, ) -> Result<(), Error> { let resolver = FunctionRelocResolver {}; let dwarf = transform_dwarf(isa, debuginfo_data, at, vmctx_info, ranges)?; - emit_dwarf(obj, dwarf, &resolver)?; + + let max = at.values().map(|v| v.body_len).fold(0, usize::max); + let mut funcs_bodies = Vec::with_capacity(max as usize); + funcs_bodies.resize(max as usize, 0); + let funcs = at + .values() + .map(|v| (::std::ptr::null(), v.body_len)) + .collect::>(); + let frames = get_debug_frame_bytes(&funcs, isa, frame_layouts)?; + + emit_dwarf(obj, dwarf, &resolver, frames)?; Ok(()) } @@ -57,6 +70,7 @@ pub fn emit_debugsections_image( vmctx_info: &ModuleVmctxInfo, at: &ModuleAddressMap, ranges: &ValueLabelsRanges, + frame_layouts: &FrameLayouts, funcs: &[(*const u8, usize)], ) -> Result, Error> { let func_offsets = &funcs @@ -79,7 +93,8 @@ pub fn emit_debugsections_image( let body = unsafe { std::slice::from_raw_parts(segment_body.0, segment_body.1) }; obj.declare_with("all", Decl::function(), body.to_vec())?; - emit_dwarf(&mut obj, dwarf, &resolver)?; + let frames = get_debug_frame_bytes(funcs, isa, frame_layouts)?; + emit_dwarf(&mut obj, dwarf, &resolver, frames)?; // LLDB is too "magical" about mach-o, generating elf let mut bytes = obj.emit_as(BinaryFormat::Elf)?; diff --git a/crates/debug/src/transform/expression.rs b/crates/debug/src/transform/expression.rs index 7461ea7007e3..e6f64ee3c769 100644 --- a/crates/debug/src/transform/expression.rs +++ b/crates/debug/src/transform/expression.rs @@ -1,11 +1,12 @@ use super::address_transform::AddressTransform; -use anyhow::{bail, Context, Error, Result}; -use gimli::{self, write, Expression, Operation, Reader, ReaderOffset, Register, X86_64}; +use super::map_reg::map_reg; +use anyhow::{Context, Error, Result}; +use gimli::{self, write, Expression, Operation, Reader, ReaderOffset, X86_64}; use more_asserts::{assert_le, assert_lt}; use std::collections::{HashMap, HashSet}; use wasmtime_environ::entity::EntityRef; use wasmtime_environ::ir::{StackSlots, ValueLabel, ValueLabelsRanges, ValueLoc}; -use wasmtime_environ::isa::{RegUnit, TargetIsa}; +use wasmtime_environ::isa::TargetIsa; use wasmtime_environ::wasm::{get_vmctx_value_label, DefinedFuncIndex}; use wasmtime_environ::ModuleMemoryOffset; @@ -70,61 +71,6 @@ impl<'a> CompiledExpression<'a> { } } -fn map_reg(isa: &dyn TargetIsa, reg: RegUnit) -> Result { - // TODO avoid duplication with fde.rs - assert!(isa.name() == "x86" && isa.pointer_bits() == 64); - // Mapping from https://github.com/bytecodealliance/cranelift/pull/902 by @iximeow - const X86_GP_REG_MAP: [gimli::Register; 16] = [ - X86_64::RAX, - X86_64::RCX, - X86_64::RDX, - X86_64::RBX, - X86_64::RSP, - X86_64::RBP, - X86_64::RSI, - X86_64::RDI, - X86_64::R8, - X86_64::R9, - X86_64::R10, - X86_64::R11, - X86_64::R12, - X86_64::R13, - X86_64::R14, - X86_64::R15, - ]; - const X86_XMM_REG_MAP: [gimli::Register; 16] = [ - X86_64::XMM0, - X86_64::XMM1, - X86_64::XMM2, - X86_64::XMM3, - X86_64::XMM4, - X86_64::XMM5, - X86_64::XMM6, - X86_64::XMM7, - X86_64::XMM8, - X86_64::XMM9, - X86_64::XMM10, - X86_64::XMM11, - X86_64::XMM12, - X86_64::XMM13, - X86_64::XMM14, - X86_64::XMM15, - ]; - let reg_info = isa.register_info(); - let bank = reg_info.bank_containing_regunit(reg).unwrap(); - match bank.name { - "IntRegs" => { - // x86 GP registers have a weird mapping to DWARF registers, so we use a - // lookup table. - Ok(X86_GP_REG_MAP[(reg - bank.first_unit) as usize]) - } - "FloatRegs" => Ok(X86_XMM_REG_MAP[(reg - bank.first_unit) as usize]), - bank_name => { - bail!("unsupported register bank: {}", bank_name); - } - } -} - fn translate_loc( loc: ValueLoc, frame_info: Option<&FunctionFrameInfo>, diff --git a/crates/debug/src/transform/map_reg.rs b/crates/debug/src/transform/map_reg.rs new file mode 100644 index 000000000000..87aed91fc8ab --- /dev/null +++ b/crates/debug/src/transform/map_reg.rs @@ -0,0 +1,58 @@ +use anyhow::{bail, Result}; +use gimli::{Register, X86_64}; +use wasmtime_environ::isa::{RegUnit, TargetIsa}; + +pub(crate) fn map_reg(isa: &dyn TargetIsa, reg: RegUnit) -> Result { + // TODO avoid duplication with fde.rs + assert!(isa.name() == "x86" && isa.pointer_bits() == 64); + // Mapping from https://github.com/bytecodealliance/cranelift/pull/902 by @iximeow + const X86_GP_REG_MAP: [Register; 16] = [ + X86_64::RAX, + X86_64::RCX, + X86_64::RDX, + X86_64::RBX, + X86_64::RSP, + X86_64::RBP, + X86_64::RSI, + X86_64::RDI, + X86_64::R8, + X86_64::R9, + X86_64::R10, + X86_64::R11, + X86_64::R12, + X86_64::R13, + X86_64::R14, + X86_64::R15, + ]; + const X86_XMM_REG_MAP: [Register; 16] = [ + X86_64::XMM0, + X86_64::XMM1, + X86_64::XMM2, + X86_64::XMM3, + X86_64::XMM4, + X86_64::XMM5, + X86_64::XMM6, + X86_64::XMM7, + X86_64::XMM8, + X86_64::XMM9, + X86_64::XMM10, + X86_64::XMM11, + X86_64::XMM12, + X86_64::XMM13, + X86_64::XMM14, + X86_64::XMM15, + ]; + let reg_info = isa.register_info(); + let bank = reg_info.bank_containing_regunit(reg).unwrap(); + match bank.name { + "IntRegs" => { + // x86 GP registers have a weird mapping to DWARF registers, so we use a + // lookup table. + Ok(X86_GP_REG_MAP[(reg - bank.first_unit) as usize]) + } + "FloatRegs" => Ok(X86_XMM_REG_MAP[(reg - bank.first_unit) as usize]), + bank_name => { + bail!("unsupported register bank: {}", bank_name); + } + } +} diff --git a/crates/debug/src/transform/mod.rs b/crates/debug/src/transform/mod.rs index a903ec5fffae..1fc6cb4cc82a 100644 --- a/crates/debug/src/transform/mod.rs +++ b/crates/debug/src/transform/mod.rs @@ -14,11 +14,13 @@ use wasmtime_environ::isa::TargetIsa; use wasmtime_environ::{ModuleAddressMap, ModuleVmctxInfo, ValueLabelsRanges}; pub use address_transform::AddressTransform; +pub(crate) use map_reg::map_reg; mod address_transform; mod attr; mod expression; mod line_program; +mod map_reg; mod range_info_builder; mod refs; mod simulate; diff --git a/crates/debug/src/write_debuginfo.rs b/crates/debug/src/write_debuginfo.rs index 9a62460b4c3d..d5cf56fe5423 100644 --- a/crates/debug/src/write_debuginfo.rs +++ b/crates/debug/src/write_debuginfo.rs @@ -1,6 +1,6 @@ use faerie::artifact::{Decl, SectionKind}; use faerie::*; -use gimli::write::{Address, Dwarf, EndianVec, Result, Sections, Writer}; +use gimli::write::{Address, DebugFrame, Dwarf, EndianVec, FrameTable, Result, Sections, Writer}; use gimli::{RunTimeEndian, SectionId}; #[derive(Clone)] @@ -24,6 +24,7 @@ pub fn emit_dwarf( artifact: &mut Artifact, mut dwarf: Dwarf, symbol_resolver: &dyn SymbolResolver, + frames: Option, ) -> anyhow::Result<()> { let endian = RunTimeEndian::Little; @@ -52,6 +53,30 @@ pub fn emit_dwarf( } Ok(()) })?; + + if let Some(frames) = frames { + let mut debug_frame = DebugFrame::from(WriterRelocate::new(endian, symbol_resolver)); + frames.write_debug_frame(&mut debug_frame).unwrap(); + artifact.declare_with( + SectionId::DebugFrame.name(), + Decl::section(SectionKind::Debug), + debug_frame.writer.take(), + )?; + for reloc in &debug_frame.relocs { + artifact.link_with( + faerie::Link { + from: SectionId::DebugFrame.name(), + to: &reloc.name, + at: u64::from(reloc.offset), + }, + faerie::Reloc::Debug { + size: reloc.size, + addend: reloc.addend as i32, + }, + )?; + } + } + Ok(()) } diff --git a/crates/environ/src/cache.rs b/crates/environ/src/cache.rs index 290a54033f88..fc7e7c643d64 100644 --- a/crates/environ/src/cache.rs +++ b/crates/environ/src/cache.rs @@ -1,5 +1,6 @@ use crate::address_map::{ModuleAddressMap, ValueLabelsRanges}; use crate::compilation::{Compilation, Relocations, Traps}; +use crate::frame_layout::FrameLayouts; use cranelift_codegen::ir; use cranelift_entity::PrimaryMap; use cranelift_wasm::DefinedFuncIndex; @@ -35,6 +36,7 @@ pub struct ModuleCacheData { value_ranges: ValueLabelsRanges, stack_slots: PrimaryMap, traps: Traps, + frame_layouts: FrameLayouts, } /// A type alias over the module cache data as a tuple. @@ -45,6 +47,7 @@ pub type ModuleCacheDataTupleType = ( ValueLabelsRanges, PrimaryMap, Traps, + FrameLayouts, ); struct Sha256Hasher(Sha256); @@ -204,6 +207,7 @@ impl ModuleCacheData { value_ranges: data.3, stack_slots: data.4, traps: data.5, + frame_layouts: data.6, } } @@ -215,6 +219,7 @@ impl ModuleCacheData { self.value_ranges, self.stack_slots, self.traps, + self.frame_layouts, ) } } diff --git a/crates/environ/src/cache/tests.rs b/crates/environ/src/cache/tests.rs index d454371178e0..35dc6c613e36 100644 --- a/crates/environ/src/cache/tests.rs +++ b/crates/environ/src/cache/tests.rs @@ -100,5 +100,6 @@ fn new_module_cache_data() -> Result { PrimaryMap::new(), PrimaryMap::new(), PrimaryMap::new(), + PrimaryMap::new(), )) } diff --git a/crates/environ/src/cranelift.rs b/crates/environ/src/cranelift.rs index da1dbe151c05..5764ce14194c 100644 --- a/crates/environ/src/cranelift.rs +++ b/crates/environ/src/cranelift.rs @@ -6,6 +6,7 @@ use crate::compilation::{ Compilation, CompileError, CompiledFunction, CompiledFunctionUnwindInfo, Relocation, RelocationTarget, TrapInformation, }; +use crate::frame_layout::FrameLayout; use crate::func_environ::{get_func_name, FuncEnvironment}; use crate::module::{Module, ModuleLocal}; use crate::module_environ::FunctionBodyData; @@ -154,6 +155,38 @@ fn get_function_address_map<'data>( } } +fn get_frame_layout( + context: &Context, + isa: &dyn isa::TargetIsa, +) -> ( + Box<[ir::FrameLayoutChange]>, + Box<[(usize, ir::FrameLayoutChange)]>, +) { + let func = &context.func; + assert!(func.frame_layout.is_some(), "expected func.frame_layout"); + + let mut blocks = func.layout.blocks().collect::>(); + blocks.sort_by_key(|b| func.offsets[*b]); // Ensure inst offsets always increase + + let encinfo = isa.encoding_info(); + let mut last_offset = 0; + let mut commands = Vec::new(); + for b in blocks { + for (offset, inst, size) in func.inst_offsets(b, &encinfo) { + if let Some(cmds) = func.frame_layout.as_ref().unwrap().instructions.get(&inst) { + let address_offset = (offset + size) as usize; + assert!(last_offset < address_offset); + for cmd in cmds.iter() { + commands.push((address_offset, cmd.clone())); + } + last_offset = address_offset; + } + } + } + let initial = func.frame_layout.as_ref().unwrap().initial.clone(); + (initial, commands.into_boxed_slice()) +} + /// A compiler that compiles a WebAssembly module with Cranelift, translating the Wasm to Cranelift IR, /// optimizing it and then translating to assembly. pub struct Cranelift; @@ -206,6 +239,7 @@ fn compile( let mut value_ranges = PrimaryMap::with_capacity(function_body_inputs.len()); let mut stack_slots = PrimaryMap::with_capacity(function_body_inputs.len()); let mut traps = PrimaryMap::with_capacity(function_body_inputs.len()); + let mut frame_layouts = PrimaryMap::with_capacity(function_body_inputs.len()); function_body_inputs .into_iter() @@ -254,6 +288,17 @@ fn compile( None }; + let frame_layout = if generate_debug_info { + let (initial_commands, commands) = get_frame_layout(&context, isa); + Some(FrameLayout { + call_conv: context.func.signature.call_conv, + initial_commands, + commands, + }) + } else { + None + }; + let ranges = if generate_debug_info { let ranges = context.build_value_labels_ranges(isa).map_err(|error| { CompileError::Codegen(pretty_error(&context.func, Some(isa), error)) @@ -268,6 +313,7 @@ fn compile( context.func.jt_offsets, reloc_sink.func_relocs, address_transform, + frame_layout, ranges, context.func.stack_slots, trap_sink.traps, @@ -282,6 +328,7 @@ fn compile( func_jt_offsets, relocs, address_transform, + frame_layout, ranges, sss, function_traps, @@ -299,6 +346,9 @@ fn compile( value_ranges.push(ranges.unwrap_or_default()); stack_slots.push(sss); traps.push(function_traps); + if let Some(frame_layout) = frame_layout { + frame_layouts.push(frame_layout); + } }, ); @@ -311,6 +361,7 @@ fn compile( value_ranges, stack_slots, traps, + frame_layouts, )) } diff --git a/crates/environ/src/frame_layout.rs b/crates/environ/src/frame_layout.rs new file mode 100644 index 000000000000..46f413279628 --- /dev/null +++ b/crates/environ/src/frame_layout.rs @@ -0,0 +1,21 @@ +use cranelift_codegen::isa::CallConv; +use cranelift_entity::PrimaryMap; +use cranelift_wasm::DefinedFuncIndex; +use serde::{Deserialize, Serialize}; + +pub use cranelift_codegen::ir::FrameLayoutChange; + +/// Frame layout information: call convention and +/// registers save/restore commands. +#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)] +pub struct FrameLayout { + /// Call convention. + pub call_conv: CallConv, + /// Frame default/initial commands. + pub initial_commands: Box<[FrameLayoutChange]>, + /// Frame commands at specific offset. + pub commands: Box<[(usize, FrameLayoutChange)]>, +} + +/// Functions frame layouts. +pub type FrameLayouts = PrimaryMap; diff --git a/crates/environ/src/lib.rs b/crates/environ/src/lib.rs index ba849b54fe5e..a4bad0274d56 100644 --- a/crates/environ/src/lib.rs +++ b/crates/environ/src/lib.rs @@ -27,6 +27,7 @@ mod address_map; mod compilation; mod data_structures; +mod frame_layout; mod func_environ; mod module; mod module_environ; @@ -52,6 +53,7 @@ pub use crate::compilation::{ }; pub use crate::cranelift::Cranelift; pub use crate::data_structures::*; +pub use crate::frame_layout::{FrameLayout, FrameLayoutChange, FrameLayouts}; pub use crate::func_environ::BuiltinFunctionIndex; #[cfg(feature = "lightbeam")] pub use crate::lightbeam::Lightbeam; diff --git a/crates/environ/src/lightbeam.rs b/crates/environ/src/lightbeam.rs index 3abf98301ff8..53e833e04a41 100644 --- a/crates/environ/src/lightbeam.rs +++ b/crates/environ/src/lightbeam.rs @@ -70,6 +70,7 @@ impl crate::compilation::Compiler for Lightbeam { ValueLabelsRanges::new(), PrimaryMap::new(), Traps::new(), + PrimaryMap::new(), )) } } diff --git a/crates/jit/src/compiler.rs b/crates/jit/src/compiler.rs index 1d264f996fbb..f33baa874e71 100644 --- a/crates/jit/src/compiler.rs +++ b/crates/jit/src/compiler.rs @@ -110,33 +110,40 @@ impl Compiler { ), SetupError, > { - let (compilation, relocations, address_transform, value_ranges, stack_slots, traps) = - match self.strategy { - // For now, interpret `Auto` as `Cranelift` since that's the most stable - // implementation. - CompilationStrategy::Auto | CompilationStrategy::Cranelift => { - wasmtime_environ::cranelift::Cranelift::compile_module( - module, - module_translation, - function_body_inputs, - &*self.isa, - debug_data.is_some(), - &self.cache_config, - ) - } - #[cfg(feature = "lightbeam")] - CompilationStrategy::Lightbeam => { - wasmtime_environ::lightbeam::Lightbeam::compile_module( - module, - module_translation, - function_body_inputs, - &*self.isa, - debug_data.is_some(), - &self.cache_config, - ) - } + let ( + compilation, + relocations, + address_transform, + value_ranges, + stack_slots, + traps, + frame_layouts, + ) = match self.strategy { + // For now, interpret `Auto` as `Cranelift` since that's the most stable + // implementation. + CompilationStrategy::Auto | CompilationStrategy::Cranelift => { + wasmtime_environ::cranelift::Cranelift::compile_module( + module, + module_translation, + function_body_inputs, + &*self.isa, + debug_data.is_some(), + &self.cache_config, + ) } - .map_err(SetupError::Compile)?; + #[cfg(feature = "lightbeam")] + CompilationStrategy::Lightbeam => { + wasmtime_environ::lightbeam::Lightbeam::compile_module( + module, + module_translation, + function_body_inputs, + &*self.isa, + debug_data.is_some(), + &self.cache_config, + ) + } + } + .map_err(SetupError::Compile)?; let allocated_functions = allocate_functions(&mut self.code_memory, &compilation).map_err(|message| { @@ -179,6 +186,7 @@ impl Compiler { &module_vmctx_info, &address_transform, &value_ranges, + &frame_layouts, &funcs, ) .map_err(SetupError::DebugInfo)?; diff --git a/src/obj.rs b/src/obj.rs index 74419c581054..8684c500c55e 100644 --- a/src/obj.rs +++ b/src/obj.rs @@ -79,30 +79,37 @@ pub fn compile_to_obj( }; // TODO: use the traps information - let (compilation, relocations, address_transform, value_ranges, stack_slots, _traps) = - match strategy { - Strategy::Auto | Strategy::Cranelift => Cranelift::compile_module( - &module, - &module_translation, - lazy_function_body_inputs, - &*isa, - debug_info, - cache_config, - ), - #[cfg(feature = "lightbeam")] - Strategy::Lightbeam => Lightbeam::compile_module( - &module, - &module_translation, - lazy_function_body_inputs, - &*isa, - debug_info, - cache_config, - ), - #[cfg(not(feature = "lightbeam"))] - Strategy::Lightbeam => bail!("lightbeam support not enabled"), - other => bail!("unsupported compilation strategy {:?}", other), - } - .context("failed to compile module")?; + let ( + compilation, + relocations, + address_transform, + value_ranges, + stack_slots, + _traps, + frame_layouts, + ) = match strategy { + Strategy::Auto | Strategy::Cranelift => Cranelift::compile_module( + &module, + &module_translation, + lazy_function_body_inputs, + &*isa, + debug_info, + cache_config, + ), + #[cfg(feature = "lightbeam")] + Strategy::Lightbeam => Lightbeam::compile_module( + &module, + &module_translation, + lazy_function_body_inputs, + &*isa, + debug_info, + cache_config, + ), + #[cfg(not(feature = "lightbeam"))] + Strategy::Lightbeam => bail!("lightbeam support not enabled"), + other => bail!("unsupported compilation strategy {:?}", other), + } + .context("failed to compile module")?; if compilation.is_empty() { bail!("no functions were found/compiled"); @@ -144,6 +151,7 @@ pub fn compile_to_obj( &debug_data, &address_transform, &value_ranges, + &frame_layouts, ) .context("failed to emit debug sections")?; }