/rust-core

a lightweight standard library for rust with freestanding support

Primary LanguageRustApache License 2.0Apache-2.0

A lightweight standard library for Rust with freestanding support. It provides a baseline level of functionality without any external dependencies, and an extended set of features in a traditional hosted environment.

The core library is currently designed to be used as a module, but as Rust's support for static linking and link-time optimization matures it will move towards the standard crate model.

Configuration

  • --cfg libc to enable features depending on a C standard library implementation
  • --cfg debug to enable debugging features (assertions)

Building

Currently, building to bytecode with --emit-llvm and then compiling/linking with clang is required because the Rust compiler cannot build code without the requirement for segmented stack support from the runtime. There is also no way to avoid position independent code and linking against the runtime without making use of clang.

rustc -O --emit-llvm foo.rs
clang -O2 -flto -lm -lpthread -o foo foo.bc

As an additional problem, the Rust compiler assumes unwinding is used. Until there is a way to disable unwinding this will be extremely problematic. Rust will output code for running destructors during table-based unwinding with a dependency on the runtime for segmented stack support. LLVM can optimize most of this away thanks to link-time optimization, but Rust provides no way to mark external functions as not throwing. As soon as calls are made to external functions not hard-wired into LLVM as nounwind, the ability to use Rust without the runtime breaks down.

Freestanding usage

For freestanding use, simply omit the libc configuration switch.

LLVM will emit calls to memcpy, memmove and memset. Until the fix for symbol visibility lands, these must be provided by the auxilliary support.rs module.

The support.rs module must be compiled with rustc --lib --emit-llvm -passes inline and then linked against the bytecode for the main module with clang -flto -O2 main.bc support.bc.

The inline pass must be run separately to due to issue #10116 or LLVM will generate infinitely recursive functions.

Stack safety

Ideally, stack safety is provided with one or more guard pages and compiler support for inserting checks based on awareness of the guard pages. GCC has this as -fcheck-stack but LLVM is missing the feature.

At the moment, core only has OS-provided guard pages without the necessary checks on frames larger than the guard size.

Rust's standard library provides stack safety via LLVM's segmented stack support, but this has a negative performance and code size impact. It's also unavailable without the Rust runtime.

Allocators

Allocators are not yet working due to issue #4252.

The core::mem::Allocator trait defines the allocator interface. A generic container takes an allocator type parameter, with core::heap::Heap as the default allocator for a container constructed with the new static method.

A container can be constructed using Container::with_alloc(allocator), and will store the allocator instance internally. Since Rust has zero-size types, this has no overhead for allocators with no instance state.

Sharing stateful allocator instances between containers can be done with core::rc or `core::arc . Containers are already expensive to clone, so a reference count on container copies shouldn't be an issue.