[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