Skip to content

Commit

Permalink
Remove smallvec dependency
Browse files Browse the repository at this point in the history
This commit removes `smallvec` as a dependency of the `read` feature of
this crate. This is an extension of #494 to help make `gimli` easier to
include into the standard library. The `smallvec` crate was only used in
one location inside of `gimli`, in `Abbreviation` parsing. This was
converted to a manual inline small-vector along with a new type
`Attributes` to wrap this up. This also removes `smallvec` from the
public API of `gimli` to allow future changes to the representation if
necessary.
  • Loading branch information
alexcrichton committed May 9, 2020
1 parent f346d6f commit a08d35c
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 31 deletions.
3 changes: 1 addition & 2 deletions Cargo.toml
Expand Up @@ -21,7 +21,6 @@ arrayvec = { version = "0.5.0", default-features = false, optional = true }
byteorder = { version = "1.0", default-features = false }
fallible-iterator = { version = "0.2.0", default-features = false, optional = true }
indexmap = { version = "1.0.2", optional = true }
smallvec = { version = "1.1.0", default-features = false, optional = true }
stable_deref_trait = { version = "1.1.0", default-features = false, optional = true }

[dev-dependencies]
Expand All @@ -36,7 +35,7 @@ test-assembler = "0.1.3"
typed-arena = "2"

[features]
read = ["arrayvec", "fallible-iterator", "smallvec", "stable_deref_trait"]
read = ["arrayvec", "fallible-iterator", "stable_deref_trait"]
write = ["indexmap"]
std = ["fallible-iterator/std", "stable_deref_trait/std"]
default = ["read", "write", "std"]
Expand Down
133 changes: 112 additions & 21 deletions src/read/abbrev.rs
Expand Up @@ -2,7 +2,9 @@

use alloc::collections::btree_map;
use alloc::vec::Vec;
use smallvec::SmallVec;
use core::fmt::{self, Debug};
use core::iter::FromIterator;
use core::ops::Deref;

use crate::common::{DebugAbbrevOffset, SectionId};
use crate::constants;
Expand Down Expand Up @@ -174,9 +176,6 @@ impl Abbreviations {
}
}

// Length of 5 based on benchmark results for both x86-64 and i686.
type Attributes = SmallVec<[AttributeSpecification; 5]>;

