Skip to content

Commit 338c548

Browse files
A proof-of-concept for defmt *without* interning strings.
This is just an experiment for now. If the 'no-interning' feature is set, instead of #[export_name = "{JSON...}"] static S: u8 = 0; &S as *const _ as usize You get: static S: &'static str = "{JSON...}"; &S as *const _ as usize Note that I had to change the size of the interned ID from u16 to usize, because with no-interning it's now a pointer to actual data.
1 parent 843e72e commit 338c548

File tree

7 files changed

+52
-22
lines changed

7 files changed

+52
-22
lines changed

book/src/setup.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,4 +59,10 @@ To learn how to enable other logging levels and filters logs per modules read th
5959

6060
### Memory use
6161

62-
When in a tight memory situation and logging over RTT, the buffer size (default: 1024 bytes) can be configured with the `DEFMT_RTT_BUFFER_SIZE` environment variable. Use a power of 2 for best performance.
62+
When in a tight memory situation and logging over RTT, the buffer size (default: 1024 bytes) can be configured with the `DEFMT_RTT_BUFFER_SIZE` environment variable. Use a power of 2 for best performance.
63+
64+
### Use on Windows/macOS/Linux
65+
66+
You can use `defmt` without string-interning by enabling the `no-interning` feature. This will mean that format strings are included as literal strings and not hidden in the symbol name.
67+
68+
You can optionally send the output to the `log` crate by enabling the `use-log-crate` feature.

defmt/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ version = "0.3.8"
2121
alloc = []
2222
avoid-default-panic = []
2323
ip_in_core = []
24+
no-interning = [ "defmt-macros/no-interning" ]
25+
use-log-crate = []
2426

2527
# Encoding feature flags. These should only be set by end-user crates, not by library crates.
2628
#

defmt/src/export/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ pub fn timestamp(fmt: crate::Formatter<'_>) {
9999
}
100100

101101
/// Returns the interned string at `address`.
102-
pub fn make_istr(address: u16) -> Str {
102+
pub fn make_istr(address: usize) -> Str {
103103
Str { address }
104104
}
105105

defmt/src/formatter.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,6 @@ pub struct Formatter<'a> {
1111
/// [`intern!`]: macro.intern.html
1212
#[derive(Clone, Copy)]
1313
pub struct Str {
14-
/// 16-bit address
15-
pub(crate) address: u16,
14+
/// The address of the interned string
15+
pub(crate) address: usize,
1616
}

macros/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ proc-macro = true
1515
[features]
1616
# WARNING: for internal use only, not covered by semver guarantees
1717
unstable-test = []
18+
# Turns off string interning
19+
no-interning = []
1820

1921
[dependencies]
2022
defmt-parser = { version = "=0.3.4", path = "../parser" }

macros/src/construct.rs

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ pub(crate) fn interned_string(
4747
let var_item = static_variable(&var_name, string, tag, prefix);
4848
quote!({
4949
#var_item
50-
&#var_name as *const u8 as u16
50+
&#var_name as *const _ as usize
5151
})
5252
};
5353

@@ -61,17 +61,23 @@ pub(crate) fn interned_string(
6161
/// under macos: ".defmt," + 16 character hex digest of symbol's hash
6262
/// otherwise: ".defmt." + prefix + symbol
6363
pub(crate) fn linker_section(for_macos: bool, prefix: Option<&str>, symbol: &str) -> String {
64-
let mut sub_section = if let Some(prefix) = prefix {
65-
format!(".{prefix}.{symbol}")
64+
let symbol_hash = hash(symbol);
65+
let suffix = if for_macos {
66+
// The Apple linker doesn't like `.` in input section names
67+
if let Some(prefix) = prefix {
68+
format!(",{prefix}_{symbol_hash:x}")
69+
} else {
70+
format!(",{symbol_hash:x}")
71+
}
6672
} else {
67-
format!(".{symbol}")
73+
if let Some(prefix) = prefix {
74+
format!(".{prefix}.{symbol_hash:x}")
75+
} else {
76+
format!(".{symbol_hash:x}")
77+
}
6878
};
6979

70-
if for_macos {
71-
sub_section = format!(",{:x}", hash(&sub_section));
72-
}
73-
74-
format!(".defmt{sub_section}")
80+
format!(".defmt{suffix}")
7581
}
7682

7783
pub(crate) fn static_variable(
@@ -83,13 +89,20 @@ pub(crate) fn static_variable(
8389
let sym_name = mangled_symbol_name(tag, data);
8490
let section = linker_section(false, prefix, &sym_name);
8591
let section_for_macos = linker_section(true, prefix, &sym_name);
86-
87-
quote!(
88-
#[cfg_attr(target_os = "macos", link_section = #section_for_macos)]
89-
#[cfg_attr(not(target_os = "macos"), link_section = #section)]
90-
#[export_name = #sym_name]
91-
static #name: u8 = 0;
92-
)
92+
if cfg!(feature = "no-interning") {
93+
quote!(
94+
#[cfg_attr(target_os = "macos", link_section = #section_for_macos)]
95+
#[cfg_attr(not(target_os = "macos"), link_section = #section)]
96+
static #name: &'static str = #sym_name;
97+
)
98+
} else {
99+
quote!(
100+
#[cfg_attr(target_os = "macos", link_section = #section_for_macos)]
101+
#[cfg_attr(not(target_os = "macos"), link_section = #section)]
102+
#[export_name = #sym_name]
103+
static #name: u8 = 0;
104+
)
105+
}
93106
}
94107

95108
pub(crate) fn string_literal(content: &str) -> LitStr {

macros/src/function_like/internp.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,21 @@ pub(crate) fn expand(args: TokenStream) -> TokenStream {
1313
let section_for_macos = construct::linker_section(true, prefix, &sym_name);
1414

1515
let var_addr = if cfg!(feature = "unstable-test") {
16-
quote!({ defmt::export::fetch_add_string_index() as u16 })
16+
quote!({ defmt::export::fetch_add_string_index() as usize })
17+
} else if cfg!(feature = "no-interning") {
18+
quote!({
19+
#[cfg_attr(target_os = "macos", link_section = #section_for_macos)]
20+
#[cfg_attr(not(target_os = "macos"), link_section = #section)]
21+
static S: &'static str = #sym_name;
22+
&S as *const _ as usize
23+
})
1724
} else {
1825
quote!({
1926
#[cfg_attr(target_os = "macos", link_section = #section_for_macos)]
2027
#[cfg_attr(not(target_os = "macos"), link_section = #section)]
2128
#[export_name = #sym_name]
2229
static S: u8 = 0;
23-
&S as *const u8 as u16
30+
&S as *const _ as usize
2431
})
2532
};
2633

0 commit comments

Comments
 (0)