Skip to content

[DRAFT] add allocator libraries compatible with the new rustc mangling #3403

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 24 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
688e05b
add allocator libraries compatible with the new rustc mangling
krasimirgg Apr 10, 2025
97d65c6
fixes
krasimirgg Apr 10, 2025
09ef052
fixes
krasimirgg Apr 10, 2025
aef67c7
add global alloc support and tests
krasimirgg Apr 11, 2025
2c20ec4
add a way to control rustc allocator libraries feature per-toolchain
krasimirgg Apr 15, 2025
fdfa08e
add to its own attribute dict
krasimirgg Apr 15, 2025
bc47c49
formatting
krasimirgg Apr 15, 2025
34770cb
formatting
krasimirgg Apr 15, 2025
911f877
reformat
krasimirgg Apr 15, 2025
3c2746d
Merge branch 'bazelbuild:main' into rustc_std_internal_symbols
krasimirgg Apr 28, 2025
161c960
add nostd test and fix
krasimirgg Apr 28, 2025
9e2c701
mv no_std tests to top-level
krasimirgg Apr 28, 2025
78d8446
merge new and old no_std tests
krasimirgg Apr 29, 2025
705bdfc
unify cc_common_link tests
krasimirgg Apr 29, 2025
78c46cd
unify cc_common_link_with_global_alloc tests
krasimirgg Apr 29, 2025
a9914a4
try to pass the alloc lib expliticly
krasimirgg Apr 29, 2025
f5b87b0
ditto
krasimirgg Apr 29, 2025
b3a613b
put the alloc libs at the bottom of stdlibs
krasimirgg May 6, 2025
08f1c2b
Merge branch 'bazelbuild:main' into rustc_std_internal_symbols
krasimirgg May 6, 2025
2dad832
adapt allocator libs to be deps of liballoc
krasimirgg May 6, 2025
47505fd
add an alloc impl provider
krasimirgg May 8, 2025
322af5c
Merge branch 'main' into rustc_std_internal_symbols
krasimirgg Jun 3, 2025
547a4f5
Merge branch 'bazelbuild:main' into rustc_std_internal_symbols
krasimirgg Jun 24, 2025
609020e
add some docs
krasimirgg Jun 24, 2025
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
36 changes: 36 additions & 0 deletions .bazelci/presubmit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,18 @@ tasks:
- "//..."
test_targets:
- "//..."
cc_common_link_and_mangling_ubuntu2004:
name: Build via cc_common.link with rustc mangling alloc symbols
platform: ubuntu2004
working_directory: test/integration/cc_common_link
build_targets:
- "//..."
test_targets:
- "//..."
build_flags:
- "--config=mangled_alloc_symbols"
test_flags:
- "--config=mangled_alloc_symbols"
cc_common_link_with_global_alloc_ubuntu2004:
name: Build via cc_common.link using a global allocator
platform: ubuntu2004
Expand All @@ -550,6 +562,18 @@ tasks:
- "//..."
test_targets:
- "//..."
cc_common_link_with_global_alloc_and_mangling_ubuntu2004:
name: Build via cc_common.link using a global allocator with rustc mangling alloc symbols
platform: ubuntu2004
working_directory: test/integration/cc_common_link_with_global_alloc
build_targets:
- "//..."
test_targets:
- "//..."
build_flags:
- "--config=mangled_alloc_symbols"
test_flags:
- "--config=mangled_alloc_symbols"
cc_common_link_no_std_ubuntu2004:
name: Build with no_std + alloc using cc_common.link infrastructure for linking
platform: ubuntu2004
Expand All @@ -562,6 +586,18 @@ tasks:
- "--config=no_std_alloc_using_cc_common_link"
test_flags:
- "--config=no_std_alloc_using_cc_common_link"
cc_common_link_no_std_and_mangling_ubuntu2004:
name: Build with no_std + alloc using cc_common.link infrastructure for linking with rust toolchain mangling alloc symbols
platform: ubuntu2004
working_directory: test/integration/no_std
build_targets:
- "//..."
test_targets:
- "//..."
build_flags:
- "--config=no_std_alloc_using_cc_common_link_and_mangled_alloc_symbols"
test_flags:
- "--config=no_std_alloc_using_cc_common_link_and_mangled_alloc_symbols"
no_std_ubuntu2004:
name: Build with no_std + alloc
platform: ubuntu2004
Expand Down
40 changes: 40 additions & 0 deletions ffi/rs/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
load("@rules_cc//cc:cc_library.bzl", "cc_library")

