1
2
3
4
5
6 #include <cmajor/symbols/Module.hpp>
7 #include <cmajor/symbols/ModuleCache.hpp>
8 #include <cmajor/symbols/SourceFileModuleMap.hpp>
9 #include <cmajor/symbols/SymbolWriter.hpp>
10 #include <cmajor/symbols/SymbolReader.hpp>
11 #include <cmajor/symbols/GlobalFlags.hpp>
12 #include <cmajor/symbols/SymbolCollector.hpp>
13 #include <cmajor/symbols/Warning.hpp>
14 #include <cmajor/symbols/DebugFlags.hpp>
15 #include <cmajor/symbols/FunctionIndex.hpp>
16 #include <cmajor/symbols/Sources.hpp>
17 #include <cmajor/cmdebug/DebugInfoIo.hpp>
18 #include <cmajor/cmdebug/DIVariable.hpp>
19 #include <sngcm/ast/Project.hpp>
20 #include <sngcm/ast/AstReader.hpp>
21 #include <soulng/util/MappedInputFile.hpp>
22 #include <soulng/util/CodeFormatter.hpp>
23 #include <soulng/util/Path.hpp>
24 #include <soulng/util/Unicode.hpp>
25 #include <soulng/util/TextUtils.hpp>
26 #include <soulng/util/Log.hpp>
27 #include <soulng/util/Time.hpp>
28 #include <boost/filesystem.hpp>
29 #include <boost/uuid/random_generator.hpp>
30 #include <boost/uuid/uuid_io.hpp>
31 #include <boost/functional/hash.hpp>
32 #include <mutex>
33 #include <iostream>
34
35 namespace cmajor { namespace symbols {
36
37
38
39
40 using namespace soulng::unicode;
41 using namespace soulng::util;
42
43 class SystemModuleSet
44 {
45 public:
46 static void Init();
47 static void Done();
48 static SystemModuleSet& Instance() { Assert(instance, "system module set not initialized"); return *instance; }
49 bool IsSystemModule(const std::u32string& moduleName) const;
50 private:
51 static std::unique_ptr<SystemModuleSet> instance;
52 std::unordered_set<std::u32string> systemModuleNames;
53 SystemModuleSet();
54 };
55
56 std::unique_ptr<SystemModuleSet> SystemModuleSet::instance;
57
58 void SystemModuleSet::Init()
59 {
60 instance.reset(new SystemModuleSet());
61 }
62
63 void SystemModuleSet::Done()
64 {
65 instance.reset();
66 }
67
68 SystemModuleSet::SystemModuleSet()
69 {
70 systemModuleNames.insert(U"System.Core");
71 systemModuleNames.insert(U"System.Runtime");
72 systemModuleNames.insert(U"System.Base");
73 systemModuleNames.insert(U"System.Lex");
74 systemModuleNames.insert(U"System.Parsing");
75 systemModuleNames.insert(U"System.Net.Sockets");
76 systemModuleNames.insert(U"System.Net.Http");
77 systemModuleNames.insert(U"System.Json");
78 systemModuleNames.insert(U"System.Xml");
79 systemModuleNames.insert(U"System.Dom");
80 systemModuleNames.insert(U"System.Xml.Serialization");
81 systemModuleNames.insert(U"System.Numerics.Multiprecision");
82 systemModuleNames.insert(U"System.IO.Compression");
83 systemModuleNames.insert(U"System.RegularExpressions");
84 systemModuleNames.insert(U"System.XPath");
85 systemModuleNames.insert(U"System.Init");
86 systemModuleNames.insert(U"System");
87 systemModuleNames.insert(U"System.Install");
88 systemModuleNames.insert(U"System.Windows");
89 systemModuleNames.insert(U"System.Windows.Install");
90 }
91
92 bool SystemModuleSet::IsSystemModule(const std::u32string& moduleName) const
93 {
94 auto it = systemModuleNames.find(moduleName);
95 if (it != systemModuleNames.cend())
96 {
97 return true;
98 }
99 return false;
100 }
101
102 bool IsSystemModule(const std::u32string& moduleName)
103 {
104 return SystemModuleSet::Instance().IsSystemModule(moduleName);
105 }
106
107 class ContainerClassTemplateMap
108 {
109 public:
110 static void Init();
111 static void Done();
112 static ContainerClassTemplateMap& Instance() { Assert(instance, "container class template map not initialized"); return *instance; }
113 cmajor::debug::ContainerClassTemplateKind GetContainerClassTemplateKind(const std::u32string& fullClassName) const;
114 private:
115 static std::unique_ptr<ContainerClassTemplateMap> instance;
116 std::unordered_map<std::u32string, cmajor::debug::ContainerClassTemplateKind> containerClassTemplateMap;
117 ContainerClassTemplateMap();
118 };
119
120 void ContainerClassTemplateMap::Init()
121 {
122 instance.reset(new ContainerClassTemplateMap());
123 }
124
125 void ContainerClassTemplateMap::Done()
126 {
127 instance.reset();
128 }
129
130 std::unique_ptr<ContainerClassTemplateMap> ContainerClassTemplateMap::instance;
131
132 ContainerClassTemplateMap::ContainerClassTemplateMap()
133 {
134 containerClassTemplateMap[U"System.Collections.ForwardList<T>"] = cmajor::debug::ContainerClassTemplateKind::forwardList;
135 containerClassTemplateMap[U"System.Collections.HashMap<K, T, H, C>"] = cmajor::debug::ContainerClassTemplateKind::hashMap;
136 containerClassTemplateMap[U"System.Collections.HashSet<T, H, C>"] = cmajor::debug::ContainerClassTemplateKind::hashSet;
137 containerClassTemplateMap[U"System.Collections.LinkedList<T>"] = cmajor::debug::ContainerClassTemplateKind::linkedList;
138 containerClassTemplateMap[U"System.Collections.List<T>"] = cmajor::debug::ContainerClassTemplateKind::list;
139 containerClassTemplateMap[U"System.Collections.Map<Key, Value, KeyCompare>"] = cmajor::debug::ContainerClassTemplateKind::map;
140 containerClassTemplateMap[U"System.Collections.Queue<T>"] = cmajor::debug::ContainerClassTemplateKind::queue;
141 containerClassTemplateMap[U"System.Collections.Set<T, C>"] = cmajor::debug::ContainerClassTemplateKind::set;
142 containerClassTemplateMap[U"System.Collections.Stack<T>"] = cmajor::debug::ContainerClassTemplateKind::stack;
143 }
144
145 cmajor::debug::ContainerClassTemplateKind ContainerClassTemplateMap::GetContainerClassTemplateKind(const std::u32string& fullClassName) const
146 {
147 auto it = containerClassTemplateMap.find(fullClassName);
148 if (it != containerClassTemplateMap.cend())
149 {
150 return it->second;
151 }
152 else
153 {
154 return cmajor::debug::ContainerClassTemplateKind::notContainerClassTemplate;
155 }
156 }
157
158 cmajor::debug::ContainerClassTemplateKind GetContainerClassTemplateKind(const std::u32string& fullClassName)
159 {
160 return ContainerClassTemplateMap::Instance().GetContainerClassTemplateKind(fullClassName);
161 }
162
163 const char* cmajorModuleTag = "CMM";
164
165 ModuleTag::ModuleTag()
166 {
167 bytes[0] = cmajorModuleTag[0];
168 bytes[1] = cmajorModuleTag[1];
169 bytes[2] = cmajorModuleTag[2];
170 bytes[3] = currentModuleFormat;
171 }
172
173 void ModuleTag::Write(SymbolWriter& writer)
174 {
175 writer.GetBinaryWriter().Write(bytes[0]);
176 writer.GetBinaryWriter().Write(bytes[1]);
177 writer.GetBinaryWriter().Write(bytes[2]);
178 writer.GetBinaryWriter().Write(bytes[3]);
179 }
180
181 void ModuleTag::Read(SymbolReader& reader)
182 {
183 bytes[0] = reader.GetBinaryReader().ReadByte();
184 bytes[1] = reader.GetBinaryReader().ReadByte();
185 bytes[2] = reader.GetBinaryReader().ReadByte();
186 bytes[3] = reader.GetBinaryReader().ReadByte();
187 }
188
189 std::string ModuleFlagStr(ModuleFlags flags)
190 {
191 std::string s;
192 if ((flags & ModuleFlags::system) != ModuleFlags::none)
193 {
194 if (!s.empty())
195 {
196 s.append(1, ' ');
197 }
198 s.append("system");
199 }
200 if ((flags & ModuleFlags::core) != ModuleFlags::none)
201 {
202 if (!s.empty())
203 {
204 s.append(1, ' ');
205 }
206 s.append("core");
207 }
208 return s;
209 }
210
211 ModuleDependency::ModuleDependency(Module* module_) : module(module_)
212 {
213 }
214
215 void ModuleDependency::AddReferencedModule(Module* referencedModule)
216 {
217 if (std::find(referencedModules.cbegin(), referencedModules.cend(), referencedModule) == referencedModules.cend())
218 {
219 referencedModules.push_back(referencedModule);
220 }
221 }
222
223 void ModuleDependency::Dump(CodeFormatter& formatter)
224 {
225 formatter.IncIndent();
226 int n = referencedModules.size();
227 for (int i = 0; i < n; ++i)
228 {
229 Module* referencedModule = referencedModules[i];
230 formatter.WriteLine(ToUtf8(referencedModule->Name()));
231 referencedModule->GetModuleDependency().Dump(formatter);
232 }
233 formatter.DecIndent();
234 }
235
236 int32_t FileTable::RegisterFilePath(const std::string& filePath)
237 {
238 int32_t fileIndex = filePaths.size();
239 filePaths.push_back(filePath);
240 return fileIndex;
241 }
242
243 std::string FileTable::GetFilePath(int32_t fileIndex) const
244 {
245 if (fileIndex >= 0 && fileIndex < filePaths.size())
246 {
247 return filePaths[fileIndex];
248 }
249 return std::string();
250 }
251
252 void FileTable::Write(BinaryWriter& writer, bool systemModule)
253 {
254 uint32_t n = filePaths.size();
255 writer.WriteULEB128UInt(n);
256 std::string cmajorRoot;
257 if (systemModule)
258 {
259 cmajorRoot = GetFullPath(CmajorRootDir());
260 if (!EndsWith(cmajorRoot, "/"))
261 {
262 cmajorRoot.append("/");
263 }
264 }
265 for (uint32_t i = 0; i < n; ++i)
266 {
267 std::string filePath = GetFullPath(filePaths[i]);
268 if (systemModule)
269 {
270 if (filePath.find(cmajorRoot, 0) == 0)
271 {
272 filePath = filePath.substr(cmajorRoot.size());
273 }
274 }
275 writer.Write(filePath);
276 }
277 }
278
279 void FileTable::Read(BinaryReader& reader, bool systemModule)
280 {
281 filePaths.clear();
282 std::string cmajorRoot;
283 if (systemModule)
284 {
285 cmajorRoot = GetFullPath(CmajorRootDir());
286 if (!EndsWith(cmajorRoot, "/"))
287 {
288 cmajorRoot.append("/");
289 }
290 }
291 uint32_t n = reader.ReadULEB128UInt();
292 for (uint32_t i = 0; i < n; ++i)
293 {
294 if (systemModule)
295 {
296 std::string filePath = reader.ReadUtf8String();
297 filePath = Path::Combine(cmajorRoot, filePath);
298 filePaths.push_back(std::move(filePath));
299 }
300 else
301 {
302 std::string filePath = reader.ReadUtf8String();
303 filePaths.push_back(std::move(filePath));
304 }
305 }
306 }
307
308 void FileTable::Dump(CodeFormatter& formatter)
309 {
310 if (!IsEmpty())
311 {
312 formatter.WriteLine("source file paths:");
313 formatter.IncIndent();
314 int n = filePaths.size();
315 for (int i = 0; i < n; ++i)
316 {
317 formatter.WriteLine(std::to_string(i) + " : " + filePaths[i]);
318 }
319 formatter.DecIndent();
320 }
321 }
322
323 SourceFileCache::SourceFileCache()
324 {
325 }
326
327 const std::u32string& SourceFileCache::GetFileContent(const std::string& filePath)
328 {
329 auto it = fileContentMap.find(filePath);
330 if (it != fileContentMap.cend())
331 {
332 return *it->second;
333 }
334 else
335 {
336 std::unique_ptr<std::u32string> fileContent(new std::u32string(ToUtf32(ReadFile(filePath))));
337 std::u32string* str = fileContent.get();
338 fileContentMap[filePath] = std::move(fileContent);
339 return *str;
340 }
341 }
342
343 cmajor::debug::SourceSpan MakeSourceSpan(const Span& span, const boost::uuids::uuid& sourceModuleId)
344 {
345 if (!span.Valid()) return cmajor::debug::SourceSpan();
346 if (sourceModuleId.is_nil()) return cmajor::debug::SourceSpan();
347 Module* module = GetModuleById(sourceModuleId);
348 if (!module) return cmajor::debug::SourceSpan();
349 return module->SpanToSourceSpan(span);
350 }
351
352 void Visit(std::std::vector<Module*>&finishReadOrder, Module*module, std::std::unordered_set<Module*>&visited, std::std::unordered_set<Module*>&tempVisit,
353 std::std::unordered_map<Module*, ModuleDependency*>&dependencyMap, constModule*rootModule)
354 {
355 if (tempVisit.find(module) == tempVisit.cend())
356 {
357 if (visited.find(module) == visited.cend())
358 {
359 tempVisit.insert(module);
360 auto i = dependencyMap.find(module);
361 if (i != dependencyMap.cend())
362 {
363 ModuleDependency* dependency = i->second;
364 for (Module* dependentAssembly : dependency->ReferencedModules())
365 {
366 Visit(finishReadOrder, dependentAssembly, visited, tempVisit, dependencyMap, rootModule);
367 }
368 tempVisit.erase(module);
369 visited.insert(module);
370 finishReadOrder.push_back(module);
371 }
372 else
373 {
374 throw std::runtime_error("module '" + ToUtf8(module->Name()) + "' not found in dependencies of module '" + ToUtf8(rootModule->Name()) + "'");
375 }
376 }
377 }
378 else
379 {
380 throw std::runtime_error("circular module dependency '" + ToUtf8(module->Name()) + "' detected in dependencies of module '" + ToUtf8(rootModule->Name()) + "'");
381 }
382 }
383
384 std::std::vector<Module*>CreateFinishReadOrder(std::std::vector<Module*>&modules, std::std::unordered_map<Module*, ModuleDependency*>&dependencyMap, constModule*rootModule)
385 {
386 std::vector<Module*> finishReadOrder;
387 std::unordered_set<Module*> visited;
388 std::unordered_set<Module*> tempVisit;
389 for (Module* module : modules)
390 {
391 if (visited.find(module) == visited.cend())
392 {
393 Visit(finishReadOrder, module, visited, tempVisit, dependencyMap, rootModule);
394 }
395 }
396 return finishReadOrder;
397 }
398
399 void FinishReads(Module* rootModule, std::std::vector<Module*>&finishReadOrder, boolall, boolreadRoot)
400 {
401 #ifdef MODULE_READING_DEBUG
402
403
404 #endif
405 int n = finishReadOrder.size() - 1;
406 if (all)
407 {
408 n = finishReadOrder.size();
409 }
410 for (int i = 0; i < n; ++i)
411 {
412 Module* module = finishReadOrder[i];
413 if (!module->HasSymbolTable() || (module == rootModule && all && readRoot))
414 {
415 #ifdef MODULE_READING_DEBUG
416
417 #endif
418 module->CreateSymbolTable();
419 std::vector<TypeOrConceptRequest> typeAndConceptRequests;
420 std::vector<FunctionRequest> functionRequests;
421 std::vector<ClassTemplateSpecializationSymbol*> classTemplateSpecializations;
422 std::vector<FunctionSymbol*> conversions;
423 std::vector<ArrayTypeSymbol*> arrayTypes;
424 std::vector<DerivedTypeSymbol*> derivedTypes;
425 SymbolReader reader(module->FilePathReadFrom());
426 reader.GetAstReader().SetModuleMaps(rootModule->Id(), module->GetModuleNameTable(), rootModule->GetModuleIdMap());
427 reader.SetModule(module);
428 reader.SetArrayTypesTarget(&arrayTypes);
429 reader.SetDerivedTypesTarget(&derivedTypes);
430 reader.SetClassTemplateSpecializationTarget(&classTemplateSpecializations);
431 reader.SetTypeAndConceptRequestTarget(&typeAndConceptRequests);
432 reader.SetFunctionRequestTarget(&functionRequests);
433 reader.SetConversionsTarget(&conversions);
434 reader.GetBinaryReader().Skip(module->SymbolTablePos());
435 reader.SetRootModule(rootModule);
436 module->GetSymbolTable().Read(reader);
437 for (Module* referencedModule : module->ReferencedModules())
438 {
439 module->GetSymbolTable().Import(referencedModule->GetSymbolTable());
440 }
441 module->GetSymbolTable().FinishRead(arrayTypes, derivedTypes, classTemplateSpecializations, typeAndConceptRequests, functionRequests, conversions);
442 module->SetImmutable();
443 #ifdef MODULE_CHECKING
444
445 #endif
446 if (rootModule == module) continue;
447 rootModule->GetSymbolTable().Import(module->GetSymbolTable());
448 }
449 else
450 {
451 #ifdef MODULE_READING_DEBUG
452
453 #endif
454 rootModule->GetSymbolTable().Import(module->GetSymbolTable());
455 }
456 }
457 #ifdef MODULE_READING_DEBUG
458
459
460 #endif
461 }
462
463 void Import(sngcm::ast::Target target, Module* rootModule, Module* module, const std::std::vector<std::string>&references, std::std::unordered_set<std::string>&importSet, std::std::vector<Module*>&modules,
464 std::std::unordered_map<std::string, ModuleDependency*>&moduleDependencyMap, std::std::unordered_map<std::string, Module*>&readMap, bool&first)
465 {
466 #ifdef MODULE_READING_DEBUG
467
468
469 #endif
470 for (const std::string& reference : references)
471 {
472 if (importSet.find(reference) == importSet.cend())
473 {
474 importSet.insert(reference);
475 #ifdef MODULE_READING_DEBUG
476
477 #endif
478 std::string config = GetConfig();
479 boost::filesystem::path mfn = boost::filesystem::path(reference).filename();
480 boost::filesystem::path mfp;
481 std::string searchedDirectories;
482 if (!rootModule->IsSystemModule())
483 {
484 sngcm::ast::BackEnd backend = sngcm::ast::BackEnd::llvm;
485 if (GetBackEnd() == cmajor::symbols::BackEnd::cmsx)
486 {
487 backend = sngcm::ast::BackEnd::cmsx;
488 }
489 else if (GetBackEnd() == cmajor::symbols::BackEnd::cmcpp)
490 {
491 backend = sngcm::ast::BackEnd::cppcm;
492 }
493 SystemDirKind systemDirKind = SystemDirKind::regular;
494 if (GetGlobalFlag(GlobalFlags::repository))
495 {
496 systemDirKind = SystemDirKind::repository;
497 }
498 mfp = CmajorSystemLibDir(config, backend, GetToolChain(), systemDirKind);
499 searchedDirectories.append("\n").append(mfp.generic_string());
500 mfp /= mfn;
501 if (!boost::filesystem::exists(mfp))
502 {
503 mfp = reference;
504 if (!boost::filesystem::exists(mfp))
505 {
506 boost::filesystem::path mrd = mfp;
507 mrd.remove_filename();
508 searchedDirectories.append("\n").append(mrd.generic_string());
509 throw std::runtime_error("Could not find module reference '" + mfn.generic_string() + "'.\nDirectories searched:\n" + searchedDirectories);
510 }
511 }
512 }
513 else
514 {
515 mfp = reference;
516 if (!boost::filesystem::exists(mfp))
517 {
518 boost::filesystem::path mrd = mfp;
519 mrd.remove_filename();
520 searchedDirectories.append("\n").append(mrd.generic_string());
521 throw std::runtime_error("Could not find module reference '" + mfn.generic_string() + "'.\nDirectories searched:\n" + searchedDirectories);
522 }
523 }
524 std::string moduleFilePath = GetFullPath(mfp.generic_string());
525 if (readMap.find(moduleFilePath) == readMap.cend())
526 {
527 Module* referencedModule = GetModuleFromModuleCache(moduleFilePath);
528 if (referencedModule->GetFlag(ModuleFlags::readFromModuleFile))
529 {
530 referencedModule->ResetFlag(ModuleFlags::readFromModuleFile);
531 referencedModule = ResetCachedModule(moduleFilePath);
532 }
533 rootModule->AllRefModules().push_back(referencedModule);
534 readMap[moduleFilePath] = referencedModule;
535 importSet.insert(moduleFilePath);
536 SymbolReader reader(moduleFilePath);
537 reader.GetAstReader().SetModuleMaps(rootModule->Id(), referencedModule->GetModuleNameTable(), rootModule->GetModuleIdMap());
538 referencedModule->ReadHeader(target, reader, rootModule, importSet, modules, moduleDependencyMap, readMap, first);
539 module->AddReferencedModule(referencedModule);
540 if (module != rootModule)
541 {
542 module->RegisterFileTable(&referencedModule->GetFileTable(), referencedModule);
543 }
544 Import(target, rootModule, module, referencedModule->ReferenceFilePaths(), importSet, modules, moduleDependencyMap, readMap, first);
545 }
546 }
547 else
548 {
549 std::string config = GetConfig();
550 boost::filesystem::path mfn = boost::filesystem::path(reference).filename();
551 boost::filesystem::path mfp;
552 std::string searchedDirectories;
553 if (!rootModule->IsSystemModule())
554 {
555 sngcm::ast::BackEnd backend = sngcm::ast::BackEnd::llvm;
556 if (GetBackEnd() == cmajor::symbols::BackEnd::cmsx)
557 {
558 backend = sngcm::ast::BackEnd::cmsx;
559 }
560 else if (GetBackEnd() == cmajor::symbols::BackEnd::cmcpp)
561 {
562 backend = sngcm::ast::BackEnd::cppcm;
563 }
564 SystemDirKind systemDirKind = SystemDirKind::regular;
565 if (GetGlobalFlag(GlobalFlags::repository))
566 {
567 systemDirKind = SystemDirKind::repository;
568 }
569 mfp = CmajorSystemLibDir(config, backend, GetToolChain(), systemDirKind);
570 mfp /= mfn;
571 if (!boost::filesystem::exists(mfp))
572 {
573 mfp = reference;
574 if (!boost::filesystem::exists(mfp))
575 {
576 boost::filesystem::path mrd = mfp;
577 mrd.remove_filename();
578 searchedDirectories.append("\n").append(mrd.generic_string());
579 throw std::runtime_error("Could not find module reference '" + mfn.generic_string() + "'.\nDirectories searched:\n" + searchedDirectories);
580 }
581 }
582 }
583 else
584 {
585 mfp = reference;
586 if (!boost::filesystem::exists(mfp))
587 {
588 boost::filesystem::path mrd = mfp;
589 mrd.remove_filename();
590 searchedDirectories.append("\n").append(mrd.generic_string());
591 throw std::runtime_error("Could not find module reference '" + mfn.generic_string() + "'.\nDirectories searched:\n" + searchedDirectories);
592 }
593 }
594 std::string moduleFilePath = GetFullPath(mfp.generic_string());
595 auto it = readMap.find(moduleFilePath);
596 if (it != readMap.cend())
597 {
598 Module* referencedModule = it->second;
599 if (rootModule->IsSystemModule() ||
600 ((target == sngcm::ast::Target::program || target == sngcm::ast::Target::library || target == sngcm::ast::Target::unitTest) &&
601 referencedModule->Name() != U"System" ||
602 (target == sngcm::ast::Target::winguiapp || target == sngcm::ast::Target::winapp || target == sngcm::ast::Target::winlib) &&
603 referencedModule->Name() != U"System.Windows"))
604 {
605 module->AddReferencedModule(referencedModule);
606 if (module != rootModule)
607 {
608 module->RegisterFileTable(&referencedModule->GetFileTable(), referencedModule);
609 }
610 }
611 #ifdef MODULE_READING_DEBUG
612
613 #endif
614 }
615 else
616 {
617 throw std::runtime_error("module file path '" + moduleFilePath + "' not found from module read map for module '" + ToUtf8(rootModule->Name()) + "'");
618 }
619 }
620 }
621 #ifdef MODULE_READING_DEBUG
622
623
624 #endif
625 }
626
627 void ImportModulesWithReferences(sngcm::ast::Target target,
628 Module* rootModule, Module* module, const std::std::vector<std::string>&references, std::std::unordered_set<std::string>&importSet, std::std::vector<Module*>&modules,
629 std::std::unordered_map<std::string, ModuleDependency*>&moduleDependencyMap, std::std::unordered_map<std::string, Module*>&readMap, bool&first)
630 {
631 #ifdef MODULE_READING_DEBUG
632
633
634 #endif
635 std::vector<std::string> allReferences = references;
636 if (!rootModule->IsSystemModule() && !GetGlobalFlag(GlobalFlags::profile))
637 {
638 sngcm::ast::BackEnd backend = sngcm::ast::BackEnd::llvm;
639 if (GetBackEnd() == cmajor::symbols::BackEnd::cmsx)
640 {
641 backend = sngcm::ast::BackEnd::cmsx;
642 }
643 else if (GetBackEnd() == cmajor::symbols::BackEnd::cmcpp)
644 {
645 backend = sngcm::ast::BackEnd::cppcm;
646 }
647 if (first)
648 {
649 first = false;
650 if (target == sngcm::ast::Target::winguiapp || target == sngcm::ast::Target::winapp || target == sngcm::ast::Target::winlib)
651 {
652 SystemDirKind systemDirKind = SystemDirKind::regular;
653 if (GetGlobalFlag(GlobalFlags::repository))
654 {
655 systemDirKind = SystemDirKind::repository;
656 }
657 allReferences.push_back(CmajorSystemWindowsModuleFilePath(GetConfig(), GetToolChain(), systemDirKind));
658 }
659 else
660 {
661 SystemDirKind systemDirKind = SystemDirKind::regular;
662 if (GetGlobalFlag(GlobalFlags::repository))
663 {
664 systemDirKind = SystemDirKind::repository;
665 }
666 allReferences.push_back(CmajorSystemModuleFilePath(GetConfig(), backend, GetToolChain(), systemDirKind));
667 }
668 }
669 }
670 Import(target, rootModule, module, allReferences, importSet, modules, moduleDependencyMap, readMap, first);
671 #ifdef MODULE_READING_DEBUG
672
673
674 #endif
675 }
676
677 void ImportModules(sngcm::ast::Target target, Module* rootModule, Module* module, std::std::unordered_set<std::string>&importSet, std::std::vector<Module*>&modules,
678 std::std::unordered_map<std::string, ModuleDependency*>&dependencyMap, std::std::unordered_map<std::string, Module*>&readMap, bool&first)
679 {
680 #ifdef MODULE_READING_DEBUG
681
682
683 #endif
684 ImportModulesWithReferences(target, rootModule, module, module->ReferenceFilePaths(), importSet, modules, dependencyMap, readMap, first);
685 #ifdef MODULE_READING_DEBUG
686
687
688 #endif
689 }
690
691 Module::Module() :
692 format(currentModuleFormat), flags(ModuleFlags::none), name(), id(boost::uuids::random_generator()()),
693 originalFilePath(), filePathReadFrom(), referenceFilePaths(), moduleDependency(this), symbolTablePos(0),
694 symbolTable(nullptr), directoryPath(), objectFileDirectoryPath(), libraryFilePaths(), moduleIdMap(), logStreamId(0), headerRead(false), systemCoreModule(nullptr), debugLogIndent(0), index(-1),
695 buildStartMs(0), buildStopMs(0), preparing(false), backend(sngcm::ast::BackEnd::llvm), config(sngcm::ast::Config::debug), functionIndex(this)
696 {
697 }
698
699 Module::Module(const std::string& filePath) : Module(filePath, false)
700 {
701 }
702
703 Module::Module(const std::string& filePath, bool readRoot) :
704 format(currentModuleFormat), flags(ModuleFlags::none), name(), id(boost::uuids::random_generator()()),
705 originalFilePath(), filePathReadFrom(), referenceFilePaths(), moduleDependency(this), symbolTablePos(0),
706 symbolTable(new SymbolTable(this)), directoryPath(), objectFileDirectoryPath(), libraryFilePaths(), moduleIdMap(), logStreamId(0), headerRead(false), systemCoreModule(nullptr), debugLogIndent(0),
707 index(-1), buildStartMs(0), buildStopMs(0), preparing(false), backend(sngcm::ast::BackEnd::llvm), config(sngcm::ast::Config::debug), functionIndex(this)
708 {
709 SymbolReader reader(filePath);
710 ModuleTag expectedTag;
711 ModuleTag tag;
712 tag.Read(reader);
713 for (int i = 0; i < 3; ++i)
714 {
715 if (tag.bytes[i] != expectedTag.bytes[i])
716 {
717 throw std::runtime_error("Invalid Cmajor module tag read from file '" + reader.GetBinaryReader().FileName() + "', please rebuild module from sources");
718 }
719 }
720 if (tag.bytes[3] != expectedTag.bytes[3])
721 {
722 throw std::runtime_error("Cmajor module format version mismatch reading from file '" + reader.GetBinaryReader().FileName() +
723 "': format " + std::string(1, expectedTag.bytes[3]) + " expected, format " + std::string(1, tag.bytes[3]) + " read, please rebuild module from sources");
724 }
725 flags = ModuleFlags(reader.GetBinaryReader().ReadByte());
726 name = reader.GetBinaryReader().ReadUtf32String();
727 reader.GetBinaryReader().ReadUuid(id);
728 MapModule(this);
729 backend = static_cast<sngcm::ast::BackEnd>(reader.GetBinaryReader().ReadSByte());
730 config = static_cast<sngcm::ast::Config>(reader.GetBinaryReader().ReadSByte());
731 std::unordered_set<std::string> importSet;
732 Module* rootModule = this;
733 if (!HasRootModuleForCurrentThread())
734 {
735 rootModule->SetRootModule();
736 SetRootModuleForCurrentThread(rootModule);
737 }
738 std::vector<Module*> modules;
739 std::unordered_map<std::string, ModuleDependency*> moduleDependencyMap;
740 std::unordered_map<std::string, Module*> readMap;
741 if (SystemModuleSet::Instance().IsSystemModule(name)) SetSystemModule();
742 SymbolReader reader2(filePath);
743 reader2.GetAstReader().SetModuleMaps(rootModule->Id(), this->GetModuleNameTable(), rootModule->GetModuleIdMap());
744 bool first = true;
745 ReadHeader(sngcm::ast::Target::library, reader2, rootModule, importSet, modules, moduleDependencyMap, readMap, first);
746 moduleDependencyMap[originalFilePath] = &moduleDependency;
747 std::unordered_map<Module*, ModuleDependency*> dependencyMap;
748 for (const auto& p : moduleDependencyMap)
749 {
750 dependencyMap[p.second->GetModule()] = p.second;
751 }
752 std::vector<Module*> finishReadOrder = CreateFinishReadOrder(modules, dependencyMap, rootModule);
753 if (!fileTable.IsEmpty())
754 {
755 #ifdef _WIN32
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778 #else
779 if (GetBackEnd() == BackEnd::cmcpp)
780 {
781 const Tool& libraryManagerTool = GetLibraryManagerTool(GetPlatform(), GetToolChain());
782 const Configuration& configuration = GetToolConfiguration(libraryManagerTool, GetConfig());
783 libraryFilePath = GetFullPath(
784 boost::filesystem::path(Path::Combine(Path::Combine(Path::GetDirectoryName(originalFilePath), configuration.outputDirectory), Path::GetFileName(originalFilePath))).replace_extension(
785 libraryManagerTool.outputFileExtension).generic_string());
786 if (IsSystemModule() && GetToolChain() == "vs")
787 {
788 libraryFilePath = GetFullPath(boost::filesystem::path(Path::Combine(Path::Combine(Path::Combine(Path::Combine(Path::Combine(Path::Combine(Path::Combine(Path::Combine(CmajorRootDir(),
789 "system"), "platform"), "linux"), "cpp"), GetToolChain()),
790 GetConfig()), configuration.outputDirectory), Path::GetFileName(originalFilePath))).replace_extension(libraryManagerTool.outputFileExtension).generic_string());
791 }
792 }
793 else
794 {
795 libraryFilePath = GetFullPath(boost::filesystem::path(originalFilePath).replace_extension(".a").generic_string());
796 }
797 #endif
798 }
799 for (Module* module : finishReadOrder)
800 {
801 if (!module->LibraryFilePath().empty() && !module->fileTable.IsEmpty())
802 {
803 libraryFilePaths.push_back(module->LibraryFilePath());
804 }
805 }
806 FinishReads(rootModule, finishReadOrder, true, readRoot);
807 MakeFilePathFileIndexMap();
808 }
809
810 Module::Module(const std::u32string& name_, const std::string& filePath_, sngcm::ast::Target target) :
811 format(currentModuleFormat), flags(ModuleFlags::none), name(name_), id(boost::uuids::random_generator()()),
812 originalFilePath(filePath_), filePathReadFrom(), referenceFilePaths(), moduleDependency(this), symbolTablePos(0),
813 symbolTable(new SymbolTable(this)), directoryPath(), objectFileDirectoryPath(), libraryFilePaths(), moduleIdMap(), logStreamId(0), headerRead(false), systemCoreModule(nullptr), debugLogIndent(0),
814 index(-1), buildStartMs(0), buildStopMs(0), preparing(false), backend(sngcm::ast::BackEnd::llvm), config(sngcm::ast::Config::debug), functionIndex(this)
815 {
816 if (SystemModuleSet::Instance().IsSystemModule(name))
817 {
818 SetSystemModule();
819 }
820 if (name == U"System.Core")
821 {
822 SetCore();
823 }
824 }
825
826 Module::~Module()
827 {
828 }
829
830 void Module::SetResourceFilePath(const std::string& resourceFilePath_)
831 {
832 resourceFilePath = resourceFilePath_;
833 }
834
835 void Module::PrepareForCompilation(const std::std::vector<std::string>&references, sngcm::ast::Targettarget)
836 {
837 MapModule(this);
838 switch (GetBackEnd())
839 {
840 case BackEnd::llvm:
841 {
842 backend = sngcm::ast::BackEnd::llvm;
843 break;
844 }
845 case BackEnd::cmsx:
846 {
847 backend = sngcm::ast::BackEnd::cmsx;
848 break;
849 }
850 case BackEnd::cmcpp:
851 {
852 backend = sngcm::ast::BackEnd::cppcm;
853 break;
854 }
855 }
856 std::string configStr = GetConfig();
857 if (configStr == "debug")
858 {
859 config = sngcm::ast::Config::debug;
860 }
861 else if (configStr == "release")
862 {
863 config = sngcm::ast::Config::release;
864 }
865 else if (configStr == "profile")
866 {
867 config = sngcm::ast::Config::profile;
868 }
869 else if (configStr == "trace")
870 {
871 config = sngcm::ast::Config::trace;
872 }
873 boost::filesystem::path mfd = originalFilePath;
874 mfd.remove_filename();
875 boost::filesystem::create_directories(mfd);
876 SetDirectoryPath(GetFullPath(mfd.generic_string()));
877 SetObjectFileDirectoryPath(GetFullPath(mfd.generic_string()));
878 if (GetBackEnd() == BackEnd::cmcpp)
879 {
880 const Tool& compilerTool = GetCompilerTool(GetPlatform(), GetToolChain());
881 const Configuration& configuration = GetToolConfiguration(compilerTool, GetConfig());
882 SetObjectFileDirectoryPath(GetFullPath((mfd / configuration.outputDirectory).generic_string()));
883 }
884 if (name == U"System.Core")
885 {
886 InitCoreSymbolTable(*symbolTable);
887 }
888 std::unordered_set<std::string> importSet;
889 Module* rootModule = this;
890 rootModule->RegisterFileTable(&fileTable, rootModule);
891 std::unordered_map<std::string, ModuleDependency*> moduleDependencyMap;
892 std::unordered_map<std::string, Module*> readMap;
893 std::vector<Module*> modules;
894 bool first = true;
895 ImportModulesWithReferences(target, rootModule, rootModule, references, importSet, modules, moduleDependencyMap, readMap, first);
896 modules.push_back(this);
897 moduleDependencyMap[originalFilePath] = &moduleDependency;
898 std::unordered_map<Module*, ModuleDependency*> dependencyMap;
899 for (const auto& p : moduleDependencyMap)
900 {
901 dependencyMap[p.second->GetModule()] = p.second;
902 }
903 std::vector<Module*> finishReadOrder = CreateFinishReadOrder(modules, dependencyMap, rootModule);
904 if (!this->fileTable.IsEmpty())
905 {
906 #ifdef _WIN32
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929 #else
930 if (GetBackEnd() == BackEnd::cmcpp)
931 {
932 const Tool& libraryManagerTool = GetLibraryManagerTool(GetPlatform(), GetToolChain());
933 const Configuration& configuration = GetToolConfiguration(libraryManagerTool, GetConfig());
934 libraryFilePath = GetFullPath(
935 boost::filesystem::path(Path::Combine(Path::Combine(Path::GetDirectoryName(originalFilePath), configuration.outputDirectory), Path::GetFileName(originalFilePath))).replace_extension(
936 libraryManagerTool.outputFileExtension).generic_string());
937 if (IsSystemModule() && GetToolChain() == "vs")
938 {
939 libraryFilePath = GetFullPath(boost::filesystem::path(Path::Combine(Path::Combine(Path::Combine(Path::Combine(Path::Combine(Path::Combine(Path::Combine(Path::Combine(CmajorRootDir(),
940 "system"), "platform"), "linux"), "cpp"), GetToolChain()),
941 GetConfig()), configuration.outputDirectory), Path::GetFileName(originalFilePath))).replace_extension(libraryManagerTool.outputFileExtension).generic_string());
942 }
943 }
944 else
945 {
946 libraryFilePath = GetFullPath(boost::filesystem::path(originalFilePath).replace_extension(".a").generic_string());
947 }
948 #endif
949 }
950 for (Module* module : finishReadOrder)
951 {
952 if (!module->LibraryFilePath().empty())
953 {
954 if (GetGlobalFlag(GlobalFlags::disableSystem))
955 {
956 if (module->IsSystemModule())
957 {
958 continue;
959 }
960 }
961 libraryFilePaths.push_back(module->LibraryFilePath());
962 }
963 }
964 FinishReads(rootModule, finishReadOrder, false, false);
965 MakeFilePathFileIndexMap();
966 }
967
968 void Module::CreateSymbolTable()
969 {
970 symbolTable.reset(new SymbolTable(this));
971 }
972
973 void Module::RegisterFileTable(FileTable* fileTable, Module* module)
974 {
975 if (std::find(fileTables.begin(), fileTables.end(), fileTable) != fileTables.end()) return;
976 int16_t moduleId = fileTables.size();
977 fileTables.push_back(fileTable);
978 std::string moduleName = ToUtf8(module->Name());
979 moduleIdMap[moduleName] = moduleId;
980 moduleNameTable[moduleId] = moduleName;
981 }
982
983 void Module::MakeFilePathFileIndexMap()
984 {
985 if (GetFlag(ModuleFlags::fileIndexFilePathMapBuilt)) return;
986 SetFlag(ModuleFlags::fileIndexFilePathMapBuilt);
987 int16_t n = fileTable.NumFilePaths();
988 for (int16_t i = 0; i < n; ++i)
989 {
990 int32_t fileIndex = i;
991 filePathFileIndexMap[fileTable.GetFilePath(i)] = fileIndex;
992 }
993 }
994
995 void Module::SetLexers(std::std::vector<std::std::unique_ptr<CmajorLexer>>&&lexers_)
996 {
997 lexers = std::move(lexers_);
998 for (const auto& lexer : lexers)
999 {
1000 lexerVec.push_back(lexer.get());
1001 }
1002 }
1003
1004 std::std::vector<soulng::lexer::Lexer*>*Module::GetLexers()
1005 {
1006 return &lexerVec;
1007 }
1008
1009 std::string Module::GetFilePath(int32_t fileIndex) const
1010 {
1011 if (fileIndex == -1)
1012 {
1013 return std::string();
1014 }
1015 return fileTable.GetFilePath(fileIndex);
1016 }
1017
1018 std::u32string Module::GetErrorLines(const Span& span) const
1019 {
1020 if (span.fileIndex >= 0)
1021 {
1022 if (GetFlag(ModuleFlags::compiling))
1023 {
1024 if (span.fileIndex < lexers.size())
1025 {
1026 return lexers[span.fileIndex]->ErrorLines(span);
1027 }
1028 }
1029 else
1030 {
1031 std::string filePath = GetFilePath(span.fileIndex);
1032 if (filePath.empty())
1033 {
1034 return std::u32string();
1035 }
1036 std::u32string content = ToUtf32(soulng::util::ReadFile(filePath));
1037 return soulng::lexer::GetErrorLines(content.c_str(), content.c_str() + content.length(), span);
1038 }
1039 }
1040 return std::u32string();
1041 }
1042
1043 void Module::GetColumns(const Span& span, int32_t& startCol, int32_t& endCol) const
1044 {
1045 if (span.fileIndex >= 0)
1046 {
1047 if (GetFlag(ModuleFlags::compiling))
1048 {
1049 if (span.fileIndex < lexers.size())
1050 {
1051 return lexers[span.fileIndex]->GetColumns(span, startCol, endCol);
1052 }
1053 }
1054 else
1055 {
1056 std::string filePath = GetFilePath(span.fileIndex);
1057 if (filePath.empty())
1058 {
1059 return;
1060 }
1061 std::u32string content = ToUtf32(soulng::util::ReadFile(filePath));
1062 return soulng::lexer::GetColumns(content.c_str(), content.c_str() + content.length(), span, startCol, endCol);
1063 }
1064 }
1065 }
1066
1067 void Module::Write(SymbolWriter& writer)
1068 {
1069 ModuleTag tag;
1070 tag.Write(writer);
1071 writer.GetBinaryWriter().Write(static_cast<uint8_t>(flags & ~(ModuleFlags::root | ModuleFlags::immutable | ModuleFlags::compiling | ModuleFlags::fileIndexFilePathMapBuilt |
1072 ModuleFlags::readFromModuleFile)));
1073 writer.GetBinaryWriter().Write(name);
1074 writer.GetBinaryWriter().Write(id);
1075 writer.GetBinaryWriter().Write(static_cast<int8_t>(backend));
1076 writer.GetBinaryWriter().Write(static_cast<int8_t>(config));
1077 std::string cmajorRootRelativeFilePath = MakeCmajorRootRelativeFilePath(originalFilePath);
1078 writer.GetBinaryWriter().Write(cmajorRootRelativeFilePath);
1079 uint32_t nr = referencedModules.size();
1080 writer.GetBinaryWriter().WriteULEB128UInt(nr);
1081 for (uint32_t i = 0; i < nr; ++i)
1082 {
1083 Module* referencedModule = referencedModules[i];
1084 std::string cmajorRootRelativeReferenceFilePath = MakeCmajorRootRelativeFilePath(referencedModule->OriginalFilePath());
1085 writer.GetBinaryWriter().Write(cmajorRootRelativeReferenceFilePath);
1086 }
1087 fileTable.Write(writer.GetBinaryWriter(), IsSystemModule());
1088 int16_t nmnt = moduleNameTable.size();
1089 writer.GetBinaryWriter().Write(nmnt);
1090 for (const auto& p : moduleNameTable)
1091 {
1092 writer.GetBinaryWriter().Write(p.first);
1093 writer.GetBinaryWriter().Write(p.second);
1094 }
1095 uint32_t n = compileUnitIds.size();
1096 writer.GetBinaryWriter().WriteULEB128UInt(n);
1097 for (const std::string& compileUnitId : compileUnitIds)
1098 {
1099 writer.GetBinaryWriter().Write(compileUnitId);
1100 }
1101 #ifdef _WIN32
1102
1103 #ifdef RESOURCE_DEBUG
1104
1105
1106
1107
1108
1109
1110
1111 #endif
1112 #endif
1113 uint32_t efn = exportedFunctions.size();
1114 writer.GetBinaryWriter().WriteULEB128UInt(efn);
1115 for (uint32_t i = 0; i < efn; ++i)
1116 {
1117 writer.GetBinaryWriter().Write(exportedFunctions[i]);
1118 }
1119 uint32_t edn = exportedData.size();
1120 writer.GetBinaryWriter().WriteULEB128UInt(edn);
1121 for (uint32_t i = 0; i < edn; ++i)
1122 {
1123 writer.GetBinaryWriter().Write(exportedData[i]);
1124 }
1125 symbolTable->Write(writer);
1126 }
1127
1128 void Module::AddReferencedModule(Module* referencedModule)
1129 {
1130 moduleDependency.AddReferencedModule(referencedModule);
1131 if (std::find(referencedModules.cbegin(), referencedModules.cend(), referencedModule) == referencedModules.cend())
1132 {
1133 referencedModules.push_back(referencedModule);
1134 }
1135 }
1136
1137 void Module::ReadHeader(sngcm::ast::Target target, SymbolReader& reader, Module* rootModule, std::std::unordered_set<std::string>&importSet, std::std::vector<Module*>&modules,
1138 std::std::unordered_map<std::string, ModuleDependency*>&dependencyMap, std::std::unordered_map<std::string, Module*>&readMap, bool&first)
1139 {
1140 if (headerRead)
1141 {
1142 #ifdef MODULE_READING_DEBUG
1143
1144
1145 #endif
1146 rootModule->RegisterFileTable(&fileTable, this);
1147 if (this != rootModule)
1148 {
1149 RegisterFileTable(&fileTable, this);
1150 }
1151 for (const std::string& compileUnitId : compileUnitIds)
1152 {
1153 rootModule->allCompileUnitIds.insert(compileUnitId);
1154 }
1155 #ifdef _WIN32
1156
1157 #ifdef RESOURCE_DEBUG
1158
1159 #endif
1160
1161
1162
1163 #ifdef RESOURCE_DEBUG
1164
1165 #endif
1166
1167
1168
1169
1170
1171 #endif
1172 if (dependencyMap.find(originalFilePath) == dependencyMap.cend())
1173 {
1174 modules.push_back(this);
1175 dependencyMap[originalFilePath] = &moduleDependency;
1176 }
1177 for (const std::string& exportedFunction : exportedFunctions)
1178 {
1179 rootModule->allExportedFunctions.push_back(exportedFunction);
1180 for (const std::string& data : exportedData)
1181 {
1182 rootModule->allExportedData.push_back(data);
1183 }
1184 }
1185 ImportModules(target, rootModule, this, importSet, modules, dependencyMap, readMap, first);
1186 #ifdef MODULE_READING_DEBUG
1187
1188
1189 #endif
1190 return;
1191 }
1192 headerRead = true;
1193 ModuleTag expectedTag;
1194 ModuleTag tag;
1195 tag.Read(reader);
1196 for (int i = 0; i < 3; ++i)
1197 {
1198 if (tag.bytes[i] != expectedTag.bytes[i])
1199 {
1200 throw std::runtime_error("Invalid Cmajor module tag read from file '" + reader.GetBinaryReader().FileName() + "', please rebuild module from sources");
1201 }
1202 }
1203 if (tag.bytes[3] != expectedTag.bytes[3])
1204 {
1205 throw std::runtime_error("Cmajor module format version mismatch reading from file '" + reader.GetBinaryReader().FileName() +
1206 "': format " + std::string(1, expectedTag.bytes[3]) + " expected, format " + std::string(1, tag.bytes[3]) + " read, please rebuild module from sources");
1207 }
1208 flags = ModuleFlags(reader.GetBinaryReader().ReadByte());
1209 name = reader.GetBinaryReader().ReadUtf32String();
1210 bool unitTesting = GetGlobalFlag(GlobalFlags::unitTest);
1211 if (unitTesting&&( flags & ModuleFlags::programModule) != ModuleFlags::none)
1212 {
1213 throw std::runtime_error("cmunit can test only library modules, module '" + ToUtf8(name) + "' is a program module");
1214 }
1215 reader.GetBinaryReader().ReadUuid(id);
1216 MapModule(this);
1217 backend = static_cast<sngcm::ast::BackEnd>(reader.GetBinaryReader().ReadSByte());
1218 config = static_cast<sngcm::ast::Config>(reader.GetBinaryReader().ReadSByte());
1219 rootModule->RegisterFileTable(&fileTable, this);
1220 if (this != rootModule)
1221 {
1222 RegisterFileTable(&fileTable, this);
1223 }
1224 #ifdef MODULE_READING_DEBUG
1225
1226
1227 #endif
1228 std::string cmajorRootRelativeFilePath = reader.GetBinaryReader().ReadUtf8String();
1229 originalFilePath = ExpandCmajorRootRelativeFilePath(cmajorRootRelativeFilePath);
1230 if (dependencyMap.find(originalFilePath) == dependencyMap.cend())
1231 {
1232 modules.push_back(this);
1233 dependencyMap[originalFilePath] = &moduleDependency;
1234 }
1235 filePathReadFrom = GetFullPath(reader.GetBinaryReader().FileName());
1236 referenceFilePaths.clear();
1237 uint32_t nr = reader.GetBinaryReader().ReadULEB128UInt();
1238 for (uint32_t i = 0; i < nr; ++i)
1239 {
1240 std::string cmajorRootRelativeReferenceFilePath = reader.GetBinaryReader().ReadUtf8String();
1241 std::string referenceFilePath = ExpandCmajorRootRelativeFilePath(cmajorRootRelativeReferenceFilePath);
1242 referenceFilePaths.push_back(referenceFilePath);
1243 }
1244 fileTable.Read(reader.GetBinaryReader(), IsSystemModule());
1245 if (GetGlobalFlag(GlobalFlags::updateSourceFileModuleMap))
1246 {
1247 UpdateSourceFileModuleMap();
1248 }
1249 if (!fileTable.IsEmpty())
1250 {
1251 #ifdef _WIN32
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274 #else
1275 if (GetBackEnd() == BackEnd::cmcpp)
1276 {
1277 const Tool& libraryManagerTool = GetLibraryManagerTool(GetPlatform(), GetToolChain());
1278 const Configuration& configuration = GetToolConfiguration(libraryManagerTool, GetConfig());
1279 libraryFilePath = GetFullPath(
1280 boost::filesystem::path(Path::Combine(Path::Combine(Path::GetDirectoryName(filePathReadFrom), configuration.outputDirectory), Path::GetFileName(filePathReadFrom))).replace_extension(
1281 libraryManagerTool.outputFileExtension).generic_string());
1282 if (IsSystemModule() && GetToolChain() == "vs")
1283 {
1284 libraryFilePath = GetFullPath(boost::filesystem::path(Path::Combine(Path::Combine(Path::Combine(Path::Combine(Path::Combine(Path::Combine(Path::Combine(Path::Combine(CmajorRootDir(),
1285 "system"), "platform"), "linux"), "cpp"), GetToolChain()),
1286 GetConfig()), configuration.outputDirectory), Path::GetFileName(filePathReadFrom))).replace_extension(libraryManagerTool.outputFileExtension).generic_string());
1287 }
1288 }
1289 else
1290 {
1291 libraryFilePath = GetFullPath(boost::filesystem::path(filePathReadFrom).replace_extension(".a").generic_string());
1292 }
1293 #endif
1294 }
1295 int16_t nmnt = reader.GetBinaryReader().ReadShort();
1296 for (int16_t i = 0; i < nmnt; ++i)
1297 {
1298 int16_t moduleId = reader.GetBinaryReader().ReadShort();
1299 std::string moduleName = reader.GetBinaryReader().ReadUtf8String();
1300 moduleNameTable[moduleId] = moduleName;
1301 }
1302 uint32_t numCompileUnitIds = reader.GetBinaryReader().ReadULEB128UInt();
1303 for (uint32_t i = 0; i < numCompileUnitIds; ++i)
1304 {
1305 std::string compileUnitId = reader.GetBinaryReader().ReadUtf8String();
1306 compileUnitIds.insert(compileUnitId);
1307 }
1308 for (const std::string& compileUnitId : compileUnitIds)
1309 {
1310 rootModule->allCompileUnitIds.insert(compileUnitId);
1311 }
1312 #ifdef _WIN32
1313
1314
1315 #ifdef RESOURCE_DEBUG
1316
1317 #endif
1318
1319
1320
1321 #ifdef RESOURCE_DEBUG
1322
1323 #endif
1324
1325
1326
1327
1328
1329 #endif
1330 exportedFunctions.clear();
1331 uint32_t efn = reader.GetBinaryReader().ReadULEB128UInt();
1332 for (uint32_t i = 0; i < efn; ++i)
1333 {
1334 exportedFunctions.push_back(reader.GetBinaryReader().ReadUtf8String());
1335 }
1336 for (const std::string& exportedFunction : exportedFunctions)
1337 {
1338 rootModule->allExportedFunctions.push_back(exportedFunction);
1339 }
1340 exportedData.clear();
1341 uint32_t edn = reader.GetBinaryReader().ReadULEB128UInt();
1342 for (uint32_t i = 0; i < edn; ++i)
1343 {
1344 exportedData.push_back(reader.GetBinaryReader().ReadUtf8String());
1345 }
1346 for (const std::string& data : exportedData)
1347 {
1348 rootModule->allExportedData.push_back(data);
1349 }
1350 CheckUpToDate();
1351 symbolTablePos = reader.GetBinaryReader().Pos();
1352 ImportModules(target, rootModule, this, importSet, modules, dependencyMap, readMap, first);
1353 #ifdef MODULE_READING_DEBUG
1354
1355
1356 #endif
1357 MakeFilePathFileIndexMap();
1358 }
1359
1360 void Module::SetDirectoryPath(const std::string& directoryPath_)
1361 {
1362 directoryPath = directoryPath_;
1363 }
1364
1365 void Module::SetObjectFileDirectoryPath(const std::string& objectFileDirectoryPath_)
1366 {
1367 objectFileDirectoryPath = objectFileDirectoryPath_;
1368 }
1369
1370 void Module::AddExportedFunction(const std::string& exportedFunction)
1371 {
1372 exportedFunctions.push_back(exportedFunction);
1373 }
1374
1375 void Module::AddExportedData(const std::string& data)
1376 {
1377 std::lock_guard<std::recursive_mutex> lck(lock);
1378 exportedData.push_back(data);
1379 }
1380
1381 void Module::Dump()
1382 {
1383 CodeFormatter formatter(std::cout);
1384 formatter.WriteLine("========================");
1385 formatter.WriteLine("MODULE " + ToUtf8(name));
1386 formatter.WriteLine("========================");
1387 formatter.WriteLine();
1388 formatter.WriteLine("format: " + std::string(1, format));
1389 formatter.WriteLine("flags: " + ModuleFlagStr(flags));
1390 formatter.WriteLine("original file path: " + originalFilePath);
1391 formatter.WriteLine("file path read from: " + filePathReadFrom);
1392 if (!libraryFilePath.empty())
1393 {
1394 formatter.WriteLine("library file path: " + libraryFilePath);
1395 }
1396 int n = referenceFilePaths.size();
1397 if (n > 0)
1398 {
1399 formatter.WriteLine("reference file paths:");
1400 formatter.IncIndent();
1401 for (int i = 0; i < n; ++i)
1402 {
1403 formatter.WriteLine(referenceFilePaths[i]);
1404 }
1405 formatter.DecIndent();
1406 }
1407 fileTable.Dump(formatter);
1408 #ifdef _WIN32
1409
1410 #endif
1411 formatter.WriteLine("module dependencies:");
1412 formatter.IncIndent();
1413 formatter.WriteLine(ToUtf8(Name()));
1414 moduleDependency.Dump(formatter);
1415 formatter.DecIndent();
1416 SymbolCollector collector;
1417 symbolTable->GlobalNs().Accept(&collector);
1418 collector.SortByFullName();
1419 if (!collector.BasicTypes().empty())
1420 {
1421 formatter.WriteLine();
1422 formatter.WriteLine("BASIC TYPES");
1423 for (BasicTypeSymbol* basicType : collector.BasicTypes())
1424 {
1425 formatter.WriteLine();
1426 basicType->Dump(formatter);
1427 }
1428 }
1429 if (!collector.Classes().empty())
1430 {
1431 formatter.WriteLine();
1432 formatter.WriteLine("CLASSES");
1433 for (ClassTypeSymbol* class_ : collector.Classes())
1434 {
1435 formatter.WriteLine();
1436 class_->Dump(formatter);
1437 }
1438 }
1439 if (!collector.Interfaces().empty())
1440 {
1441 formatter.WriteLine();
1442 formatter.WriteLine("INTERFACES");
1443 for (InterfaceTypeSymbol* interface : collector.Interfaces())
1444 {
1445 formatter.WriteLine();
1446 interface->Dump(formatter);
1447 }
1448 }
1449 if (!collector.Functions().empty())
1450 {
1451 formatter.WriteLine();
1452 formatter.WriteLine("FUNCTIONS");
1453 for (FunctionSymbol* function : collector.Functions())
1454 {
1455 formatter.WriteLine();
1456 function->Dump(formatter);
1457 }
1458 }
1459 if (!collector.Typedefs().empty())
1460 {
1461 formatter.WriteLine();
1462 formatter.WriteLine("TYPEDEFS");
1463 for (TypedefSymbol* typedef_ : collector.Typedefs())
1464 {
1465 formatter.WriteLine();
1466 typedef_->Dump(formatter);
1467 }
1468 }
1469 if (!collector.Concepts().empty())
1470 {
1471 formatter.WriteLine();
1472 formatter.WriteLine("CONCEPTS");
1473 for (ConceptSymbol* concept_ : collector.Concepts())
1474 {
1475 formatter.WriteLine();
1476 concept_->Dump(formatter);
1477 }
1478 }
1479 if (!collector.Delegates().empty())
1480 {
1481 formatter.WriteLine();
1482 formatter.WriteLine("DELEGATES");
1483 for (DelegateTypeSymbol* delegate_ : collector.Delegates())
1484 {
1485 formatter.WriteLine();
1486 delegate_->Dump(formatter);
1487 }
1488 }
1489 if (!collector.ClassDelegates().empty())
1490 {
1491 formatter.WriteLine();
1492 formatter.WriteLine("CLASS DELEGATES");
1493 for (ClassDelegateTypeSymbol* classDelegate : collector.ClassDelegates())
1494 {
1495 formatter.WriteLine();
1496 classDelegate->Dump(formatter);
1497 }
1498 }
1499 if (!collector.Constants().empty())
1500 {
1501 formatter.WriteLine();
1502 formatter.WriteLine("CONSTANTS");
1503 for (ConstantSymbol* constant : collector.Constants())
1504 {
1505 formatter.WriteLine();
1506 constant->Dump(formatter);
1507 }
1508 }
1509 if (!collector.EnumeratedTypes().empty())
1510 {
1511 formatter.WriteLine();
1512 formatter.WriteLine("ENUMERATED TYPES");
1513 for (EnumTypeSymbol* enumeratedType : collector.EnumeratedTypes())
1514 {
1515 formatter.WriteLine();
1516 enumeratedType->Dump(formatter);
1517 }
1518 }
1519 }
1520
1521 void Module::CheckUpToDate()
1522 {
1523 if (fileTable.IsEmpty()) return;
1524 boost::filesystem::path libDirPath = boost::filesystem::path(originalFilePath).parent_path();
1525 int n = fileTable.NumFilePaths();
1526 for (int i = 0; i < n; ++i)
1527 {
1528 boost::filesystem::path sfp(fileTable.GetFilePath(i));
1529 if (boost::filesystem::exists(sfp))
1530 {
1531 boost::filesystem::path objectFilePath;
1532 #ifdef _WIN32
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548 #else
1549 objectFilePath = libDirPath / sfp.filename().replace_extension(".o");
1550 #endif
1551 if (boost::filesystem::exists(objectFilePath))
1552 {
1553 if (boost::filesystem::last_write_time(sfp) > boost::filesystem::last_write_time(objectFilePath))
1554 {
1555 Warning warning(name, "source file '" + GetFullPath(sfp.generic_string()) + "' is more recent than object file '" +
1556 GetFullPath(objectFilePath.generic_string()) + "'");
1557 bool found = false;
1558 for (const Warning& prev : warnings.Warnings())
1559 {
1560 if (prev.Message() == warning.Message())
1561 {
1562 found = true;
1563 break;
1564 }
1565 }
1566 if (!found)
1567 {
1568 warnings.AddWarning(warning);
1569 }
1570 }
1571 }
1572 }
1573 }
1574 }
1575
1576 void Module::SetCurrentProjectName(const std::u32string& currentProjectName_)
1577 {
1578 if (IsRootModule())
1579 {
1580 currentProjectName = currentProjectName_;
1581 }
1582 else
1583 {
1584 throw std::runtime_error("cannot set current project name for a nonroot module");
1585 }
1586 }
1587
1588 std::u32string Module::GetCurrentProjectName()
1589 {
1590 if (IsRootModule())
1591 {
1592 return currentProjectName;
1593 }
1594 else
1595 {
1596 throw std::runtime_error("cannot get current project name for a nonroot module");
1597 }
1598 }
1599
1600 void Module::SetCurrentToolName(const std::u32string& currentToolName_)
1601 {
1602 if (IsRootModule())
1603 {
1604 currentToolName = currentToolName_;
1605 }
1606 else
1607 {
1608 throw std::runtime_error("cannot set current tool name for a nonroot module");
1609 }
1610 }
1611
1612 std::u32string Module::GetCurrentToolName()
1613 {
1614 if (IsRootModule())
1615 {
1616 return currentToolName;
1617 }
1618 else
1619 {
1620 throw std::runtime_error("cannot get current tool name for a nonroot module");
1621 }
1622 }
1623
1624 CompileWarningCollection& Module::WarningCollection()
1625 {
1626 if (IsRootModule())
1627 {
1628 return warnings;
1629 }
1630 else
1631 {
1632 throw std::runtime_error("cannot get warnings for a nonroot module");
1633 }
1634 }
1635
1636 void Module::ClearDefines()
1637 {
1638 if (IsRootModule())
1639 {
1640 defines = GetCommandLineDefines();
1641 }
1642 else
1643 {
1644 throw std::runtime_error("cannot clear defines for a nonroot module");
1645 }
1646 }
1647
1648 void Module::DefineSymbol(const std::u32string& symbol)
1649 {
1650 if (IsRootModule())
1651 {
1652 defines.insert(symbol);
1653 }
1654 else
1655 {
1656 throw std::runtime_error("cannot define a symbol for a nonroot module");
1657 }
1658 }
1659
1660 bool Module::IsSymbolDefined(const std::u32string& symbol)
1661 {
1662 if (IsRootModule())
1663 {
1664 auto it = defines.find(symbol);
1665 if (it != defines.cend())
1666 {
1667 return true;
1668 }
1669 else
1670 {
1671 return false;
1672 }
1673 }
1674 else
1675 {
1676 throw std::runtime_error("cannot get defined symbol for a nonroot module");
1677 }
1678 }
1679
1680 Module* Module::GetSystemCoreModule()
1681 {
1682 if (IsCore())
1683 {
1684 return this;
1685 }
1686 if (!systemCoreModule)
1687 {
1688 for (Module* referencedModule : referencedModules)
1689 {
1690 Module* systemCore = referencedModule->GetSystemCoreModule();
1691 if (systemCore)
1692 {
1693 systemCoreModule = systemCore;
1694 break;
1695 }
1696 }
1697 }
1698 return systemCoreModule;
1699 }
1700
1701 void Module::Check()
1702 {
1703 symbolTable->Check();
1704 }
1705
1706 void Module::StartBuild()
1707 {
1708 buildStartMs = CurrentMs();
1709 }
1710
1711 void Module::StopBuild()
1712 {
1713 buildStopMs = CurrentMs();
1714 }
1715
1716 int Module::GetBuildTimeMs()
1717 {
1718 return static_cast<int>(buildStopMs - buildStartMs);
1719 }
1720
1721 void Module::AddCompileUnitId(const std::string& compileUnitId)
1722 {
1723 std::lock_guard<std::recursive_mutex> lck(lock);
1724 if (compileUnitId.empty())
1725 {
1726 throw std::runtime_error("module '" + ToUtf8(Name()) + "': compile unit id is empty");
1727 }
1728 compileUnitIds.insert(compileUnitId);
1729 allCompileUnitIds.insert(compileUnitId);
1730 }
1731
1732 void Module::WriteProjectDebugInfoFile(const std::string& projectDebufInfoFilePath)
1733 {
1734 BinaryWriter writer(projectDebufInfoFilePath);
1735 int32_t numCompileUnits = fileTable.NumFilePaths();
1736 cmajor::debug::WriteProjectTableHeader(writer, ToUtf8(name), Path::GetDirectoryName(originalFilePath), Id(), numCompileUnits, functionIndex.GetMainFunctionId());
1737 for (int32_t i = 0; i < numCompileUnits; ++i)
1738 {
1739 std::string compileUnitBaseName = Path::GetFileNameWithoutExtension(fileTable.GetFilePath(i));
1740 cmajor::debug::WriteProjectTableRecord(writer, compileUnitBaseName);
1741 }
1742 int32_t n = fileTable.NumFilePaths();
1743 cmajor::debug::WriteNumberOfFileIndexRecords(writer, n);
1744 for (int32_t i = 0; i < n; ++i)
1745 {
1746 int32_t fileIndex = i;
1747 std::string filePath = fileTable.GetFilePath(fileIndex);
1748 Assert(!filePath.empty(), "source file path is empty");
1749 cmajor::debug::WriteFileIndexRecord(writer, fileIndex, filePath);
1750 }
1751 functionIndex.Write(writer);
1752 typeIndex.Write(writer);
1753 }
1754
1755 void Module::WriteCmdbFile(const std::string& cmdbFilePath)
1756 {
1757 BinaryWriter cmdbWriter(cmdbFilePath);
1758 cmajor::debug::WriteCmdbFileTag(cmdbWriter);
1759 std::string mainProjectName = ToUtf8(name);
1760 cmajor::debug::WriteMainProjectName(cmdbWriter, mainProjectName);
1761 int32_t numProjects = 0;
1762 uint32_t numProjectsPos = cmdbWriter.Pos();
1763 cmajor::debug::WriteNumberOfProjects(cmdbWriter, numProjects);
1764 for (Module* referencedModule : referencedModules)
1765 {
1766 referencedModule->WriteDebugInfo(cmdbWriter, numProjects, this);
1767 }
1768 WriteDebugInfo(cmdbWriter, numProjects, this);
1769 uint32_t currentPos = cmdbWriter.Pos();
1770 cmdbWriter.Seek(numProjectsPos);
1771 cmajor::debug::WriteNumberOfProjects(cmdbWriter, numProjects);
1772 cmdbWriter.Seek(currentPos);
1773 }
1774
1775 void Module::WriteDebugInfo(BinaryWriter& cmdbWriter, int32_t& numProjects, Module* rootModule)
1776 {
1777 std::string pdiFilePath = Path::ChangeExtension(originalFilePath, ".pdi");
1778 BinaryReader pdiReader(pdiFilePath);
1779 std::string projectName;
1780 std::string projectDirectoryPath;
1781 boost::uuids::uuid moduleId;
1782 int32_t numCompileUnits;
1783 boost::uuids::uuid mainFunctionId;
1784 cmajor::debug::ReadProjectTableHeader(pdiReader, projectName, projectDirectoryPath, moduleId, numCompileUnits, mainFunctionId);
1785 cmajor::debug::WriteProjectTableHeader(cmdbWriter, projectName, projectDirectoryPath, moduleId, numCompileUnits, mainFunctionId);
1786 for (int32_t i = 0; i < numCompileUnits; ++i)
1787 {
1788 std::string compileUnitBaseName;
1789 cmajor::debug::ReadProjectTableRecord(pdiReader, compileUnitBaseName);
1790 cmajor::debug::WriteProjectTableRecord(cmdbWriter, compileUnitBaseName);
1791 std::string cudiFilePath = Path::Combine(projectDirectoryPath, compileUnitBaseName + ".cudi");
1792 BinaryReader cudiReader(cudiFilePath);
1793 int32_t numFunctionRecords;
1794 cmajor::debug::ReadNumberOfCompileUnitFunctionRecords(cudiReader, numFunctionRecords);
1795 cmajor::debug::WriteNumberOfCompileUnitFunctionRecords(cmdbWriter, numFunctionRecords);
1796 for (int32_t i = 0; i < numFunctionRecords; ++i)
1797 {
1798 int32_t fileIndex;
1799 boost::uuids::uuid sourceModuleId;
1800 boost::uuids::uuid functionId;
1801 cmajor::debug::ReadCompileUnitFunctionRecord(cudiReader, fileIndex, sourceModuleId, functionId);
1802 cmajor::debug::WriteCompileUnitFunctionRecord(cmdbWriter, fileIndex, sourceModuleId, functionId);
1803 int32_t numInstructionRecords;
1804 cmajor::debug::ReadNumberOfInstructionRecords(cudiReader, numInstructionRecords);
1805 cmajor::debug::WriteNumberOfInstructionRecords(cmdbWriter, numInstructionRecords);
1806 for (int32_t i = 0; i < numInstructionRecords; ++i)
1807 {
1808 int32_t cppLineNumber;
1809 cmajor::debug::SourceSpan span;
1810 int32_t cppLineIndex;
1811 int16_t scopeId;
1812 int16_t flags;
1813 cmajor::debug::ReadInstructionRecord(cudiReader, cppLineNumber, span, cppLineIndex, scopeId, flags);
1814 cmajor::debug::WriteInstructionRecord(cmdbWriter, cppLineNumber, span, cppLineIndex, scopeId, flags);
1815 }
1816 int32_t numScopes;
1817 cmajor::debug::ReadNumberOfScopes(cudiReader, numScopes);
1818 cmajor::debug::WriteNumberOfScopes(cmdbWriter, numScopes);
1819 for (int32_t i = 0; i < numScopes; ++i)
1820 {
1821 int16_t scopeId;
1822 int16_t parentScopeId;
1823 int32_t numLocalVariables;
1824 cmajor::debug::ReadScopeRecord(cudiReader, scopeId, parentScopeId, numLocalVariables);
1825 cmajor::debug::WriteScopeRecord(cmdbWriter, scopeId, parentScopeId, numLocalVariables);
1826 for (int32_t i = 0; i < numLocalVariables; ++i)
1827 {
1828 cmajor::debug::DIVariable variable(cmajor::debug::DIVariable::Kind::localVariable);
1829 variable.Read(cudiReader);
1830 variable.Write(cmdbWriter);
1831 }
1832 }
1833 int32_t controlFlowGraphNodeCount;
1834 cmajor::debug::ReadControlFlowGraphNodeCount(cudiReader, controlFlowGraphNodeCount);
1835 cmajor::debug::WriteControlFlowGraphNodeCount(cmdbWriter, controlFlowGraphNodeCount);
1836 for (int32_t i = 0; i < controlFlowGraphNodeCount; ++i)
1837 {
1838 int32_t nodeId;
1839 cmajor::debug::SourceSpan span;
1840 int32_t cppLineIndex;
1841 int32_t cppLineNumber;
1842 cmajor::debug::ReadControlFlowGraphNode(cudiReader, nodeId, span, cppLineIndex, cppLineNumber);
1843 cmajor::debug::WriteControlFlowGraphNode(cmdbWriter, nodeId, span, cppLineIndex, cppLineNumber);
1844 int32_t edgeCount;
1845 cmajor::debug::ReadControlFlowGraphNodeEdgeCount(cudiReader, edgeCount);
1846 cmajor::debug::WriteControlFlowGraphNodeEdgeCount(cmdbWriter, edgeCount);
1847 for (int32_t i = 0; i < edgeCount; ++i)
1848 {
1849 int32_t endNodeId;
1850 cmajor::debug::ReadControlFlowGraphNodeEdge(cudiReader, endNodeId);
1851 cmajor::debug::WriteControlFlowGraphNodeEdge(cmdbWriter, endNodeId);
1852 }
1853 }
1854 }
1855 }
1856 int32_t numFileIndexRecords;
1857 cmajor::debug::ReadNumberOfFileIndexRecords(pdiReader, numFileIndexRecords);
1858 cmajor::debug::WriteNumberOfFileIndexRecords(cmdbWriter, numFileIndexRecords);
1859 for (int32_t i = 0; i < numFileIndexRecords; ++i)
1860 {
1861 int32_t fileIndex;
1862 std::string sourceFilePath;
1863 cmajor::debug::ReadFileIndexRecord(pdiReader, fileIndex, sourceFilePath);
1864 cmajor::debug::WriteFileIndexRecord(cmdbWriter, fileIndex, sourceFilePath);
1865 }
1866 int32_t numFunctionIndexRecords;
1867 cmajor::debug::ReadNumberOfFunctionIndexFunctionRecords(pdiReader, numFunctionIndexRecords);
1868 cmajor::debug::WriteNumberOfFunctionIndexFunctionRecords(cmdbWriter, numFunctionIndexRecords);
1869 for (int32_t i = 0; i < numFunctionIndexRecords; ++i)
1870 {
1871 boost::uuids::uuid functionId;
1872 std::string fullFunctionName;
1873 std::string mangledFunctionName;
1874 cmajor::debug::ReadFunctionIndexFunctionRecord(pdiReader, functionId, fullFunctionName, mangledFunctionName);
1875 cmajor::debug::WriteFunctionIndexFunctionRecord(cmdbWriter, functionId, fullFunctionName, mangledFunctionName);
1876 }
1877 int32_t numTypeIndexRecords = pdiReader.ReadInt();
1878 cmdbWriter.Write(numTypeIndexRecords);
1879 for (int32_t i = 0; i < numTypeIndexRecords; ++i)
1880 {
1881 std::unique_ptr<cmajor::debug::DIType> diType = cmajor::debug::ReadType(pdiReader, nullptr);
1882 cmajor::debug::WriteType(cmdbWriter, diType.get());
1883 }
1884 ++numProjects;
1885 }
1886
1887 cmajor::debug::SourceSpan Module::SpanToSourceSpan(const Span& span)
1888 {
1889 if (!span.Valid()) return cmajor::debug::SourceSpan();
1890 cmajor::debug::SourceSpan sourceSpan;
1891 sourceSpan.line = span.line;
1892 if (GetFlag(ModuleFlags::compiling))
1893 {
1894 CmajorLexer* lexer = lexers[span.fileIndex].get();
1895 int32_t startCol = 0;
1896 int32_t endCol = 0;
1897 lexer->GetColumns(span, startCol, endCol);
1898 sourceSpan.scol = static_cast<int16_t>(startCol);
1899 sourceSpan.ecol = static_cast<int16_t>(endCol);
1900 }
1901 else
1902 {
1903 std::lock_guard<std::recursive_mutex> lck(lock);
1904 std::string filePath = GetFilePath(span.fileIndex);
1905 const std::u32string& content = sourceFileCache.GetFileContent(filePath);
1906 int32_t startCol = 0;
1907 int32_t endCol = 0;
1908 soulng::lexer::GetColumns(content.c_str(), content.c_str() + content.length(), span, startCol, endCol);
1909 sourceSpan.scol = static_cast<int16_t>(startCol);
1910 sourceSpan.ecol = static_cast<int16_t>(endCol);
1911 }
1912 return sourceSpan;
1913 }
1914
1915 int32_t Module::GetFileIndexForFilePath(const std::string& filePath) const
1916 {
1917 auto it = filePathFileIndexMap.find(filePath);
1918 if (it != filePathFileIndexMap.cend())
1919 {
1920 return it->second;
1921 }
1922 else
1923 {
1924 return -1;
1925 }
1926 }
1927
1928 void Module::UpdateSourceFileModuleMap()
1929 {
1930 int16_t n = fileTable.NumFilePaths();
1931 for (int16_t i = 0; i < n; ++i)
1932 {
1933 MapSourceFileToModuleId(backend, config, fileTable.GetFilePath(i), Id());
1934 }
1935 }
1936
1937 ParseResult Module::ParseSources()
1938 {
1939 if (sources)
1940 {
1941 ParseResult parseResult = sources->Parse(this);
1942 sources->AddSymbols(this);
1943 sources->GetScopes(this);
1944 sources->BindTypes(this);
1945 parseResult.numberOfErrors = sources->GetNumberOfErrors();
1946 parseResult.synchronized = sources->Synchronized();
1947 return parseResult;
1948 }
1949 else
1950 {
1951 ParseResult result;
1952 result.ok = false;
1953 result.error = "sources not set";
1954 return result;
1955 }
1956 }
1957
1958 ParseResult Module::ParseSource(const std::string& sourceFilePath, const std::u32string& sourceCode)
1959 {
1960 if (sources)
1961 {
1962 return sources->ParseSource(this, sourceFilePath, sourceCode);
1963 }
1964 else
1965 {
1966 ParseResult result;
1967 result.ok = false;
1968 result.error = "sources not set";
1969 return result;
1970 }
1971 }
1972
1973 std::string Module::GetCCList(const std::string& sourceFilePath, const std::string& ccText)
1974 {
1975 if (sources)
1976 {
1977 return sources->GetCCList(this, sourceFilePath, ccText);
1978 }
1979 else
1980 {
1981 throw std::runtime_error("sources not set");
1982 }
1983 }
1984
1985 std::string Module::GetOverloadList(const std::string& functionGroup)
1986 {
1987 Symbol* symbol = symbolTable->GlobalNs().GetContainerScope()->Lookup(ToUtf32(functionGroup));
1988 if (symbol->GetSymbolType() == SymbolType::functionGroupSymbol)
1989 {
1990 FunctionGroupSymbol* functionGroupSymbol = static_cast<FunctionGroupSymbol*>(symbol);
1991 return functionGroupSymbol->GetOverloadList();
1992 }
1993 return std::string();
1994 }
1995
1996 #ifdef _WIN32
1997
1998 #else
1999 Module* rootModule = nullptr;
2000 #endif
2001
2002 std::string GetSourceFilePath(int32_t fileIndex, const boost::uuids::uuid& moduleId)
2003 {
2004 if (fileIndex == -1)
2005 {
2006 return std::string();
2007 }
2008 Module* module = rootModule;
2009 if (!moduleId.is_nil())
2010 {
2011 Module* m = GetModuleById(moduleId);
2012 if (m)
2013 {
2014 module = m;
2015 }
2016 }
2017 if (module)
2018 {
2019 std::string sourceFilePath = module->GetFilePath(fileIndex);
2020 return sourceFilePath;
2021 }
2022 else
2023 {
2024 return std::string();
2025 }
2026 }
2027
2028 bool HasRootModuleForCurrentThread()
2029 {
2030 return rootModule != nullptr;
2031 }
2032
2033 Module* GetRootModuleForCurrentThread()
2034 {
2035 if (!rootModule)
2036 {
2037 throw std::runtime_error("root module for the current thread not set");
2038 }
2039 return rootModule;
2040 }
2041
2042 void SetRootModuleForCurrentThread(Module* rootModule_)
2043 {
2044 rootModule = rootModule_;
2045 }
2046
2047 class SystemModuleVersionTagVerifier : public sngcm::ast::ModuleVersionTagVerifier
2048 {
2049 public:
2050 void VerifyModuleVersionTag(const std::string& moduleFilePath) override;
2051 };
2052
2053 void SystemModuleVersionTagVerifier::VerifyModuleVersionTag(const std::string& moduleFilePath)
2054 {
2055 SymbolReader reader(moduleFilePath);
2056 ModuleTag expectedTag;
2057 ModuleTag tag;
2058 tag.Read(reader);
2059 for (int i = 0; i < 3; ++i)
2060 {
2061 if (tag.bytes[i] != expectedTag.bytes[i])
2062 {
2063 throw std::runtime_error("Invalid Cmajor module tag read from file '" + reader.GetBinaryReader().FileName() + "', please rebuild module from sources");
2064 }
2065 }
2066 if (tag.bytes[3] != expectedTag.bytes[3])
2067 {
2068 throw std::runtime_error("Cmajor module format version mismatch reading from file '" + reader.GetBinaryReader().FileName() +
2069 "': format " + std::string(1, expectedTag.bytes[3]) + " expected, format " + std::string(1, tag.bytes[3]) + " read, please rebuild module from sources");
2070 }
2071 }
2072
2073 SystemModuleVersionTagVerifier verifier;
2074
2075 void InitModule()
2076 {
2077 sngcm::ast::SetModuleVersionTagVerifier(&verifier);
2078 SystemModuleSet::Init();
2079 ContainerClassTemplateMap::Init();
2080 }
2081
2082 void DoneModule()
2083 {
2084 ContainerClassTemplateMap::Done();
2085 SystemModuleSet::Done();
2086 }
2087
2088 } }