Skip to content

Commit 563d273

Browse files
authored
Merge pull request #9772 from github/redsun82/swift-extraction
Swift: extract ImportDecl and ModuleDecl
2 parents 7a1c380 + 8addc06 commit 563d273

29 files changed

+225
-49
lines changed

swift/codegen/schema.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,9 @@ IfConfigDecl:
273273

274274
ImportDecl:
275275
_extends: Decl
276+
is_exported: predicate
277+
module: ModuleDecl
278+
declarations: ValueDecl*
276279

277280
MissingMemberDecl:
278281
_extends: Decl
@@ -1067,6 +1070,8 @@ GenericTypeDecl:
10671070

10681071
ModuleDecl:
10691072
_extends: TypeDecl
1073+
is_builtin_module: predicate
1074+
is_system_module: predicate
10701075

10711076
ConstructorRefCallExpr:
10721077
_extends: SelfApplyExpr

swift/extractor/SwiftExtractor.cpp

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,19 @@ static std::string getTrapFilename(swift::ModuleDecl& module, swift::SourceFile*
6464
return filename;
6565
}
6666

67+
static llvm::SmallVector<swift::Decl*> getTopLevelDecls(swift::ModuleDecl& module,
68+
swift::SourceFile* primaryFile = nullptr) {
69+
llvm::SmallVector<swift::Decl*> ret;
70+
ret.push_back(&module);
71+
if (primaryFile) {
72+
primaryFile->getTopLevelDecls(ret);
73+
} else {
74+
module.getTopLevelDecls(ret);
75+
}
76+
return ret;
77+
}
78+
6779
static void extractDeclarations(const SwiftExtractorConfiguration& config,
68-
llvm::ArrayRef<swift::Decl*> topLevelDecls,
6980
swift::CompilerInstance& compiler,
7081
swift::ModuleDecl& module,
7182
swift::SourceFile* primaryFile = nullptr) {
@@ -119,10 +130,14 @@ static void extractDeclarations(const SwiftExtractorConfiguration& config,
119130
trap.emit(LocationsTrap{unknownLocationLabel, unknownFileLabel});
120131

121132
SwiftVisitor visitor(compiler.getSourceMgr(), arena, trap, module, primaryFile);
133+
auto topLevelDecls = getTopLevelDecls(module, primaryFile);
122134
for (auto decl : topLevelDecls) {
123135
visitor.extract(decl);
124136
}
125-
if (topLevelDecls.empty()) {
137+
// TODO the following will be moved to the dispatcher when we start caching swift file objects
138+
// for the moment, topLevelDecls always contains the current module, which does not have a file
139+
// associated with it, so we need a special case when there are no top level declarations
140+
if (topLevelDecls.size() == 1) {
126141
// In the case of empty files, the dispatcher is not called, but we still want to 'record' the
127142
// fact that the file was extracted
128143
llvm::SmallString<PATH_MAX> name(filename);
@@ -203,18 +218,15 @@ void codeql::extractSwiftFiles(const SwiftExtractorConfiguration& config,
203218
// user code twice: once during the module build in a form of a source file, and then as
204219
// a pre-built module during building of the dependent source files.
205220
if (module->isSystemModule() || module->isBuiltinModule()) {
206-
llvm::SmallVector<swift::Decl*> decls;
207-
module->getTopLevelDecls(decls);
208-
// TODO: pass ModuleDecl directly when we have module extraction in place?
209-
extractDeclarations(config, decls, compiler, *module);
221+
extractDeclarations(config, compiler, *module);
210222
} else {
211223
for (auto file : module->getFiles()) {
212224
auto sourceFile = llvm::dyn_cast<swift::SourceFile>(file);
213225
if (!sourceFile || inputFiles.count(sourceFile->getFilename().str()) == 0) {
214226
continue;
215227
}
216228
archiveFile(config, *sourceFile);
217-
extractDeclarations(config, sourceFile->getTopLevelDecls(), compiler, *module, sourceFile);
229+
extractDeclarations(config, compiler, *module, sourceFile);
218230
}
219231
}
220232
}

swift/extractor/infra/SwiftDispatcher.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,12 @@ class SwiftDispatcher {
112112
return assignNewLabel(&e, std::forward<Args>(args)...);
113113
}
114114

115+
// convenience methods for structured C++ creation
116+
template <typename E, typename... Args, std::enable_if_t<!std::is_pointer_v<E>>* = nullptr>
117+
auto createEntry(const E& e, Args&&... args) {
118+
return TrapClassOf<E>{assignNewLabel(&e, std::forward<Args>(args)...)};
119+
}
120+
115121
template <typename Tag>
116122
TrapLabel<Tag> createLabel() {
117123
auto ret = arena.allocateLabel<Tag>();
@@ -173,6 +179,11 @@ class SwiftDispatcher {
173179
return ret;
174180
}
175181

182+
template <typename... Args>
183+
void emitDebugInfo(const Args&... args) {
184+
trap.debug(std::forward<Args>(args)...);
185+
}
186+
176187
// In order to not emit duplicated entries for declarations, we restrict emission to only
177188
// Decls declared within the current "scope".
178189
// Depending on the whether we are extracting a primary source file or not the scope is defined as
@@ -186,7 +197,9 @@ class SwiftDispatcher {
186197
if (decl.getModuleContext() != &currentModule) {
187198
return false;
188199
}
189-
if (!currentPrimarySourceFile) {
200+
// ModuleDecl is a special case: if it passed the previous test, it is the current module
201+
// but it never has a source file, so we short circuit to emit it in any case
202+
if (!currentPrimarySourceFile || decl.getKind() == swift::DeclKind::Module) {
190203
return true;
191204
}
192205
if (auto context = decl.getDeclContext()) {

swift/extractor/trap/TrapOutput.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ class TrapOutput {
4141

4242
template <typename... Args>
4343
void debug(const Args&... args) {
44-
out_ << "// DEBUG: ";
45-
(out_ << ... << args) << '\n';
44+
out_ << "/* DEBUG:\n";
45+
(out_ << ... << args) << "\n*/\n";
4646
}
4747

4848
private:

swift/extractor/visitors/DeclVisitor.cpp

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -241,16 +241,15 @@ std::variant<codeql::AccessorDecl, codeql::AccessorDeclsTrap> DeclVisitor::trans
241241

242242
std::optional<codeql::SubscriptDecl> DeclVisitor::translateSubscriptDecl(
243243
const swift::SubscriptDecl& decl) {
244-
auto id = dispatcher_.assignNewLabel(decl, mangledName(decl));
245-
if (!dispatcher_.shouldEmitDeclBody(decl)) {
244+
auto entry = createNamedEntry(decl);
245+
if (!entry) {
246246
return std::nullopt;
247247
}
248-
SubscriptDecl entry{id};
249-
entry.element_type = dispatcher_.fetchLabel(decl.getElementInterfaceType());
248+
entry->element_type = dispatcher_.fetchLabel(decl.getElementInterfaceType());
250249
if (auto indices = decl.getIndices()) {
251-
entry.params = dispatcher_.fetchRepeatedLabels(*indices);
250+
entry->params = dispatcher_.fetchRepeatedLabels(*indices);
252251
}
253-
fillAbstractStorageDecl(decl, entry);
252+
fillAbstractStorageDecl(decl, *entry);
254253
return entry;
255254
}
256255

@@ -262,7 +261,32 @@ codeql::ExtensionDecl DeclVisitor::translateExtensionDecl(const swift::Extension
262261
return entry;
263262
}
264263

264+
codeql::ImportDecl DeclVisitor::translateImportDecl(const swift::ImportDecl& decl) {
265+
auto entry = dispatcher_.createEntry(decl);
266+
entry.is_exported = decl.isExported();
267+
entry.module = dispatcher_.fetchLabel(decl.getModule());
268+
entry.declarations = dispatcher_.fetchRepeatedLabels(decl.getDecls());
269+
return entry;
270+
}
271+
272+
std::optional<codeql::ModuleDecl> DeclVisitor::translateModuleDecl(const swift::ModuleDecl& decl) {
273+
auto entry = createNamedEntry(decl);
274+
if (!entry) {
275+
return std::nullopt;
276+
}
277+
entry->is_builtin_module = decl.isBuiltinModule();
278+
entry->is_system_module = decl.isSystemModule();
279+
fillTypeDecl(decl, *entry);
280+
return entry;
281+
}
282+
265283
std::string DeclVisitor::mangledName(const swift::ValueDecl& decl) {
284+
// ASTMangler::mangleAnyDecl crashes when called on `ModuleDecl`
285+
// TODO find a more unique string working also when different modules are compiled with the same
286+
// name
287+
if (decl.getKind() == swift::DeclKind::Module) {
288+
return static_cast<const swift::ModuleDecl&>(decl).getRealName().str().str();
289+
}
266290
// prefix adds a couple of special symbols, we don't necessary need them
267291
return mangler.mangleAnyDecl(&decl, /* prefix = */ false);
268292
}

swift/extractor/visitors/DeclVisitor.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ class DeclVisitor : public AstVisitorBase<DeclVisitor> {
5050
const swift::AccessorDecl& decl);
5151
std::optional<codeql::SubscriptDecl> translateSubscriptDecl(const swift::SubscriptDecl& decl);
5252
codeql::ExtensionDecl translateExtensionDecl(const swift::ExtensionDecl& decl);
53+
codeql::ImportDecl translateImportDecl(const swift::ImportDecl& decl);
54+
std::optional<codeql::ModuleDecl> translateModuleDecl(const swift::ModuleDecl& decl);
5355

5456
private:
5557
std::string mangledName(const swift::ValueDecl& decl);
@@ -66,6 +68,15 @@ class DeclVisitor : public AstVisitorBase<DeclVisitor> {
6668
void fillAbstractStorageDecl(const swift::AbstractStorageDecl& decl,
6769
codeql::AbstractStorageDecl& entry);
6870

71+
template <typename D>
72+
std::optional<TrapClassOf<D>> createNamedEntry(const D& decl) {
73+
auto id = dispatcher_.assignNewLabel(decl, mangledName(decl));
74+
if (dispatcher_.shouldEmitDeclBody(decl)) {
75+
return TrapClassOf<D>{id};
76+
}
77+
return std::nullopt;
78+
}
79+
6980
private:
7081
swift::Mangle::ASTMangler mangler;
7182
};

swift/extractor/visitors/TypeVisitor.cpp

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -122,13 +122,13 @@ void TypeVisitor::visitParenType(swift::ParenType* type) {
122122
}
123123

124124
codeql::OptionalType TypeVisitor::translateOptionalType(const swift::OptionalType& type) {
125-
auto entry = createEntry(type);
125+
auto entry = createTypeEntry(type);
126126
fillUnarySyntaxSugarType(type, entry);
127127
return entry;
128128
}
129129

130130
codeql::ArraySliceType TypeVisitor::translateArraySliceType(const swift::ArraySliceType& type) {
131-
auto entry = createEntry(type);
131+
auto entry = createTypeEntry(type);
132132
fillUnarySyntaxSugarType(type, entry);
133133
return entry;
134134
}
@@ -163,7 +163,7 @@ void TypeVisitor::visitLValueType(swift::LValueType* type) {
163163

164164
codeql::PrimaryArchetypeType TypeVisitor::translatePrimaryArchetypeType(
165165
const swift::PrimaryArchetypeType& type) {
166-
auto entry = createEntry(type);
166+
auto entry = createTypeEntry(type);
167167
fillArchetypeType(type, entry);
168168
return entry;
169169
}
@@ -229,7 +229,7 @@ void TypeVisitor::emitAnyGenericType(swift::AnyGenericType* type,
229229

230230
codeql::NestedArchetypeType TypeVisitor::translateNestedArchetypeType(
231231
const swift::NestedArchetypeType& type) {
232-
auto entry = createEntry(type);
232+
auto entry = createTypeEntry(type);
233233
entry.parent = dispatcher_.fetchLabel(type.getParent());
234234
entry.associated_type_declaration = dispatcher_.fetchLabel(type.getAssocType());
235235
fillArchetypeType(type, entry);
@@ -248,26 +248,26 @@ void TypeVisitor::fillArchetypeType(const swift::ArchetypeType& type, ArchetypeT
248248
}
249249

250250
codeql::ExistentialType TypeVisitor::translateExistentialType(const swift::ExistentialType& type) {
251-
auto entry = createEntry(type);
251+
auto entry = createTypeEntry(type);
252252
entry.constraint = dispatcher_.fetchLabel(type.getConstraintType());
253253
return entry;
254254
}
255255

256256
codeql::DynamicSelfType TypeVisitor::translateDynamicSelfType(const swift::DynamicSelfType& type) {
257-
auto entry = createEntry(type);
257+
auto entry = createTypeEntry(type);
258258
entry.static_self_type = dispatcher_.fetchLabel(type.getSelfType());
259259
return entry;
260260
}
261261

262262
codeql::VariadicSequenceType TypeVisitor::translateVariadicSequenceType(
263263
const swift::VariadicSequenceType& type) {
264-
auto entry = createEntry(type);
264+
auto entry = createTypeEntry(type);
265265
fillUnarySyntaxSugarType(type, entry);
266266
return entry;
267267
}
268268

269269
codeql::InOutType TypeVisitor::translateInOutType(const swift::InOutType& type) {
270-
auto entry = createEntry(type);
270+
auto entry = createTypeEntry(type);
271271
entry.object_type = dispatcher_.fetchLabel(type.getObjectType());
272272
return entry;
273273
}
@@ -300,19 +300,19 @@ void TypeVisitor::fillReferenceStorageType(const swift::ReferenceStorageType& ty
300300

301301
codeql::ProtocolCompositionType TypeVisitor::translateProtocolCompositionType(
302302
const swift::ProtocolCompositionType& type) {
303-
auto entry = createEntry(type);
303+
auto entry = createTypeEntry(type);
304304
entry.members = dispatcher_.fetchRepeatedLabels(type.getMembers());
305305
return entry;
306306
}
307307

308308
codeql::BuiltinIntegerLiteralType TypeVisitor::translateBuiltinIntegerLiteralType(
309309
const swift::BuiltinIntegerLiteralType& type) {
310-
return createEntry(type);
310+
return createTypeEntry(type);
311311
}
312312

313313
codeql::BuiltinIntegerType TypeVisitor::translateBuiltinIntegerType(
314314
const swift::BuiltinIntegerType& type) {
315-
auto entry = createEntry(type);
315+
auto entry = createTypeEntry(type);
316316
if (type.isFixedWidth()) {
317317
entry.width = type.getFixedWidth();
318318
}
@@ -321,51 +321,51 @@ codeql::BuiltinIntegerType TypeVisitor::translateBuiltinIntegerType(
321321

322322
codeql::BuiltinBridgeObjectType TypeVisitor::translateBuiltinBridgeObjectType(
323323
const swift::BuiltinBridgeObjectType& type) {
324-
return createEntry(type);
324+
return createTypeEntry(type);
325325
}
326326

327327
codeql::BuiltinDefaultActorStorageType TypeVisitor::translateBuiltinDefaultActorStorageType(
328328
const swift::BuiltinDefaultActorStorageType& type) {
329-
return createEntry(type);
329+
return createTypeEntry(type);
330330
}
331331

332332
codeql::BuiltinExecutorType TypeVisitor::translateBuiltinExecutorType(
333333
const swift::BuiltinExecutorType& type) {
334-
return createEntry(type);
334+
return createTypeEntry(type);
335335
}
336336

337337
codeql::BuiltinFloatType TypeVisitor::translateBuiltinFloatType(
338338
const swift::BuiltinFloatType& type) {
339-
return createEntry(type);
339+
return createTypeEntry(type);
340340
}
341341

342342
codeql::BuiltinJobType TypeVisitor::translateBuiltinJobType(const swift::BuiltinJobType& type) {
343-
return createEntry(type);
343+
return createTypeEntry(type);
344344
}
345345

346346
codeql::BuiltinNativeObjectType TypeVisitor::translateBuiltinNativeObjectType(
347347
const swift::BuiltinNativeObjectType& type) {
348-
return createEntry(type);
348+
return createTypeEntry(type);
349349
}
350350

351351
codeql::BuiltinRawPointerType TypeVisitor::translateBuiltinRawPointerType(
352352
const swift::BuiltinRawPointerType& type) {
353-
return createEntry(type);
353+
return createTypeEntry(type);
354354
}
355355

356356
codeql::BuiltinRawUnsafeContinuationType TypeVisitor::translateBuiltinRawUnsafeContinuationType(
357357
const swift::BuiltinRawUnsafeContinuationType& type) {
358-
return createEntry(type);
358+
return createTypeEntry(type);
359359
}
360360

361361
codeql::BuiltinUnsafeValueBufferType TypeVisitor::translateBuiltinUnsafeValueBufferType(
362362
const swift::BuiltinUnsafeValueBufferType& type) {
363-
return createEntry(type);
363+
return createTypeEntry(type);
364364
}
365365

366366
codeql::BuiltinVectorType TypeVisitor::translateBuiltinVectorType(
367367
const swift::BuiltinVectorType& type) {
368-
return createEntry(type);
368+
return createTypeEntry(type);
369369
}
370370

371371
} // namespace codeql

swift/extractor/visitors/TypeVisitor.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,8 @@ class TypeVisitor : public TypeVisitorBase<TypeVisitor> {
8181
void emitAnyGenericType(swift::AnyGenericType* type, TrapLabel<AnyGenericTypeTag> label);
8282

8383
template <typename T>
84-
auto createEntry(const T& type) {
85-
TrapClassOf<T> entry{dispatcher_.assignNewLabel(type)};
84+
auto createTypeEntry(const T& type) {
85+
auto entry = dispatcher_.createEntry(type);
8686
fillType(type, entry);
8787
return entry;
8888
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
| file://:0:0:0:0 | A |
2+
| file://:0:0:0:0 | B |
3+
| file://:0:0:0:0 | main |
4+
| file://:0:0:0:0 | partial_modules |
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import swift
2+
3+
from ModuleDecl decl
4+
where not decl.isBuiltinModule() and not decl.isSystemModule()
5+
select decl

0 commit comments

Comments
 (0)