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 21 commits into
base: main
Choose a base branch
from
Draft
Changes from all commits
Commits
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
@@ -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
@@ -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
@@ -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
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
@@ -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,
}
@@ -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 = {}
@@ -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.",
),
@@ -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 " +
18 changes: 18 additions & 0 deletions rust/private/providers.bzl
Original file line number Diff line number Diff line change
@@ -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