Skip to content

Commit 5e9eab6

Browse files
committed
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 two breaking changes that prevented the clang-plugin from loading on Windows: 1. The CLANG_ABI macro was added to Attr classes, causing inline methods like classof() and getAnnotation() to generate dllimport references. This fails because these methods are defined inline in headers, not exported from the DLL. 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 three patches for the Clang 20 build: - add-plugin-symbols_clang_20.patch: Adds pattern matching to extract_symbols.py to recognize and export Registry<T>::Head and ::Tail static members for any Registry instantiation. This replaces the need for hardcoded symbol whitelists and works across different plugin types. See llvm/llvm-project#163367 and llvm/llvm-project#163391. - force-plugin-symbols_clang_20.patch: Adds C++ code to driver.cpp that references Registry<PluginASTAction>::add_node() and ::begin() to force the linker to include these symbols. This replaces hardcoded mangled symbol names with type-safe references that work across compiler versions. See llvm/llvm-project#163367 and llvm/llvm-project#163391. - remove-clang-abi-from-attrs_clang_20.patch: Removes the CLANG_ABI macro from Attr class generation to prevent dllimport issues with inline methods. See llvm/llvm-project#163349. To test this locally: - Install the current clang-20 inside the firefox checkout: `./mach artifact toolchain --from-build win64-clang-20` - Install libxml2 (necessary for clang-mt.exe): `./mach artifact toolchain --from-build win64-libxml2` - Install wasm32-wasi-compiler-rt-20 (necessary for WASM compilation?): `./mach artifact toolchain --from-build wasm32-wasi-compiler-rt-20` - Check out llvm 20.1.8 in a directory alongside the firefox checkout. - Try to build llvm, and fail when the wasi lib is missing: `MOZ_FETCHES_DIR=../firefox python3 ../firefox/build/build-clang/build-clang.py -c ../firefox/build/build-clang/use-clang-cl-artifact.json -c ../firefox/build/build-clang/win64.json -c ../firefox/build/build-clang/clang-20.json -c ../firefox/build/build-clang/2stages.json` - Copy the missing wasi lib to the stage2 build directory: ``` mkdir build/stage2/clang/lib/clang/20/lib/wasm32-unknown-wasi cp ../firefox/compiler-rt-wasm32-wasi/lib/wasi/libclang_rt.builtins-wasm32.a build/stage2/clang/lib/clang/20/lib/wasm32-unknown-wasi/libclang_rt.builtins.a ``` - Try to build llvm again and succeed: `MOZ_FETCHES_DIR=../firefox python3 ../firefox/build/build-clang/build-clang.py -c ../firefox/build/build-clang/use-clang-cl-artifact.json -c ../firefox/build/build-clang/win64.json -c ../firefox/build/build-clang/clang-20.json -c ../firefox/build/build-clang/2stages.json` - Update the mozconfig in the firefox checkout to turn on the clang plugin and use the right compiler: ``` export CC=[THE LLVM CHECKOUT DIRECTORY]/build/stage2/clang/bin/clang-cl.exe ac_add_options --enable-clang-plugin ``` - Build firefox: `./mach clobber && ./mach configure --enable-bootstrap=no-update && ./mach build` Differential Revision: https://phabricator.services.mozilla.com/D268255
1 parent 77c24e7 commit 5e9eab6

File tree

4 files changed

+80
-1
lines changed

4 files changed

+80
-1
lines changed
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
Export Registry<T> Head and Tail symbols for plugin support.
2+
3+
Clang 20's extract_symbols.py filters static data members that don't match
4+
function signatures. Add pattern matching for Registry<T>::Head and ::Tail.
5+
6+
diff --git a/llvm/utils/extract_symbols.py b/llvm/utils/extract_symbols.py
7+
index 388723421d66..72f992f560c7 100755
8+
--- a/llvm/utils/extract_symbols.py
9+
+++ b/llvm/utils/extract_symbols.py
10+
@@ -105,6 +105,11 @@ def should_keep_microsoft_symbol(symbol, calling_convention_decoration):
11+
# Skip X86GenMnemonicTables functions, they are not exposed from llvm/include/.
12+
elif re.match(r"\?is[A-Z0-9]*@X86@llvm", symbol):
13+
return None
14+
+ # Keep Registry<T>::Head and Registry<T>::Tail static members for plugin support.
15+
+ # Pattern matches: ?Head@?$Registry@<template_args>@llvm@@ or ?Tail@?$Registry@...
16+
+ elif ("?$Registry@" in symbol and "@llvm@@" in symbol and
17+
+ (symbol.startswith("?Head@") or symbol.startswith("?Tail@"))):
18+
+ return symbol
19+
# Keep mangled llvm:: and clang:: function symbols. How we detect these is a
20+
# bit of a mess and imprecise, but that avoids having to completely demangle
21+
# the symbol name. The outermost namespace is at the end of the identifier

