commit ef329a4d7eb35c16e2374cfd373d37083afcf494
parent ee2e8ced9d0225fae9822c2a7046264d377d5ab2
Author: Martin Bruse <zondolfin@gmail.com>
Date: Tue, 21 Oct 2025 07:27:03 +0000
Bug 1941482 - Enable Clang 20 support for Firefox with Windows plugin fixes r=glandium
This change adds support for building Firefox with Clang 20, including
critical fixes for the clang-plugin dynamic linking on Windows.
Clang 20 introduced breaking changes that prevented the clang-plugin
from building on Windows:
1. Clang is built with '/Zc:dllexportInlines-' which excludes inlined
members like some methods of Attr classes from being dllexported.
2. The extract_symbols.py script became more aggressive in filtering
symbols, blocking Registry<T> static data members (Head/Tail) that
don't match function signature patterns.
The fix consists of one change to the build configuration of clang-plugin,
and one patch for the Clang 20 and trunk builds:
- plugin-registry-symbols-llvm-pr-163391.patch:
Make extract_symbols.py recognize and export Registry<T>::Head and
::Tail static members for any Registry instantiation.
See https://github.com/llvm/llvm-project/issues/163367 and
https://github.com/llvm/llvm-project/pull/163391.
- Add '/Zc:dllexportInlines-' to the CXX flags when building
clang-plugin, which will match the clang build configuration and
inline the members instead of referencing the symbols.
Differential Revision: https://phabricator.services.mozilla.com/D268255
Diffstat:
4 files changed, 42 insertions(+), 2 deletions(-)
diff --git a/build/build-clang/clang-20.json b/build/build-clang/clang-20.json
@@ -13,6 +13,7 @@
"llvmorg-22-init-4745-gbe179d069664.patch",
"android-hardware-buffer-header-workaround.patch",
"arm64e-hack.patch",
- "compiler-rt-rss-limit-heap-profile.patch"
+ "compiler-rt-rss-limit-heap-profile.patch",
+ "plugin-registry-symbols-llvm-pr-163391.patch"
]
}
diff --git a/build/build-clang/clang-trunk.json b/build/build-clang/clang-trunk.json
@@ -10,6 +10,7 @@
"revert-llvmorg-15-init-13446-g7524fe962e47.patch",
"android-hardware-buffer-header-workaround_clang_21.patch",
"arm64e-hack.patch",
- "compiler-rt-rss-limit-heap-profile.patch"
+ "compiler-rt-rss-limit-heap-profile.patch",
+ "plugin-registry-symbols-llvm-pr-163391.patch"
]
}
diff --git a/build/build-clang/plugin-registry-symbols-llvm-pr-163391.patch b/build/build-clang/plugin-registry-symbols-llvm-pr-163391.patch
@@ -0,0 +1,35 @@
+Fix plugin registry symbols not exported in static builds with plugin support.
+
+When building LLVM statically (without BUILD_SHARED_LIBS) on Windows with
+LLVM_EXPORT_SYMBOLS_FOR_PLUGINS=ON, external plugins cannot register through
+llvm::Registry<clang::PluginASTAction> because:
+
+Static data members (Head, Tail) are filtered out during symbol export by
+extract_symbols.py because they don't match the function signature patterns
+that the script looks for.
+
+This patch fixes the issue by adding pattern matching to extract_symbols.py
+to recognize and export Registry static data members.
+
+Note: When both LLVM and the plugins are built with /Zc:dllexportInlines-,
+the static methods (add_node(), begin()) are inlined by the plugin at call
+sites, so only the data symbols need to be exported.
+
+See https://github.com/llvm/llvm-project/issues/163367
+
+diff --git a/llvm/utils/extract_symbols.py b/llvm/utils/extract_symbols.py
+index 388723421d66..72f992f560c7 100755
+--- a/llvm/utils/extract_symbols.py
++++ b/llvm/utils/extract_symbols.py
+@@ -105,6 +105,11 @@ def should_keep_microsoft_symbol(symbol, calling_convention_decoration):
+ # Skip X86GenMnemonicTables functions, they are not exposed from llvm/include/.
+ elif re.match(r"\?is[A-Z0-9]*@X86@llvm", symbol):
+ return None
++ # Keep Registry<T>::Head and Registry<T>::Tail static members for plugin support.
++ # Pattern matches: ?Head@?$Registry@<template_args>@llvm@@ or ?Tail@?$Registry@...
++ elif ("?$Registry@" in symbol and "@llvm@@" in symbol and
++ (symbol.startswith("?Head@") or symbol.startswith("?Tail@"))):
++ return symbol
+ # Keep mangled llvm:: and clang:: function symbols. How we detect these is a
+ # bit of a mess and imprecise, but that avoids having to completely demangle
+ # the symbol name. The outermost namespace is at the end of the identifier
diff --git a/build/clang-plugin/moz.build b/build/clang-plugin/moz.build
@@ -134,6 +134,9 @@ if CONFIG["HOST_OS_ARCH"] == "WINNT":
# but as of writing, it's not necessary for the plugin code, so enable
# the escape hatch, at least until we generally upgrade to VS 2019.
HOST_DEFINES["LLVM_FORCE_USE_OLD_TOOLCHAIN"] = True
+ # Clang 20+ needs /Zc:dllexportInlines- to work around CLANG_ABI issues with inline methods
+ if CONFIG["HOST_CC_VERSION"] and int(CONFIG["HOST_CC_VERSION"].split(".")[0]) >= 20:
+ extra_cxxflags += ["/Zc:dllexportInlines-"]
else:
extra_cxxflags = ["-fno-rtti", "-fno-exceptions"]