rust-lang/compiler-builtins

compiler-builtins

Porting compiler-rt intrinsics to Rust

``

Porting compiler-rt intrinsics to Rust

See rust-lang/rust#35437.

When and how to use this crate?

If you are working with a target that doesn't have binary releases of std available via rustup (this probably means you are building the core crate yourself) and need compiler-rt intrinsics (i.e. you are probably getting linker errors when building an executable: undefined reference to __aeabi_memcpy), you can use this crate to get those intrinsics and solve the linker errors. To do that, add this crate somewhere in the dependency graph of the crate you are building:

# Cargo.toml
[dependencies]
compiler_builtins = { git = "https://github.com/rust-lang/" }
extern crate compiler_builtins;

// ...

If you still get an "undefined reference to $INTRINSIC" error after that change, that means that we haven't ported $INTRINSIC to Rust yet! Please open an issue with the name of the intrinsic and the LLVM triple (e.g. thumbv7m-none-eabi) of the target you are using. That way we can prioritize porting that particular intrinsic.

If you've got a C compiler available for your target then while we implement this intrinsic you can temporarily enable a fallback to the actual compiler-rt implementation as well for unimplemented intrinsics:

[dependencies.compiler_builtins]
git = "https://github.com/rust-lang/"
features = ["c"]

Contributing

  1. Pick one or more intrinsics from the pending list.
  2. Fork this repository.
  3. Port the intrinsic(s) and their corresponding unit tests from their C implementation to Rust.
  4. Implement a test generator to compare the behavior of the ported intrinsic(s) with their implementation on the testing host. Note that randomized compiler-builtin tests should be run using cargo test --features gen-tests.
  5. Send a Pull Request (PR).
  6. Once the PR passes our extensive testing infrastructure, we'll merge it!
  7. Celebrate :tada:

Porting Reminders

  1. Rust and C have slightly different operator precedence. C evaluates comparisons (== !=) before bitwise operations (& | ^), while Rust evaluates the other way.
  2. C assumes wrapping operations everywhere. Rust panics on overflow when in debug mode. Consider using the Wrapping type or the explicit wrapping_* functions where applicable.
  3. Note C implicit casts, especially integer promotion. Rust is much more explicit about casting, so be sure that any cast which affects the output is ported to the Rust implementation.
  4. Rust has many functions for integer or floating point manipulation in the standard library. Consider using one of these functions rather than porting a new one.

