Skip to content

Commit 952d572

Browse files
committedApr 4, 2023
Allow plugging in observer
1 parent cf1b1ff commit 952d572

7 files changed

+345
-70
lines changed
 

‎patch.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#!/bin/bash
1+
#!/bin/bash -e
22

33
PATCH_DIR="$(cd "$(dirname "$0")/patches"; pwd)"
44

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
Remove block of code that is turning off auto-compilation of stdlib `.swiftinterface`
2+
files.
3+
4+
diff --git a/lib/Frontend/ModuleInterfaceLoader.cpp b/lib/Frontend/ModuleInterfaceLoader.cpp
5+
index 2a490a680d8..8d8f48aeed0 100644
6+
--- a/lib/Frontend/ModuleInterfaceLoader.cpp
7+
+++ b/lib/Frontend/ModuleInterfaceLoader.cpp
8+
@@ -726,21 +726,6 @@ class ModuleInterfaceLoaderImpl {
9+
<< "; deferring to serialized module loader\n");
10+
UsableModulePath = adjacentMod;
11+
return std::make_error_code(std::errc::not_supported);
12+
- } else if (isInResourceDir(adjacentMod) &&
13+
- loadMode == ModuleLoadingMode::PreferSerialized) {
14+
- // Special-case here: If we're loading a .swiftmodule from the resource
15+
- // dir adjacent to the compiler, defer to the serialized loader instead
16+
- // of falling back. This is mainly to support development of Swift,
17+
- // where one might change the module format version but forget to
18+
- // recompile the standard library. If that happens, don't fall back
19+
- // and silently recompile the standard library -- instead, error like
20+
- // we used to.
21+
- LLVM_DEBUG(llvm::dbgs() << "Found out-of-date module in the "
22+
- "resource-dir at "
23+
- << adjacentMod
24+
- << "; deferring to serialized module loader "
25+
- "to diagnose\n");
26+
- return std::make_error_code(std::errc::not_supported);
27+
} else {
28+
LLVM_DEBUG(llvm::dbgs() << "Found out-of-date module at "
29+
<< adjacentMod << "\n");
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
Add a `finished(int status)` method to `FrontendObserver`, fired when the frontend has finished.
2+
3+
diff --git a/include/swift/FrontendTool/FrontendTool.h b/include/swift/FrontendTool/FrontendTool.h
4+
index 184e6196918..ef5c3eafe69 100644
5+
--- a/include/swift/FrontendTool/FrontendTool.h
6+
+++ b/include/swift/FrontendTool/FrontendTool.h
7+
@@ -53,6 +53,9 @@ public:
8+
/// The frontend has executed the SIL optimization and diagnostics pipelines.
9+
virtual void performedSILProcessing(SILModule &module);
10+
11+
+ /// The frontend has finished executing with the given return value
12+
+ virtual void finished(int status);
13+
+
14+
// TODO: maybe enhance this interface to hear about IRGen and LLVM
15+
// progress.
16+
};
17+
diff --git a/lib/FrontendTool/FrontendTool.cpp b/lib/FrontendTool/FrontendTool.cpp
18+
index 811fb912f8a..afa2034aa71 100644
19+
--- a/lib/FrontendTool/FrontendTool.cpp
20+
+++ b/lib/FrontendTool/FrontendTool.cpp
21+
@@ -1924,7 +1924,7 @@ public:
22+
};
23+
};
24+
25+
-int swift::performFrontend(ArrayRef<const char *> Args,
26+
+static int performFrontendImpl(ArrayRef<const char *> Args,
27+
const char *Argv0, void *MainAddr,
28+
FrontendObserver *observer) {
29+
INITIALIZE_LLVM();
30+
@@ -2263,8 +2263,19 @@ int swift::performFrontend(ArrayRef<const char *> Args,
31+
return r;
32+
}
33+
34+
+int swift::performFrontend(ArrayRef<const char *> Args,
35+
+ const char *Argv0, void *MainAddr,
36+
+ FrontendObserver *observer) {
37+
+ auto ret = performFrontendImpl(Args, Argv0, MainAddr, observer);
38+
+ if (observer) {
39+
+ observer->finished(ret);
40+
+ }
41+
+ return ret;
42+
+}
43+
+
44+
void FrontendObserver::parsedArgs(CompilerInvocation &invocation) {}
45+
void FrontendObserver::configuredCompiler(CompilerInstance &instance) {}
46+
void FrontendObserver::performedSemanticAnalysis(CompilerInstance &instance) {}
47+
void FrontendObserver::performedSILGeneration(SILModule &module) {}
48+
void FrontendObserver::performedSILProcessing(SILModule &module) {}
49+
+void FrontendObserver::finished(int status) {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt
2+
index 60b0ae22368..f99551bbf7b 100644
3+
--- a/tools/CMakeLists.txt
4+
+++ b/tools/CMakeLists.txt
5+
@@ -40,18 +40,6 @@ if(SWIFT_BUILD_SYNTAXPARSERLIB)
6+
endif()
7+
endif()
8+
9+
-if(SWIFT_INCLUDE_TESTS OR SWIFT_INCLUDE_TEST_BINARIES)
10+
- add_swift_tool_subdirectory(swift-ide-test)
11+
- add_swift_tool_subdirectory(swift-remoteast-test)
12+
- add_swift_tool_subdirectory(lldb-moduleimport-test)
13+
- add_swift_tool_subdirectory(swift-syntax-test)
14+
-endif()
15+
-
16+
-if(LLVM_USE_SANITIZE_COVERAGE)
17+
-add_swift_tool_subdirectory(swift-demangle-fuzzer)
18+
-add_swift_tool_subdirectory(swift-reflection-fuzzer)
19+
-endif()
20+
-
21+
if(SWIFT_BUILD_SOURCEKIT)
22+
add_swift_tool_subdirectory(SourceKit)
23+
endif()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
Make calls to `performFrontend` use an observer taken from `getFrontendObserver`, which
2+
is provided by a shared library. Substituting the shared library can plug in our
3+
extractor.
4+
5+
diff --git a/cmake/modules/AddSwift.cmake b/cmake/modules/AddSwift.cmake
6+
index 6d93e52f1d5..10225f40fb1 100644
7+
--- a/cmake/modules/AddSwift.cmake
8+
+++ b/cmake/modules/AddSwift.cmake
9+
@@ -715,6 +715,7 @@ function(add_swift_host_tool executable)
10+
11+
# Include the abi stable system stdlib in our rpath.
12+
list(APPEND RPATH_LIST "/usr/lib/swift")
13+
+ list(APPEND RPATH_LIST "@executable_path/../lib")
14+
15+
elseif(BOOTSTRAPPING_MODE STREQUAL "CROSSCOMPILE-WITH-HOSTLIBS")
16+
17+
@@ -798,7 +799,7 @@ function(add_swift_host_tool executable)
18+
if(BOOTSTRAPPING_MODE STREQUAL "HOSTTOOLS")
19+
set_target_properties(${executable} PROPERTIES
20+
BUILD_WITH_INSTALL_RPATH YES
21+
- INSTALL_RPATH "${host_lib_dir}")
22+
+ INSTALL_RPATH "${host_lib_dir};$ORIGIN/../lib")
23+
else()
24+
set_target_properties(${executable} PROPERTIES
25+
BUILD_WITH_INSTALL_RPATH YES
26+
diff --git a/include/swift/DriverTool/FrontendObserver.h b/include/swift/DriverTool/FrontendObserver.h
27+
new file mode 100644
28+
index 00000000000..4ac9b299a13
29+
--- /dev/null
30+
+++ b/include/swift/DriverTool/FrontendObserver.h
31+
@@ -0,0 +1,10 @@
32+
+#pragma once
33+
+
34+
+#include "llvm/ADT/ArrayRef.h"
35+
+#include "swift/FrontendTool/FrontendTool.h"
36+
+
37+
+namespace swift {
38+
+
39+
+FrontendObserver* getFrontendObserver(llvm::ArrayRef<const char*> argv);
40+
+
41+
+} // namespace swift
42+
diff --git a/lib/DriverTool/CMakeLists.txt b/lib/DriverTool/CMakeLists.txt
43+
index 869c00fece9..b1f49a976d5 100644
44+
--- a/lib/DriverTool/CMakeLists.txt
45+
+++ b/lib/DriverTool/CMakeLists.txt
46+
@@ -14,16 +14,24 @@ set(driver_common_libs
47+
swiftSymbolGraphGen
48+
LLVMBitstreamReader)
49+
50+
+add_swift_host_library(swiftFrontendObserver SHARED
51+
+ swift_frontend_observer.cpp)
52+
+target_link_libraries(swiftFrontendObserver
53+
+ PUBLIC
54+
+ swiftFrontendTool)
55+
+
56+
add_swift_host_library(swiftDriverTool STATIC
57+
${driver_sources_and_options}
58+
)
59+
target_link_libraries(swiftDriverTool
60+
PUBLIC
61+
- ${driver_common_libs})
62+
+ ${driver_common_libs}
63+
+ swiftFrontendObserver)
64+
65+
# If building as part of clang, make sure the headers are installed.
66+
if(NOT SWIFT_BUILT_STANDALONE)
67+
add_dependencies(swiftDriverTool clang-resource-headers)
68+
endif()
69+
70+
+set_swift_llvm_is_available(swiftFrontendObserver)
71+
set_swift_llvm_is_available(swiftDriverTool)
72+
diff --git a/lib/DriverTool/driver.cpp b/lib/DriverTool/driver.cpp
73+
index f71e2de9eae..a500e30827f 100644
74+
--- a/lib/DriverTool/driver.cpp
75+
+++ b/lib/DriverTool/driver.cpp
76+
@@ -31,6 +31,7 @@
77+
#include "swift/Frontend/PrintingDiagnosticConsumer.h"
78+
#include "swift/FrontendTool/FrontendTool.h"
79+
#include "swift/DriverTool/DriverTool.h"
80+
+#include "swift/DriverTool/FrontendObserver.h"
81+
#include "llvm/ADT/SmallVector.h"
82+
#include "llvm/Support/CommandLine.h"
83+
#include "llvm/Support/ConvertUTF.h"
84+
@@ -197,7 +198,8 @@ static int run_driver(StringRef ExecName,
85+
if (FirstArg == "-frontend") {
86+
return performFrontend(llvm::makeArrayRef(argv.data()+2,
87+
argv.data()+argv.size()),
88+
- argv[0], (void *)(intptr_t)getExecutablePath);
89+
+ argv[0], (void *)(intptr_t)getExecutablePath,
90+
+ getFrontendObserver(argv));
91+
}
92+
if (FirstArg == "-modulewrap") {
93+
return modulewrap_main(llvm::makeArrayRef(argv.data()+2,
94+
@@ -211,7 +213,8 @@ static int run_driver(StringRef ExecName,
95+
&& ExecName == "swift-frontend") {
96+
return performFrontend(llvm::makeArrayRef(argv.data()+1,
97+
argv.data()+argv.size()),
98+
- argv[0], (void *)(intptr_t)getExecutablePath);
99+
+ argv[0], (void *)(intptr_t)getExecutablePath,
100+
+ getFrontendObserver(argv));
101+
}
102+
103+
if (FirstArg == "repl") {
104+
diff --git a/lib/DriverTool/swift_frontend_observer.cpp b/lib/DriverTool/swift_frontend_observer.cpp
105+
new file mode 100644
106+
index 00000000000..e16b2f970cd
107+
--- /dev/null
108+
+++ b/lib/DriverTool/swift_frontend_observer.cpp
109+
@@ -0,0 +1,9 @@
110+
+#include "swift/DriverTool/FrontendObserver.h"
111+
+
112+
+namespace swift {
113+
+
114+
+FrontendObserver* getFrontendObserver(llvm::ArrayRef<const char*>) {
115+
+ return nullptr;
116+
+}
117+
+
118+
+} // namespace swift
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
When using our extractor as a plugin, it turns out there special opaque pointers
2+
are different in the frontend and our extractor contexts, leading to special
3+
members (subscripts, inits, deinits) to lose their name.
4+
5+
This avoids using this opaque data pointers and relies instead on actual data
6+
contained therein. This special data is distinguished from normal identifiers by
7+
using the unprintable `\1` as first character, and `s`, `c` or `d` as second
8+
character for subscript, constructors and destructors respectively.
9+
10+
diff --git a/include/swift/AST/Identifier.h b/include/swift/AST/Identifier.h
11+
index 6f65385e097..6ec0da0dd09 100644
12+
--- a/include/swift/AST/Identifier.h
13+
+++ b/include/swift/AST/Identifier.h
14+
@@ -72,8 +72,12 @@ private:
15+
&& "Identifier pointer does not use any spare bits");
16+
}
17+
18+
- /// A type with the alignment expected of a valid \c Identifier::Pointer .
19+
- struct alignas(uint64_t) Aligner {};
20+
+ /** A type with the alignment expected of a valid \c Identifier::Pointer
21+
+ * The actual value is used to distinguish special identifiers
22+
+ */
23+
+ struct alignas(uint64_t) Aligner {
24+
+ char value[3];
25+
+ };
26+
27+
static_assert(alignof(Aligner) >= RequiredAlignment,
28+
"Identifier table will provide enough spare bits");
29+
@@ -271,7 +275,7 @@ public:
30+
};
31+
32+
private:
33+
- /// In a special DeclName representing a subscript, this opaque pointer
34+
+ /// In a special DeclName representing a subscript, this opaque structure
35+
/// is used as the data of the base name identifier.
36+
/// This is an implementation detail that should never leak outside of
37+
/// DeclName.
38+
@@ -289,29 +293,19 @@ public:
39+
DeclBaseName(Identifier I) : Ident(I) {}
40+
41+
static DeclBaseName createSubscript() {
42+
- return DeclBaseName(Identifier((const char *)&SubscriptIdentifierData));
43+
+ return DeclBaseName(Identifier(SubscriptIdentifierData.value));
44+
}
45+
46+
static DeclBaseName createConstructor() {
47+
- return DeclBaseName(Identifier((const char *)&ConstructorIdentifierData));
48+
+ return DeclBaseName(Identifier(ConstructorIdentifierData.value));
49+
}
50+
51+
static DeclBaseName createDestructor() {
52+
- return DeclBaseName(Identifier((const char *)&DestructorIdentifierData));
53+
- }
54+
-
55+
- Kind getKind() const {
56+
- if (Ident.get() == (const char *)&SubscriptIdentifierData) {
57+
- return Kind::Subscript;
58+
- } else if (Ident.get() == (const char *)&ConstructorIdentifierData) {
59+
- return Kind::Constructor;
60+
- } else if (Ident.get() == (const char *)&DestructorIdentifierData) {
61+
- return Kind::Destructor;
62+
- } else {
63+
- return Kind::Normal;
64+
- }
65+
+ return DeclBaseName(Identifier(DestructorIdentifierData.value));
66+
}
67+
68+
+ Kind getKind() const;
69+
+
70+
bool isSpecial() const { return getKind() != Kind::Normal; }
71+
72+
bool isSubscript() const { return getKind() == Kind::Subscript; }
73+
diff --git a/lib/AST/Identifier.cpp b/lib/AST/Identifier.cpp
74+
index da9ffbc3ee9..d870d0d85e6 100644
75+
--- a/lib/AST/Identifier.cpp
76+
+++ b/lib/AST/Identifier.cpp
77+
@@ -23,9 +23,21 @@
78+
#include "clang/Basic/CharInfo.h"
79+
using namespace swift;
80+
81+
-constexpr const Identifier::Aligner DeclBaseName::SubscriptIdentifierData{};
82+
-constexpr const Identifier::Aligner DeclBaseName::ConstructorIdentifierData{};
83+
-constexpr const Identifier::Aligner DeclBaseName::DestructorIdentifierData{};
84+
+constexpr const Identifier::Aligner DeclBaseName::SubscriptIdentifierData{"\1s"};
85+
+constexpr const Identifier::Aligner DeclBaseName::ConstructorIdentifierData{"\1c"};
86+
+constexpr const Identifier::Aligner DeclBaseName::DestructorIdentifierData{"\1d"};
87+
+
88+
+DeclBaseName::Kind DeclBaseName::getKind() const {
89+
+ if (!Ident.get() || Ident.get()[0] != '\1') {
90+
+ return Kind::Normal;
91+
+ }
92+
+ switch(Ident.get()[1]) {
93+
+ case 's': return Kind::Subscript;
94+
+ case 'c': return Kind::Constructor;
95+
+ case 'd': return Kind::Destructor;
96+
+ default: return Kind::Normal;
97+
+ }
98+
+}
99+
100+
raw_ostream &llvm::operator<<(raw_ostream &OS, Identifier I) {
101+
if (I.get() == nullptr)
102+
@@ -305,5 +317,3 @@ StringRef ObjCSelector::getString(llvm::SmallVectorImpl<char> &scratch) const {
103+
void ObjCSelector::dump() const {
104+
llvm::errs() << *this << "\n";
105+
}
106+
-
107+
-

‎pkg_swift_llvm.py

+18-69
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ def getoptions():
3434
return opts
3535

3636

37-
Libs = namedtuple("Libs", ("archive", "static", "shared", "linker_flags"))
37+
Libs = namedtuple("Libs", ("static", "shared", "linker_flags"))
3838

3939
EXPORTED_LIB = "CodeQLSwiftFrontendTool"
4040

@@ -74,11 +74,11 @@ def get_libs(configured):
7474
print("extracting linking information from dummy project")
7575
with open(configured / "CMakeFiles" / "codeql-swift-artifacts.dir" / "link.txt") as link:
7676
libs = link.read().split()
77-
libs = libs[libs.index('codeql-swift-artifacts')+1:] # skip up to -o dummy
78-
ret = Libs([], [], [], [])
77+
libs = libs[libs.index('codeql-swift-artifacts') + 1:] # skip up to -o dummy
78+
ret = Libs([], [], [])
7979
for l in libs:
8080
if l.endswith(".a"):
81-
ret.static.append(str((configured / l).resolve()))
81+
ret.static.append((configured / l).resolve())
8282
elif l.endswith(".so") or l.endswith(".tbd") or l.endswith(".dylib"):
8383
l = pathlib.Path(l).stem
8484
ret.shared.append(f"-l{l[3:]}") # drop 'lib' prefix and '.so' suffix
@@ -97,55 +97,6 @@ def get_tgt(tgt, filename):
9797
return tgt.resolve()
9898

9999

100-
def create_static_lib(tgt, libs):
101-
tgt = get_tgt(tgt, f"lib{EXPORTED_LIB}.a")
102-
print(f"packaging {tgt.name}")
103-
if sys.platform == 'linux':
104-
includedlibs = "\n".join(f"addlib {l}" for l in libs.archive + libs.static)
105-
mriscript = f"create {tgt}\n{includedlibs}\nsave\nend"
106-
run(["ar", "-M"], cwd=tgt.parent, input=mriscript)
107-
else:
108-
libtool_args = ["libtool", "-static"]
109-
libtool_args.extend(libs.archive)
110-
libtool_args.extend(libs.static)
111-
libtool_args.append("-o")
112-
libtool_args.append(str(tgt))
113-
run(libtool_args, cwd=tgt.parent)
114-
return tgt
115-
116-
117-
def create_shared_lib(tgt, libs):
118-
ext = "so"
119-
if sys.platform != 'linux':
120-
ext = "dylib"
121-
libname = f"lib{EXPORTED_LIB}.{ext}"
122-
tgt = get_tgt(tgt, libname)
123-
print(f"packaging {libname}")
124-
compiler = os.environ.get("CC", "clang")
125-
cmd = [compiler, "-shared"]
126-
cmd.extend(libs.linker_flags)
127-
128-
if sys.platform == 'linux':
129-
cmd.append("-Wl,--whole-archive")
130-
else:
131-
cmd.append("-Wl,-all_load")
132-
133-
cmd.append(f"-o{tgt}")
134-
cmd.extend(libs.archive)
135-
136-
if sys.platform == 'linux':
137-
cmd.append("-Wl,--no-whole-archive")
138-
else:
139-
cmd.append("-lc++")
140-
141-
cmd.extend(libs.static)
142-
cmd.extend(libs.shared)
143-
run(cmd, cwd=tgt.parent)
144-
if sys.platform != "linux":
145-
run(["install_name_tool", "-id", f"@executable_path/{libname}", libname], cwd=tgt.parent)
146-
return tgt
147-
148-
149100
def copy_includes(src, tgt):
150101
print("copying includes")
151102
for dir, exts in (("include", ("h", "def", "inc")), ("stdlib", ("h",))):
@@ -159,7 +110,7 @@ def copy_includes(src, tgt):
159110

160111
def export_sdk(tgt, swift_source_tree, swift_build_tree):
161112
print("assembling sdk")
162-
srcdir = swift_build_tree/ "lib" / "swift"
113+
srcdir = swift_build_tree / "lib" / "swift"
163114
tgtdir = tgt / "usr" / "lib" / "swift"
164115
if get_platform() == "linux":
165116
srcdir /= "linux"
@@ -181,11 +132,11 @@ def export_stdlibs(exported_dir, swift_build_tree):
181132
ext = 'so'
182133
lib_dir = swift_build_tree / 'lib/swift' / platform
183134
stdlibs = [
184-
f'libswiftCore.{ext}',
185-
'libswiftCompatibility50.a',
186-
'libswiftCompatibility51.a',
187-
'libswiftCompatibilityConcurrency.a',
188-
'libswiftCompatibilityDynamicReplacements.a']
135+
f'libswiftCore.{ext}',
136+
'libswiftCompatibility50.a',
137+
'libswiftCompatibility51.a',
138+
'libswiftCompatibilityConcurrency.a',
139+
'libswiftCompatibilityDynamicReplacements.a']
189140
for stdlib in stdlibs:
190141
lib_path = lib_dir / stdlib
191142
if lib_path.exists():
@@ -197,13 +148,8 @@ def export_stdlibs(exported_dir, swift_build_tree):
197148

198149
def export_libs(exported_dir, libs, swift_build_tree):
199150
print("exporting libraries")
200-
exportedlibs = [
201-
create_static_lib(exported_dir, libs),
202-
create_shared_lib(exported_dir, libs)
203-
]
204-
205-
for l in exportedlibs:
206-
l.rename(exported_dir / l.name)
151+
for i, l in enumerate(libs.static):
152+
shutil.copy(l, exported_dir / f"lib{i:03}{l.name[3:]}")
207153
export_stdlibs(exported_dir, swift_build_tree)
208154

209155

@@ -213,10 +159,14 @@ def export_headers(exported_dir, swift_source_tree, llvm_build_tree, swift_build
213159
llvm_source_tree = swift_source_tree.parent / 'llvm-project/llvm'
214160
clang_source_tree = swift_source_tree.parent / 'llvm-project/clang'
215161
clang_tools_build_tree = llvm_build_tree / 'tools/clang'
216-
header_dirs = [ llvm_source_tree, clang_source_tree, swift_source_tree, llvm_build_tree, swift_build_tree, clang_tools_build_tree ]
162+
header_dirs = [llvm_source_tree, clang_source_tree, swift_source_tree, llvm_build_tree, swift_build_tree,
163+
clang_tools_build_tree]
217164
for h in header_dirs:
218165
copy_includes(h, exported_dir)
219166

167+
def export_frontend(exported_dir, swift_build_tree):
168+
print("exporting swift-frontend")
169+
shutil.copy(swift_build_tree / 'bin' / 'swift-frontend', exported_dir)
220170

221171
def zip_dir(src, tgt):
222172
tgt = get_tgt(tgt, f"swift-prebuilt-{get_platform()}.zip")
@@ -238,10 +188,9 @@ def main(opts):
238188
export_libs(exported, libs, opts.swift_build_tree)
239189
export_headers(exported, opts.swift_source_tree, opts.llvm_build_tree, opts.swift_build_tree)
240190
export_sdk(exported / "sdk", opts.swift_source_tree, opts.swift_build_tree)
241-
191+
export_frontend(exported, opts.swift_build_tree)
242192
zip_dir(exported, opts.output)
243193

244194

245195
if __name__ == "__main__":
246196
main(getoptions())
247-

0 commit comments

Comments
 (0)
Please sign in to comment.