Skip to content
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

The "mangled-names" feature removes intrinsics from compiler_builtins that aren't in compiler_rt #525

Closed
danakj opened this issue May 18, 2023 · 9 comments

Comments

@danakj
Copy link
Contributor

danakj commented May 18, 2023

We're trying to link Rust into a C++ target and we don't want to create ODR violations between compiler_rt and compiler_builtins.

To avoid this, we set the mangled-names feature on compiler_builtins, so that the intrinsics do not get demangled. This avoids all collisions!

However Rust's compiler_builtins provides some intrinsics that are not present in clang's compiler_rt, for 128-bit integers. Such as: __udivti3 and __umodti3 which are referenced by rust\library\std\src\sys\windows\thread_parking.rs:169.

An error showing this is here: https://logs.chromium.org/logs/chromium/buildbucket/cr-buildbucket/8780748803129506673/+/u/compile__with_patch_/stdout#L7628_7

The mangled-names feature claims that it is for using Rust with compiler_rt, which is good. But it still needs to provide intrinsics that a C++ compiler_rt does not have.

How do we use mangled-names but keep 128-bit integer intrinsics that Rust needs and C/C++ does not provide?

@bjorn3
Copy link
Member

bjorn3 commented May 18, 2023

mangled-names is meant only for testing purposes as far as I can tell. If you use it, compiler-builtins is effectively unused as LLVM won't know to use the mangled names when emitting calls into it (and LLVM doesn't support changing the names afaik). Duplicate definitions in compiler_rt and compiler-builtins shouldn't matter. Rust's build system builds compiler-builtins with like 1000 codegen units and we place ever intrinsic in it's own module. This combined effectively causes every intrinsic to end up in a separate object file inside the libcompiler_builtins.rlib archive. By default linkers only pull in archive members if any of the symbols defined in them are actually used. This means that if an intrinsic is defined by both compiler-builtins and compiler_rt, the linker will pull in the right object for either compiler-builtins or compiler_rt, but not both, thus preventing a ODR violation.

Based on my reading of https://bugs.chromium.org/p/chromium/issues/detail?id=1445978 it seems the issue you are having is not that both impls collide (they should behave identically and only one of them will be picked by the linker) but that LLVM codegens an __aeabi_llsl call with a shift amount larger than the size in bits of the shifted value and the compiler-builtins impl doesn't allow this. I can't find any information about how it should behave for too large shift amounts. If that is UB, LLVM will have to be fixed. If it is defined behavior, the impl in compiler-builtins will have to be fixed.

Edit: It is UB. Quoting the ABI specification:

The shift functions only need to work for shift counts in 0..63.

@bjorn3
Copy link
Member

bjorn3 commented May 18, 2023

LLVM's RISC-V backend has the same UB issue, which caused a problem with compiler-builtins too: llvm/llvm-project#57988

@danakj
Copy link
Contributor Author

danakj commented May 18, 2023

Thanks for the additional context and links.

If you use it, compiler-builtins is effectively unused

This is what we want, as we want to use the C++ intrinsics until such time as we can make the explicit choice to switch.

This means that if an intrinsic is defined by both compiler-builtins and compiler_rt, the linker will pull in the right object for either compiler-builtins or compiler_rt, but not both, thus preventing a ODR violation.

It does not use the right one unfortunately, it appears to favour the Rust ones for C++ as well, unless we put the compiler-rt lib on the command line before any rlibs. We discovered this when C++ code started panicking in Rust intrinsics due to us linking a small piece of Rust into the C++ binary: https://bugs.chromium.org/p/chromium/issues/detail?id=1445978#c2

Your reading is correct, and as well, the Rust intrinsics have since been fixed to not panic in this situation. However the implementations are not the exact same and we don't intend that linking a Rust library changes the implementation of all C++ intrinsics, with potential performance implications. We would really like to have control over which intrinsics are used, and keep using the C++ intrinsics until we see that the Rust ones are a better choice globally.

Additional context: clang-cl's compiler-rt is missing i128 div/mod specifically https://bugs.chromium.org/p/chromium/issues/detail?id=787617 which is why we hit this problem when turning on mangled-names.

@bjorn3
Copy link
Member

bjorn3 commented May 18, 2023

Ideally LLVM would allow changing the names of the intrinsic calls it emits such that we can use our own implementation for rust code while allowing C/C++ code to keep using whichever implementation they want to use.

As for the missing intrinsics in compiler-rt, I guess the easiest way would be to copy the implementation in compiler-builtins to a separate crate. And for x86/x86_64, I think you did also have to copy src/probestack.rs if you want to omit compiler-builtins from the linker invocation (which enabling mangled-names is effectively equivalent too).