Progress

  • adddf3.c
  • addsf3.c
  • arm/adddf3vfp.S
  • arm/addsf3vfp.S
  • arm/aeabi_dcmp.S
  • arm/aeabi_fcmp.S
  • arm/aeabi_idivmod.S
  • arm/aeabi_ldivmod.S
  • arm/aeabi_memcpy.S
  • arm/aeabi_memmove.S
  • arm/aeabi_memset.S
  • arm/aeabi_uidivmod.S
  • arm/aeabi_uldivmod.S
  • arm/divdf3vfp.S
  • arm/divmodsi4.S (generic version is done)
  • arm/divsf3vfp.S
  • arm/divsi3.S (generic version is done)
  • arm/eqdf2vfp.S
  • arm/eqsf2vfp.S
  • arm/extendsfdf2vfp.S
  • arm/fixdfsivfp.S
  • arm/fixsfsivfp.S
  • arm/fixunsdfsivfp.S
  • arm/fixunssfsivfp.S
  • arm/floatsidfvfp.S
  • arm/floatsisfvfp.S
  • arm/floatunssidfvfp.S
  • arm/floatunssisfvfp.S
  • arm/gedf2vfp.S
  • arm/gesf2vfp.S
  • arm/gtdf2vfp.S
  • arm/gtsf2vfp.S
  • arm/ledf2vfp.S
  • arm/lesf2vfp.S
  • arm/ltdf2vfp.S
  • arm/ltsf2vfp.S
  • arm/modsi3.S (generic version is done)
  • arm/muldf3vfp.S
  • arm/mulsf3vfp.S
  • arm/nedf2vfp.S
  • arm/negdf2vfp.S
  • arm/negsf2vfp.S
  • arm/nesf2vfp.S
  • arm/softfloat-alias.list
  • arm/subdf3vfp.S
  • arm/subsf3vfp.S
  • arm/truncdfsf2vfp.S
  • arm/udivmodsi4.S (generic version is done)
  • arm/udivsi3.S (generic version is done)
  • arm/umodsi3.S (generic version is done)
  • arm/unorddf2vfp.S
  • arm/unordsf2vfp.S
  • ashldi3.c
  • ashrdi3.c
  • comparedf2.c
  • comparesf2.c
  • divdf3.c
  • divdi3.c
  • divmoddi4.c
  • divmodsi4.c
  • divsf3.c
  • divsi3.c
  • extendhfsf2.c
  • extendsfdf2.c
  • fixdfdi.c
  • fixdfsi.c
  • fixsfdi.c
  • fixsfsi.c
  • fixunsdfdi.c
  • fixunsdfsi.c
  • fixunssfdi.c
  • fixunssfsi.c
  • floatdidf.c
  • floatdisf.c
  • floatsidf.c
  • floatsisf.c
  • floatundidf.c
  • floatundisf.c
  • floatunsidf.c
  • floatunsisf.c
  • i386/ashldi3.S
  • i386/ashrdi3.S
  • i386/chkstk.S
  • i386/chkstk2.S
  • i386/divdi3.S
  • i386/lshrdi3.S
  • i386/moddi3.S
  • i386/muldi3.S
  • i386/udivdi3.S
  • i386/umoddi3.S
  • lshrdi3.c
  • moddi3.c
  • modsi3.c
  • muldf3.c
  • muldi3.c
  • mulodi4.c
  • mulosi4.c
  • mulsf3.c
  • powidf2.c
  • powisf2.c
  • subdf3.c
  • subsf3.c
  • truncdfhf2.c
  • truncdfsf2.c
  • truncsfhf2.c
  • udivdi3.c
  • udivmoddi4.c
  • udivmodsi4.c
  • udivsi3.c
  • umoddi3.c
  • umodsi3.c
  • x86_64/chkstk.S
  • x86_64/chkstk2.S

These builtins are needed to support 128-bit integers, which are in the process of being added to Rust.

  • ashlti3.c
  • ashrti3.c
  • divti3.c
  • fixdfti.c
  • fixsfti.c
  • fixunsdfti.c
  • fixunssfti.c
  • floattidf.c
  • floattisf.c
  • floatuntidf.c
  • floatuntisf.c
  • lshrti3.c
  • modti3.c
  • muloti4.c
  • multi3.c
  • udivmodti4.c
  • udivti3.c
  • umodti3.c

Unimplemented functions

These builtins involve floating-point types ("f128", "f80" and complex numbers) that are not supported by Rust.

  • addtf3.c
  • comparetf2.c
  • divdc3.c
  • divsc3.c
  • divtc3.c
  • divtf3.c
  • divxc3.c
  • extenddftf2.c
  • extendsftf2.c
  • fixtfdi.c
  • fixtfsi.c
  • fixtfti.c
  • fixunstfdi.c
  • fixunstfsi.c
  • fixunstfti.c
  • fixunsxfdi.c
  • fixunsxfsi.c
  • fixunsxfti.c
  • fixxfdi.c
  • fixxfti.c
  • floatditf.c
  • floatdixf.c
  • floatsitf.c
  • floattixf.c
  • floatunditf.c
  • floatundixf.c
  • floatunsitf.c
  • floatuntixf.c
  • i386/floatdixf.S
  • i386/floatundixf.S
  • muldc3.c
  • mulsc3.c
  • multc3.c
  • multf3.c
  • mulxc3.c
  • powitf2.c
  • powixf2.c
  • ppc/divtc3.c
  • ppc/fixtfdi.c
  • ppc/fixunstfdi.c
  • ppc/floatditf.c
  • ppc/floatunditf.c
  • ppc/gcc_qadd.c
  • ppc/gcc_qdiv.c
  • ppc/gcc_qmul.c
  • ppc/gcc_qsub.c
  • ppc/multc3.c
  • subtf3.c
  • trunctfdf2.c
  • trunctfsf2.c
  • x86_64/floatdixf.c
  • x86_64/floatundixf.S

These builtins are never called by LLVM.

  • absvdi2.c
  • absvsi2.c
  • absvti2.c
  • addvdi3.c
  • addvsi3.c
  • addvti3.c
  • arm/aeabi_cdcmp.S
  • arm/aeabi_cdcmpeq_check_nan.c
  • arm/aeabi_cfcmp.S
  • arm/aeabi_cfcmpeq_check_nan.c
  • arm/aeabi_div0.c
  • arm/aeabi_drsub.c
  • arm/aeabi_frsub.c
  • arm/aeabi_memcmp.S
  • arm/bswapdi2.S
  • arm/bswapsi2.S
  • arm/clzdi2.S
  • arm/clzsi2.S
  • arm/comparesf2.S
  • arm/restore_vfp_d8_d15_regs.S
  • arm/save_vfp_d8_d15_regs.S
  • arm/switch16.S
  • arm/switch32.S
  • arm/switch8.S
  • arm/switchu8.S
  • clzdi2.c
  • clzsi2.c
  • clzti2.c
  • cmpdi2.c
  • cmpti2.c
  • ctzdi2.c
  • ctzsi2.c
  • ctzti2.c
  • ffsdi2.c - this is called by gcc though!
  • ffsti2.c
  • mulvdi3.c
  • mulvsi3.c
  • mulvti3.c
  • negdf2.c
  • negdi2.c
  • negsf2.c
  • negti2.c
  • negvdi2.c
  • negvsi2.c
  • negvti2.c
  • paritydi2.c
  • paritysi2.c
  • parityti2.c
  • popcountdi2.c
  • popcountsi2.c
  • popcountti2.c
  • ppc/restFP.S
  • ppc/saveFP.S
  • subvdi3.c
  • subvsi3.c
  • subvti3.c
  • ucmpdi2.c
  • ucmpti2.c
  • udivmodti4.c

Rust only exposes atomic types on platforms that support them, and therefore does not need to fall back to software implementations.

  • arm/sync_fetch_and_add_4.S
  • arm/sync_fetch_and_add_8.S
  • arm/sync_fetch_and_and_4.S
  • arm/sync_fetch_and_and_8.S
  • arm/sync_fetch_and_max_4.S
  • arm/sync_fetch_and_max_8.S
  • arm/sync_fetch_and_min_4.S
  • arm/sync_fetch_and_min_8.S
  • arm/sync_fetch_and_nand_4.S
  • arm/sync_fetch_and_nand_8.S
  • arm/sync_fetch_and_or_4.S
  • arm/sync_fetch_and_or_8.S
  • arm/sync_fetch_and_sub_4.S
  • arm/sync_fetch_and_sub_8.S
  • arm/sync_fetch_and_umax_4.S
  • arm/sync_fetch_and_umax_8.S
  • arm/sync_fetch_and_umin_4.S
  • arm/sync_fetch_and_umin_8.S
  • arm/sync_fetch_and_xor_4.S
  • arm/sync_fetch_and_xor_8.S
  • arm/sync_synchronize.S
  • atomic.c
  • atomic_flag_clear.c
  • atomic_flag_clear_explicit.c
  • atomic_flag_test_and_set.c
  • atomic_flag_test_and_set_explicit.c
  • atomic_signal_fence.c
  • atomic_thread_fence.c

Miscellaneous functionality that is not used by Rust.

  • apple_versioning.c
  • clear_cache.c
  • emutls.c
  • enable_execute_stack.c
  • eprintf.c
  • gcc_personality_v0.c
  • trampoline_setup.c

Floating-point implementations of builtins that are only called from soft-float code. It would be better to simply use the generic soft-float versions in this case.

  • i386/floatdidf.S
  • i386/floatdisf.S
  • i386/floatundidf.S
  • i386/floatundisf.S
  • x86_64/floatundidf.S
  • x86_64/floatundisf.S
  • x86_64/floatdidf.c
  • x86_64/floatdisf.c

License

The crate is dual licensed under both the University of Illinois "BSD-Like" license and the MIT license. As a user of this code you may choose to use it under either license. As a contributor, you agree to allow your code to be used under both.

Full text of the relevant licenses is in LICENSE.TXT.

Issues

Collection of the latest Issues

pgowda-cve

pgowda-cve

Comment Icon1

Hi,

We are trying to build mozjs-91 in debug mode on Yocto framework.

