Skip to content
This repository has been archived by the owner on Jun 26, 2020. It is now read-only.

Refactor unwind; add FDE support. #1320

Merged
merged 7 commits into from
Jan 13, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion cranelift-codegen/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ hashbrown = { version = "0.6", optional = true }
target-lexicon = "0.10"
log = { version = "0.4.6", default-features = false }
serde = { version = "1.0.94", features = ["derive"], optional = true }
gimli = { version = "0.19.0", default-features = false, features = ["write"], optional = true }
smallvec = { version = "1.0.0" }
thiserror = "1.0.4"
byteorder = { version = "1.3.2", default-features = false }
Expand All @@ -32,7 +33,7 @@ byteorder = { version = "1.3.2", default-features = false }
cranelift-codegen-meta = { path = "meta", version = "0.54.0" }

[features]
default = ["std", "basic-blocks"]
default = ["std", "basic-blocks", "unwind"]

# The "std" feature enables use of libstd. The "core" feature enables use
# of some minimal std-like replacement libraries. At least one of these two
Expand All @@ -47,6 +48,9 @@ core = ["hashbrown"]
# can significantly increase the size of the library.
testing_hooks = []

# This enables unwind info generation functionality.
unwind = ["gimli"]

# ISA targets for which we should build.
# If no ISA targets are explicitly enabled, the ISA target for the host machine is enabled.
x86 = []
Expand Down
30 changes: 30 additions & 0 deletions cranelift-codegen/src/binemit/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,36 @@ 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
13 changes: 9 additions & 4 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, MemoryCodeSink, RelocSink, StackmapSink,
TrapSink,
relax_branches, shrink_instructions, CodeInfo, FrameUnwindKind, FrameUnwindSink,
MemoryCodeSink, RelocSink, StackmapSink, TrapSink,
};
use crate::dce::do_dce;
use crate::dominator_tree::DominatorTree;
Expand Down Expand Up @@ -201,8 +201,13 @@ impl Context {
///
/// 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(&self, isa: &dyn TargetIsa, mem: &mut Vec<u8>) {
isa.emit_unwind_info(&self.func, mem);
pub fn emit_unwind_info(
&self,
isa: &dyn TargetIsa,
kind: FrameUnwindKind,
peterhuene marked this conversation as resolved.
Show resolved Hide resolved
sink: &mut dyn FrameUnwindSink,
) {
isa.emit_unwind_info(&self.func, kind, sink);
}

/// Run the verifier on the function.
Expand Down
5 changes: 5 additions & 0 deletions cranelift-codegen/src/ir/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,11 @@ 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());
}

Expand Down
8 changes: 6 additions & 2 deletions cranelift-codegen/src/isa/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ use crate::settings::SetResult;
use crate::timing;
use alloc::borrow::Cow;
use alloc::boxed::Box;
use alloc::vec::Vec;
use core::fmt;
use target_lexicon::{triple, Architecture, PointerWidth, Triple};
use thiserror::Error;
Expand Down Expand Up @@ -382,7 +381,12 @@ pub trait TargetIsa: fmt::Display + Send + Sync {
/// Emit unwind information for the given function.
///
/// Only some calling conventions (e.g. Windows fastcall) will have unwind information.
fn emit_unwind_info(&self, _func: &ir::Function, _mem: &mut Vec<u8>) {
fn emit_unwind_info(
&self,
_func: &ir::Function,
_kind: binemit::FrameUnwindKind,
_sink: &mut dyn binemit::FrameUnwindSink,
) {
// No-op by default
}
}
31 changes: 25 additions & 6 deletions cranelift-codegen/src/isa/x86/abi.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
//! x86 ABI implementation.

use super::super::settings as shared_settings;
#[cfg(feature = "unwind")]
use super::fde::emit_fde;
use super::registers::{FPR, GPR, RU};
use super::settings as isa_settings;
#[cfg(feature = "unwind")]
use super::unwind::UnwindInfo;
use crate::abi::{legalize_args, ArgAction, ArgAssigner, ValueConversion};
#[cfg(feature = "unwind")]
use crate::binemit::{FrameUnwindKind, FrameUnwindSink};
use crate::cursor::{Cursor, CursorPosition, EncCursor};
use crate::ir;
use crate::ir::immediates::Imm64;
Expand All @@ -18,7 +23,6 @@ use crate::regalloc::RegisterSet;
use crate::result::CodegenResult;
use crate::stack_layout::layout_stack;
use alloc::borrow::Cow;
use alloc::vec::Vec;
use core::i32;
use std::boxed::Box;
use target_lexicon::{PointerWidth, Triple};
Expand Down Expand Up @@ -947,10 +951,25 @@ fn insert_common_epilogue(
}
}

pub fn emit_unwind_info(func: &ir::Function, isa: &dyn TargetIsa, mem: &mut Vec<u8>) {
// Assumption: RBP is being used as the frame pointer
// In the future, Windows fastcall codegen should usually omit the frame pointer
if let Some(info) = UnwindInfo::try_from_func(func, isa, Some(RU::rbp.into())) {
info.emit(mem);
#[cfg(feature = "unwind")]
pub fn emit_unwind_info(
func: &ir::Function,
isa: &dyn TargetIsa,
kind: FrameUnwindKind,
sink: &mut dyn FrameUnwindSink,
) {
match kind {
FrameUnwindKind::Fastcall => {
// Assumption: RBP is being used as the frame pointer
// In the future, Windows fastcall codegen should usually omit the frame pointer
if let Some(info) = UnwindInfo::try_from_func(func, isa, Some(RU::rbp.into())) {
info.emit(sink);
}
}
FrameUnwindKind::Libunwind => {
if func.frame_layout.is_some() {
emit_fde(func, isa, sink);
}
}
}
}
Loading