Skip to content

WIP: Port dmd and druntime to GNU/Hurd#22829

Draft
yelninei wants to merge 6 commits intodlang:masterfrom
yelninei:dmd-hurd
Draft

WIP: Port dmd and druntime to GNU/Hurd#22829
yelninei wants to merge 6 commits intodlang:masterfrom
yelninei:dmd-hurd

Conversation

@yelninei
Copy link
Copy Markdown
Contributor

@yelninei yelninei commented Mar 27, 2026

Hi,

As announced on https://forum.dlang.org/thread/agrrykgbdsjlbsgjtatq@forum.dlang.org here is my WIP PR for porting druntime and dmd to GNU Hurd.

To be able to build also #22787 is needed.

Things that I know are still a bit of a mess:

  • Indentation
  • How to add version(linux) where CRuntime_Glibc is used to mean linux + glibc.
  • Mix of new and old alias syntax. Some of the parts were originally against gcc-11 to be able to bootrap and I have not revised the patches yet.

I am currently quite happy with the dmd part as all tests pass on 32bit and 64bit except

  • dmd/compiler/test/dshell/sameenv.d : checks that 2 executables have the same environment variables but they expectedly differ in LD_ORIGIN_PATH
  • dmd/compiler/test/runnable_cxx/cppa.d : A warning coming from non _GLIBCXX_USE_CXX98_ABI version

For the runtime some tests still crash in pthread_join, I am not entirely sure why as the same test outside of libdruntime_ut works fine.
On x86_64 the test runner gets killed after a while with the gc suspend signal, I dont know yet why the runtime does not handle it.

I am not erntirely sure about the format for the dmd triplet as it differs from both the gnu config and llvm triplet.

I have asked people on the bug-hurd mailing list for help as well
https://lists.gnu.org/archive/html/bug-hurd/2026-03/msg00274.html
https://lists.gnu.org/archive/html/bug-hurd/2026-03/msg00275.html

There are some more things needed to bring this back into gdc,

@dlang-bot
Copy link
Copy Markdown
Contributor

Thanks for your pull request and interest in making D better, @yelninei! We are looking forward to reviewing it, and you should be hearing from a maintainer soon.
Please verify that your PR follows this checklist:

  • My PR is fully covered with tests (you can see the coverage diff by visiting the details link of the codecov check)
  • My PR is as minimal as possible (smaller, focused PRs are easier to review than big ones)
  • I have provided a detailed rationale explaining my changes
  • New or modified functions have Ddoc comments (with Params: and Returns:)

Please see CONTRIBUTING.md for more information.


If you have addressed all reviews or aren't sure how to proceed, don't hesitate to ping us with a simple comment.

Bugzilla references

Your PR doesn't reference any Bugzilla issue.

If your PR contains non-trivial changes, please reference a Bugzilla issue or create a manual changelog.

Testing this PR locally

If you don't have a local development environment setup, you can use Digger to test this PR:

dub run digger -- build "master + dmd#22829"

@yelninei
Copy link
Copy Markdown
Contributor Author

The error from the circleci is

ERROR: Newly generated header file (/home/circleci/dmd/generated/linux/release/64/frontend.h) doesn't match with the reference header file (/home/circleci/dmd/compiler/src/dmd/frontend.h)

DETAILS:

diff --git a/home/circleci/dmd/compiler/src/dmd/frontend.h b/home/circleci/dmd/generated/linux/release/64/frontend.h
index 8e8e2fe76..479667814 100644
--- a/home/circleci/dmd/compiler/src/dmd/frontend.h
+++ b/home/circleci/dmd/generated/linux/release/64/frontend.h
@@ -7363,8 +7363,9 @@ struct Target final
         FreeBSD = 16u,
         Solaris = 32u,
         DragonFlyBSD = 64u,
-        all = 127u,
-        Posix = 125u,
+        Hurd = 128u,
+        all = 255u,
+        Posix = 253u,
     };
 
     OS os;

===============
The file `src/dmd/frontend.h` seems to be out of sync. This is likely because
changes were made which affect the C++ interface used by GDC and LDC.

I guess this is expected, is there a way to regenerate the header?

@pbackus
Copy link
Copy Markdown
Contributor

pbackus commented Mar 27, 2026

Re: regenerating the headers, if you read a few more lines down in that error message, you will see this:

To read more about frontend.h and its usage, see src/README.md#cxx-headers-test

Which refers to https://github.com/dlang/dmd/tree/master/compiler/src#cxx-headers-test

@ibuclaw
Copy link
Copy Markdown
Member

ibuclaw commented Mar 27, 2026

I am not erntirely sure about the format for the dmd triplet as it differs from both the gnu config and llvm triplet.

I thought dmd triplet (tuples?) matched ldc.