/// An abbreviation describes the shape of a `DebuggingInformationEntry`'s type:
/// its code, tag type, whether it has children, and its set of attributes.
#[derive(Debug, Clone, PartialEq, Eq)]
Expand All @@ -193,7 +192,7 @@ impl Abbreviation {
/// ### Panics
///
/// Panics if `code` is `0`.
pub fn new(
pub(crate) fn new(
code: u64,
tag: constants::DwTag,
has_children: constants::DwChildren,
Expand Down Expand Up @@ -256,7 +255,7 @@ impl Abbreviation {
/// Parse a series of attribute specifications, terminated by a null attribute
/// specification.
fn parse_attributes<R: Reader>(input: &mut R) -> Result<Attributes> {
let mut attrs = SmallVec::new();
let mut attrs = Attributes::new();

while let Some(attr) = AttributeSpecification::parse(input)? {
attrs.push(attr);
Expand All @@ -281,6 +280,93 @@ impl Abbreviation {
}
}

/// A list of attributes found in an `Abbreviation`
#[derive(Clone)]
pub(crate) enum Attributes {
Inline {
buf: [AttributeSpecification; MAX_ATTRIBUTES_INLINE],
len: usize,
},
Heap(Vec<AttributeSpecification>),
}

// Length of 5 based on benchmark results for both x86-64 and i686.
const MAX_ATTRIBUTES_INLINE: usize = 5;

impl Attributes {
/// Returns a new empty list of attributes
fn new() -> Attributes {
let default =
AttributeSpecification::new(constants::DW_AT_null, constants::DW_FORM_null, None);
Attributes::Inline {
buf: [default; 5],
len: 0,
}
}

/// Pushes a new value onto this list of attributes.
fn push(&mut self, attr: AttributeSpecification) {
match self {
Attributes::Heap(list) => return list.push(attr),
Attributes::Inline {
buf,
len: MAX_ATTRIBUTES_INLINE,
} => {
let mut list = buf.to_vec();
list.push(attr);
*self = Attributes::Heap(list);
}
Attributes::Inline { buf, len } => {
buf[*len] = attr;
*len += 1;
}
}
}
}

impl Debug for Attributes {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
(&**self).fmt(f)
}
}

impl PartialEq for Attributes {
fn eq(&self, other: &Attributes) -> bool {
&**self == &**other
}
}

impl Eq for Attributes {}

impl Deref for Attributes {
type Target = [AttributeSpecification];
fn deref(&self) -> &[AttributeSpecification] {
match self {
Attributes::Inline { buf, len } => &buf[..*len],
Attributes::Heap(list) => list,
}
}
}

impl FromIterator<AttributeSpecification> for Attributes {
fn from_iter<I>(iter: I) -> Attributes
where
I: IntoIterator<Item = AttributeSpecification>,
{
let mut list = Attributes::new();
for item in iter {
list.push(item);
}
return list;
}
}

impl From<Vec<AttributeSpecification>> for Attributes {
fn from(list: Vec<AttributeSpecification>) -> Attributes {
Attributes::Heap(list)
}
}

/// The description of an attribute in an abbreviated type. It is a pair of name
/// and form.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
Expand Down Expand Up @@ -420,7 +506,6 @@ pub mod tests {
use crate::test_util::GimliSectionMethods;
#[cfg(target_pointer_width = "32")]
use core::u32;
use smallvec::smallvec;
use test_assembler::Section;

pub trait AbbrevSectionMethods {
Expand Down Expand Up @@ -478,7 +563,7 @@ pub mod tests {
1,
constants::DW_TAG_compile_unit,
constants::DW_CHILDREN_yes,
smallvec![
vec![
AttributeSpecification::new(
constants::DW_AT_producer,
constants::DW_FORM_strp,
Expand All @@ -489,18 +574,20 @@ pub mod tests {
constants::DW_FORM_data2,
None,
),
],
]
.into(),
);

let abbrev2 = Abbreviation::new(
2,
constants::DW_TAG_subprogram,
constants::DW_CHILDREN_no,
smallvec![AttributeSpecification::new(
vec![AttributeSpecification::new(
constants::DW_AT_name,
constants::DW_FORM_string,
None,
)],
)]
.into(),
);

let debug_abbrev = DebugAbbrev::new(&buf, LittleEndian);
Expand All @@ -519,7 +606,7 @@ pub mod tests {
code.into(),
constants::DwTag(code),
constants::DW_CHILDREN_no,
smallvec![],
vec![].into(),
)
}

Expand Down Expand Up @@ -586,7 +673,7 @@ pub mod tests {
code,
constants::DwTag(code as u16),
constants::DW_CHILDREN_no,
smallvec![],
vec![].into(),
)
}

Expand Down Expand Up @@ -629,7 +716,7 @@ pub mod tests {
1,
constants::DW_TAG_compile_unit,
constants::DW_CHILDREN_yes,
smallvec![
vec![
AttributeSpecification::new(
constants::DW_AT_producer,
constants::DW_FORM_strp,
Expand All @@ -640,18 +727,20 @@ pub mod tests {
constants::DW_FORM_data2,
None,
),
],
]
.into(),
);

let abbrev2 = Abbreviation::new(
2,
constants::DW_TAG_subprogram,
constants::DW_CHILDREN_no,
smallvec![AttributeSpecification::new(
vec![AttributeSpecification::new(
constants::DW_AT_name,
constants::DW_FORM_string,
None,
)],
)]
.into(),
);

let abbrevs = Abbreviations::parse(rest).expect("Should parse abbreviations");
Expand Down Expand Up @@ -733,11 +822,12 @@ pub mod tests {
1,
constants::DW_TAG_subprogram,
constants::DW_CHILDREN_no,
smallvec![AttributeSpecification::new(
vec![AttributeSpecification::new(
constants::DW_AT_name,
constants::DW_FORM_string,
None,
)],
)]
.into(),
));

let abbrev = Abbreviation::parse(rest).expect("Should parse abbreviation");
Expand All @@ -761,11 +851,12 @@ pub mod tests {
1,
constants::DW_TAG_subprogram,
constants::DW_CHILDREN_no,
smallvec![AttributeSpecification::new(
vec![AttributeSpecification::new(
constants::DW_AT_name,
constants::DW_FORM_implicit_const,
Some(-42),
)],
)]
.into(),
));

let abbrev = Abbreviation::parse(rest).expect("Should parse abbreviation");
Expand Down
11 changes: 6 additions & 5 deletions src/read/unit.rs
Expand Up @@ -3447,7 +3447,6 @@ mod tests {
use crate::test_util::GimliSectionMethods;
use alloc::vec::Vec;
use core::cell::Cell;
use smallvec::smallvec;
use test_assembler::{Endian, Label, LabelMaker, Section};

// Mixin methods for `Section` to help define binary test data.
Expand Down Expand Up @@ -4766,15 +4765,16 @@ mod tests {
42,
constants::DW_TAG_subprogram,
constants::DW_CHILDREN_yes,
smallvec![
vec![
AttributeSpecification::new(constants::DW_AT_name, constants::DW_FORM_string, None),
AttributeSpecification::new(constants::DW_AT_low_pc, constants::DW_FORM_addr, None),
AttributeSpecification::new(
constants::DW_AT_high_pc,
constants::DW_FORM_addr,
None,
),
],
]
.into(),
);

// "foo", 42, 1337, 4 dangling bytes of 0xaa where children would be
Expand Down Expand Up @@ -4874,15 +4874,16 @@ mod tests {
42,
constants::DW_TAG_subprogram,
constants::DW_CHILDREN_yes,
smallvec![
vec![
AttributeSpecification::new(constants::DW_AT_name, constants::DW_FORM_string, None),
AttributeSpecification::new(constants::DW_AT_low_pc, constants::DW_FORM_addr, None),
AttributeSpecification::new(
constants::DW_AT_high_pc,
constants::DW_FORM_addr,
None,
),
],
]
.into(),
);

// "foo"
Expand Down
5 changes: 2 additions & 3 deletions src/read/value.rs
Expand Up @@ -912,7 +912,6 @@ mod tests {
Abbreviation, AttributeSpecification, DebuggingInformationEntry, EndianSlice, UnitHeader,
UnitOffset,
};
use smallvec::smallvec;

#[test]
#[rustfmt::skip]
Expand All @@ -933,7 +932,7 @@ mod tests {
42,
constants::DW_TAG_base_type,
constants::DW_CHILDREN_no,
smallvec![
vec![
AttributeSpecification::new(
constants::DW_AT_byte_size,
constants::DW_FORM_udata,
Expand All @@ -949,7 +948,7 @@ mod tests {
constants::DW_FORM_udata,
None,
),
],
].into(),
);

for &(attrs, result) in &[
Expand Down

0 comments on commit a08d35c

Please sign in to comment.