Skip to content

Commit bd0bb16

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 two patches for the Clang 20 build: - plugin-registry-symbols_clang_20-llvm-pr-163391.patch: Make extract_symbols.py recognize and export Registry<T>::Head and ::Tail static members for any Registry instantiation. References Registry<PluginASTAction>::add_node() and ::begin() to force the linker to include these symbols. 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 in Windows. See llvm/llvm-project#163349. Differential Revision: https://phabricator.services.mozilla.com/D268255
1 parent 77c24e7 commit bd0bb16

File tree

3 files changed

+95
-1
lines changed

3 files changed

+95
-1
lines changed

build/build-clang/clang-20.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
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+
"plugin-registry-symbols_clang_20-llvm-pr-163391.patch",
17+
"remove-clang-abi-from-attrs_clang_20.patch"
1618
]
1719
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
Fix plugin registry symbols not exported/linked with CLANG_LINK_CLANG_DYLIB.
2+
3+
When building LLVM with CLANG_LINK_CLANG_DYLIB=ON on Windows, external plugins
4+
cannot register through llvm::Registry<clang::PluginASTAction> due to two issues:
5+
6+
1. Static data members (Head, Tail) are filtered out during symbol export by
7+
extract_symbols.py because they don't match function signature patterns.
8+
9+
2. Static methods (add_node(), begin()) exist in libraries but aren't linked
10+
into clang.exe because they're unreferenced by the driver.
11+
12+
This patch fixes both issues by adding pattern matching to recognize Registry
13+
symbols for export and by adding C++ code to force linking of Registry methods.
14+
15+
See https://github.com/llvm/llvm-project/issues/163367
16+
17+
diff --git a/clang/tools/driver/driver.cpp b/clang/tools/driver/driver.cpp
18+
index 00c00cea16f4..d2622e679a47 100644
19+
--- a/clang/tools/driver/driver.cpp
20+
+++ b/clang/tools/driver/driver.cpp
21+
@@ -55,6 +55,25 @@
22+
#include <set>
23+
#include <system_error>
24+
25+
+#if defined(CLANG_PLUGIN_SUPPORT) && defined(_WIN32)
26+
+#include "clang/Frontend/FrontendPluginRegistry.h"
27+
+
28+
+// Force plugin registry symbols into clang.exe on Windows so plugins can
29+
+// register. These methods exist in libraries but aren't linked by default
30+
+// because they're unreferenced. Taking their addresses forces the linker to
31+
+// include them.
32+
+namespace {
33+
+void ForcePluginRegistrySymbols() {
34+
+ using PluginRegistry = llvm::Registry<clang::PluginASTAction>;
35+
+ // Use volatile to prevent the compiler from optimizing away these references
36+
+ volatile auto add_node_ptr = &PluginRegistry::add_node;
37+
+ volatile auto begin_ptr = &PluginRegistry::begin;
38+
+ (void)add_node_ptr;
39+
+ (void)begin_ptr;
40+
+}
41+
+} // anonymous namespace
42+
+#endif
43+
+
44+
using namespace clang;
45+
using namespace clang::driver;
46+
using namespace llvm::opt;
47+
diff --git a/llvm/utils/extract_symbols.py b/llvm/utils/extract_symbols.py
48+
index 388723421d66..72f992f560c7 100755
49+
--- a/llvm/utils/extract_symbols.py
50+
+++ b/llvm/utils/extract_symbols.py
51+
@@ -105,6 +105,11 @@ def should_keep_microsoft_symbol(symbol, calling_convention_decoration):
52+
# Skip X86GenMnemonicTables functions, they are not exposed from llvm/include/.
53+
elif re.match(r"\?is[A-Z0-9]*@X86@llvm", symbol):
54+
return None
55+
+ # Keep Registry<T>::Head and Registry<T>::Tail static members for plugin support.
56+
+ # Pattern matches: ?Head@?$Registry@<template_args>@llvm@@ or ?Tail@?$Registry@...
57+
+ elif ("?$Registry@" in symbol and "@llvm@@" in symbol and
58+
+ (symbol.startswith("?Head@") or symbol.startswith("?Tail@"))):
59+
+ return symbol
60+
# Keep mangled llvm:: and clang:: function symbols. How we detect these is a
61+
# bit of a mess and imprecise, but that avoids having to completely demangle
62+
# the symbol name. The outermost namespace is at the end of the identifier
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
Remove CLANG_ABI macro from generated Attr classes on Windows only.
2+
3+
Clang 20 added CLANG_ABI (__declspec(dllimport)) to Attr classes, but on Windows
4+
this breaks inline methods like classof() and getAnnotation() in plugins because
5+
they are defined in headers and can't be imported. This change only removes
6+
CLANG_ABI on Windows, keeping it for other platforms.
7+
8+
diff --git a/clang/utils/TableGen/ClangAttrEmitter.cpp b/clang/utils/TableGen/ClangAttrEmitter.cpp
9+
index de12c7062666..2a7676569973 100644
10+
--- a/clang/utils/TableGen/ClangAttrEmitter.cpp
11+
+++ b/clang/utils/TableGen/ClangAttrEmitter.cpp
12+
@@ -2722,10 +2722,14 @@ static void emitAttributes(const RecordKeeper &Records, raw_ostream &OS,
13+
Inheritable = true;
14+
}
15+
16+
- if (Header)
17+
- OS << "class CLANG_ABI " << R.getName() << "Attr : public " << SuperName
18+
- << " {\n";
19+
- else
20+
+ if (Header) {
21+
+ // On Windows, CLANG_ABI causes issues with inline methods in plugins
22+
+ OS << "class ";
23+
+#ifndef _WIN32
24+
+ OS << "CLANG_ABI ";
25+
+#endif
26+
+ OS << R.getName() << "Attr : public " << SuperName << " {\n";
27+
+ } else
28+
OS << "\n// " << R.getName() << "Attr implementation\n\n";
29+
30+
std::vector<const Record *> ArgRecords = R.getValueAsListOfDefs("Args");

0 commit comments

Comments
 (0)