build/build-clang/clang-20.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
"llvmorg-22-init-4745-gbe179d069664.patch",
1313
"android-hardware-buffer-header-workaround.patch",
1414
"arm64e-hack.patch",
15-
"compiler-rt-rss-limit-heap-profile.patch"
15+
"compiler-rt-rss-limit-heap-profile.patch",
16+
"add-plugin-symbols_clang_20.patch",
17+
"force-plugin-symbols_clang_20.patch",
18+
"remove-clang-abi-from-attrs_clang_20.patch"
1619
]
1720
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
Force plugin registry symbols into clang.exe for Windows plugin support.
2+
3+
Add C++ code that references Registry<PluginASTAction>::add_node() and ::begin()
4+
to force the linker to include these symbols. This replaces hardcoded mangled symbol
5+
names with type-safe references that work across compiler versions.
6+
7+
diff --git a/clang/tools/driver/driver.cpp b/clang/tools/driver/driver.cpp
8+
index 00c00cea16f4..d2622e679a47 100644
9+
--- a/clang/tools/driver/driver.cpp
10+
+++ b/clang/tools/driver/driver.cpp
11+
@@ -55,6 +55,25 @@
12+
#include <set>
13+
#include <system_error>
14+
15+
+#if defined(CLANG_PLUGIN_SUPPORT) && defined(_WIN32)
16+
+#include "clang/Frontend/FrontendPluginRegistry.h"
17+
+
18+
+// Force plugin registry symbols into clang.exe on Windows so plugins can
19+
+// register. These methods exist in libraries but aren't linked by default
20+
+// because they're unreferenced. Taking their addresses forces the linker to
21+
+// include them.
22+
+namespace {
23+
+void ForcePluginRegistrySymbols() {
24+
+ using PluginRegistry = llvm::Registry<clang::PluginASTAction>;
25+
+ // Use volatile to prevent the compiler from optimizing away these references
26+
+ volatile auto add_node_ptr = &PluginRegistry::add_node;
27+
+ volatile auto begin_ptr = &PluginRegistry::begin;
28+
+ (void)add_node_ptr;
29+
+ (void)begin_ptr;
30+
+}
31+
+} // anonymous namespace
32+
+#endif
33+
+
34+
using namespace clang;
35+
using namespace clang::driver;
36+
using namespace llvm::opt;
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
Remove CLANG_ABI macro from generated Attr classes to fix Windows plugin builds.
2+
3+
Clang 20 added CLANG_ABI (__declspec(dllimport)) to Attr classes, but this breaks
4+
inline methods like classof() and getAnnotation() that are defined in headers.
5+
These can't be imported as they have no DLL export. This reverts to Clang 19 behavior.
6+
7+
diff --git a/clang/utils/TableGen/ClangAttrEmitter.cpp b/clang/utils/TableGen/ClangAttrEmitter.cpp
8+
index de12c7062666..38e1db6b3ea4 100644
9+
--- a/clang/utils/TableGen/ClangAttrEmitter.cpp
10+
+++ b/clang/utils/TableGen/ClangAttrEmitter.cpp
11+
@@ -2723,7 +2723,7 @@ static void emitAttributes(const RecordKeeper &Records, raw_ostream &OS,
12+
}
13+
14+
if (Header)
15+
- OS << "class CLANG_ABI " << R.getName() << "Attr : public " << SuperName
16+
+ OS << "class " << R.getName() << "Attr : public " << SuperName
17+
<< " {\n";
18+
else
19+
OS << "\n// " << R.getName() << "Attr implementation\n\n";

0 commit comments

Comments
 (0)