]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp
Vendor import of lldb trunk r300422:
[FreeBSD/FreeBSD.git] / source / Plugins / ExpressionParser / Clang / ClangModulesDeclVendor.cpp
1 //===-- ClangModulesDeclVendor.cpp ------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 // C Includes
11 // C++ Includes
12 #include <mutex>
13
14 // Other libraries and framework includes
15 #include "clang/Basic/TargetInfo.h"
16 #include "clang/Frontend/CompilerInstance.h"
17 #include "clang/Frontend/FrontendActions.h"
18 #include "clang/Lex/Preprocessor.h"
19 #include "clang/Lex/PreprocessorOptions.h"
20 #include "clang/Parse/Parser.h"
21 #include "clang/Sema/Lookup.h"
22 #include "clang/Serialization/ASTReader.h"
23 #include "llvm/Support/FileSystem.h"
24 #include "llvm/Support/Path.h"
25 #include "llvm/Support/Threading.h"
26
27 // Project includes
28 #include "ClangModulesDeclVendor.h"
29
30 #include "lldb/Host/Host.h"
31 #include "lldb/Host/HostInfo.h"
32 #include "lldb/Symbol/CompileUnit.h"
33 #include "lldb/Target/Target.h"
34 #include "lldb/Utility/FileSpec.h"
35 #include "lldb/Utility/LLDBAssert.h"
36 #include "lldb/Utility/Log.h"
37 #include "lldb/Utility/StreamString.h"
38
39 using namespace lldb_private;
40
41 namespace {
42 // Any Clang compiler requires a consumer for diagnostics.  This one stores them
43 // as strings
44 // so we can provide them to the user in case a module failed to load.
45 class StoringDiagnosticConsumer : public clang::DiagnosticConsumer {
46 public:
47   StoringDiagnosticConsumer();
48
49   void HandleDiagnostic(clang::DiagnosticsEngine::Level DiagLevel,
50                         const clang::Diagnostic &info) override;
51
52   void ClearDiagnostics();
53
54   void DumpDiagnostics(Stream &error_stream);
55
56 private:
57   typedef std::pair<clang::DiagnosticsEngine::Level, std::string>
58       IDAndDiagnostic;
59   std::vector<IDAndDiagnostic> m_diagnostics;
60   Log *m_log;
61 };
62
63 // The private implementation of our ClangModulesDeclVendor.  Contains all the
64 // Clang state required
65 // to load modules.
66 class ClangModulesDeclVendorImpl : public ClangModulesDeclVendor {
67 public:
68   ClangModulesDeclVendorImpl(
69       llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> diagnostics_engine,
70       std::shared_ptr<clang::CompilerInvocation> compiler_invocation,
71       std::unique_ptr<clang::CompilerInstance> compiler_instance,
72       std::unique_ptr<clang::Parser> parser);
73
74   ~ClangModulesDeclVendorImpl() override = default;
75
76   bool AddModule(ModulePath &path, ModuleVector *exported_modules,
77                  Stream &error_stream) override;
78
79   bool AddModulesForCompileUnit(CompileUnit &cu, ModuleVector &exported_modules,
80                                 Stream &error_stream) override;
81
82   uint32_t FindDecls(const ConstString &name, bool append, uint32_t max_matches,
83                      std::vector<clang::NamedDecl *> &decls) override;
84
85   void ForEachMacro(const ModuleVector &modules,
86                     std::function<bool(const std::string &)> handler) override;
87
88 private:
89   void
90   ReportModuleExportsHelper(std::set<ClangModulesDeclVendor::ModuleID> &exports,
91                             clang::Module *module);
92
93   void ReportModuleExports(ModuleVector &exports, clang::Module *module);
94
95   clang::ModuleLoadResult DoGetModule(clang::ModuleIdPath path,
96                                       bool make_visible);
97
98   bool m_enabled = false;
99
100   llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> m_diagnostics_engine;
101   std::shared_ptr<clang::CompilerInvocation> m_compiler_invocation;
102   std::unique_ptr<clang::CompilerInstance> m_compiler_instance;
103   std::unique_ptr<clang::Parser> m_parser;
104   size_t m_source_location_index =
105       0; // used to give name components fake SourceLocations
106
107   typedef std::vector<ConstString> ImportedModule;
108   typedef std::map<ImportedModule, clang::Module *> ImportedModuleMap;
109   typedef std::set<ModuleID> ImportedModuleSet;
110   ImportedModuleMap m_imported_modules;
111   ImportedModuleSet m_user_imported_modules;
112 };
113 } // anonymous namespace
114
115 StoringDiagnosticConsumer::StoringDiagnosticConsumer() {
116   m_log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS);
117 }
118
119 void StoringDiagnosticConsumer::HandleDiagnostic(
120     clang::DiagnosticsEngine::Level DiagLevel, const clang::Diagnostic &info) {
121   llvm::SmallVector<char, 256> diagnostic_string;
122
123   info.FormatDiagnostic(diagnostic_string);
124
125   m_diagnostics.push_back(
126       IDAndDiagnostic(DiagLevel, std::string(diagnostic_string.data(),
127                                              diagnostic_string.size())));
128 }
129
130 void StoringDiagnosticConsumer::ClearDiagnostics() { m_diagnostics.clear(); }
131
132 void StoringDiagnosticConsumer::DumpDiagnostics(Stream &error_stream) {
133   for (IDAndDiagnostic &diag : m_diagnostics) {
134     switch (diag.first) {
135     default:
136       error_stream.PutCString(diag.second);
137       error_stream.PutChar('\n');
138       break;
139     case clang::DiagnosticsEngine::Level::Ignored:
140       break;
141     }
142   }
143 }
144
145 static FileSpec GetResourceDir() {
146   static FileSpec g_cached_resource_dir;
147
148   static llvm::once_flag g_once_flag;
149
150   llvm::call_once(g_once_flag, []() {
151     HostInfo::GetLLDBPath(lldb::ePathTypeClangDir, g_cached_resource_dir);
152   });
153
154   return g_cached_resource_dir;
155 }
156
157 ClangModulesDeclVendor::ClangModulesDeclVendor() {}
158
159 ClangModulesDeclVendor::~ClangModulesDeclVendor() {}
160
161 ClangModulesDeclVendorImpl::ClangModulesDeclVendorImpl(
162     llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> diagnostics_engine,
163     std::shared_ptr<clang::CompilerInvocation> compiler_invocation,
164     std::unique_ptr<clang::CompilerInstance> compiler_instance,
165     std::unique_ptr<clang::Parser> parser)
166     : m_diagnostics_engine(std::move(diagnostics_engine)),
167       m_compiler_invocation(std::move(compiler_invocation)),
168       m_compiler_instance(std::move(compiler_instance)),
169       m_parser(std::move(parser)) {}
170
171 void ClangModulesDeclVendorImpl::ReportModuleExportsHelper(
172     std::set<ClangModulesDeclVendor::ModuleID> &exports,
173     clang::Module *module) {
174   if (exports.count(reinterpret_cast<ClangModulesDeclVendor::ModuleID>(module)))
175     return;
176
177   exports.insert(reinterpret_cast<ClangModulesDeclVendor::ModuleID>(module));
178
179   llvm::SmallVector<clang::Module *, 2> sub_exports;
180
181   module->getExportedModules(sub_exports);
182
183   for (clang::Module *module : sub_exports) {
184     ReportModuleExportsHelper(exports, module);
185   }
186 }
187
188 void ClangModulesDeclVendorImpl::ReportModuleExports(
189     ClangModulesDeclVendor::ModuleVector &exports, clang::Module *module) {
190   std::set<ClangModulesDeclVendor::ModuleID> exports_set;
191
192   ReportModuleExportsHelper(exports_set, module);
193
194   for (ModuleID module : exports_set) {
195     exports.push_back(module);
196   }
197 }
198
199 bool ClangModulesDeclVendorImpl::AddModule(ModulePath &path,
200                                            ModuleVector *exported_modules,
201                                            Stream &error_stream) {
202   // Fail early.
203
204   if (m_compiler_instance->hadModuleLoaderFatalFailure()) {
205     error_stream.PutCString("error: Couldn't load a module because the module "
206                             "loader is in a fatal state.\n");
207     return false;
208   }
209
210   // Check if we've already imported this module.
211
212   std::vector<ConstString> imported_module;
213
214   for (ConstString path_component : path) {
215     imported_module.push_back(path_component);
216   }
217
218   {
219     ImportedModuleMap::iterator mi = m_imported_modules.find(imported_module);
220
221     if (mi != m_imported_modules.end()) {
222       if (exported_modules) {
223         ReportModuleExports(*exported_modules, mi->second);
224       }
225       return true;
226     }
227   }
228
229   if (!m_compiler_instance->getPreprocessor()
230            .getHeaderSearchInfo()
231            .lookupModule(path[0].GetStringRef())) {
232     error_stream.Printf("error: Header search couldn't locate module %s\n",
233                         path[0].AsCString());
234     return false;
235   }
236
237   llvm::SmallVector<std::pair<clang::IdentifierInfo *, clang::SourceLocation>,
238                     4>
239       clang_path;
240
241   {
242     clang::SourceManager &source_manager =
243         m_compiler_instance->getASTContext().getSourceManager();
244
245     for (ConstString path_component : path) {
246       clang_path.push_back(std::make_pair(
247           &m_compiler_instance->getASTContext().Idents.get(
248               path_component.GetStringRef()),
249           source_manager.getLocForStartOfFile(source_manager.getMainFileID())
250               .getLocWithOffset(m_source_location_index++)));
251     }
252   }
253
254   StoringDiagnosticConsumer *diagnostic_consumer =
255       static_cast<StoringDiagnosticConsumer *>(
256           m_compiler_instance->getDiagnostics().getClient());
257
258   diagnostic_consumer->ClearDiagnostics();
259
260   clang::Module *top_level_module = DoGetModule(clang_path.front(), false);
261
262   if (!top_level_module) {
263     diagnostic_consumer->DumpDiagnostics(error_stream);
264     error_stream.Printf("error: Couldn't load top-level module %s\n",
265                         path[0].AsCString());
266     return false;
267   }
268
269   clang::Module *submodule = top_level_module;
270
271   for (size_t ci = 1; ci < path.size(); ++ci) {
272     llvm::StringRef component = path[ci].GetStringRef();
273     submodule = submodule->findSubmodule(component.str());
274     if (!submodule) {
275       diagnostic_consumer->DumpDiagnostics(error_stream);
276       error_stream.Printf("error: Couldn't load submodule %s\n",
277                           component.str().c_str());
278       return false;
279     }
280   }
281
282   clang::Module *requested_module = DoGetModule(clang_path, true);
283
284   if (requested_module != nullptr) {
285     if (exported_modules) {
286       ReportModuleExports(*exported_modules, requested_module);
287     }
288
289     m_imported_modules[imported_module] = requested_module;
290
291     m_enabled = true;
292
293     return true;
294   }
295
296   return false;
297 }
298
299 bool ClangModulesDeclVendor::LanguageSupportsClangModules(
300     lldb::LanguageType language) {
301   switch (language) {
302   default:
303     return false;
304   // C++ and friends to be added
305   case lldb::LanguageType::eLanguageTypeC:
306   case lldb::LanguageType::eLanguageTypeC11:
307   case lldb::LanguageType::eLanguageTypeC89:
308   case lldb::LanguageType::eLanguageTypeC99:
309   case lldb::LanguageType::eLanguageTypeObjC:
310     return true;
311   }
312 }
313
314 bool ClangModulesDeclVendorImpl::AddModulesForCompileUnit(
315     CompileUnit &cu, ClangModulesDeclVendor::ModuleVector &exported_modules,
316     Stream &error_stream) {
317   if (LanguageSupportsClangModules(cu.GetLanguage())) {
318     std::vector<ConstString> imported_modules = cu.GetImportedModules();
319
320     for (ConstString imported_module : imported_modules) {
321       std::vector<ConstString> path;
322
323       path.push_back(imported_module);
324
325       if (!AddModule(path, &exported_modules, error_stream)) {
326         return false;
327       }
328     }
329
330     return true;
331   }
332
333   return true;
334 }
335
336 // ClangImporter::lookupValue
337
338 uint32_t
339 ClangModulesDeclVendorImpl::FindDecls(const ConstString &name, bool append,
340                                       uint32_t max_matches,
341                                       std::vector<clang::NamedDecl *> &decls) {
342   if (!m_enabled) {
343     return 0;
344   }
345
346   if (!append)
347     decls.clear();
348
349   clang::IdentifierInfo &ident =
350       m_compiler_instance->getASTContext().Idents.get(name.GetStringRef());
351
352   clang::LookupResult lookup_result(
353       m_compiler_instance->getSema(), clang::DeclarationName(&ident),
354       clang::SourceLocation(), clang::Sema::LookupOrdinaryName);
355
356   m_compiler_instance->getSema().LookupName(
357       lookup_result,
358       m_compiler_instance->getSema().getScopeForContext(
359           m_compiler_instance->getASTContext().getTranslationUnitDecl()));
360
361   uint32_t num_matches = 0;
362
363   for (clang::NamedDecl *named_decl : lookup_result) {
364     if (num_matches >= max_matches)
365       return num_matches;
366
367     decls.push_back(named_decl);
368     ++num_matches;
369   }
370
371   return num_matches;
372 }
373
374 void ClangModulesDeclVendorImpl::ForEachMacro(
375     const ClangModulesDeclVendor::ModuleVector &modules,
376     std::function<bool(const std::string &)> handler) {
377   if (!m_enabled) {
378     return;
379   }
380
381   typedef std::map<ModuleID, ssize_t> ModulePriorityMap;
382   ModulePriorityMap module_priorities;
383
384   ssize_t priority = 0;
385
386   for (ModuleID module : modules) {
387     module_priorities[module] = priority++;
388   }
389
390   if (m_compiler_instance->getPreprocessor().getExternalSource()) {
391     m_compiler_instance->getPreprocessor()
392         .getExternalSource()
393         ->ReadDefinedMacros();
394   }
395
396   for (clang::Preprocessor::macro_iterator
397            mi = m_compiler_instance->getPreprocessor().macro_begin(),
398            me = m_compiler_instance->getPreprocessor().macro_end();
399        mi != me; ++mi) {
400     const clang::IdentifierInfo *ii = nullptr;
401
402     {
403       if (clang::IdentifierInfoLookup *lookup =
404               m_compiler_instance->getPreprocessor()
405                   .getIdentifierTable()
406                   .getExternalIdentifierLookup()) {
407         lookup->get(mi->first->getName());
408       }
409       if (!ii) {
410         ii = mi->first;
411       }
412     }
413
414     ssize_t found_priority = -1;
415     clang::MacroInfo *macro_info = nullptr;
416
417     for (clang::ModuleMacro *module_macro :
418          m_compiler_instance->getPreprocessor().getLeafModuleMacros(ii)) {
419       clang::Module *module = module_macro->getOwningModule();
420
421       {
422         ModulePriorityMap::iterator pi =
423             module_priorities.find(reinterpret_cast<ModuleID>(module));
424
425         if (pi != module_priorities.end() && pi->second > found_priority) {
426           macro_info = module_macro->getMacroInfo();
427           found_priority = pi->second;
428         }
429       }
430
431       clang::Module *top_level_module = module->getTopLevelModule();
432
433       if (top_level_module != module) {
434         ModulePriorityMap::iterator pi = module_priorities.find(
435             reinterpret_cast<ModuleID>(top_level_module));
436
437         if ((pi != module_priorities.end()) && pi->second > found_priority) {
438           macro_info = module_macro->getMacroInfo();
439           found_priority = pi->second;
440         }
441       }
442     }
443
444     if (macro_info) {
445       std::string macro_expansion = "#define ";
446       macro_expansion.append(mi->first->getName().str());
447
448       {
449         if (macro_info->isFunctionLike()) {
450           macro_expansion.append("(");
451
452           bool first_arg = true;
453
454           for (clang::MacroInfo::arg_iterator ai = macro_info->arg_begin(),
455                                               ae = macro_info->arg_end();
456                ai != ae; ++ai) {
457             if (!first_arg) {
458               macro_expansion.append(", ");
459             } else {
460               first_arg = false;
461             }
462
463             macro_expansion.append((*ai)->getName().str());
464           }
465
466           if (macro_info->isC99Varargs()) {
467             if (first_arg) {
468               macro_expansion.append("...");
469             } else {
470               macro_expansion.append(", ...");
471             }
472           } else if (macro_info->isGNUVarargs()) {
473             macro_expansion.append("...");
474           }
475
476           macro_expansion.append(")");
477         }
478
479         macro_expansion.append(" ");
480
481         bool first_token = true;
482
483         for (clang::MacroInfo::tokens_iterator ti = macro_info->tokens_begin(),
484                                                te = macro_info->tokens_end();
485              ti != te; ++ti) {
486           if (!first_token) {
487             macro_expansion.append(" ");
488           } else {
489             first_token = false;
490           }
491
492           if (ti->isLiteral()) {
493             if (const char *literal_data = ti->getLiteralData()) {
494               std::string token_str(literal_data, ti->getLength());
495               macro_expansion.append(token_str);
496             } else {
497               bool invalid = false;
498               const char *literal_source =
499                   m_compiler_instance->getSourceManager().getCharacterData(
500                       ti->getLocation(), &invalid);
501
502               if (invalid) {
503                 lldbassert(0 && "Unhandled token kind");
504                 macro_expansion.append("<unknown literal value>");
505               } else {
506                 macro_expansion.append(
507                     std::string(literal_source, ti->getLength()));
508               }
509             }
510           } else if (const char *punctuator_spelling =
511                          clang::tok::getPunctuatorSpelling(ti->getKind())) {
512             macro_expansion.append(punctuator_spelling);
513           } else if (const char *keyword_spelling =
514                          clang::tok::getKeywordSpelling(ti->getKind())) {
515             macro_expansion.append(keyword_spelling);
516           } else {
517             switch (ti->getKind()) {
518             case clang::tok::TokenKind::identifier:
519               macro_expansion.append(ti->getIdentifierInfo()->getName().str());
520               break;
521             case clang::tok::TokenKind::raw_identifier:
522               macro_expansion.append(ti->getRawIdentifier().str());
523               break;
524             default:
525               macro_expansion.append(ti->getName());
526               break;
527             }
528           }
529         }
530
531         if (handler(macro_expansion)) {
532           return;
533         }
534       }
535     }
536   }
537 }
538
539 clang::ModuleLoadResult
540 ClangModulesDeclVendorImpl::DoGetModule(clang::ModuleIdPath path,
541                                         bool make_visible) {
542   clang::Module::NameVisibilityKind visibility =
543       make_visible ? clang::Module::AllVisible : clang::Module::Hidden;
544
545   const bool is_inclusion_directive = false;
546
547   return m_compiler_instance->loadModule(path.front().second, path, visibility,
548                                          is_inclusion_directive);
549 }
550
551 static const char *ModuleImportBufferName = "LLDBModulesMemoryBuffer";
552
553 lldb_private::ClangModulesDeclVendor *
554 ClangModulesDeclVendor::Create(Target &target) {
555   // FIXME we should insure programmatically that the expression parser's
556   // compiler and the modules runtime's
557   // compiler are both initialized in the same way – preferably by the same
558   // code.
559
560   if (!target.GetPlatform()->SupportsModules())
561     return nullptr;
562
563   const ArchSpec &arch = target.GetArchitecture();
564
565   std::vector<std::string> compiler_invocation_arguments = {
566       "clang",
567       "-fmodules",
568       "-fimplicit-module-maps",
569       "-fcxx-modules",
570       "-fsyntax-only",
571       "-femit-all-decls",
572       "-target",
573       arch.GetTriple().str(),
574       "-fmodules-validate-system-headers",
575       "-Werror=non-modular-include-in-framework-module"};
576
577   target.GetPlatform()->AddClangModuleCompilationOptions(
578       &target, compiler_invocation_arguments);
579
580   compiler_invocation_arguments.push_back(ModuleImportBufferName);
581
582   // Add additional search paths with { "-I", path } or { "-F", path } here.
583
584   {
585     llvm::SmallString<128> DefaultModuleCache;
586     const bool erased_on_reboot = false;
587     llvm::sys::path::system_temp_directory(erased_on_reboot,
588                                            DefaultModuleCache);
589     llvm::sys::path::append(DefaultModuleCache, "org.llvm.clang");
590     llvm::sys::path::append(DefaultModuleCache, "ModuleCache");
591     std::string module_cache_argument("-fmodules-cache-path=");
592     module_cache_argument.append(DefaultModuleCache.str().str());
593     compiler_invocation_arguments.push_back(module_cache_argument);
594   }
595
596   FileSpecList &module_search_paths = target.GetClangModuleSearchPaths();
597
598   for (size_t spi = 0, spe = module_search_paths.GetSize(); spi < spe; ++spi) {
599     const FileSpec &search_path = module_search_paths.GetFileSpecAtIndex(spi);
600
601     std::string search_path_argument = "-I";
602     search_path_argument.append(search_path.GetPath());
603
604     compiler_invocation_arguments.push_back(search_path_argument);
605   }
606
607   {
608     FileSpec clang_resource_dir = GetResourceDir();
609
610     if (llvm::sys::fs::is_directory(clang_resource_dir.GetPath())) {
611       compiler_invocation_arguments.push_back("-resource-dir");
612       compiler_invocation_arguments.push_back(clang_resource_dir.GetPath());
613     }
614   }
615
616   llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> diagnostics_engine =
617       clang::CompilerInstance::createDiagnostics(new clang::DiagnosticOptions,
618                                                  new StoringDiagnosticConsumer);
619
620   std::vector<const char *> compiler_invocation_argument_cstrs;
621
622   for (const std::string &arg : compiler_invocation_arguments) {
623     compiler_invocation_argument_cstrs.push_back(arg.c_str());
624   }
625
626   std::shared_ptr<clang::CompilerInvocation> invocation =
627       clang::createInvocationFromCommandLine(compiler_invocation_argument_cstrs,
628                                              diagnostics_engine);
629
630   if (!invocation)
631     return nullptr;
632
633   std::unique_ptr<llvm::MemoryBuffer> source_buffer =
634       llvm::MemoryBuffer::getMemBuffer(
635           "extern int __lldb __attribute__((unavailable));",
636           ModuleImportBufferName);
637
638   invocation->getPreprocessorOpts().addRemappedFile(ModuleImportBufferName,
639                                                     source_buffer.release());
640
641   std::unique_ptr<clang::CompilerInstance> instance(
642       new clang::CompilerInstance);
643
644   instance->setDiagnostics(diagnostics_engine.get());
645   instance->setInvocation(invocation);
646
647   std::unique_ptr<clang::FrontendAction> action(new clang::SyntaxOnlyAction);
648
649   instance->setTarget(clang::TargetInfo::CreateTargetInfo(
650       *diagnostics_engine, instance->getInvocation().TargetOpts));
651
652   if (!instance->hasTarget())
653     return nullptr;
654
655   instance->getTarget().adjust(instance->getLangOpts());
656
657   if (!action->BeginSourceFile(*instance,
658                                instance->getFrontendOpts().Inputs[0]))
659     return nullptr;
660
661   instance->getPreprocessor().enableIncrementalProcessing();
662
663   instance->createModuleManager();
664
665   instance->createSema(action->getTranslationUnitKind(), nullptr);
666
667   const bool skipFunctionBodies = false;
668   std::unique_ptr<clang::Parser> parser(new clang::Parser(
669       instance->getPreprocessor(), instance->getSema(), skipFunctionBodies));
670
671   instance->getPreprocessor().EnterMainSourceFile();
672   parser->Initialize();
673
674   clang::Parser::DeclGroupPtrTy parsed;
675
676   while (!parser->ParseTopLevelDecl(parsed))
677     ;
678
679   return new ClangModulesDeclVendorImpl(std::move(diagnostics_engine),
680                                         std::move(invocation),
681                                         std::move(instance), std::move(parser));
682 }