Historically, I guess gnu/hurd would be i*86-gnu or x86_64-gnu.

/**
* D header file for GNU Hurd
*
* Copyright: Copyright Martin Nowak 2012.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wrong year, wrong copyright. :-)

If unsure, please use:

Copyright: Copyright (c) 2026 D Language Foundation

*
* Copyright: Copyright Martin Nowak 2012.
* License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
* Authors: Martin Nowak
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume Martin didn't author this module.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The file is a copy paste of the linux version with s/linux/hurd/

Is that enough to void the original copyright as it is clearly a derivative?

Copy link
Copy Markdown
Member

@ibuclaw ibuclaw Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not qualified to say. In isolation, I don't consider the file big enough to warrant any copyright claim.

Rather, the body of work as a whole (this PR) ought to be considered as authored by the contributor.

@@ -0,0 +1,25 @@
module core.sys.hurd.unistd;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some modules are missing comment headings/notices entirely. Others have inconsistent styles.

As these are newly introduced sources, I'd err towards not repeating previous bad habits, and pick one format, and use it consistently throughout all new files.

}
else version (Hurd)
{
// What is needed here?
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any part of ioctls.h or ioctl-types.h that would be needed to interact with ioctl().

@ibuclaw
Copy link
Copy Markdown
Member

ibuclaw commented Apr 1, 2026

I have some patches for gdc-11 and gdc-14 that I currently use to get to dmd, but I have not kept them up to date as maintaining multiple variants of the same changes while it is still quite unstable is a bit to much work for me right now.

More than happy to commit them to a development branch under /users/ibuclaw/ in the gcc git repo.

@yelninei
Copy link
Copy Markdown
Contributor Author

yelninei commented Apr 1, 2026

Fixed importc_compare on x86_64 which also fixes the testrunner getting killed by the gc suspend signal

@yelninei
Copy link
Copy Markdown
Contributor Author

yelninei commented Apr 1, 2026

More than happy to commit them to a development branch under /users/ibuclaw/ in the gcc git repo.

If you want to take a look they are here: https://codeberg.org/Yelninei/dmd/src/branch/version-1.112/patches
they are definitly not ready and are based on an earlier version of the druntime port.
I have just been focusing on dmd as I can more easily run the unittests to find more issues.

Mostly the druntime change with minor gdc specific adjustments and then connecting things in configure and Makefile and regenerating them

@yelninei
Copy link
Copy Markdown
Contributor Author

yelninei commented Apr 2, 2026

I think I found the reason for the crash.

looking at one backtrace I noticed that it started from src/rt/dmain2.d (rt_term) the runtime shutdown.

Through some divine intervention i then tried looking at my pthread_cleanup_push and pthread_cleanup_pop cases which is where I had to convert the c macros to D.

These come from glibc/sysdeps/htl/bits/cancelation.h and is very likely that I incorrectly ported these.

Making these do nothing it stops crashing.

To be continued.

@@ -0,0 +1,52 @@
module core.sys.hurd.sys.types;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this file should be removed, and inline all the values where needed. It just looks odd to have a module with public symbols all starting with __.

Comment on lines +185 to +186
PTHREAD_PROCESS_PRIVATE = __pthread_process_shared.__PTHREAD_PROCESS_PRIVATE,
PTHREAD_PROCESS_SHARED = __pthread_process_shared.__PTHREAD_PROCESS_SHARED,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
PTHREAD_PROCESS_PRIVATE = __pthread_process_shared.__PTHREAD_PROCESS_PRIVATE,
PTHREAD_PROCESS_SHARED = __pthread_process_shared.__PTHREAD_PROCESS_SHARED,
PTHREAD_PROCESS_PRIVATE = 0,
PTHREAD_PROCESS_SHARED,


struct pthread_condattr_t
{
__pthread_process_shared __pshared;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
__pthread_process_shared __pshared;
int __pshared;


struct pthread_rwlockattr_t
{
__pthread_process_shared __pshared;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
__pthread_process_shared __pshared;
int __pshared;


struct pthread_barrierattr_t
{
__pthread_process_shared __pshared;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
__pthread_process_shared __pshared;
int __pshared;

Comment on lines +176 to +177
PTHREAD_EXPLICIT_SCHED = __pthread_inheritsched.__PTHREAD_EXPLICIT_SCHED,
PTHREAD_INHERIT_SCHED = __pthread_inheritsched.__PTHREAD_INHERIT_SCHED,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
PTHREAD_EXPLICIT_SCHED = __pthread_inheritsched.__PTHREAD_EXPLICIT_SCHED,
PTHREAD_INHERIT_SCHED = __pthread_inheritsched.__PTHREAD_INHERIT_SCHED,
PTHREAD_EXPLICIT_SCHED = 0,
PTHREAD_INHERIT_SCHED,

Comment on lines +170 to +171
PTHREAD_CREATE_JOINABLE = __pthread_detachstate.__PTHREAD_CREATE_JOINABLE,
PTHREAD_CREATE_DETACHED = __pthread_detachstate.__PTHREAD_CREATE_DETACHED,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
PTHREAD_CREATE_JOINABLE = __pthread_detachstate.__PTHREAD_CREATE_JOINABLE,
PTHREAD_CREATE_DETACHED = __pthread_detachstate.__PTHREAD_CREATE_DETACHED,
PTHREAD_CREATE_JOINABLE = 0,
PTHREAD_CREATE_DETACHED,

Comment on lines +1178 to +1180
enum PTHREAD_MUTEX_NORMAL = __pthread_mutex_type.__PTHREAD_MUTEX_TIMED;
enum PTHREAD_MUTEX_ERRORCHECK = __pthread_mutex_type.__PTHREAD_MUTEX_ERRORCHECK;
enum PTHREAD_MUTEX_RECURSIVE = __pthread_mutex_type.__PTHREAD_MUTEX_RECURSIVE;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
enum PTHREAD_MUTEX_NORMAL = __pthread_mutex_type.__PTHREAD_MUTEX_TIMED;
enum PTHREAD_MUTEX_ERRORCHECK = __pthread_mutex_type.__PTHREAD_MUTEX_ERRORCHECK;
enum PTHREAD_MUTEX_RECURSIVE = __pthread_mutex_type.__PTHREAD_MUTEX_RECURSIVE;
enum PTHREAD_MUTEX_NORMAL = 0;
enum PTHREAD_MUTEX_ERRORCHECK = 1;
enum PTHREAD_MUTEX_RECURSIVE = 2;

Comment on lines +845 to +847
__pthread_mutex_protocol __protocol;
__pthread_process_shared __pshared;
__pthread_mutex_type __mutex_type;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
__pthread_mutex_protocol __protocol;
__pthread_process_shared __pshared;
__pthread_mutex_type __mutex_type;
int __protocol;
int __pshared;
int __mutex_type;

Comment on lines +1524 to +1526
PTHREAD_PRIO_NONE =__pthread_mutex_protocol.__PTHREAD_PRIO_NONE,
PTHREAD_PRIO_INHERIT =__pthread_mutex_protocol.__PTHREAD_PRIO_INHERIT,
PTHREAD_PRIO_PROTECT =__pthread_mutex_protocol.__PTHREAD_PRIO_PROTECT,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
PTHREAD_PRIO_NONE =__pthread_mutex_protocol.__PTHREAD_PRIO_NONE,
PTHREAD_PRIO_INHERIT =__pthread_mutex_protocol.__PTHREAD_PRIO_INHERIT,
PTHREAD_PRIO_PROTECT =__pthread_mutex_protocol.__PTHREAD_PRIO_PROTECT,
PTHREAD_PRIO_NONE = 0,
PTHREAD_PRIO_INHERIT,
PTHREAD_PRIO_PROTECT,

Comment on lines +798 to +800
struct pthread_attr_t
{
__sched_param schedparam;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
struct pthread_attr_t
{
__sched_param schedparam;
private struct __sched_param
{
int __sched_priority;
}
private struct __pthread;
struct pthread_attr_t
{
__sched_param schedparam;

Comment on lines +40 to +47
ErrorFilter("core.stdc.math.double_t", "", "Hurd", 0, ""),
ErrorFilter("core.stdc.math.float_t", "", "Hurd", 0, ""),
ErrorFilter("core.stdc.signal.sig_atomic_t", "", "FreeBSD", 0, ""),
ErrorFilter("core.stdc.stdio.FILE", "", "FreeBSD", 0, ""),
ErrorFilter("core.stdc.stdio.FILE", "", "linux", 0, ""),
ErrorFilter("core.stdc.stdio._IO_FILE", "", "linux", 0, ""),
ErrorFilter("core.stdc.stdio.FILE", "", "Hurd", 0, ""),
ErrorFilter("core.stdc.stdio._IO_FILE", "", "Hurd", 0, ""),
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these failures are inherited from CRuntime_Glibc

@@ -0,0 +1,18 @@
bytes allocated, allocations, type, function, file:line
128 1 float profilegc.main src/profilegc.d:18
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a copy pase of the linux/freebsd one as the the test fails if the file is not present.

having duplicate files for different oses seems a bit weird to me.

@yelninei
Copy link
Copy Markdown
Contributor Author

yelninei commented Apr 2, 2026

The remaining test failures in druntime (phobos has some more, but i have not looked yet whether this is because of druntime or phobos)

  • core/thread/osthread : this fails because we hit stubs in libc failing with ENOSYS for pthread_setschedprio, sched_get_priority_max and sched_get_priority_min . Not that big of a deal for now.
  • druntime/test/shared: loadDR and host test segfault

all dmd compiler tests also pass.

Comment on lines +251 to +252
version (X86)
{
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Our old friend, indentation. :-)

ushort __seq;
}
}
else
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be on the safe side, guard with (X86_64), then add

else
    static assert(false, "Unsupported platform");

Just in case someone decides to do aarch64-gnu or riscv-gnu.

Suggested change
else
else version (X86_64)

Comment on lines +201 to +202
struct msg;
struct __wait_queue;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
struct msg;
struct __wait_queue;
private struct msg;
private struct __wait_queue;

No need to make these opaque types public.

I'd be almost inclined to actually use void* as the field type instead in the msqid_ds definition.

else
alias ipc_pid_t = int;

struct __vm_area_struct;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
struct __vm_area_struct;
private struct __vm_area_struct;

Comment on lines +209 to +211
ushort __shm_npages;
c_ulong* __shm_pages;
__vm_area_struct* __attaches;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
ushort __shm_npages;
c_ulong* __shm_pages;
__vm_area_struct* __attaches;
private ushort __shm_npages;
private c_ulong* __shm_pages;
private __vm_area_struct* __attaches;

Fields not present in the POSIX standard should be private to the user.

https://pubs.opengroup.org/onlinepubs/007904875/basedefs/sys/shm.h.html

_pthread_fastlock __sem_lock;
int __sem_value;
void* __sem_waiting;
enum __SIZEOF_SEM_T = 20;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
enum __SIZEOF_SEM_T = 20;
private enum __SIZEOF_SEM_T = 20;

int __policy;
int[16] __pad;
}
struct __spawn_action;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
struct __spawn_action;
private struct __spawn_action;

Comment on lines +173 to +194
// This exists but always return 32
// private extern (C) nothrow @nogc
// {
// int __libc_current_sigrtmin();
// int __libc_current_sigrtmax();
// }

// @property int SIGRTMIN()() nothrow @nogc {
// __gshared int sig = -1;
// if (sig == -1) {
// sig = __libc_current_sigrtmin();
// }
// return sig;
// }

// @property int SIGRTMAX()() nothrow @nogc {
// __gshared int sig = -1;
// if (sig == -1) {
// sig = __libc_current_sigrtmax();
// }
// return sig;
// }
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My guess is this should be identical to the version (linux) path? Or just don't include this at all - same as OpenBSD.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, but i think this is the gcc-11 version of the linux code.

this is how SIGRTMIN/SIGRTMAX are defined but currently SIGRTMIN == SIGRTMAX == 32 always so it is not useful.

This then caused problem for the gc as the default is using SIGRTMIN and SIGRTMIN + 1 for the suspend/resume signals which is an invalid signo.

I guess removing makes more sense and make it someone elses problem in the future.

@ibuclaw
Copy link
Copy Markdown
Member

ibuclaw commented Apr 2, 2026

I think I've managed to get through the entire lot. Just the open comments to address.

@ibuclaw
Copy link
Copy Markdown
Member

ibuclaw commented Apr 2, 2026

@yelninei oh - and thanks for this herculean effort, and the patience. 🙇

@yelninei
Copy link
Copy Markdown
Contributor Author

yelninei commented Apr 2, 2026

I fixed struct flock which incorrectly uses int vs short on 32 bit.

This was pointed out on the bug-hurd thread.

The importc_compare test does not seem to catch this.

@yelninei
Copy link
Copy Markdown
Contributor Author

yelninei commented Apr 2, 2026

@ibuclaw thanks a lot for the very helpful feedback and dealing with my mess of whitespace issues :)

@yelninei
Copy link
Copy Markdown
Contributor Author

yelninei commented Apr 3, 2026

i fixed a few things that were noticed by the probos tests. I went over all tests again to see if the failure is bercause of druntime:

  • std/file: rename(NULL, "") and remove(NULL) crash in libc
  • std/socket: lots of unimplemented things in libc, setsockopt with SO_RCVTIMEO, getpeername, ...
  • std/net/curl: A test timeouts after a while
  • core/thread/osthread and std/parallelism : The tests using pthread_setschedprio fail. Currently only the libc stub is availanble which always fails and raises warnings during linking.

druntime/test/shared: loadDR and host : fail somewhere in pthread .

A flaky std/process test but not sure about that.

The rest just works (with the linked minimal phobos patch).

There are some things that could be done i.e. faking priority on the D side as is already done for netbsd but Ill leave that to someone in the future.

This feels like a good place for the initial support to me and should make future updates and bugfixes a lot easier.

I hope I can address your comments soon.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants