66#include < queue>
77
88#include < swift/AST/SourceFile.h>
9+ #include < swift/AST/Builtins.h>
910#include < swift/Basic/FileTypes.h>
1011#include < llvm/ADT/SmallString.h>
1112#include < llvm/Support/FileSystem.h>
@@ -68,22 +69,52 @@ static std::string getFilename(swift::ModuleDecl& module, swift::SourceFile* pri
6869 return module .getModuleFilename ().str ();
6970}
7071
72+ static llvm::SmallVector<swift::ValueDecl*> getBuiltinDecls (swift::ModuleDecl& builtinModule) {
73+ llvm::SmallVector<swift::ValueDecl*> values;
74+ for (auto symbol : {
75+ " zeroInitializer" , " BridgeObject" , " Word" , " NativeObject" ,
76+ " RawPointer" , " Int1" , " Int8" , " Int16" ,
77+ " Int32" , " Int64" , " IntLiteral" , " FPIEEE16" ,
78+ " FPIEEE32" , " FPIEEE64" , " FPIEEE80" , " Vec2xInt8" ,
79+ " Vec4xInt8" , " Vec8xInt8" , " Vec16xInt8" , " Vec32xInt8" ,
80+ " Vec64xInt8" , " Vec2xInt16" , " Vec4xInt16" , " Vec8xInt16" ,
81+ " Vec16xInt16" , " Vec32xInt16" , " Vec64xInt16" , " Vec2xInt32" ,
82+ " Vec4xInt32" , " Vec8xInt32" , " Vec16xInt32" , " Vec32xInt32" ,
83+ " Vec64xInt32" , " Vec2xInt64" , " Vec4xInt64" , " Vec8xInt64" ,
84+ " Vec16xInt64" , " Vec32xInt64" , " Vec64xInt64" , " Vec2xFPIEEE16" ,
85+ " Vec4xFPIEEE16" , " Vec8xFPIEEE16" , " Vec16xFPIEEE16" , " Vec32xFPIEEE16" ,
86+ " Vec64xFPIEEE16" , " Vec2xFPIEEE32" , " Vec4xFPIEEE32" , " Vec8xFPIEEE32" ,
87+ " Vec16xFPIEEE32" , " Vec32xFPIEEE32" , " Vec64xFPIEEE32" , " Vec2xFPIEEE64" ,
88+ " Vec4xFPIEEE64" , " Vec8xFPIEEE64" , " Vec16xFPIEEE64" , " Vec32xFPIEEE64" ,
89+ " Vec64xFPIEEE64" ,
90+ }) {
91+ builtinModule.lookupValue (builtinModule.getASTContext ().getIdentifier (symbol),
92+ swift::NLKind::QualifiedLookup, values);
93+ }
94+ return values;
95+ }
96+
7197static llvm::SmallVector<swift::Decl*> getTopLevelDecls (swift::ModuleDecl& module ,
7298 swift::SourceFile* primaryFile = nullptr ) {
7399 llvm::SmallVector<swift::Decl*> ret;
74100 ret.push_back (&module );
75101 if (primaryFile) {
76102 primaryFile->getTopLevelDecls (ret);
103+ } else if (module .isBuiltinModule ()) {
104+ for (auto d : getBuiltinDecls (module )) {
105+ ret.push_back (d);
106+ }
77107 } else {
78108 module .getTopLevelDecls (ret);
79109 }
80110 return ret;
81111}
82112
83- static void extractDeclarations (const SwiftExtractorConfiguration& config,
84- swift::CompilerInstance& compiler,
85- swift::ModuleDecl& module ,
86- swift::SourceFile* primaryFile = nullptr ) {
113+ static std::unordered_set<swift::ModuleDecl*> extractDeclarations (
114+ const SwiftExtractorConfiguration& config,
115+ swift::CompilerInstance& compiler,
116+ swift::ModuleDecl& module ,
117+ swift::SourceFile* primaryFile = nullptr ) {
87118 auto filename = getFilename (module , primaryFile);
88119
89120 // The extractor can be called several times from different processes with
@@ -92,7 +123,7 @@ static void extractDeclarations(const SwiftExtractorConfiguration& config,
92123 auto trapTarget = createTargetTrapFile (config, filename);
93124 if (!trapTarget) {
94125 // another process arrived first, nothing to do for us
95- return ;
126+ return {} ;
96127 }
97128 TrapDomain trap{*trapTarget};
98129
@@ -116,6 +147,7 @@ static void extractDeclarations(const SwiftExtractorConfiguration& config,
116147 for (auto & comment : comments) {
117148 visitor.extract (comment);
118149 }
150+ return std::move (visitor).getEncounteredModules ();
119151}
120152
121153static std::unordered_set<std::string> collectInputFilenames (swift::CompilerInstance& compiler) {
@@ -132,40 +164,18 @@ static std::unordered_set<std::string> collectInputFilenames(swift::CompilerInst
132164 return sourceFiles;
133165}
134166
135- static std::unordered_set<swift::ModuleDecl*> collectModules (swift::CompilerInstance& compiler) {
136- // getASTContext().getLoadedModules() does not provide all the modules available within the
137- // program.
138- // We need to iterate over all the imported modules (recursively) to see the whole "universe."
139- std::unordered_set<swift::ModuleDecl*> allModules;
140- std::queue<swift::ModuleDecl*> worklist;
141- for (auto & [_, module ] : compiler.getASTContext ().getLoadedModules ()) {
142- worklist.push (module );
143- allModules.insert (module );
144- }
145-
146- while (!worklist.empty ()) {
147- auto module = worklist.front ();
148- worklist.pop ();
149- llvm::SmallVector<swift::ImportedModule> importedModules;
150- // TODO: we may need more than just Exported ones
151- module ->getImportedModules (importedModules, swift::ModuleDecl::ImportFilterKind::Exported);
152- for (auto & imported : importedModules) {
153- if (allModules.count (imported.importedModule ) == 0 ) {
154- worklist.push (imported.importedModule );
155- allModules.insert (imported.importedModule );
156- }
157- }
158- }
159- return allModules;
160- }
161-
162167void codeql::extractSwiftFiles (const SwiftExtractorConfiguration& config,
163168 swift::CompilerInstance& compiler) {
164169 auto inputFiles = collectInputFilenames (compiler);
165- auto modules = collectModules (compiler);
170+ std::vector<swift::ModuleDecl*> todo = {compiler.getMainModule ()};
171+ std::unordered_set<swift::ModuleDecl*> processed = {};
166172
167- for (auto & module : modules) {
173+ while (!todo.empty ()) {
174+ auto module = todo.back ();
175+ todo.pop_back ();
176+ llvm::errs () << " processing module " << module ->getName () << ' \n ' ;
168177 bool isFromSourceFile = false ;
178+ std::unordered_set<swift::ModuleDecl*> encounteredModules;
169179 for (auto file : module ->getFiles ()) {
170180 auto sourceFile = llvm::dyn_cast<swift::SourceFile>(file);
171181 if (!sourceFile) {
@@ -176,10 +186,16 @@ void codeql::extractSwiftFiles(const SwiftExtractorConfiguration& config,
176186 continue ;
177187 }
178188 archiveFile (config, *sourceFile);
179- extractDeclarations (config, compiler, *module , sourceFile);
189+ encounteredModules = extractDeclarations (config, compiler, *module , sourceFile);
180190 }
181191 if (!isFromSourceFile) {
182- extractDeclarations (config, compiler, *module );
192+ encounteredModules = extractDeclarations (config, compiler, *module );
193+ }
194+ processed.insert (module );
195+ for (auto encountered : encounteredModules) {
196+ if (processed.count (encountered) == 0 ) {
197+ todo.push_back (encountered);
198+ }
183199 }
184200 }
185201}
0 commit comments