Skip to content

Commit

Permalink
Refactor unwind generation in Cranelift.
Browse files Browse the repository at this point in the history
This commit makes the following changes to unwind information generation in
Cranelift:

* Remove frame layout change implementation in favor of processing the prologue
  and epilogue instructions when unwind information is requested.  This also
  means this work is no longer performed for Windows, which didn't utilize it.
  It also helps simplify the prologue and epilogue generation code.

* Remove the unwind sink implementation that required each unwind information
  to be represented in final form. For FDEs, this meant writing a
  complete frame table per function, which wastes 20 bytes or so for each
  function with duplicate CIEs.  This also enables Cranelift users to collect the
  unwind information and write it as a single frame table.

* For System V calling convention, the unwind information is no longer stored
  in code memory (it's only a requirement for Windows ABI to do so).  This allows
  for more compact code memory for modules with a lot of functions.

* Deletes some duplicate code relating to frame table generation.  Users can
  now simply use gimli to create a frame table from each function's unwind
  information.

Fixes bytecodealliance#1181.
  • Loading branch information
peterhuene committed Apr 3, 2020
1 parent f6e3ab0 commit 4674f5c
Show file tree
Hide file tree
Showing 42 changed files with 2,463 additions and 2,937 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 0 additions & 30 deletions cranelift/codegen/src/binemit/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,36 +164,6 @@ pub trait CodeSink {
fn add_stackmap(&mut self, _: &[Value], _: &Function, _: &dyn TargetIsa);
}

/// Type of the frame unwind information.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum FrameUnwindKind {
/// Windows fastcall unwinding (as in .pdata).
Fastcall,
/// FDE entry for libunwind (similar to .eh_frame format).
Libunwind,
}

/// Offset in frame unwind information buffer.
pub type FrameUnwindOffset = usize;

/// Sink for frame unwind information.
pub trait FrameUnwindSink {
/// Get the current position.
fn len(&self) -> FrameUnwindOffset;

/// Add bytes to the code section.
fn bytes(&mut self, _: &[u8]);

/// Reserves bytes in the buffer.
fn reserve(&mut self, _len: usize) {}

/// Add a relocation entry.
fn reloc(&mut self, _: Reloc, _: FrameUnwindOffset);

/// Specified offset to main structure.
fn set_entry_offset(&mut self, _: FrameUnwindOffset);
}

