[libc-commits] [libc] Enable bare-metal hermetic tests on Arm (PR #207361)
Petr Hosek via libc-commits
libc-commits at lists.llvm.org
Tue Jul 7 01:06:46 PDT 2026
================
@@ -0,0 +1,117 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Arm bare-metal hermetic test utilities.
+///
+//===----------------------------------------------------------------------===//
+
+#include "hdr/stdint_proxy.h"
+#include "hdr/types/size_t.h"
+#include "hdr/types/ssize_t.h"
+#include "hdr/types/struct_timespec.h"
+
+// Redirect stdout/stderr, time and exit from libc tests to semihosting
+
+namespace {
+// Semihosting constants and semihosting call wrapper.
+// https://github.com/ARM-software/abi-aa/blob/main/semihosting/semihosting.rst
+constexpr uint32_t SYS_OPEN = 0x01;
+constexpr uint32_t SYS_WRITE = 0x05;
+constexpr uint32_t SYS_CLOCK = 0x10;
+constexpr uint32_t SYS_TIME = 0x11;
+constexpr uint32_t SYS_EXIT = 0x18;
+
+constexpr uint32_t OPENMODE_W = 4;
+
+constexpr uint32_t ADP_Stopped_ApplicationExit = 0x20026;
+constexpr uint32_t ADP_Stopped_RunTimeErrorUnknown = 0x20023;
+
+#if defined(__thumb__) // T32
+#if defined(__ARM_ARCH_PROFILE) && __ARM_ARCH_PROFILE == 'M'
+#define SEMIHOST_INSTRUCTION "bkpt #0xAB"
+#else
+#define SEMIHOST_INSTRUCTION "svc 0xab"
+#endif
+#else // A32
+#define SEMIHOST_INSTRUCTION "svc 0x123456"
+#endif
+
+long semihosting_call(long val, const void *ptr) {
+ register long v __asm__("r0") = val;
+ register const void *p __asm__("r1") = ptr;
+ __asm__ __volatile__(SEMIHOST_INSTRUCTION
+ : "+r"(v), "+r"(p)
+ :
+ : "memory", "cc");
+ return v;
+}
+} // namespace
+
+extern "C" {
+struct __llvm_libc_stdio_cookie {
+ int handle;
+};
+
+struct __llvm_libc_stdio_cookie __llvm_libc_stdout_cookie;
+struct __llvm_libc_stdio_cookie __llvm_libc_stderr_cookie;
+
+static void stdio_open(struct __llvm_libc_stdio_cookie *cookie, size_t mode) {
+ const char std_stream_name[] = ":tt";
+ size_t args[3];
+ args[0] = reinterpret_cast<size_t>(std_stream_name);
+ args[1] = mode;
+ args[2] = sizeof(std_stream_name) - 1UL;
+ cookie->handle = semihosting_call(SYS_OPEN, args);
+}
+
+void _platform_init(void) {
+ stdio_open(&__llvm_libc_stdout_cookie, OPENMODE_W);
+ stdio_open(&__llvm_libc_stderr_cookie, OPENMODE_W);
+}
+
+void __llvm_libc_exit(int status) {
+ uint32_t semihosting_status = (status == 0) ? ADP_Stopped_ApplicationExit
+ : ADP_Stopped_RunTimeErrorUnknown;
+ semihosting_call(SYS_EXIT,
+ reinterpret_cast<const void *>(semihosting_status));
+ __builtin_unreachable(); // This semihosting call does not return.
+}
+
+ssize_t __llvm_libc_stdio_write(struct __llvm_libc_stdio_cookie *cookie,
+ const char *buf, size_t size) {
+ size_t args[4];
+ args[0] = static_cast<size_t>(cookie->handle);
+ args[1] = reinterpret_cast<size_t>(buf);
+ args[2] = size;
----------------
petrhosek wrote:
Ditto here:
```suggestion
size_t args[] = {
static_cast<size_t>(cookie->handle),
reinterpret_cast<size_t>(buf),
size,
}
```
Is there any particular reason why `args` is declared to be 4 rather than 3 elements?
https://github.com/llvm/llvm-project/pull/207361
More information about the libc-commits
mailing list