From 835d2b98f0fe7e09eae6e6d64e1b73fc859b93c9 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sat, 15 Mar 2025 23:41:30 +0100 Subject: [PATCH 1/7] GHA: Test macos-14 arm64 image --- .github/workflows/main.yml | 4 ++-- ci/cirrusci.sh | 7 ++++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 74c99390fa4d..c1deee658f8d 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -54,8 +54,8 @@ jobs: container_image: alpine:3.21 host_dmd: ldmd2 # macOS - - job_name: macOS 13 x64, DMD (latest) - os: macos-13 + - job_name: macOS 14 x64, DMD (latest) + os: macos-14 host_dmd: dmd # Disabled because of failure https://issues.dlang.org/show_bug.cgi?id=24518 # - job_name: macOS 13 x64, DMD (coverage) diff --git a/ci/cirrusci.sh b/ci/cirrusci.sh index 776c6a2e7a5d..85ab45d6bf03 100755 --- a/ci/cirrusci.sh +++ b/ci/cirrusci.sh @@ -36,7 +36,12 @@ if [ "$OS_NAME" == "linux" ]; then elif [ "$OS_NAME" == "osx" ]; then # upgrade GNU make brew install make - sudo ln -s /usr/local/opt/make/libexec/gnubin/make /usr/local/bin/make + for candidateDir in /usr/local/opt/make/libexec/gnubin /opt/homebrew/opt/make/libexec/gnubin; do + if [[ -f $candidateDir/make ]]; then + sudo ln -s $candidateDir/make /usr/local/bin/make + break + fi + done elif [ "$OS_NAME" == "freebsd" ]; then packages="git gmake devel/llvm12" if [ "$HOST_DMD" == "dmd-2.079.0" ] ; then From 70b5f03d9556e3d4e37ad6dd03f80d81e0848dd5 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sun, 16 Mar 2025 00:28:17 +0100 Subject: [PATCH 2/7] [switch to LDC host compiler, and so a native arm64 DMD build] --- .github/workflows/main.yml | 4 ++-- compiler/src/dmd/backend/x86/cg87.d | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c1deee658f8d..2b5bd1eb6897 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -54,9 +54,9 @@ jobs: container_image: alpine:3.21 host_dmd: ldmd2 # macOS - - job_name: macOS 14 x64, DMD (latest) + - job_name: macOS 14 arm64, LDC os: macos-14 - host_dmd: dmd + host_dmd: ldc # Disabled because of failure https://issues.dlang.org/show_bug.cgi?id=24518 # - job_name: macOS 13 x64, DMD (coverage) # os: macos-13 diff --git a/compiler/src/dmd/backend/x86/cg87.d b/compiler/src/dmd/backend/x86/cg87.d index d1cd09a00af9..4971bd69b09f 100644 --- a/compiler/src/dmd/backend/x86/cg87.d +++ b/compiler/src/dmd/backend/x86/cg87.d @@ -649,7 +649,7 @@ ubyte loadconst(elem* e, int im) immutable double[7] dval = [0.0,1.0,PI,LOG2T,LOG2E,LOG2,LN2]; - static if (real.sizeof < 10) + static if (!is(targ_ldouble == real)) { import dmd.root.longdouble; immutable targ_ldouble[7] ldval = @@ -742,7 +742,7 @@ ubyte loadconst(elem* e, int im) // Note that for this purpose, -0 is not regarded as +0, // since FLDZ loads a +0 assert(sz <= zeros.length); - zero = (memcmp(p, zeros.ptr, sz) == 0); + zero = (memcmp(p, zeros.ptr, sz < targ_ldouble.sizeof ? sz : targ_ldouble.sizeof) == 0); if (zero && config.target_cpu >= TARGET_PentiumPro) return 0xEE; // FLDZ is the only one with 1 micro-op From 9c858d3237f43d1402ccbd90db195a016c96476a Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sun, 16 Mar 2025 01:46:16 +0100 Subject: [PATCH 3/7] [fix up target `real` properties if host `real_t` is not x87] --- compiler/src/dmd/target.d | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/compiler/src/dmd/target.d b/compiler/src/dmd/target.d index f52bcc57b8f2..61e4a44f9c0b 100644 --- a/compiler/src/dmd/target.d +++ b/compiler/src/dmd/target.d @@ -485,6 +485,22 @@ extern (C++) struct Target } } + // fix up RealProperties if the target real is x87, but host real_t isn't + if (realsize - realpad == 10 && RealProperties.mant_dig != 64) { + import dmd.root.ctfloat : CTFloat; + + bool isOutOfRange; + RealProperties.max = CTFloat.parse("0x1.fffffffffffffffep+16383", isOutOfRange); + RealProperties.min_normal = CTFloat.parse("0x1p-16382", isOutOfRange); + RealProperties.epsilon = CTFloat.parse("0x1p-63", isOutOfRange); + RealProperties.dig = 18; + RealProperties.mant_dig = 64; + RealProperties.max_exp = 16_384; + RealProperties.min_exp = -16_381; + RealProperties.max_10_exp = 4932; + RealProperties.min_10_exp = -4931; + } + c.initialize(params, this); cpp.initialize(params, this); objc.initialize(params, this); From f013b702b2e44a296e2b67dc9526e55c7fda263f Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sun, 16 Mar 2025 02:10:56 +0100 Subject: [PATCH 4/7] [set up Apple clang for cross-linking automatically] --- compiler/src/dmd/link.d | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/compiler/src/dmd/link.d b/compiler/src/dmd/link.d index a0850b829165..2402ed6682ab 100644 --- a/compiler/src/dmd/link.d +++ b/compiler/src/dmd/link.d @@ -443,10 +443,31 @@ public int runLINK(bool verbose, ErrorSink eSink) argv.push("-g"); if (target.isX86_64) argv.push("-m64"); - else + else if (target.isX86) argv.push("-m32"); version (OSX) { + // might need to set up Apple clang for cross-linking + if (target.os == Target.OS.OSX) + { + version (AArch64) + { + if (target.isX86_64) + { + argv.push("-arch"); + argv.push("x86_64"); + } + } + else + { + if (target.isAArch64) + { + argv.push("-arch"); + argv.push("arm64"); + } + } + } + /* Without this switch, ld generates messages of the form: * ld: warning: could not create compact unwind for __Dmain: offset of saved registers too far to encode * meaning they are further than 255 bytes from the frame register. From 7cd178d3c9162ea223b7d401b18c12a5a020a60e Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sun, 16 Mar 2025 02:52:18 +0100 Subject: [PATCH 5/7] CI: Add native arm64 hello-world smoke test --- .github/workflows/main.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 2b5bd1eb6897..474d5b20f102 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -156,7 +156,20 @@ jobs: uses: seanmiddleditch/gha-setup-vsdevenv@v4 with: arch: ${{ env.MODEL == '64' && 'x64' || 'x86' }} + - name: 'macOS arm64: Run arm64 smoke test' + if: matrix.os == 'macos-14' + run: | + set -uexo pipefail + + cat >hello.d < Date: Sun, 16 Mar 2025 17:27:04 +0100 Subject: [PATCH 6/7] [add 2nd macos-14 CI job, using latest DMD as host compiler, and so an emulated fresh x86_64 DMD build] --- .github/workflows/main.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 474d5b20f102..2e18d62df346 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -57,6 +57,9 @@ jobs: - job_name: macOS 14 arm64, LDC os: macos-14 host_dmd: ldc + - job_name: macOS 14 x64, DMD (latest) + os: macos-14 + host_dmd: dmd # Disabled because of failure https://issues.dlang.org/show_bug.cgi?id=24518 # - job_name: macOS 13 x64, DMD (coverage) # os: macos-13 @@ -79,7 +82,8 @@ jobs: name: ${{ matrix.job_name }} runs-on: ${{ matrix.os }} container: ${{ matrix.container_image }} - timeout-minutes: 40 + # for some reason, the compiler testsuite is extremely slow with x86_64 emulation on macos-14 runners + timeout-minutes: ${{ matrix.os == 'macos-14' && 60 || 40 }} env: # for ci/run.sh: OS_NAME: ${{ startsWith(matrix.os, 'ubuntu') && 'linux' || (startsWith(matrix.os, 'macos') && 'osx' || (startsWith(matrix.os, 'windows') && 'windows' || '')) }} From bbb794be394337e9b2ab5afc2aa957fd1884da95 Mon Sep 17 00:00:00 2001 From: Martin Kinkelin Date: Sun, 16 Mar 2025 18:21:13 +0100 Subject: [PATCH 7/7] [add tentative support for arm64 Mach-O object files] --- compiler/src/dmd/backend/mach.d | 3 +++ compiler/src/dmd/backend/machobj.d | 5 +++-- compiler/src/dmd/lib/scanmach.d | 6 ++++-- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/compiler/src/dmd/backend/mach.d b/compiler/src/dmd/backend/mach.d index a7078e2766f7..3bcd8927bea8 100644 --- a/compiler/src/dmd/backend/mach.d +++ b/compiler/src/dmd/backend/mach.d @@ -25,10 +25,13 @@ enum CPU_TYPE_X86_64 = cast(cpu_type_t)7 | 0x1000000, CPU_TYPE_POWERPC = cast(cpu_type_t)18, CPU_TYPE_POWERPC64 = CPU_TYPE_POWERPC | 0x1000000, + CPU_TYPE_ARM = cast(cpu_type_t)12, + CPU_TYPE_ARM64 = CPU_TYPE_ARM | 0x1000000, // cpusubtype CPU_SUBTYPE_POWERPC_ALL = cast(cpu_subtype_t)0, CPU_SUBTYPE_I386_ALL = cast(cpu_subtype_t)3, + CPU_SUBTYPE_ARM64_ALL = cast(cpu_subtype_t)0, // filetype MH_OBJECT = 1, diff --git a/compiler/src/dmd/backend/machobj.d b/compiler/src/dmd/backend/machobj.d index dc89956beb5d..c4adae38138b 100644 --- a/compiler/src/dmd/backend/machobj.d +++ b/compiler/src/dmd/backend/machobj.d @@ -642,9 +642,10 @@ void MachObj_term(const(char)[] objfilename) { mach_header_64 header = void; + const isARM64 = config.target_cpu == TARGET_AArch64; header.magic = MH_MAGIC_64; - header.cputype = CPU_TYPE_X86_64; - header.cpusubtype = CPU_SUBTYPE_I386_ALL; + header.cputype = isARM64 ? CPU_TYPE_ARM64 : CPU_TYPE_X86_64; + header.cpusubtype = isARM64 ? CPU_SUBTYPE_ARM64_ALL : CPU_SUBTYPE_I386_ALL; header.filetype = MH_OBJECT; header.ncmds = 4; header.sizeofcmds = cast(uint)(segment_command_64.sizeof + diff --git a/compiler/src/dmd/lib/scanmach.d b/compiler/src/dmd/lib/scanmach.d index 0d0d5c28716f..ee0a7019cc3f 100644 --- a/compiler/src/dmd/lib/scanmach.d +++ b/compiler/src/dmd/lib/scanmach.d @@ -19,6 +19,7 @@ import dmd.location; //import core.sys.darwin.mach.loader; import dmd.backend.mach; import dmd.root.string : fTuple; +import dmd.target : target; nothrow: @@ -79,9 +80,10 @@ void scanMachObjModule(void delegate(const(char)[] name, int pickAny) nothrow pA header64 = cast(mach_header_64*)buf; if (buflen < mach_header_64.sizeof) return corrupt(__LINE__); - if (header64.cputype != CPU_TYPE_X86_64) + const expectedCPUType = target.isAArch64 ? CPU_TYPE_ARM64 : CPU_TYPE_X86_64; + if (header64.cputype != expectedCPUType) { - eSink.error(Loc.initial, "Mach-O object module `%s` has cputype = %d, should be %d", module_name, header64.cputype, CPU_TYPE_X86_64); + eSink.error(Loc.initial, "Mach-O object module `%s` has cputype = %d, should be %d", module_name, header64.cputype, expectedCPUType); return; } if (header64.filetype != MH_OBJECT)