# buildifier: disable=bzl-visibility
load("@rules_rust//rust/private:rust.bzl", "rust_allocator_libraries")

rust_allocator_libraries(
name = "allocator_libraries_with_mangling_support",
allocator_library = "@rules_rust//ffi/rs/allocator_library",
global_allocator_library = "@rules_rust//ffi/rs/global_allocator_library",
visibility = ["//visibility:public"],
)

rust_allocator_libraries(
name = "empty_allocator_libraries",
visibility = ["//visibility:public"],
)

alias(
name = "default_allocator_libraries",
actual = select({
"@rules_rust//rust/settings:experimental_use_allocator_libraries_with_mangled_symbols_on": ":allocator_libraries_with_mangling_support",
"//conditions:default": ":empty_allocator_libraries",
}),
visibility = ["//visibility:public"],
)

cc_library(
name = "empty",
visibility = ["//visibility:public"],
)

# Allocator libraries used while bootstrapping the process wrapper.
rust_allocator_libraries(
name = "allocator_libraries_with_mangling_support_without_process_wrapper",
allocator_library = "@rules_rust//ffi/rs/allocator_library:allocator_library_without_process_wrapper",
# no need for a global allocator library, since the process wrapper
# is always bootstrapped in exec mode, which always uses the default
# allocator.
visibility = ["@rules_rust//util/process_wrapper:__subpackages__"],
)
35 changes: 35 additions & 0 deletions ffi/rs/allocator_library/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
load("@rules_rust//rust:defs.bzl", "rust_library")

# buildifier: disable=bzl-visibility
load(
"@rules_rust//rust/private:rust.bzl",
"rust_library_without_process_wrapper",
)

package(
default_visibility = ["@rules_rust//ffi/rs:__subpackages__"],
)

srcs = select({
# Windows doesn't support weak symbol linkage.
# If someone can make this work on Windows, please do!
# For now we will silently not supply any symbols, because it would be very messy to conditionally define the default allocator library on toolchains depending on the platform.
"@platforms//os:windows": ["empty.rs"],
"//conditions:default": ["allocator_library.rs"],
})

rust_library(
name = "allocator_library",
srcs = srcs,
allocator_libraries = "@rules_rust//ffi/rs:empty_allocator_libraries",
edition = "2024",
tags = ["manual"],
)

rust_library_without_process_wrapper(
name = "allocator_library_without_process_wrapper",
srcs = srcs,
allocator_libraries = "@rules_rust//ffi/rs:empty_allocator_libraries",
edition = "2024",
tags = ["manual"],
)
86 changes: 86 additions & 0 deletions ffi/rs/allocator_library/allocator_library.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// Workaround for Rust issue https://github.com/rust-lang/rust/issues/73632
// We provide the allocator functions that rustc leaves in rlibs. These are
// normally provided by rustc during the linking phase (since the allocator in
// use can vary), but if rustc doesn't do the final link we have to provide
// these manually. Hopefully we can make progress on the above bug and
// eventually not need this kludge.
//
// Recently rustc started mangling these symbols, so we rewrote them in
// rust.
// https://github.com/rust-lang/rust/pull/127173
//
// This code uses unstable internal rustc features that are only available when
// using a nightly toolchain. Also, it is only compatible with versions
// of rustc that include the symbol mangling, such as nightly/2025-04-08 or
// later.
//
// This has been translated from our c++ version
// rules_rust/ffi/cc/allocator_library/allocator_library.cc.
#![no_std]
#![allow(warnings)]
#![allow(internal_features)]
#![feature(rustc_attrs)]
#![feature(linkage)]

unsafe extern "C" {
#[rustc_std_internal_symbol]
fn __rdl_alloc(size: usize, align: usize) -> *mut u8;

#[rustc_std_internal_symbol]
fn __rdl_dealloc(ptr: *mut u8, size: usize, align: usize);

#[rustc_std_internal_symbol]
fn __rdl_realloc(ptr: *mut u8, old_size: usize, align: usize, new_size: usize) -> *mut u8;

#[rustc_std_internal_symbol]
fn __rdl_alloc_zeroed(size: usize, align: usize) -> *mut u8;
}

#[linkage = "weak"]
#[rustc_std_internal_symbol]
fn __rust_alloc(size: usize, align: usize) -> *mut u8 {
unsafe {
return __rdl_alloc(size, align);
}
}

#[linkage = "weak"]
#[rustc_std_internal_symbol]
fn __rust_dealloc(ptr: *mut u8, size: usize, align: usize) {
unsafe {
return __rdl_dealloc(ptr, size, align);
}
}

#[linkage = "weak"]
#[rustc_std_internal_symbol]
fn __rust_realloc(ptr: *mut u8, old_size: usize, align: usize, new_size: usize) -> *mut u8 {
unsafe {
return __rdl_realloc(ptr, old_size, align, new_size);
}
}

#[linkage = "weak"]
#[rustc_std_internal_symbol]
fn __rust_alloc_zeroed(size: usize, align: usize) -> *mut u8 {
unsafe {
return __rdl_alloc_zeroed(size, align);
}
}

#[linkage = "weak"]
#[rustc_std_internal_symbol]
fn __rust_alloc_error_handler(size: usize, align: usize) {
panic!();
}

// New feature as of https://github.com/rust-lang/rust/pull/88098.
// This symbol is normally emitted by rustc. 0 means OOMs should abort, 1 means OOMs should panic.
#[linkage = "weak"]
#[rustc_std_internal_symbol]
static mut __rust_alloc_error_handler_should_panic: u8 = 1;

// See https://github.com/rust-lang/rust/issues/73632#issuecomment-1563462239
#[linkage = "weak"]
#[rustc_std_internal_symbol]
static mut __rust_no_alloc_shim_is_unstable: u8 = 0;
Empty file.
21 changes: 21 additions & 0 deletions ffi/rs/global_allocator_library/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
load("@rules_rust//rust:defs.bzl", "rust_library")

package(
default_visibility = ["@rules_rust//ffi/rs:__subpackages__"],
)

srcs = select({
# Windows doesn't support weak symbol linkage.
# If someone can make this work on Windows, please do!
# For now we will silently not supply any symbols, because it would be very messy to conditionally define the global allocator library on toolchains depending on the platform.
"@platforms//os:windows": ["empty.rs"],
"//conditions:default": ["global_allocator_library.rs"],
})

rust_library(
name = "global_allocator_library",
srcs = srcs,
allocator_libraries = "@rules_rust//ffi/rs:empty_allocator_libraries",
edition = "2024",
tags = ["manual"],
)
Empty file.
48 changes: 48 additions & 0 deletions ffi/rs/global_allocator_library/global_allocator_library.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Workaround for Rust issue https://github.com/rust-lang/rust/issues/73632
// We provide the allocator functions that rustc leaves in rlibs. These are
// normally provided by rustc during the linking phase (since the allocator in
// use can vary), but if rustc doesn't do the final link we have to provide
// these manually. Hopefully we can make progress on the above bug and
// eventually not need this kludge.
//
// Recently rustc started mangling these symbols, so we rewrote them in
// rust.
// https://github.com/rust-lang/rust/pull/127173
//
// This code uses unstable internal rustc features that are only available when
// using a nightly toolchain. Also, it is only compatible with versions
// of rustc that include the symbol mangling, such as nightly/2025-04-08 or
// later.
//
// This has been translated from our c++ version
// rules_rust/ffi/cc/global_allocator_library/global_allocator_library.cc.
#![no_std]
#![allow(warnings)]
#![allow(internal_features)]
#![feature(rustc_attrs)]
#![feature(linkage)]

