diff --git a/.github/actions/1-setup/action.yml b/.github/actions/1-setup/action.yml index c83400a318..3a8cec87a7 100644 --- a/.github/actions/1-setup/action.yml +++ b/.github/actions/1-setup/action.yml @@ -23,7 +23,7 @@ runs: packages=( \ git-core cmake g++ \ - libcurl4 libxml2-dev libzstd-dev \ + libcurl4 libzstd-dev \ curl gdb p7zip-full tzdata unzip zip python3-pip \ ) if [[ $arch == x86_64 ]]; then @@ -37,30 +37,34 @@ runs: # Make sure to link libzstd statically sudo rm /usr/lib/$arch-linux-gnu/libzstd.so - - name: 'Linux: Install clang 19 from apt.llvm.org' + - name: 'Linux: Install clang 20 from apt.llvm.org' if: runner.os == 'Linux' shell: bash run: | set -eux cd .. curl -fL --retry 3 --max-time 30 -O https://apt.llvm.org/llvm.sh - sudo bash llvm.sh 19 + sudo bash llvm.sh 20 for tool in clang clang++ ld.lld; do - sudo ln -sf $tool-19 /usr/bin/$tool + sudo ln -sf $tool-20 /usr/bin/$tool $tool --version done - - name: 'macOS arm64: Install Homebrew clang 19' # see mimalloc comment in ../3-build-native/action.yml + - name: 'macOS arm64: Install Homebrew clang 20' # see mimalloc comment in ../3-build-native/action.yml if: runner.os == 'macOS' && inputs.arch == 'arm64' shell: bash - run: brew install llvm@19 - - name: 'Windows: Install clang v19.1.3 from GitHub' + run: brew install llvm@20 + - name: 'Windows: Install clang v20.1.3 from GitHub' if: runner.os == 'Windows' shell: bash run: | set -eux cd .. + suffix='win64' + if [[ '${{ inputs.arch }}' == arm64 ]]; then + suffix='woa64' + fi curl -fL --retry 3 --max-time 300 -o clang.exe \ - https://github.com/llvm/llvm-project/releases/download/llvmorg-19.1.3/LLVM-19.1.3-win64.exe + https://github.com/llvm/llvm-project/releases/download/llvmorg-20.1.3/LLVM-20.1.3-$suffix.exe ./clang.exe //S # double-slash for bash rm clang.exe # C:\Program Files\LLVM\bin should already be in PATH @@ -163,7 +167,9 @@ runs: cd .. url='https://curl.se/windows/latest.cgi?p=win64-mingw.zip' - if [[ '${{ inputs.arch }}' == x86 ]]; then + if [[ '${{ inputs.arch }}' == arm64 ]]; then + url='https://curl.se/windows/latest.cgi?p=win64a-mingw.zip' + elif [[ '${{ inputs.arch }}' == x86 ]]; then url='https://curl.se/windows/latest.cgi?p=win32-mingw.zip' fi diff --git a/.github/actions/3-build-cross/android-llvm-config.in b/.github/actions/3-build-cross/android-llvm-config.in index c67f3b2a6f..8ac719b4b9 100644 --- a/.github/actions/3-build-cross/android-llvm-config.in +++ b/.github/actions/3-build-cross/android-llvm-config.in @@ -45,36 +45,36 @@ prefix=@LLVM_INSTALL_DIR@ has_rtti=NO CPPFLAGS="-I${prefix}/include -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS" CFLAGS="${CPPFLAGS} ${CFLAGS}" -CXXFLAGS="${CFLAGS} -std=c++17 -fno-exceptions -fno-unwind-tables -fno-asynchronous-unwind-tables" +CXXFLAGS="${CFLAGS} -std=c++17 -fno-exceptions -funwind-tables" if [ "$has_rtti" != "YES" ]; then CXXFLAGS="$CXXFLAGS -fno-rtti"; fi LDFLAGS="-L${prefix}/lib" LIBFILE="${prefix}/lib/libLLVM-$version.so" components="aarch64 aarch64asmparser aarch64codegen aarch64desc aarch64disassembler aarch64info aarch64utils \ aggressiveinstcombine all all-targets analysis arm armasmparser armcodegen armdesc armdisassembler arminfo armutils \ -asmparser asmprinter binaryformat bitreader bitstreamreader bitwriter cfguard codegen codegendata codegentypes core coroutines coverage \ +asmparser asmprinter binaryformat bitreader bitstreamreader bitwriter cfguard cgdata codegen codegentypes core coroutines coverage \ debuginfobtf debuginfocodeview debuginfodwarf debuginfogsym debuginfologicalview debuginfomsf debuginfopdb demangle dlltooldriver dwarflinker dwarflinkerclassic dwarflinkerparallel dwp \ -engine executionengine extensions filecheck frontenddriver frontendhlsl frontendoffloading frontendopenacc frontendopenmp fuzzercli fuzzmutate globalisel hipstdpar instcombine \ +engine executionengine extensions filecheck frontendatomic frontenddriver frontendhlsl frontendoffloading frontendopenacc frontendopenmp fuzzercli fuzzmutate globalisel hipstdpar instcombine \ instrumentation interfacestub interpreter ipo irprinter irreader jitlink libdriver lineeditor linker lto mc mca mcdisassembler \ mcjit mcparser mirparser native nativecodegen objcarcopts objcopy object objectyaml option orcdebugging orcjit orcshared orctargetprocess \ -passes profiledata remarks runtimedyld sandboxir scalaropts selectiondag spirv spirvanalysis spirvcodegen spirvdesc spirvinfo support symbolize tablegen target targetparser textapi \ +passes profiledata remarks runtimedyld sandboxir scalaropts selectiondag spirv spirvanalysis spirvcodegen spirvdesc spirvinfo support symbolize tablegen target targetparser telemetry textapi \ textapibinaryreader transformutils vectorize webassembly webassemblyasmparser webassemblycodegen webassemblydesc webassemblydisassembler \ webassemblyinfo webassemblyutils windowsdriver windowsmanifest x86 x86asmparser x86codegen x86desc x86disassembler x86info \ x86targetmca xray" -static_libs="-lLLVMWindowsManifest -lLLVMXRay -lLLVMLibDriver -lLLVMDlltoolDriver -lLLVMTextAPIBinaryReader -lLLVMCoverage -lLLVMLineEditor \ --lLLVMSandboxIR -lLLVMSPIRVCodeGen -lLLVMSPIRVDesc -lLLVMSPIRVInfo -lLLVMSPIRVAnalysis \ --lLLVMX86TargetMCA -lLLVMX86Disassembler -lLLVMX86AsmParser -lLLVMX86CodeGen -lLLVMX86Desc -lLLVMX86Info -lLLVMWebAssemblyDisassembler \ +static_libs="-lLLVMWindowsManifest -lLLVMXRay -lLLVMLibDriver -lLLVMDlltoolDriver -lLLVMTelemetry -lLLVMTextAPIBinaryReader -lLLVMCoverage -lLLVMLineEditor \ +-lLLVMX86TargetMCA -lLLVMX86Disassembler -lLLVMX86AsmParser -lLLVMX86CodeGen -lLLVMX86Desc -lLLVMX86Info \ +-lLLVMSPIRVCodeGen -lLLVMSPIRVDesc -lLLVMSPIRVInfo -lLLVMSPIRVAnalysis -lLLVMWebAssemblyDisassembler \ -lLLVMWebAssemblyAsmParser -lLLVMWebAssemblyCodeGen -lLLVMWebAssemblyUtils -lLLVMWebAssemblyDesc -lLLVMWebAssemblyInfo -lLLVMARMDisassembler \ -lLLVMARMAsmParser -lLLVMARMCodeGen -lLLVMARMDesc -lLLVMARMUtils -lLLVMARMInfo -lLLVMAArch64Disassembler \ -lLLVMAArch64AsmParser -lLLVMAArch64CodeGen -lLLVMAArch64Desc -lLLVMAArch64Utils -lLLVMAArch64Info -lLLVMOrcDebugging -lLLVMOrcJIT \ -lLLVMWindowsDriver -lLLVMMCJIT -lLLVMJITLink -lLLVMInterpreter -lLLVMExecutionEngine -lLLVMRuntimeDyld -lLLVMOrcTargetProcess -lLLVMOrcShared \ -lLLVMDWP -lLLVMDebugInfoLogicalView -lLLVMDebugInfoGSYM -lLLVMOption -lLLVMObjectYAML -lLLVMObjCopy -lLLVMMCA \ -lLLVMMCDisassembler -lLLVMLTO -lLLVMPasses -lLLVMHipStdPar -lLLVMCFGuard -lLLVMCoroutines -lLLVMipo \ --lLLVMVectorize -lLLVMLinker -lLLVMInstrumentation -lLLVMFrontendOpenMP -lLLVMFrontendOffloading -lLLVMFrontendOpenACC -lLLVMFrontendHLSL -lLLVMFrontendDriver -lLLVMExtensions \ --lLLVMDWARFLinkerParallel -lLLVMDWARFLinkerClassic -lLLVMDWARFLinker -lLLVMCodeGenData -lLLVMGlobalISel -lLLVMMIRParser -lLLVMAsmPrinter -lLLVMSelectionDAG \ --lLLVMCodeGen -lLLVMTarget -lLLVMObjCARCOpts -lLLVMCodeGenTypes -lLLVMIRPrinter -lLLVMInterfaceStub -lLLVMFileCheck -lLLVMFuzzMutate \ +-lLLVMVectorize -lLLVMSandboxIR -lLLVMLinker -lLLVMInstrumentation -lLLVMFrontendOpenMP -lLLVMFrontendOffloading -lLLVMFrontendOpenACC -lLLVMFrontendHLSL -lLLVMFrontendDriver -lLLVMFrontendAtomic -lLLVMExtensions \ +-lLLVMDWARFLinkerParallel -lLLVMDWARFLinkerClassic -lLLVMDWARFLinker -lLLVMGlobalISel -lLLVMMIRParser -lLLVMAsmPrinter -lLLVMSelectionDAG \ +-lLLVMCodeGen -lLLVMTarget -lLLVMObjCARCOpts -lLLVMCodeGenTypes -lLLVMCGData -lLLVMIRPrinter -lLLVMInterfaceStub -lLLVMFileCheck -lLLVMFuzzMutate \ -lLLVMScalarOpts -lLLVMInstCombine -lLLVMAggressiveInstCombine -lLLVMTransformUtils -lLLVMBitWriter -lLLVMAnalysis \ --lLLVMProfileData -lLLVMSymbolize -lLLVMDebugInfoBTF -lLLVMDebugInfoPDB -lLLVMDebugInfoMSF -lLLVMDebugInfoDWARF -lLLVMObject -lLLVMTextAPI -lLLVMMCParser -lLLVMIRReader -lLLVMAsmParser -lLLVMMC -lLLVMDebugInfoCodeView \ +-lLLVMProfileData -lLLVMSymbolize -lLLVMDebugInfoBTF -lLLVMDebugInfoPDB -lLLVMDebugInfoMSF -lLLVMDebugInfoCodeView -lLLVMDebugInfoDWARF -lLLVMObject -lLLVMTextAPI -lLLVMMCParser -lLLVMIRReader -lLLVMAsmParser -lLLVMMC \ -lLLVMBitReader -lLLVMFuzzerCLI -lLLVMCore -lLLVMRemarks -lLLVMBitstreamReader -lLLVMBinaryFormat -lLLVMTargetParser -lLLVMTableGen -lLLVMSupport \ -lLLVMDemangle" shared_libs="-lLLVM-$version" diff --git a/.github/actions/5-install/action.yml b/.github/actions/5-install/action.yml index 6ab8f09c78..bf14b2ea15 100644 --- a/.github/actions/5-install/action.yml +++ b/.github/actions/5-install/action.yml @@ -66,6 +66,11 @@ runs: cp libcurl/ldc2/* installed/bin/ + if [[ '${{ inputs.arch }}' == arm64 ]]; then + echo "No MinGW-based libraries available for arm64 yet." + exit 0 + fi + curl -fL --retry 3 --max-time 60 -o mingw-w64-libs.7z \ https://github.com/ldc-developers/mingw-w64-libs/releases/download/v8.0.0/mingw-w64-libs-v8.0.0.7z mkdir mingw-w64-libs diff --git a/.github/actions/merge-windows/action.yml b/.github/actions/merge-windows/action.yml index d9a9a9f619..0bab4d697c 100644 --- a/.github/actions/merge-windows/action.yml +++ b/.github/actions/merge-windows/action.yml @@ -67,6 +67,7 @@ runs: set PATH=%CD%\ldc2-multilib\lib32;%PATH% ldc2-multilib\bin\ldc2 -link-defaultlib-shared -m32 -run hello.d || exit /b + # TODO # preliminary arm64 cross-compilation support - name: Install ninja v1.12.1 uses: Ahajha/gha-setup-ninja@69595b0cf872acdad8ce599142fbdc88724b9a2b diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 5b7838e875..8531b27f68 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -14,7 +14,7 @@ concurrency: cancel-in-progress: true env: - LLVM_VERSION: 19.1.7 + LLVM_VERSION: a905655f jobs: build-native: @@ -85,8 +85,8 @@ jobs: os: macos-14 arch: arm64 extra_cmake_flags: >- - -DCMAKE_C_COMPILER=/opt/homebrew/opt/llvm@19/bin/clang - -DCMAKE_CXX_COMPILER=/opt/homebrew/opt/llvm@19/bin/clang++ + -DCMAKE_C_COMPILER=/opt/homebrew/opt/llvm@20/bin/clang + -DCMAKE_CXX_COMPILER=/opt/homebrew/opt/llvm@20/bin/clang++ -DD_COMPILER_FLAGS="-O -flto=full -defaultlib=phobos2-ldc-lto,druntime-ldc-lto -L-exported_symbol '-L__*' -L-w" -DEXTRA_CXXFLAGS=-flto=full with_pgo: true @@ -101,6 +101,17 @@ jobs: -DEXTRA_CXXFLAGS=-flto=full with_pgo: true + - job_name: Windows arm64 + os: windows-11-arm + arch: arm64 + base_cmake_flags: >- + -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded + -DD_COMPILER_FLAGS=-link-internally + #extra_cmake_flags: >- + # "-DD_COMPILER_FLAGS=-O -flto=full -defaultlib=phobos2-ldc-lto,druntime-ldc-lto" + # -DEXTRA_CXXFLAGS=-flto=full + #with_pgo: true + - job_name: Windows x86 os: windows-2025 arch: x86 diff --git a/CMakeLists.txt b/CMakeLists.txt index 934700f58e..1a27a5b992 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -195,7 +195,10 @@ if(NOT MSVC_IDE) endif() if(MSVC) - if(CMAKE_SIZEOF_VOID_P EQUAL 8) + if($ENV{VSCMD_ARG_TGT_ARCH} STREQUAL "arm64") + message(STATUS "Let D host compiler output arm64 object files") + append("-mtriple=aarch64-windows-msvc" DFLAGS_BASE) + elseif(CMAKE_SIZEOF_VOID_P EQUAL 8) message(STATUS "Let D host compiler output 64-bit object files") append("-m64" DFLAGS_BASE) else() @@ -300,7 +303,9 @@ endif() if(MSVC) separate_arguments(LLVM_LDFLAGS WINDOWS_COMMAND "${LLVM_LDFLAGS}") if(NOT MSVC_IDE) # apparently not needed for VS (and spaces in path are problematic) - if(CMAKE_SIZEOF_VOID_P EQUAL 8) + if($ENV{VSCMD_ARG_TGT_ARCH} STREQUAL "arm64") + list(APPEND LLVM_LDFLAGS "$ENV{VSINSTALLDIR}DIA SDK\\lib\\arm64\\diaguids.lib") + elseif(CMAKE_SIZEOF_VOID_P EQUAL 8) list(APPEND LLVM_LDFLAGS "$ENV{VSINSTALLDIR}DIA SDK\\lib\\amd64\\diaguids.lib") else() list(APPEND LLVM_LDFLAGS "$ENV{VSINSTALLDIR}DIA SDK\\lib\\diaguids.lib") @@ -895,7 +900,9 @@ if (LDC_INSTALL_LLVM_RUNTIME_LIBS) copy_compilerrt_lib("libclang_rt.xray-profiling${compilerrt_suffix}.a" "libldc_rt.xray-profiling.a" FALSE) elseif(WIN32) set(compilerrt_arch_suffix "x86_64") - if(CMAKE_SIZEOF_VOID_P EQUAL 4) + if($ENV{VSCMD_ARG_TGT_ARCH} STREQUAL "arm64") + set(compilerrt_arch_suffix "aarch64") + elseif(CMAKE_SIZEOF_VOID_P EQUAL 4) set(compilerrt_arch_suffix "i386") endif() if(LDC_LLVM_VER LESS 2000) diff --git a/dmd/main.d b/dmd/main.d index 43c5a621df..2ebb78611c 100644 --- a/dmd/main.d +++ b/dmd/main.d @@ -442,8 +442,11 @@ else reconcileLinkRunLib(params, files.length, target.obj_ext); version(CRuntime_Microsoft) { - import dmd.root.longdouble; - initFPU(); + version(AArch64) { /* no longdouble_soft support on arm64 host */ } else + { + import dmd.root.longdouble; + initFPU(); + } } import dmd.root.ctfloat : CTFloat; CTFloat.initialize(); diff --git a/dmd/root/ctfloat.d b/dmd/root/ctfloat.d index 2996d7cd60..4c674f4ebd 100644 --- a/dmd/root/ctfloat.d +++ b/dmd/root/ctfloat.d @@ -27,13 +27,17 @@ private { version(CRuntime_DigitalMars) __gshared extern (C) extern const(char)* __locale_decpoint; - version(CRuntime_Microsoft) extern (C++) + version(CRuntime_Microsoft) { - public import dmd.root.longdouble : longdouble_soft, ld_sprint; + version(AArch64) { /* 64-bit real_t */ } else + { + version = MSVC_X87; + import dmd.root.longdouble : longdouble_soft, ld_sprint; version (IN_LLVM) {} else { - import dmd.root.strtold; + import dmd.root.strtold; } + } } } @@ -193,7 +197,7 @@ extern (C++) struct CTFloat // the implementation of longdouble for MSVC is a struct, so mangling // doesn't match with the C++ header. // add a wrapper just for isSNaN as this is the only function called from C++ - version(CRuntime_Microsoft) static if (is(real_t == real)) + version(MSVC_X87) static if (is(real_t == real)) pure @trusted static bool isSNaN(longdouble_soft ld) { @@ -239,7 +243,7 @@ extern (C++) struct CTFloat @system static int sprint(char* str, size_t size, char fmt, real_t x) { - version(CRuntime_Microsoft) + version(MSVC_X87) { auto len = cast(int) ld_sprint(str, size, fmt, longdouble_soft(x)); } diff --git a/dmd/root/longdouble.d b/dmd/root/longdouble.d index 0bbd27a39e..563e4c5036 100644 --- a/dmd/root/longdouble.d +++ b/dmd/root/longdouble.d @@ -13,7 +13,9 @@ module dmd.root.longdouble; version (CRuntime_Microsoft) { - static if (real.sizeof > 8) + version (AArch64) + alias longdouble = real; // 64-bit + else static if (real.sizeof > 8) alias longdouble = real; else alias longdouble = longdouble_soft; @@ -24,6 +26,7 @@ else // longdouble_soft needed when building the backend with // Visual C or the frontend with LDC on Windows version (CRuntime_Microsoft): +version (AArch64) { /* cannot use x87 inline asm on arm64 host */ } else: extern (C++): nothrow: @nogc: diff --git a/dmd/root/longdouble.h b/dmd/root/longdouble.h index 150b9f55e1..4a3db75422 100644 --- a/dmd/root/longdouble.h +++ b/dmd/root/longdouble.h @@ -11,7 +11,7 @@ #pragma once -#if !_MSC_VER // has native 10 byte doubles +#if !defined(_MSC_VER) || defined(_M_ARM64) #include typedef long double longdouble; typedef volatile long double volatile_longdouble; @@ -48,7 +48,7 @@ inline size_t ld_sprint(char* str, size_t size, int fmt, longdouble x) #undef snprintf #endif -#else +#else // defined(_MSC_VER) && !defined(_M_ARM64) #include #include @@ -264,4 +264,4 @@ typedef longdouble_soft longdouble; // is not required. typedef longdouble_soft volatile_longdouble; -#endif // !_MSC_VER +#endif // defined(_MSC_VER) && !defined(_M_ARM64) diff --git a/gen/ctfloat.cpp b/gen/ctfloat.cpp index ef033c018d..dd411277fa 100644 --- a/gen/ctfloat.cpp +++ b/gen/ctfloat.cpp @@ -42,8 +42,8 @@ void CTFloat::initialize() { if (apSemantics) return; -#ifdef _MSC_VER - // MSVC hosts use dmd.root.longdouble (80-bit x87) +#if defined(_MSC_VER) && !defined(_M_ARM64) + // MSVC x86[_64] hosts use dmd.root.longdouble (80-bit x87) apSemantics = &APFloat::x87DoubleExtended(); #else static_assert(std::numeric_limits::is_specialized,