|
| 1 | +--- |
| 2 | +layout: post |
| 3 | +title: "Clang 17 now in dev container, and other toolchain news" |
| 4 | +date: 2025-01-23 |
| 5 | +categories: cheri toolchain |
| 6 | +author: Owen Anderson |
| 7 | +--- |
| 8 | + |
| 9 | +Thanks to a collaboration with the [upstream CHERI toolchain](https://github.com/ctsrd-cheri/llvm-project), the CHERIoT toolchain has now been rebased onto Clang 17 from Clang 13, bringing us two years closer to upstream Clang. |
| 10 | +Major thanks to [Alex Richardson](https://github.com/arichardson) (Google) and [Sam Leffler](https://github.com/sleffler/) (Google) for their work on this effort! |
| 11 | + |
| 12 | +This update brings with it substantially improved support for C++20 features, as well as preliminary support for some C++23 and C23 features. |
| 13 | +It also brings with it many improvements to the core of the RISC-V code generator, notably benefiting code size: the firmware image for the Cheriot RTOS testsuite is 2.7% smaller when built with Clang 17 compared to Clang 13. |
| 14 | +Other highlights include compile time improvements, and too many under-the-hood fixes to enumerate. |
| 15 | +You can find detailed release notes for all Clang and LLVM releases on the LLVM.org [releases page](https://releases.llvm.org). |
| 16 | + |
| 17 | +While we generally attempt to maintain compatibility between CHERIoT RTOS and the older toolchain, we recommend pulling the latest devcontainer (or otherwise updating your toolchain) to ensure the best experience. |
| 18 | + |
| 19 | +## Other Toolchain Improvements |
| 20 | + |
| 21 | +Since landing the Clang 17 rebase, we've been busy bringing bugfixes and enhancements to the CHERIoT toolchain, including: |
| 22 | + |
| 23 | +### Language & Usability Improvements |
| 24 | + |
| 25 | +- [Implemented](https://github.com/CHERIoT-Platform/llvm-project/commit/025c5d452e8935ebbe2a09d78fb2a10c1c96a626) a new Clang diagnostic to warn on compartment exports that return void, or where the return value is unused. |
| 26 | +This is important in practice, because cross-compartment calls can fail in the compartment switcher, and void returns make this failure undetectable. |
| 27 | +These warnings are disabled by default until CHERIoT RTOS has been updated for them, and are controlled by the `-Wcheri-compartment-return-void` compiler flag. Thanks to [Robert Dazi](https://github.com/v01dXYZ) for this one! |
| 28 | + |
| 29 | +- [Allowed](https://github.com/CHERIoT-Platform/llvm-project/commit/0de0fb3e8f63be9102c5b5eab1b496415b667ca9) `cheri_libcall`-annotated functions to decay into unannotated function pointers. |
| 30 | +This is useful for passing the address of a `cheri_libcall` function as a callback within a compartment. |
| 31 | + |
| 32 | +- [Improved](https://github.com/CHERIoT-Platform/llvm-project/commit/b14e86345d929bf91ab3fb1197ac716dc7ca6e2d) linker error reporting if you accidentally omit the compartment export annotation on a declaration. |
| 33 | +`lld` will now look for matching unexported functions and provide a suggested fix. |
| 34 | + |
| 35 | +- [Eliminated](https://github.com/CHERIoT-Platform/llvm-project/issues/58) the need to repeat the minimum stack size in both the annotation and in the stack check, improving the ergonomics significantly. |
| 36 | +Below is an example of using the `StackUsageCheck` template in CHERIoT RTOS to verify stack usage, demonstrating the older style that repeats the size, and the new style that does not. |
| 37 | +The related `STACK_CHECK(expected)` macro in CHERIoT RTOS has been updated to use the new style, and the `expected` parameter will be removed in the future. |
| 38 | +```c++ |
| 39 | + __cheriot_minimum_stack(0x200) |
| 40 | + int old_style() { |
| 41 | + StackUsageCheck<StackCheckMode::Asserting, 0x200, __PRETTY_FUNCTION__> stackCheck; |
| 42 | + } |
| 43 | + |
| 44 | + __cheriot_minimum_stack(0x200) |
| 45 | + int new_style() { |
| 46 | + StackUsageCheck<StackCheckMode::Asserting, __cheriot_minimum_stack__, __PRETTY_FUNCTION__> stackCheck; |
| 47 | + } |
| 48 | +``` |
| 49 | +
|
| 50 | +- [Added support](https://github.com/CHERIoT-Platform/llvm-project/issues/38) for "temporal" capability valid bit checking, using a new builtin `__builtin_cheri_tag_get_temporal(void*)`. |
| 51 | +This is needed when reading the valid bit in situations where validity can change within the current function, such as around a deallocation or pinning. |
| 52 | +In all other circumstances, the existing non-temporal version should be preferred for better optimization. |
| 53 | +An example would be using a double-checked pattern when pinning with `heap_claim_fast`, where combining the two valid bit reads would yield incorrect code. |
| 54 | +```c++ |
| 55 | +void func(Timeout *t, int *ptr) { |
| 56 | + if (__builtin_cheri_tag_get_temporal(ptr)) { |
| 57 | + int claim = heap_claim_fast(t, ptr, nullptr); |
| 58 | + if (claim == 0 && __builtin_cheri_tag_get_temporal(ptr)) { |
| 59 | + *ptr = 1234; |
| 60 | + // ... |
| 61 | + } |
| 62 | + } |
| 63 | +} |
| 64 | +``` |
| 65 | + |
| 66 | +### Bugfixes |
| 67 | + |
| 68 | +- [Fixed](https://github.com/CHERIoT-Platform/llvm-project/commit/60b4a582dfc1579b3c08c65d4b6ede961eb267f5) a recurring issue where the compiler would generate improperly mangled calls to `memcpy`, `memmove` and/or `memcmp` in specific circumstances, resulting in linker errors. |
| 69 | +This has now been fixed at the source. |
| 70 | +- [Fixed](https://github.com/CHERIoT-Platform/llvm-project/issues/57) linker errors that arise when taking the address of non-exported, non-libcall functions with non-default interrupt state annotations. |
| 71 | + |
| 72 | +### Optimizations |
| 73 | +- [Taught](https://github.com/CHERIoT-Platform/llvm-project/commit/25ad11d7832237e81ca476d4e3e6bac2defc3fa7) the compiler to better optimize `CAndPerm` instructions, including constant folding and idempotence. |
| 74 | +This tends to benefit places where redundant `CAndPerm` instructions were generated by macros or C++ templates. |
| 75 | +- [Freed](https://github.com/CHERIoT-Platform/llvm-project/commit/8221b74cffbfa03149eb5bab1776280ebb43785f) up the TP/X4 register for the compiler's use in code generation. |
| 76 | +This register is normally reserved as a "thread pointer" in RISC-V ABIs, but is not used for that purpose on CHERIoT. |
| 77 | +We haven't observed this making a significant performance or size difference, but some compute-intensive code may benefit. |
| 78 | +- [Re-enabled the MachineOutliner](https://github.com/CHERIoT-Platform/llvm-project/issues/46) size optimization. This improved the firmware size on the CHERIoT RTOS testsuite by 4.4%, and will likely benefit other code bases similarly. |
| 79 | +However, this optimization uncovered an issue in the CHERIoT ISA related to return sentinels that has since been [fixed in the specification](https://github.com/CHERIoT-Platform/cheriot-sail/issues/85). |
| 80 | +If your development board does not contain the fix, you will need to pass `-enable-machine-outliner=never` to the compiler. |
| 81 | +We have added automatic support for enabling this flag when required to the CHERIoT RTOS build system prior to enabling the optimization by default. |
| 82 | +- [Improved code quality](https://github.com/CHERIoT-Platform/llvm-project/issues/85) for unaligned memory accesses. |
| 83 | +We've seen this particularly benefitting some cryptographic code. |
| 84 | +Note that you need to be using an up-to-date SAIL simulator that supports misaligned memory accesses by default, or, if using an older simulator, you will need to pass `-m` to the simulator explicitly to enable them. |
| 85 | + |
| 86 | +## Looking Forward |
| 87 | + |
| 88 | +We have one major improvement in the works that we hope to make available to CHERIoT toolchain users soon: [sealed capability annotations](https://github.com/CHERIoT-Platform/llvm-project/pull/88). |
| 89 | + |
| 90 | +This change adds a new pointer attribute `__sealed_capability`, which disallows any operations that would cause the pointer to be dereferenced, or to be lose its `__sealed_capability` annotation. |
| 91 | +Once integrated with CHERIoT RTOS, we will be able to represent sealing, unsealing, and the propagation of sealed capabilities in a type-safe manner. |
| 92 | + |
| 93 | +```c++ |
| 94 | +// CHERI sealing and unsealing operations now have signatures that are type-safe with respect to sealing. |
| 95 | +void * __sealed_capability cheri_seal(void *cap, const void *type); |
| 96 | +void * cheri_unseal(void * __sealed_capability cap, void *type); |
| 97 | + |
| 98 | +int func(int * __sealed_capability ptr) { |
| 99 | + // This causes a compiler error! |
| 100 | + return *p; |
| 101 | +} |
| 102 | +``` |
| 103 | +
|
| 104 | +We expect that integrating sealed capabilities into the type system will result in more ergonomic and less error-prone programming when dealing with sealing and unsealing operations, as well as detecting most incorrect dereferences of sealed capabilities at compile time. |
0 commit comments