/// Report a bad encoding error.
#[cold]
pub fn bad_encoding(func: &Function, inst: Inst) -> ! {
Expand Down
20 changes: 8 additions & 12 deletions cranelift/codegen/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
//! single ISA instance.
use crate::binemit::{
relax_branches, shrink_instructions, CodeInfo, FrameUnwindKind, FrameUnwindSink,
MemoryCodeSink, RelocSink, StackmapSink, TrapSink,
relax_branches, shrink_instructions, CodeInfo, MemoryCodeSink, RelocSink, StackmapSink,
TrapSink,
};
use crate::dce::do_dce;
use crate::dominator_tree::DominatorTree;
Expand Down Expand Up @@ -195,19 +195,15 @@ impl Context {
sink.info
}

/// Emit unwind information.
/// Creates unwind information for the function.
///
/// Requires that the function layout be calculated (see `relax_branches`).
///
/// Only some calling conventions (e.g. Windows fastcall) will have unwind information.
/// This is a no-op if the function has no unwind information.
pub fn emit_unwind_info(
/// Returns `None` if the function has no unwind information.
#[cfg(feature = "unwind")]
pub fn create_unwind_info(
&self,
isa: &dyn TargetIsa,
kind: FrameUnwindKind,
sink: &mut dyn FrameUnwindSink,
) {
isa.emit_unwind_info(&self.func, kind, sink);
) -> Option<crate::isa::unwind::UnwindInfo> {
isa.create_unwind_info(&self.func)
}

/// Run the verifier on the function.
Expand Down
74 changes: 0 additions & 74 deletions cranelift/codegen/src/ir/framelayout.rs

This file was deleted.

23 changes: 8 additions & 15 deletions cranelift/codegen/src/ir/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@ use crate::ir::{
Block, ExtFuncData, FuncRef, GlobalValue, GlobalValueData, Heap, HeapData, Inst, JumpTable,
JumpTableData, Opcode, SigRef, StackSlot, StackSlotData, Table, TableData,
};
use crate::ir::{BlockOffsets, FrameLayout, InstEncodings, SourceLocs, StackSlots, ValueLocations};
use crate::ir::{BlockOffsets, InstEncodings, SourceLocs, StackSlots, ValueLocations};
use crate::ir::{DataFlowGraph, ExternalName, Layout, Signature};
use crate::ir::{JumpTableOffsets, JumpTables};
use crate::isa::{CallConv, EncInfo, Encoding, Legalize, TargetIsa};
use crate::regalloc::{EntryRegDiversions, RegDiversions};
use crate::value_label::ValueLabelsRanges;
use crate::write::write_function;
use alloc::vec::Vec;
use core::fmt;

/// A function.
Expand Down Expand Up @@ -87,15 +88,13 @@ pub struct Function {

/// Instruction that marks the end (inclusive) of the function's prologue.
///
/// This is used for some calling conventions to track the end of unwind information.
/// This is used for some ABIs to generate unwind information.
pub prologue_end: Option<Inst>,

/// Frame layout for the instructions.
/// The instructions that mark the start (inclusive) of an epilogue in the function.
///
/// The stack unwinding requires to have information about which registers and where they
/// are saved in the frame. This information is created during the prologue and epilogue
/// passes.
pub frame_layout: Option<FrameLayout>,
/// This is used for some ABIs to generate unwind information.
pub epilogues_start: Vec<Inst>,
}

impl Function {
Expand All @@ -119,7 +118,7 @@ impl Function {
jt_offsets: SecondaryMap::new(),
srclocs: SecondaryMap::new(),
prologue_end: None,
frame_layout: None,
epilogues_start: Vec::new(),
}
}

Expand All @@ -140,7 +139,7 @@ impl Function {
self.jt_offsets.clear();
self.srclocs.clear();
self.prologue_end = None;
self.frame_layout = None;
self.epilogues_start.clear();
}

/// Create a new empty, anonymous function with a Fast calling convention.
Expand Down Expand Up @@ -250,12 +249,6 @@ impl Function {
/// Starts collection of debug information.
pub fn collect_debug_info(&mut self) {
self.dfg.collect_debug_info();
self.collect_frame_layout_info();
}

/// Starts collection of frame layout information.
pub fn collect_frame_layout_info(&mut self) {
self.frame_layout = Some(FrameLayout::new());
}

/// Changes the destination of a jump or branch instruction.
Expand Down
2 changes: 0 additions & 2 deletions cranelift/codegen/src/ir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ pub mod dfg;
pub mod entities;
mod extfunc;
mod extname;
mod framelayout;
pub mod function;
mod globalvalue;
mod heap;
Expand Down Expand Up @@ -40,7 +39,6 @@ pub use crate::ir::extfunc::{
AbiParam, ArgumentExtension, ArgumentPurpose, ExtFuncData, Signature,
};
pub use crate::ir::extname::ExternalName;
pub use crate::ir::framelayout::{FrameLayout, FrameLayoutChange, FrameLayoutChanges};
pub use crate::ir::function::{DisplayFunctionAnnotations, Function};
pub use crate::ir::globalvalue::GlobalValueData;
pub use crate::ir::heap::{HeapData, HeapStyle};
Expand Down
33 changes: 18 additions & 15 deletions cranelift/codegen/src/isa/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,18 +74,15 @@ mod riscv;
#[cfg(feature = "x86")]
mod x86;

#[cfg(all(feature = "x86", feature = "unwind"))]
/// Expose the register-mapping functionality necessary for exception handling, debug, etc.
pub mod fde {
pub use super::x86::map_reg;
}

#[cfg(feature = "arm32")]
mod arm32;

#[cfg(feature = "arm64")]
mod arm64;

#[cfg(feature = "unwind")]
pub mod unwind;

mod call_conv;
mod constraints;
mod enc_tables;
Expand Down Expand Up @@ -385,16 +382,22 @@ pub trait TargetIsa: fmt::Display + Send + Sync {
/// IntCC condition for Unsigned Subtraction Overflow (Borrow/Carry).
fn unsigned_sub_overflow_condition(&self) -> ir::condcodes::IntCC;

/// Emit unwind information for the given function.
/// Creates unwind information for the function.
///
/// Only some calling conventions (e.g. Windows fastcall) will have unwind information.
fn emit_unwind_info(
&self,
_func: &ir::Function,
_kind: binemit::FrameUnwindKind,
_sink: &mut dyn binemit::FrameUnwindSink,
) {
// No-op by default
/// Returns `None` if there is no unwind information for the function.
#[cfg(feature = "unwind")]
fn create_unwind_info(&self, _func: &ir::Function) -> Option<unwind::UnwindInfo> {
// By default, an ISA has no unwind information
None
}

/// Creates a new System V Common Information Entry for the ISA.
///
/// Returns `None` if the ISA does not support System V unwind information.
#[cfg(feature = "unwind")]
fn create_systemv_cie(&self) -> Option<gimli::write::CommonInformationEntry> {
// By default, an ISA cannot create a System V CIE
None
}
}

Expand Down
16 changes: 16 additions & 0 deletions cranelift/codegen/src/isa/unwind.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//! Represents information relating to function unwinding.
#[cfg(feature = "enable-serde")]
use serde::{Deserialize, Serialize};

pub mod systemv;

/// Represents unwind information for a single function.
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub enum UnwindInfo {
/// Windows x64 ABI unwind information.
#[cfg(feature = "x86")]
WindowsX64(super::x86::unwind::windows::UnwindInfo),
/// System V ABI unwind information.
SystemV(systemv::UnwindInfo),
}
Loading

0 comments on commit 4674f5c

Please sign in to comment.