However, the build fails with the following error on compiler_builtins.

/libexec/i686-linux/gcc/i686-linux/12.1.0/ld: mozjs-91/91.8.0-r0/build/i686-linux/release/libjsrust.a(compiler_builtins-3fc4b4898efc1e1d.compiler_builtins.b3f4713f-cgu.3.rcgu.o): in function compiler_builtins::int::specialized_div_rem::u64_div_rem': compiler_builtins.b3f4713f-cgu.3:(.text._ZN17compiler_builtins3int19specialized_div_rem11u64_div_rem17ha9ef929772c35813E+0x178): undefined reference to core::panicking::panic'

The issue is not seen when built without debug mode (DEBUG_BUILD = "1") Tried to debug the issue and observed that building libstd-rs in release mode fixed the issue.

The following issues were referred that are related to the same error https://github.com/rust-lang/compiler-builtins/issues/347 https://github.com/rust-lang/compiler-builtins/issues/79

Tweaked the files to modify for overflow-checks = false opt-level = 1 However, it did not fix the issue.

StackDoubleFlow

StackDoubleFlow

Comment Icon8

Attempting to dlopen my shared library on an android device results in it being unable to find the __clear_cache symbol. This is needed for my project.

It is needed for me to build core for bbqsrc/cargo-ndk#22.

emgre

emgre

Comment Icon10

Similar to #412, on armv7-unknown-linux-gnueabihf we get symbols __sync_fetch_and_add_4 and __sync_fetch_and_add_8 (and probably others) clashing when a C/C++ tries to link with our library. We've tried on arm-unknown-linux-gnueabihf, aarch64-unknown-linux-gnu and x86_64-unknown-linux-gnu and it doesn't seem to generate these symbols.

On Zulip, Alex Crichton suggested to flag the symbol as weak. This issue is off my level of competence, so I'll probably leave it to someone who knows better than me.

Some links that I've found while investigating this (for cross-reference):

jiayihu

jiayihu

Comment Icon5

I'm having a similar issue to #334 but it's different I think. I have build-std = ["core", "alloc"] in config.toml and I'm trying to compile a local patch of compiler-builtins, for the reasons stated in #387 . In Cargo.toml I have the following configuration:

But the compiler is giving the error:

I believe one version is the one included by default by cargo because of core in https://github.com/rust-lang/cargo/blob/master/src/cargo/core/compiler/standard_lib.rs#L28, whereas the second one is my patch. How do I opt-out the cargo-inserted one?

lygstate

lygstate

Comment Icon1

C:\work\study\languages\rust\relibc>cl /MD kernel32.lib bufferoverflowu.lib target\debug\relibc.lib examples\test.c -X -Iinclude -Itarget\include -link -NODEFAULTLIB 用于 x64 的 Microsoft (R) C/C++ 优化编译器 19.27.29111 版 版权所有(C) Microsoft Corporation。保留所有权利。

test.c Microsoft (R) Incremental Linker Version 14.27.29111.0 Copyright (C) Microsoft Corporation. All rights reserved.

