1 // =================================
   2 // Copyright (c) 2021 Seppo Laakko
   3 // Distributed under the MIT license
   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 // #define RESOURCE_DEBUG
  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::u32stringcmajor::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& writerbool 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(cmajorRoot0) == 0)
 271             {
 272                 filePath = filePath.substr(cmajorRoot.size());
 273             }
 274         }
 275         writer.Write(filePath);
 276     }
 277 }
 278 
 279 void FileTable::Read(BinaryReader& readerbool 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(cmajorRootfilePath);
 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& spanconst 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*>&finishReadOrderModule*modulestd::std::unordered_set<Module*>&visitedstd::std::unordered_set<Module*>&tempVisit
 353     std::std::unordered_map<Module*ModuleDependency*>&dependencyMapconstModule*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(finishReadOrderdependentAssemblyvisitedtempVisitdependencyMaprootModule);
 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*>&modulesstd::std::unordered_map<Module*ModuleDependency*>&dependencyMapconstModule*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(finishReadOrdermodulevisitedtempVisitdependencyMaprootModule);
 394         }
 395     }
 396     return finishReadOrder;
 397 }
 398 
 399 void FinishReads(Module* rootModulestd::std::vector<Module*>&finishReadOrderboolallboolreadRoot)
 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(arrayTypesderivedTypesclassTemplateSpecializationstypeAndConceptRequestsfunctionRequestsconversions);
 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 targetModule* rootModuleModule* moduleconst std::std::vector<std::string>&referencesstd::std::unordered_set<std::string>&importSetstd::std::vector<Module*>&modules
 464     std::std::unordered_map<std::stringModuleDependency*>&moduleDependencyMapstd::std::unordered_map<std::stringModule*>&readMapbool&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(configbackendGetToolChain()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(targetreaderrootModuleimportSetmodulesmoduleDependencyMapreadMapfirst);
 539                 module->AddReferencedModule(referencedModule);
 540                 if (module != rootModule)
 541                 {
 542                     module->RegisterFileTable(&referencedModule->GetFileTable()referencedModule);
 543                 }
 544                 Import(targetrootModulemodulereferencedModule->ReferenceFilePaths()importSetmodulesmoduleDependencyMapreadMapfirst);
 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(configbackendGetToolChain()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* rootModuleModule* moduleconst std::std::vector<std::string>&referencesstd::std::unordered_set<std::string>&importSetstd::std::vector<Module*>&modules
 629     std::std::unordered_map<std::stringModuleDependency*>&moduleDependencyMapstd::std::unordered_map<std::stringModule*>&readMapbool&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()backendGetToolChain()systemDirKind));
 667             }
 668         }
 669     }
 670     Import(targetrootModulemoduleallReferencesimportSetmodulesmoduleDependencyMapreadMapfirst);
 671 #ifdef MODULE_READING_DEBUG
 672 
 673 
 674 #endif 
 675 }
 676 
 677 void ImportModules(sngcm::ast::Target targetModule* rootModuleModule* modulestd::std::unordered_set<std::string>&importSetstd::std::vector<Module*>&modules
 678     std::std::unordered_map<std::stringModuleDependency*>&dependencyMapstd::std::unordered_map<std::stringModule*>&readMapbool&first)
 679 {
 680 #ifdef MODULE_READING_DEBUG
 681 
 682 
 683 #endif 
 684     ImportModulesWithReferences(targetrootModulemodulemodule->ReferenceFilePaths()importSetmodulesdependencyMapreadMapfirst);
 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(filePathfalse)
 700 {
 701 }
 702 
 703 Module::Module(const std::string& filePathbool 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(1expectedTag.bytes[3]) + " expected, format " + std::string(1tag.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::stringModuleDependency*> moduleDependencyMap;
 740     std::unordered_map<std::stringModule*> 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::libraryreader2rootModuleimportSetmodulesmoduleDependencyMapreadMapfirst);
 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(modulesdependencyMaprootModule);
 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(libraryManagerToolGetConfig());
 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(rootModulefinishReadOrdertruereadRoot);
 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>&referencessngcm::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(compilerToolGetConfig());
 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(&fileTablerootModule);
 891     std::unordered_map<std::stringModuleDependency*> moduleDependencyMap;
 892     std::unordered_map<std::stringModule*> readMap;
 893     std::vector<Module*> modules;
 894     bool first = true;
 895     ImportModulesWithReferences(targetrootModulerootModulereferencesimportSetmodulesmoduleDependencyMapreadMapfirst);
 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(modulesdependencyMaprootModule);
 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(libraryManagerToolGetConfig());
 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(rootModulefinishReadOrderfalsefalse);
 965     MakeFilePathFileIndexMap();
 966 }
 967 
 968 void Module::CreateSymbolTable()
 969 {
 970     symbolTable.reset(new SymbolTable(this));
 971 }
 972 
 973 void Module::RegisterFileTable(FileTable* fileTableModule* 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& spanint32_t& startColint32_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(spanstartColendCol);
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()spanstartColendCol);
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 targetSymbolReader& readerModule* rootModulestd::std::unordered_set<std::string>&importSetstd::std::vector<Module*>&modules
1138     std::std::unordered_map<std::stringModuleDependency*>&dependencyMapstd::std::unordered_map<std::stringModule*>&readMapbool&first)
1139 {
1140     if (headerRead)
1141     {
1142 #ifdef MODULE_READING_DEBUG
1143 
1144 
1145 #endif 
1146         rootModule->RegisterFileTable(&fileTablethis);
1147         if (this != rootModule)
1148         {
1149             RegisterFileTable(&fileTablethis);
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(targetrootModulethisimportSetmodulesdependencyMapreadMapfirst);
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(1expectedTag.bytes[3]) + " expected, format " + std::string(1tag.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(&fileTablethis);
1220     if (this != rootModule)
1221     {
1222         RegisterFileTable(&fileTablethis);
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(libraryManagerToolGetConfig());
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(targetrootModulethisimportSetmodulesdependencyMapreadMapfirst);
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(1format));
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(writerToUtf8(name)Path::GetDirectoryName(originalFilePath)Id()numCompileUnitsfunctionIndex.GetMainFunctionId());
1737     for (int32_t i = 0; i < numCompileUnits; ++i)
1738     {
1739         std::string compileUnitBaseName = Path::GetFileNameWithoutExtension(fileTable.GetFilePath(i));
1740         cmajor::debug::WriteProjectTableRecord(writercompileUnitBaseName);
1741     }
1742     int32_t n = fileTable.NumFilePaths();
1743     cmajor::debug::WriteNumberOfFileIndexRecords(writern);
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(writerfileIndexfilePath);
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(cmdbWritermainProjectName);
1761     int32_t numProjects = 0;
1762     uint32_t numProjectsPos = cmdbWriter.Pos();
1763     cmajor::debug::WriteNumberOfProjects(cmdbWriternumProjects);
1764     for (Module* referencedModule : referencedModules)
1765     {
1766         referencedModule->WriteDebugInfo(cmdbWriternumProjectsthis);
1767     }
1768     WriteDebugInfo(cmdbWriternumProjectsthis);
1769     uint32_t currentPos = cmdbWriter.Pos();
1770     cmdbWriter.Seek(numProjectsPos);
1771     cmajor::debug::WriteNumberOfProjects(cmdbWriternumProjects);
1772     cmdbWriter.Seek(currentPos);
1773 }
1774 
1775 void Module::WriteDebugInfo(BinaryWriter& cmdbWriterint32_t& numProjectsModule* 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(pdiReaderprojectNameprojectDirectoryPathmoduleIdnumCompileUnitsmainFunctionId);
1785     cmajor::debug::WriteProjectTableHeader(cmdbWriterprojectNameprojectDirectoryPathmoduleIdnumCompileUnitsmainFunctionId);
1786     for (int32_t i = 0; i < numCompileUnits; ++i)
1787     {
1788         std::string compileUnitBaseName;
1789         cmajor::debug::ReadProjectTableRecord(pdiReadercompileUnitBaseName);
1790         cmajor::debug::WriteProjectTableRecord(cmdbWritercompileUnitBaseName);
1791         std::string cudiFilePath = Path::Combine(projectDirectoryPathcompileUnitBaseName + ".cudi");
1792         BinaryReader cudiReader(cudiFilePath);
1793         int32_t numFunctionRecords;
1794         cmajor::debug::ReadNumberOfCompileUnitFunctionRecords(cudiReadernumFunctionRecords);
1795         cmajor::debug::WriteNumberOfCompileUnitFunctionRecords(cmdbWriternumFunctionRecords);
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(cudiReaderfileIndexsourceModuleIdfunctionId);
1802             cmajor::debug::WriteCompileUnitFunctionRecord(cmdbWriterfileIndexsourceModuleIdfunctionId);
1803             int32_t numInstructionRecords;
1804             cmajor::debug::ReadNumberOfInstructionRecords(cudiReadernumInstructionRecords);
1805             cmajor::debug::WriteNumberOfInstructionRecords(cmdbWriternumInstructionRecords);
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(cudiReadercppLineNumberspancppLineIndexscopeIdflags);
1814                 cmajor::debug::WriteInstructionRecord(cmdbWritercppLineNumberspancppLineIndexscopeIdflags);
1815             }
1816             int32_t numScopes;
1817             cmajor::debug::ReadNumberOfScopes(cudiReadernumScopes);
1818             cmajor::debug::WriteNumberOfScopes(cmdbWriternumScopes);
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(cudiReaderscopeIdparentScopeIdnumLocalVariables);
1825                 cmajor::debug::WriteScopeRecord(cmdbWriterscopeIdparentScopeIdnumLocalVariables);
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(cudiReadercontrolFlowGraphNodeCount);
1835             cmajor::debug::WriteControlFlowGraphNodeCount(cmdbWritercontrolFlowGraphNodeCount);
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(cudiReadernodeIdspancppLineIndexcppLineNumber);
1843                 cmajor::debug::WriteControlFlowGraphNode(cmdbWriternodeIdspancppLineIndexcppLineNumber);
1844                 int32_t edgeCount;
1845                 cmajor::debug::ReadControlFlowGraphNodeEdgeCount(cudiReaderedgeCount);
1846                 cmajor::debug::WriteControlFlowGraphNodeEdgeCount(cmdbWriteredgeCount);
1847                 for (int32_t i = 0; i < edgeCount; ++i)
1848                 {
1849                     int32_t endNodeId;
1850                     cmajor::debug::ReadControlFlowGraphNodeEdge(cudiReaderendNodeId);
1851                     cmajor::debug::WriteControlFlowGraphNodeEdge(cmdbWriterendNodeId);
1852                 }
1853             }
1854         }
1855     }
1856     int32_t numFileIndexRecords;
1857     cmajor::debug::ReadNumberOfFileIndexRecords(pdiReadernumFileIndexRecords);
1858     cmajor::debug::WriteNumberOfFileIndexRecords(cmdbWriternumFileIndexRecords);
1859     for (int32_t i = 0; i < numFileIndexRecords; ++i)
1860     {
1861         int32_t fileIndex;
1862         std::string sourceFilePath;
1863         cmajor::debug::ReadFileIndexRecord(pdiReaderfileIndexsourceFilePath);
1864         cmajor::debug::WriteFileIndexRecord(cmdbWriterfileIndexsourceFilePath);
1865     }
1866     int32_t numFunctionIndexRecords;
1867     cmajor::debug::ReadNumberOfFunctionIndexFunctionRecords(pdiReadernumFunctionIndexRecords);
1868     cmajor::debug::WriteNumberOfFunctionIndexFunctionRecords(cmdbWriternumFunctionIndexRecords);
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(pdiReaderfunctionIdfullFunctionNamemangledFunctionName);
1875         cmajor::debug::WriteFunctionIndexFunctionRecord(cmdbWriterfunctionIdfullFunctionNamemangledFunctionName);
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(pdiReadernullptr);
1882         cmajor::debug::WriteType(cmdbWriterdiType.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(spanstartColendCol);
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()spanstartColendCol);
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(backendconfigfileTable.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& sourceFilePathconst std::u32string& sourceCode)
1959 {
1960     if (sources)
1961     {
1962         return sources->ParseSource(thissourceFilePathsourceCode);
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& sourceFilePathconst std::string& ccText)
1974 {
1975     if (sources)
1976     {
1977         return sources->GetCCList(thissourceFilePathccText);
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 fileIndexconst 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(1expectedTag.bytes[3]) + " expected, format " + std::string(1tag.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 } } // namespace cmajor::symbols