@danakj
Copy link
Contributor Author

danakj commented May 18, 2023

FWIW This is the Rust change to not panic on bad shifts: 1634193

@danakj
Copy link
Contributor Author

danakj commented May 18, 2023

Another option here would be to mark the symbols in compiler_builtins as weak. I know some other C++/Rust toolchains have done this to resolve the same issue. I was trying to avoid a post-build step like that though. If we could mark them all as #[linkage="weak"] behind a cfg that would be really good too (if linkage=weak works in nightly?)

@bjorn3
Copy link
Member

bjorn3 commented May 18, 2023

Behind a feature that is off by default I think using weak linkage should be fine.

danakj added a commit to danakj/compiler-builtins that referenced this issue May 19, 2023
When enabled, the weak-intrinsics feature will cause all intrinsics
functions to be marked with weak linkage (i.e. `#[linkage = "weak"])
so that they can be replaced at link time by a stronger symbol.

This can be set to use C++ intrinsics from the compiler-rt library,
as it will avoid Rust's implementation replacing the compiler-rt
implementation as long as the compiler-rt symbols are linked as
strong symbols. Typically this requires the compiler-rt library to
be explicitly specified in the link command.

Addresses rust-lang#525.
danakj added a commit to danakj/compiler-builtins that referenced this issue May 19, 2023
When enabled, the weak-intrinsics feature will cause all intrinsics
functions to be marked with weak linkage (i.e. `#[linkage = "weak"])
so that they can be replaced at link time by a stronger symbol.

This can be set to use C++ intrinsics from the compiler-rt library,
as it will avoid Rust's implementation replacing the compiler-rt
implementation as long as the compiler-rt symbols are linked as
strong symbols. Typically this requires the compiler-rt library to
be explicitly specified in the link command.

Addresses rust-lang#525.
danakj added a commit to danakj/compiler-builtins that referenced this issue May 19, 2023
When enabled, the weak-intrinsics feature will cause all intrinsics
functions to be marked with weak linkage (i.e. `#[linkage = "weak"])
so that they can be replaced at link time by a stronger symbol.

This can be set to use C++ intrinsics from the compiler-rt library,
as it will avoid Rust's implementation replacing the compiler-rt
implementation as long as the compiler-rt symbols are linked as
strong symbols. Typically this requires the compiler-rt library to
be explicitly specified in the link command.

Addresses rust-lang#525.

Without weak-intrinsics, from nm:
```
00000000 W __aeabi_memclr8  // Is explicitly weak
00000000 T __udivsi3  // Is not.
```

With weak-intrinsics, from nm:
```
00000000 W __aeabi_memclr8  // Is explicitly weak
00000000 W __udivsi3  // Is weak due to weak-intrinsics
```
@danakj
Copy link
Contributor Author

danakj commented May 19, 2023

#526 will provide a feature to mark everything weak, that is off by default. I did it in such a way so as to avoid having to make all explicit weak requests conditional on the feature being disabled, without them colliding with the weak linkage specified in the macro.

@danakj
Copy link
Contributor Author

danakj commented May 22, 2023

Thanks for the support on this issue

@danakj danakj closed this as completed May 22, 2023
aarongable pushed a commit to chromium/chromium that referenced this issue May 30, 2023
This makes the intrinsic symbols contained within considered as strong
symbols, so that when the Rust stdlib intrinsics are marked as weak,
the C++ ones will take precedence. Otherwise, even if they are marked
weak, the Rust stdlib intrinsics are selected by the linker.

It may be the Rust intrinsics are preferable, but we want to stay on
the C++ intrinsics (for C++ and Rust code in mixed binaries) unless we
can demonstrate a good reason to switch.

Upstream bug for marking Rust intrinsic symbols weak:
rust-lang/compiler-builtins#525

To test and verify this works:
1. Revert the changes to shift.rs in rust-lang/compiler-builtins@1634193 to third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-*/src/int/shift.rs
2. Apply https://chromium-review.googlesource.com/c/chromium/src/+/45461823
3. Follow the instructions in its description to build and run bad_intrinsics
4. The bad_intrinsics binary panics without this CL, but not with this CL, meaning the C++ intrinsics are used.

Bug: 1445978
Change-Id: Ib251660346d03902f531285999aeeabc28882049
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4546164
Commit-Queue: Arthur Eubanks <[email protected]>
Reviewed-by: Arthur Eubanks <[email protected]>
Auto-Submit: danakj <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1150647}
aarongable pushed a commit to chromium/chromium that referenced this issue May 30, 2023
This reverts commit 31b9cb8.

Reason for revert: Duplicate intrinsics symbols with Rust stdlib until https://chromium-review.googlesource.com/c/chromium/src/+/4567107

Original change's description:
> Explicitly include compiler-rt builtins library in linking
>
> This makes the intrinsic symbols contained within considered as strong
> symbols, so that when the Rust stdlib intrinsics are marked as weak,
> the C++ ones will take precedence. Otherwise, even if they are marked
> weak, the Rust stdlib intrinsics are selected by the linker.
>
> It may be the Rust intrinsics are preferable, but we want to stay on
> the C++ intrinsics (for C++ and Rust code in mixed binaries) unless we
> can demonstrate a good reason to switch.
>
> Upstream bug for marking Rust intrinsic symbols weak:
> rust-lang/compiler-builtins#525
>
> To test and verify this works:
> 1. Revert the changes to shift.rs in rust-lang/compiler-builtins@1634193 to third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-*/src/int/shift.rs
> 2. Apply https://chromium-review.googlesource.com/c/chromium/src/+/45461823
> 3. Follow the instructions in its description to build and run bad_intrinsics
> 4. The bad_intrinsics binary panics without this CL, but not with this CL, meaning the C++ intrinsics are used.
>
> Bug: 1445978
> Change-Id: Ib251660346d03902f531285999aeeabc28882049
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4546164
> Commit-Queue: Arthur Eubanks <[email protected]>
> Reviewed-by: Arthur Eubanks <[email protected]>
> Auto-Submit: danakj <[email protected]>
> Cr-Commit-Position: refs/heads/main@{#1150647}

Bug: 1445978
Change-Id: I435a63212b230848e9e9603165140257a4a9b071
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4574984
Reviewed-by: Sébastien Lalancette <[email protected]>
Owners-Override: Sébastien Lalancette <[email protected]>
Commit-Queue: danakj <[email protected]>
Bot-Commit: Rubber Stamper <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1150658}
aarongable pushed a commit to chromium/chromium that referenced this issue May 31, 2023
This is a reland of commit 31b9cb8

Original change's description:
> Explicitly include compiler-rt builtins library in linking
>
> This makes the intrinsic symbols contained within considered as strong
> symbols, so that when the Rust stdlib intrinsics are marked as weak,
> the C++ ones will take precedence. Otherwise, even if they are marked
> weak, the Rust stdlib intrinsics are selected by the linker.
>
> It may be the Rust intrinsics are preferable, but we want to stay on
> the C++ intrinsics (for C++ and Rust code in mixed binaries) unless we
> can demonstrate a good reason to switch.
>
> Upstream bug for marking Rust intrinsic symbols weak:
> rust-lang/compiler-builtins#525
>
> To test and verify this works:
> 1. Revert the changes to shift.rs in rust-lang/compiler-builtins@1634193 to third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-*/src/int/shift.rs
> 2. Apply https://chromium-review.googlesource.com/c/chromium/src/+/45461823
> 3. Follow the instructions in its description to build and run bad_intrinsics
> 4. The bad_intrinsics binary panics without this CL, but not with this CL, meaning the C++ intrinsics are used.
>
> Bug: 1445978
> Change-Id: Ib251660346d03902f531285999aeeabc28882049
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4546164
> Commit-Queue: Arthur Eubanks <[email protected]>
> Reviewed-by: Arthur Eubanks <[email protected]>
> Auto-Submit: danakj <[email protected]>
> Cr-Commit-Position: refs/heads/main@{#1150647}

Bug: 1445978
Change-Id: I04302cd1f67b911c81b3413c09d391379380710b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4574784
Commit-Queue: danakj <[email protected]>
Reviewed-by: Arthur Eubanks <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1151259}
UI-RayanWang pushed a commit to ubiquiti/ubnt_libjingle_component_src_build that referenced this issue Aug 16, 2023
This makes the intrinsic symbols contained within considered as strong
symbols, so that when the Rust stdlib intrinsics are marked as weak,
the C++ ones will take precedence. Otherwise, even if they are marked
weak, the Rust stdlib intrinsics are selected by the linker.

It may be the Rust intrinsics are preferable, but we want to stay on
the C++ intrinsics (for C++ and Rust code in mixed binaries) unless we
can demonstrate a good reason to switch.

Upstream bug for marking Rust intrinsic symbols weak:
rust-lang/compiler-builtins#525

To test and verify this works:
1. Revert the changes to shift.rs in rust-lang/compiler-builtins@1634193 to third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-*/src/int/shift.rs
2. Apply https://chromium-review.googlesource.com/c/chromium/src/+/45461823
3. Follow the instructions in its description to build and run bad_intrinsics
4. The bad_intrinsics binary panics without this CL, but not with this CL, meaning the C++ intrinsics are used.

Bug: 1445978
Change-Id: Ib251660346d03902f531285999aeeabc28882049
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4546164
Commit-Queue: Arthur Eubanks <[email protected]>
Reviewed-by: Arthur Eubanks <[email protected]>
Auto-Submit: danakj <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1150647}
NOKEYCHECK=True
GitOrigin-RevId: 31b9cb886d359780569bc5e1281bc7515d16e9bb
UI-RayanWang pushed a commit to ubiquiti/ubnt_libjingle_component_src_build that referenced this issue Aug 16, 2023
This reverts commit 31b9cb886d359780569bc5e1281bc7515d16e9bb.

Reason for revert: Duplicate intrinsics symbols with Rust stdlib until https://chromium-review.googlesource.com/c/chromium/src/+/4567107

Original change's description:
> Explicitly include compiler-rt builtins library in linking
>
> This makes the intrinsic symbols contained within considered as strong
> symbols, so that when the Rust stdlib intrinsics are marked as weak,
> the C++ ones will take precedence. Otherwise, even if they are marked
> weak, the Rust stdlib intrinsics are selected by the linker.
>
> It may be the Rust intrinsics are preferable, but we want to stay on
> the C++ intrinsics (for C++ and Rust code in mixed binaries) unless we
> can demonstrate a good reason to switch.
>
> Upstream bug for marking Rust intrinsic symbols weak:
> rust-lang/compiler-builtins#525
>
> To test and verify this works:
> 1. Revert the changes to shift.rs in rust-lang/compiler-builtins@1634193 to third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-*/src/int/shift.rs
> 2. Apply https://chromium-review.googlesource.com/c/chromium/src/+/45461823
> 3. Follow the instructions in its description to build and run bad_intrinsics
> 4. The bad_intrinsics binary panics without this CL, but not with this CL, meaning the C++ intrinsics are used.
>
> Bug: 1445978
> Change-Id: Ib251660346d03902f531285999aeeabc28882049
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4546164
> Commit-Queue: Arthur Eubanks <[email protected]>
> Reviewed-by: Arthur Eubanks <[email protected]>
> Auto-Submit: danakj <[email protected]>
> Cr-Commit-Position: refs/heads/main@{#1150647}

Bug: 1445978
Change-Id: I435a63212b230848e9e9603165140257a4a9b071
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4574984
Reviewed-by: Sébastien Lalancette <[email protected]>
Owners-Override: Sébastien Lalancette <[email protected]>
Commit-Queue: danakj <[email protected]>
Bot-Commit: Rubber Stamper <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1150658}
NOKEYCHECK=True
GitOrigin-RevId: ef9da79aa41c325251772332454e594966dd0371
UI-RayanWang pushed a commit to ubiquiti/ubnt_libjingle_component_src_build that referenced this issue Aug 16, 2023
This is a reland of commit 31b9cb886d359780569bc5e1281bc7515d16e9bb

Original change's description:
> Explicitly include compiler-rt builtins library in linking
>
> This makes the intrinsic symbols contained within considered as strong
> symbols, so that when the Rust stdlib intrinsics are marked as weak,
> the C++ ones will take precedence. Otherwise, even if they are marked
> weak, the Rust stdlib intrinsics are selected by the linker.
>
> It may be the Rust intrinsics are preferable, but we want to stay on
> the C++ intrinsics (for C++ and Rust code in mixed binaries) unless we
> can demonstrate a good reason to switch.
>
> Upstream bug for marking Rust intrinsic symbols weak:
> rust-lang/compiler-builtins#525
>
> To test and verify this works:
> 1. Revert the changes to shift.rs in rust-lang/compiler-builtins@1634193 to third_party/rust-toolchain/lib/rustlib/src/rust/vendor/compiler_builtins-*/src/int/shift.rs
> 2. Apply https://chromium-review.googlesource.com/c/chromium/src/+/45461823
> 3. Follow the instructions in its description to build and run bad_intrinsics
> 4. The bad_intrinsics binary panics without this CL, but not with this CL, meaning the C++ intrinsics are used.
>
> Bug: 1445978
> Change-Id: Ib251660346d03902f531285999aeeabc28882049
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4546164
> Commit-Queue: Arthur Eubanks <[email protected]>
> Reviewed-by: Arthur Eubanks <[email protected]>
> Auto-Submit: danakj <[email protected]>
> Cr-Commit-Position: refs/heads/main@{#1150647}

Bug: 1445978
Change-Id: I04302cd1f67b911c81b3413c09d391379380710b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4574784
Commit-Queue: danakj <[email protected]>
Reviewed-by: Arthur Eubanks <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1151259}
NOKEYCHECK=True
GitOrigin-RevId: 7f005a3864b1d534838b2f1382281148bffbb5a1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants