1 // =================================
   2 // Copyright (c) 2021 Seppo Laakko
   3 // Distributed under the MIT license
   4 // =================================
   5 
   6 #include <cmajor/symbols/DelegateSymbol.hpp>
   7 #include <cmajor/symbols/VariableSymbol.hpp>
   8 #include <cmajor/symbols/SymbolTable.hpp>
   9 #include <cmajor/symbols/SymbolWriter.hpp>
  10 #include <cmajor/symbols/SymbolReader.hpp>
  11 #include <cmajor/symbols/Exception.hpp>
  12 #include <cmajor/symbols/SymbolCollector.hpp>
  13 #include <cmajor/symbols/Module.hpp>
  14 #include <cmajor/symbols/GlobalFlags.hpp>
  15 #include <soulng/util/Unicode.hpp>
  16 #include <boost/uuid/uuid_io.hpp>
  17 
  18 namespace cmajor { namespace symbols {
  19 
  20 using namespace soulng::unicode;
  21 
  22 DelegateTypeSymbol::DelegateTypeSymbol(const Span& span_const boost::uuids::uuid& sourceModuleId_const std::u32string& name_) :
  23     TypeSymbol(SymbolType::delegateTypeSymbolspan_sourceModuleId_name_)returnType()parameters()
  24 {
  25 }
  26 
  27 void DelegateTypeSymbol::Write(SymbolWriter& writer)
  28 {
  29     TypeSymbol::Write(writer);
  30     const boost::uuids::uuid& returnTypeId = returnType->TypeId();
  31     writer.GetBinaryWriter().Write(returnTypeId);
  32     bool hasReturnParam = returnParam != nullptr;
  33     writer.GetBinaryWriter().Write(hasReturnParam);
  34     if (hasReturnParam)
  35     {
  36         writer.Write(returnParam.get());
  37     }
  38 }
  39 
  40 void DelegateTypeSymbol::Read(SymbolReader& reader)
  41 {
  42     TypeSymbol::Read(reader);
  43     boost::uuids::uuid returnTypeId;
  44     reader.GetBinaryReader().ReadUuid(returnTypeId);
  45     reader.GetSymbolTable()->EmplaceTypeRequest(readerthisreturnTypeId0);
  46     bool hasReturnParam = reader.GetBinaryReader().ReadBool();
  47     if (hasReturnParam)
  48     {
  49         returnParam.reset(reader.ReadParameterSymbol(this));
  50     }
  51 }
  52 
  53 void DelegateTypeSymbol::EmplaceType(TypeSymbol* typeSymbolint index)
  54 {
  55     Assert(index == 0"invalid emplace type index");
  56     returnType = typeSymbol;
  57 }
  58 
  59 void DelegateTypeSymbol::AddMember(Symbol* member)
  60 {
  61     TypeSymbol::AddMember(member);
  62     if (member->GetSymbolType() == SymbolType::parameterSymbol)
  63     {
  64         parameters.push_back(static_cast<ParameterSymbol*>(member));
  65     }
  66 }
  67 
  68 std::string DelegateTypeSymbol::Syntax() const
  69 {
  70     std::string syntax = GetSpecifierStr();
  71     if (!syntax.empty())
  72     {
  73         syntax.append(1' ');
  74     }
  75     syntax.append("delegate ");
  76     syntax.append(ToUtf8(ReturnType()->DocName()));
  77     syntax.append(1' ');
  78     syntax.append(ToUtf8(DocName()));
  79     syntax.append(1'(');
  80     bool first = true;
  81     for (ParameterSymbol* param : parameters)
  82     {
  83         if (first)
  84         {
  85             first = false;
  86         }
  87         else
  88         {
  89             syntax.append(", ");
  90         }
  91         syntax.append(ToUtf8(param->GetType()->DocName()));
  92         syntax.append(1' ');
  93         syntax.append(ToUtf8(param->DocName()));
  94     }
  95     syntax.append(");");
  96     return syntax;
  97 }
  98 
  99 std::u32string DelegateTypeSymbol::Id() const
 100 {
 101     return MangledName();
 102 }
 103 
 104 void DelegateTypeSymbol::Accept(SymbolCollector* collector)
 105 {
 106     if (IsProject() && Access() == SymbolAccess::public_)
 107     {
 108         collector->AddDelegate(this);
 109     }
 110 }
 111 
 112 void DelegateTypeSymbol::Dump(CodeFormatter& formatter)
 113 {
 114     formatter.WriteLine(ToUtf8(Name()));
 115     formatter.WriteLine("full name: " + ToUtf8(FullNameWithSpecifiers()));
 116     formatter.WriteLine("typeid: " + boost::uuids::to_string(TypeId()));
 117 }
 118 
 119 void* DelegateTypeSymbol::IrType(Emitter& emitter)
 120 {
 121     void* localIrType = emitter.GetIrTypeByTypeId(TypeId());
 122     if (!localIrType)
 123     {
 124         void* retType = emitter.GetIrTypeForVoid();
 125         if (!returnType->IsVoidType() && !ReturnsClassInterfaceOrClassDelegateByValue())
 126         {
 127             retType = returnType->IrType(emitter);
 128         }
 129         std::vector<void*> paramTypes;
 130         int np = parameters.size();
 131         for (int i = 0; i < np; ++i)
 132         {
 133             ParameterSymbol* parameter = parameters[i];
 134             paramTypes.push_back(parameter->GetType()->IrType(emitter));
 135         }
 136         if (returnParam)
 137         {
 138             paramTypes.push_back(returnParam->GetType()->IrType(emitter));
 139         }
 140         localIrType = emitter.GetIrTypeForDelegateType(retTypeparamTypes);
 141         emitter.SetIrTypeByTypeId(TypeId()localIrType);
 142     }
 143     return localIrType;
 144 }
 145 
 146 void* DelegateTypeSymbol::CreateDefaultIrValue(Emitter& emitter)
 147 {
 148     return emitter.CreateDefaultIrValueForDelegateType(IrType(emitter));
 149 }
 150 
 151 void DelegateTypeSymbol::SetSpecifiers(Specifiers specifiers)
 152 {
 153     Specifiers accessSpecifiers = specifiers & Specifiers::access_;
 154     SetAccess(accessSpecifiers);
 155     if ((specifiers & Specifiers::static_) != Specifiers::none)
 156     {
 157         throw Exception("delegate cannot be static"GetSpan()SourceModuleId());
 158     }
 159     if ((specifiers & Specifiers::virtual_) != Specifiers::none)
 160     {
 161         throw Exception("delegate cannot be virtual"GetSpan()SourceModuleId());
 162     }
 163     if ((specifiers & Specifiers::override_) != Specifiers::none)
 164     {
 165         throw Exception("delegate cannot be override"GetSpan()SourceModuleId());
 166     }
 167     if ((specifiers & Specifiers::abstract_) != Specifiers::none)
 168     {
 169         throw Exception("delegate cannot be abstract"GetSpan()SourceModuleId());
 170     }
 171     if ((specifiers & Specifiers::inline_) != Specifiers::none)
 172     {
 173         throw Exception("delegate cannot be inline"GetSpan()SourceModuleId());
 174     }
 175     if ((specifiers & Specifiers::explicit_) != Specifiers::none)
 176     {
 177         throw Exception("delegate cannot be explicit"GetSpan()SourceModuleId());
 178     }
 179     if ((specifiers & Specifiers::external_) != Specifiers::none)
 180     {
 181         throw Exception("delegate cannot be external"GetSpan()SourceModuleId());
 182     }
 183     if ((specifiers & Specifiers::suppress_) != Specifiers::none)
 184     {
 185         throw Exception("delegate cannot be suppressed"GetSpan()SourceModuleId());
 186     }
 187     if ((specifiers & Specifiers::default_) != Specifiers::none)
 188     {
 189         throw Exception("delegate cannot be default"GetSpan()SourceModuleId());
 190     }
 191     if ((specifiers & Specifiers::constexpr_) != Specifiers::none)
 192     {
 193         throw Exception("delegate cannot be constexpr"GetSpan()SourceModuleId());
 194     }
 195     if ((specifiers & Specifiers::cdecl_) != Specifiers::none)
 196     {
 197         throw Exception("delegate cannot be cdecl"GetSpan()SourceModuleId());
 198     }
 199     if ((specifiers & Specifiers::nothrow_) != Specifiers::none)
 200     {
 201         SetNothrow();
 202     }
 203     if ((specifiers & Specifiers::throw_) != Specifiers::none)
 204     {
 205         if (IsNothrow())
 206         {
 207             throw Exception("delegate cannot be throw and nothrow at the same time"GetSpan()SourceModuleId());
 208         }
 209     }
 210     if ((specifiers & Specifiers::new_) != Specifiers::none)
 211     {
 212         throw Exception("delegate cannot be new"GetSpan()SourceModuleId());
 213     }
 214     if ((specifiers & Specifiers::const_) != Specifiers::none)
 215     {
 216         throw Exception("delegate cannot be const"GetSpan()SourceModuleId());
 217     }
 218     if ((specifiers & Specifiers::unit_test_) != Specifiers::none)
 219     {
 220         throw Exception("delegate cannot be unit_test"GetSpan()SourceModuleId());
 221     }
 222 }
 223 
 224 bool DelegateTypeSymbol::ReturnsClassInterfaceOrClassDelegateByValue() const
 225 {
 226     return returnType->IsClassTypeSymbol() || returnType->GetSymbolType() == SymbolType::classDelegateTypeSymbol || returnType->GetSymbolType() == SymbolType::interfaceTypeSymbol;
 227 }
 228 
 229 void DelegateTypeSymbol::SetReturnParam(ParameterSymbol* returnParam_)
 230 {
 231     returnParam.reset(returnParam_);
 232 }
 233 
 234 void DelegateTypeSymbol::GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId)
 235 {
 236     void* callee = nullptr;
 237     int na = genObjects.size();
 238     for (int i = 0; i < na; ++i)
 239     {
 240         GenObject* genObject = genObjects[i];
 241         genObject->Load(emitterflags & OperationFlags::functionCallFlags);
 242         if (i == 0)
 243         {
 244             callee = emitter.Stack().Pop();
 245         }
 246     }
 247     std::vector<void*> args;
 248     int n = parameters.size();
 249     if (ReturnsClassInterfaceOrClassDelegateByValue())
 250     {
 251         ++n;
 252     }
 253     args.resize(n);
 254     for (int i = 0; i < n; ++i)
 255     {
 256         void* arg = emitter.Stack().Pop();
 257         args[n - i - 1] = arg;
 258     }
 259     emitter.SetCurrentDebugLocation(span);
 260     void* handlerBlock = emitter.HandlerBlock();
 261     void* cleanupBlock = emitter.CleanupBlock();
 262     bool newCleanupNeeded = emitter.NewCleanupNeeded();
 263     Pad* currentPad = emitter.CurrentPad();
 264     std::vector<void*> bundles;
 265     if (currentPad != nullptr)
 266     {
 267         bundles.push_back(currentPad->value);
 268     }
 269     if (returnType->GetSymbolType() != SymbolType::voidTypeSymbol && !ReturnsClassInterfaceOrClassDelegateByValue())
 270     {
 271         if (IsNothrow() || (!handlerBlock && !cleanupBlock && !newCleanupNeeded))
 272         {
 273             if (currentPad == nullptr)
 274             {
 275                 emitter.Stack().Push(emitter.CreateCall(calleeargs));
 276             }
 277             else
 278             {
 279                 void* callInst = emitter.CreateCallInst(calleeargsbundlesspan);
 280                 emitter.Stack().Push(callInst);
 281             }
 282         }
 283         else
 284         {
 285             void* nextBlock = nullptr;
 286             if (GetBackEnd() == BackEnd::llvm || GetBackEnd() == BackEnd::cmcpp)
 287             {
 288                 nextBlock = emitter.CreateBasicBlock("next");
 289             }
 290             if (newCleanupNeeded)
 291             {
 292                 emitter.CreateCleanup();
 293                 cleanupBlock = emitter.CleanupBlock();
 294             }
 295             void* unwindBlock = cleanupBlock;
 296             if (unwindBlock == nullptr)
 297             {
 298                 unwindBlock = handlerBlock;
 299                 Assert(unwindBlock"no unwind block");
 300             }
 301             if (currentPad == nullptr)
 302             {
 303                 emitter.Stack().Push(emitter.CreateInvoke(calleenextBlockunwindBlockargs));
 304             }
 305             else
 306             {
 307                 void* invokeInst = emitter.CreateInvokeInst(calleenextBlockunwindBlockargsbundlesspan);
 308                 emitter.Stack().Push(invokeInst);
 309             }
 310             if (GetBackEnd() == BackEnd::llvm || GetBackEnd() == BackEnd::cmcpp)
 311             {
 312                 emitter.SetCurrentBasicBlock(nextBlock);
 313             }
 314         }
 315     }
 316     else
 317     {
 318         if (IsNothrow() || (!handlerBlock && !cleanupBlock && !newCleanupNeeded))
 319         {
 320             if (currentPad == nullptr)
 321             {
 322                 emitter.CreateCall(calleeargs);
 323             }
 324             else
 325             {
 326                 emitter.CreateCallInst(calleeargsbundlesspan);
 327             }
 328         }
 329         else
 330         {
 331             void* nextBlock = nullptr;
 332             if (GetBackEnd() == BackEnd::llvm || GetBackEnd() == BackEnd::cmcpp)
 333             {
 334                 nextBlock = emitter.CreateBasicBlock("next");
 335             }
 336             if (newCleanupNeeded)
 337             {
 338                 emitter.CreateCleanup();
 339                 cleanupBlock = emitter.CleanupBlock();
 340             }
 341             void* unwindBlock = cleanupBlock;
 342             if (unwindBlock == nullptr)
 343             {
 344                 unwindBlock = handlerBlock;
 345                 Assert(unwindBlock"no unwind block");
 346             }
 347             if (currentPad == nullptr)
 348             {
 349                 emitter.CreateInvoke(calleenextBlockunwindBlockargs);
 350             }
 351             else
 352             {
 353                 emitter.CreateInvokeInst(calleenextBlockunwindBlockargsbundlesspan);
 354             }
 355             if (GetBackEnd() == BackEnd::llvm || GetBackEnd() == BackEnd::cmcpp)
 356             {
 357                 emitter.SetCurrentBasicBlock(nextBlock);
 358             }
 359         }
 360     }
 361 }
 362 
 363 void DelegateTypeSymbol::Check()
 364 {
 365     TypeSymbol::Check();
 366     if (!returnType)
 367     {
 368         throw SymbolCheckException("delegate type symbol has no return type"GetSpan()SourceModuleId());
 369     }
 370 }
 371 
 372 std::string DelegateTypeSymbol::GetSymbolHelp() const
 373 {
 374     std::string help = "(";
 375     help.append(GetSymbolCategoryDescription()).append(") ");
 376     help.append(ToUtf8(ReturnType()->FullName())).append(" ").append(ToUtf8(FullName())).append("(");
 377     bool first = true;
 378     for (ParameterSymbol* param : parameters)
 379     {
 380         if (first)
 381         {
 382             first = false;
 383         }
 384         else
 385         {
 386             help.append(", ");
 387         }
 388         help.append(ToUtf8(param->GetType()->FullName())).append(" ").append(ToUtf8(param->Name()));
 389     }
 390     help.append(")");
 391     return help;
 392 }
 393 
 394 DelegateTypeDefaultConstructor::DelegateTypeDefaultConstructor(const Span& span_const boost::uuids::uuid& sourceModuleId_const std::u32string& name_) :
 395     FunctionSymbol(SymbolType::delegateTypeDefaultConstructorspan_sourceModuleId_name_)
 396 {
 397 }
 398 
 399 DelegateTypeDefaultConstructor::DelegateTypeDefaultConstructor(DelegateTypeSymbol* delegateType_) :
 400     FunctionSymbol(SymbolType::delegateTypeDefaultConstructordelegateType_->GetSpan()delegateType_->SourceModuleId()U"@constructor")delegateType(delegateType_)
 401 {
 402     SetGroupName(U"@constructor");
 403     SetAccess(SymbolAccess::public_);
 404     ParameterSymbol* thisParam = new ParameterSymbol(delegateType->GetSpan()delegateType->SourceModuleId()U"this");
 405     thisParam->SetType(delegateType->AddPointer(Span()boost::uuids::nil_uuid()));
 406     AddMember(thisParam);
 407     ComputeName();
 408 }
 409 
 410 void DelegateTypeDefaultConstructor::Write(SymbolWriter& writer)
 411 {
 412     FunctionSymbol::Write(writer);
 413     writer.GetBinaryWriter().Write(delegateType->TypeId());
 414 }
 415 
 416 void DelegateTypeDefaultConstructor::Read(SymbolReader& reader)
 417 {
 418     FunctionSymbol::Read(reader);
 419     boost::uuids::uuid typeId;
 420     reader.GetBinaryReader().ReadUuid(typeId);
 421     reader.GetSymbolTable()->EmplaceTypeRequest(readerthistypeId1);
 422 }
 423 
 424 void DelegateTypeDefaultConstructor::EmplaceType(TypeSymbol* typeSymbolint index)
 425 {
 426     if (index == 1)
 427     {
 428         Assert(typeSymbol->GetSymbolType() == SymbolType::delegateTypeSymbol"delegate type symbol expected");
 429         delegateType = static_cast<DelegateTypeSymbol*>(typeSymbol);
 430     }
 431     else
 432     {
 433         FunctionSymbol::EmplaceType(typeSymbolindex);
 434     }
 435 }
 436 
 437 void DelegateTypeDefaultConstructor::GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId)
 438 {
 439     Assert(genObjects.size() == 1"default constructor needs one object");
 440     emitter.Stack().Push(delegateType->CreateDefaultIrValue(emitter));
 441     genObjects[0]->Store(emitterOperationFlags::none);
 442 }
 443 
 444 void DelegateTypeDefaultConstructor::Check()
 445 {
 446     FunctionSymbol::Check();
 447     if (!delegateType)
 448     {
 449         throw SymbolCheckException("delegate type default constructor has no delegate type"GetSpan()SourceModuleId());
 450     }
 451 }
 452 
 453 DelegateTypeCopyConstructor::DelegateTypeCopyConstructor(const Span& span_const boost::uuids::uuid& sourceModuleId_const std::u32string& name_) :
 454     FunctionSymbol(SymbolType::delegateTypeCopyConstructorspan_sourceModuleId_name_)
 455 {
 456 }
 457 
 458 DelegateTypeCopyConstructor::DelegateTypeCopyConstructor(DelegateTypeSymbol* delegateType) : FunctionSymbol(SymbolType::delegateTypeCopyConstructor
 459     delegateType->GetSpan()delegateType->SourceModuleId()U"@constructor")
 460 {
 461     SetGroupName(U"@constructor");
 462     SetAccess(SymbolAccess::public_);
 463     ParameterSymbol* thisParam = new ParameterSymbol(delegateType->GetSpan()delegateType->SourceModuleId()U"this");
 464     thisParam->SetType(delegateType->AddPointer(Span()boost::uuids::nil_uuid()));
 465     AddMember(thisParam);
 466     ParameterSymbol* thatParam = new ParameterSymbol(delegateType->GetSpan()delegateType->SourceModuleId()U"that");
 467     thatParam->SetType(delegateType);
 468     AddMember(thatParam);
 469     ComputeName();
 470 }
 471 
 472 void DelegateTypeCopyConstructor::GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId)
 473 {
 474     Assert(genObjects.size() == 2"copy constructor needs two objects");
 475     genObjects[1]->Load(emitterOperationFlags::none);
 476     genObjects[0]->Store(emitterOperationFlags::none);
 477 }
 478 
 479 DelegateTypeMoveConstructor::DelegateTypeMoveConstructor(const Span& span_const boost::uuids::uuid& sourceModuleId_const std::u32string& name_) :
 480     FunctionSymbol(SymbolType::delegateTypeMoveConstructorspan_sourceModuleId_name_)
 481 {
 482 }
 483 
 484 DelegateTypeMoveConstructor::DelegateTypeMoveConstructor(DelegateTypeSymbol* delegateType) :
 485     FunctionSymbol(SymbolType::delegateTypeMoveConstructordelegateType->GetSpan()delegateType->SourceModuleId()U"@constructor")
 486 {
 487     SetGroupName(U"@constructor");
 488     SetAccess(SymbolAccess::public_);
 489     ParameterSymbol* thisParam = new ParameterSymbol(delegateType->GetSpan()delegateType->SourceModuleId()U"this");
 490     thisParam->SetType(delegateType->AddPointer(Span()boost::uuids::nil_uuid()));
 491     AddMember(thisParam);
 492     ParameterSymbol* thatParam = new ParameterSymbol(delegateType->GetSpan()delegateType->SourceModuleId()U"that");
 493     thatParam->SetType(delegateType->AddRvalueReference(Span()boost::uuids::nil_uuid()));
 494     AddMember(thatParam);
 495     ComputeName();
 496 }
 497 
 498 void DelegateTypeMoveConstructor::GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId)
 499 {
 500     Assert(genObjects.size() == 2"move constructor needs two objects");
 501     genObjects[1]->Load(emitterOperationFlags::none);
 502     void* rvalueRefValue = emitter.Stack().Pop();
 503     emitter.Stack().Push(emitter.CreateLoad(rvalueRefValue));
 504     genObjects[0]->Store(emitterOperationFlags::none);
 505 }
 506 
 507 DelegateTypeCopyAssignment::DelegateTypeCopyAssignment(const Span& span_const boost::uuids::uuid& sourceModuleId_const std::u32string& name_) :
 508     FunctionSymbol(SymbolType::delegateTypeCopyAssignmentspan_sourceModuleId_name_)
 509 {
 510 }
 511 
 512 DelegateTypeCopyAssignment::DelegateTypeCopyAssignment(DelegateTypeSymbol* delegateTypeTypeSymbol* voidType) :
 513     FunctionSymbol(SymbolType::delegateTypeCopyAssignmentdelegateType->GetSpan()delegateType->SourceModuleId()U"operator=")
 514 {
 515     SetGroupName(U"operator=");
 516     SetAccess(SymbolAccess::public_);
 517     ParameterSymbol* thisParam = new ParameterSymbol(delegateType->GetSpan()delegateType->SourceModuleId()U"this");
 518     thisParam->SetType(delegateType->AddPointer(Span()boost::uuids::nil_uuid()));
 519     AddMember(thisParam);
 520     ParameterSymbol* thatParam = new ParameterSymbol(delegateType->GetSpan()delegateType->SourceModuleId()U"that");
 521     thatParam->SetType(delegateType);
 522     AddMember(thatParam);
 523     SetReturnType(voidType);
 524     ComputeName();
 525 }
 526 
 527 void DelegateTypeCopyAssignment::GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId)
 528 {
 529     Assert(genObjects.size() == 2"copy assignment needs two objects");
 530     genObjects[1]->Load(emitterOperationFlags::none);
 531     genObjects[0]->Store(emitterOperationFlags::none);
 532 }
 533 
 534 DelegateTypeMoveAssignment::DelegateTypeMoveAssignment(const Span& span_const boost::uuids::uuid& sourceModuleId_const std::u32string& name_) :
 535     FunctionSymbol(SymbolType::delegateTypeMoveAssignmentspan_sourceModuleId_name_)
 536 {
 537 }
 538 
 539 DelegateTypeMoveAssignment::DelegateTypeMoveAssignment(DelegateTypeSymbol* delegateTypeTypeSymbol* voidType) :
 540     FunctionSymbol(SymbolType::delegateTypeMoveAssignmentdelegateType->GetSpan()delegateType->SourceModuleId()U"operator=")
 541 {
 542     SetGroupName(U"operator=");
 543     SetAccess(SymbolAccess::public_);
 544     ParameterSymbol* thisParam = new ParameterSymbol(delegateType->GetSpan()delegateType->SourceModuleId()U"this");
 545     thisParam->SetType(delegateType->AddPointer(Span()boost::uuids::nil_uuid()));
 546     AddMember(thisParam);
 547     ParameterSymbol* thatParam = new ParameterSymbol(delegateType->GetSpan()delegateType->SourceModuleId()U"that");
 548     thatParam->SetType(delegateType->AddRvalueReference(Span()boost::uuids::nil_uuid()));
 549     AddMember(thatParam);
 550     SetReturnType(voidType);
 551     ComputeName();
 552 }
 553 
 554 void DelegateTypeMoveAssignment::GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId)
 555 {
 556     Assert(genObjects.size() == 2"move assignment needs two objects");
 557     genObjects[1]->Load(emitterOperationFlags::none);
 558     void* rvalueRefValue = emitter.Stack().Pop();
 559     emitter.Stack().Push(emitter.CreateLoad(rvalueRefValue));
 560     genObjects[0]->Store(emitterOperationFlags::none);
 561 }
 562 
 563 DelegateTypeReturn::DelegateTypeReturn(const Span& span_const boost::uuids::uuid& sourceModuleId_const std::u32string& name_) :
 564     FunctionSymbol(SymbolType::delegateTypeReturnspan_sourceModuleId_name_)
 565 {
 566 }
 567 
 568 DelegateTypeReturn::DelegateTypeReturn(DelegateTypeSymbol* delegateType) : FunctionSymbol(SymbolType::delegateTypeReturndelegateType->GetSpan()delegateType->SourceModuleId()U"@return")
 569 {
 570     SetGroupName(U"@return");
 571     ParameterSymbol* valueParam = new ParameterSymbol(delegateType->GetSpan()delegateType->SourceModuleId()U"value");
 572     valueParam->SetType(delegateType);
 573     AddMember(valueParam);
 574     SetReturnType(delegateType);
 575     ComputeName();
 576 }
 577 
 578 void DelegateTypeReturn::GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId)
 579 {
 580     Assert(genObjects.size() == 1"return needs one object");
 581     genObjects[0]->Load(emitterOperationFlags::none);
 582 }
 583 
 584 DelegateTypeEquality::DelegateTypeEquality(const Span& span_const boost::uuids::uuid& sourceModuleId_const std::u32string& name_) :
 585     FunctionSymbol(SymbolType::delegateTypeEqualityspan_sourceModuleId_name_)
 586 {
 587 }
 588 
 589 DelegateTypeEquality::DelegateTypeEquality(DelegateTypeSymbol* delegateTypeTypeSymbol* boolType)
 590     : FunctionSymbol(SymbolType::delegateTypeEqualitydelegateType->GetSpan()delegateType->SourceModuleId()U"operator==")
 591 {
 592     SetGroupName(U"operator==");
 593     SetAccess(SymbolAccess::public_);
 594     ParameterSymbol* leftParam = new ParameterSymbol(delegateType->GetSpan()delegateType->SourceModuleId()U"left");
 595     leftParam->SetType(delegateType);
 596     AddMember(leftParam);
 597     ParameterSymbol* rightParam = new ParameterSymbol(delegateType->GetSpan()delegateType->SourceModuleId()U"right");
 598     rightParam->SetType(delegateType);
 599     AddMember(rightParam);
 600     SetReturnType(boolType);
 601     ComputeName();
 602 }
 603 
 604 void DelegateTypeEquality::GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId)
 605 {
 606     Assert(genObjects.size() == 2"operator== needs two objects");
 607     genObjects[0]->Load(emitterOperationFlags::none);
 608     void* left = emitter.Stack().Pop();
 609     genObjects[1]->Load(emitterOperationFlags::none);
 610     void* right = emitter.Stack().Pop();
 611     emitter.Stack().Push(emitter.CreateICmpEQ(leftright));
 612 }
 613 
 614 FunctionToDelegateConversion::FunctionToDelegateConversion(const Span& span_const boost::uuids::uuid& sourceModuleId_const std::u32string& name_) :
 615     FunctionSymbol(SymbolType::functionToDelegateSymbolspan_sourceModuleId_name_)sourceType(nullptr)targetType(nullptr)function(nullptr)
 616 {
 617 }
 618 
 619 FunctionToDelegateConversion::FunctionToDelegateConversion(TypeSymbol* sourceType_TypeSymbol* targetType_FunctionSymbol* function_) :
 620     FunctionSymbol(SymbolType::functionToDelegateSymbolfunction_->GetSpan()function_->SourceModuleId()U"@conversion")sourceType(sourceType_)targetType(targetType_)function(function_)
 621 {
 622     SetConversion();
 623     SetConversionSourceType(sourceType->PlainType(GetSpan()SourceModuleId()));
 624     SetConversionTargetType(targetType->PlainType(GetSpan()SourceModuleId()));
 625 }
 626 
 627 void FunctionToDelegateConversion::GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId)
 628 {
 629     emitter.Stack().Pop();
 630     emitter.Stack().Push(emitter.GetOrInsertFunction(ToUtf8(function->MangledName())function->IrType(emitter)function->DontThrow()));
 631 }
 632 
 633 void FunctionToDelegateConversion::Check()
 634 {
 635     FunctionSymbol::Check();
 636     if (!sourceType)
 637     {
 638         throw SymbolCheckException("function to delegate conversion has no source type"GetSpan()SourceModuleId());
 639     }
 640     if (!targetType)
 641     {
 642         throw SymbolCheckException("function to delegate conversion has no target type"GetSpan()SourceModuleId());
 643     }
 644     if (!function)
 645     {
 646         throw SymbolCheckException("function to delegate conversion has no function"GetSpan()SourceModuleId());
 647     }
 648 }
 649 
 650 DelegateToVoidPtrConversion::DelegateToVoidPtrConversion(TypeSymbol* delegateType_TypeSymbol* voidPtrType_) :
 651     FunctionSymbol(delegateType_->GetSpan()delegateType_->SourceModuleId()U"dlg2voidptr")delegateType(delegateType_)voidPtrType(voidPtrType_)
 652 {
 653     SetConversion();
 654     SetGroupName(U"@conversion");
 655     SetAccess(SymbolAccess::public_);
 656     SetConversionSourceType(delegateType->PlainType(GetSpan()SourceModuleId()));
 657     SetConversionTargetType(voidPtrType->PlainType(GetSpan()SourceModuleId()));
 658 }
 659 
 660 void DelegateToVoidPtrConversion::GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId)
 661 {
 662     emitter.SetCurrentDebugLocation(span);
 663     void* value = emitter.Stack().Pop();
 664     emitter.Stack().Push(emitter.CreateBitCast(valuevoidPtrType->IrType(emitter)));
 665 }
 666 
 667 VoidPtrToDelegateConversion::VoidPtrToDelegateConversion(TypeSymbol* voidPtrType_TypeSymbol* delegateType_TypeSymbol* ulongType_) :
 668     FunctionSymbol(delegateType_->GetSpan()delegateType_->SourceModuleId()U"voidptr2dlg")voidPtrType(voidPtrType_)delegateType(delegateType_)ulongType(ulongType_)
 669 {
 670     SetConversion();
 671     SetGroupName(U"@conversion");
 672     SetAccess(SymbolAccess::public_);
 673     SetConversionSourceType(delegateType->PlainType(GetSpan()SourceModuleId()));
 674     SetConversionTargetType(voidPtrType->PlainType(GetSpan()SourceModuleId()));
 675 }
 676 
 677 void VoidPtrToDelegateConversion::GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId)
 678 {
 679     emitter.SetCurrentDebugLocation(span);
 680     void* value = emitter.Stack().Pop();
 681     void* ulongValue = emitter.CreatePtrToInt(valueulongType->IrType(emitter));
 682     emitter.Stack().Push(emitter.CreateIntToPtr(ulongValuedelegateType->IrType(emitter)));
 683 }
 684 
 685 ClassDelegateTypeSymbol::ClassDelegateTypeSymbol(const Span& span_const boost::uuids::uuid& sourceModuleId_const std::u32string& name_) :
 686     TypeSymbol(SymbolType::classDelegateTypeSymbolspan_sourceModuleId_name_)returnType(nullptr)parameters()delegateType(nullptr)objectDelegatePairType(nullptr)
 687     copyConstructor(nullptr)
 688 {
 689 }
 690 
 691 void ClassDelegateTypeSymbol::Write(SymbolWriter& writer)
 692 {
 693     TypeSymbol::Write(writer);
 694     const boost::uuids::uuid& returnTypeId = returnType->TypeId();
 695     writer.GetBinaryWriter().Write(returnTypeId);
 696 }
 697 
 698 void ClassDelegateTypeSymbol::Read(SymbolReader& reader)
 699 {
 700     TypeSymbol::Read(reader);
 701     boost::uuids::uuid returnTypeId;
 702     reader.GetBinaryReader().ReadUuid(returnTypeId);
 703     reader.GetSymbolTable()->EmplaceTypeRequest(readerthisreturnTypeId-1);
 704 }
 705 
 706 void ClassDelegateTypeSymbol::EmplaceType(TypeSymbol* typeSymbolint index)
 707 {
 708     if (index == -1)
 709     {
 710         returnType = typeSymbol;
 711     }
 712     else
 713     {
 714         TypeSymbol::EmplaceType(typeSymbolindex);
 715     }
 716 }
 717 
 718 void ClassDelegateTypeSymbol::AddMember(Symbol* member)
 719 {
 720     TypeSymbol::AddMember(member);
 721     if (member->GetSymbolType() == SymbolType::parameterSymbol)
 722     {
 723         parameters.push_back(static_cast<ParameterSymbol*>(member));
 724     }
 725     else if (member->GetSymbolType() == SymbolType::delegateTypeSymbol)
 726     {
 727         delegateType = static_cast<DelegateTypeSymbol*>(member);
 728     }
 729     else if (member->GetSymbolType() == SymbolType::classTypeSymbol)
 730     {
 731         objectDelegatePairType = static_cast<ClassTypeSymbol*>(member);
 732     }
 733     else if (member->IsFunctionSymbol())
 734     {
 735         FunctionSymbol* functionSymbol = static_cast<FunctionSymbol*>(member);
 736         if (functionSymbol->IsClassDelegateCopyConstructor())
 737         {
 738             copyConstructor = functionSymbol;
 739         }
 740     }
 741 }
 742 
 743 std::string ClassDelegateTypeSymbol::Syntax() const
 744 {
 745     std::string syntax = GetSpecifierStr();
 746     if (!syntax.empty())
 747     {
 748         syntax.append(1' ');
 749     }
 750     syntax.append("class delegate ");
 751     syntax.append(ToUtf8(ReturnType()->DocName()));
 752     syntax.append(1' ');
 753     syntax.append(ToUtf8(DocName()));
 754     syntax.append(1'(');
 755     bool first = true;
 756     for (ParameterSymbol* param : parameters)
 757     {
 758         if (first)
 759         {
 760             first = false;
 761         }
 762         else
 763         {
 764             syntax.append(", ");
 765         }
 766         syntax.append(ToUtf8(param->GetType()->DocName()));
 767         syntax.append(1' ');
 768         syntax.append(ToUtf8(param->DocName()));
 769     }
 770     syntax.append(");");
 771     return syntax;
 772 }
 773 
 774 std::string ClassDelegateTypeSymbol::GetSymbolHelp() const
 775 {
 776     std::string help = "(";
 777     help.append(GetSymbolCategoryDescription()).append(") ");
 778     help.append(ToUtf8(ReturnType()->FullName())).append(" ").append(ToUtf8(FullName())).append("(");
 779     bool first = true;
 780     for (ParameterSymbol* param : parameters)
 781     {
 782         if (first)
 783         {
 784             first = false;
 785         }
 786         else
 787         {
 788             help.append(", ");
 789         }
 790         help.append(ToUtf8(param->GetType()->FullName())).append(" ").append(ToUtf8(param->Name()));
 791     }
 792     help.append(")");
 793     return help;
 794 }
 795 
 796 std::u32string ClassDelegateTypeSymbol::Id() const
 797 {
 798     return MangledName();
 799 }
 800 
 801 void ClassDelegateTypeSymbol::Accept(SymbolCollector* collector)
 802 {
 803     if (IsProject() && Access() == SymbolAccess::public_)
 804     {
 805         collector->AddClassDelegate(this);
 806     }
 807 }
 808 
 809 void ClassDelegateTypeSymbol::Dump(CodeFormatter& formatter)
 810 {
 811     formatter.WriteLine(ToUtf8(Name()));
 812     formatter.WriteLine("full name: " + ToUtf8(FullNameWithSpecifiers()));
 813     formatter.WriteLine("typeid: " + boost::uuids::to_string(TypeId()));
 814 }
 815 
 816 void* ClassDelegateTypeSymbol::IrType(Emitter& emitter)
 817 {
 818     void* localIrType = emitter.GetIrTypeByTypeId(TypeId());
 819     if (!localIrType)
 820     {
 821         std::vector<void*> elementTypes;
 822         elementTypes.push_back(emitter.GetIrTypeForVoidPtrType());
 823         elementTypes.push_back(delegateType->IrType(emitter));
 824         localIrType = emitter.GetIrTypeForStructType(elementTypes);
 825         emitter.SetIrTypeByTypeId(TypeId()localIrType);
 826     }
 827     return localIrType;
 828 }
 829 
 830 void* ClassDelegateTypeSymbol::CreateDefaultIrValue(Emitter& emitter)
 831 {
 832     std::vector<void*> constants;
 833     constants.push_back(emitter.CreateDefaultIrValueForVoidPtrType());
 834     constants.push_back(delegateType->CreateDefaultIrValue(emitter));
 835     return emitter.CreateDefaultIrValueForStruct(IrType(emitter)constants);
 836 }
 837 
 838 bool ClassDelegateTypeSymbol::ReturnsClassInterfaceOrClassDelegateByValue() const
 839 {
 840     return returnType->IsClassTypeSymbol() || returnType->GetSymbolType() == SymbolType::classDelegateTypeSymbol || returnType->GetSymbolType() == SymbolType::interfaceTypeSymbol;
 841 }
 842 
 843 void ClassDelegateTypeSymbol::SetReturnParam(ParameterSymbol* returnParam_)
 844 {
 845     returnParam.reset(returnParam_);
 846 }
 847 
 848 void ClassDelegateTypeSymbol::SetSpecifiers(Specifiers specifiers)
 849 {
 850     Specifiers accessSpecifiers = specifiers & Specifiers::access_;
 851     SetAccess(accessSpecifiers);
 852     if ((specifiers & Specifiers::static_) != Specifiers::none)
 853     {
 854         throw Exception("class delegate cannot be static"GetSpan()SourceModuleId());
 855     }
 856     if ((specifiers & Specifiers::virtual_) != Specifiers::none)
 857     {
 858         throw Exception("class delegate cannot be virtual"GetSpan()SourceModuleId());
 859     }
 860     if ((specifiers & Specifiers::override_) != Specifiers::none)
 861     {
 862         throw Exception("class delegate cannot be override"GetSpan()SourceModuleId());
 863     }
 864     if ((specifiers & Specifiers::abstract_) != Specifiers::none)
 865     {
 866         throw Exception("class delegate cannot be abstract"GetSpan()SourceModuleId());
 867     }
 868     if ((specifiers & Specifiers::inline_) != Specifiers::none)
 869     {
 870         throw Exception("class delegate cannot be inline"GetSpan()SourceModuleId());
 871     }
 872     if ((specifiers & Specifiers::explicit_) != Specifiers::none)
 873     {
 874         throw Exception("class delegate cannot be explicit"GetSpan()SourceModuleId());
 875     }
 876     if ((specifiers & Specifiers::external_) != Specifiers::none)
 877     {
 878         throw Exception("class delegate cannot be external"GetSpan()SourceModuleId());
 879     }
 880     if ((specifiers & Specifiers::suppress_) != Specifiers::none)
 881     {
 882         throw Exception("class delegate cannot be suppressed"GetSpan()SourceModuleId());
 883     }
 884     if ((specifiers & Specifiers::default_) != Specifiers::none)
 885     {
 886         throw Exception("class delegate cannot be default"GetSpan()SourceModuleId());
 887     }
 888     if ((specifiers & Specifiers::constexpr_) != Specifiers::none)
 889     {
 890         throw Exception("class delegate cannot be constexpr"GetSpan()SourceModuleId());
 891     }
 892     if ((specifiers & Specifiers::cdecl_) != Specifiers::none)
 893     {
 894         throw Exception("class delegate cannot be cdecl"GetSpan()SourceModuleId());
 895     }
 896     if ((specifiers & Specifiers::nothrow_) != Specifiers::none)
 897     {
 898         SetNothrow();
 899     }
 900     if ((specifiers & Specifiers::throw_) != Specifiers::none)
 901     {
 902         if (IsNothrow())
 903         {
 904             throw Exception("class delegate cannot be throw and nothrow at the same time"GetSpan()SourceModuleId());
 905         }
 906     }
 907     if ((specifiers & Specifiers::new_) != Specifiers::none)
 908     {
 909         throw Exception("class delegate cannot be new"GetSpan()SourceModuleId());
 910     }
 911     if ((specifiers & Specifiers::const_) != Specifiers::none)
 912     {
 913         throw Exception("class delegate cannot be const"GetSpan()SourceModuleId());
 914     }
 915     if ((specifiers & Specifiers::unit_test_) != Specifiers::none)
 916     {
 917         throw Exception("class delegate cannot be unit_test"GetSpan()SourceModuleId());
 918     }
 919 }
 920 
 921 void ClassDelegateTypeSymbol::GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId)
 922 {
 923     Assert(!genObjects.empty()"gen objects is empty");
 924     genObjects[0]->Load(emitterflags);
 925     void* classDelegatePtr = emitter.Stack().Pop();
 926     void* delegatePtr = emitter.GetDelegateFromClassDelegate(classDelegatePtr);
 927     void* callee = emitter.CreateLoad(delegatePtr);
 928     NativeValue calleeValue(callee);
 929     void* objectPtr = emitter.GetObjectFromClassDelegate(classDelegatePtr);
 930     void* object = emitter.CreateLoad(objectPtr);
 931     NativeValue objectValue(object);
 932     std::vector<GenObject*> classDelegateCallObjects;
 933     classDelegateCallObjects.push_back(&calleeValue);
 934     classDelegateCallObjects.push_back(&objectValue);
 935     int na = genObjects.size();
 936     for (int i = 1; i < na; ++i)
 937     {
 938         GenObject* genObject = genObjects[i];
 939         classDelegateCallObjects.push_back(genObject);
 940     }
 941     delegateType->GenerateCall(emitterclassDelegateCallObjectsflagsspanmoduleId);
 942 }
 943 
 944 void ClassDelegateTypeSymbol::Check()
 945 {
 946     TypeSymbol::Check();
 947     if (!returnType)
 948     {
 949         throw SymbolCheckException("class delegate type symbol has no return type"GetSpan()SourceModuleId());
 950     }
 951     if (!delegateType)
 952     {
 953         throw SymbolCheckException("class delegate type symbol has no delegate type"GetSpan()SourceModuleId());
 954     }
 955     if (!objectDelegatePairType)
 956     {
 957         throw SymbolCheckException("class delegate type symbol has no object delegate pair type"GetSpan()SourceModuleId());
 958     }
 959     if (!copyConstructor)
 960     {
 961         throw SymbolCheckException("class delegate type symbol has no copy constructor"GetSpan()SourceModuleId());
 962     }
 963 }
 964 
 965 ClassDelegateTypeDefaultConstructor::ClassDelegateTypeDefaultConstructor(const Span& span_const boost::uuids::uuid& sourceModuleId_const std::u32string& name_) :
 966     FunctionSymbol(SymbolType::classDelegateTypeDefaultConstructorspan_sourceModuleId_name_)
 967 {
 968 }
 969 
 970 ClassDelegateTypeDefaultConstructor::ClassDelegateTypeDefaultConstructor(ClassDelegateTypeSymbol* classDelegateType_) :
 971     FunctionSymbol(SymbolType::classDelegateTypeDefaultConstructorclassDelegateType_->GetSpan()classDelegateType_->SourceModuleId()U"@constructor")classDelegateType(classDelegateType_)
 972 {
 973     SetGroupName(U"@constructor");
 974     SetAccess(SymbolAccess::public_);
 975     ParameterSymbol* thisParam = new ParameterSymbol(classDelegateType_->GetSpan()classDelegateType_->SourceModuleId()U"this");
 976     thisParam->SetType(classDelegateType->AddPointer(Span()boost::uuids::nil_uuid()));
 977     AddMember(thisParam);
 978     ComputeName();
 979 }
 980 
 981 void ClassDelegateTypeDefaultConstructor::Write(SymbolWriter& writer)
 982 {
 983     FunctionSymbol::Write(writer);
 984     writer.GetBinaryWriter().Write(classDelegateType->TypeId());
 985 }
 986 
 987 void ClassDelegateTypeDefaultConstructor::Read(SymbolReader& reader)
 988 {
 989     FunctionSymbol::Read(reader);
 990     boost::uuids::uuid typeId;
 991     reader.GetBinaryReader().ReadUuid(typeId);
 992     reader.GetSymbolTable()->EmplaceTypeRequest(readerthistypeId1);
 993 }
 994 
 995 void ClassDelegateTypeDefaultConstructor::EmplaceType(TypeSymbol* typeSymbolint index)
 996 {
 997     if (index == 1)
 998     {
 999         Assert(typeSymbol->GetSymbolType() == SymbolType::classDelegateTypeSymbol"class delegate type symbol expected");
1000         classDelegateType = static_cast<ClassDelegateTypeSymbol*>(typeSymbol);
1001     }
1002     else
1003     {
1004         FunctionSymbol::EmplaceType(typeSymbolindex);
1005     }
1006 }
1007 
1008 void ClassDelegateTypeDefaultConstructor::GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId)
1009 {
1010     Assert(genObjects.size() == 1"default constructor needs one object");
1011     void* objectValue = emitter.CreateDefaultIrValueForVoidPtrType();
1012     genObjects[0]->Load(emitterOperationFlags::none);
1013     void* ptr = emitter.Stack().Pop();
1014     void* objectPtr = emitter.GetObjectFromClassDelegate(ptr);
1015     emitter.CreateStore(objectValueobjectPtr);
1016     void* delegateValue = classDelegateType->DelegateType()->CreateDefaultIrValue(emitter);
1017     void* delegatePtr = emitter.GetDelegateFromClassDelegate(ptr);
1018     emitter.CreateStore(delegateValuedelegatePtr);
1019 }
1020 
1021 void ClassDelegateTypeDefaultConstructor::Check()
1022 {
1023     FunctionSymbol::Check();
1024     if (!classDelegateType)
1025     {
1026         throw SymbolCheckException("class delegate type default constructor has no class delegate type"GetSpan()SourceModuleId());
1027     }
1028 }
1029 
1030 ClassDelegateTypeCopyConstructor::ClassDelegateTypeCopyConstructor(const Span& span_const boost::uuids::uuid& sourceModuleId_const std::u32string& name_) :
1031     FunctionSymbol(SymbolType::classDelegateTypeCopyConstructorspan_sourceModuleId_name_)
1032 {
1033 }
1034 
1035 ClassDelegateTypeCopyConstructor::ClassDelegateTypeCopyConstructor(ClassDelegateTypeSymbol* classDelegateType) :
1036     FunctionSymbol(SymbolType::classDelegateTypeCopyConstructorclassDelegateType->GetSpan()classDelegateType->SourceModuleId()U"@constructor")
1037 {
1038     SetGroupName(U"@constructor");
1039     SetAccess(SymbolAccess::public_);
1040     ParameterSymbol* thisParam = new ParameterSymbol(classDelegateType->GetSpan()classDelegateType->SourceModuleId()U"this");
1041     thisParam->SetType(classDelegateType->AddPointer(Span()boost::uuids::nil_uuid()));
1042     AddMember(thisParam);
1043     ParameterSymbol* thatParam = new ParameterSymbol(classDelegateType->GetSpan()classDelegateType->SourceModuleId()U"that");
1044     thatParam->SetType(classDelegateType->AddConst(Span()boost::uuids::nil_uuid())->AddLvalueReference(Span()boost::uuids::nil_uuid()));
1045     AddMember(thatParam);
1046     ComputeName();
1047 }
1048 
1049 void ClassDelegateTypeCopyConstructor::GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId)
1050 {
1051     genObjects[1]->Load(emitterOperationFlags::none);
1052     void* thatPtr = emitter.Stack().Pop();
1053     void* thatObjectPtr = emitter.GetObjectFromClassDelegate(thatPtr);
1054     void* objectValue = emitter.CreateLoad(thatObjectPtr);
1055     OperationFlags loadFlags = OperationFlags::none;
1056     if ((flags & OperationFlags::leaveFirstArg) != OperationFlags::none)
1057     {
1058         loadFlags = loadFlags | OperationFlags::leaveFirstArg;
1059     }
1060     genObjects[0]->Load(emitterloadFlags);
1061     void* thisPtr = emitter.Stack().Pop();
1062     void* thisObjectPtr = emitter.GetObjectFromClassDelegate(thisPtr);
1063     emitter.CreateStore(objectValuethisObjectPtr);
1064     void* thatDelegatePtr = emitter.GetDelegateFromClassDelegate(thatPtr);
1065     void* delegateValue = emitter.CreateLoad(thatDelegatePtr);
1066     void* thisDelegatePtr = emitter.GetDelegateFromClassDelegate(thisPtr);
1067     emitter.CreateStore(delegateValuethisDelegatePtr);
1068 }
1069 
1070 ClassDelegateTypeMoveConstructor::ClassDelegateTypeMoveConstructor(const Span& span_const boost::uuids::uuid& sourceModuleId_const std::u32string& name_) :
1071     FunctionSymbol(SymbolType::classDelegateTypeMoveConstructorspan_sourceModuleId_name_)
1072 {
1073 }
1074 
1075 ClassDelegateTypeMoveConstructor::ClassDelegateTypeMoveConstructor(ClassDelegateTypeSymbol* classDelegateType) :
1076     FunctionSymbol(SymbolType::classDelegateTypeCopyConstructorclassDelegateType->GetSpan()classDelegateType->SourceModuleId()U"@constructor")
1077 {
1078     SetGroupName(U"@constructor");
1079     SetAccess(SymbolAccess::public_);
1080     ParameterSymbol* thisParam = new ParameterSymbol(classDelegateType->GetSpan()classDelegateType->SourceModuleId()U"this");
1081     thisParam->SetType(classDelegateType->AddPointer(Span()boost::uuids::nil_uuid()));
1082     AddMember(thisParam);
1083     ParameterSymbol* thatParam = new ParameterSymbol(classDelegateType->GetSpan()classDelegateType->SourceModuleId()U"that");
1084     thatParam->SetType(classDelegateType->AddRvalueReference(Span()boost::uuids::nil_uuid()));
1085     AddMember(thatParam);
1086     ComputeName();
1087 }
1088 
1089 void ClassDelegateTypeMoveConstructor::GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId)
1090 {
1091     genObjects[1]->Load(emitterOperationFlags::none);
1092     void* thatPtr = emitter.Stack().Pop();
1093     void* thatObjectPtr = emitter.GetObjectFromClassDelegate(thatPtr);
1094     void* objectValue = emitter.CreateLoad(thatObjectPtr);
1095     OperationFlags loadFlags = OperationFlags::none;
1096     if ((flags & OperationFlags::leaveFirstArg) != OperationFlags::none)
1097     {
1098         loadFlags = loadFlags | OperationFlags::leaveFirstArg;
1099     }
1100     genObjects[0]->Load(emitterloadFlags);
1101     void* thisPtr = emitter.Stack().Pop();
1102     void* thisObjectPtr = emitter.GetObjectFromClassDelegate(thisPtr);
1103     emitter.CreateStore(objectValuethisObjectPtr);
1104     void* thatDelegatePtr = emitter.GetDelegateFromClassDelegate(thatPtr);
1105     void* delegateValue = emitter.CreateLoad(thatDelegatePtr);
1106     void* thisDelegatePtr = emitter.GetDelegateFromClassDelegate(thisPtr);
1107     emitter.CreateStore(delegateValuethisDelegatePtr);
1108 }
1109 
1110 ClassDelegateTypeCopyAssignment::ClassDelegateTypeCopyAssignment(const Span& span_const boost::uuids::uuid& sourceModuleId_const std::u32string& name_) :
1111     FunctionSymbol(SymbolType::classDelegateTypeCopyAssignmentspan_sourceModuleId_name_)
1112 {
1113 }
1114 
1115 ClassDelegateTypeCopyAssignment::ClassDelegateTypeCopyAssignment(ClassDelegateTypeSymbol* classDelegateTypeTypeSymbol* voidType) :
1116     FunctionSymbol(SymbolType::classDelegateTypeCopyAssignmentclassDelegateType->GetSpan()classDelegateType->SourceModuleId()U"operator=")
1117 {
1118     SetGroupName(U"operator=");
1119     SetAccess(SymbolAccess::public_);
1120     ParameterSymbol* thisParam = new ParameterSymbol(classDelegateType->GetSpan()classDelegateType->SourceModuleId()U"this");
1121     thisParam->SetType(classDelegateType->AddPointer(Span()boost::uuids::nil_uuid()));
1122     AddMember(thisParam);
1123     ParameterSymbol* thatParam = new ParameterSymbol(classDelegateType->GetSpan()classDelegateType->SourceModuleId()U"that");
1124     thatParam->SetType(classDelegateType->AddConst(Span()boost::uuids::nil_uuid())->AddLvalueReference(Span()boost::uuids::nil_uuid()));
1125     AddMember(thatParam);
1126     SetReturnType(voidType);
1127     ComputeName();
1128 }
1129 
1130 void ClassDelegateTypeCopyAssignment::GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId)
1131 {
1132     genObjects[1]->Load(emitterOperationFlags::none);
1133     void* thatPtr = emitter.Stack().Pop();
1134     void* thatObjectPtr = emitter.GetObjectFromClassDelegate(thatPtr);
1135     void* objectValue = emitter.CreateLoad(thatObjectPtr);
1136     genObjects[0]->Load(emitterOperationFlags::none);
1137     void* thisPtr = emitter.Stack().Pop();
1138     void* thisObjectPtr = emitter.GetObjectFromClassDelegate(thisPtr);
1139     emitter.CreateStore(objectValuethisObjectPtr);
1140     void* thatDelegatePtr = emitter.GetDelegateFromClassDelegate(thatPtr);
1141     void* delegateValue = emitter.CreateLoad(thatDelegatePtr);
1142     void* thisDelegatePtr = emitter.GetDelegateFromClassDelegate(thisPtr);
1143     emitter.CreateStore(delegateValuethisDelegatePtr);
1144 }
1145 
1146 ClassDelegateTypeMoveAssignment::ClassDelegateTypeMoveAssignment(const Span& span_const boost::uuids::uuid& sourceModuleId_const std::u32string& name_) :
1147     FunctionSymbol(SymbolType::classDelegateTypeMoveAssignmentspan_sourceModuleId_name_)
1148 {
1149 }
1150 
1151 ClassDelegateTypeMoveAssignment::ClassDelegateTypeMoveAssignment(ClassDelegateTypeSymbol* classDelegateTypeTypeSymbol* voidType) :
1152     FunctionSymbol(SymbolType::classDelegateTypeMoveAssignmentclassDelegateType->GetSpan()classDelegateType->SourceModuleId()U"operator=")
1153 {
1154     SetGroupName(U"operator=");
1155     SetAccess(SymbolAccess::public_);
1156     ParameterSymbol* thisParam = new ParameterSymbol(classDelegateType->GetSpan()classDelegateType->SourceModuleId()U"this");
1157     thisParam->SetType(classDelegateType->AddPointer(Span()boost::uuids::nil_uuid()));
1158     AddMember(thisParam);
1159     ParameterSymbol* thatParam = new ParameterSymbol(classDelegateType->GetSpan()classDelegateType->SourceModuleId()U"that");
1160     thatParam->SetType(classDelegateType->AddRvalueReference(Span()boost::uuids::nil_uuid()));
1161     AddMember(thatParam);
1162     SetReturnType(voidType);
1163     ComputeName();
1164 }
1165 
1166 void ClassDelegateTypeMoveAssignment::GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId)
1167 {
1168     genObjects[1]->Load(emitterOperationFlags::none);
1169     void* thatPtr = emitter.Stack().Pop();
1170     void* thatObjectPtr = emitter.GetObjectFromClassDelegate(thatPtr);
1171     void* objectValue = emitter.CreateLoad(thatObjectPtr);
1172     genObjects[0]->Load(emitterOperationFlags::none);
1173     void* thisPtr = emitter.Stack().Pop();
1174     void* thisObjectPtr = emitter.GetObjectFromClassDelegate(thisPtr);
1175     emitter.CreateStore(objectValuethisObjectPtr);
1176     void* thatDelegatePtr = emitter.GetDelegateFromClassDelegate(thatPtr);
1177     void* delegateValue = emitter.CreateLoad(thatDelegatePtr);
1178     void* thisDelegatePtr = emitter.GetDelegateFromClassDelegate(thisPtr);
1179     emitter.CreateStore(delegateValuethisDelegatePtr);
1180 }
1181 
1182 ClassDelegateTypeEquality::ClassDelegateTypeEquality(const Span& span_const boost::uuids::uuid& sourceModuleId_const std::u32string& name_) :
1183     FunctionSymbol(SymbolType::classDelegateTypeEqualityspan_sourceModuleId_name_)
1184 {
1185 }
1186 
1187 ClassDelegateTypeEquality::ClassDelegateTypeEquality(ClassDelegateTypeSymbol* classDelegateTypeTypeSymbol* boolType) :
1188     FunctionSymbol(SymbolType::classDelegateTypeEqualityclassDelegateType->GetSpan()classDelegateType->SourceModuleId()U"operator==")
1189 {
1190     SetGroupName(U"operator==");
1191     SetAccess(SymbolAccess::public_);
1192     ParameterSymbol* leftParam = new ParameterSymbol(classDelegateType->GetSpan()classDelegateType->SourceModuleId()U"left");
1193     leftParam->SetType(classDelegateType->AddConst(Span()boost::uuids::nil_uuid())->AddLvalueReference(Span()boost::uuids::nil_uuid()));
1194     AddMember(leftParam);
1195     ParameterSymbol* rightParam = new ParameterSymbol(classDelegateType->GetSpan()classDelegateType->SourceModuleId()U"right");
1196     rightParam->SetType(classDelegateType->AddConst(Span()boost::uuids::nil_uuid())->AddLvalueReference(Span()boost::uuids::nil_uuid()));
1197     AddMember(rightParam);
1198     SetReturnType(boolType);
1199     ComputeName();
1200 }
1201 
1202 void ClassDelegateTypeEquality::GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId)
1203 {
1204     genObjects[0]->Load(emitterOperationFlags::none);
1205     void* leftPtr = emitter.Stack().Pop();
1206     void* leftObjectPtr = emitter.GetObjectFromClassDelegate(leftPtr);
1207     void* leftObjectValue = emitter.CreateLoad(leftObjectPtr);
1208     genObjects[1]->Load(emitterOperationFlags::none);
1209     void* rightPtr = emitter.Stack().Pop();
1210     void* rightObjectPtr = emitter.GetObjectFromClassDelegate(rightPtr);
1211     void* rightObjectValue = emitter.CreateLoad(rightObjectPtr);
1212     void* objectsEqual = emitter.CreateICmpEQ(leftObjectValuerightObjectValue);
1213     void* leftDelegatePtr = emitter.GetDelegateFromClassDelegate(leftPtr);
1214     void* leftDelegateValue = emitter.CreateLoad(leftDelegatePtr);
1215     void* rightDelegatePtr = emitter.GetDelegateFromClassDelegate(rightPtr);
1216     void* rightDelegateValue = emitter.CreateLoad(rightDelegatePtr);
1217     void* delegatesEqual = emitter.CreateICmpEQ(leftDelegateValuerightDelegateValue);
1218     void* equal = emitter.CreateAnd(objectsEqualdelegatesEqual);
1219     emitter.Stack().Push(equal);
1220 }
1221 
1222 MemberFunctionToClassDelegateConversion::MemberFunctionToClassDelegateConversion(const Span& span_const boost::uuids::uuid& sourceModuleId_const std::u32string& name_) :
1223     FunctionSymbol(SymbolType::memberFunctionToClassDelegateSymbolspan_sourceModuleId_name_)sourceType(nullptr)targetType(nullptr)function(nullptr)
1224 {
1225 }
1226 
1227 MemberFunctionToClassDelegateConversion::MemberFunctionToClassDelegateConversion(const Span& span_const boost::uuids::uuid& sourceModuleId_TypeSymbol* sourceType_ClassDelegateTypeSymbol* targetType_FunctionSymbol* function_) :
1228     FunctionSymbol(SymbolType::memberFunctionToClassDelegateSymbolspan_sourceModuleId_U"@conversion")sourceType(sourceType_)targetType(targetType_)function(function_)
1229 {
1230     SetConversion();
1231     SetConversionSourceType(sourceType->PlainType(GetSpan()SourceModuleId()));
1232     SetConversionTargetType(targetType->PlainType(GetSpan()SourceModuleId()));
1233 }
1234 
1235 std::std::vector<LocalVariableSymbol*>MemberFunctionToClassDelegateConversion::CreateTemporariesTo(FunctionSymbol*currentFunction)
1236 {
1237     std::vector<LocalVariableSymbol*> temporaries;
1238     LocalVariableSymbol* objectDelegatePairVariable = currentFunction->CreateTemporary(targetType->ObjectDelegatePairType()GetSpan()SourceModuleId());
1239     temporaries.push_back(objectDelegatePairVariable);
1240     return temporaries;
1241 }
1242 
1243 void MemberFunctionToClassDelegateConversion::GenerateCall(Emitter& emitterstd::std::vector<GenObject*>&genObjectsOperationFlagsflagsconstSpan&spanconstboost::uuids::uuid& moduleId)
1244 {
1245     Assert(genObjects.size() == 1"MemberFunctionToClassDelegateConversion needs one temporary object");
1246     void* objectValue = emitter.Stack().Pop();
1247     if (!objectValue)
1248     {
1249         throw Exception("cannot construct class delegate because expression has no this pointer"spanmoduleId);
1250     }
1251     void* objectValueAsVoidPtr = emitter.CreateBitCast(objectValueemitter.GetIrTypeForVoidPtrType());
1252     void* memFunPtrValue = emitter.GetOrInsertFunction(ToUtf8(function->MangledName())function->IrType(emitter)function->DontThrow());
1253     genObjects[0]->Load(emitterOperationFlags::addr);
1254     void* ptr = emitter.Stack().Pop();
1255     void* objectPtr = emitter.GetObjectFromClassDelegate(ptr);
1256     emitter.CreateStore(objectValueAsVoidPtrobjectPtr);
1257     void* delegatePtr = emitter.GetDelegateFromClassDelegate(ptr);
1258     void* delegateValue = emitter.CreateBitCast(memFunPtrValuetargetType->DelegateType()->IrType(emitter));
1259     emitter.CreateStore(delegateValuedelegatePtr);
1260     emitter.Stack().Push(ptr);
1261 }
1262 
1263 void MemberFunctionToClassDelegateConversion::Check()
1264 {
1265     FunctionSymbol::Check();
1266     if (!sourceType)
1267     {
1268         throw SymbolCheckException("member function to class delegate conversion has no source type"GetSpan()SourceModuleId());
1269     }
1270     if (!targetType)
1271     {
1272         throw SymbolCheckException("member function to class delegate conversion has no target type"GetSpan()SourceModuleId());
1273     }
1274     if (!function)
1275     {
1276         throw SymbolCheckException("member function to class delegate conversion has no function"GetSpan()SourceModuleId());
1277     }
1278 }
1279 
1280 } } // namespace cmajor::symbols