[packages/ldc] up to 1.43.0
atler
atler at pld-linux.org
Tue Sep 1 12:08:46 CEST 2026
commit 3f7e934b5834dcfd38d80b7b5c9e31ef21e57449
Author: Jan Palus <atler at pld-linux.org>
Date: Tue Sep 1 12:08:26 2026 +0200
up to 1.43.0
git.patch | 10578 -----------------------------------------------
ldc-include-path.patch | 2 +-
ldc.spec | 24 +-
3 files changed, 12 insertions(+), 10592 deletions(-)
---
diff --git a/ldc.spec b/ldc.spec
index 9b1bc61..849eade 100644
--- a/ldc.spec
+++ b/ldc.spec
@@ -6,27 +6,26 @@
%bcond_without geany # geany autocompletion support
%bcond_with jit # dynamic compilation support (JIT) (LLVM 18/19 only)
-%define rel 3
+%define rel 1
-%define bootstrap_version 1.42.0
+%define bootstrap_version 1.43.0
Summary: LLVM D Compiler
Summary(pl.UTF-8): Kompilator D oparty na LLVM
Name: ldc
-Version: 1.42.0
+Version: 1.43.0
Release: %{rel}
# The DMD frontend in dmd/* GPL version 1 or artistic license
# The files gen/asmstmt.cpp and gen/asm-*.hG PL version 2+ or artistic license
License: BSD
Source0: https://github.com/ldc-developers/ldc/releases/download/v%{version}/%{name}-%{version}-src.tar.gz
-# Source0-md5: a18a249c2a3d487f79b831fef3d446b9
+# Source0-md5: a07371f8d988010e98eed3143367c1fe
Source1: https://github.com/ldc-developers/ldc/releases/download/v%{bootstrap_version}/%{name}2-%{bootstrap_version}-linux-x86_64.tar.xz
-# Source1-md5: 1b813099a0eaeff0b7353780c0b43c8a
+# Source1-md5: e02a0763e81134ffba110f39b48f0565
# for aarch64 bootstrap: https://github.com/ldc-developers/ldc/releases/download/v%{bootstrap_version}/ldc2-%{bootstrap_version}-linux-aarch64.tar.xz
Source3: macros.%{name}
Patch0: %{name}-include-path.patch
Patch1: %{name}-no-default-rpath.patch
Patch2: %{name}-dmd.patch
-Patch3: git.patch
URL: https://github.com/ldc-developers/ldc
# for llvm < 16
#BuildRequires: SPIRV-LLVM-Translator-devel
@@ -128,7 +127,6 @@ Obsługa automatycznego dopełniania dla biblioteki Phobos w IDE geany.
%patch -P0 -p1
%patch -P1 -p1
%patch -P2 -p1
-%patch -P3 -p1
%if %{with geany}
# temp geany config directory for allow geany to generate tags
@@ -257,21 +255,21 @@ rm -rf $RPM_BUILD_ROOT
%files druntime
%defattr(644,root,root,755)
%attr(755,root,root) %{_libdir}/libdruntime-ldc-debug-shared.so.*.*
-%ghost %{_libdir}/libdruntime-ldc-debug-shared.so.112
+%ghost %{_libdir}/libdruntime-ldc-debug-shared.so.113
%attr(755,root,root) %{_libdir}/libdruntime-ldc-shared.so.*.*
-%ghost %{_libdir}/libdruntime-ldc-shared.so.112
+%ghost %{_libdir}/libdruntime-ldc-shared.so.113
%if %{with jit}
-%attr(755,root,root) %{_libdir}/libldc-jit.so.112.0
-%ghost %{_libdir}/libldc-jit.so.112
+%attr(755,root,root) %{_libdir}/libldc-jit.so.113.0
+%ghost %{_libdir}/libldc-jit.so.113
%endif
%files phobos
%defattr(644,root,root,755)
%doc runtime/phobos/{LICENSE_1_0.txt,README.md}
%attr(755,root,root) %{_libdir}/libphobos2-ldc-debug-shared.so.*.*
-%ghost %{_libdir}/libphobos2-ldc-debug-shared.so.112
+%ghost %{_libdir}/libphobos2-ldc-debug-shared.so.113
%attr(755,root,root) %{_libdir}/libphobos2-ldc-shared.so.*.*
-%ghost %{_libdir}/libphobos2-ldc-shared.so.112
+%ghost %{_libdir}/libphobos2-ldc-shared.so.113
%if %{with geany}
%files phobos-geany-tags
diff --git a/git.patch b/git.patch
deleted file mode 100644
index 5675698..0000000
--- a/git.patch
+++ /dev/null
@@ -1,10578 +0,0 @@
-diff --git a/CHANGELOG.md b/CHANGELOG.md
-index 647eb518f6..d9f19defa1 100644
---- a/CHANGELOG.md
-+++ b/CHANGELOG.md
-@@ -1,8 +1,13 @@
- # LDC master
-
- #### Big news
-+- Support for [LLVM 22](https://releases.llvm.org/22.1.0/docs/ReleaseNotes.html). The prebuilt packages use v22.1.2. (#5097, #5102)
-+- Minimum LLVM version raised to 18. (#5094)
-+- DMD-style inline assembly: `asm { naked; }` is now much less of a special case wrt. codegen - such naked functions are now emitted as if `asm { naked; }` was replaced with the `@naked` function UDA. IR-wise, they are not emitted as module-level asm blobs anymore, but regular IR functions. This should lift a few former `asm { naked; }`-specific restrictions and fixed at least one LTO issue. (#5041)
-+- Predefined version `LDC_LLVM_*` now only contains the LLVM major version, i.e., former `version (LDC_LLVM_1801)` with LLVM v18.1 is now `version (LDC_LLVM_18)`. Use `ldc.intrinsics.LLVM_version` for backwards compatibility if really needed. (#5109)
-
- #### Platform support
-+- Supports LLVM 18 - 22.
-
- #### Bug fixes
-
-diff --git a/CMakeLists.txt b/CMakeLists.txt
-index 81ca3effa7..83584dcae8 100644
---- a/CMakeLists.txt
-+++ b/CMakeLists.txt
-@@ -29,14 +29,13 @@ include(BuildDExecutable)
- # Locate LLVM.
- #
-
--find_package(LLVM 15.0 REQUIRED
-+find_package(LLVM 18.0 REQUIRED
- all-targets analysis asmparser asmprinter bitreader bitwriter codegen core
- debuginfodwarf debuginfomsf debuginfopdb demangle
- instcombine ipo instrumentation irreader libdriver linker lto mc
- mcdisassembler mcparser objcarcopts object option profiledata scalaropts
- selectiondag support tablegen target transformutils vectorize
- windowsdriver windowsmanifest symbolize ${EXTRA_LLVM_MODULES})
--math(EXPR LDC_LLVM_VER ${LLVM_VERSION_MAJOR}*100+${LLVM_VERSION_MINOR})
- message(STATUS "Using LLVM Version ${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}")
- # Remove LLVMTableGen library from list of libraries
- string(REGEX MATCH "[^;]*LLVMTableGen[^;]*" LLVM_TABLEGEN_LIBRARY "${LLVM_LIBRARIES}")
-@@ -49,7 +48,7 @@ endforeach()
-
- # Set MLIR support variables if it is found.
- # FIXME: LLVM 14+ (`mlir::OwningModuleRef` replacement)
--if(NOT LDC_WITH_MLIR STREQUAL "OFF" AND LDC_LLVM_VER LESS 1400)
-+if(NOT LDC_WITH_MLIR STREQUAL "OFF" AND LLVM_VERSION_MAJOR LESS 14)
- include(FindMLIR)
- if(MLIR_FOUND)
- message(STATUS "-- Building LDC with MLIR support (${MLIR_ROOT_DIR})")
-@@ -61,46 +60,6 @@ if(NOT LDC_WITH_MLIR STREQUAL "OFF" AND LDC_LLVM_VER LESS 1400)
- endif()
- endif()
-
--# Check and adapt for LLVMSPIRVLib (Khronos SPIRV-LLVM-Translator)
--set(LLVM_SPIRV_FOUND OFF)
--if (LDC_LLVM_VER LESS 1600)
--if(MSVC)
-- if(EXISTS "${LLVM_LIBRARY_DIRS}/LLVMSPIRVLib.lib")
-- set(LLVM_SPIRV_FOUND ON)
-- set(LLVM_LIBRARIES "${LLVM_LIBRARY_DIRS}/LLVMSPIRVLib.lib" ${LLVM_LIBRARIES})
-- endif()
--else()
-- if((EXISTS "${LLVM_LIBRARY_DIRS}/libLLVMSPIRVLib.a") OR
-- (EXISTS "${LLVM_LIBRARY_DIRS}/libLLVMSPIRVLib.so") OR
-- (EXISTS "${LLVM_LIBRARY_DIRS}/libLLVMSPIRVLib.dylib"))
-- set(LLVM_SPIRV_FOUND ON)
-- set(LLVM_LIBRARIES -lLLVMSPIRVLib ${LLVM_LIBRARIES})
-- endif()
--endif()
--if(NOT LLVM_SPIRV_FOUND)
-- find_package(PkgConfig)
-- if(PkgConfig_FOUND)
-- if(MSVC)
-- # make pkg-config use -LC:\path\to\build\LLVMSPIRVLib.lib not -L-lLLVMSPIRVLib
-- set(PKG_CONFIG_EXECUTABLE "${PKG_CONFIG_EXECUTABLE} --msvc-syntax")
-- endif()
-- pkg_check_modules(LLVM_SPIRV LLVMSPIRVLib)
-- if(LLVM_SPIRV_FOUND)
-- set(LLVM_SPIRV_FOUND ON) # translate 1 to ON
-- include_directories(${LLVM_SPIRV_INCLUDE_DIRS})
-- else()
-- set(LLVM_SPIRV_FOUND OFF)
-- endif()
-- endif()
--endif()
--if(LLVM_SPIRV_FOUND)
-- message(STATUS "-- Building LDC with SPIR-V support")
-- add_definitions("-DLDC_LLVM_SUPPORTED_TARGET_SPIRV=1")
--else()
-- message(STATUS "-- Building LDC without SPIR-V support: not found")
--endif()
--endif()
--
- #
- # Get info about used Linux distribution.
- #
-@@ -137,6 +96,9 @@ set(ALTERNATIVE_MALLOC_O "" CACHE STRING "If specified, adds ALTERNATIVE_M
- # Most linux distributions have a policy of not bundling dependencies like zlib
- set(PHOBOS_SYSTEM_ZLIB OFF CACHE BOOL "Use system zlib instead of Phobos' vendored version")
-
-+# Force use of softfloat for compiler
-+option(LDC_FORCE_SOFTFLOAT_REAL "Force LDC to be built with 80-bit real in software" OFF)
-+
- if(D_VERSION EQUAL 1)
- message(FATAL_ERROR "D version 1 is no longer supported.
- Please consider using D version 2 or checkout the 'd1' git branch for the last version supporting D version 1.")
-@@ -175,6 +137,7 @@ if(NOT MSVC_IDE)
- endif()
-
- if(MSVC)
-+ set(LDC_FORCE_SOFTFLOAT_REAL ON)
- if(CMAKE_SIZEOF_VOID_P EQUAL 8)
- message(STATUS "Let D host compiler output 64-bit object files")
- append("-m64" DFLAGS_BASE)
-@@ -206,6 +169,11 @@ if(MSVC)
- endforeach()
- endif()
-
-+if (LDC_FORCE_SOFTFLOAT_REAL)
-+ append("-version=LDC_real_softfloat" DFLAGS_LDC)
-+ append("-DLDC_real_softfloat" LDC_CXXFLAGS)
-+endif()
-+
- # Use separate compiler flags for the frontend and for the LDC-specific parts,
- # as enabling warnings on the DMD frontend only leads to a lot of clutter in
- # the output (LLVM_CXXFLAGS sometimes already includes -Wall).
-@@ -435,10 +403,8 @@ include(HandleLTOPGOBuildOptions)
- set(LDC_DYNAMIC_COMPILE "AUTO" CACHE STRING "Support dynamic compilation (ON|OFF). Enabled by default; not supported for LLVM < 18.")
- option(LDC_DYNAMIC_COMPILE_USE_CUSTOM_PASSES "Use custom LDC passes in jit" ON)
- if(LDC_DYNAMIC_COMPILE STREQUAL "AUTO")
-- if(LDC_LLVM_VER LESS 1800)
-- set(LDC_DYNAMIC_COMPILE OFF)
- # FIXME: dynamic-compile regressions with LLVM 20
-- elseif(LDC_LLVM_VER LESS 2000)
-+ if(LLVM_VERSION_MAJOR LESS 20)
- set(LDC_DYNAMIC_COMPILE ON)
- else()
- set(LDC_DYNAMIC_COMPILE OFF)
-@@ -475,13 +441,11 @@ append("-J${PROJECT_SOURCE_DIR}/dmd/res" DFLAGS_LDC)
-
- append("-version=IN_LLVM" DFLAGS_LDC)
- append("-DIN_LLVM" LDC_CXXFLAGS)
--append("-DOPAQUE_VTBLS" LDC_CXXFLAGS)
- # Predefine LDC_INSTALL_PREFIX as raw string literal, requiring shell + CMake escaping.
- # E.g., for CMAKE_INSTALL_PREFIX=`C:\dir with space`:
- # g++ "-DLDC_INSTALL_PREFIX=R\"(C:\dir with space)\"" ...
- # => LDC_INSTALL_PREFIX defined as `R"(C:\dir with space)"`
- append("\"-DLDC_INSTALL_PREFIX=R\\\"(${CMAKE_INSTALL_PREFIX})\\\"\"" LDC_CXXFLAGS)
--append("-DLDC_LLVM_VER=${LDC_LLVM_VER}" LDC_CXXFLAGS)
- append("\"-DLDC_LIBDIR_SUFFIX=R\\\"(${LIB_SUFFIX})\\\"\"" LDC_CXXFLAGS)
- append("-DLDC_HOST_${D_COMPILER_ID}=1" LDC_CXXFLAGS)
- append("-DLDC_HOST_FE_VER=${D_COMPILER_FE_VERSION}" LDC_CXXFLAGS)
-@@ -580,9 +544,6 @@ if(WIN32)
- elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
- target_link_libraries(${LDC_LIB} dl)
- endif()
--if(LLVM_SPIRV_FOUND)
-- target_link_libraries(${LDC_LIB} ${LLVM_SPIRV_LIBRARIES} ${LLVM_SPIRV_LDFLAGS})
--endif()
-
- set(LDC_EXE_FULL ${PROJECT_BINARY_DIR}/bin/${LDC_EXE_NAME}${CMAKE_EXECUTABLE_SUFFIX})
- set(LDMD_EXE_FULL ${PROJECT_BINARY_DIR}/bin/${LDMD_EXE_NAME}${CMAKE_EXECUTABLE_SUFFIX})
-@@ -601,19 +562,17 @@ if(MSVC)
- endif()
- endif()
- if(LDC_WITH_LLD)
-- if(MSVC)
-- list(APPEND LDC_LINKERFLAG_LIST LLVMSymbolize.lib)
-- else()
-- set(LDC_LINKERFLAG_LIST -lLLVMSymbolize ${LDC_LINKERFLAG_LIST})
-+ if(LLVM_VERSION_MAJOR GREATER 21)
-+ if(MSVC)
-+ list(APPEND LDC_LINKERFLAG_LIST LLVMDTLTO.lib)
-+ else()
-+ set(LDC_LINKERFLAG_LIST -lLLVMDTLTO ${LDC_LINKERFLAG_LIST})
-+ endif()
- endif()
- if(MSVC)
-- list(APPEND LDC_LINKERFLAG_LIST lldMinGW.lib lldCOFF.lib lldELF.lib lldMachO.lib lldWasm.lib lldCommon.lib)
-+ list(APPEND LDC_LINKERFLAG_LIST lldMinGW.lib lldCOFF.lib lldELF.lib lldMachO.lib lldWasm.lib lldCommon.lib LLVMSymbolize.lib)
- else()
-- set(LDC_LINKERFLAG_LIST -llldMinGW -llldCOFF -llldELF -llldMachO -llldWasm -llldCommon ${LDC_LINKERFLAG_LIST})
-- endif()
-- if(APPLE)
-- # LLD 13.0.0 on Mac needs libxar
-- list(APPEND LDC_LINKERFLAG_LIST -lxar)
-+ set(LDC_LINKERFLAG_LIST -llldMinGW -llldCOFF -llldELF -llldMachO -llldWasm -llldCommon -lLLVMSymbolize ${LDC_LINKERFLAG_LIST})
- endif()
- if(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
- # FreeBSD LLVM port links to zstd, but does not convey this information via CMake
-@@ -799,11 +758,7 @@ endif()
- # another directory.
- set(COMPILER_RT_BASE_DIR "${LLVM_LIBRARY_DIRS}/clang" CACHE PATH "Base path of compiler-rt libraries. If they in are /usr/lib/clang/17/lib/linux/libclang_rt* you should set this value to /usr/lib/clang")
- set(COMPILER_RT_LIBDIR "${COMPILER_RT_BASE_DIR}")
--if(LDC_LLVM_VER LESS 1600)
-- set(COMPILER_RT_LIBDIR "${COMPILER_RT_LIBDIR}/${LLVM_VERSION_BASE_STRING}")
--else()
-- set(COMPILER_RT_LIBDIR "${COMPILER_RT_LIBDIR}/${LLVM_VERSION_MAJOR}")
--endif()
-+set(COMPILER_RT_LIBDIR "${COMPILER_RT_LIBDIR}/${LLVM_VERSION_MAJOR}")
- set(COMPILER_RT_LIBDIR "${COMPILER_RT_LIBDIR}/lib")
- if(APPLE)
- set(COMPILER_RT_LIBDIR "${COMPILER_RT_LIBDIR}/darwin")
-@@ -881,7 +836,7 @@ if (LDC_INSTALL_LLVM_RUNTIME_LIBS)
- if(CMAKE_SIZEOF_VOID_P EQUAL 4)
- set(compilerrt_arch_suffix "i386")
- endif()
-- if(LDC_LLVM_VER LESS 2000)
-+ if(LLVM_VERSION_MAJOR LESS 20)
- copy_compilerrt_lib("clang_rt.asan-${compilerrt_arch_suffix}.lib" "ldc_rt.asan.lib" FALSE)
- copy_compilerrt_lib("clang_rt.lsan-${compilerrt_arch_suffix}.lib" "ldc_rt.lsan.lib" FALSE)
- else()
-@@ -956,12 +911,6 @@ add_subdirectory(tools)
-
- set(switches)
-
--# LLVM 16: Disable function specializations by default.
--# They cause miscompiles of e.g. the frontend for some targets (macOS x86_64 and Windows x64).
--if(LDC_LLVM_VER GREATER 1599 AND LDC_LLVM_VER LESS 1700)
-- list(APPEND switches "-func-specialization-size-threshold=1000000000")
--endif()
--
- list(APPEND switches "-defaultlib=phobos2-ldc,druntime-ldc")
-
- makeConfSection(NAME "30-compiler" SECTION "default"
-diff --git a/README.md b/README.md
-index 9d8b8e568b..5076bf12f7 100644
---- a/README.md
-+++ b/README.md
-@@ -75,7 +75,7 @@ libraries is available on the project wiki for
- [Windows](https://wiki.dlang.org/Building_and_hacking_LDC_on_Windows_using_MSVC).
-
- If you have a working C++/D build environment, CMake, and a recent LLVM
--version (≥ 15) available, there should be no big surprises. Do not
-+version (≥ 18) available, there should be no big surprises. Do not
- forget to make sure the Phobos submodule is up to date:
-
- $ cd ldc
-diff --git a/cmake/Modules/FindLLVM.cmake b/cmake/Modules/FindLLVM.cmake
-index 75fa1eee29..018011e8d0 100644
---- a/cmake/Modules/FindLLVM.cmake
-+++ b/cmake/Modules/FindLLVM.cmake
-@@ -36,9 +36,6 @@ set(llvm_config_names llvm-config-21.1 llvm-config211 llvm-config-21
- llvm-config-20.1 llvm-config201 llvm-config-20
- llvm-config-19.1 llvm-config191 llvm-config-19
- llvm-config-18.1 llvm-config181 llvm-config-18
-- llvm-config-17.0 llvm-config170 llvm-config-17
-- llvm-config-16.0 llvm-config160 llvm-config-16
-- llvm-config-15.0 llvm-config150 llvm-config-15
- llvm-config)
- find_program(LLVM_CONFIG
- NAMES ${llvm_config_names}
-@@ -51,14 +48,10 @@ if(APPLE)
- NAMES ${llvm_config_names}
- PATHS /opt/local/libexec/llvm-21/bin
- /opt/local/libexec/llvm-20/bin /opt/local/libexec/llvm-19/bin
-- /opt/local/libexec/llvm-18/bin /opt/local/libexec/llvm-17/bin
-- /opt/local/libexec/llvm-16/bin /opt/local/libexec/llvm-15/bin
-- /opt/local/libexec/llvm/bin
-+ /opt/local/libexec/llvm-18/bin /opt/local/libexec/llvm/bin
- /usr/local/opt/llvm at 21/bin
- /usr/local/opt/llvm at 20/bin /usr/local/opt/llvm at 19/bin
-- /usr/local/opt/llvm at 18/bin /usr/local/opt/llvm at 17/bin
-- /usr/local/opt/llvm at 16/bin /usr/local/opt/llvm at 15/bin
-- /usr/local/opt/llvm/bin
-+ /usr/local/opt/llvm at 18/bin /usr/local/opt/llvm/bin
- NO_DEFAULT_PATH)
- endif()
-
-diff --git a/dmd/declaration.h b/dmd/declaration.h
-index 7533348374..5c4562aab9 100644
---- a/dmd/declaration.h
-+++ b/dmd/declaration.h
-@@ -581,6 +581,9 @@ public:
- VarDeclaration *v_argptr; // '_argptr' variable
- VarDeclarations *parameters; // Array of VarDeclaration's for parameters
- DsymbolTable *labtab; // statement label symbol table
-+#if IN_LLVM
-+ Identifiers *asmLabels; // identifiers of labels defined in DMD-style inline assembly
-+#endif
- Dsymbol *overnext; // next in overload list
- FuncDeclaration *overnext0; // next in overload list (only used during IFTI)
- Loc endloc; // location of closing curly bracket
-diff --git a/dmd/func.d b/dmd/func.d
-index 6709e32ebb..e39e233eae 100644
---- a/dmd/func.d
-+++ b/dmd/func.d
-@@ -256,6 +256,10 @@ version (IN_LLVM)
- VarDeclaration v_argptr; /// '_argptr' variable
- VarDeclarations* parameters; /// Array of VarDeclaration's for parameters
- DsymbolTable labtab; /// statement label symbol table
-+version (IN_LLVM)
-+{
-+ Identifiers* asmLabels; /// identifiers of labels defined in DMD-style inline assembly
-+}
- Dsymbol overnext; /// next in overload list
- FuncDeclaration overnext0; /// next in overload list (only used during IFTI)
- Loc endloc; /// location of closing curly bracket
-diff --git a/dmd/globals.h b/dmd/globals.h
-index 9d4bf185a5..bad8e9c410 100644
---- a/dmd/globals.h
-+++ b/dmd/globals.h
-@@ -17,11 +17,7 @@
- #include "compiler.h"
-
- #if IN_LLVM
--#if LDC_LLVM_VER < 1700
--#include "llvm/ADT/Triple.h"
--#else
- #include "llvm/TargetParser/Triple.h"
--#endif
-
- enum OUTPUTFLAG
- {
-diff --git a/dmd/root/ctfloat.d b/dmd/root/ctfloat.d
-index 2996d7cd60..2ca9e20527 100644
---- a/dmd/root/ctfloat.d
-+++ b/dmd/root/ctfloat.d
-@@ -47,7 +47,8 @@ extern (C++) struct CTFloat
- version (GNU)
- enum yl2x_supported = false;
- else
-- enum yl2x_supported = __traits(compiles, core.math.yl2x(1.0L, 2.0L));
-+ enum yl2x_supported = is(real_t == real) &&
-+ __traits(compiles, core.math.yl2x(1.0L, 2.0L));
- enum yl2xp1_supported = yl2x_supported;
-
- static void yl2x(const real_t* x, const real_t* y, real_t* res) // IN_LLVM: impure because of log2
-diff --git a/dmd/root/longdouble.d b/dmd/root/longdouble.d
-index 0bbd27a39e..9da7f09e06 100644
---- a/dmd/root/longdouble.d
-+++ b/dmd/root/longdouble.d
-@@ -11,8 +11,14 @@
-
- module dmd.root.longdouble;
-
--version (CRuntime_Microsoft)
-+version (LDC_real_softfloat)
- {
-+ version = EnableSoftfloat;
-+ alias longdouble = longdouble_soft;
-+}
-+else version (CRuntime_Microsoft)
-+{
-+ version = EnableSoftfloat;
- static if (real.sizeof > 8)
- alias longdouble = real;
- else
-@@ -23,7 +29,7 @@ else
-
- // longdouble_soft needed when building the backend with
- // Visual C or the frontend with LDC on Windows
--version (CRuntime_Microsoft):
-+version (EnableSoftfloat):
- extern (C++):
- nothrow:
- @nogc:
-@@ -71,7 +77,7 @@ bool initFPU()
- return true;
- }
-
--version(unittest) version(CRuntime_Microsoft)
-+version(unittest)
- extern(D) shared static this()
- {
- initFPU(); // otherwise not guaranteed to be run before pure unittest below
-diff --git a/dmd/root/longdouble.h b/dmd/root/longdouble.h
-index 150b9f55e1..251be1d0f3 100644
---- a/dmd/root/longdouble.h
-+++ b/dmd/root/longdouble.h
-@@ -11,7 +11,13 @@
-
- #pragma once
-
--#if !_MSC_VER // has native 10 byte doubles
-+#if defined(LDC_real_softfloat)
-+#define USE_LONGDOUBLE_SOFTFLOAT 1
-+#elif defined(_MSC_VER)
-+#define USE_LONGDOUBLE_SOFTFLOAT 1
-+#endif
-+
-+#if !USE_LONGDOUBLE_SOFTFLOAT // has native 10 byte doubles
- #include <stdio.h>
- typedef long double longdouble;
- typedef volatile long double volatile_longdouble;
-diff --git a/dmd/statementsem.d b/dmd/statementsem.d
-index 987979bb88..a5be77972f 100644
---- a/dmd/statementsem.d
-+++ b/dmd/statementsem.d
-@@ -3695,6 +3695,13 @@ version (IN_LLVM)
- if (auto ls = s.isLabelStatement())
- {
- sc.func.searchLabel(ls.ident, ls.loc);
-+
-+version (IN_LLVM)
-+{
-+ if (!sc.func.asmLabels)
-+ sc.func.asmLabels = new Identifiers();
-+ sc.func.asmLabels.push(ls.ident);
-+}
- }
- }
- }
-diff --git a/driver/archiver.cpp b/driver/archiver.cpp
-index 14c91d810c..15725a947d 100644
---- a/driver/archiver.cpp
-+++ b/driver/archiver.cpp
-@@ -14,13 +14,8 @@
- #include "driver/cl_options.h"
- #include "driver/tool.h"
- #include "gen/logger.h"
--#if LDC_LLVM_VER < 1700
--#include "llvm/ADT/Triple.h"
--#include "llvm/Support/Host.h"
--#else
- #include "llvm/TargetParser/Host.h"
- #include "llvm/TargetParser/Triple.h"
--#endif
- #include "llvm/Object/Archive.h"
- #include "llvm/Object/ArchiveWriter.h"
- #include "llvm/Object/MachO.h"
-@@ -45,11 +40,7 @@ namespace llvm_ar {
- StringRef ArchiveName;
- std::vector<const char *> Members;
-
--#if LDC_LLVM_VER < 1800
--bool Symtab = true;
--#else
- llvm::SymtabWritingMode Symtab = llvm::SymtabWritingMode::NormalSymtab;
--#endif
- bool Deterministic = true;
- bool Thin = false;
-
-diff --git a/driver/args.cpp b/driver/args.cpp
-index 2485dab7dd..2ce4210a12 100644
---- a/driver/args.cpp
-+++ b/driver/args.cpp
-@@ -170,11 +170,7 @@ int executeAndWait(std::vector<const char *> fullArgs,
- }
-
- const std::vector<llvm::StringRef> argv = toRefsVector(fullArgs);
--#if LDC_LLVM_VER < 1600
-- auto envVars = llvm::None;
--#else
- auto envVars = std::nullopt;
--#endif
-
- return llvm::sys::ExecuteAndWait(argv[0], argv, envVars, {}, 0, 0, errorMsg);
- }
-diff --git a/driver/cache.cpp b/driver/cache.cpp
-index 9e9278847d..2556ef2422 100644
---- a/driver/cache.cpp
-+++ b/driver/cache.cpp
-@@ -309,30 +309,14 @@ void outputIR2ObjRelevantCmdlineArgs(llvm::raw_ostream &hash_os) {
- hash_os << opts::getFeaturesStr();
- hash_os << opts::floatABI;
- const auto relocModel = opts::getRelocModel();
--#if LDC_LLVM_VER >= 1600
- if (relocModel.has_value())
- hash_os << relocModel.value();
--#else
-- if (relocModel.hasValue())
-- hash_os << relocModel.getValue();
--#endif
- const auto codeModel = opts::getCodeModel();
--#if LDC_LLVM_VER >= 1600
- if (codeModel.has_value())
- hash_os << codeModel.value();
--#else
-- if (codeModel.hasValue())
-- hash_os << codeModel.getValue();
--#endif
--
- const auto framePointerUsage = opts::framePointerUsage();
--#if LDC_LLVM_VER >= 1600
- if (framePointerUsage.has_value())
- hash_os << static_cast<int>(framePointerUsage.value());
--#else
-- if (framePointerUsage.hasValue())
-- hash_os << static_cast<int>(framePointerUsage.getValue());
--#endif
- }
-
- // Output to `hash_os` all environment flags that influence object code output
-diff --git a/driver/cl_options-llvm.cpp b/driver/cl_options-llvm.cpp
-index 036e0bfa4f..168fab6adb 100644
---- a/driver/cl_options-llvm.cpp
-+++ b/driver/cl_options-llvm.cpp
-@@ -10,12 +10,8 @@
- #include "driver/cl_options-llvm.h"
-
- #if LDC_WITH_LLD
--#if LDC_LLVM_VER < 1700
--#include "llvm/ADT/Triple.h"
--#else
- #include "llvm/TargetParser/Triple.h"
- #endif
--#endif
-
- // Pull in command-line options and helper functions from special LLVM header
- // shared by multiple LLVM tools.
-@@ -35,17 +31,17 @@ std::string getArchStr() {
- return codegen::getMArch();
- }
-
--Optional<Reloc::Model> getRelocModel() {
-+std::optional<Reloc::Model> getRelocModel() {
- return codegen::getExplicitRelocModel();
- }
-
--Optional<CodeModel::Model> getCodeModel() {
-+std::optional<CodeModel::Model> getCodeModel() {
- return codegen::getExplicitCodeModel();
- }
-
- using FPK = llvm::FramePointerKind;
-
--llvm::Optional<FPK> framePointerUsage() {
-+std::optional<FPK> framePointerUsage() {
- // Defaults to `FP::None`; no way to check if set explicitly by user except
- // indirectly via setFunctionAttributes()...
- return codegen::getFramePointerUsage();
-@@ -89,11 +85,11 @@ TargetOptions initTargetOptionsFromCodeGenFlags() {
- return ::opts::InitTargetOptionsFromCodeGenFlags(llvm::Triple());
- }
-
--Optional<Reloc::Model> getRelocModelFromCMModel() {
-+std::optional<Reloc::Model> getRelocModelFromCMModel() {
- return ::opts::getRelocModel();
- }
-
--Optional<CodeModel::Model> getCodeModelFromCMModel() {
-+std::optional<CodeModel::Model> getCodeModelFromCMModel() {
- return ::opts::getCodeModel();
- }
-
-diff --git a/driver/cl_options-llvm.h b/driver/cl_options-llvm.h
-index 2f39b2401a..69b54359dc 100644
---- a/driver/cl_options-llvm.h
-+++ b/driver/cl_options-llvm.h
-@@ -9,17 +9,10 @@
-
- #pragma once
-
--#if LDC_LLVM_VER < 1700
--#include "llvm/ADT/Optional.h"
--#else
--#include <optional>
--namespace llvm {
--template <typename T> using Optional = std::optional<T>;
--}
--#endif
- #include "llvm/Support/CommandLine.h"
- #include "llvm/Support/CodeGen.h"
- #include "llvm/Target/TargetOptions.h"
-+#include <optional>
-
- namespace llvm {
- class Function;
-@@ -29,9 +22,9 @@ class Triple;
- namespace opts {
-
- std::string getArchStr();
--llvm::Optional<llvm::Reloc::Model> getRelocModel();
--llvm::Optional<llvm::CodeModel::Model> getCodeModel();
--llvm::Optional<llvm::FramePointerKind> framePointerUsage();
-+std::optional<llvm::Reloc::Model> getRelocModel();
-+std::optional<llvm::CodeModel::Model> getCodeModel();
-+std::optional<llvm::FramePointerKind> framePointerUsage();
-
- bool disableRedZone();
- bool printTargetFeaturesHelp();
-diff --git a/driver/cl_options.cpp b/driver/cl_options.cpp
-index 5b155a6797..c101cf199c 100644
---- a/driver/cl_options.cpp
-+++ b/driver/cl_options.cpp
-@@ -20,6 +20,12 @@ namespace opts {
- // This vector is filled by parseCommandLine in main.cpp.
- llvm::SmallVector<const char *, 32> allArguments;
-
-+cl::opt<bool> noBuiltIn(
-+ "fno-builtin",
-+ cl::desc("Disable implicit builtin knowledge of functions"),
-+ cl::ZeroOrMore
-+);
-+
- cl::OptionCategory linkingCategory("Linking options");
-
- // Positional options first, in order:
-@@ -577,7 +583,7 @@ llvm::FastMathFlags defaultFMF;
- void setDefaultMathOptions(llvm::TargetOptions &targetOptions) {
- if (fFastMath) {
- defaultFMF.setFast();
--#if LDC_LLVM_VER < 2200
-+#if LLVM_VERSION_MAJOR < 22
- targetOptions.UnsafeFPMath = true;
- #endif
- }
-@@ -788,12 +794,15 @@ static cl::extrahelp
- /// The clashing LLVM options are suffixed with "llvm-" and hidden from the
- /// -help output.
- void createClashingOptions() {
-- llvm::StringMap<cl::Option *> &map = cl::getRegisteredOptions();
--
-+ auto &map = cl::getRegisteredOptions();
- auto renameAndHide = [&map](const char *from, const char *to) {
- auto i = map.find(from);
- if (i != map.end()) {
-+#if LLVM_VERSION_MAJOR >= 22
-+ cl::Option *opt = i->second;
-+#else
- cl::Option *opt = i->getValue();
-+#endif
- map.erase(i);
- if (to) {
- opt->setArgStr(to);
-@@ -847,7 +856,8 @@ void hideLLVMOptions() {
- "amdgpu-enable-global-sgpr-addr", "amdgpu-enable-merge-m0",
- "amdgpu-enable-power-sched", "amdgpu-igrouplp",
- "amdgpu-indirect-call-specialization-threshold",
-- "amdgpu-kernarg-preload-count", "amdgpu-module-splitting-max-depth",
-+ "amdgpu-kernarg-preload", "amdgpu-kernarg-preload-count",
-+ "amdgpu-module-splitting-max-depth",
- "amdgpu-promote-alloca-to-vector-limit",
- "amdgpu-promote-alloca-to-vector-max-regs",
- "amdgpu-promote-alloca-to-vector-vgpr-ratio",
-@@ -857,9 +867,11 @@ void hideLLVMOptions() {
- "argext-abi-check", "arm-add-build-attributes",
- "arm-implicit-it", "asm-instrumentation", "asm-show-inst",
- "atomic-counter-update-promoted", "atomic-first-counter",
-- "basic-block-address-map", "basic-block-sections",
-+ "basic-block-address-map", "basic-block-section-match-infer",
-+ "basic-block-sections",
- "basicblock-sections", "bounds-checking-single-trap",
-- "bounds-checking-unique-traps", "bpf-stack-size", "cfg-hide-cold-paths",
-+ "bounds-checking-unique-traps", "bpf-stack-size",
-+ "call-graph-section", "cfg-hide-cold-paths",
- "cfg-hide-deoptimize-paths", "cfg-hide-unreachable-paths",
- "check-functions-filter", "code-model", "conditional-counter-update",
- "cost-kind", "cppfname", "cppfor", "cppgen", "crel",
-@@ -867,18 +879,21 @@ void hideLLVMOptions() {
- "cvp-dont-process-adds", "debug-counter", "debug-entry-values",
- "debugger-tune", "debugify-atoms", "debugify-func-limit",
- "debugify-level", "debugify-quiet", "debug-info-correlate",
-- "denormal-fp-math", "denormal-fp-math-f32",
-+ "denormal-fp-math", "denormal-fp-math-f32", "devirtualize-speculatively",
- "disable-auto-upgrade-debug-info", "disable-debug-info-verifier",
- "disable-i2p-p2i-opt",
- "disable-objc-arc-checkforcfghazards", "disable-promote-alloca-to-lds",
-- "disable-promote-alloca-to-vector", "disable-slp-vectorization",
-+ "disable-promote-alloca-to-vector", "disable-qfp-opt",
-+ "disable-qfp-opt-mul", "disable-slp-vectorization",
- "disable-spill-fusing",
-- "do-counter-promotion", "dot-cfg-mssa", "dwarf64", "emit-call-site-info",
-+ "do-counter-promotion", "dot-cfg-mssa", "dwarf64",
-+ "elide-all-zero-branch-weights", "emit-bb-hash", "emit-call-site-info",
- "emit-compact-unwind-non-canonical", "emit-dwarf-unwind",
- "emit-gnuas-syntax-on-zos", "emscripten-cxx-exceptions-allowed",
- "emscripten-cxx-exceptions-whitelist",
- "emulated-tls", "enable-approx-func-fp-math", "enable-correct-eh-support",
- "enable-cse-in-irtranslator", "enable-cse-in-legalizer",
-+ "enable-devirtualize-speculatively",
- "enable-emscripten-cxx-exceptions", "enable-emscripten-sjlj",
- "enable-fp-mad", "enable-gvn-hoist", "enable-gvn-memdep",
- "enable-gvn-memoryssa",
-@@ -889,7 +904,8 @@ void hideLLVMOptions() {
- "enable-no-nans-fp-math", "enable-no-signed-zeros-fp-math",
- "enable-no-trapping-fp-math", "enable-objc-arc-annotations",
- "enable-objc-arc-opts", "enable-pgo-force-function-attrs",
-- "enable-pie", "enable-scoped-noalias",
-+ "enable-pie", "enable-poison-reuse-guard",
-+ "enable-scoped-noalias",
- "enable-split-backedge-in-load-pre", "enable-split-loopiv-heuristic",
- "enable-tbaa", "enable-tlsdesc", "enable-unsafe-fp-math",
- "enable-vtable-profile-use", "enable-vtable-value-profiling",
-@@ -901,8 +917,8 @@ void hideLLVMOptions() {
- "force-dwarf-frame-section", "force-opaque-pointers",
- "force-tail-folding-style",
- "fs-profile-debug-bw-threshold", "fs-profile-debug-prob-diff-threshold",
-- "generate-merged-base-profiles",
-- "gpsize", "hash-based-counter-split", "hexagon-add-build-attributes",
-+ "generate-merged-base-profiles", "gpsize", "gsframe",
-+ "hash-based-counter-split", "hexagon-add-build-attributes",
- "hexagon-rdf-limit", "hot-cold-split", "hwasan-percentile-cutoff-hot",
- "hwasan-random-rate", "ignore-xcoff-visibility",
- "imp-null-check-page-size", "imp-null-max-insts-to-consider",
-@@ -914,7 +930,8 @@ void hideLLVMOptions() {
- "instcombine-negator-max-depth", "instcombine-unsafe-select-transform",
- "instrprof-atomic-counter-update-all", "internalize-public-api-file",
- "internalize-public-api-list", "intrinsic-cost-strategy",
-- "ir2vec-arg-weight", "ir2vec-opc-weight", "ir2vec-type-weight",
-+ "ir2vec-arg-weight", "ir2vec-kind", "ir2vec-opc-weight",
-+ "ir2vec-type-weight",
- "ir2vec-vocab-path", "iterative-counter-promotion",
- "join-liveintervals", "jump-table-type", "large-data-threshold",
- "limit-float-precision", "lint-abort-on-error", "loongarch-use-aa",
-@@ -927,7 +944,10 @@ void hideLLVMOptions() {
- "memop-size-large", "memop-size-range", "merror-missing-parenthesis",
- "merror-noncontigious-register", "mfuture-regs", "mhvx",
- "mips-compact-branches", "mips16-constant-islands", "mips16-hard-float",
-- "mir-strip-debugify-only", "misexpect-tolerance", "mlsm", "mno-compound",
-+ "mir-strip-debugify-only",
-+ "mir2vec-common-operand-weight", "mir2vec-kind", "mir2vec-opc-weight",
-+ "mir2vec-reg-operand-weight", "mir2vec-vocab-path",
-+ "misexpect-tolerance", "mlsm", "mno-compound",
- "mno-fixup", "mno-ldc1-sdc1", "mno-pairing",
- "ms-secure-hotpatch-functions-file", "ms-secure-hotpatch-functions-list",
- "mwarn-missing-parenthesis",
-@@ -943,10 +963,15 @@ void hideLLVMOptions() {
- "polly-dump-after", "polly-dump-after-file", "polly-dump-before",
- "polly-dump-before-file", "pre-RA-sched", "print-after-all",
- "print-before-all", "print-machineinstrs", "print-module-scope",
-- "print-pipeline-passes", "profile-correlate",
-+ "print-pipeline-passes",
-+ "profcheck-annotate-select", "profcheck-default-function-entry-count",
-+ "profcheck-default-select-false-weight",
-+ "profcheck-default-select-true-weight", "profcheck-weights-for-test",
-+ "profile-correlate",
- "profile-estimator-loop-weight", "profile-estimator-loop-weight",
- "profile-file", "profile-info-file", "profile-verifier-noassert",
-- "promote-alloca-vector-loop-user-weight", "pseudo-probe-for-profiling",
-+ "promote-alloca-vector-loop-user-weight", "propeller-infer-threshold",
-+ "pseudo-probe-for-profiling",
- "r600-ir-structurize", "rdf-dump", "rdf-limit", "recip", "regalloc",
- "relax-elf-relocations", "remarks-section", "rewrite-map-file",
- "riscv-add-build-attributes", "riscv-use-aa", "rng-seed",
-@@ -961,11 +986,12 @@ void hideLLVMOptions() {
- "skip-ret-exit-block",
- "speculative-counter-promotion-max-exiting",
- "speculative-counter-promotion-to-loop", "spiller", "spirv-debug",
-+ "spirv-emit-op-names",
- "spirv-erase-cl-md", "spirv-ext", "spirv-lower-const-expr",
- "spirv-mem2reg",
- "spirv-no-deref-attr", "spirv-text", "spirv-verify-regularize-passes",
-- "split-machine-functions", "spv-dump-deps",
-- "spv-emit-nonsemantic-debug-info",
-+ "split-machine-functions", "spv-allow-unknown-intrinsics",
-+ "spv-dump-deps", "spv-emit-nonsemantic-debug-info",
- "spv-lower-saddwithoverflow-validate", "spvbool-validate",
- "spvmemmove-validate", "stack-alignment", "stack-protector-guard",
- "stack-protector-guard-offset", "stack-protector-guard-reg",
-@@ -1016,7 +1042,8 @@ void hideLLVMOptions() {
- "trap-func",
- "W"};
-
-- llvm::StringMap<cl::Option *> &map = cl::getRegisteredOptions();
-+ auto &map = cl::getRegisteredOptions();
-+
- for (const auto name : hiddenOptions) {
- // Check if option exists first for resilience against LLVM changes
- // between versions.
-diff --git a/driver/cl_options.h b/driver/cl_options.h
-index 964874bcce..481b83adcc 100644
---- a/driver/cl_options.h
-+++ b/driver/cl_options.h
-@@ -41,6 +41,7 @@ extern cl::OptionCategory linkingCategory;
- egrep -e '^(cl::|#if|#e)' gen/cl_options.cpp \
- | sed -re 's/^(cl::.*)\(.*$/ extern \1;/'
- */
-+extern cl::opt<bool> noBuiltIn;
- extern cl::list<std::string> fileList;
- extern cl::list<std::string> runargs;
- extern cl::opt<bool> invokedByLDMD;
-diff --git a/driver/cl_options_instrumentation.cpp b/driver/cl_options_instrumentation.cpp
-index 325f71383d..c8c0a07a77 100644
---- a/driver/cl_options_instrumentation.cpp
-+++ b/driver/cl_options_instrumentation.cpp
-@@ -18,11 +18,7 @@
- #include "dmd/errors.h"
- #include "dmd/globals.h"
- #include "gen/to_string.h"
--#if LDC_LLVM_VER < 1700
--#include "llvm/ADT/Triple.h"
--#else
- #include "llvm/TargetParser/Triple.h"
--#endif
-
- namespace {
- namespace cl = llvm::cl;
-diff --git a/driver/cl_options_sanitizers.h b/driver/cl_options_sanitizers.h
-index e1eaa3c934..423322e7fd 100644
---- a/driver/cl_options_sanitizers.h
-+++ b/driver/cl_options_sanitizers.h
-@@ -14,7 +14,7 @@
- #pragma once
-
- #include "driver/cl_helpers.h"
--#if LDC_LLVM_VER >= 2000
-+#if LLVM_VERSION_MAJOR >= 20
- #include "llvm/Transforms/Utils/Instrumentation.h"
- #else
- #include "llvm/Transforms/Instrumentation.h"
-diff --git a/driver/codegenerator.cpp b/driver/codegenerator.cpp
-index 04fdeee4a6..6ec8044eb4 100644
---- a/driver/codegenerator.cpp
-+++ b/driver/codegenerator.cpp
-@@ -37,7 +37,7 @@
- #include "mlir/IR/MLIRContext.h"
- #endif
-
--#if LDC_LLVM_VER < 2200
-+#if LLVM_VERSION_MAJOR < 22
- namespace llvm {
- using LLVMRemarkFileHandle = std::unique_ptr<llvm::ToolOutputFile>;
- }
-@@ -218,7 +218,7 @@ void CodeGenerator::prepareLLModule(Module *m) {
- // name, as it should not collide with a symbol name used somewhere in the
- // module.
- ir_ = new IRState(m->srcfile.toChars(), context_);
--#if LDC_LLVM_VER >= 2100
-+#if LLVM_VERSION_MAJOR >= 21
- ir_->module.setTargetTriple(*global.params.targetTriple);
- #else
- ir_->module.setTargetTriple(global.params.targetTriple->str());
-diff --git a/driver/cpreprocessor.cpp b/driver/cpreprocessor.cpp
-index fff0e5d223..d4b579d99e 100644
---- a/driver/cpreprocessor.cpp
-+++ b/driver/cpreprocessor.cpp
-@@ -99,7 +99,6 @@ FileName runCPreprocessor(FileName csrcfile, Loc loc, OutBuffer &defines) {
- // propagate the target to the preprocessor
- args.push_back("--target=" + triple.getTriple());
-
--#if LDC_LLVM_VER >= 1800 // getAllProcessorFeatures was introduced in this version
- // propagate all enabled/disabled features to the preprocessor
- const auto &subTarget = gTargetMachine->getMCSubtargetInfo();
- const auto &featureBits = subTarget->getFeatureBits();
-@@ -114,7 +113,6 @@ FileName runCPreprocessor(FileName csrcfile, Loc loc, OutBuffer &defines) {
- args.push_back(featureString.str().str());
- featureString.clear();
- }
--#endif
-
- // print macro definitions (clang-cl doesn't support /PD - use clang's
- // -dD)
-diff --git a/driver/linker-gcc.cpp b/driver/linker-gcc.cpp
-index d3ad82b346..93cb97a492 100644
---- a/driver/linker-gcc.cpp
-+++ b/driver/linker-gcc.cpp
-@@ -27,14 +27,12 @@
-
- #if LDC_WITH_LLD
- #include "lld/Common/Driver.h"
--#if LDC_LLVM_VER >= 1700
- LLD_HAS_DRIVER(coff)
- LLD_HAS_DRIVER(elf)
- LLD_HAS_DRIVER(mingw)
- LLD_HAS_DRIVER(macho)
- LLD_HAS_DRIVER(wasm)
- #endif
--#endif
-
- //////////////////////////////////////////////////////////////////////////////
-
-@@ -161,11 +159,6 @@ void ArgsBuilder::addLTOGoldPluginFlags(bool requirePlugin) {
- addLdFlag("-plugin-opt=-function-sections");
- if (TO.DataSections)
- addLdFlag("-plugin-opt=-data-sections");
--
--#if LDC_LLVM_VER >= 1600 && LDC_LLVM_VER < 1700
-- // LLVM 16: disable function specializations by default
-- addLdFlag("-plugin-opt=-func-specialization-size-threshold=1000000000");
--#endif
- }
-
- // Returns an empty string when libLTO.dylib was not specified nor found.
-@@ -196,11 +189,6 @@ void ArgsBuilder::addDarwinLTOFlags() {
- std::string dylibPath = getLTOdylibPath();
- if (!dylibPath.empty()) {
- addLdFlag("-lto_library", dylibPath);
--
--#if LDC_LLVM_VER >= 1600 && LDC_LLVM_VER < 1700
-- // LLVM 16: disable function specializations by default
-- addLdFlag("-mllvm", "-func-specialization-size-threshold=1000000000");
--#endif
- }
- }
-
-@@ -624,20 +612,11 @@ void ArgsBuilder::build(llvm::StringRef outputPath,
- }
-
- const auto explicitPlatformLibs = getExplicitPlatformLibs();
--#if LDC_LLVM_VER >= 1600
- if (explicitPlatformLibs.has_value()) {
- for (const auto &name : explicitPlatformLibs.value()) {
- args.push_back("-l" + name);
- }
-- }
--#else
-- if (explicitPlatformLibs.hasValue()) {
-- for (const auto &name : explicitPlatformLibs.getValue()) {
-- args.push_back("-l" + name);
-- }
-- }
--#endif
-- else {
-+ } else {
- addDefaultPlatformLibs();
- }
-
-@@ -656,10 +635,6 @@ void ArgsBuilder::addLinker() {
- //////////////////////////////////////////////////////////////////////////////
-
- void ArgsBuilder::addUserSwitches() {
--#if LDC_LLVM_VER >= 1800
-- #define startswith starts_with
--#endif
--
- // additional linker and cc switches (preserve order across both lists)
- for (unsigned ilink = 0, icc = 0;;) {
- unsigned linkpos = ilink < opts::linkerSwitches.size()
-@@ -676,9 +651,9 @@ void ArgsBuilder::addUserSwitches() {
- // Options starting with `-Wl,`, -shared or -static are not handled by
- // the linker and must be passed to the driver.
- auto str = llvm::StringRef(p);
-- if (!(str.startswith("-l") || str.startswith("-L") ||
-- str.startswith("-Wl,") || str.startswith("-shared") ||
-- str.startswith("-static"))) {
-+ if (!(str.starts_with("-l") || str.starts_with("-L") ||
-+ str.starts_with("-Wl,") || str.starts_with("-shared") ||
-+ str.starts_with("-static"))) {
- args.push_back("-Xlinker");
- }
- args.push_back(p);
-@@ -688,10 +663,6 @@ void ArgsBuilder::addUserSwitches() {
- break;
- }
- }
--
--#if LDC_LLVM_VER >= 1800
-- #undef startswith
--#endif
- }
-
- //////////////////////////////////////////////////////////////////////////////
-diff --git a/driver/linker-msvc.cpp b/driver/linker-msvc.cpp
-index ad86ebabdf..931ccc3bb5 100644
---- a/driver/linker-msvc.cpp
-+++ b/driver/linker-msvc.cpp
-@@ -22,10 +22,8 @@
-
- #if LDC_WITH_LLD
- #include "lld/Common/Driver.h"
--#if LDC_LLVM_VER >= 1700
- LLD_HAS_DRIVER(coff)
- #endif
--#endif
-
- //////////////////////////////////////////////////////////////////////////////
-
-@@ -39,22 +37,15 @@ void addMscrtLibs(bool useInternalToolchain, std::vector<std::string> &args) {
- // We need the vcruntime lib for druntime's exception handling (ldc.eh_msvc).
- // Pick one of the 4 variants matching the selected main UCRT lib.
-
--#if LDC_LLVM_VER >= 1700
--#define contains_lower contains_insensitive
--#define endswith_lower ends_with_insensitive
--#else
--#define contains_lower contains_insensitive
--#define endswith_lower endswith_insensitive
--#endif
- if (useInternalToolchain) {
-- assert(mscrtlibName.contains_lower("vcruntime"));
-+ assert(mscrtlibName.contains_insensitive("vcruntime"));
- return;
- }
-
-- const bool isStatic = mscrtlibName.contains_lower("libcmt");
-+ const bool isStatic = mscrtlibName.contains_insensitive("libcmt");
-
-- const bool isDebug =
-- mscrtlibName.endswith_lower("d") || mscrtlibName.endswith_lower("d.lib");
-+ const bool isDebug = mscrtlibName.ends_with_insensitive("d") ||
-+ mscrtlibName.ends_with_insensitive("d.lib");
-
- const llvm::StringRef prefix = isStatic ? "lib" : "";
- const llvm::StringRef suffix = isDebug ? "d" : "";
-@@ -77,9 +68,9 @@ void addSanitizerLibs(bool useInternalToolchain,
- std::vector<std::string> &args) {
- if (opts::isSanitizerEnabled(opts::AddressSanitizer)) {
- args.push_back("ldc_rt.asan.lib");
--#if LDC_LLVM_VER >= 2000 // extra library since LLVM 20
-+#if LLVM_VERSION_MAJOR >= 20 // extra library since LLVM 20
- const bool linkStaticCRT =
-- getMscrtLibName(&useInternalToolchain).contains_lower("libcmt");
-+ getMscrtLibName(&useInternalToolchain).contains_insensitive("libcmt");
- args.push_back((llvm::Twine("ldc_rt.asan_") +
- (linkStaticCRT ? "static" : "dynamic") +
- "_runtime_thunk.lib")
-@@ -108,7 +99,8 @@ int linkObjToBinaryMSVC(llvm::StringRef outputPath,
-
- const bool forceMSVC = env::has(L"LDC_VSDIR_FORCE");
- const bool useInternalToolchain =
-- (!forceMSVC && getExplicitMscrtLibName().contains_lower("vcruntime")) ||
-+ (!forceMSVC &&
-+ getExplicitMscrtLibName().contains_insensitive("vcruntime")) ||
- !msvcEnv.setup();
-
- if (forceMSVC && useInternalToolchain) {
-@@ -243,22 +235,12 @@ int linkObjToBinaryMSVC(llvm::StringRef outputPath,
- }
-
- auto explicitPlatformLibs = getExplicitPlatformLibs();
--#if LDC_LLVM_VER >= 1600
- if (explicitPlatformLibs.has_value()) {
- for (auto &lib : explicitPlatformLibs.value()) {
- args.push_back(llvm::sys::path::has_extension(lib) ? std::move(lib)
- : lib + ".lib");
- }
-- }
--#else
-- if (explicitPlatformLibs.hasValue()) {
-- for (auto &lib : explicitPlatformLibs.getValue()) {
-- args.push_back(llvm::sys::path::has_extension(lib) ? std::move(lib)
-- : lib + ".lib");
-- }
-- }
--#endif
-- else {
-+ } else {
- // default platform libs
- // TODO check which libaries are necessary
- args.insert(args.end(),
-diff --git a/driver/linker.cpp b/driver/linker.cpp
-index 65e0a099e0..44495896ee 100644
---- a/driver/linker.cpp
-+++ b/driver/linker.cpp
-@@ -192,14 +192,10 @@ static std::vector<std::string> getDefaultLibNames() {
-
- //////////////////////////////////////////////////////////////////////////////
-
--llvm::Optional<std::vector<std::string>> getExplicitPlatformLibs() {
-+std::optional<std::vector<std::string>> getExplicitPlatformLibs() {
- if (platformLib.getNumOccurrences() > 0)
- return parseLibNames(platformLib);
--#if LDC_LLVM_VER < 1600
-- return llvm::None;
--#else
- return std::nullopt;
--#endif
- }
-
- //////////////////////////////////////////////////////////////////////////////
-diff --git a/driver/linker.h b/driver/linker.h
-index 28362d8652..4f584f8359 100644
---- a/driver/linker.h
-+++ b/driver/linker.h
-@@ -42,11 +42,7 @@ bool linkAgainstSharedDefaultLibs();
- /**
- * Returns the -platformlib library names, if specified.
- */
--#if LDC_LLVM_VER < 1600
--llvm::Optional<std::vector<std::string>> getExplicitPlatformLibs();
--#else
- std::optional<std::vector<std::string>> getExplicitPlatformLibs();
--#endif
-
- /**
- * Returns the value of -mscrtlib.
-diff --git a/driver/main.cpp b/driver/main.cpp
-index e1619dc0cb..df3637f55c 100644
---- a/driver/main.cpp
-+++ b/driver/main.cpp
-@@ -57,11 +57,7 @@
- #include "llvm/LinkAllIR.h"
- #include "llvm/LinkAllPasses.h"
- #include "llvm/Support/FileSystem.h"
--#if LDC_LLVM_VER >= 1700
- #include "llvm/TargetParser/Host.h"
--#else
--#include "llvm/Support/Host.h"
--#endif
- #include "llvm/Support/ManagedStatic.h"
- #include "llvm/Support/Path.h"
- #include "llvm/Support/StringSaver.h"
-@@ -189,17 +185,13 @@ void tryParse(const llvm::SmallVectorImpl<const char *> &args, size_t i,
- }
-
- bool tryParseLowmem(const llvm::SmallVectorImpl<const char *> &args) {
--#if LDC_LLVM_VER >= 1800
-- #define startswith starts_with
--#endif
--
- bool lowmem = false;
- for (size_t i = 1; i < args.size(); ++i) {
- if (args::isRunArg(args[i]))
- break;
-
- llvm::StringRef arg = args[i];
-- if (arg.startswith("-lowmem") || arg.startswith("--lowmem")) {
-+ if (arg.starts_with("-lowmem") || arg.starts_with("--lowmem")) {
- auto remainder = arg.substr(arg[1] == '-' ? 8 : 7);
- if (remainder.empty()) {
- lowmem = true;
-@@ -210,10 +202,6 @@ bool tryParseLowmem(const llvm::SmallVectorImpl<const char *> &args) {
- }
- }
- return lowmem;
--
--#if LDC_LLVM_VER >= 1800
-- #undef startswith
--#endif
- }
-
- const char *
-@@ -322,7 +310,11 @@ void parseCommandLine(Strings &sourceFiles) {
- if (auto target = lookupTarget("", triple, errMsg)) {
- llvm::errs() << "Targeting " << target->getName() << ". ";
- // this prints the available CPUs and features of the target to stderr...
-+#if LLVM_VERSION_MAJOR >= 22
-+ target->createMCSubtargetInfo(triple, "help", "");
-+#else
- target->createMCSubtargetInfo(cfg_triple, "help", "");
-+#endif
- } else {
- error(Loc(), "%s", errMsg.c_str());
- fatal();
-@@ -574,13 +566,6 @@ void parseCommandLine(Strings &sourceFiles) {
-
- global.params.dihdr.fullOutput = opts::hdrKeepAllBodies;
- global.params.disableRedZone = opts::disableRedZone();
--
-- // enforce opaque IR pointers
--#if LDC_LLVM_VER >= 1700
-- // supports opaque IR pointers only
--#else
-- getGlobalContext().setOpaquePointers(true);
--#endif
- }
-
- void initializePasses() {
-@@ -590,28 +575,13 @@ void initializePasses() {
- initializeCore(Registry);
- initializeTransformUtils(Registry);
- initializeScalarOpts(Registry);
--#if LDC_LLVM_VER < 1600
-- initializeObjCARCOpts(Registry);
--#endif
- initializeVectorization(Registry);
- initializeInstCombine(Registry);
--#if LDC_LLVM_VER < 1600
-- initializeAggressiveInstCombine(Registry);
--#endif
- initializeIPO(Registry);
--#if LDC_LLVM_VER < 1600
-- initializeInstrumentation(Registry);
--#endif
- initializeAnalysis(Registry);
- initializeCodeGen(Registry);
- initializeGlobalISel(Registry);
- initializeTarget(Registry);
--
--#if LDC_LLVM_VER < 1700
--// Initialize passes not included above
-- initializeRewriteSymbolsLegacyPassPass(Registry);
-- initializeSjLjEHPreparePass(Registry);
--#endif
- }
-
- /// Register the MIPS ABI.
-@@ -774,7 +744,6 @@ void registerPredefinedTargetVersions() {
- case llvm::Triple::wasm64:
- VersionCondition::addPredefinedGlobalIdent("WebAssembly");
- break;
--#if LDC_LLVM_VER >= 1600
- case llvm::Triple::loongarch32:
- VersionCondition::addPredefinedGlobalIdent("LoongArch32");
- registerPredefinedFloatABI("LoongArch_SoftFloat", "LoongArch_HardFloat");
-@@ -786,7 +755,6 @@ void registerPredefinedTargetVersions() {
- case llvm::Triple::xtensa:
- VersionCondition::addPredefinedGlobalIdent("Xtensa");
- break;
--#endif // LDC_LLVM_VER >= 1600
- default:
- warning(Loc(), "unknown target CPU architecture: %s",
- triple.getArchName().str().c_str());
-@@ -1064,7 +1032,7 @@ void registerPredefinedVersions() {
- // Expose LLVM version to runtime
- #define STR(x) #x
- #define XSTR(x) STR(x)
-- VersionCondition::addPredefinedGlobalIdent("LDC_LLVM_" XSTR(LDC_LLVM_VER));
-+ VersionCondition::addPredefinedGlobalIdent("LDC_LLVM_" XSTR(LLVM_VERSION_MAJOR));
- #undef XSTR
- #undef STR
- }
-@@ -1181,15 +1149,9 @@ int cppmain() {
- }
-
- auto relocModel = getRelocModel();
--#if LDC_LLVM_VER >= 1600
- if (global.params.dll && !relocModel.has_value()) {
- relocModel = llvm::Reloc::PIC_;
- }
--#else
-- if (global.params.dll && !relocModel.hasValue()) {
-- relocModel = llvm::Reloc::PIC_;
-- }
--#endif
-
- fixupTripleEnv(mTargetTriple);
-
-diff --git a/driver/plugins.cpp b/driver/plugins.cpp
-index 1356b4c5fd..b6baa8dfba 100644
---- a/driver/plugins.cpp
-+++ b/driver/plugins.cpp
-@@ -25,7 +25,11 @@
- #include "llvm/Support/CommandLine.h"
- #include "llvm/Support/DynamicLibrary.h"
- #include "llvm/ADT/SmallVector.h"
-+#if LLVM_VERSION_MAJOR >= 22
-+#include "llvm/Plugins/PassPlugin.h"
-+#else
- #include "llvm/Passes/PassPlugin.h"
-+#endif
- #include "llvm/Support/Error.h"
-
- #include "driver/cl_options.h"
-diff --git a/driver/targetmachine.cpp b/driver/targetmachine.cpp
-index 0afc279bcc..6f85efd660 100644
---- a/driver/targetmachine.cpp
-+++ b/driver/targetmachine.cpp
-@@ -21,21 +21,12 @@
- #include "gen/logger.h"
- #include "llvm/ADT/StringExtras.h"
- #include "llvm/ADT/StringSwitch.h"
--#if LDC_LLVM_VER < 1700
--#include "llvm/ADT/Triple.h"
--#include "llvm/MC/SubtargetFeature.h"
--#include "llvm/Support/Host.h"
--#include "llvm/Support/TargetParser.h"
--#include "llvm/Support/AArch64TargetParser.h"
--#include "llvm/Support/ARMTargetParser.h"
--#else
- #include "llvm/TargetParser/AArch64TargetParser.h"
- #include "llvm/TargetParser/ARMTargetParser.h"
- #include "llvm/TargetParser/Host.h"
- #include "llvm/TargetParser/SubtargetFeature.h"
- #include "llvm/TargetParser/TargetParser.h"
- #include "llvm/TargetParser/Triple.h"
--#endif
- #include "llvm/IR/Module.h"
- #include "llvm/MC/MCObjectFileInfo.h"
- #include "llvm/Support/CommandLine.h"
-@@ -46,10 +37,6 @@
-
- #include "gen/optimizer.h"
-
--#if LDC_LLVM_VER >= 1800
--#define startswith starts_with
--#endif
--
- #ifdef LDC_LLVM_SUPPORTS_MACHO_DWARF_LINE_AS_REGULAR_SECTION
- // LDC-LLVM >= 20:
- // On Darwin, emit __debug_line section in __DWARF segment as regular
-@@ -87,65 +74,63 @@ const char *getABI(const llvm::Triple &triple, const llvm::SmallVectorImpl<llvm:
- switch (triple.getArch()) {
- case llvm::Triple::arm:
- case llvm::Triple::armeb:
-- if (ABIName.startswith("aapcs"))
-+ if (ABIName.starts_with("aapcs"))
- return "aapcs";
-- if (ABIName.startswith("eabi"))
-+ if (ABIName.starts_with("eabi"))
- return "apcs";
- break;
- case llvm::Triple::mips:
- case llvm::Triple::mipsel:
- case llvm::Triple::mips64:
- case llvm::Triple::mips64el:
-- if (ABIName.startswith("o32"))
-+ if (ABIName.starts_with("o32"))
- return "o32";
-- if (ABIName.startswith("n32"))
-+ if (ABIName.starts_with("n32"))
- return "n32";
-- if (ABIName.startswith("n64"))
-+ if (ABIName.starts_with("n64"))
- return "n64";
-- if (ABIName.startswith("eabi"))
-+ if (ABIName.starts_with("eabi"))
- return "eabi";
- break;
- case llvm::Triple::ppc64:
- case llvm::Triple::ppc64le:
-- if (ABIName.startswith("elfv1"))
-+ if (ABIName.starts_with("elfv1"))
- return "elfv1";
-- if (ABIName.startswith("elfv2"))
-+ if (ABIName.starts_with("elfv2"))
- return "elfv2";
- break;
- case llvm::Triple::riscv64:
-- if (ABIName.startswith("lp64f"))
-+ if (ABIName.starts_with("lp64f"))
- return "lp64f";
-- if (ABIName.startswith("lp64d"))
-+ if (ABIName.starts_with("lp64d"))
- return "lp64d";
-- if (ABIName.startswith("lp64"))
-+ if (ABIName.starts_with("lp64"))
- return "lp64";
- break;
- case llvm::Triple::riscv32:
-- if (ABIName.startswith("ilp32f"))
-+ if (ABIName.starts_with("ilp32f"))
- return "ilp32f";
-- if (ABIName.startswith("ilp32d"))
-+ if (ABIName.starts_with("ilp32d"))
- return "ilp32d";
-- if (ABIName.startswith("ilp32"))
-+ if (ABIName.starts_with("ilp32"))
- return "ilp32";
- break;
--#if LDC_LLVM_VER >= 1600
- case llvm::Triple::loongarch32:
-- if (ABIName.startswith("ilp32s"))
-+ if (ABIName.starts_with("ilp32s"))
- return "ilp32s";
-- if (ABIName.startswith("ilp32f"))
-+ if (ABIName.starts_with("ilp32f"))
- return "ilp32f";
-- if (ABIName.startswith("ilp32d"))
-+ if (ABIName.starts_with("ilp32d"))
- return "ilp32d";
- break;
- case llvm::Triple::loongarch64:
-- if (ABIName.startswith("lp64f"))
-+ if (ABIName.starts_with("lp64f"))
- return "lp64f";
-- if (ABIName.startswith("lp64d"))
-+ if (ABIName.starts_with("lp64d"))
- return "lp64d";
-- if (ABIName.startswith("lp64s"))
-+ if (ABIName.starts_with("lp64s"))
- return "lp64s";
- break;
--#endif // LDC_LLVM_VER >= 1600
- default:
- break;
- }
-@@ -169,7 +154,6 @@ const char *getABI(const llvm::Triple &triple, const llvm::SmallVectorImpl<llvm:
- return "lp64";
- case llvm::Triple::riscv32:
- return "ilp32";
--#if LDC_LLVM_VER >= 1600
- case llvm::Triple::loongarch32:
- if (isFeatureEnabled(features, "d"))
- return "ilp32d";
-@@ -182,7 +166,6 @@ const char *getABI(const llvm::Triple &triple, const llvm::SmallVectorImpl<llvm:
- if (isFeatureEnabled(features, "f"))
- return "lp64f";
- return "lp64d";
--#endif // LDC_LLVM_VER >= 1600
- default:
- return "";
- }
-@@ -222,22 +205,22 @@ static std::string getX86TargetCPU(const llvm::Triple &triple) {
- if (triple.isArch64Bit()) {
- return "x86-64";
- }
-- if (triple.getOSName().startswith("haiku")) {
-+ if (triple.getOSName().starts_with("haiku")) {
- return "i586";
- }
-- if (triple.getOSName().startswith("openbsd")) {
-+ if (triple.getOSName().starts_with("openbsd")) {
- return "i486";
- }
-- if (triple.getOSName().startswith("freebsd")) {
-+ if (triple.getOSName().starts_with("freebsd")) {
- return "i486";
- }
-- if (triple.getOSName().startswith("netbsd")) {
-+ if (triple.getOSName().starts_with("netbsd")) {
- return "i486";
- }
-- if (triple.getOSName().startswith("openbsd")) {
-+ if (triple.getOSName().starts_with("openbsd")) {
- return "i486";
- }
-- if (triple.getOSName().startswith("dragonfly")) {
-+ if (triple.getOSName().starts_with("dragonfly")) {
- return "i486";
- }
-
-@@ -263,12 +246,6 @@ static std::string getARMTargetCPU(const llvm::Triple &triple) {
- }
-
- static std::string getAArch64TargetCPU(const llvm::Triple &triple) {
--#if LDC_LLVM_VER < 1600
-- auto defaultCPU = llvm::AArch64::getDefaultCPU(triple.getArchName());
-- if (!defaultCPU.empty())
-- return std::string(defaultCPU);
--#endif
--
- return "generic";
- }
-
-@@ -309,18 +286,32 @@ static std::string getTargetCPU(const llvm::Triple &triple) {
- return getRiscv32TargetCPU(triple);
- case llvm::Triple::riscv64:
- return getRiscv64TargetCPU(triple);
--#if LDC_LLVM_VER >= 1600
- case llvm::Triple::loongarch32:
- return getLoongArch32TargetCPU(triple);
- case llvm::Triple::loongarch64:
- return getLoongArch64TargetCPU(triple);
--#endif // LDC_LLVM_VER >= 1600
- }
- }
-
- static const char *getLLVMArchSuffixForARM(llvm::StringRef CPU) {
- return llvm::StringSwitch<const char *>(CPU)
- .Case("strongarm", "v4")
-+#if LLVM_VERSION_MAJOR >= 22
-+ .Cases({"arm7tdmi", "arm7tdmi-s", "arm710t"}, "v4t")
-+ .Cases({"arm720t", "arm9", "arm9tdmi"}, "v4t")
-+ .Cases({"arm920", "arm920t", "arm922t"}, "v4t")
-+ .Cases({"arm940t", "ep9312"}, "v4t")
-+ .Cases({"arm10tdmi", "arm1020t"}, "v5")
-+ .Cases({"arm9e", "arm926ej-s", "arm946e-s"}, "v5e")
-+ .Cases({"arm966e-s", "arm968e-s", "arm10e"}, "v5e")
-+ .Cases({"arm1020e", "arm1022e", "xscale", "iwmmxt"}, "v5e")
-+ .Cases({"arm1136j-s", "arm1136jf-s", "arm1176jz-s"}, "v6")
-+ .Cases({"arm1176jzf-s", "mpcorenovfp", "mpcore"}, "v6")
-+ .Cases({"arm1156t2-s", "arm1156t2f-s"}, "v6t2")
-+ .Cases({"cortex-a5", "cortex-a7", "cortex-a8"}, "v7")
-+ .Cases({"cortex-a9", "cortex-a12", "cortex-a15"}, "v7")
-+ .Cases({"cortex-r4", "cortex-r5"}, "v7r")
-+#else
- .Cases("arm7tdmi", "arm7tdmi-s", "arm710t", "v4t")
- .Cases("arm720t", "arm9", "arm9tdmi", "v4t")
- .Cases("arm920", "arm920t", "arm922t", "v4t")
-@@ -335,6 +326,7 @@ static const char *getLLVMArchSuffixForARM(llvm::StringRef CPU) {
- .Cases("cortex-a5", "cortex-a7", "cortex-a8", "v7")
- .Cases("cortex-a9", "cortex-a12", "cortex-a15", "v7")
- .Cases("cortex-r4", "cortex-r5", "v7r")
-+#endif
- .Case("cortex-m0", "v6m")
- .Case("cortex-m3", "v7m")
- .Case("cortex-m4", "v7em")
-@@ -349,8 +341,8 @@ static FloatABI::Type getARMFloatABI(const llvm::Triple &triple,
- const char *llvmArchSuffix) {
- if (triple.isOSDarwin()) {
- // Darwin defaults to "softfp" for v6 and v7.
-- if (llvm::StringRef(llvmArchSuffix).startswith("v6") ||
-- llvm::StringRef(llvmArchSuffix).startswith("v7")) {
-+ if (llvm::StringRef(llvmArchSuffix).starts_with("v6") ||
-+ llvm::StringRef(llvmArchSuffix).starts_with("v7")) {
- return FloatABI::SoftFP;
- }
- return FloatABI::Soft;
-@@ -361,9 +353,9 @@ static FloatABI::Type getARMFloatABI(const llvm::Triple &triple,
- return FloatABI::Soft;
- }
-
-- if (triple.getVendorName().startswith("hardfloat"))
-+ if (triple.getVendorName().starts_with("hardfloat"))
- return FloatABI::Hard;
-- if (triple.getVendorName().startswith("softfloat"))
-+ if (triple.getVendorName().starts_with("softfloat"))
- return FloatABI::SoftFP;
-
- switch (triple.getEnvironment()) {
-@@ -375,7 +367,7 @@ static FloatABI::Type getARMFloatABI(const llvm::Triple &triple,
- // EABI is always AAPCS, and if it was not marked 'hard', it's softfp
- return FloatABI::SoftFP;
- case llvm::Triple::Android: {
-- if (llvm::StringRef(llvmArchSuffix).startswith("v7")) {
-+ if (llvm::StringRef(llvmArchSuffix).starts_with("v7")) {
- return FloatABI::SoftFP;
- }
- return FloatABI::Soft;
-@@ -425,7 +417,11 @@ const llvm::Target *lookupTarget(const std::string &arch, llvm::Triple &triple,
- }
- } else {
- std::string tempError;
-+#if LLVM_VERSION_MAJOR >= 22
-+ target = llvm::TargetRegistry::lookupTarget(triple, tempError);
-+#else
- target = llvm::TargetRegistry::lookupTarget(triple.getTriple(), tempError);
-+#endif
- if (!target) {
- errorMsg = "unable to get target for '" + triple.getTriple() +
- "', see -version and -mtriple.";
-@@ -440,8 +436,8 @@ createTargetMachine(const std::string targetTriple, const std::string arch,
- std::string cpu, const std::string featuresString,
- const ExplicitBitness::Type bitness,
- FloatABI::Type &floatABI,
-- llvm::Optional<llvm::Reloc::Model> relocModel,
-- llvm::Optional<llvm::CodeModel::Model> codeModel,
-+ std::optional<llvm::Reloc::Model> relocModel,
-+ std::optional<llvm::CodeModel::Model> codeModel,
- const llvm::CodeGenOptLevel codeGenOptLevel,
- const bool noLinkerStripDead) {
- // Determine target triple. If the user didn't explicitly specify one, use
-@@ -543,19 +539,12 @@ createTargetMachine(const std::string targetTriple, const std::string arch,
-
- // For LoongArch 64-bit target default to la64 if nothing has been selected
- // All current LoongArch targets have 64-bit floating point registers.
--#if LDC_LLVM_VER >= 1600
- if (triple.getArch() == llvm::Triple::loongarch64 && features.empty()) {
- features = {"+d"};
- }
--#endif
-
- // Handle cases where LLVM picks wrong default relocModel
--#if LDC_LLVM_VER >= 1600
-- if (relocModel.has_value()) {}
--#else
-- if (relocModel.hasValue()) {}
--#endif
-- else {
-+ if (!relocModel.has_value()) {
- if (triple.isOSDarwin()) {
- // Darwin defaults to PIC (and as of 10.7.5/LLVM 3.1-3.3, TLS use leads
- // to crashes for non-PIC code). LLVM doesn't handle this.
-@@ -636,11 +625,6 @@ createTargetMachine(const std::string targetTriple, const std::string arch,
- // EmuTLS).
- if (triple.getEnvironment() == llvm::Triple::Android) {
- targetOptions.EmulatedTLS = false;
--#if LDC_LLVM_VER < 1700
-- // Removed in this commit:
-- // https://github.com/llvm/llvm-project/commit/0d333bf0e3aa37e2e6ae211e3aa80631c3e01b85
-- targetOptions.ExplicitEmulatedTLS = true;
--#endif
- }
-
- const std::string finalFeaturesString =
-@@ -653,7 +637,7 @@ createTargetMachine(const std::string targetTriple, const std::string arch,
- }
-
- return target->createTargetMachine(
--#if LDC_LLVM_VER >= 2100
-+#if LLVM_VERSION_MAJOR >= 21
- triple,
- #else
- triple.str(),
-diff --git a/driver/targetmachine.h b/driver/targetmachine.h
-index 3bfa567e4f..e0c21ee140 100644
---- a/driver/targetmachine.h
-+++ b/driver/targetmachine.h
-@@ -14,24 +14,12 @@
-
- #pragma once
-
--#if LDC_LLVM_VER < 1700
--#include "llvm/ADT/Optional.h"
--#else
--#include <optional>
--namespace llvm {
--template <typename T> using Optional = std::optional<T>;
--}
--#endif
- #include "llvm/ADT/SmallVector.h"
- #include "llvm/ADT/StringRef.h"
- #include "llvm/Support/CodeGen.h"
-+#include <optional>
- #include <string>
- #include <vector>
--namespace llvm {
--#if LDC_LLVM_VER < 1800
--using CodeGenOptLevel = llvm::CodeGenOpt::Level;
--#endif
--}
-
- namespace ExplicitBitness {
- enum Type { None, M32, M64 };
-@@ -69,8 +57,8 @@ llvm::TargetMachine *
- createTargetMachine(std::string targetTriple, std::string arch, std::string cpu,
- std::string featuresString, ExplicitBitness::Type bitness,
- FloatABI::Type &floatABI,
-- llvm::Optional<llvm::Reloc::Model> relocModel,
-- llvm::Optional<llvm::CodeModel::Model> codeModel,
-+ std::optional<llvm::Reloc::Model> relocModel,
-+ std::optional<llvm::CodeModel::Model> codeModel,
- llvm::CodeGenOptLevel codeGenOptLevel,
- bool noLinkerStripDead);
-
-diff --git a/driver/toobj.cpp b/driver/toobj.cpp
-index f9789452f4..211d8d88f4 100644
---- a/driver/toobj.cpp
-+++ b/driver/toobj.cpp
-@@ -37,34 +37,14 @@
- #include "llvm/CodeGen/TargetSubtargetInfo.h"
- #include "llvm/Transforms/Utils/Cloning.h"
- #include "llvm/IR/Module.h"
--#ifdef LDC_LLVM_SUPPORTED_TARGET_SPIRV
--#if LDC_LLVM_VER < 1600
--#include "LLVMSPIRVLib/LLVMSPIRVLib.h"
--#endif
--#endif
- #include <cstddef>
- #include <fstream>
-
--using CodeGenFileType = llvm::CodeGenFileType;
--
--#if LDC_LLVM_VER >= 1800
--constexpr llvm::CodeGenFileType CGFT_AssemblyFile = CodeGenFileType::AssemblyFile;
--constexpr llvm::CodeGenFileType CGFT_ObjectFile = CodeGenFileType::ObjectFile;
--#endif
--
--#if LDC_LLVM_VER < 1700
--static llvm::cl::opt<bool>
-- NoIntegratedAssembler("no-integrated-as", llvm::cl::ZeroOrMore,
-- llvm::cl::Hidden,
-- llvm::cl::desc("Disable integrated assembler"));
--#else
- namespace llvm {
- namespace codegen {
- bool getDisableIntegratedAS();
- }
- }
--#define NoIntegratedAssembler llvm::codegen::getDisableIntegratedAS()
--#endif
-
- namespace {
-
-@@ -81,21 +61,13 @@ void runDLLImportRelocationPass(llvm::TargetMachine &Target, llvm::Module &m) {
- // based on llc code, University of Illinois Open Source License
- void codegenModule(llvm::TargetMachine &Target, llvm::Module &m,
- const char *filename,
-- CodeGenFileType fileType) {
-+ llvm::CodeGenFileType fileType) {
- using namespace llvm;
-
- const ComputeBackend::Type cb = getComputeTargetType(&m);
-
- if (cb == ComputeBackend::SPIRV) {
--#ifdef LDC_LLVM_SUPPORTED_TARGET_SPIRV
--#if LDC_LLVM_VER < 1600
-- IF_LOG Logger::println("running createSPIRVWriterPass()");
-- std::ofstream out(filename, std::ofstream::binary);
-- llvm::createSPIRVWriterPass(out)->runOnModule(m);
-- IF_LOG Logger::println("Success.");
-- return;
--#endif
--#else
-+#ifndef LDC_LLVM_SUPPORTED_TARGET_SPIRV
- error(Loc(), "Trying to target SPIRV, but LDC is not built to do so!");
- return;
- #endif
-@@ -132,11 +104,8 @@ void codegenModule(llvm::TargetMachine &Target, llvm::Module &m,
- nullptr, // DWO output file
- // Always generate assembly for ptx as it is an assembly format
- // The PTX backend fails if we pass anything else.
-- (cb == ComputeBackend::NVPTX) ? CGFT_AssemblyFile : fileType
--#if LDC_LLVM_VER < 1700
-- , codeGenOptLevel()
--#endif
-- )) {
-+ (cb == ComputeBackend::NVPTX) ? CodeGenFileType::AssemblyFile
-+ : fileType)) {
- llvm_unreachable("no support for asm output");
- }
-
-@@ -300,14 +269,14 @@ public:
- void writeObjectFile(llvm::Module *m, const char *filename) {
- IF_LOG Logger::println("Writing object file to: %s", filename);
- codegenModule(*gTargetMachine, *m, filename,
-- CGFT_ObjectFile);
-+ llvm::CodeGenFileType::ObjectFile);
- }
-
- bool shouldAssembleExternally() {
- // There is no integrated assembler on AIX because XCOFF is not supported.
- // Starting with LLVM 3.5 the integrated assembler can be used with MinGW.
- return global.params.output_o &&
-- (NoIntegratedAssembler ||
-+ (llvm::codegen::getDisableIntegratedAS() ||
- global.params.targetTriple->getOS() == llvm::Triple::AIX);
- }
-
-@@ -479,10 +448,10 @@ void writeModule(llvm::Module *m, const char *filename) {
- // to avoid running 'addPassesToEmitFile' passes twice on same module
- auto clonedModule = llvm::CloneModule(*m);
- codegenModule(*gTargetMachine, *clonedModule, spath.c_str(),
-- CGFT_AssemblyFile);
-+ llvm::CodeGenFileType::AssemblyFile);
- } else {
- codegenModule(*gTargetMachine, *m, spath.c_str(),
-- CGFT_AssemblyFile);
-+ llvm::CodeGenFileType::AssemblyFile);
- }
-
- if (assembleExternally) {
-diff --git a/driver/tool.cpp b/driver/tool.cpp
-index e64ec96cbd..31ff31cf83 100644
---- a/driver/tool.cpp
-+++ b/driver/tool.cpp
-@@ -20,12 +20,7 @@
- #include "llvm/Support/MemoryBuffer.h"
- #include "llvm/Support/Path.h"
- #include "llvm/Target/TargetMachine.h"
--
--#if LDC_LLVM_VER >= 1600
- #include "llvm/TargetParser/Host.h"
--#else
--#include "llvm/Support/Host.h"
--#endif
-
- #ifdef _WIN32
- #include <Windows.h>
-@@ -214,12 +209,10 @@ void appendTargetArgsForGcc(std::vector<std::string> &args) {
- case Triple::nvptx64:
- args.push_back(triple.isArch64Bit() ? "-m64" : "-m32");
- return;
--#if LDC_LLVM_VER >= 1600
- // LoongArch does not use -m32/-m64 and uses -mabi=.
- case Triple::loongarch64:
- args.emplace_back(triple.isArch64Bit() ? "-mabi=lp64d" : "-mabi=ilp32d");
- return;
--#endif // LDC_LLVM_VER >= 1600
- // MIPS does not have -m32/-m64 but requires -mabi=.
- case Triple::mips64:
- case Triple::mips64el:
-diff --git a/gen/abi/abi.cpp b/gen/abi/abi.cpp
-index eab1ca5ca1..5e5a1baa20 100644
---- a/gen/abi/abi.cpp
-+++ b/gen/abi/abi.cpp
-@@ -158,11 +158,7 @@ llvm::CallingConv::ID TargetABI::callingConv(FuncDeclaration *fdecl) {
- void TargetABI::setUnwindTableKind(llvm::Function *fn) {
- llvm::UWTableKind kind = defaultUnwindTableKind();
- if (kind != llvm::UWTableKind::None) {
--#if LDC_LLVM_VER >= 1600
- fn->setUWTableKind(kind);
--#else
-- fn->setUWTableKind(kind);
--#endif
- }
- }
-
-@@ -285,10 +281,8 @@ TargetABI *TargetABI::getTarget() {
- case llvm::Triple::thumb:
- case llvm::Triple::thumbeb:
- return getArmTargetABI();
--#if LDC_LLVM_VER >= 1600
- case llvm::Triple::loongarch64:
- return getLoongArch64TargetABI();
--#endif // LDC_LLVM_VER >= 1600
- case llvm::Triple::wasm32:
- case llvm::Triple::wasm64:
- return getWasmTargetABI();
-diff --git a/gen/abi/generic.h b/gen/abi/generic.h
-index 6458d28b8b..4def40c790 100644
---- a/gen/abi/generic.h
-+++ b/gen/abi/generic.h
-@@ -260,7 +260,7 @@ struct IndirectByvalRewrite : ABIRewrite {
- auto &attrs = arg.attrs;
- attrs.clear();
- attrs.addAttribute(LLAttribute::NoAlias);
--#if LDC_LLVM_VER >= 2100
-+#if LLVM_VERSION_MAJOR >= 21
- attrs.addCapturesAttr(llvm::CaptureInfo::none());
- #else
- attrs.addAttribute(LLAttribute::NoCapture);
-diff --git a/gen/abi/nvptx.cpp b/gen/abi/nvptx.cpp
-index cd81b6261f..31cf01d946 100644
---- a/gen/abi/nvptx.cpp
-+++ b/gen/abi/nvptx.cpp
-@@ -38,7 +38,7 @@ struct NVPTXTargetABI : TargetABI {
- return;
-
- Type *ty = arg.type->toBasetype();
-- llvm::Optional<DcomputePointer> ptr;
-+ std::optional<DcomputePointer> ptr;
- if (ty->ty == TY::Tstruct &&
- (ptr = toDcomputePointer(static_cast<TypeStruct *>(ty)->sym))) {
- pointerRewite.applyTo(arg);
-diff --git a/gen/abi/spirv.cpp b/gen/abi/spirv.cpp
-index 60a3eada37..df8a487acc 100644
---- a/gen/abi/spirv.cpp
-+++ b/gen/abi/spirv.cpp
-@@ -44,7 +44,7 @@ struct SPIRVTargetABI : TargetABI {
- return;
-
- Type *ty = arg.type->toBasetype();
-- llvm::Optional<DcomputePointer> ptr;
-+ std::optional<DcomputePointer> ptr;
- if (ty->ty == TY::Tstruct &&
- (ptr = toDcomputePointer(static_cast<TypeStruct *>(ty)->sym))) {
- pointerRewite.applyTo(arg);
-diff --git a/gen/arrays.cpp b/gen/arrays.cpp
-index 8179679d10..a27c4338e6 100644
---- a/gen/arrays.cpp
-+++ b/gen/arrays.cpp
-@@ -533,11 +533,7 @@ llvm::Constant *arrayLiteralToConst(IRState *p, ArrayLiteralExp *ale) {
- // extend i1 to i8
- if (val->getType()->isIntegerTy(1)) {
- LLType *I8PtrTy = LLType::getInt8Ty(p->context());
--#if LDC_LLVM_VER < 1800
-- val = llvm::ConstantExpr::getZExt(val, I8PtrTy);
--#else
- val = llvm::ConstantFoldCastOperand(llvm::Instruction::ZExt, val, I8PtrTy, *gDataLayout);
--#endif
- }
- if (!elementType) {
- elementType = val->getType();
-diff --git a/gen/asm-gcc.cpp b/gen/asm-gcc.cpp
-index 9df3c55c2e..60026c6f98 100644
---- a/gen/asm-gcc.cpp
-+++ b/gen/asm-gcc.cpp
-@@ -63,10 +63,6 @@ class ConstraintsBuilder {
- // Appends a constraint string expression with an optional prefix.
- // Returns true if the string describes an indirect operand.
- bool append(Expression *e, char prefix = 0) {
--#if LDC_LLVM_VER >= 1800
-- #define startswith starts_with
--#endif
--
- auto se = e->isStringExp();
- assert(se);
- llvm::StringRef code = peekString(se);
-@@ -81,10 +77,10 @@ class ConstraintsBuilder {
-
- // commit any modifier and strip from `code`
- bool isIndirect = false;
-- if (code.startswith("&")) { // early clobber
-+ if (code.starts_with("&")) { // early clobber
- str << '&';
- code = code.substr(1);
-- } else if (code.startswith("*")) { // indirect in/output
-+ } else if (code.starts_with("*")) { // indirect in/output
- isIndirect = true; // delay the commit
- code = code.substr(1);
- }
-@@ -97,10 +93,6 @@ class ConstraintsBuilder {
- str << ',';
-
- return isIndirect;
--
--#if LDC_LLVM_VER >= 1800
-- #undef startswith
--#endif
- }
-
- // Might set `isIndirect` to true (but never resets to false).
-diff --git a/gen/asm-x86.h b/gen/asm-x86.h
-index eecd1a8b65..2104b4155c 100644
---- a/gen/asm-x86.h
-+++ b/gen/asm-x86.h
-@@ -2340,57 +2340,15 @@ struct AsmProcessor {
- AsmCode *asmcode, AsmArgMode mode = Mode_Input) {
- using namespace dmd;
-
-- if (sc->func->isNaked()) {
-- switch (type) {
-- case Arg_Integer:
-- if (e->type->isUnsigned()) {
-- insnTemplate << "$" << e->toUInteger();
-- } else {
-+ if (type == Arg_Integer) {
-+ if (e->type->isUnsigned()) {
-+ insnTemplate << "$$" << e->toUInteger();
-+ } else {
- #ifndef ASM_X86_64
-- insnTemplate << "$" << static_cast<sinteger_t>(e->toInteger());
-+ insnTemplate << "$$" << static_cast<sinteger_t>(e->toInteger());
- #else
-- insnTemplate << "$" << e->toInteger();
-+ insnTemplate << "$$" << e->toInteger();
- #endif
-- }
-- break;
--
-- case Arg_Pointer:
-- error(stmt->loc, "unsupported pointer reference to `%s` in naked asm",
-- e->toChars());
-- break;
--
-- case Arg_Memory:
-- // Peel off one layer of explicitly taking the address, if present.
-- if (auto ae = e->isAddrExp()) {
-- e = ae->e1;
-- }
--
-- if (auto v = e->isVarExp()) {
-- if (VarDeclaration *vd = v->var->isVarDeclaration()) {
-- if (!vd->isDataseg()) {
-- error(stmt->loc, "only global variables can be referenced by "
-- "identifier in naked asm");
-- break;
-- }
--
-- // print out the mangle
-- if (prependExtraUnderscore(vd->resolvedLinkage())) {
-- insnTemplate << "_";
-- }
-- OutBuffer buf;
-- mangleToBuffer(vd, buf);
-- insnTemplate << buf.peekChars();
-- getIrGlobal(vd, true)->nakedUse = true;
-- break;
-- }
-- }
-- error(stmt->loc, "unsupported memory reference to `%s` in naked asm",
-- e->toChars());
-- break;
--
-- default:
-- llvm_unreachable("Unsupported argument in asm.");
-- break;
- }
- } else {
- insnTemplate << fmt << "<<" << (mode == Mode_Input ? "in" : "out")
-@@ -2401,13 +2359,6 @@ struct AsmProcessor {
- void addOperand2(const char *fmtpre, const char *fmtpost, AsmArgType type,
- Expression *e, AsmCode *asmcode,
- AsmArgMode mode = Mode_Input) {
-- if (sc->func->isNaked()) {
-- // taken from above
-- error(stmt->loc, "only global variables can be referenced by identifier in "
-- "naked asm");
-- return;
-- }
--
- insnTemplate << fmtpre << "<<" << (mode == Mode_Input ? "in" : "out")
- << ">>" << fmtpost;
- asmcode->args.push_back(AsmArg(type, e, mode));
-@@ -3078,11 +3029,9 @@ struct AsmProcessor {
- // If we subtract 8 from our const-displacement, then we can use the `H` modifier to ensure
- // that we always end up with a valid syntax for a memory operand with an offset.
- // So, we do just that when we have const-displacement in play.
-- // (Only for non-naked asm, as this isn't an issue for naked asm.)
- //
- // See also: https://lists.llvm.org/pipermail/llvm-dev/2017-August/116244.html
-- const auto forceLeadingDisplacement = hasConstDisplacement && !sc->func->isNaked();
-- if (forceLeadingDisplacement) {
-+ if (hasConstDisplacement) {
- // Subtract 8 from our const-displacement, and prepare to add the 8 from the `H` modifier.
- insnTemplate << "-8+";
- }
-@@ -3092,14 +3041,11 @@ struct AsmProcessor {
- use_star = false;
- }
-
-- if (!sc->func->isNaked()) // no addrexp in naked asm please :)
-- {
-- Type *tt = pointerTo(e->type);
-- e = createAddrExp(Loc(), e);
-- e->type = tt;
-- }
-+ Type *tt = pointerTo(e->type);
-+ e = createAddrExp(Loc(), e);
-+ e->type = tt;
-
-- if (forceLeadingDisplacement) {
-+ if (hasConstDisplacement) {
- // We have a const-displacement in play, so we add the `H` modifier, as described earlier.
- insnTemplate << "${" << "<<" << (mode == Mode_Input ? "in" : "out")
- << asmcode->args.size() << ">>" << ":H}";
-diff --git a/gen/asmstmt.cpp b/gen/asmstmt.cpp
-index 12d364d012..b5c868a844 100644
---- a/gen/asmstmt.cpp
-+++ b/gen/asmstmt.cpp
-@@ -532,9 +532,14 @@ void CompoundAsmStatement_toIR(CompoundAsmStatement *stmt, IRState *p) {
- }
- Identifier *const ident = targetLabel->ident;
-
-- // if internal, no special handling is necessary, skip
-- if (llvm::any_of(asmblock->internalLabels,
-- [ident](Identifier *i) { return i->equals(ident); })) {
-+ // if the label is defined in inline asm, we can jump to it directly
-+ if (fd->isNaked() // in naked DMD-style inline-asm functions, all D labels
-+ // become assembly labels too (and the extra forwarding
-+ // code would mess with the stack due to an i32 alloca)
-+ || (fd->asmLabels &&
-+ llvm::any_of(*fd->asmLabels, [ident](Identifier *i) {
-+ return i->equals(ident);
-+ }))) {
- continue;
- }
-
-@@ -784,21 +789,3 @@ void CompoundAsmStatement_toIR(CompoundAsmStatement *stmt, IRState *p) {
- p->ir->SetInsertPoint(bb);
- }
- }
--
--//////////////////////////////////////////////////////////////////////////////
--
--void AsmStatement_toNakedIR(InlineAsmStatement *stmt, IRState *irs) {
-- IF_LOG Logger::println("InlineAsmStatement::toNakedIR(): %s",
-- stmt->loc.toChars());
-- LOG_SCOPE;
--
-- // is there code?
-- if (!stmt->asmcode) {
-- return;
-- }
-- AsmCode *code = static_cast<AsmCode *>(stmt->asmcode);
--
-- // build asm stmt
-- replace_func_name(irs, code->insnTemplate);
-- irs->nakedAsm << "\t" << code->insnTemplate << std::endl;
--}
-diff --git a/gen/ctfloat.cpp b/gen/ctfloat.cpp
-index ef033c018d..9ce8ad72d7 100644
---- a/gen/ctfloat.cpp
-+++ b/gen/ctfloat.cpp
-@@ -83,7 +83,11 @@ void CTFloat::toAPFloat(const real_t src, APFloat &dst) {
- u.fp = src;
-
- const unsigned sizeInBits = APFloat::getSizeInBits(*apSemantics);
-+#if LLVM_VERSION_MAJOR >= 22
-+ const APInt bits = APInt(sizeInBits, u.bits);
-+#else
- const APInt bits = APInt(sizeInBits, numUint64Parts, u.bits);
-+#endif
-
- dst = APFloat(*apSemantics, bits);
- }
-diff --git a/gen/dcompute/druntime.cpp b/gen/dcompute/druntime.cpp
-index 0f2c79bd4c..829185481c 100644
---- a/gen/dcompute/druntime.cpp
-+++ b/gen/dcompute/druntime.cpp
-@@ -43,17 +43,13 @@ bool isFromLDC_OpenCL(Dsymbol *sym) {
- return isFromLDC_Mod(sym,Id::opencl);
- }
-
--llvm::Optional<DcomputePointer> toDcomputePointer(StructDeclaration *sd) {
-+std::optional<DcomputePointer> toDcomputePointer(StructDeclaration *sd) {
- if (sd->ident != Id::dcPointer || !isFromLDC_DCompute(sd)) {
--#if LDC_LLVM_VER < 1600
-- return llvm::Optional<DcomputePointer>(llvm::None);
--#else
- return std::optional<DcomputePointer>(std::nullopt);
--#endif
- }
-
- TemplateInstance *ti = sd->isInstantiated();
- int addrspace = isExpression((*ti->tiargs)[0])->toInteger();
- Type *type = isType((*ti->tiargs)[1]);
-- return llvm::Optional<DcomputePointer>(DcomputePointer(addrspace, type));
-+ return std::optional<DcomputePointer>(DcomputePointer(addrspace, type));
- }
-diff --git a/gen/dcompute/druntime.h b/gen/dcompute/druntime.h
-index 6ff3b2c8a8..673eb24951 100644
---- a/gen/dcompute/druntime.h
-+++ b/gen/dcompute/druntime.h
-@@ -18,14 +18,7 @@
- #include "gen/irstate.h"
- #include "gen/llvm.h"
- #include "gen/tollvm.h"
--#if LDC_LLVM_VER < 1700
--#include "llvm/ADT/Optional.h"
--#else
- #include <optional>
--namespace llvm {
--template <typename T> using Optional = std::optional<T>;
--}
--#endif
-
- class Dsymbol;
- class Type;
-@@ -45,4 +38,4 @@ struct DcomputePointer {
- return LLPointerType::get(getGlobalContext(), as);
- }
- };
--llvm::Optional<DcomputePointer> toDcomputePointer(StructDeclaration *sd);
-+std::optional<DcomputePointer> toDcomputePointer(StructDeclaration *sd);
-diff --git a/gen/dcompute/targetCUDA.cpp b/gen/dcompute/targetCUDA.cpp
-index ffd2711acc..9861cb2764 100644
---- a/gen/dcompute/targetCUDA.cpp
-+++ b/gen/dcompute/targetCUDA.cpp
-@@ -43,7 +43,7 @@ public:
- llvm::Reloc::Static, llvm::CodeModel::Medium, codeGenOptLevel(), false);
-
- _ir = new IRState("dcomputeTargetCUDA", ctx);
--#if LDC_LLVM_VER >= 2100
-+#if LLVM_VERSION_MAJOR >= 21
- _ir->module.setTargetTriple(llvm::Triple(tripleString));
- #else
- _ir->module.setTargetTriple(tripleString);
-diff --git a/gen/dcompute/targetOCL.cpp b/gen/dcompute/targetOCL.cpp
-index b93850c95e..e0fa37310e 100644
---- a/gen/dcompute/targetOCL.cpp
-+++ b/gen/dcompute/targetOCL.cpp
-@@ -24,7 +24,7 @@
- #include <string>
-
- // from SPIRVInternal.h
--#if LDC_LLVM_VER < 1900
-+#if LLVM_VERSION_MAJOR < 19
- # define SPIR_TARGETTRIPLE32 "spir-unknown-unknown"
- # define SPIR_TARGETTRIPLE64 "spir64-unknown-unknown"
- # define SPIR_DATALAYOUT32 \
-@@ -42,7 +42,7 @@
- #else // LLVM 19+
- # define SPIR_TARGETTRIPLE32 "spirv-unknown-unknown"
- # define SPIR_TARGETTRIPLE64 "spirv64-unknown-unknown"
--# if LDC_LLVM_VER < 2000
-+# if LLVM_VERSION_MAJOR < 20
- # define SPIR_DATALAYOUT32 \
- "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64" \
- "-v96:128-v192:256-v256:256-v512:512-v1024:1024-G1"
-@@ -75,14 +75,13 @@ public:
- _ir = new IRState("dcomputeTargetOCL", ctx);
- std::string targTripleStr = is64 ? SPIR_TARGETTRIPLE64
- : SPIR_TARGETTRIPLE32;
--#if LDC_LLVM_VER >= 2100
-+#if LLVM_VERSION_MAJOR >= 21
- llvm::Triple targTriple = llvm::Triple(targTripleStr);
- #else
- std::string targTriple = targTripleStr;
- #endif
- _ir->module.setTargetTriple(targTriple);
-
--#if LDC_LLVM_VER >= 1600
- auto floatABI = ::FloatABI::Hard;
- targetMachine = createTargetMachine(
- targTripleStr,
-@@ -90,7 +89,6 @@ public:
- "", {},
- is64 ? ExplicitBitness::M64 : ExplicitBitness::M32, floatABI,
- llvm::Reloc::Static, llvm::CodeModel::Medium, codeGenOptLevel(), false);
--#endif
- _ir->module.setDataLayout(is64 ? SPIR_DATALAYOUT64 : SPIR_DATALAYOUT32);
- _ir->dcomputetarget = this;
- }
-@@ -200,7 +198,7 @@ public:
- void decodeTypes(std::array<llvm::SmallVector<llvm::Metadata *, 8>,count_KernArgMD>& attrs,
- VarDeclaration *v)
- {
-- llvm::Optional<DcomputePointer> ptr;
-+ std::optional<DcomputePointer> ptr;
- std::string typeQuals;
- std::string baseTyName;
- std::string tyName;
-diff --git a/gen/declarations.cpp b/gen/declarations.cpp
-index bdadc84c61..0e43a20ff6 100644
---- a/gen/declarations.cpp
-+++ b/gen/declarations.cpp
-@@ -412,24 +412,19 @@ public:
- void visit(PragmaDeclaration *decl) override {
- const auto &triple = *global.params.targetTriple;
-
--#if LDC_LLVM_VER >= 1800
-- #define endswith ends_with
-- #define startswith starts_with
--#endif
--
- if (decl->ident == Id::lib) {
- assert(!irs->dcomputetarget);
- llvm::StringRef name = getPragmaStringArg(decl);
-
- if (triple.isWindowsGNUEnvironment()) {
-- if (name.endswith(".lib")) {
-+ if (name.ends_with(".lib")) {
- // On MinGW, strip the .lib suffix, if any, to improve compatibility
- // with code written for DMD (we pass the name to GCC via -l, just as
- // on Posix).
- name = name.drop_back(4);
- }
-
-- if (name.startswith("shell32")) {
-+ if (name.starts_with("shell32")) {
- // Another DMD compatibility kludge: Ignore
- // pragma(lib, "shell32.lib"), it is implicitly provided by
- // MinGW.
-@@ -438,10 +433,10 @@ public:
- }
-
- if (triple.isWindowsMSVCEnvironment()) {
-- if (name.endswith(".a")) {
-+ if (name.ends_with(".a")) {
- name = name.drop_back(2);
- }
-- if (name.endswith(".lib")) {
-+ if (name.ends_with(".lib")) {
- name = name.drop_back(4);
- }
-
-@@ -450,7 +445,7 @@ public:
- std::string arg = ("/DEFAULTLIB:\"" + name + "\"").str();
- gIR->addLinkerOption(llvm::StringRef(arg));
- } else {
-- const bool isStaticLib = name.endswith(".a");
-+ const bool isStaticLib = name.ends_with(".a");
- const size_t nameLen = name.size();
-
- char *arg = nullptr;
-@@ -490,11 +485,6 @@ public:
- }
- }
- visit(static_cast<AttribDeclaration *>(decl));
--
--#if LDC_LLVM_VER >= 1800
-- #undef endswith
-- #undef startswith
--#endif
- }
-
- //////////////////////////////////////////////////////////////////////////
-diff --git a/gen/dibuilder.cpp b/gen/dibuilder.cpp
-index 21b176ef00..df1328ecdb 100644
---- a/gen/dibuilder.cpp
-+++ b/gen/dibuilder.cpp
-@@ -47,13 +47,6 @@ using namespace dmd;
- namespace cl = llvm::cl;
- using LLMetadata = llvm::Metadata;
-
--#if LDC_LLVM_VER >= 1600
--namespace llvm {
-- template <typename T> using Optional = std::optional<T>;
-- inline constexpr std::nullopt_t None = std::nullopt;
--}
--#endif
--
- static cl::opt<cl::boolOrDefault> emitColumnInfo(
- "gcolumn-info", cl::ZeroOrMore, cl::Hidden,
- cl::desc("Include column numbers in line debug infos. Defaults to "
-@@ -426,7 +419,7 @@ DIType DIBuilder::CreateEnumType(TypeEnum *type) {
- DIType DIBuilder::CreatePointerType(TypePointer *type) {
- // TODO: The addressspace is important for dcompute targets. See e.g.
- // https://www.mail-archive.com/dwarf-discuss@lists.dwarfstd.org/msg00326.html
-- const llvm::Optional<unsigned> DWARFAddressSpace = llvm::None;
-+ const std::optional<unsigned> DWARFAddressSpace;
-
- const auto name = processDIName(type->toPrettyChars(true));
-
-@@ -672,10 +665,7 @@ DIType DIBuilder::CreateCompositeType(Type *t) {
- ret = DBuilder.createClassType(
- scope, name, file, lineNum, sizeInBits, alignmentInBits,
- classOffsetInBits, DIFlags::FlagZero, derivedFrom, elemsArray,
--#if LDC_LLVM_VER >= 1800
-- runtimeLang,
--#endif
-- vtableHolder, templateParams, uniqueIdentifier);
-+ runtimeLang, vtableHolder, templateParams, uniqueIdentifier);
- } else {
- ret = DBuilder.createStructType(scope, name, file, lineNum, sizeInBits,
- alignmentInBits, DIFlags::FlagZero,
-@@ -799,7 +789,7 @@ DISubroutineType DIBuilder::CreateFunctionType(Type *type,
- DIType ditype = DBuilder.createReferenceType(
- llvm::dwarf::DW_TAG_pointer_type, pointeeType, target.ptrsize * 8);
- ditype = DBuilder.createObjectPointerType(ditype
--#if LDC_LLVM_VER >= 2000
-+#if LLVM_VERSION_MAJOR >= 20
- , /* Implicit */ true
- #endif
- );
-@@ -819,11 +809,7 @@ DISubroutineType DIBuilder::CreateFunctionType(Type *type,
- }
-
- DISubroutineType DIBuilder::CreateEmptyFunctionType() {
--#if LDC_LLVM_VER >= 2100
- auto paramsArray = DBuilder.getOrCreateTypeArray({});
--#else
-- auto paramsArray = DBuilder.getOrCreateTypeArray(llvm::None);
--#endif
- return DBuilder.createSubroutineType(paramsArray);
- }
-
-@@ -869,7 +855,7 @@ DIType DIBuilder::CreateTypeDescription(Type *t, bool voidToUbyte) {
- // display null as void*
- return DBuilder.createPointerType(
- CreateTypeDescription(Type::tvoid), target.ptrsize * 8, 0,
-- /* DWARFAddressSpace */ llvm::None, "typeof(null)");
-+ /* DWARFAddressSpace */ std::nullopt, "typeof(null)");
- }
- if (auto te = t->isTypeEnum())
- return CreateEnumType(te);
-@@ -892,7 +878,7 @@ DIType DIBuilder::CreateTypeDescription(Type *t, bool voidToUbyte) {
- const auto name =
- (tc->sym->toPrettyChars(true) + llvm::StringRef("*")).str();
- return DBuilder.createPointerType(aggregateDIType, target.ptrsize * 8, 0,
-- llvm::None, processDIName(name));
-+ std::nullopt, processDIName(name));
- }
- if (auto tf = t->isTypeFunction())
- return CreateFunctionType(tf);
-@@ -1229,7 +1215,7 @@ void DIBuilder::EmitValue(llvm::Value *val, VarDeclaration *vd) {
- auto instr = DBuilder.insertDbgValueIntrinsic(
- val, debugVariable, DBuilder.createExpression(),
- IR->ir->getCurrentDebugLocation(), IR->scopebb());
--#if LDC_LLVM_VER >= 1900
-+#if LLVM_VERSION_MAJOR >= 19
- llvm::cast<llvm::DbgRecord *>
- #endif
- (instr)->setDebugLoc(IR->ir->getCurrentDebugLocation());
-diff --git a/gen/functions.cpp b/gen/functions.cpp
-index 3c3e6d3d35..b1e106f6bc 100644
---- a/gen/functions.cpp
-+++ b/gen/functions.cpp
-@@ -773,10 +773,8 @@ static LinkageWithCOMDAT lowerFuncLinkage(FuncDeclaration *fdecl) {
- return LinkageWithCOMDAT(LLGlobalValue::ExternalLinkage, false);
- }
-
-- // A body-less declaration always needs to be marked as external in LLVM
-- // (also e.g. naked template functions which would otherwise be weak_odr,
-- // but where the definition is in module-level inline asm).
-- if (!fdecl->fbody || fdecl->isNaked()) {
-+ // A body-less declaration always needs to be marked as external in LLVM.
-+ if (!fdecl->fbody) {
- return LinkageWithCOMDAT(LLGlobalValue::ExternalLinkage, false);
- }
-
-@@ -910,10 +908,6 @@ bool eraseDummyAfterReturnBB(llvm::BasicBlock *bb) {
- * to be found.
- */
- void emulateWeakAnyLinkageForMSVC(IrFunction *irFunc, LINK linkage) {
--#if LDC_LLVM_VER >= 1800
-- #define startswith starts_with
--#endif
--
- LLFunction *func = irFunc->getLLVMFunc();
-
- const bool isWin32 = global.params.targetTriple->isArch32Bit();
-@@ -930,18 +924,18 @@ void emulateWeakAnyLinkageForMSVC(IrFunction *irFunc, LINK linkage) {
-
- std::string finalWeakMangle = finalMangle.str();
- if (linkage == LINK::cpp) {
-- assert(finalMangle.startswith("?"));
-+ assert(finalMangle.starts_with("?"));
- // prepend `__weak_` to first identifier
-- size_t offset = finalMangle.startswith("??$") ? 3 : 1;
-+ size_t offset = finalMangle.starts_with("??$") ? 3 : 1;
- finalWeakMangle.insert(offset, "__weak_");
- } else if (linkage == LINK::d) {
- const size_t offset = isWin32 ? 1 : 0;
-- assert(finalMangle.substr(offset).startswith("_D"));
-+ assert(finalMangle.substr(offset).starts_with("_D"));
- // prepend a `__weak` package
- finalWeakMangle.insert(offset + 2, "6__weak");
- } else {
- // prepend `__weak_`
-- const size_t offset = isWin32 && finalMangle.startswith("_") ? 1 : 0;
-+ const size_t offset = isWin32 && finalMangle.starts_with("_") ? 1 : 0;
- finalWeakMangle.insert(offset, "__weak_");
- }
-
-@@ -965,10 +959,6 @@ void emulateWeakAnyLinkageForMSVC(IrFunction *irFunc, LINK linkage) {
- // declaration
- irFunc->setLLVMFunc(newFunc);
- func->replaceNonMetadataUsesWith(newFunc);
--
--#if LDC_LLVM_VER >= 1800
-- #undef startswith
--#endif
- }
-
- } // anonymous namespace
-@@ -1127,12 +1117,6 @@ void DtoDefineFunction(FuncDeclaration *fd, bool linkageAvailableExternally) {
- gIR->funcGenStates.pop_back();
- };
-
-- // if this function is naked, we take over right away! no standard processing!
-- if (fd->isNaked()) {
-- DtoDefineNakedFunction(fd);
-- return;
-- }
--
- SCOPE_EXIT {
- if (irFunc->isDynamicCompiled()) {
- defineDynamicCompiledFunction(gIR, irFunc);
-@@ -1172,6 +1156,10 @@ void DtoDefineFunction(FuncDeclaration *fd, bool linkageAvailableExternally) {
- func->addFnAttr(LLAttribute::SanitizeAddress);
- }
-
-+ if (opts::isSanitizerEnabled(opts::FuzzSanitizer)) {
-+ func->addFnAttr(LLAttribute::OptForFuzzing);
-+ }
-+
- if (opts::isSanitizerEnabled(opts::MemorySanitizer & noSanitizeMask)) {
- func->addFnAttr(LLAttribute::SanitizeMemory);
- }
-@@ -1190,7 +1178,9 @@ void DtoDefineFunction(FuncDeclaration *fd, bool linkageAvailableExternally) {
- if (opts::isUsingSampleBasedPGOProfile()) {
- func->addFnAttr("use-sample-profile");
- }
--
-+ if (opts::noBuiltIn) {
-+ func->addFnAttr("no-builtins");
-+ }
- if (fd->hasInlineAsm()) {
- // disable frame-pointer-elimination for functions with DMD-style inline asm
- func->addFnAttr("frame-pointer", "all");
-@@ -1210,18 +1200,13 @@ void DtoDefineFunction(FuncDeclaration *fd, bool linkageAvailableExternally) {
- gIR->ir->setFastMathFlags(irFunc->FMF);
- gIR->DBuilder.EmitFuncStart(fd);
-
-- // @naked: emit body and return, no prologue/epilogue
-- if (func->hasFnAttribute(llvm::Attribute::Naked)) {
-- Statement_toIR(fd->fbody, gIR);
-- const bool wasDummy = eraseDummyAfterReturnBB(gIR->scopebb());
-- if (!wasDummy && !gIR->scopereturned()) {
-- // this is what clang does to prevent LLVM complaining about
-- // non-terminated function
-- gIR->ir->CreateUnreachable();
-- }
-- return;
-+ if (fd->isNaked()) { // DMD-style `asm { naked; }`
-+ func->addFnAttr(llvm::Attribute::Naked);
- }
-
-+ // @naked: emit body and return, no prologue/epilogue
-+ const bool isNaked = func->hasFnAttribute(llvm::Attribute::Naked);
-+
- // create temporary allocas block
- funcGen.allocasBlock =
- llvm::BasicBlock::Create(gIR->context(), "allocas", func);
-@@ -1229,12 +1214,12 @@ void DtoDefineFunction(FuncDeclaration *fd, bool linkageAvailableExternally) {
- emitInstrumentationFnEnter(fd);
-
- if (global.params.trace && fd->emitInstrumentation && !fd->isCMain() &&
-- !fd->isNaked()) {
-+ !isNaked) {
- emitDMDStyleFunctionTrace(*gIR, fd, funcGen);
- }
-
- // give the 'this' parameter (an lvalue) storage and debug info
-- if (irFty.arg_this) {
-+ if (!isNaked && irFty.arg_this) {
- LLValue *thisvar = irFunc->thisArg;
- assert(thisvar);
-
-@@ -1256,7 +1241,7 @@ void DtoDefineFunction(FuncDeclaration *fd, bool linkageAvailableExternally) {
- }
-
- // define all explicit parameters
-- if (fd->parameters)
-+ if (!isNaked && fd->parameters)
- defineParameters(irFty, *fd->parameters);
-
- // Initialize PGO state for this function
-@@ -1322,7 +1307,10 @@ void DtoDefineFunction(FuncDeclaration *fd, bool linkageAvailableExternally) {
-
- // pass the previous block into this block
- gIR->DBuilder.EmitStopPoint(fd->endloc);
-- if (func->getReturnType() == LLType::getVoidTy(gIR->context())) {
-+
-+ if (isNaked) {
-+ gIR->ir->CreateUnreachable();
-+ } else if (func->getReturnType() == LLType::getVoidTy(gIR->context())) {
- gIR->ir->CreateRetVoid();
- } else if (isAnyMainFunction(fd)) {
- gIR->ir->CreateRet(LLConstant::getNullValue(func->getReturnType()));
-@@ -1335,12 +1323,7 @@ void DtoDefineFunction(FuncDeclaration *fd, bool linkageAvailableExternally) {
- }
-
- // move allocas from temporary block to the start of the function
--#if LDC_LLVM_VER >= 1600
- beginbb->splice(beginbb->begin(), funcGen.allocasBlock);
--#else
-- beginbb->getInstList().splice(beginbb->begin(),
-- funcGen.allocasBlock->getInstList());
--#endif
- funcGen.allocasBlock->eraseFromParent();
- funcGen.allocasBlock = nullptr;
-
-diff --git a/gen/functions.h b/gen/functions.h
-index 5dcfa7032d..609da95620 100644
---- a/gen/functions.h
-+++ b/gen/functions.h
-@@ -40,7 +40,6 @@ void DtoResolveFunction(FuncDeclaration *fdecl);
- void DtoDeclareFunction(FuncDeclaration *fdecl);
- void DtoDefineFunction(FuncDeclaration *fd, bool linkageAvailableExternally = false);
-
--void DtoDefineNakedFunction(FuncDeclaration *fd);
- void emitABIReturnAsmStmt(IRAsmBlock *asmblock, Loc loc,
- FuncDeclaration *fdecl);
-
-diff --git a/gen/irstate.cpp b/gen/irstate.cpp
-index 6834025129..364e825763 100644
---- a/gen/irstate.cpp
-+++ b/gen/irstate.cpp
-@@ -45,14 +45,14 @@ IrFunction *IRState::func() { return &funcGen().irFunc; }
-
- llvm::Function *IRState::topfunc() { return func()->getLLVMFunc(); }
-
--#if LDC_LLVM_VER >= 1900
-+#if LLVM_VERSION_MAJOR >= 19
- llvm::BasicBlock::iterator IRState::nextAllocaPos() {
- #else
- llvm::BasicBlock *IRState::nextAllocaPos() {
- #endif
- return funcGen()
- .allocasBlock
--#if LDC_LLVM_VER >= 1900
-+#if LLVM_VERSION_MAJOR >= 19
- ->end()
- #endif
- ;
-@@ -203,9 +203,7 @@ LLGlobalVariable *
- getCachedStringLiteralImpl(llvm::Module &module,
- llvm::StringMap<LLGlobalVariable *> &cache,
- llvm::StringRef key,
--#if LDC_LLVM_VER >= 1700
- std::optional< unsigned > addrspace,
--#endif
- F initFactory) {
- auto iter = cache.find(key);
- if (iter != cache.end()) {
-@@ -214,14 +212,9 @@ getCachedStringLiteralImpl(llvm::Module &module,
-
- LLConstant *constant = initFactory();
-
-- auto gvar =
-- new LLGlobalVariable(module, constant->getType(), true,
-- LLGlobalValue::PrivateLinkage, constant,
-- ".str", nullptr, llvm::GlobalValue::NotThreadLocal
--#if LDC_LLVM_VER >= 1700
-- , addrspace
--#endif
-- );
-+ auto gvar = new LLGlobalVariable(
-+ module, constant->getType(), true, LLGlobalValue::PrivateLinkage,
-+ constant, ".str", nullptr, llvm::GlobalValue::NotThreadLocal, addrspace);
- gvar->setUnnamedAddr(LLGlobalValue::UnnamedAddr::Global);
-
- cache[key] = gvar;
-@@ -261,30 +254,18 @@ LLGlobalVariable *IRState::getCachedStringLiteral(StringExp *se) {
- const llvm::StringRef key(reinterpret_cast<const char *>(keyData.ptr),
- keyData.length);
-
-- return getCachedStringLiteralImpl(module, *cache, key,
--#if LDC_LLVM_VER >= 1700
-- std::nullopt,
--#endif
-- [se]() {
-+ return getCachedStringLiteralImpl(module, *cache, key, std::nullopt, [se]() {
- // null-terminate
- return buildStringLiteralConstant(se, se->len + 1);
- });
- }
-
--LLGlobalVariable *IRState::getCachedStringLiteral(llvm::StringRef s
--#if LDC_LLVM_VER >= 1700
-- ,std::optional< unsigned > addrspace
--#endif
-- ) {
-- return getCachedStringLiteralImpl(module,
-- cachedStringLiterals,
-- s,
--#if LDC_LLVM_VER >= 1700
-- addrspace,
--#endif
-- [&]() {
-- return llvm::ConstantDataArray::getString(context(), s, true);
-- });
-+LLGlobalVariable *
-+IRState::getCachedStringLiteral(llvm::StringRef s,
-+ std::optional<unsigned> addrspace) {
-+ return getCachedStringLiteralImpl(
-+ module, cachedStringLiterals, s, addrspace,
-+ [&]() { return llvm::ConstantDataArray::getString(context(), s, true); });
- }
-
- ////////////////////////////////////////////////////////////////////////////////
-diff --git a/gen/irstate.h b/gen/irstate.h
-index 25e963dce9..0e8983a9f7 100644
---- a/gen/irstate.h
-+++ b/gen/irstate.h
-@@ -24,10 +24,10 @@
- #include "llvm/ProfileData/InstrProfReader.h"
- #include <deque>
- #include <memory>
-+#include <optional>
- #include <set>
- #include <sstream>
- #include <vector>
--#include <optional>
-
- namespace llvm {
- class LLVMContext;
-@@ -94,9 +94,6 @@ struct IRAsmBlock {
- std::set<std::string> clobs;
- size_t outputcount;
-
-- // stores the labels within the asm block
-- std::vector<Identifier *> internalLabels;
--
- CompoundAsmStatement *asmBlock;
- LLType *retty;
- unsigned retn;
-@@ -156,7 +153,7 @@ public:
- IrFunction *func();
- llvm::Function *topfunc();
-
--#if LDC_LLVM_VER >= 1900
-+#if LLVM_VERSION_MAJOR >= 19
- llvm::BasicBlock::iterator nextAllocaPos();
- #else
- llvm::BasicBlock *nextAllocaPos();
-@@ -220,7 +217,6 @@ public:
-
- // for inline asm
- IRAsmBlock *asmBlock = nullptr;
-- std::ostringstream nakedAsm;
-
- // Globals to pin in the llvm.used array to make sure they are not
- // eliminated.
-@@ -254,11 +250,9 @@ public:
- // calls with a StringExp with matching data will return the same variable.
- // Exception: ulong[]-typed hex strings (not null-terminated either).
- llvm::GlobalVariable *getCachedStringLiteral(StringExp *se);
-- llvm::GlobalVariable *getCachedStringLiteral(llvm::StringRef s
--#if LDC_LLVM_VER >= 1700
-- ,std::optional< unsigned > = std::nullopt
--#endif
-- );
-+ llvm::GlobalVariable *
-+ getCachedStringLiteral(llvm::StringRef s,
-+ std::optional<unsigned> = std::nullopt);
-
- // List of functions with cpu or features attributes overriden by user
- std::vector<IrFunction *> targetCpuOrFeaturesOverridden;
-diff --git a/gen/llvm.h b/gen/llvm.h
-index 45f051aa93..0070894b8b 100644
---- a/gen/llvm.h
-+++ b/gen/llvm.h
-@@ -35,10 +35,10 @@ using llvm::APFloat;
- using llvm::APInt;
- using llvm::IRBuilder;
-
--#if LDC_LLVM_VER >= 2000
-+#if LLVM_VERSION_MAJOR >= 20
- #define GET_INTRINSIC_DECL(_X, _TY) \
- (llvm::Intrinsic::getOrInsertDeclaration(&gIR->module, llvm::Intrinsic::_X, _TY))
--#elif LDC_LLVM_VER >= 1900
-+#elif LLVM_VERSION_MAJOR >= 19
- #define GET_INTRINSIC_DECL(_X, _TY) \
- (llvm::Intrinsic::getDeclaration(&gIR->module, llvm::Intrinsic::_X, _TY))
- #else
-diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp
-index 0771ab54ca..83d72dcc55 100644
---- a/gen/llvmhelpers.cpp
-+++ b/gen/llvmhelpers.cpp
-@@ -1132,11 +1132,7 @@ LLConstant *DtoConstExpInit(Loc loc, Type *targetType, Expression *exp) {
- // extend i1 to i8
- if (llType->isIntegerTy(1)) {
- llType = LLType::getInt8Ty(gIR->context());
--#if LDC_LLVM_VER < 1800
-- val = llvm::ConstantExpr::getZExt(val, llType);
--#else
- val = llvm::ConstantFoldCastOperand(llvm::Instruction::ZExt, val, llType, *gDataLayout);
--#endif
- }
-
- if (llType == targetLLType)
-@@ -1196,11 +1192,7 @@ LLConstant *DtoConstExpInit(Loc loc, Type *targetType, Expression *exp) {
- "On initializer integer type mismatch, the target should be wider "
- "than the source.");
-
--#if LDC_LLVM_VER < 1800
-- return llvm::ConstantExpr::getZExtOrBitCast(val, target);
--#else
- return llvm::ConstantFoldCastOperand(llvm::Instruction::ZExt, val, target, *gDataLayout);
--#endif
- }
-
- Logger::println("Unhandled type mismatch, giving up.");
-diff --git a/gen/modules.cpp b/gen/modules.cpp
-index 569859e468..41fcc777b3 100644
---- a/gen/modules.cpp
-+++ b/gen/modules.cpp
-@@ -50,9 +50,7 @@
- #include "llvm/Support/FileSystem.h"
- #include "llvm/Support/Path.h"
- #include "llvm/Transforms/Utils/ModuleUtils.h"
--#if LDC_LLVM_VER >= 1700
- #include "llvm/Support/VirtualFileSystem.h"
--#endif
-
- #if _AIX || __sun
- #include <alloca.h>
-@@ -340,13 +338,8 @@ void loadInstrProfileData(IRState *irs) {
- IF_LOG Logger::println("Read profile data from %s",
- global.params.datafileInstrProf);
-
-- auto readerOrErr =
-- llvm::IndexedInstrProfReader::create(global.params.datafileInstrProf
--#if LDC_LLVM_VER >= 1700
-- ,
-- *llvm::vfs::getRealFileSystem()
--#endif
-- );
-+ auto readerOrErr = llvm::IndexedInstrProfReader::create(
-+ global.params.datafileInstrProf, *llvm::vfs::getRealFileSystem());
- if (auto E = readerOrErr.takeError()) {
- handleAllErrors(std::move(E), [&](const llvm::ErrorInfoBase &EI) {
- error(irs->dmodule->loc, "Could not read profile file '%s': %s",
-diff --git a/gen/ms-cxx-helper.cpp b/gen/ms-cxx-helper.cpp
-index d17cd3c677..815eb5d058 100644
---- a/gen/ms-cxx-helper.cpp
-+++ b/gen/ms-cxx-helper.cpp
-@@ -113,11 +113,7 @@ void cloneBlocks(const std::vector<llvm::BasicBlock *> &srcblocks,
- if (!newInst)
- newInst = Inst->clone();
-
--#if LDC_LLVM_VER < 1600
-- nbb->getInstList().push_back(newInst);
--#else
- newInst->insertInto(nbb, nbb->end());
--#endif
-
- VMap[Inst] = newInst; // Add instruction map to value.
- if (unwindTo)
-diff --git a/gen/naked.cpp b/gen/naked.cpp
-index 5e5b3ea653..e63ed83d55 100644
---- a/gen/naked.cpp
-+++ b/gen/naked.cpp
-@@ -27,228 +27,6 @@
-
- using namespace dmd;
-
--////////////////////////////////////////////////////////////////////////////////
--// FIXME: Integrate these functions
--void AsmStatement_toNakedIR(InlineAsmStatement *stmt, IRState *irs);
--
--////////////////////////////////////////////////////////////////////////////////
--
--class ToNakedIRVisitor : public Visitor {
-- IRState *irs;
--
--public:
-- explicit ToNakedIRVisitor(IRState *irs) : irs(irs) {}
--
-- //////////////////////////////////////////////////////////////////////////
--
-- // Import all functions from class Visitor
-- using Visitor::visit;
--
-- //////////////////////////////////////////////////////////////////////////
--
-- void visit(Statement *stmt) override {
-- error(stmt->loc, "Statement not allowed in naked function");
-- }
--
-- //////////////////////////////////////////////////////////////////////////
--
-- void visit(InlineAsmStatement *stmt) override {
-- AsmStatement_toNakedIR(stmt, irs);
-- }
--
-- //////////////////////////////////////////////////////////////////////////
--
-- void visit(CompoundStatement *stmt) override {
-- IF_LOG Logger::println("CompoundStatement::toNakedIR(): %s",
-- stmt->loc.toChars());
-- LOG_SCOPE;
--
-- if (stmt->statements) {
-- for (auto s : *stmt->statements) {
-- if (s) {
-- s->accept(this);
-- }
-- }
-- }
-- }
--
-- //////////////////////////////////////////////////////////////////////////
--
-- void visit(ExpStatement *stmt) override {
-- IF_LOG Logger::println("ExpStatement::toNakedIR(): %s",
-- stmt->loc.toChars());
-- LOG_SCOPE;
--
-- // This happens only if there is a ; at the end:
-- // asm { naked; ... };
-- // Is this a legal AST?
-- if (!stmt->exp) {
-- return;
-- }
--
-- // only expstmt supported in declarations
-- if (!stmt->exp || stmt->exp->op != EXP::declaration) {
-- visit(static_cast<Statement *>(stmt));
-- return;
-- }
--
-- DeclarationExp *d = static_cast<DeclarationExp *>(stmt->exp);
-- VarDeclaration *vd = d->declaration->isVarDeclaration();
-- FuncDeclaration *fd = d->declaration->isFuncDeclaration();
-- EnumDeclaration *ed = d->declaration->isEnumDeclaration();
--
-- // and only static variable/function declaration
-- // no locals or nested stuffies!
-- if (!vd && !fd && !ed) {
-- visit(static_cast<Statement *>(stmt));
-- return;
-- }
-- if (vd && !(vd->storage_class & (STCstatic | STCmanifest))) {
-- error(vd->loc, "non-static variable `%s` not allowed in naked function",
-- vd->toChars());
-- return;
-- }
-- if (fd && !fd->isStatic()) {
-- error(fd->loc,
-- "non-static nested function `%s` not allowed in naked function",
-- fd->toChars());
-- return;
-- }
-- // enum decls should always be safe
--
-- // make sure the symbols gets processed
-- // TODO: codegen() here is likely incorrect
-- Declaration_codegen(d->declaration, irs);
-- }
--
-- //////////////////////////////////////////////////////////////////////////
--
-- void visit(LabelStatement *stmt) override {
-- IF_LOG Logger::println("LabelStatement::toNakedIR(): %s",
-- stmt->loc.toChars());
-- LOG_SCOPE;
--
-- printLabelName(irs->nakedAsm, mangleExact(irs->func()->decl),
-- stmt->ident->toChars());
-- irs->nakedAsm << ":";
--
-- if (stmt->statement) {
-- stmt->statement->accept(this);
-- }
-- }
--};
--
--////////////////////////////////////////////////////////////////////////////////
--
--void DtoDefineNakedFunction(FuncDeclaration *fd) {
-- IF_LOG Logger::println("DtoDefineNakedFunction(%s)", mangleExact(fd));
-- LOG_SCOPE;
--
-- // we need to do special processing on the body, since we only want
-- // to allow actual inline asm blocks to reach the final asm output
--
-- std::ostringstream &asmstr = gIR->nakedAsm;
--
-- // build function header
--
-- // FIXME: could we perhaps use llvm asmwriter to give us these details ?
--
-- const char *mangle = mangleExact(fd);
-- std::string fullmangle; // buffer only
--
-- const auto &triple = *global.params.targetTriple;
-- bool const isWin = triple.isOSWindows();
-- bool const isDarwin = triple.isOSDarwin();
--
-- // osx is different
-- // also mangling has an extra underscore prefixed
-- if (isDarwin) {
-- fullmangle += '_';
-- fullmangle += mangle;
-- mangle = fullmangle.c_str();
--
-- asmstr << "\t.section\t__TEXT,__text,regular,pure_instructions"
-- << std::endl;
-- asmstr << "\t.globl\t" << mangle << std::endl;
-- if (fd->isInstantiated()) {
-- asmstr << "\t.weak_definition\t" << mangle << std::endl;
-- }
-- asmstr << "\t.p2align\t4, 0x90" << std::endl;
-- asmstr << mangle << ":" << std::endl;
-- }
-- // Windows is different
-- else if (isWin) {
-- // mangled names starting with '?' (MSVC++ symbols) apparently need quoting
-- if (mangle[0] == '?') {
-- fullmangle += '"';
-- fullmangle += mangle;
-- fullmangle += '"';
-- mangle = fullmangle.c_str();
-- } else if (triple.isArch32Bit()) {
-- // prepend extra underscore for Windows x86
-- fullmangle += '_';
-- fullmangle += mangle;
-- mangle = fullmangle.c_str();
-- }
--
-- asmstr << "\t.def\t" << mangle << ";" << std::endl;
-- // hard code these two numbers for now since gas ignores .scl and llvm
-- // is defaulting to .type 32 for everything I have seen
-- asmstr << "\t.scl\t2;" << std::endl;
-- asmstr << "\t.type\t32;" << std::endl;
-- asmstr << "\t.endef" << std::endl;
--
-- if (fd->isInstantiated()) {
-- asmstr << "\t.section\t.text,\"xr\",discard," << mangle << std::endl;
-- } else {
-- asmstr << "\t.text" << std::endl;
-- }
-- asmstr << "\t.globl\t" << mangle << std::endl;
-- asmstr << "\t.p2align\t4, 0x90" << std::endl;
-- asmstr << mangle << ":" << std::endl;
-- } else {
-- if (fd->isInstantiated()) {
-- asmstr << "\t.section\t.text." << mangle << ",\"axG\", at progbits,"
-- << mangle << ",comdat" << std::endl;
-- asmstr << "\t.weak\t" << mangle << std::endl;
-- } else {
-- asmstr << "\t.text" << std::endl;
-- asmstr << "\t.globl\t" << mangle << std::endl;
-- }
-- asmstr << "\t.p2align\t4, 0x90" << std::endl;
-- asmstr << "\t.type\t" << mangle << ", at function" << std::endl;
-- asmstr << mangle << ":" << std::endl;
-- }
--
-- // emit body
-- ToNakedIRVisitor v(gIR);
-- fd->fbody->accept(&v);
--
-- // We could have generated new errors in toNakedIR(), but we are in codegen
-- // already so we have to abort here.
-- if (global.errors) {
-- fatal();
-- }
--
-- // emit size after body
-- // llvm does this on linux, but not on osx or Win
-- if (!(isWin || isDarwin)) {
-- asmstr << "\t.size\t" << mangle << ", .-" << mangle << std::endl
-- << std::endl;
-- }
--
-- gIR->module.appendModuleInlineAsm(asmstr.str());
-- asmstr.str("");
--
-- if (global.params.dllexport ||
-- (global.params.targetTriple->isOSWindows() && fd->isExport())) {
-- // Embed a linker switch telling the MS linker to export the naked function.
-- // This mimics the effect of the dllexport attribute for regular functions.
-- const auto linkerSwitch = std::string("/EXPORT:") + mangle;
-- gIR->addLinkerOption(llvm::StringRef(linkerSwitch));
-- }
--}
--
- ////////////////////////////////////////////////////////////////////////////////
-
- void emitABIReturnAsmStmt(IRAsmBlock *asmblock, Loc loc,
-@@ -436,7 +214,7 @@ DValue *DtoInlineAsmExpr(Loc loc, FuncDeclaration *fd,
- LLSmallVector<LLValue *, 8> operands;
- LLSmallVector<LLType *, 8> indirectTypes;
- operands.reserve(n);
--
-+
- Type *returnType = fd->type->nextOf();
- const size_t cisize = constraintInfo.size();
- const size_t minRequired = n + (returnType->ty == TY::Tvoid ? 0 : 1);
-diff --git a/gen/optimizer.cpp b/gen/optimizer.cpp
-index 7029959452..e418774715 100644
---- a/gen/optimizer.cpp
-+++ b/gen/optimizer.cpp
-@@ -36,11 +36,7 @@
- #include "driver/targetmachine.h"
- #endif
-
--#if LDC_LLVM_VER < 1700
--#include "llvm/ADT/Triple.h"
--#else
- #include "llvm/TargetParser/Triple.h"
--#endif
- #include "llvm/Analysis/InlineCost.h"
- #include "llvm/Analysis/TargetLibraryInfo.h"
- #include "llvm/Analysis/TargetTransformInfo.h"
-@@ -52,15 +48,12 @@
- #include "llvm/LinkAllPasses.h"
- #include "llvm/Support/CommandLine.h"
- #include "llvm/Target/TargetMachine.h"
--#if LDC_LLVM_VER >= 2000
-+#if LLVM_VERSION_MAJOR >= 20
- #include "llvm/Transforms/Utils/Instrumentation.h"
- #else
- #include "llvm/Transforms/Instrumentation.h"
- #endif
- #include "llvm/Transforms/IPO.h"
--#if LDC_LLVM_VER < 1700
--#include "llvm/Transforms/IPO/PassManagerBuilder.h"
--#endif
- #include "llvm/Transforms/Instrumentation/MemorySanitizer.h"
- #include "llvm/Transforms/Instrumentation/ThreadSanitizer.h"
- #include "llvm/Transforms/Instrumentation/AddressSanitizer.h"
-@@ -212,7 +205,7 @@ static OptimizationLevel getOptimizationLevel(){
- #ifndef IN_JITRT
- static void addAddressSanitizerPasses(ModulePassManager &mpm,
- OptimizationLevel level
--#if LDC_LLVM_VER >= 2000
-+#if LLVM_VERSION_MAJOR >= 20
- ,
- ThinOrFullLTOPhase
- #endif
-@@ -223,11 +216,7 @@ static void addAddressSanitizerPasses(ModulePassManager &mpm,
- aso.UseAfterScope = true;
- aso.UseAfterReturn = opts::fSanitizeAddressUseAfterReturn;
-
--#if LDC_LLVM_VER >= 1600
- mpm.addPass(AddressSanitizerPass(aso));
--#else
-- mpm.addPass(ModuleAddressSanitizerPass(aso));
--#endif
- }
-
- static void addMemorySanitizerPass(ModulePassManager &mpm,
-@@ -236,13 +225,8 @@ static void addMemorySanitizerPass(ModulePassManager &mpm,
- int trackOrigins = fSanitizeMemoryTrackOrigins;
- bool recover = opts::isSanitizerRecoveryEnabled(opts::MemorySanitizer);
- bool kernel = false;
--#if LDC_LLVM_VER >= 1600
- mpm.addPass(MemorySanitizerPass(
- MemorySanitizerOptions{trackOrigins, recover, kernel}));
--#else
-- fpm.addPass(MemorySanitizerPass(
-- MemorySanitizerOptions{trackOrigins, recover, kernel}));
--#endif
-
- // MemorySanitizer inserts complex instrumentation that mostly follows
- // the logic of the original code, but operates on "shadow" values.
-@@ -260,7 +244,7 @@ static void addMemorySanitizerPass(ModulePassManager &mpm,
- }
- static void addThreadSanitizerPass(ModulePassManager &mpm,
- OptimizationLevel level
--#if LDC_LLVM_VER >= 2000
-+#if LLVM_VERSION_MAJOR >= 20
- ,
- ThinOrFullLTOPhase
- #endif
-@@ -271,18 +255,13 @@ static void addThreadSanitizerPass(ModulePassManager &mpm,
-
- static void addSanitizerCoveragePass(ModulePassManager &mpm,
- OptimizationLevel level
--#if LDC_LLVM_VER >= 2000
-+#if LLVM_VERSION_MAJOR >= 20
- ,
- ThinOrFullLTOPhase
- #endif
- ) {
--#if LDC_LLVM_VER >= 1600
- mpm.addPass(SanitizerCoveragePass(
- opts::getSanitizerCoverageOptions()));
--#else
-- mpm.addPass(ModuleSanitizerCoveragePass(
-- opts::getSanitizerCoverageOptions()));
--#endif
- }
- // Adds PGO instrumentation generation and use passes.
- static void addPGOPasses(ModulePassManager &mpm, OptimizationLevel level) {
-@@ -291,13 +270,7 @@ static void addPGOPasses(ModulePassManager &mpm, OptimizationLevel level) {
- options.NoRedZone = global.params.disableRedZone;
- if (global.params.datafileInstrProf)
- options.InstrProfileOutput = global.params.datafileInstrProf;
-- mpm.addPass(
--#if LDC_LLVM_VER < 1800
-- InstrProfiling(options)
--#else
-- InstrProfilingLoweringPass(options)
--#endif // LDC_LLVM_VER < 1800
-- );
-+ mpm.addPass(InstrProfilingLoweringPass(options));
- } else if (opts::isUsingASTBasedPGOProfile()) {
- // We are generating code with PGO profile information available.
- // Do indirect call promotion from -O1
-@@ -310,7 +283,7 @@ static void addPGOPasses(ModulePassManager &mpm, OptimizationLevel level) {
-
- static void addStripExternalsPass(ModulePassManager &mpm,
- OptimizationLevel level
--#if LDC_LLVM_VER >= 2000
-+#if LLVM_VERSION_MAJOR >= 20
- ,
- ThinOrFullLTOPhase
- #endif
-@@ -327,7 +300,7 @@ static void addStripExternalsPass(ModulePassManager &mpm,
-
- static void addSimplifyDRuntimeCallsPass(ModulePassManager &mpm,
- OptimizationLevel level
--#if LDC_LLVM_VER >= 2000
-+#if LLVM_VERSION_MAJOR >= 20
- ,
- ThinOrFullLTOPhase
- #endif
-@@ -342,7 +315,7 @@ static void addSimplifyDRuntimeCallsPass(ModulePassManager &mpm,
-
- static void addGarbageCollect2StackPass(ModulePassManager &mpm,
- OptimizationLevel level
--#if LDC_LLVM_VER >= 2000
-+#if LLVM_VERSION_MAJOR >= 20
- ,
- ThinOrFullLTOPhase
- #endif
-@@ -356,58 +329,48 @@ static void addGarbageCollect2StackPass(ModulePassManager &mpm,
- }
-
- #ifndef IN_JITRT
--static llvm::Optional<PGOOptions> getPGOOptions() {
-+static std::optional<PGOOptions> getPGOOptions() {
- // FIXME: Do we have these anywhere?
- bool debugInfoForProfiling = false;
- bool pseudoProbeForProfiling = false;
- if (opts::isInstrumentingForIRBasedPGO()) {
- return PGOOptions(
- global.params.datafileInstrProf, "", "",
--#if LDC_LLVM_VER >= 1700
- "" /*MemoryProfileUsePath*/,
--#if LDC_LLVM_VER < 2200
-+#if LLVM_VERSION_MAJOR < 22
- llvm::vfs::getRealFileSystem(),
--#endif
- #endif
- PGOOptions::PGOAction::IRInstr, PGOOptions::CSPGOAction::NoCSAction,
--#if LDC_LLVM_VER >= 1900
-+#if LLVM_VERSION_MAJOR >= 19
- PGOOptions::ColdFuncOpt::Default,
- #endif
- debugInfoForProfiling, pseudoProbeForProfiling);
- } else if (opts::isUsingIRBasedPGOProfile()) {
- return PGOOptions(
- global.params.datafileInstrProf, "", "",
--#if LDC_LLVM_VER >= 1700
- "" /*MemoryProfileUsePath*/,
--#if LDC_LLVM_VER < 2200
-+#if LLVM_VERSION_MAJOR < 22
- llvm::vfs::getRealFileSystem(),
--#endif
- #endif
- PGOOptions::PGOAction::IRUse, PGOOptions::CSPGOAction::NoCSAction,
--#if LDC_LLVM_VER >= 1900
-+#if LLVM_VERSION_MAJOR >= 19
- PGOOptions::ColdFuncOpt::Default,
- #endif
- debugInfoForProfiling, pseudoProbeForProfiling);
- } else if (opts::isUsingSampleBasedPGOProfile()) {
- return PGOOptions(
- global.params.datafileInstrProf, "", "",
--#if LDC_LLVM_VER >= 1700
- "" /*MemoryProfileUsePath*/,
--#if LDC_LLVM_VER < 2200
-+#if LLVM_VERSION_MAJOR < 22
- llvm::vfs::getRealFileSystem(),
--#endif
- #endif
- PGOOptions::PGOAction::SampleUse, PGOOptions::CSPGOAction::NoCSAction,
--#if LDC_LLVM_VER >= 1900
-+#if LLVM_VERSION_MAJOR >= 19
- PGOOptions::ColdFuncOpt::Default,
- #endif
- debugInfoForProfiling, pseudoProbeForProfiling);
- }
--#if LDC_LLVM_VER < 1600
-- return None;
--#else
- return std::nullopt;
--#endif
- }
- #endif // !IN_JITRT
-
-@@ -472,17 +435,9 @@ void runOptimizationPasses(llvm::Module *M, llvm::TargetMachine *TM) {
- bool debugLogging = false;
- ppo.Indent = false;
- ppo.SkipAnalyses = false;
--#if LDC_LLVM_VER < 1600
-- StandardInstrumentations si(debugLogging, /*VerifyEach=*/false, ppo);
--#else
- StandardInstrumentations si(M->getContext(), debugLogging, /*VerifyEach=*/false, ppo);
--#endif
-
--#if LDC_LLVM_VER < 1700
-- si.registerCallbacks(pic, &fam);
--#else
- si.registerCallbacks(pic, &mam);
--#endif
-
- PassBuilder pb(TM, getPipelineTuningOptions(optLevelVal, sizeLevelVal),
- #ifdef IN_JITRT
-@@ -566,14 +521,14 @@ void runOptimizationPasses(llvm::Module *M, llvm::TargetMachine *TM) {
-
- if (optLevelVal == 0) {
- #ifdef IN_JITRT
--#if LDC_LLVM_VER >= 2000
-+#if LLVM_VERSION_MAJOR >= 20
- const ThinOrFullLTOPhase ltoPrelink = ThinOrFullLTOPhase::None;
- #else
- const bool ltoPrelink = false;
--#endif // LDC_LLVM_VER >= 2000
-+#endif
- mpm = pb.buildO0DefaultPipeline(level, ltoPrelink);
--#else
--#if LDC_LLVM_VER >= 2000
-+#else // !IN_JITRT
-+#if LLVM_VERSION_MAJOR >= 20
- const ThinOrFullLTOPhase ltoPrelink =
- opts::isUsingLTO()
- ? (opts::isUsingThinLTO() ? ThinOrFullLTOPhase::ThinLTOPreLink
-@@ -581,15 +536,13 @@ void runOptimizationPasses(llvm::Module *M, llvm::TargetMachine *TM) {
- : ThinOrFullLTOPhase::None;
- #else
- const bool ltoPrelink = opts::isUsingLTO();
--#endif // LDC_LLVM_VER >= 2000
-+#endif
- mpm = pb.buildO0DefaultPipeline(level, ltoPrelink);
--#if LDC_LLVM_VER >= 1700
- } else if (opts::ltoFatObjects && opts::isUsingLTO()) {
- mpm = pb.buildFatLTODefaultPipeline(level,
- opts::isUsingThinLTO(),
- opts::isUsingThinLTO()
- );
--#endif
- } else if (opts::isUsingThinLTO()) {
- mpm = pb.buildThinLTOPreLinkDefaultPipeline(level);
- } else if (opts::isUsingLTO()) {
-diff --git a/gen/optimizer.h b/gen/optimizer.h
-index 8ba3521a28..688b654069 100644
---- a/gen/optimizer.h
-+++ b/gen/optimizer.h
-@@ -19,12 +19,6 @@
-
- #include "llvm/Support/CommandLine.h"
-
--namespace llvm {
--#if LDC_LLVM_VER < 1800
--using CodeGenOptLevel = llvm::CodeGenOpt::Level;
--#endif
--}
--
- namespace llvm {
- class raw_ostream;
- }
-diff --git a/gen/passes/DLLImportRelocation.cpp b/gen/passes/DLLImportRelocation.cpp
-index d2dc6c8369..288f71cbfd 100644
---- a/gen/passes/DLLImportRelocation.cpp
-+++ b/gen/passes/DLLImportRelocation.cpp
-@@ -272,11 +272,7 @@ bool DLLImportRelocation::run(Module &m) {
- Impl impl(m);
- bool hasChanged = false;
-
--#if LDC_LLVM_VER >= 1700
- for (GlobalVariable &global : m.globals()) {
--#else
-- for (GlobalVariable &global : m.getGlobalList()) {
--#endif
- // TODO: thread-local globals would need to be initialized in a separate TLS
- // ctor
- if (!global.hasInitializer() || global.isThreadLocal())
-diff --git a/gen/passes/GarbageCollect2Stack.cpp b/gen/passes/GarbageCollect2Stack.cpp
-index 4c9b82c0c8..a788789c86 100644
---- a/gen/passes/GarbageCollect2Stack.cpp
-+++ b/gen/passes/GarbageCollect2Stack.cpp
-@@ -24,7 +24,7 @@
- #include "llvm/ADT/Statistic.h"
- #include "llvm/ADT/StringMap.h"
- #include "llvm/ADT/StringSwitch.h"
--#if LDC_LLVM_VER >= 2100
-+#if LLVM_VERSION_MAJOR >= 21
- #include "llvm/IR/AbstractCallSite.h"
- #endif
- #include "llvm/IR/Constants.h"
-@@ -100,7 +100,7 @@ Value* FunctionInfo::promote(CallBase *CB, IRBuilder<> &B, const G2StackAnalysis
- // FIXME: set alignment on alloca?
- return new AllocaInst(
- Ty, BB.getModule()->getDataLayout().getAllocaAddrSpace(), ".nongc_mem",
--#if LDC_LLVM_VER >= 1900
-+#if LLVM_VERSION_MAJOR >= 19
- BB.begin()
- #else
- &(*BB.begin())
-@@ -352,7 +352,7 @@ static void RemoveCall(CallBase *CB, const G2StackAnalysis &A) {
- // the dominator tree here.
- if (auto Invoke = dyn_cast<InvokeInst>(static_cast<Instruction *>(CB))) {
- BranchInst::Create(Invoke->getNormalDest(),
--#if LDC_LLVM_VER >= 1900
-+#if LLVM_VERSION_MAJOR >= 19
- Invoke->getIterator()
- #else
- Invoke
-@@ -363,7 +363,7 @@ static void RemoveCall(CallBase *CB, const G2StackAnalysis &A) {
-
- // Remove the runtime call.
- if (A.CGNode) {
--#if LDC_LLVM_VER >= 2100
-+#if LLVM_VERSION_MAJOR >= 21
- //FIXME: Look into using `LazyCallGraph` and the new pass manager
- for (auto I = A.CGNode->begin(); ; I++) {
- assert(I != A.CGNode->end() && "Cannot find callsite to remove!");
-@@ -755,7 +755,7 @@ bool isSafeToStackAllocate(BasicBlock::iterator Alloc, Value *V,
- auto B = CB->arg_begin(), E = CB->arg_end();
- for (auto A = B; A != E; ++A) {
- if (A->get() == V) {
--#if LDC_LLVM_VER >= 2100
-+#if LLVM_VERSION_MAJOR >= 21
- if (!(CB->paramHasAttr(A - B, llvm::Attribute::AttrKind::Captures) &&
- capturesNothing(
- CB->getParamAttr(A - B, llvm::Attribute::AttrKind::Captures)
-diff --git a/gen/passes/SimplifyDRuntimeCalls.cpp b/gen/passes/SimplifyDRuntimeCalls.cpp
-index 9dd672f20b..fd698cfeb9 100644
---- a/gen/passes/SimplifyDRuntimeCalls.cpp
-+++ b/gen/passes/SimplifyDRuntimeCalls.cpp
-@@ -160,7 +160,7 @@ Value *ArraySliceCopyOpt::CallOptimizer(Function *Callee, CallInst *CI,
- Sz = (Int->getValue() * ElemSz->getValue()).getZExtValue();
- }
-
--#if LDC_LLVM_VER >= 2100
-+#if LLVM_VERSION_MAJOR >= 21
- llvm::LocationSize Sz2 =
- (Sz == llvm::MemoryLocation::UnknownSize)
- ? llvm::LocationSize::beforeOrAfterPointer()
-diff --git a/gen/pgo_ASTbased.cpp b/gen/pgo_ASTbased.cpp
-index 723cabdd95..c1937b5539 100644
---- a/gen/pgo_ASTbased.cpp
-+++ b/gen/pgo_ASTbased.cpp
-@@ -38,13 +38,17 @@ llvm::cl::opt<bool, false, opts::FlagParser<bool>> enablePGOIndirectCalls(
- "pgo-indirect-calls", llvm::cl::ZeroOrMore, llvm::cl::Hidden,
- llvm::cl::desc("(*) Enable PGO of indirect calls"),
- llvm::cl::init(true));
--}
-
--#if LDC_LLVM_VER >= 1800
--namespace llvm::support {
-- const auto little = llvm::endianness::little;
--}
-+uint64_t inLittleEndian(uint64_t x) {
-+#if LLVM_VERSION_MAJOR >= 22
-+ return llvm::support::endian::byte_swap<uint64_t>(x,
-+ llvm::endianness::little);
-+#else
-+ return llvm::support::endian::byte_swap<uint64_t, llvm::endianness::little>(
-+ x);
- #endif
-+}
-+} // anonymous namespace
-
- /// \brief Stable hasher for PGO region counters.
- ///
-@@ -121,8 +125,7 @@ public:
-
- // Pass through MD5 if enough work has built up.
- if (Count && Count % NumTypesPerWord == 0) {
-- using namespace llvm::support;
-- uint64_t Swapped = endian::byte_swap<uint64_t, little>(Working);
-+ uint64_t Swapped = inLittleEndian(Working);
- MD5.update(llvm::ArrayRef<uint8_t>((uint8_t *)&Swapped, sizeof(Swapped)));
- Working = 0;
- }
-@@ -142,8 +145,7 @@ public:
-
- // Check for remaining work in Working.
- if (Working) {
-- using namespace llvm::support;
-- uint64_t Swapped = endian::byte_swap<uint64_t, little>(Working);
-+ uint64_t Swapped = inLittleEndian(Working);
- MD5.update(llvm::ArrayRef<uint8_t>((uint8_t *)&Swapped, sizeof(Swapped)));
- }
-
-@@ -924,11 +926,7 @@ void CodeGenPGO::loadRegionCounts(llvm::IndexedInstrProfReader *PGOReader,
- auto EC = RecordExpected.takeError();
-
- if (EC) {
--#if LDC_LLVM_VER >= 1700
- auto IPE = std::get<0>(llvm::InstrProfError::take(std::move(EC)));
--#else
-- auto IPE = llvm::InstrProfError::take(std::move(EC));
--#endif
- if (IPE == llvm::instrprof_error::unknown_function) {
- IF_LOG Logger::println("No profile data for function: %s",
- FuncName.c_str());
-diff --git a/gen/runtime.cpp b/gen/runtime.cpp
-index 5d3cbb6ebf..7ac04957e1 100644
---- a/gen/runtime.cpp
-+++ b/gen/runtime.cpp
-@@ -32,9 +32,7 @@
- #include "ir/irtypefunction.h"
- #include "llvm/Bitcode/BitcodeWriter.h"
- #include "llvm/IR/Attributes.h"
--#if LDC_LLVM_VER >= 1600
- #include "llvm/Support/ModRef.h"
--#endif
- #include "llvm/IR/Module.h"
- #include "llvm/Support/CommandLine.h"
- #include "llvm/Support/MemoryBuffer.h"
-@@ -511,15 +509,9 @@ static void buildRuntimeModule() {
- // `readonly`
- {
- auto addReadOnly = [&](AttrSet& a) {
--#if LDC_LLVM_VER >= 1600
- a = a.merge(AttrSet(llvm::AttributeList().addFnAttribute(
- context, llvm::Attribute::getWithMemoryEffects(
- context, llvm::MemoryEffects::readOnly()))));
--#else
-- llvm::AttrBuilder ab(context);
-- ab.addAttribute(llvm::Attribute::ReadOnly);
-- a = a.addToFunction(ab);
--#endif
- };
- addReadOnly(Attr_ReadOnly);
- addReadOnly(Attr_ReadOnly_NoUnwind);
-@@ -542,7 +534,7 @@ static void buildRuntimeModule() {
- {
- auto addCapturesNone = [&](int extra, AttrSet& a) {
- llvm::AttrBuilder ab(context);
--#if LDC_LLVM_VER >= 2100
-+#if LLVM_VERSION_MAJOR >= 21
- ab.addCapturesAttr(llvm::CaptureInfo::none());
- #else
- ab.addAttribute(llvm::Attribute::NoCapture);
-diff --git a/gen/semantic-dcompute.cpp b/gen/semantic-dcompute.cpp
-index 5fe5f64e16..1cf3fb4843 100644
---- a/gen/semantic-dcompute.cpp
-+++ b/gen/semantic-dcompute.cpp
-@@ -92,6 +92,9 @@ struct DComputeSemanticAnalyser : public StoppableVisitor {
- return;
- }
-
-+ if (!decl->type)
-+ return;
-+
- if (decl->type->ty == TY::Taarray) {
- error(decl->loc, "associative arrays not allowed in `@compute` code");
- stop = true;
-diff --git a/gen/statements.cpp b/gen/statements.cpp
-index 1bdd3cef30..004fba0656 100644
---- a/gen/statements.cpp
-+++ b/gen/statements.cpp
-@@ -431,7 +431,11 @@ public:
- if (llvm::ConstantInt *const_val = llvm::dyn_cast<llvm::ConstantInt>(cond_val)) {
- Statement *executed = stmt->ifbody;
- Statement *skipped = stmt->elsebody;
-+#if LLVM_VERSION_MAJOR >= 21
-+ if (const_val->isZero()) {
-+#else
- if (const_val->isZeroValue()) {
-+#endif
- std::swap(executed, skipped);
- }
- if (!containsLabel(skipped)) {
-@@ -441,7 +445,11 @@ public:
- irs->DBuilder.EmitBlockStart(executed->loc);
- }
- // True condition, the branch is taken so emit counter increment.
-+#if LLVM_VERSION_MAJOR >= 21
-+ if (!const_val->isZero()) {
-+#else
- if (!const_val->isZeroValue()) {
-+#endif
- PGO.emitCounterIncrement(stmt);
- }
- if (executed) {
-@@ -1542,17 +1550,21 @@ public:
- auto &PGO = irs->funcGen().pgo;
- PGO.setCurrentStmt(stmt);
-
-+ auto fd = irs->func()->decl;
-+
-+ const auto getFullAsmLabelString = [stmt, fd]() {
-+ std::stringstream s;
-+ printLabelName(s, mangleExact(fd), stmt->ident->toChars());
-+ s << ":";
-+ return s.str();
-+ };
-+
- // if it's an inline asm label, we don't create a basicblock, just emit it
- // in the asm
- if (irs->asmBlock) {
- auto a = new IRAsmStmt;
-- std::stringstream label;
-- printLabelName(label, mangleExact(irs->func()->decl),
-- stmt->ident->toChars());
-- label << ":";
-- a->code = label.str();
-+ a->code = getFullAsmLabelString();
- irs->asmBlock->s.push_back(a);
-- irs->asmBlock->internalLabels.push_back(stmt->ident);
-
- // disable inlining
- irs->func()->setNeverInline();
-@@ -1566,6 +1578,13 @@ public:
- }
-
- irs->ir->SetInsertPoint(labelBB);
-+
-+ // in a naked DMD-style inline-asm function, create an assembly label too
-+ // (so that inline-asm can jump to it directly)
-+ if (fd->isNaked()) {
-+ DtoInlineAsmExpr(stmt->loc, getFullAsmLabelString(), "", {}, {},
-+ irs->ir->getVoidTy());
-+ }
- }
-
- PGO.emitCounterIncrement(stmt);
-diff --git a/gen/target.cpp b/gen/target.cpp
-index 7f77923a39..16622a9922 100644
---- a/gen/target.cpp
-+++ b/gen/target.cpp
-@@ -83,10 +83,8 @@ llvm::Type *getRealType(const llvm::Triple &triple) {
-
- case Triple::riscv32:
- case Triple::riscv64:
--#if LDC_LLVM_VER >= 1600
- case Triple::loongarch32:
- case Triple::loongarch64:
--#endif // LDC_LLVM_VER >= 1600
- return LLType::getFP128Ty(ctx);
-
- case Triple::wasm32:
-diff --git a/gen/tocall.cpp b/gen/tocall.cpp
-index edc5ef837c..c1b0bc1b3c 100644
---- a/gen/tocall.cpp
-+++ b/gen/tocall.cpp
-@@ -1045,7 +1045,7 @@ DValue *DtoCallFunction(Loc loc, Type *resulttype, DValue *fnval,
- if (cf->isIntrinsic()) { // override intrinsic attrs
- attrlist =
- llvm::Intrinsic::getAttributes(gIR->context(), cf->getIntrinsicID()
--#if LDC_LLVM_VER >= 2100
-+#if LLVM_VERSION_MAJOR >= 21
- ,cf->getFunctionType()
- #endif
- );
-diff --git a/gen/toconstelem.cpp b/gen/toconstelem.cpp
-index c32f6f4a7b..9ded6dddc0 100644
---- a/gen/toconstelem.cpp
-+++ b/gen/toconstelem.cpp
-@@ -522,11 +522,7 @@ public:
- // extend i1 to i8
- if (c->getType()->isIntegerTy(1)) {
- LLType *I8PtrTy = LLType::getInt8Ty(p->context());
--#if LDC_LLVM_VER < 1800
-- c = llvm::ConstantExpr::getZExt(c, I8PtrTy);
--#else
- c = llvm::ConstantFoldCastOperand(llvm::Instruction::ZExt, c, I8PtrTy, *gDataLayout);
--#endif
- }
- varInits[e->sd->fields[i]] = c;
- }
-diff --git a/gen/toir.cpp b/gen/toir.cpp
-index 0a22d1b0d5..e746c6bbcd 100644
---- a/gen/toir.cpp
-+++ b/gen/toir.cpp
-@@ -1016,11 +1016,7 @@ public:
- }
-
- static llvm::PointerType * getWithSamePointeeType(llvm::PointerType *p, unsigned addressSpace) {
--#if LDC_LLVM_VER >= 1700
- return llvm::PointerType::get(p->getContext(), addressSpace);
--#else
-- return llvm::PointerType::getWithSamePointeeType(p, addressSpace);
--#endif
- }
-
- //////////////////////////////////////////////////////////////////////////////
-diff --git a/gen/trycatchfinally.cpp b/gen/trycatchfinally.cpp
-index b486228874..510e0c0ac6 100644
---- a/gen/trycatchfinally.cpp
-+++ b/gen/trycatchfinally.cpp
-@@ -323,7 +323,7 @@ CleanupScope::CleanupScope(llvm::BasicBlock *beginBlock,
- }
-
- namespace {
--#if LDC_LLVM_VER >= 1900
-+#if LLVM_VERSION_MAJOR >= 19
- llvm::BasicBlock::iterator getTerminatorPos(llvm::BasicBlock *bb) {
- auto it = bb->rbegin().getReverse();
- assert(it->isTerminator());
-diff --git a/gen/uda.cpp b/gen/uda.cpp
-index a89c2c1e75..63f84e5699 100644
---- a/gen/uda.cpp
-+++ b/gen/uda.cpp
-@@ -210,11 +210,7 @@ void applyAttrAllocSize(StructLiteralExp *sle, IrFunction *irFunc) {
- if (numArgIdx >= 0) {
- builder.addAllocSizeAttr(llvmSizeIdx, llvmNumIdx);
- } else {
--#if LDC_LLVM_VER < 1600
-- builder.addAllocSizeAttr(llvmSizeIdx, llvm::Optional<unsigned>());
--#else
- builder.addAllocSizeAttr(llvmSizeIdx, std::optional<unsigned>());
--#endif
- }
-
- llvm::Function *func = irFunc->getLLVMFunc();
-@@ -307,10 +303,6 @@ void applyAttrTarget(StructLiteralExp *sle, llvm::Function *func,
- // The current implementation here does not do any checking of the specified
- // string and simply passes all to llvm.
-
--#if LDC_LLVM_VER >= 1800
-- #define startswith starts_with
--#endif
--
- checkStructElems(sle, {Type::tstring});
- llvm::StringRef targetspec = getFirstElemString(sle);
-
-@@ -338,20 +330,20 @@ void applyAttrTarget(StructLiteralExp *sle, llvm::Function *func,
- if (s.empty())
- continue;
-
-- if (s.startswith("arch=")) {
-+ if (s.starts_with("arch=")) {
- // TODO: be smarter than overwriting the previous arch= setting
- CPU = s.drop_front(5);
- continue;
- }
-- if (s.startswith("tune=")) {
-+ if (s.starts_with("tune=")) {
- // clang 3.8 ignores tune= too
- continue;
- }
-- if (s.startswith("fpmath=")) {
-+ if (s.starts_with("fpmath=")) {
- // TODO: implementation; clang 3.8 ignores fpmath= too
- continue;
- }
-- if (s.startswith("no-")) {
-+ if (s.starts_with("no-")) {
- std::string f = (std::string("-") + s.drop_front(3)).str();
- features.emplace_back(std::move(f));
- continue;
-@@ -370,10 +362,6 @@ void applyAttrTarget(StructLiteralExp *sle, llvm::Function *func,
- llvm::join(features.begin(), features.end(), ","));
- irFunc->targetFeaturesOverridden = true;
- }
--
--#if LDC_LLVM_VER >= 1800
-- #undef startswith
--#endif
- }
-
- void applyAttrAssumeUsed(IRState &irs, StructLiteralExp *sle,
-@@ -438,11 +426,7 @@ bool parseCallingConvention(llvm::StringRef name,
- .Case("intel_ocl_bicc", llvm::CallingConv::Intel_OCL_BI)
- .Case("x86_64_sysvcc", llvm::CallingConv::X86_64_SysV)
- .Case("win64cc", llvm::CallingConv::Win64)
--#if LDC_LLVM_VER >= 1800
- .Case("webkit_jscc", llvm::CallingConv::WASM_EmscriptenInvoke)
--#else
-- .Case("webkit_jscc", llvm::CallingConv::WebKit_JS)
--#endif
- .Case("anyregcc", llvm::CallingConv::AnyReg)
- .Case("preserve_mostcc", llvm::CallingConv::PreserveMost)
- .Case("preserve_allcc", llvm::CallingConv::PreserveAll)
-@@ -450,13 +434,8 @@ bool parseCallingConvention(llvm::StringRef name,
- .Case("swiftcc", llvm::CallingConv::Swift)
- .Case("swifttailcc", llvm::CallingConv::SwiftTail)
- .Case("x86_intrcc", llvm::CallingConv::X86_INTR)
--#if LDC_LLVM_VER >= 1700
- .Case("hhvmcc", llvm::CallingConv::DUMMY_HHVM)
- .Case("hhvm_ccc", llvm::CallingConv::DUMMY_HHVM_C)
--#else
-- .Case("hhvmcc", llvm::CallingConv::HHVM)
-- .Case("hhvm_ccc", llvm::CallingConv::HHVM_C)
--#endif
- .Case("cxx_fast_tlscc", llvm::CallingConv::CXX_FAST_TLS)
- .Case("amdgpu_vs", llvm::CallingConv::AMDGPU_VS)
- .Case("amdgpu_gfx", llvm::CallingConv::AMDGPU_Gfx)
-diff --git a/gen/variable_lifetime.cpp b/gen/variable_lifetime.cpp
-index ed0b772dbf..717760881e 100644
---- a/gen/variable_lifetime.cpp
-+++ b/gen/variable_lifetime.cpp
-@@ -53,7 +53,7 @@ void LocalVariableLifetimeAnnotator::addLocalVariable(llvm::AllocaInst *address,
-
- // Emit lifetime start
- irs.CreateCallOrInvoke(getLLVMLifetimeStartFn(),
--#if LDC_LLVM_VER >= 2200
-+#if LLVM_VERSION_MAJOR >= 22
- {address},
- #else
- {size, address},
-@@ -67,7 +67,7 @@ void LocalVariableLifetimeAnnotator::popScope() {
- return;
-
- for (const auto &var : scopes.back().variables) {
--#if LDC_LLVM_VER < 2200
-+#if LLVM_VERSION_MAJOR < 22
- auto size = var.first;
- #endif
- auto address = var.second;
-@@ -75,7 +75,7 @@ void LocalVariableLifetimeAnnotator::popScope() {
- assert(address);
-
- irs.CreateCallOrInvoke(getLLVMLifetimeEndFn(),
--#if LDC_LLVM_VER >= 2200
-+#if LLVM_VERSION_MAJOR >= 22
- {address},
- #else
- {size, address},
-@@ -92,7 +92,7 @@ llvm::Function *LocalVariableLifetimeAnnotator::getLLVMLifetimeStartFn() {
- return lifetimeStartFunction;
-
- lifetimeStartFunction = llvm::Intrinsic::
--#if LDC_LLVM_VER >= 2000
-+#if LLVM_VERSION_MAJOR >= 20
- getOrInsertDeclaration(
- #else
- getDeclaration(
-@@ -108,7 +108,7 @@ llvm::Function *LocalVariableLifetimeAnnotator::getLLVMLifetimeEndFn() {
- return lifetimeEndFunction;
-
- lifetimeEndFunction = llvm::Intrinsic::
--#if LDC_LLVM_VER >= 2000
-+#if LLVM_VERSION_MAJOR >= 20
- getOrInsertDeclaration(
- #else
- getDeclaration(
-diff --git a/ir/iraggr.cpp b/ir/iraggr.cpp
-index 28d2ddddd2..94275dafce 100644
---- a/ir/iraggr.cpp
-+++ b/ir/iraggr.cpp
-@@ -63,10 +63,6 @@ bool IrAggr::useDLLImport() const {
- //////////////////////////////////////////////////////////////////////////////
-
- LLGlobalVariable *IrAggr::getInitSymbol(bool define) {
--#if LDC_LLVM_VER >= 1800
-- #define startswith starts_with
--#endif
--
- if (!init) {
- const auto irMangle = getIRMangledInitSymbolName(aggrdecl);
-
-@@ -74,7 +70,7 @@ LLGlobalVariable *IrAggr::getInitSymbol(bool define) {
- // special.
- auto cd = aggrdecl->isClassDeclaration();
- const bool isBuiltinTypeInfo =
-- cd && llvm::StringRef(cd->ident->toChars()).startswith("TypeInfo_");
-+ cd && llvm::StringRef(cd->ident->toChars()).starts_with("TypeInfo_");
-
- // Only declare the symbol if it isn't yet, otherwise the init symbol of
- // built-in TypeInfos may clash with an existing base-typed forward
-@@ -108,10 +104,6 @@ LLGlobalVariable *IrAggr::getInitSymbol(bool define) {
- }
-
- return init;
--
--#if LDC_LLVM_VER >= 1800
-- #undef startswith
--#endif
- }
-
- //////////////////////////////////////////////////////////////////////////////
-diff --git a/ir/irtypestruct.cpp b/ir/irtypestruct.cpp
-index cac45683e0..644c196021 100644
---- a/ir/irtypestruct.cpp
-+++ b/ir/irtypestruct.cpp
-@@ -72,7 +72,7 @@ IrTypeStruct *IrTypeStruct::get(StructDeclaration *sd) {
-
- // For ldc.dcomptetypes.Pointer!(uint n,T),
- // emit { T addrspace(gIR->dcomputetarget->mapping[n])* }
-- llvm::Optional<DcomputePointer> p;
-+ std::optional<DcomputePointer> p;
-
- if (gIR->dcomputetarget && (p = toDcomputePointer(sd))) {
- // Translate the virtual dcompute address space into the real one for
-diff --git a/runtime/druntime/src/__importc_builtins.di b/runtime/druntime/src/__importc_builtins.di
-index 476852cd82..3c870c1842 100644
---- a/runtime/druntime/src/__importc_builtins.di
-+++ b/runtime/druntime/src/__importc_builtins.di
-@@ -12,6 +12,10 @@
-
- module __builtins;
-
-+import core.stdc.config : c_long, c_ulong;
-+import core.checkedint : adds, subs, muls;
-+
-+
- /* gcc relies on internal __builtin_xxxx functions and templates to
- * accomplish <stdarg.h>. D does the same thing with templates in core.stdc.stdarg.
- * Here, we redirect the gcc builtin declarations to the equivalent
-@@ -101,6 +105,11 @@ version (DigitalMars)
- alias __builtin_fabsf = imported!"core.stdc.math".fabsf;
- alias __builtin_fabsl = imported!"core.stdc.math".fabsl;
-
-+ alias __builtin_memcmp = imported!"core.stdc.string".memcmp;
-+ alias __builtin_memcpy = imported!"core.stdc.string".memcpy;
-+ alias __builtin_memmove = imported!"core.stdc.string".memmove;
-+ alias __builtin_memset = imported!"core.stdc.string".memset;
-+
- ushort __builtin_bswap16()(ushort value)
- {
- return cast(ushort) (((value >> 8) & 0xFF) | ((value << 8) & 0xFF00U));
-@@ -161,6 +170,11 @@ else version (LDC)
- alias __builtin_fabsf = imported!"ldc.intrinsics".llvm_fabs!float;
- alias __builtin_fabsl = imported!"ldc.intrinsics".llvm_fabs!real;
-
-+ alias __builtin_memcmp = imported!"core.stdc.string".memcmp;
-+ alias __builtin_memcpy = imported!"ldc.intrinsics".llvm_memcpy!size_t;
-+ alias __builtin_memmove = imported!"ldc.intrinsics".llvm_memmove!size_t;
-+ alias __builtin_memset = imported!"ldc.intrinsics".llvm_memset!size_t;
-+
- alias __builtin_bswap16 = imported!"ldc.intrinsics".llvm_bswap!ushort;
- alias __builtin_bswap32 = imported!"ldc.intrinsics".llvm_bswap!uint;
- alias __builtin_bswap64 = imported!"ldc.intrinsics".llvm_bswap!ulong;
-@@ -172,7 +186,8 @@ else version (LDC)
-
- alias __uint128_t = imported!"core.int128".Cent;
-
-- alias __builtin_alloca = imported!"core.stdc.stdlib".alloca;
-+ pragma(LDC_alloca)
-+ extern(C) void* __builtin_alloca(size_t size) nothrow @nogc pure;
-
- // gcc builtins:
-
-@@ -200,3 +215,233 @@ version (CRuntime_Glibc) version (AArch64)
- alias __Float32x4_t = __vector(float[4]);
- alias __Float64x2_t = __vector(double[2]);
- }
-+
-+// https://gcc.gnu.org/onlinedocs/gcc/Integer-Overflow-Builtins.html
-+
-+private bool overflowOp(alias op, T1, T2, T3)(T1 a, T2 b, ref T3 res)
-+{
-+ bool overflow = false;
-+ res = op(a, b, overflow);
-+ return overflow;
-+}
-+
-+private T builtin_opc(alias op, T)(T a, T b, T carry_in, ref T carry_out)
-+{
-+ carry_out = op(a, b, a) | op(a, carry_in, a);
-+ return a;
-+}
-+
-+pragma(inline, true)
-+{
-+ bool __builtin_add_overflow(T1, T2, T3)(T1 a, T2 b, T3* res) => overflowOp!(adds, T1, T2, T3)(a, b, *res);
-+ bool __builtin_sub_overflow(T1, T2, T3)(T1 a, T2 b, T3* res) => overflowOp!(subs, T1, T2, T3)(a, b, *res);
-+ bool __builtin_mul_overflow(T1, T2, T3)(T1 a, T2 b, T3* res) => overflowOp!(muls, T1, T2, T3)(a, b, *res);
-+ bool __builtin_add_overflow_p(T1, T2, T3)(T1 a, T2 b, T3 c) => overflowOp!(adds, T1, T2, T3)(a, b, res);
-+ bool __builtin_sub_overflow_p(T1, T2, T3)(T1 a, T2 b, T3 c) => overflowOp!(subs, T1, T2, T3)(a, b, res);
-+ bool __builtin_mul_overflow_p(T1, T2, T3)(T1 a, T2 b, T3 c) => overflowOp!(muls, T1, T2, T3)(a, b, res);
-+ bool __builtin_sadd_overflow ()(int a, int b, int* res) => overflowOp!(adds, int , int , int )(a, b, *res);
-+ bool __builtin_saddl_overflow ()(c_long a, c_long b, c_long* res) => overflowOp!(adds, c_long , c_long , c_long )(a, b, *res);
-+ bool __builtin_saddll_overflow()(long a, long b, long* res) => overflowOp!(adds, long , long , long )(a, b, *res);
-+ bool __builtin_uadd_overflow ()(uint a, uint b, uint* res) => overflowOp!(adds, uint , uint , uint )(a, b, *res);
-+ bool __builtin_uaddl_overflow ()(c_ulong a, c_ulong b, c_ulong* res) => overflowOp!(adds, c_ulong, c_ulong, c_ulong)(a, b, *res);
-+ bool __builtin_uaddll_overflow()(ulong a, ulong b, ulong* res) => overflowOp!(adds, ulong , ulong , ulong )(a, b, *res);
-+ bool __builtin_ssub_overflow ()(int a, int b, int* res) => overflowOp!(subs, int , int , int )(a, b, *res);
-+ bool __builtin_ssubl_overflow ()(c_long a, c_long b, c_long* res) => overflowOp!(subs, c_long , c_long , c_long )(a, b, *res);
-+ bool __builtin_ssubll_overflow()(long a, long b, long* res) => overflowOp!(subs, long , long , long )(a, b, *res);
-+ bool __builtin_usub_overflow ()(uint a, uint b, uint* res) => overflowOp!(subs, uint , uint , uint )(a, b, *res);
-+ bool __builtin_usubl_overflow ()(c_ulong a, c_ulong b, c_ulong* res) => overflowOp!(subs, c_ulong, c_ulong, c_ulong)(a, b, *res);
-+ bool __builtin_usubll_overflow()(ulong a, ulong b, ulong* res) => overflowOp!(subs, ulong , ulong , ulong )(a, b, *res);
-+ bool __builtin_smul_overflow ()(int a, int b, int* res) => overflowOp!(muls, int , int , int )(a, b, *res);
-+ bool __builtin_smull_overflow ()(c_long a, c_long b, c_long* res) => overflowOp!(muls, c_long , c_long , c_long )(a, b, *res);
-+ bool __builtin_smulll_overflow()(long a, long b, long* res) => overflowOp!(muls, long , long , long )(a, b, *res);
-+ bool __builtin_umul_overflow ()(uint a, uint b, uint* res) => overflowOp!(muls, uint , uint , uint )(a, b, *res);
-+ bool __builtin_umull_overflow ()(c_ulong a, c_ulong b, c_ulong* res) => overflowOp!(muls, c_ulong, c_ulong, c_ulong)(a, b, *res);
-+ bool __builtin_umulll_overflow()(ulong a, ulong b, ulong* res) => overflowOp!(muls, ulong , ulong , ulong )(a, b, *res);
-+
-+ uint __builtin_addc ()(uint a, uint b, uint carry_in, uint* carry_out) => builtin_opc!(adds, uint )(a, b, carry_in, *carry_out);
-+ ulong __builtin_addcl ()(ulong a, ulong b, uint carry_in, ulong* carry_out) => builtin_opc!(adds, ulong)(a, b, carry_in, *carry_out);
-+ ulong __builtin_addcll()(ulong a, ulong b, ulong carry_in, ulong* carry_out) => builtin_opc!(adds, ulong)(a, b, carry_in, *carry_out);
-+ uint __builtin_subc ()(uint a, uint b, uint carry_in, uint* carry_out) => builtin_opc!(subs, uint )(a, b, carry_in, *carry_out);
-+ ulong __builtin_subcl ()(ulong a, ulong b, uint carry_in, ulong* carry_out) => builtin_opc!(subs, ulong)(a, b, carry_in, *carry_out);
-+ ulong __builtin_subcll()(ulong a, ulong b, ulong carry_in, ulong* carry_out) => builtin_opc!(subs, ulong)(a, b, carry_in, *carry_out);
-+}
-+
-+unittest {
-+ int r1;
-+ assert(__builtin_sadd_overflow(2147483647, 1, &r1) == true);
-+ assert(__builtin_sadd_overflow(1, 1, &r1) == false);
-+
-+ assert(__builtin_ssub_overflow(-2147483648, 1, &r1) == true);
-+ assert(__builtin_ssub_overflow(5, 3, &r1) == false);
-+
-+ assert(__builtin_smul_overflow(2000000000, 2, &r1) == true);
-+ assert(__builtin_smul_overflow(10, 20, &r1) == false);
-+
-+ uint ur;
-+ assert(__builtin_uadd_overflow(0xFFFFFFFFu, 1u, &ur) == true);
-+ assert(__builtin_uadd_overflow(10u, 20u, &ur) == false);
-+
-+ assert(__builtin_usub_overflow(0u, 1u, &ur) == true);
-+ assert(__builtin_usub_overflow(20u, 10u, &ur) == false);
-+
-+ assert(__builtin_umul_overflow(0xFFFFFFFFu, 2u, &ur) == true);
-+ assert(__builtin_umul_overflow(10u, 20u, &ur) == false);
-+
-+ uint carry;
-+ uint rr = __builtin_addc(1u, 1u, 0u, &carry);
-+ assert(rr == 2);
-+ assert(carry == 0);
-+
-+ rr = __builtin_addc(0xFFFFFFFFu, 1u, 0u, &carry);
-+ assert(carry == 1);
-+
-+ rr = __builtin_subc(1u, 1u, 0u, &carry);
-+ assert(rr == 0);
-+ assert(carry == 0);
-+
-+ rr = __builtin_subc(0u, 1u, 0u, &carry);
-+ assert(carry == 1);
-+}
-+
-+private U signbit(T, U)(T x)
-+{
-+ T arg = x;
-+ return cast(U)arg >> (T.sizeof * 8 - 1);
-+}
-+
-+pragma(inline, true)
-+{
-+ // https://gcc.gnu.org/onlinedocs/gcc/Bit-Operation-Builtins.html
-+ import core.bitop : popcnt, bsr, bsf, rol, ror;
-+ private int clz(T)(T x) => bsr(x) ^ ((int.sizeof * 8)-1);
-+
-+ int __builtin_clz()(uint x) => clz!uint(x);
-+ int __builtin_clzl()(c_ulong x) => clz!c_ulong(x);
-+ int __builtin_clzll()(ulong x) => clz!ulong(x);
-+ int __builtin_clzg(T)(T arg) => clz(arg);
-+
-+ int __builtin_ctz()(uint x) => bsf(x);
-+ int __builtin_ctzl()(c_ulong x) => bsf(x);
-+ int __builtin_ctzll()(ulong x) => bsf(x);
-+ int __builtin_ctzg(T)(T arg) => bsf(arg);
-+
<Skipped 6692 lines>
================================================================
---- gitweb:
http://git.pld-linux.org/gitweb.cgi/packages/ldc.git/commitdiff/3f7e934b5834dcfd38d80b7b5c9e31ef21e57449
More information about the pld-cvs-commit
mailing list