/out:test.exe -NODEFAULTLIB kernel32.lib bufferoverflowu.lib target\debug\relibc.lib test.obj relibc.lib(compiler_builtins-88a1b2fb6f0103b9.compiler_builtins.7aumvbvw-cgu.10.rcgu.o) : error LNK2005: __udivti3 已经在 relibc.lib(compiler_builtins-39d38ac12950f0ad.compiler_builtins.7s4tkjsi-cgu.101.rcgu.o) 中定义 relibc.lib(compiler_builtins-88a1b2fb6f0103b9.compiler_builtins.7aumvbvw-cgu.10.rcgu.o) : error LNK2005: __umodti3 已经在 relibc.lib(compiler_builtins-39d38ac12950f0ad.compiler_builtins.7s4tkjsi-cgu.91.rcgu.o) 中定义 relibc.lib(compiler_builtins-88a1b2fb6f0103b9.compiler_builtins.7aumvbvw-cgu.12.rcgu.o) : error LNK2005: __muloti4 已经在 relibc.lib(compiler_builtins-39d38ac12950f0ad.compiler_builtins.7s4tkjsi-cgu.55.rcgu.o) 中定义 relibc.lib(relibc-9d9c08d1b0a05e35.4hpfjzg8pdsfqzra.rcgu.o) : error LNK2019: 无法解析的外部符号 pthread_init,函数 _ZN6relibc5start10init_array17ha673ba50bf14f52fE 中引用了该符号 relibc.lib(relibc-9d9c08d1b0a05e35.4hpfjzg8pdsfqzra.rcgu.o) : error LNK2019: 无法解析的外部符号 __preinit_array_start,函数 relibc_start 中引用了该符号 relibc.lib(relibc-9d9c08d1b0a05e35.4hpfjzg8pdsfqzra.rcgu.o) : error LNK2019: 无法解析的外部符号 __preinit_array_end,函数 relibc_start 中引用了该符号 relibc.lib(relibc-9d9c08d1b0a05e35.4hpfjzg8pdsfqzra.rcgu.o) : error LNK2019: 无法解析的外部符号 _init,函数 relibc_start 中引用了该符号 relibc.lib(relibc-9d9c08d1b0a05e35.4hpfjzg8pdsfqzra.rcgu.o) : error LNK2019: 无法解析的外部符号 __init_array_start,函数 relibc_start 中引用了该符号 relibc.lib(relibc-9d9c08d1b0a05e35.4hpfjzg8pdsfqzra.rcgu.o) : error LNK2019: 无法解析的外部符号 __init_array_end,函数 relibc_start 中引用了该符号 relibc.lib(relibc-9d9c08d1b0a05e35.4f7bjoz4nyl9872d.rcgu.o) : error LNK2001: 无法解析的外部符号 _tls_index relibc.lib(relibc-9d9c08d1b0a05e35.2wmih4feibvw9owg.rcgu.o) : error LNK2001: 无法解析的外部符号 _tls_index relibc.lib(relibc-9d9c08d1b0a05e35.1x5l4jupgiuvbkpn.rcgu.o) : error LNK2001: 无法解析的外部符号 _tls_index relibc.lib(relibc-9d9c08d1b0a05e35.4nuobiwtkb3zdwi.rcgu.o) : error LNK2001: 无法解析的外部符号 _tls_index relibc.lib(relibc-9d9c08d1b0a05e35.52c5u33q78mlilk9.rcgu.o) : error LNK2001: 无法解析的外部符号 _tls_index relibc.lib(relibc-9d9c08d1b0a05e35.1x8g2g4krrmlz5q3.rcgu.o) : error LNK2001: 无法解析的外部符号 _tls_index relibc.lib(relibc-9d9c08d1b0a05e35.4syvupwgp4u7bbps.rcgu.o) : error LNK2001: 无法解析的外部符号 _tls_index relibc.lib(relibc-9d9c08d1b0a05e35.vixotrs3z2efb03.rcgu.o) : error LNK2001: 无法解析的外部符号 _tls_index relibc.lib(relibc-9d9c08d1b0a05e35.32hfqahjeuk49qyz.rcgu.o) : error LNK2001: 无法解析的外部符号 _tls_index relibc.lib(relibc-9d9c08d1b0a05e35.206xjy6h5e8hs1h.rcgu.o) : error LNK2001: 无法解析的外部符号 _tls_index relibc.lib(relibc-9d9c08d1b0a05e35.zz2dtjlpmanf1h.rcgu.o) : error LNK2001: 无法解析的外部符号 _tls_index relibc.lib(relibc-9d9c08d1b0a05e35.3gkoli02u3xvwi6l.rcgu.o) : error LNK2001: 无法解析的外部符号 _tls_index relibc.lib(relibc-9d9c08d1b0a05e35.2h61x08khw1ukwbx.rcgu.o) : error LNK2001: 无法解析的外部符号 _tls_index relibc.lib(relibc-9d9c08d1b0a05e35.3dwdb5p8xjdh2ne1.rcgu.o) : error LNK2001: 无法解析的外部符号 _tls_index relibc.lib(relibc-9d9c08d1b0a05e35.434wb6pmguwct0qa.rcgu.o) : error LNK2001: 无法解析的外部符号 _tls_index relibc.lib(relibc-9d9c08d1b0a05e35.2b4gng32pwix0ldd.rcgu.o) : error LNK2001: 无法解析的外部符号 _tls_index relibc.lib(relibc-9d9c08d1b0a05e35.2wrawszkxk9rt8rm.rcgu.o) : error LNK2001: 无法解析的外部符号 _tls_index relibc.lib(relibc-9d9c08d1b0a05e35.434wb6pmguwct0qa.rcgu.o) : error LNK2019: 无法解析的外部符号 __fini_array_end,函数 exit 中引用了该符号 relibc.lib(relibc-9d9c08d1b0a05e35.434wb6pmguwct0qa.rcgu.o) : error LNK2019: 无法解析的外部符号 __fini_array_start,函数 exit 中引用了该符号 relibc.lib(relibc-9d9c08d1b0a05e35.434wb6pmguwct0qa.rcgu.o) : error LNK2019: 无法解析的外部符号 _fini,函数 exit 中引用了该符号 relibc.lib(relibc-9d9c08d1b0a05e35.434wb6pmguwct0qa.rcgu.o) : error LNK2019: 无法解析的外部符号 pthread_terminate,函数 exit 中引用了该符号 relibc.lib(relibc-9d9c08d1b0a05e35.4ifofswltr4zyltf.rcgu.o) : error LNK2001: 无法解析的外部符号 __chkstk relibc.lib(rand-6a35eaeaab7f31be.rand.a1ul4dd6-cgu.4.rcgu.o) : error LNK2001: 无法解析的外部符号 __chkstk relibc.lib(relibc-9d9c08d1b0a05e35.1x5l4jupgiuvbkpn.rcgu.o) : error LNK2001: 无法解析的外部符号 __chkstk relibc.lib(rand-6a35eaeaab7f31be.rand.a1ul4dd6-cgu.5.rcgu.o) : error LNK2001: 无法解析的外部符号 __chkstk relibc.lib(rand-6a35eaeaab7f31be.rand.a1ul4dd6-cgu.7.rcgu.o) : error LNK2001: 无法解析的外部符号 __chkstk relibc.lib(relibc-9d9c08d1b0a05e35.vpu42b44v1qtr6s.rcgu.o) : error LNK2001: 无法解析的外部符号 __chkstk relibc.lib(posix_regex-a35eeca5f6847290.9sburftcvegype3.rcgu.o) : error LNK2001: 无法解析的外部符号 __chkstk relibc.lib(goblin-fca5be98fc157ea8.goblin.2sopokfe-cgu.8.rcgu.o) : error LNK2001: 无法解析的外部符号 __chkstk relibc.lib(rand-6a35eaeaab7f31be.rand.a1ul4dd6-cgu.0.rcgu.o) : error LNK2001: 无法解析的外部符号 __chkstk relibc.lib(relibc-9d9c08d1b0a05e35.zz2dtjlpmanf1h.rcgu.o) : error LNK2001: 无法解析的外部符号 __chkstk relibc.lib(relibc-9d9c08d1b0a05e35.3gkoli02u3xvwi6l.rcgu.o) : error LNK2001: 无法解析的外部符号 __chkstk relibc.lib(rand-6a35eaeaab7f31be.rand.a1ul4dd6-cgu.13.rcgu.o) : error LNK2001: 无法解析的外部符号 __chkstk relibc.lib(relibc-9d9c08d1b0a05e35.1kzz6vo5r9kpp7wu.rcgu.o) : error LNK2001: 无法解析的外部符号 __chkstk relibc.lib(dlmalloc.o) : error LNK2001: 无法解析的外部符号 __GSHandlerCheck relibc.lib(relibc-9d9c08d1b0a05e35.phoxdfwpp2w85bj.rcgu.o) : error LNK2019: 无法解析的外部符号 __restore_rt,函数 ZN6relibc6header6signal9sigaction28$u7b$$u7b$closure$u7d$$u7d$17hc01bd509a69f5b63E 中引用了该符号 relibc.lib(relibc-9d9c08d1b0a05e35.52c5u33q78mlilk9.rcgu.o) : error LNK2001: 无法解析的外部符号 __restore_rt test.exe : fatal error LNK1120: 14 个无法解析的外部命令

