1 // =================================
   2 // Copyright (c) 2021 Seppo Laakko
   3 // Distributed under the MIT license
   4 // =================================
   5 
   6 #include <cmajor/binder/BoundCompileUnit.hpp>
   7 #include <cmajor/binder/BoundNamespace.hpp>
   8 #include <cmajor/binder/BoundNodeVisitor.hpp>
   9 #include <cmajor/binder/StatementBinder.hpp>
  10 #include <cmajor/binder/BoundStatement.hpp>
  11 #include <cmajor/binder/BoundFunction.hpp>
  12 #include <cmajor/binder/OverloadResolution.hpp>
  13 #include <cmajor/symbols/Exception.hpp>
  14 #include <cmajor/symbols/FunctionSymbol.hpp>
  15 #include <cmajor/symbols/ClassTypeSymbol.hpp>
  16 #include <cmajor/symbols/GlobalFlags.hpp>
  17 #include <cmajor/symbols/DelegateSymbol.hpp>
  18 #include <cmajor/symbols/InterfaceTypeSymbol.hpp>
  19 #include <cmajor/symbols/Module.hpp>
  20 #include <cmajor/symbols/DebugFlags.hpp>
  21 #include <soulng/util/Path.hpp>
  22 #include <soulng/util/Unicode.hpp>
  23 #include <soulng/util/Log.hpp>
  24 #include <soulng/util/Time.hpp>
  25 #include <boost/filesystem.hpp>
  26 
  27 namespace cmajor { namespace binder {
  28 
  29 using namespace soulng::util;
  30 using namespace soulng::unicode;
  31 
  32 class ClassTypeConversion public FunctionSymbol
  33 {
  34 public:
  35     ClassTypeConversion(const std::u32string& name_ConversionType conversionType_uint8_t conversionDistance_TypeSymbol* sourceType_TypeSymbol* targetType_);
  36     ConversionType GetConversionType() const override { return conversionType; }
  37     uint8_t ConversionDistance() const override { return conversionDistance; }
  38     bool IsBasicTypeOperation() const override { return true; }
  39     void GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId) override;
  40     const char* ClassName() const override { return "ClassTypeConversion"; }
  41 private:
  42     ConversionType conversionType;
  43     uint8_t conversionDistance;
  44     TypeSymbol* sourceType;
  45     TypeSymbol* targetType;
  46 };
  47 
  48 ClassTypeConversion::ClassTypeConversion(const std::u32string& name_ConversionType conversionType_uint8_t conversionDistance_TypeSymbol* sourceType_TypeSymbol* targetType_) :
  49     FunctionSymbol(Span()boost::uuids::nil_uuid()name_)conversionType(conversionType_)conversionDistance(conversionDistance_)sourceType(sourceType_)targetType(targetType_)
  50 {
  51     SetConversion();
  52     SetGroupName(U"@conversion");
  53     SetAccess(SymbolAccess::public_);
  54     SetConversionSourceType(sourceType);
  55     SetConversionTargetType(targetType);
  56 }
  57 
  58 void ClassTypeConversion::GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId)
  59 {
  60     emitter.SetCurrentDebugLocation(span);
  61     void* value = emitter.Stack().Pop();
  62     emitter.Stack().Push(emitter.CreateBitCast(valuetargetType->IrType(emitter)));
  63 }
  64 
  65 class NullPtrToPtrConversion public FunctionSymbol
  66 {
  67 public:
  68     NullPtrToPtrConversion(TypeSymbol* nullPtrType_TypeSymbol* targetPointerType_);
  69     ConversionType GetConversionType() const override { return ConversionType::implicit_; }
  70     uint8_t ConversionDistance() const override { return 1; }
  71     bool IsBasicTypeOperation() const override { return true; }
  72     void GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId) override;
  73     std::unique_ptr<Value> ConvertValue(const std::std::unique_ptr<Value>&value) const override;
  74     const char* ClassName() const override { return "NullPtrToPtrConversion"; }
  75 private:
  76     TypeSymbol* nullPtrType;
  77     TypeSymbol* targetPointerType;
  78 };
  79 
  80 NullPtrToPtrConversion::NullPtrToPtrConversion(TypeSymbol* nullPtrType_TypeSymbol* targetPointerType_) :
  81     FunctionSymbol(Span()boost::uuids::nil_uuid()U"nullptr2ptr")nullPtrType(nullPtrType_)targetPointerType(targetPointerType_)
  82 {
  83     SetConversion();
  84     SetGroupName(U"@conversion");
  85     SetAccess(SymbolAccess::public_);
  86     SetConversionSourceType(nullPtrType->PlainType(GetSpan()SourceModuleId()));
  87     SetConversionTargetType(targetPointerType->PlainType(GetSpan()SourceModuleId()));
  88 
  89 }
  90 
  91 void NullPtrToPtrConversion::GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId)
  92 {
  93     emitter.SetCurrentDebugLocation(span);
  94     void* value = emitter.Stack().Pop();
  95     emitter.Stack().Push(emitter.CreateBitCast(valuetargetPointerType->IrType(emitter)));
  96 }
  97 
  98 std::std::unique_ptr<Value>NullPtrToPtrConversion::ConvertValue(conststd::std::unique_ptr<Value>&value) const
  99 {
 100     TypeSymbol* type = value->GetType(&nullPtrType->GetModule()->GetSymbolTable());
 101     if (type->IsPointerType())
 102     {
 103         return std::unique_ptr<Value>(new PointerValue(value->GetSpan()value->ModuleId()typenullptr));
 104     }
 105     else
 106     {
 107         return std::unique_ptr<Value>();
 108     }
 109 }
 110 
 111 class VoidPtrToPtrConversion public FunctionSymbol
 112 {
 113 public:
 114     VoidPtrToPtrConversion(TypeSymbol* voidPtrType_TypeSymbol* targetPointerType_);
 115     ConversionType GetConversionType() const override { return ConversionType::explicit_; }
 116     uint8_t ConversionDistance() const override { return 255; }
 117     bool IsBasicTypeOperation() const override { return true; }
 118     void GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId) override;
 119     const char* ClassName() const override { return "VoidPtrToPtrConversion"; }
 120 private:
 121     TypeSymbol* voidPtrType;
 122     TypeSymbol* targetPointerType;
 123 };
 124 
 125 VoidPtrToPtrConversion::VoidPtrToPtrConversion(TypeSymbol* voidPtrType_TypeSymbol* targetPointerType_) :
 126     FunctionSymbol(Span()boost::uuids::nil_uuid()U"voidPtr2ptr")voidPtrType(voidPtrType_)targetPointerType(targetPointerType_)
 127 {
 128     SetConversion();
 129     SetGroupName(U"@conversion");
 130     SetAccess(SymbolAccess::public_);
 131     SetConversionSourceType(voidPtrType->PlainType(GetSpan()SourceModuleId()));
 132     SetConversionTargetType(targetPointerType->PlainType(GetSpan()SourceModuleId()));
 133 }
 134 
 135 void VoidPtrToPtrConversion::GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId)
 136 {
 137     emitter.SetCurrentDebugLocation(span);
 138     void* value = emitter.Stack().Pop();
 139     emitter.Stack().Push(emitter.CreateBitCast(valuetargetPointerType->IrType(emitter)));
 140 }
 141 
 142 class PtrToVoidPtrConversion public FunctionSymbol
 143 {
 144 public:
 145     PtrToVoidPtrConversion(TypeSymbol* sourcePtrType_TypeSymbol* voidPtrType_);
 146     ConversionType GetConversionType() const override { return ConversionType::implicit_; }
 147     uint8_t ConversionDistance() const override { return 10; }
 148     bool IsBasicTypeOperation() const override { return true; }
 149     void GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId) override;
 150     const char* ClassName() const override { return "PtrToVoidPtrConversion"; }
 151 private:
 152     TypeSymbol* sourcePtrType;
 153     TypeSymbol* voidPtrType;
 154 };
 155 
 156 PtrToVoidPtrConversion::PtrToVoidPtrConversion(TypeSymbol* sourcePtrType_TypeSymbol* voidPtrType_) :
 157     FunctionSymbol(Span()boost::uuids::nil_uuid()U"ptr2voidPtr")sourcePtrType(sourcePtrType_)voidPtrType(voidPtrType_)
 158 {
 159     SetConversion();
 160     SetGroupName(U"@conversion");
 161     SetAccess(SymbolAccess::public_);
 162     SetConversionSourceType(sourcePtrType->PlainType(GetSpan()SourceModuleId()));
 163     SetConversionTargetType(voidPtrType->PlainType(GetSpan()SourceModuleId()));
 164 }
 165 
 166 void PtrToVoidPtrConversion::GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId)
 167 {
 168     emitter.SetCurrentDebugLocation(span);
 169     void* value = emitter.Stack().Pop();
 170     emitter.Stack().Push(emitter.CreateBitCast(valuevoidPtrType->IrType(emitter)));
 171 }
 172 
 173 class PtrToULongConversion public FunctionSymbol
 174 {
 175 public:
 176     PtrToULongConversion(TypeSymbol* ptrType_TypeSymbol* ulongType_);
 177     ConversionType GetConversionType() const override { return ConversionType::explicit_; }
 178     uint8_t ConversionDistance() const override { return 255; }
 179     bool IsBasicTypeOperation() const override { return true; }
 180     void GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId) override;
 181     const char* ClassName() const override { return "PtrToULongConversion"; }
 182 private:
 183     TypeSymbol* ptrType;
 184     TypeSymbol* ulongType;
 185 };
 186 
 187 PtrToULongConversion::PtrToULongConversion(TypeSymbol* ptrType_TypeSymbol* ulongType_) :
 188     FunctionSymbol(Span()boost::uuids::nil_uuid()U"ptr2ulong")ptrType(ptrType_)ulongType(ulongType_)
 189 {
 190     SetConversion();
 191     SetGroupName(U"@conversion");
 192     SetAccess(SymbolAccess::public_);
 193     SetConversionSourceType(ptrType->PlainType(GetSpan()SourceModuleId()));
 194     SetConversionTargetType(ulongType->PlainType(GetSpan()SourceModuleId()));
 195 }
 196 
 197 void PtrToULongConversion::GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId)
 198 {
 199     emitter.SetCurrentDebugLocation(span);
 200     void* value = emitter.Stack().Pop();
 201     emitter.Stack().Push(emitter.CreatePtrToInt(valueulongType->IrType(emitter)));
 202 }
 203 
 204 class ULongToVoidPtrConversion public FunctionSymbol
 205 {
 206 public:
 207     ULongToVoidPtrConversion(TypeSymbol* ulongType_TypeSymbol* voidPtrType_);
 208     ConversionType GetConversionType() const override { return ConversionType::explicit_; }
 209     uint8_t ConversionDistance() const override { return 255; }
 210     bool IsBasicTypeOperation() const override { return true; }
 211     void GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId) override;
 212     const char* ClassName() const override { return "ULongToVoidPtrConversion"; }
 213 private:
 214     TypeSymbol* ulongType;
 215     TypeSymbol* voidPtrType;
 216 };
 217 
 218 ULongToVoidPtrConversion::ULongToVoidPtrConversion(TypeSymbol* ulongType_TypeSymbol* voidPtrType_) :
 219     FunctionSymbol(Span()boost::uuids::nil_uuid()U"ulong2voidPtr")ulongType(ulongType_)voidPtrType(voidPtrType_)
 220 {
 221     SetConversion();
 222     SetGroupName(U"@conversion");
 223     SetAccess(SymbolAccess::public_);
 224     SetConversionSourceType(ulongType->PlainType(GetSpan()SourceModuleId()));
 225     SetConversionTargetType(voidPtrType->PlainType(GetSpan()SourceModuleId()));
 226 }
 227 
 228 void ULongToVoidPtrConversion::GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId)
 229 {
 230     emitter.SetCurrentDebugLocation(span);
 231     void* value = emitter.Stack().Pop();
 232     emitter.Stack().Push(emitter.CreateIntToPtr(valuevoidPtrType->IrType(emitter)));
 233 }
 234 
 235 class CharacterPointerLiteralToStringFunctionContainerConversion public FunctionSymbol
 236 {
 237 public:
 238     CharacterPointerLiteralToStringFunctionContainerConversion(TypeSymbol* characterPtrType_TypeSymbol* stringFunctionContainerType_);
 239     ConversionType GetConversionType() const override { return ConversionType::implicit_; }
 240     uint8_t ConversionDistance() const override { return 1; }
 241     bool IsBasicTypeOperation() const override { return true; }
 242     void GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId) override;
 243     std::unique_ptr<Value> ConvertValue(const std::std::unique_ptr<Value>&value) const override;
 244     const char* ClassName() const override { return "CharacterPointerLiteralToStringFunctionContainerConversion"; }
 245 private:
 246     TypeSymbol* characterPtrType;
 247     TypeSymbol* stringFunctionContainerType;
 248 };
 249 
 250 CharacterPointerLiteralToStringFunctionContainerConversion::CharacterPointerLiteralToStringFunctionContainerConversion(TypeSymbol* characterPtrType_TypeSymbol* stringFunctionContainerType_) :
 251     FunctionSymbol(Span()boost::uuids::nil_uuid()U"charlit2stringFun")characterPtrType(characterPtrType_)stringFunctionContainerType(stringFunctionContainerType_)
 252 {
 253     SetConversion();
 254     SetGroupName(U"@conversion");
 255     SetAccess(SymbolAccess::public_);
 256     SetConversionSourceType(characterPtrType->PlainType(GetSpan()SourceModuleId()));
 257     SetConversionTargetType(stringFunctionContainerType->PlainType(GetSpan()SourceModuleId()));
 258 }
 259 
 260 void CharacterPointerLiteralToStringFunctionContainerConversion::GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId)
 261 {
 262     throw std::runtime_error(ToUtf8(Name()) + " function provides compile time calls only");
 263 }
 264 
 265 std::std::unique_ptr<Value>CharacterPointerLiteralToStringFunctionContainerConversion::ConvertValue(conststd::std::unique_ptr<Value>&value) const
 266 {
 267     return std::unique_ptr<Value>();
 268 }
 269 
 270 BoundCompileUnit::BoundCompileUnit(Module& module_CompileUnitNode* compileUnitNode_AttributeBinder* attributeBinder_) :
 271     BoundNode(Span()boost::uuids::nil_uuid()BoundNodeType::boundCompileUnit)module(module_)symbolTable(module.GetSymbolTable())
 272     compileUnitNode(compileUnitNode_)attributeBinder(attributeBinder_)currentNamespace(nullptr)
 273     hasGotos(false)operationRepository(*this)functionTemplateRepository(*this)classTemplateRepository(*this)inlineFunctionRepository(*this)
 274     constExprFunctionRepository(*this)conversionTable(ConversionTable::Owner::compileUnitnullptr)bindingTypes(false)compileUnitIndex(-2)immutable(false)nextExitEntryIndex(0)
 275     systemRuntimeUnwindInfoSymbol(nullptr)systemRuntimeAddCompileUnitFunctionSymbol(nullptr)pushCompileUnitUnwindInfoInitFunctionSymbol(nullptr)
 276     initUnwindInfoDelegateType(nullptr)globalInitFunctionSymbol(nullptr)latestIdentifierNode(nullptr)
 277 {
 278     if (compileUnitNode)
 279     {
 280         boost::filesystem::path fileName = boost::filesystem::path(compileUnitNode->FilePath()).filename();
 281         boost::filesystem::path directory = module.DirectoryPath();
 282         boost::filesystem::path objectFileDirectory = module.ObjectFileDirectoryPath();
 283         boost::filesystem::path llfp = (directory / fileName).replace_extension(".ll");
 284         boost::filesystem::path cppfp = (directory / fileName).replace_extension(".cpp");
 285         boost::filesystem::path bcfp = (directory / fileName).replace_extension(".bc");
 286         boost::filesystem::path optbcfp = (directory / fileName).replace_extension(".opt.bc");
 287         boost::filesystem::path optllfp = (directory / fileName).replace_extension(".opt.ll");
 288         boost::filesystem::path objfp;
 289 #ifdef _WIN32
 290 
 291 
 292 
 293 
 294 
 295 
 296 
 297 
 298 
 299 
 300 
 301 
 302 
 303 
 304 
 305 #else
 306         objfp = (objectFileDirectory / fileName).replace_extension(".o");
 307 #endif
 308         llFilePath = GetFullPath(llfp.generic_string());
 309         cppFilePath = GetFullPath(cppfp.generic_string());
 310         bcFilePath = GetFullPath(bcfp.generic_string());
 311         optBCFilePath = GetFullPath(optbcfp.generic_string());
 312         optLLFilePath = GetFullPath(optllfp.generic_string());
 313         objectFilePath = GetFullPath(objfp.generic_string());
 314     }
 315 }
 316 
 317 void BoundCompileUnit::Load(Emitter& emitterOperationFlags flags)
 318 {
 319     throw Exception("cannot load from compile unit"GetSpan()module.Id());
 320 }
 321 
 322 void BoundCompileUnit::Store(Emitter& emitterOperationFlags flags)
 323 {
 324     throw Exception("cannot store to compile unit"GetSpan()module.Id());
 325 }
 326 
 327 void BoundCompileUnit::Accept(BoundNodeVisitor& visitor)
 328 {
 329     visitor.Visit(*this);
 330 }
 331 
 332 void BoundCompileUnit::AddFileScope(FileScope* fileScope)
 333 {
 334     fileScopes.push_back(std::unique_ptr<FileScope>(fileScope));
 335 }
 336 
 337 void BoundCompileUnit::RemoveLastFileScope()
 338 {
 339     if (fileScopes.empty())
 340     {
 341         throw Exception("file scopes of bound compile unit is empty"GetSpan()module.Id());
 342     }
 343     fileScopes.erase(fileScopes.end() - 1);
 344 }
 345 
 346 FileScope* BoundCompileUnit::ReleaseLastFileScope()
 347 {
 348     if (fileScopes.empty())
 349     {
 350         throw Exception("file scopes of bound compile unit is empty"GetSpan()module.Id());
 351     }
 352     FileScope* fileScope = fileScopes.back().release();
 353     RemoveLastFileScope();
 354     return fileScope;
 355 }
 356 
 357 void BoundCompileUnit::AddBoundNode(std::std::unique_ptr<BoundNode>&&boundNode)
 358 {
 359     if (immutable)
 360     {
 361         throw std::runtime_error("internal error: " + compileUnitNode->FilePath() + " is immutable");
 362     }
 363     if (currentNamespace)
 364     {
 365         currentNamespace->AddMember(std::move(boundNode));
 366     }
 367     else
 368     {
 369         boundNodes.push_back(std::move(boundNode));
 370     }
 371 }
 372 
 373 FunctionSymbol* BoundCompileUnit::GetConversion(TypeSymbol* sourceTypeTypeSymbol* targetTypeContainerScope* containerScopeBoundFunction* currentFunction
 374     const Span& spanconst boost::uuids::uuid& moduleIdArgumentMatch& argumentMatch)
 375 {
 376     FunctionSymbol* conversion = symbolTable.GetConversion(sourceTypetargetTypespanmoduleId);
 377     if (conversion && conversion->GetSymbolType() == SymbolType::conversionFunctionSymbol)
 378     {
 379         argumentMatch.preReferenceConversionFlags = OperationFlags::addr;
 380     }
 381     if (!conversion)
 382     {
 383         conversion = conversionTable.GetConversion(sourceTypetargetTypespanmoduleId);
 384         if (!conversion)
 385         {
 386             if (sourceType->IsNullPtrType() && targetType->IsPointerType() && !targetType->IsReferenceType())
 387             {
 388                 std::unique_ptr<FunctionSymbol> nullPtrToPtrConversion(new NullPtrToPtrConversion(symbolTable.GetTypeByName(U"@nullptr_type")targetType));
 389                 nullPtrToPtrConversion->SetParent(&symbolTable.GlobalNs());
 390                 conversion = nullPtrToPtrConversion.get();
 391                 conversionTable.AddConversion(conversion);
 392                 conversionTable.AddGeneratedConversion(std::move(nullPtrToPtrConversion));
 393                 return conversion;
 394             }
 395             else if (sourceType->IsVoidPtrType() && targetType->IsPointerType() && !targetType->IsReferenceType())
 396             {
 397                 std::unique_ptr<FunctionSymbol> voidPtrToPtrConversion(new VoidPtrToPtrConversion(symbolTable.GetTypeByName(U"void")->AddPointer(spanmoduleId)targetType));
 398                 voidPtrToPtrConversion->SetParent(&symbolTable.GlobalNs());
 399                 conversion = voidPtrToPtrConversion.get();
 400                 conversionTable.AddConversion(conversion);
 401                 conversionTable.AddGeneratedConversion(std::move(voidPtrToPtrConversion));
 402                 return conversion;
 403             }
 404             else if (sourceType->PlainType(spanmoduleId)->IsPointerType() && targetType == symbolTable.GetTypeByName(U"ulong"))
 405             {
 406                 std::unique_ptr<FunctionSymbol> ptrToULongConversion(new PtrToULongConversion(sourceType->PlainType(spanmoduleId)symbolTable.GetTypeByName(U"ulong")));
 407                 ptrToULongConversion->SetParent(&symbolTable.GlobalNs());
 408                 conversion = ptrToULongConversion.get();
 409                 conversionTable.AddConversion(conversion);
 410                 conversionTable.AddGeneratedConversion(std::move(ptrToULongConversion));
 411                 return conversion;
 412             }
 413             else if (sourceType == symbolTable.GetTypeByName(U"ulong") && targetType->IsVoidPtrType())
 414             {
 415                 std::unique_ptr<FunctionSymbol> ulongToVoidPtrConversion(new ULongToVoidPtrConversion(sourceTypetargetType));
 416                 ulongToVoidPtrConversion->SetParent(&symbolTable.GlobalNs());
 417                 conversion = ulongToVoidPtrConversion.get();
 418                 conversionTable.AddConversion(conversion);
 419                 conversionTable.AddGeneratedConversion(std::move(ulongToVoidPtrConversion));
 420                 return conversion;
 421             }
 422             else if (sourceType->IsDelegateType() && targetType->IsVoidPtrType())
 423             {
 424                 std::unique_ptr<FunctionSymbol> dlgToVoidPtrConversion(new DelegateToVoidPtrConversion(sourceTypetargetType));
 425                 dlgToVoidPtrConversion->SetParent(&symbolTable.GlobalNs());
 426                 conversion = dlgToVoidPtrConversion.get();
 427                 conversionTable.AddConversion(conversion);
 428                 conversionTable.AddGeneratedConversion(std::move(dlgToVoidPtrConversion));
 429                 return conversion;
 430             }
 431             else if (sourceType->IsVoidPtrType() && targetType->IsDelegateType())
 432             {
 433                 std::unique_ptr<FunctionSymbol> voidPtrToDlgConversion(new VoidPtrToDelegateConversion(sourceTypetargetTypesymbolTable.GetTypeByName(U"ulong")));
 434                 voidPtrToDlgConversion->SetParent(&symbolTable.GlobalNs());
 435                 conversion = voidPtrToDlgConversion.get();
 436                 conversionTable.AddConversion(conversion);
 437                 conversionTable.AddGeneratedConversion(std::move(voidPtrToDlgConversion));
 438                 return conversion;
 439             }
 440             else if (sourceType->PlainType(spanmoduleId)->IsPointerType() && targetType->RemoveConst(spanmoduleId)->IsVoidPtrType())
 441             {
 442                 std::unique_ptr<FunctionSymbol> ptrToVoidPtrConversion(new PtrToVoidPtrConversion(sourceType->PlainType(spanmoduleId)symbolTable.GetTypeByName(U"void")->AddPointer(spanmoduleId)));
 443                 ptrToVoidPtrConversion->SetParent(&symbolTable.GlobalNs());
 444                 conversion = ptrToVoidPtrConversion.get();
 445                 conversionTable.AddConversion(conversion);
 446                 conversionTable.AddGeneratedConversion(std::move(ptrToVoidPtrConversion));
 447                 return conversion;
 448             }
 449             else if (sourceType->PlainType(spanmoduleId)->IsCharacterPointerType() && targetType->IsStringFunctionContainer())
 450             {
 451                 std::unique_ptr<FunctionSymbol> charPtr2StringFunctionsConversion(
 452                     new CharacterPointerLiteralToStringFunctionContainerConversion(sourceType->PlainType(spanmoduleId)symbolTable.GetTypeByName(U"@string_functions")));
 453                 charPtr2StringFunctionsConversion->SetParent(&symbolTable.GlobalNs());
 454                 conversion = charPtr2StringFunctionsConversion.get();
 455                 conversionTable.AddConversion(conversion);
 456                 conversionTable.AddGeneratedConversion(std::move(charPtr2StringFunctionsConversion));
 457                 return conversion;
 458             }
 459             else if (sourceType->BaseType()->IsClassTypeSymbol() && targetType->BaseType()->IsClassTypeSymbol())
 460             {
 461                 if (sourceType->PointerCount() == targetType->PointerCount() && 
 462                     (!sourceType->IsArrayType() && !targetType->IsArrayType()))
 463                 {
 464                     ClassTypeSymbol* sourceClassType = static_cast<ClassTypeSymbol*>(sourceType->BaseType());
 465                     ClassTypeSymbol* targetClassType = static_cast<ClassTypeSymbol*>(targetType->BaseType());
 466                     uint8_t conversionDistance = 0;
 467                     if (sourceClassType->HasBaseClass(targetClassTypeconversionDistance))
 468                     {
 469                         //if (targetType->IsLvalueReferenceType() && !sourceType->IsReferenceType()) // bug???
 470                         if (targetType->IsReferenceType() && !sourceType->IsReferenceType())
 471                         {
 472                             argumentMatch.preReferenceConversionFlags = OperationFlags::addr;
 473                             sourceType = sourceType->AddLvalueReference(spanmoduleId);
 474                             if (targetType->IsConstType())
 475                             {
 476                                 sourceType = sourceType->AddConst(spanmoduleId);
 477                             }
 478                         }
 479                         std::u32string conversionName = sourceType->FullName() + U"2" + targetType->FullName();
 480                         std::unique_ptr<FunctionSymbol> implicitClassTypeConversion(new ClassTypeConversion(conversionNameConversionType::implicit_conversionDistancesourceTypetargetType));
 481                         conversion = implicitClassTypeConversion.get();
 482                         // do not add entry to the conversion table
 483                         conversionTable.AddGeneratedConversion(std::move(implicitClassTypeConversion));
 484                         return conversion;
 485                     }
 486                     else
 487                     {
 488                         uint8_t conversionDistance = 0;
 489                         if (targetClassType->HasBaseClass(sourceClassTypeconversionDistance))
 490                         {
 491                             //if (targetType->IsLvalueReferenceType() && !sourceType->IsReferenceType()) // bug???
 492                             if (targetType->IsReferenceType() && !sourceType->IsReferenceType())
 493                             {
 494                                 argumentMatch.preReferenceConversionFlags = OperationFlags::addr;
 495                                 sourceType = sourceType->AddLvalueReference(spanmoduleId);
 496                                 if (targetType->IsConstType())
 497                                 {
 498                                     sourceType = sourceType->AddConst(spanmoduleId);
 499                                 }
 500                             }
 501                             std::u32string conversionName = sourceType->FullName() + U"2" + targetType->FullName();
 502                             std::unique_ptr<FunctionSymbol> explicitClassTypeConversion(new ClassTypeConversion(conversionNameConversionType::explicit_conversionDistancesourceTypetargetType));
 503                             conversion = explicitClassTypeConversion.get();
 504                             // do not add entry to the conversion table
 505                             conversionTable.AddGeneratedConversion(std::move(explicitClassTypeConversion));
 506                             return conversion;
 507                         }
 508                     }
 509                 }
 510             }
 511             else if ((sourceType->GetSymbolType() == SymbolType::functionGroupTypeSymbol || sourceType->GetSymbolType() == SymbolType::memberExpressionTypeSymbol) && 
 512                 targetType->GetSymbolType() == SymbolType::delegateTypeSymbol)
 513             {
 514                 FunctionGroupSymbol* functionGroupSymbol = nullptr;
 515                 BoundMemberExpression* boundMemberExpression = nullptr;
 516                 if (sourceType->GetSymbolType() == SymbolType::functionGroupTypeSymbol)
 517                 {
 518                     FunctionGroupTypeSymbol* functionGroupTypeSymbol = static_cast<FunctionGroupTypeSymbol*>(sourceType);
 519                     functionGroupSymbol = functionGroupTypeSymbol->FunctionGroup();
 520                 }
 521                 else if (sourceType->GetSymbolType() == SymbolType::memberExpressionTypeSymbol)
 522                 {
 523                     MemberExpressionTypeSymbol* memberExpressionTypeSymbol = static_cast<MemberExpressionTypeSymbol*>(sourceType);
 524                     boundMemberExpression = static_cast<BoundMemberExpression*>(memberExpressionTypeSymbol->BoundMemberExpression());
 525                     if (boundMemberExpression->Member()->GetBoundNodeType() == BoundNodeType::boundFunctionGroupExpression)
 526                     {
 527                         BoundFunctionGroupExpression* boundFunctionGroupExpression = static_cast<BoundFunctionGroupExpression*>(boundMemberExpression->Member());
 528                         functionGroupSymbol = boundFunctionGroupExpression->FunctionGroup();
 529                     }
 530                 }
 531                 if (functionGroupSymbol)
 532                 {
 533                     DelegateTypeSymbol* delegateTypeSymbol = static_cast<DelegateTypeSymbol*>(targetType);
 534                     int arity = delegateTypeSymbol->Arity();
 535                     ViableFunctionSet viableFunctions;
 536                     functionGroupSymbol->CollectViableFunctions(arityviableFunctions&GetModule());
 537                     for (FunctionSymbol* viableFunction : viableFunctions.Get())
 538                     {
 539                         if (viableFunction->GetSymbolType() == SymbolType::memberFunctionSymbol && !viableFunction->IsStatic()) continue;
 540                         bool found = true;
 541                         for (int i = 0; i < arity; ++i)
 542                         {
 543                             ParameterSymbol* sourceParam = viableFunction->Parameters()[i];
 544                             ParameterSymbol* targetParam = delegateTypeSymbol->Parameters()[i];
 545                             if (!TypesEqual(sourceParam->GetType()targetParam->GetType()))
 546                             {
 547                                 found = false;
 548                                 break;
 549                             }
 550                         }
 551                         if (found)
 552                         {
 553                             found = TypesEqual(viableFunction->ReturnType()delegateTypeSymbol->ReturnType());
 554                         }
 555                         if (found)
 556                         {
 557                             if (boundMemberExpression)
 558                             {
 559                                 boundMemberExpression->ResetClassPtr();
 560                             }
 561                             if (viableFunction->IsFunctionTemplate())
 562                             {
 563                                 if (sourceType->GetSymbolType() == SymbolType::functionGroupTypeSymbol)
 564                                 {
 565                                     FunctionGroupTypeSymbol* functionGroupTypeSymbol = static_cast<FunctionGroupTypeSymbol*>(sourceType);
 566                                     BoundFunctionGroupExpression* boundFunctionGroupExpression = static_cast<BoundFunctionGroupExpression*>(functionGroupTypeSymbol->BoundFunctionGroup());
 567                                     std::unordered_map<TemplateParameterSymbol*TypeSymbol*> templateParameterMap;
 568                                     int n = viableFunction->TemplateParameters().size();
 569                                     if (boundFunctionGroupExpression->TemplateArgumentTypes().size() == n)
 570                                     {
 571                                         for (int i = 0; i < n; ++i)
 572                                         {
 573                                             TemplateParameterSymbol* templateParameterSymbol = viableFunction->TemplateParameters()[i];
 574                                             TypeSymbol* templateArgumentType = boundFunctionGroupExpression->TemplateArgumentTypes()[i];
 575                                             templateParameterMap[templateParameterSymbol] = templateArgumentType;
 576                                         }
 577                                         viableFunction = InstantiateFunctionTemplate(viableFunctiontemplateParameterMapspanmoduleId);
 578                                     }
 579                                     else
 580                                     {
 581                                         return nullptr;
 582                                     }
 583                                 }
 584                                 else
 585                                 {
 586                                     return nullptr;
 587                                 }
 588                             }
 589                             std::unique_ptr<FunctionSymbol> functionToDelegateConversion(new FunctionToDelegateConversion(sourceTypedelegateTypeSymbolviableFunction));
 590                             functionToDelegateConversion->SetParent(&symbolTable.GlobalNs());
 591                             conversion = functionToDelegateConversion.get();
 592                             conversionTable.AddConversion(conversion);
 593                             conversionTable.AddGeneratedConversion(std::move(functionToDelegateConversion));
 594                             return conversion;
 595                         }
 596                     }
 597                 }
 598             }
 599             else if ((sourceType->GetSymbolType() == SymbolType::functionGroupTypeSymbol || sourceType->GetSymbolType() == SymbolType::memberExpressionTypeSymbol) && 
 600                 targetType->PlainType(spanmoduleId)->GetSymbolType() == SymbolType::classDelegateTypeSymbol && currentFunction)
 601             {
 602                 ClassDelegateTypeSymbol* classDelegateType = static_cast<ClassDelegateTypeSymbol*>(targetType->PlainType(spanmoduleId));
 603                 FunctionGroupSymbol* functionGroup = nullptr;
 604                 if (sourceType->GetSymbolType() == SymbolType::functionGroupTypeSymbol)
 605                 {
 606                     FunctionGroupTypeSymbol* functionGroupTypeSymbol = static_cast<FunctionGroupTypeSymbol*>(sourceType);
 607                     BoundFunctionGroupExpression* boundFunctionGroup = static_cast<BoundFunctionGroupExpression*>(functionGroupTypeSymbol->BoundFunctionGroup());
 608                     functionGroup = functionGroupTypeSymbol->FunctionGroup();
 609                 }
 610                 else if (sourceType->GetSymbolType() == SymbolType::memberExpressionTypeSymbol)
 611                 {
 612                     MemberExpressionTypeSymbol* memberExpressionType = static_cast<MemberExpressionTypeSymbol*>(sourceType);
 613                     BoundMemberExpression* boundMemberExpr = static_cast<BoundMemberExpression*>(memberExpressionType->BoundMemberExpression());
 614                     if (boundMemberExpr->Member()->GetBoundNodeType() == BoundNodeType::boundFunctionGroupExpression)
 615                     {
 616                         BoundFunctionGroupExpression* boundFunctionGroup = static_cast<BoundFunctionGroupExpression*>(boundMemberExpr->Member());
 617                         functionGroup = boundFunctionGroup->FunctionGroup();
 618                     }
 619                 }
 620                 if (functionGroup)
 621                 {
 622                     int arity = classDelegateType->Arity();
 623                     ViableFunctionSet viableFunctions;
 624                     functionGroup->CollectViableFunctions(arity + 1viableFunctions&GetModule());
 625                     for (FunctionSymbol* viableFunction : viableFunctions.Get())
 626                     {
 627                         bool found = true;
 628                         for (int i = 1; i < arity + 1; ++i)
 629                         {
 630                             ParameterSymbol* sourceParam = viableFunction->Parameters()[i];
 631                             ParameterSymbol* targetParam = classDelegateType->Parameters()[i - 1];
 632                             if (!TypesEqual(sourceParam->GetType()targetParam->GetType()))
 633                             {
 634                                 found = false;
 635                                 break;
 636                             }
 637                         }
 638                         if (found)
 639                         {
 640                             found = TypesEqual(viableFunction->ReturnType()classDelegateType->ReturnType());
 641                         }
 642                         if (found)
 643                         {
 644                             //LocalVariableSymbol* objectDelegatePairVariable = currentFunction->GetFunctionSymbol()->CreateTemporary(classDelegateType->ObjectDelegatePairType(), span);
 645                             std::unique_ptr<FunctionSymbol> memberFunctionToClassDelegateConversion(new MemberFunctionToClassDelegateConversion(spanmoduleIdsourceTypeclassDelegateTypeviableFunction));
 646                             memberFunctionToClassDelegateConversion->SetParent(&symbolTable.GlobalNs());
 647                             conversion = memberFunctionToClassDelegateConversion.get();
 648                             conversionTable.AddConversion(conversion);
 649                             conversionTable.AddGeneratedConversion(std::move(memberFunctionToClassDelegateConversion));
 650                             return conversion;
 651                         }
 652                     }
 653                 }
 654             }
 655             else if (targetType->PlainType(spanmoduleId)->GetSymbolType() == SymbolType::interfaceTypeSymbol && currentFunction)
 656             {
 657                 InterfaceTypeSymbol* targetInterfaceType = static_cast<InterfaceTypeSymbol*>(targetType->PlainType(spanmoduleId));
 658                 if (sourceType->IsClassTypeSymbol())
 659                 {
 660                     ClassTypeSymbol* sourceClassType = static_cast<ClassTypeSymbol*>(sourceType);
 661                     int32_t n = sourceClassType->ImplementedInterfaces().size();
 662                     for (int32_t i = 0; i < n; ++i)
 663                     {
 664                         InterfaceTypeSymbol* sourceInterfaceType = sourceClassType->ImplementedInterfaces()[i];
 665                         if (TypesEqual(targetInterfaceTypesourceInterfaceType))
 666                         {
 667                             //LocalVariableSymbol* temporaryInterfaceObjectVar = currentFunction->GetFunctionSymbol()->CreateTemporary(targetInterfaceType, span);
 668                             std::unique_ptr<FunctionSymbol> classToInterfaceConversion(new ClassToInterfaceConversion(sourceClassTypetargetInterfaceTypeispanmoduleId));
 669                             classToInterfaceConversion->SetParent(&symbolTable.GlobalNs());
 670                             classToInterfaceConversion->SetModule(&GetModule());
 671                             conversion = classToInterfaceConversion.get();
 672                             conversionTable.AddConversion(conversion);
 673                             conversionTable.AddGeneratedConversion(std::move(classToInterfaceConversion));
 674                             return conversion;
 675                         }
 676                     }
 677                 }
 678             }
 679         }
 680     }
 681     if (conversion)
 682     {
 683         if (conversion->Parent() && !conversion->IsGeneratedFunction() && conversion->Parent()->GetSymbolType() == SymbolType::classTemplateSpecializationSymbol)
 684         {
 685             ClassTemplateSpecializationSymbol* specialization = static_cast<ClassTemplateSpecializationSymbol*>(conversion->Parent());
 686             if (specialization->GetModule() != &GetModule())
 687             {
 688                 specialization = symbolTable.GetCurrentClassTemplateSpecialization(specialization);
 689                 int index = conversion->GetIndex();
 690                 conversion = specialization->GetFunctionByIndex(index);
 691             }
 692             bool firstTry = InstantiateClassTemplateMemberFunction(conversioncontainerScopecurrentFunctionspanmoduleId);
 693             if (!firstTry)
 694             {
 695                 ClassTemplateSpecializationSymbol* specialization = static_cast<ClassTemplateSpecializationSymbol*>(conversion->Parent());
 696                 std::lock_guard<std::recursive_mutex> lock(symbolTable.GetModule()->GetLock());
 697                 ClassTemplateSpecializationSymbol* copy = symbolTable.CopyClassTemplateSpecialization(specialization);
 698                 classTemplateRepository.BindClassTemplateSpecialization(copysymbolTable.GlobalNs().GetContainerScope()spanmoduleId);
 699                 int index = conversion->GetIndex();
 700                 conversion = copy->GetFunctionByIndex(index);
 701                 bool secondTry = InstantiateClassTemplateMemberFunction(conversioncontainerScopecurrentFunctionspanmoduleId);
 702                 if (!secondTry)
 703                 {
 704                     throw Exception("internal error: could not instantiate member function of a class template specialization '" + ToUtf8(specialization->FullName()) + "'"
 705                         specialization->GetSpan()specialization->SourceModuleId());
 706                 }
 707             }
 708         }
 709         else if (GetGlobalFlag(GlobalFlags::release) && conversion->IsInline())
 710         {
 711             conversion = InstantiateInlineFunction(conversioncontainerScopespanmoduleId);
 712         }
 713     }
 714     return conversion;
 715 }
 716 
 717 void BoundCompileUnit::CollectViableFunctions(const std::u32string& groupNameContainerScope* containerScopestd::std::vector<std::std::unique_ptr<BoundExpression>>&arguments
 718     BoundFunction* currentFunctionViableFunctionSet& viableFunctionsstd::std::unique_ptr<Exception>&exceptionconstSpan&spanconstboost::uuids::uuid&moduleIdCollectFlags flags)
 719 {
 720     operationRepository.CollectViableFunctions(groupNamecontainerScopeargumentscurrentFunctionviableFunctionsexceptionspanmoduleIdflags);
 721 }
 722 
 723 FunctionSymbol* BoundCompileUnit::InstantiateFunctionTemplate(FunctionSymbol* functionTemplateconst std::std::unordered_map<TemplateParameterSymbol*TypeSymbol*>&templateParameterMapping
 724     const Span& spanconst boost::uuids::uuid& moduleId)
 725 {
 726     return functionTemplateRepository.Instantiate(functionTemplatetemplateParameterMappingspanmoduleId);
 727 }
 728 
 729 bool BoundCompileUnit::InstantiateClassTemplateMemberFunction(FunctionSymbol* memberFunctionContainerScope* containerScopeBoundFunction* currentFunctionconst Span& spanconst boost::uuids::uuid& moduleId)
 730 {
 731     return classTemplateRepository.Instantiate(memberFunctioncontainerScopecurrentFunctionspanmoduleId);
 732 }
 733 
 734 FunctionSymbol* BoundCompileUnit::InstantiateInlineFunction(FunctionSymbol* inlineFunctionContainerScope* containerScopeconst Span& spanconst boost::uuids::uuid& moduleId)
 735 {
 736     return inlineFunctionRepository.Instantiate(inlineFunctioncontainerScopespanmoduleId);
 737 }
 738 
 739 FunctionNode* BoundCompileUnit::GetFunctionNodeFor(FunctionSymbol* constExprFunctionSymbol)
 740 {
 741     return constExprFunctionRepository.GetFunctionNodeFor(constExprFunctionSymbol);
 742 }
 743 
 744 void BoundCompileUnit::GenerateCopyConstructorFor(ClassTypeSymbol* classTypeSymbolContainerScope* containerScopeBoundFunction* currentFunctionconst Span& spanconst boost::uuids::uuid& moduleId)
 745 {
 746     operationRepository.GenerateCopyConstructorFor(classTypeSymbolcontainerScopecurrentFunctionspanmoduleId);
 747 }
 748 
 749 void BoundCompileUnit::GenerateCopyConstructorFor(InterfaceTypeSymbol* interfaceTypeSymbolContainerScope* containerScopeBoundFunction* currentFunctionconst Span& spanconst boost::uuids::uuid& moduleId)
 750 {
 751     operationRepository.GenerateCopyConstructorFor(interfaceTypeSymbolcontainerScopecurrentFunctionspanmoduleId);
 752 }
 753 
 754 int BoundCompileUnit::Install(const std::string& str)
 755 {
 756     return utf8StringRepository.Install(str);
 757 }
 758 
 759 int BoundCompileUnit::Install(const std::u16string& str)
 760 {
 761     return utf16StringRepository.Install(str);
 762 }
 763 
 764 int BoundCompileUnit::Install(const std::u32string& str)
 765 {
 766     return utf32StringRepository.Install(str);
 767 }
 768 
 769 int BoundCompileUnit::Install(const boost::uuids::uuid& uuid)
 770 {
 771     return uuidRepository.Install(uuid);
 772 }
 773 
 774 const std::string& BoundCompileUnit::GetUtf8String(int stringId) const
 775 {
 776     return utf8StringRepository.GetString(stringId);
 777 }
 778 
 779 const std::u16string& BoundCompileUnit::GetUtf16String(int stringId) const
 780 {
 781     return utf16StringRepository.GetString(stringId);
 782 }
 783 
 784 const std::u32string& BoundCompileUnit::GetUtf32String(int stringId) const
 785 {
 786     return utf32StringRepository.GetString(stringId);
 787 }
 788 
 789 const unsigned char* BoundCompileUnit::GetUtf8CharPtr(int stringId) const
 790 {
 791     return utf8StringRepository.CharPtr(stringId);
 792 }
 793 
 794 const char16_t* BoundCompileUnit::GetUtf16CharPtr(int stringId) const
 795 {
 796     return utf16StringRepository.CharPtr(stringId);
 797 }
 798 
 799 const char32_t* BoundCompileUnit::GetUtf32CharPtr(int stringId) const
 800 {
 801     return utf32StringRepository.CharPtr(stringId);
 802 }
 803 
 804 const boost::uuids::uuid& BoundCompileUnit::GetUuid(int uuidId) const
 805 {
 806     return uuidRepository.GetUuid(uuidId);
 807 }
 808 
 809 void BoundCompileUnit::AddConstantArray(ConstantSymbol* constantArraySymbol)
 810 {
 811     constantArrayRepository.AddConstantArray(constantArraySymbol);
 812 }
 813 
 814 void BoundCompileUnit::AddConstantStructure(ConstantSymbol* constantStructureSymbol)
 815 {
 816     constantStructureRepository.AddConstantStructure(constantStructureSymbol);
 817 }
 818 
 819 void BoundCompileUnit::PushBindingTypes()
 820 {
 821     bindingTypesStack.push(bindingTypes);
 822     bindingTypes = true;
 823 }
 824 
 825 void BoundCompileUnit::PopBindingTypes()
 826 {
 827     bindingTypes = bindingTypesStack.top();
 828     bindingTypesStack.pop();
 829 }
 830 
 831 void BoundCompileUnit::FinalizeBinding(ClassTemplateSpecializationSymbol* classTemplateSpecialization)
 832 {
 833     if (classTemplateSpecialization->GetModule() == &module && classTemplateSpecialization->StatementsNotBound())
 834     {
 835         classTemplateSpecialization->ResetStatementsNotBound();
 836         FileScope* fileScope = classTemplateSpecialization->ReleaseFileScope();
 837         bool fileScopeAdded = false;
 838         if (fileScope)
 839         {
 840             AddFileScope(fileScope);
 841             fileScopeAdded = true;
 842         }
 843         StatementBinder statementBinder(*this);
 844         classTemplateSpecialization->GlobalNs()->Accept(statementBinder);
 845         if (fileScopeAdded)
 846         {
 847             RemoveLastFileScope();
 848         }
 849     }
 850 }
 851 
 852 void BoundCompileUnit::PushNamespace(BoundNamespace* ns)
 853 {
 854     namespaceStack.push(currentNamespace);
 855     currentNamespace = ns;
 856 }
 857 
 858 void BoundCompileUnit::PopNamespace()
 859 {
 860     currentNamespace = namespaceStack.top();
 861     namespaceStack.pop();
 862 }
 863 
 864 bool BoundCompileUnit::HasCopyConstructorFor(const boost::uuids::uuid& typeId) const
 865 {
 866     return copyConstructorMap.find(typeId) != copyConstructorMap.cend();
 867 }
 868 
 869 FunctionSymbol* BoundCompileUnit::GetCopyConstructorFor(const boost::uuids::uuid& typeId) const
 870 {
 871     auto it = copyConstructorMap.find(typeId);
 872     if (it != copyConstructorMap.cend())
 873     {
 874         return it->second;
 875     }
 876     else
 877     {
 878         throw std::runtime_error("internal error: copy constructor for type not found from compile unit");
 879     }
 880 }
 881  
 882 void BoundCompileUnit::AddCopyConstructorFor(const boost::uuids::uuid& typeIdstd::std::unique_ptr<FunctionSymbol>&&copyConstructor)
 883 {
 884     copyConstructorMap[typeId] = copyConstructor.get();
 885     copyConstructors.push_back(std::move(copyConstructor));
 886 }
 887 
 888 void BoundCompileUnit::AddCopyConstructorToMap(const boost::uuids::uuid& typeIdFunctionSymbol* copyConstructor)
 889 {
 890     copyConstructorMap[typeId] = copyConstructor;
 891 }
 892 
 893 void BoundCompileUnit::AddGlobalNs(std::std::unique_ptr<NamespaceNode>&&globalNs)
 894 {
 895     globalNamespaceNodes.push_back(std::move(globalNs));
 896 }
 897 
 898 bool BoundCompileUnit::IsGeneratedDestructorInstantiated(DestructorSymbol* generatedDestructorSymbol) const
 899 {
 900     return instantiatedGeneratedDestructors.find(generatedDestructorSymbol) != instantiatedGeneratedDestructors.cend();
 901 }
 902 
 903 void BoundCompileUnit::SetGeneratedDestructorInstantiated(DestructorSymbol* generatedDestructorSymbol)
 904 {
 905     instantiatedGeneratedDestructors.insert(generatedDestructorSymbol);
 906 }
 907 
 908 void BoundCompileUnit::SetSystemRuntimeUnwindInfoSymbol(TypeSymbol* systemRuntimeUnwindInfoSymbol_)
 909 {
 910     systemRuntimeUnwindInfoSymbol = systemRuntimeUnwindInfoSymbol_;
 911 }
 912 
 913 void BoundCompileUnit::GenerateInitUnwindInfoFunctionSymbol()
 914 {
 915     if (cmajor::symbols::GetBackEnd() == cmajor::symbols::BackEnd::cmsx) return;
 916     std::string compileUnitId = compileUnitNode->Id();
 917     std::u32string groupName = U"InitUnwindInfo_" + ToUtf32(compileUnitId);
 918     FunctionSymbol* functionSymbol = new FunctionSymbol(Span()boost::uuids::nil_uuid()groupName);
 919     functionSymbol->SetParent(&symbolTable.GlobalNs());
 920     functionSymbol->SetGroupName(groupName);
 921     functionSymbol->SetAccess(SymbolAccess::public_);
 922     functionSymbol->SetCDecl();
 923     functionSymbol->SetNothrow();
 924     functionSymbol->ComputeMangledName();
 925     functionSymbol->SetReturnType(symbolTable.GetTypeByName(U"void"));
 926     symbolTable.SetFunctionIdFor(functionSymbol);
 927     initUnwindInfoFunctionSymbol.reset(functionSymbol);
 928 }
 929 
 930 void BoundCompileUnit::GenerateCompileUnitInitialization()
 931 {
 932     if (module.IsCore()) return;
 933     if (cmajor::symbols::GetBackEnd() == cmajor::symbols::BackEnd::cmsx) return;
 934     std::string compileUnitId = compileUnitNode->Id();
 935     std::u32string groupName = U"InitCompileUnit_" + ToUtf32(compileUnitId);
 936     FunctionSymbol* functionSymbol = new FunctionSymbol(Span()boost::uuids::nil_uuid()groupName);
 937     functionSymbol->SetParent(&symbolTable.GlobalNs());
 938     functionSymbol->SetGroupName(groupName);
 939     functionSymbol->SetAccess(SymbolAccess::public_);
 940     functionSymbol->SetCDecl();
 941     functionSymbol->SetNothrow();
 942     functionSymbol->ComputeMangledName();
 943     functionSymbol->SetReturnType(symbolTable.GetTypeByName(U"void"));
 944     symbolTable.SetFunctionIdFor(functionSymbol);
 945     initCompileUnitFunctionSymbol.reset(functionSymbol);
 946     Symbol* symbol = symbolTable.GlobalNs().GetContainerScope()->Lookup(U"System.Runtime.PushCompileUnitUnwindInfoInit");
 947     if (symbol)
 948     {
 949         if (symbol->GetSymbolType() == SymbolType::functionGroupSymbol)
 950         {
 951             FunctionGroupSymbol* functionGroup = static_cast<FunctionGroupSymbol*>(symbol);
 952             pushCompileUnitUnwindInfoInitFunctionSymbol = functionGroup->GetFunction();
 953         }
 954     }
 955     if (!pushCompileUnitUnwindInfoInitFunctionSymbol)
 956     {
 957         throw std::runtime_error("internal error: 'System.Runtime.PushCompileUnitUnwindInfoInit' symbol not found");
 958     }
 959     Span span = initCompileUnitFunctionSymbol->GetSpan();
 960     boost::uuids::uuid moduleId = initCompileUnitFunctionSymbol->SourceModuleId();
 961     compileUnitUnwindInfoVarSymbol.reset(new GlobalVariableSymbol(spanmoduleIdU"unwindInfoInit_" + ToUtf32(compileUnitId)));
 962     compileUnitUnwindInfoVarSymbol->SetAccess(SymbolAccess::public_);
 963     compileUnitUnwindInfoVarSymbol->ComputeMangledName();
 964     Symbol* cuUnwindInfoTypeSymbol = symbolTable.GlobalNs().GetContainerScope()->Lookup(U"System.Runtime.CompileUnitUnwindInfo");
 965     if (cuUnwindInfoTypeSymbol && cuUnwindInfoTypeSymbol->GetSymbolType() == SymbolType::classGroupTypeSymbol)
 966     {
 967         ClassGroupTypeSymbol* classGroup = static_cast<ClassGroupTypeSymbol*>(cuUnwindInfoTypeSymbol);
 968         ClassTypeSymbol* classTypeSymbol = classGroup->GetClass(0);
 969         if (!classTypeSymbol)
 970         {
 971             throw std::runtime_error("internal error: 'System.Runtime.CompileUnitUnwindInfo' class not found");
 972         }
 973         compileUnitUnwindInfoVarSymbol->SetType(classTypeSymbol);
 974         BoundGlobalVariable* compileUnitUnwindInfoVar = new BoundGlobalVariable(spanmoduleIdcompileUnitUnwindInfoVarSymbol.get());
 975         AddBoundNode(std::unique_ptr<BoundNode>(compileUnitUnwindInfoVar));
 976     }
 977     else
 978     {
 979         throw std::runtime_error("internal error: 'System.Runtime.CompileUnitUnwindInfo' symbol not found");
 980     }
 981     Symbol* initUnwindInfoDelegateSymbol = symbolTable.GlobalNs().GetContainerScope()->Lookup(U"System.Runtime.InitCompileUnitUnwindInfoFunction");
 982     if (initUnwindInfoDelegateSymbol && initUnwindInfoDelegateSymbol->IsTypeSymbol())
 983     {
 984         initUnwindInfoDelegateType = static_cast<TypeSymbol*>(initUnwindInfoDelegateSymbol);
 985     }
 986     else
 987     {
 988         throw std::runtime_error("internal error: 'System.Runtime.InitCompileUnitUnwindInfoFunction' symbol not found");
 989     }
 990 }
 991 
 992 void BoundCompileUnit::GenerateGlobalInitializationFunction()
 993 {
 994     if (cmajor::symbols::GetBackEnd() == cmajor::symbols::BackEnd::cmsx) return;
 995     std::u32string groupName = U"GlobalInitCompileUnits";
 996     globalInitFunctionSymbol = new FunctionSymbol(Span()boost::uuids::nil_uuid()groupName);
 997     globalInitFunctionSymbol->SetParent(&symbolTable.GlobalNs());
 998     globalInitFunctionSymbol->SetGroupName(groupName);
 999     globalInitFunctionSymbol->SetAccess(SymbolAccess::public_);
1000     globalInitFunctionSymbol->SetCDecl();
1001     globalInitFunctionSymbol->SetNothrow();
1002     globalInitFunctionSymbol->ComputeMangledName();
1003     globalInitFunctionSymbol->SetReturnType(symbolTable.GetTypeByName(U"void"));
1004     symbolTable.SetFunctionIdFor(globalInitFunctionSymbol);
1005     symbolTable.GlobalNs().AddMember(globalInitFunctionSymbol);
1006     const std::std::set<std::string>&compileUnitIds=symbolTable.GetModule()->AllCompileUnitIds();
1007     for (const std::string& compileUnitId : compileUnitIds)
1008     {
1009         Assert(!compileUnitId.empty()"compiler unit ID is empty");
1010         std::u32string groupName = U"InitCompileUnit_" + ToUtf32(compileUnitId);
1011         FunctionSymbol* initFunctionSymbol = new FunctionSymbol(Span()boost::uuids::nil_uuid()groupName);
1012         initFunctionSymbol->SetParent(&symbolTable.GlobalNs());
1013         initFunctionSymbol->SetGroupName(groupName);
1014         initFunctionSymbol->SetAccess(SymbolAccess::public_);
1015         initFunctionSymbol->SetCDecl();
1016         initFunctionSymbol->SetNothrow();
1017         initFunctionSymbol->ComputeMangledName();
1018         initFunctionSymbol->SetReturnType(symbolTable.GetTypeByName(U"void"));
1019         symbolTable.SetFunctionIdFor(initFunctionSymbol);
1020         allCompileUnitInitFunctionSymbols.push_back(std::unique_ptr<FunctionSymbol>(initFunctionSymbol));
1021     }
1022 }
1023 
1024 bool BoundCompileUnit::CodeGenerated(FunctionSymbol* functionSymbol) const
1025 {
1026     return codeGenerated.find(functionSymbol) != codeGenerated.cend();
1027 }
1028 
1029 void BoundCompileUnit::SetCodeGenerated(FunctionSymbol* functionSymbol)
1030 {
1031     codeGenerated.insert(functionSymbol);
1032 }
1033 
1034 bool BoundCompileUnit::CanReuse(FunctionSymbol* functionSymbol) const
1035 {
1036     return canReuse.find(functionSymbol) != canReuse.cend();
1037 }
1038 
1039 void BoundCompileUnit::SetCanReuse(FunctionSymbol* functionSymbol)
1040 {
1041     canReuse.insert(functionSymbol);
1042 }
1043 
1044 } } // namespace cmajor::binder