• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# `compiler-builtins`
2
3> Porting `compiler-rt` intrinsics to Rust
4
5See [rust-lang/rust#35437][0].
6
7[0]: https://github.com/rust-lang/rust/issues/35437
8
9## When and how to use this crate?
10
11If you are working with a target that doesn't have binary releases of std
12available via rustup (this probably means you are building the core crate
13yourself) and need compiler-rt intrinsics (i.e. you are probably getting linker
14errors when building an executable: `undefined reference to __aeabi_memcpy`),
15you can use this crate to get those intrinsics and solve the linker errors. To
16do that, add this crate somewhere in the dependency graph of the crate you are
17building:
18
19```toml
20# Cargo.toml
21[dependencies]
22compiler_builtins = { git = "https://github.com/rust-lang/compiler-builtins" }
23```
24
25```rust
26extern crate compiler_builtins;
27
28// ...
29```
30
31If you still get an "undefined reference to $INTRINSIC" error after that change,
32that means that we haven't ported `$INTRINSIC` to Rust yet! Please open [an
33issue] with the name of the intrinsic and the LLVM triple (e.g.
34thumbv7m-none-eabi) of the target you are using. That way we can prioritize
35porting that particular intrinsic.
36
37If you've got a C compiler available for your target then while we implement
38this intrinsic you can temporarily enable a fallback to the actual compiler-rt
39implementation as well for unimplemented intrinsics:
40
41```toml
42[dependencies.compiler_builtins]
43git = "https://github.com/rust-lang/compiler-builtins"
44features = ["c"]
45```
46
47[an issue]: https://github.com/rust-lang/compiler-builtins/issues
48
49## Contributing
50
511. Pick one or more intrinsics from the [pending list](#progress).
522. Fork this repository.
533. Port the intrinsic(s) and their corresponding [unit tests][1] from their
54   [C implementation][2] to Rust.
554. Add a test to compare the behavior of the ported intrinsic(s) with their
56   implementation on the testing host.
575. Add the intrinsic to `examples/intrinsics.rs` to verify it can be linked on
58   all targets.
596. Send a Pull Request (PR).
607. Once the PR passes our extensive testing infrastructure, we'll merge it!
618. Celebrate :tada:
62
63[1]: https://github.com/rust-lang/llvm-project/tree/9e3de9490ff580cd484fbfa2908292b4838d56e7/compiler-rt/test/builtins/Unit
64[2]: https://github.com/rust-lang/llvm-project/tree/9e3de9490ff580cd484fbfa2908292b4838d56e7/compiler-rt/lib/builtins
65[3]: https://github.com/rust-lang/compiler-builtins/actions
66
67### Porting Reminders
68
691. [Rust][5a] and [C][5b] have slightly different operator precedence. C evaluates comparisons (`== !=`) before bitwise operations (`& | ^`), while Rust evaluates the other way.
702. C assumes wrapping operations everywhere. Rust panics on overflow when in debug mode. Consider using the [Wrapping][6] type or the explicit [wrapping_*][7] functions where applicable.
713. Note [C implicit casts][8], 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.
724. Rust has [many functions][9] for integer or floating point manipulation in the standard library. Consider using one of these functions rather than porting a new one.
73
74[5a]: https://doc.rust-lang.org/reference/expressions.html#expression-precedence
75[5b]: http://en.cppreference.com/w/c/language/operator_precedence
76[6]: https://doc.rust-lang.org/core/num/struct.Wrapping.html
77[7]: https://doc.rust-lang.org/std/primitive.i32.html#method.wrapping_add
78[8]: http://en.cppreference.com/w/cpp/language/implicit_conversion
79[9]: https://doc.rust-lang.org/std/primitive.i32.html
80
81## Testing
82
83The easiest way to test locally is using Docker. This can be done by running
84`./ci/run-docker.sh [target]`. If no target is specified, all targets will be
85run.
86
87In order to run the full test suite, you will also need the C compiler runtime
88to test against, located in a directory called `compiler-rt`. This can be
89obtained with the following:
90
91```sh
92curl -L -o rustc-llvm-19.1.tar.gz https://github.com/rust-lang/llvm-project/archive/rustc/19.1-2024-09-17.tar.gz
93tar xzf rustc-llvm-19.1.tar.gz --strip-components 1 llvm-project-rustc-19.1-2024-09-17/compiler-rt
94```
95
96Local targets may also be tested with `./ci/run.sh [target]`.
97
98Note that testing may not work on all hosts, in which cases it is acceptable to
99rely on CI.
100
101## Progress
102
103- [x] aarch64/chkstk.S
104- [x] adddf3.c
105- [x] addsf3.c
106- [x] arm/addsf3.S
107- [x] arm/aeabi_dcmp.S
108- [x] arm/aeabi_fcmp.S
109- [x] arm/aeabi_idivmod.S
110- [x] arm/aeabi_ldivmod.S
111- [x] arm/aeabi_memcpy.S
112- [x] arm/aeabi_memmove.S
113- [x] arm/aeabi_memset.S
114- [x] arm/aeabi_uidivmod.S
115- [x] arm/aeabi_uldivmod.S
116- [ ] arm/chkstk.S
117- [ ] arm/divmodsi4.S (generic version is done)
118- [ ] arm/divsi3.S (generic version is done)
119- [ ] arm/modsi3.S (generic version is done)
120- [x] arm/softfloat-alias.list
121- [ ] arm/udivmodsi4.S (generic version is done)
122- [ ] arm/udivsi3.S (generic version is done)
123- [ ] arm/umodsi3.S (generic version is done)
124- [x] ashldi3.c
125- [x] ashrdi3.c
126- [ ] avr/divmodhi4.S
127- [ ] avr/divmodqi4.S
128- [ ] avr/mulhi3.S
129- [ ] avr/mulqi3.S
130- [ ] avr/udivmodhi4.S
131- [ ] avr/udivmodqi4.S
132- [x] bswapdi2.c
133- [x] bswapsi2.c
134- [x] bswapti2.c
135- [x] clzdi2.c
136- [x] clzsi2.c
137- [x] clzti2.c
138- [x] comparedf2.c
139- [x] comparesf2.c
140- [x] ctzdi2.c
141- [x] ctzsi2.c
142- [x] ctzti2.c
143- [x] divdf3.c
144- [x] divdi3.c
145- [x] divmoddi4.c
146- [x] divmodsi4.c
147- [x] divmodti4.c
148- [x] divsf3.c
149- [x] divsi3.c
150- [x] extendsfdf2.c
151- [x] fixdfdi.c
152- [x] fixdfsi.c
153- [x] fixsfdi.c
154- [x] fixsfsi.c
155- [x] fixunsdfdi.c
156- [x] fixunsdfsi.c
157- [x] fixunssfdi.c
158- [x] fixunssfsi.c
159- [x] floatdidf.c
160- [x] floatdisf.c
161- [x] floatsidf.c
162- [x] floatsisf.c
163- [x] floatundidf.c
164- [x] floatundisf.c
165- [x] floatunsidf.c
166- [x] floatunsisf.c
167- [ ] i386/ashldi3.S
168- [ ] i386/ashrdi3.S
169- [x] i386/chkstk.S
170- [ ] i386/divdi3.S
171- [ ] i386/lshrdi3.S
172- [ ] i386/moddi3.S
173- [ ] i386/muldi3.S
174- [ ] i386/udivdi3.S
175- [ ] i386/umoddi3.S
176- [x] lshrdi3.c
177- [x] moddi3.c
178- [x] modsi3.c
179- [x] muldf3.c
180- [x] muldi3.c
181- [x] mulodi4.c
182- [x] mulosi4.c
183- [x] mulsf3.c
184- [x] powidf2.c
185- [x] powisf2.c
186- [ ] riscv/muldi3.S
187- [ ] riscv/mulsi3.S
188- [x] subdf3.c
189- [x] subsf3.c
190- [x] truncdfsf2.c
191- [x] udivdi3.c
192- [x] udivmoddi4.c
193- [x] udivmodsi4.c
194- [x] udivsi3.c
195- [x] umoddi3.c
196- [x] umodsi3.c
197- [x] x86_64/chkstk.S
198
199These builtins are needed to support 128-bit integers.
200
201- [x] ashlti3.c
202- [x] ashrti3.c
203- [x] divti3.c
204- [x] fixdfti.c
205- [x] fixsfti.c
206- [x] fixunsdfti.c
207- [x] fixunssfti.c
208- [x] floattidf.c
209- [x] floattisf.c
210- [x] floatuntidf.c
211- [x] floatuntisf.c
212- [x] lshrti3.c
213- [x] modti3.c
214- [x] muloti4.c
215- [x] multi3.c
216- [x] udivmodti4.c
217- [x] udivti3.c
218- [x] umodti3.c
219
220These builtins are needed to support `f16` and `f128`, which are in the process
221of being added to Rust.
222
223- [x] addtf3.c
224- [x] comparetf2.c
225- [x] divtf3.c
226- [x] extenddftf2.c
227- [x] extendhfsf2.c
228- [x] extendhftf2.c
229- [x] extendsftf2.c
230- [x] fixtfdi.c
231- [x] fixtfsi.c
232- [x] fixtfti.c
233- [x] fixunstfdi.c
234- [x] fixunstfsi.c
235- [x] fixunstfti.c
236- [ ] floatditf.c
237- [ ] floatsitf.c
238- [ ] floattitf.c
239- [ ] floatunditf.c
240- [ ] floatunsitf.c
241- [ ] floatuntitf.c
242- [x] multf3.c
243- [x] powitf2.c
244- [x] subtf3.c
245- [x] truncdfhf2.c
246- [x] truncsfhf2.c
247- [x] trunctfdf2.c
248- [x] trunctfhf2.c
249- [x] trunctfsf2.c
250
251
252These builtins are used by the Hexagon DSP
253
254- [ ] hexagon/common_entry_exit_abi1.S
255- [ ] hexagon/common_entry_exit_abi2.S
256- [ ] hexagon/common_entry_exit_legacy.S
257- [x] hexagon/dfaddsub.S~~
258- [x] hexagon/dfdiv.S~~
259- [x] hexagon/dffma.S~~
260- [x] hexagon/dfminmax.S~~
261- [x] hexagon/dfmul.S~~
262- [x] hexagon/dfsqrt.S~~
263- [x] hexagon/divdi3.S~~
264- [x] hexagon/divsi3.S~~
265- [x] hexagon/fastmath2_dlib_asm.S~~
266- [x] hexagon/fastmath2_ldlib_asm.S~~
267- [x] hexagon/fastmath_dlib_asm.S~~
268- [x] hexagon/memcpy_forward_vp4cp4n2.S~~
269- [x] hexagon/memcpy_likely_aligned.S~~
270- [x] hexagon/moddi3.S~~
271- [x] hexagon/modsi3.S~~
272- [x] hexagon/sfdiv_opt.S~~
273- [x] hexagon/sfsqrt_opt.S~~
274- [x] hexagon/udivdi3.S~~
275- [x] hexagon/udivmoddi4.S~~
276- [x] hexagon/udivmodsi4.S~~
277- [x] hexagon/udivsi3.S~~
278- [x] hexagon/umoddi3.S~~
279- [x] hexagon/umodsi3.S~~
280
281## Unimplemented functions
282
283These builtins are for x87 `f80` floating-point numbers that are not supported
284by Rust.
285
286- ~~extendxftf2.c~~
287- ~~fixunsxfdi.c~~
288- ~~fixunsxfsi.c~~
289- ~~fixunsxfti.c~~
290- ~~fixxfdi.c~~
291- ~~fixxfti.c~~
292- ~~floatdixf.c~~
293- ~~floattixf.c~~
294- ~~floatundixf.c~~
295- ~~floatuntixf.c~~
296- ~~i386/floatdixf.S~~
297- ~~i386/floatundixf.S~~
298- ~~x86_64/floatdixf.c~~
299- ~~x86_64/floatundixf.S~~
300
301These builtins are for IBM "extended double" non-IEEE 128-bit floating-point
302numbers.
303
304- ~~ppc/divtc3.c~~
305- ~~ppc/fixtfdi.c~~
306- ~~ppc/fixtfti.c~~
307- ~~ppc/fixunstfdi.c~~
308- ~~ppc/fixunstfti.c~~
309- ~~ppc/floatditf.c~~
310- ~~ppc/floattitf.c~~
311- ~~ppc/floatunditf.c~~
312- ~~ppc/gcc_qadd.c~~
313- ~~ppc/gcc_qdiv.c~~
314- ~~ppc/gcc_qmul.c~~
315- ~~ppc/gcc_qsub.c~~
316- ~~ppc/multc3.c~~
317
318These builtins are for 16-bit brain floating-point numbers that are not
319supported by Rust.
320
321- ~~truncdfbf2.c~~
322- ~~truncsfbf2.c~~
323- ~~trunctfxf2.c~~
324
325These builtins involve complex floating-point types that are not supported by
326Rust.
327
328- ~~divdc3.c~~
329- ~~divsc3.c~~
330- ~~divtc3.c~~
331- ~~divxc3.c~~
332- ~~muldc3.c~~
333- ~~mulsc3.c~~
334- ~~multc3.c~~
335- ~~mulxc3.c~~
336- ~~powixf2.c~~
337
338These builtins are never called by LLVM.
339
340- ~~absvdi2.c~~
341- ~~absvsi2.c~~
342- ~~absvti2.c~~
343- ~~addvdi3.c~~
344- ~~addvsi3.c~~
345- ~~addvti3.c~~
346- ~~arm/aeabi_cdcmp.S~~
347- ~~arm/aeabi_cdcmpeq_check_nan.c~~
348- ~~arm/aeabi_cfcmp.S~~
349- ~~arm/aeabi_cfcmpeq_check_nan.c~~
350- ~~arm/aeabi_div0.c~~
351- ~~arm/aeabi_drsub.c~~
352- ~~arm/aeabi_frsub.c~~
353- ~~arm/aeabi_memcmp.S~~
354- ~~arm/bswapdi2.S~~
355- ~~arm/bswapsi2.S~~
356- ~~arm/clzdi2.S~~
357- ~~arm/clzsi2.S~~
358- ~~arm/comparesf2.S~~
359- ~~arm/restore_vfp_d8_d15_regs.S~~
360- ~~arm/save_vfp_d8_d15_regs.S~~
361- ~~arm/switch16.S~~
362- ~~arm/switch32.S~~
363- ~~arm/switch8.S~~
364- ~~arm/switchu8.S~~
365- ~~cmpdi2.c~~
366- ~~cmpti2.c~~
367- ~~ffssi2.c~~
368- ~~ffsdi2.c~~ - this is [called by gcc][jemalloc-fail] though!
369- ~~ffsti2.c~~
370- ~~mulvdi3.c~~
371- ~~mulvsi3.c~~
372- ~~mulvti3.c~~
373- ~~negdf2.c~~
374- ~~negdi2.c~~
375- ~~negsf2.c~~
376- ~~negti2.c~~
377- ~~negvdi2.c~~
378- ~~negvsi2.c~~
379- ~~negvti2.c~~
380- ~~paritydi2.c~~
381- ~~paritysi2.c~~
382- ~~parityti2.c~~
383- ~~popcountdi2.c~~
384- ~~popcountsi2.c~~
385- ~~popcountti2.c~~
386- ~~ppc/restFP.S~~
387- ~~ppc/saveFP.S~~
388- ~~subvdi3.c~~
389- ~~subvsi3.c~~
390- ~~subvti3.c~~
391- ~~ucmpdi2.c~~
392- ~~ucmpti2.c~~
393- ~~udivmodti4.c~~
394
395[jemalloc-fail]: https://travis-ci.org/rust-lang/rust/jobs/249772758
396
397Rust only exposes atomic types on platforms that support them, and therefore does not need to fall back to software implementations.
398
399- ~~arm/sync_fetch_and_add_4.S~~
400- ~~arm/sync_fetch_and_add_8.S~~
401- ~~arm/sync_fetch_and_and_4.S~~
402- ~~arm/sync_fetch_and_and_8.S~~
403- ~~arm/sync_fetch_and_max_4.S~~
404- ~~arm/sync_fetch_and_max_8.S~~
405- ~~arm/sync_fetch_and_min_4.S~~
406- ~~arm/sync_fetch_and_min_8.S~~
407- ~~arm/sync_fetch_and_nand_4.S~~
408- ~~arm/sync_fetch_and_nand_8.S~~
409- ~~arm/sync_fetch_and_or_4.S~~
410- ~~arm/sync_fetch_and_or_8.S~~
411- ~~arm/sync_fetch_and_sub_4.S~~
412- ~~arm/sync_fetch_and_sub_8.S~~
413- ~~arm/sync_fetch_and_umax_4.S~~
414- ~~arm/sync_fetch_and_umax_8.S~~
415- ~~arm/sync_fetch_and_umin_4.S~~
416- ~~arm/sync_fetch_and_umin_8.S~~
417- ~~arm/sync_fetch_and_xor_4.S~~
418- ~~arm/sync_fetch_and_xor_8.S~~
419- ~~arm/sync_synchronize.S~~
420- ~~atomic.c~~
421- ~~atomic_flag_clear.c~~
422- ~~atomic_flag_clear_explicit.c~~
423- ~~atomic_flag_test_and_set.c~~
424- ~~atomic_flag_test_and_set_explicit.c~~
425- ~~atomic_signal_fence.c~~
426- ~~atomic_thread_fence.c~~
427
428Miscellaneous functionality that is not used by Rust.
429
430- ~~aarch64/fp_mode.c~~
431- ~~aarch64/lse.S~~ (LSE atomics)
432- ~~aarch64/sme-abi-init.c~~ (matrix extension)
433- ~~aarch64/sme-abi.S~~ (matrix extension)
434- ~~aarch64/sme-libc-routines.c~~ (matrix extension)
435- ~~apple_versioning.c~~
436- ~~arm/fp_mode.c~~
437- ~~avr/exit.S~~
438- ~~clear_cache.c~~
439- ~~cpu_model/aarch64.c~~
440- ~~cpu_model/x86.c~~
441- ~~crtbegin.c~~
442- ~~crtend.c~~
443- ~~emutls.c~~
444- ~~enable_execute_stack.c~~
445- ~~eprintf.c~~
446- ~~fp_mode.c~~ (float exception handling)
447- ~~gcc_personality_v0.c~~
448- ~~i386/fp_mode.c~~
449- ~~int_util.c~~
450- ~~loongarch/fp_mode.c~~
451- ~~os_version_check.c~~
452- ~~riscv/fp_mode.c~~
453- ~~riscv/restore.S~~ (callee-saved registers)
454- ~~riscv/save.S~~ (callee-saved registers)
455- ~~trampoline_setup.c~~
456- ~~ve/grow_stack.S~~
457- ~~ve/grow_stack_align.S~~
458
459Floating-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.
460
461- ~~i386/floatdidf.S~~
462- ~~i386/floatdisf.S~~
463- ~~i386/floatundidf.S~~
464- ~~i386/floatundisf.S~~
465- ~~x86_64/floatundidf.S~~
466- ~~x86_64/floatundisf.S~~
467- ~~x86_64/floatdidf.c~~
468- ~~x86_64/floatdisf.c~~
469
470Unsupported in any current target: used on old versions of 32-bit iOS with ARMv5.
471
472- ~~arm/adddf3vfp.S~~
473- ~~arm/addsf3vfp.S~~
474- ~~arm/divdf3vfp.S~~
475- ~~arm/divsf3vfp.S~~
476- ~~arm/eqdf2vfp.S~~
477- ~~arm/eqsf2vfp.S~~
478- ~~arm/extendsfdf2vfp.S~~
479- ~~arm/fixdfsivfp.S~~
480- ~~arm/fixsfsivfp.S~~
481- ~~arm/fixunsdfsivfp.S~~
482- ~~arm/fixunssfsivfp.S~~
483- ~~arm/floatsidfvfp.S~~
484- ~~arm/floatsisfvfp.S~~
485- ~~arm/floatunssidfvfp.S~~
486- ~~arm/floatunssisfvfp.S~~
487- ~~arm/gedf2vfp.S~~
488- ~~arm/gesf2vfp.S~~
489- ~~arm/gtdf2vfp.S~~
490- ~~arm/gtsf2vfp.S~~
491- ~~arm/ledf2vfp.S~~
492- ~~arm/lesf2vfp.S~~
493- ~~arm/ltdf2vfp.S~~
494- ~~arm/ltsf2vfp.S~~
495- ~~arm/muldf3vfp.S~~
496- ~~arm/mulsf3vfp.S~~
497- ~~arm/nedf2vfp.S~~
498- ~~arm/negdf2vfp.S~~
499- ~~arm/negsf2vfp.S~~
500- ~~arm/nesf2vfp.S~~
501- ~~arm/subdf3vfp.S~~
502- ~~arm/subsf3vfp.S~~
503- ~~arm/truncdfsf2vfp.S~~
504- ~~arm/unorddf2vfp.S~~
505- ~~arm/unordsf2vfp.S~~
506
507## License
508
509The compiler-builtins crate is dual licensed under both the University of
510Illinois "BSD-Like" license and the MIT license.  As a user of this code you may
511choose to use it under either license.  As a contributor, you agree to allow
512your code to be used under both.
513
514Full text of the relevant licenses is in LICENSE.TXT.
515