m-ou-se

m-ou-se

Comment Icon3

A crate compiled on x86_64 with -Ctarget-feature=+soft-float will use floating point conversions from compiler-builtins. However, some of the floating point conversions in compiler-builtins are implemented using floating point instructions. This breaks when enabling the +soft-float target-feature. Should +soft-float be supported? Or should this have given an error? Right now, it silently gives wrong results:

https://godbolt.org/z/9zvecP

apullin

apullin

Comment Icon9

I am having some issues using a rust staticlib that is being called from C via FFI, being built for an embedded target (Cortex M). This issue is sort-of a result of needing this library, not necessarily an error in the code.

To get the linking step to succeed, I have to link the rust staticlib in last. If not, I will get link errors for multiple definitions of memset, where one implementation is providing the unmangled symbol from this compiler-builtins crate.

Linking the rustlib last does resolve that. However, it causes all uses of memset in the C code to be linked to the compiler-builtins implementations.

Even beyond that, using a softfp MCU, even FP multiple like float a=b*c will end up linking the __aebi_fmul to the Rust implementation!

Example of how invoke linking: arm-none-eabi-gcc -mcpu=cortex-m0plus -mthumb -specs=nano.specs -specs=nosys.specs -TSTM32L072CZEx_FLASH.ld -lnosys -Wl,-Map=target/double.map,--cref -Wl,--gc-sections target/startup_stm32l072xx.o target/stm32l0xx_it.o target/main.o target/thumbv6m-none-eabi/debug/libdouble_input.a -o target/double

