portable_link_section 0.1.0

A portable version of the #[link_section] macro.
Documentation
# Portable `#[link_section]` for Rust

A macro to provide support for portable `#[link_section]` annotations in Rust.

This respects the following binary file formats:

- [ELF]https://en.wikipedia.org/wiki/Executable_and_Linkable_Format
- [Mach-O]https://en.wikipedia.org/wiki/Mach-O
- [COFF]https://en.wikipedia.org/wiki/COFF

## Usage

In essence the `#[portable_link_section]` macro is a restricted version of `#[link_section]`.

The `#[portable_link_section]` macro accepts one of the following `segment` identifiers:

- `text`: code
- `data`: writable data
- `rodata`: read-only data
- `bss`: zero-initialized data

When given `text` or `data` the macro expects another `group` identifier that has to follow some strict rules to provide portability.

Interpreters might have a use for portable `#[link_section]` in order to have more control where certain operator handler functions are placed in memory in order to improve I-cache efficiency by grouping hot and cold code.

## Examples

### Apply `text` on `fn` items.

```rust
#[portable_link_section(text(hot))]
fn func_0() {}

#[portable_link_section(text(cold_i32))]
fn func_1(lhs: i32, rhs: i32) -> i32 {
    lhs.wrapping_add(rhs)
}
```

### Apply `data`, `rodata` or `bss` on `static` items.

```rust
#[portable_link_section(data(my_group))]
static DATA_0: i32 = 42;

#[portable_link_section(rodata)]
static DATA_1: i32 = 42;

#[portable_link_section(bss)]
static DATA_2: i32 = 0;
```

### Strict Rules Examples

Certain `group` identifiers have special meaning on some platforms,
therefore their usage is forbidden as to not end up with non-conformant
semantics across platforms.

```rust
#[portable_link_section(text(const))] // ~ERROR: const is reserved for `text` in MACH-O and therefore forbidden
fn func_0() {}

#[portable_link_section(data(common))] // ~ERROR: common is reserved for `data` in MACH-O and therefore forbidden
static DATA_0: i32 = 42;
```

The MACH-O file format has a strict limit on the structure of link section identifiers
as their length is capped to 16 bytes. Since they are represented as zero-terminated strings
we allow a maximum of 15 bytes per `group` identifier. 

```rust
#[portable_link_section(text(this_group_identifier_is_too_long))] // ~ERROR: MACH-O has a limit of 15 bytes per identifier
fn func_0() {}
```

### Macro Expansion

The following Rust code that uses the `#[portable_link_section]`:

```rust
#[portable_link_section(text(hot))]
fn func_0() {}
```

Gets expanded into the following Rust code:

```rust
#[cfg_attr(
    all(target_family = "unix", not(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))),
    unsafe(link_section = ".text.hot"),
)]
#[cfg_attr(
    any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"),
    unsafe(link_section = "__TEXT,__hot"),
)]
#[cfg_attr(
    target_os = "windows",
    unsafe(link_section = ".text$hot"),
)]
fn func_0() {}
```

## License

Licensed under either of

  * Apache License, Version 2.0, ([LICENSE-APACHE]LICENSE-APACHE or <https://www.apache.org/licenses/LICENSE-2.0>)
  * MIT license ([LICENSE-MIT]LICENSE-MIT or <https://opensource.org/licenses/MIT>)

at your option.