unsafe extern "C" {
#[rustc_std_internal_symbol]
fn __rg_oom(size: usize, align: usize) -> *mut u8;
}

#[linkage = "weak"]
#[rustc_std_internal_symbol]
fn __rust_alloc_error_handler(size: usize, align: usize) {
unsafe {
__rg_oom(size, align);
}
}


// New feature as of https://github.com/rust-lang/rust/pull/88098.
// This symbol is normally emitted by rustc. 0 means OOMs should abort, 1 means OOMs should panic.
#[linkage = "weak"]
#[rustc_std_internal_symbol]
static mut __rust_alloc_error_handler_should_panic: u8 = 1;

// See https://github.com/rust-lang/rust/issues/73632#issuecomment-1563462239
#[linkage = "weak"]
#[rustc_std_internal_symbol]
static mut __rust_no_alloc_shim_is_unstable: u8 = 0;
8 changes: 8 additions & 0 deletions rust/extensions.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ def _rust_impl(module_ctx):
"name": repository_set.name,
"rustfmt_version": repository_set.rustfmt_version,
"sha256s": repository_set.sha256s,
"target_settings": [str(v) for v in repository_set.target_settings],
"urls": repository_set.urls,
"versions": repository_set.versions,
}
Expand Down Expand Up @@ -119,6 +120,7 @@ def _rust_impl(module_ctx):
register_toolchains = False,
aliases = toolchain.aliases,
toolchain_triples = toolchain_triples,
target_settings = [str(v) for v in toolchain.target_settings],
extra_toolchain_infos = extra_toolchain_infos,
)
metadata_kwargs = {}
Expand Down Expand Up @@ -170,6 +172,9 @@ _RUST_REPOSITORY_SET_TAG_ATTRS = {
"target_compatible_with": attr.label_list(
doc = "List of platform constraints this toolchain produces, for the particular target_triple this call is for.",
),
"target_settings": attr.label_list(
doc = "A list of `config_settings` that must be satisfied by the target configuration in order for this toolchain to be selected during toolchain resolution.",
),
"target_triple": attr.string(
doc = "target_triple to configure.",
),
Expand Down Expand Up @@ -214,6 +219,9 @@ _RUST_TOOLCHAIN_TAG = tag_class(
"rust_analyzer_version": attr.string(
doc = "The version of Rustc to pair with rust-analyzer.",
),
"target_settings": attr.label_list(
doc = "A list of `config_settings` that must be satisfied by the target configuration in order for this toolchain to be selected during toolchain resolution.",
),
"versions": attr.string_list(
doc = (
"A list of toolchain versions to download. This parameter only accepts one version " +
Expand Down
18 changes: 18 additions & 0 deletions rust/private/providers.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -188,3 +188,21 @@ LintsInfo = provider(
"rustdoc_lint_flags": "List[String]: rustc flags to specify when building rust_doc targets.",
},
)

AllocatorLibrariesInfo = provider(
doc = "AllocatorLibrariesInfo provides allocator libraries for linking rust code with a non-rust linker.",
fields = {
"allocator_library": "Optional[CcInfo]: used when the default rust allocator is used",
"global_allocator_library": "Optional[CcInfo]: used when a global rust allocator is used",
"libstd_and_allocator_ccinfo": "Optional[CcInfo]: used when the default rust allocator is used",
"libstd_and_global_allocator_ccinfo": "Optional[CcInfo]: used when a global rust allocator is used",
"nostd_and_global_allocator_ccinfo": "Optional[CcInfo]: used when nostd with a global rust allocator is used",
},
)

AllocatorLibrariesImplInfo = provider(
doc = "AllocatorLibrariesImplInfo provides the rust-generated linker input for linking rust code with a non-rust linker.",
fields = {
"static_archive": "Optional[File]: the allocator library archive (typically .a file).",
},
)
Loading
Loading