(where the name "double" is because I am using the libdouble_input from FFI examples and adding a few other tests: https://github.com/alexcrichton/rust-ffi-examples/tree/master/c-to-rust )

Is this a known limitation? Is there a workaround to avoid that level of hybridization of the C codes into the rust code, given the overlapping implementations?

As far as I understand the notes in the README, that does not cover this case for the behavior I am trying to get.

I have tried partially linking all the C code first with -lc, and it does pick up the libc implementations of memcpy, float multiply, etc, but then the final linking step fails becasue there are still two memset objects in the output files.

CryZe

CryZe

Comment Icon10

I've seen the assembly of the memcpy here for both powerpc and wasm (where the one here seems to be used unless you use the WASI target) and in both cases really simplistic byte wise loops are emitted. I haven't really done any benchmarks but these likely perform worse than more optimized loops that work on 32-bit or so at a time.

brson

brson

Comment Icon18

The source code in this crate is derivative of LLVM's compiler-rt, the license of which is declared correctly in LICENSE.TXT, but not in Cargo.toml, and is the NCSA license (similar to BSD).

Cargo.toml needs to be updated to declare the NCSA license, and then the Rust tidy file in deps.rs to declare it as either an exception or an acceptable permissive license.

Note that LLVM is in the process of relicensing to add a runtime exception to its code (which Rust lacks), and this crate will not obviously benefit from that relicensing since it was derived prior to the relicense.

cc https://github.com/rust-lang/rust/issues/63232

jlb6740

jlb6740

Comment Icon0

Hi ... I am not sure I need to use this crate. I am trying to build a rust based static library to link with a RTOS embedded application. Unfortunately I get all sorts of duplicate item errors (primarily compiler_builtins) when linking the rust static library (.a file) when compiling and linking with the image for the embedded device.

I've found that if I emit objects and link in the .o of my rust library before cargo xbuild based command links in compiler_intrinsics then I can almost get my embedded application to build, I just have one undefined reference of __rust_probstack. If I manually add this function by copying code from the compiler_builtin's source to my rust code for the static library I can get my embedded application to compile and at least start execution. I'd like to properly link in select compiler_builtin functions into my static library (.a file) without manually adding the code for __rust_probstack, but I am not having luck doing that. After reading the description, I was wondering if I could fine tune which functions I used from compiler_builtins by adding this crate. However when I add to my rust code:

and add to my cargo.toml:

Obviously I do not know my way around the rust build system very well. I am having trouble understanding which blogs and instructions I am following are already obsolete for what I am looking to do. In particular it seems compiler_builtins are built and linked automatically as part of libcore so I am not sure how bringing in this crate could not cause these type of linking errors. Can someone help my understanding here? Also I am not sure how/when to consider dependencies on the stage0 vs stage1 vs stage2 rust compiler but is that important to understand and apply here? In what direction do I need to look for these compiler intrinsic linking woes.

japaric

japaric

Comment Icon1

From #155

I have seen this target spuriously segfault while running tests on other project so this may be some QEMU bug.

japaric

japaric

Comment Icon4

The problem

Some symbols, like the __aeabi_* ones, are defined as "aliases" of others in the C implementation of compiler-rt. For example: __aeabi_dadd is an alias of __adddf3. This means that both symbols, the original and its alias, refer to the same routine and use of either will result in a call to the same routine.

Rust doesn't have a mechanism for aliasing symbols and right now we are "emulating" aliases like this:

Although this works (calling that "alias" does the right thing), it also incurrs in an extra function call everytime the alias is used:

Attempted solutions

Use #[link_args] to ask the linker to duplicate the symbol. See #39. Sadly, this didn't work because #[link_args] is not propagated through crates and also that feature is slated for removal so we can't rely on it anyway.

Possible non-ideal solutions

export_name

Most (all?) ARM builtins have the form __aeabi_*. compiler-rt implements them as aliases to the non-aeabi symbols. For example: __aeabi_dadd is an alias of __adddf3 and both symbols appear in libcompiler-rt.a. Given that ARM executables never use the non-aeabi symbols, we could simply expose the __adddf3 routine as the __aeabi_dadd symbol without providing the __adddf3 symbol. In Rust code this would look like this:

The result would be:

  • rustc_builtins on x86 exposes the __adddf3 symbol
  • rustc_builtins on ARM exposes the __aeabi_dadd symbol

In contrast, libcompiler-rt.a on ARM exposes both the __adddf3 and the __aeabi_dadd symbols

This approach can only be used if the implementation resides in rustc-builtins. For instance, we can't use this to expose the __aeabi_memcpy* symbols which are all aliases to memcpy.

Just duplicate the routine

This would get rid of the extra function call in the "alias" but would probably result in duplicate code/instructions in the final executable (unless LLVM is smart enough to deduplicate two routines that have the same instructions)


Anyone has any other idea about how to solve this?

Information - Updated Jul 16, 2022

Stars: 259
Forks: 150
Issues: 29

This is an example of a Rust server that functions as a remote schema for...

Rust + Hasura Rust server that functions as a Hasura

This is an example of a Rust server that functions as a remote schema for...

Newport Engine is a modular 2D and 3D game engine built in Rust for Rust

It is designed to be easily extendable and easy to use

Newport Engine is a modular 2D and 3D game engine built in Rust for Rust

Newport Engine is a modular 2D and 3D game engine built in Rust for Rust

It is designed to be easily extendable and easy to use

Newport Engine is a modular 2D and 3D game engine built in Rust for Rust

liboqs-rust: Rust bindings for liboqs

Qyantum Safe liboqs rust bindings

liboqs-rust: Rust bindings for liboqs

msgflo-rust: Rust participant support for MsgFlo

Flowhub visual programming IDE

msgflo-rust: Rust participant support for MsgFlo
Actix

1.0K

How to be a full stack Rust Developer

Read Rust the Rust blog posts at Steadylearner

How to be a full stack Rust Developer

Rust library translation (rust-src/rust-std/stdlib/rustlib translation)

This is the place to translate Having a documentation in your native language is essential if you don't speak English, and still enjoyable even if...

Rust library translation (rust-src/rust-std/stdlib/rustlib translation)

False Positive for rust-lang/rust#83583

The deprecation lint proc_macro_derive_resolution_fallback is intended to catch proc macro generated code that refers to items from parent modules that should not be in scope:

False Positive for rust-lang/rust#83583

A CHIP-8 & SuperChip interpreter written in Rust using rust-sdl2

If you're getting compile errors it may be because

A CHIP-8 & SuperChip interpreter written in Rust using rust-sdl2

Rust-Svelte-on-Rust

Starter template for Rocket backend server

Rust-Svelte-on-Rust

xbuild is a build tool for rust and rust/flutter projects with support for cross compiling...

xbuild is a build tool for rust and rust/flutter projects with support for cross compiling and

xbuild is a build tool for rust and rust/flutter projects with support for cross compiling...
Facebook Instagram Twitter GitHub Dribbble
Privacy