1 // =================================
   2 // Copyright (c) 2021 Seppo Laakko
   3 // Distributed under the MIT license
   4 // =================================
   5 
   6 #include <cmajor/codegensx/SystemXCodeGenerator.hpp>
   7 #include <cmajor/cmsxbe/EmittingContext.hpp>
   8 #include <cmajor/binder/BoundCompileUnit.hpp>
   9 #include <cmajor/binder/BoundNamespace.hpp>
  10 #include <cmajor/binder/BoundFunction.hpp>
  11 #include <cmajor/symbols/InterfaceTypeSymbol.hpp>
  12 #include <cmajor/symbols/GlobalFlags.hpp>
  13 #include <soulng/util/Path.hpp>
  14 #include <soulng/util/Process.hpp>
  15 #include <soulng/util/System.hpp>
  16 #include <soulng/util/Unicode.hpp>
  17 #include <soulng/util/Error.hpp>
  18 #include <soulng/util/Sha1.hpp>
  19 #include <soulng/util/TextUtils.hpp>
  20 #include <soulng/util/Log.hpp>
  21 #include <boost/filesystem.hpp>
  22 
  23 namespace cmajor { namespace codegensx {
  24 
  25 using namespace soulng::util;
  26 using namespace soulng::unicode;
  27 
  28 struct NativeModule 
  29 {
  30     NativeModule(cmajor::ir::Emitter* emitter_const std::string& moduleFilePath_) : emitter(emitter_)
  31     {
  32         module = emitter->CreateModule(moduleFilePath_);
  33         emitter->SetModule(module);
  34     }
  35     ~NativeModule()
  36     {
  37         emitter->DestroyModule(module);
  38     }
  39     cmajor::ir::Emitter* emitter;
  40     void* module;
  41 };
  42 
  43 SystemXCodeGenerator::SystemXCodeGenerator(cmajor::ir::EmittingContext& emittingContext_) :
  44     cmajor::codegenbase::CodeGenerator(emittingContext_)emitter(GetEmitter())emittingContext(&emittingContext_)symbolTable(nullptr)module(nullptr)compileUnit(nullptr)
  45     nativeCompileUnit(nullptr)function(nullptr)entryBasicBlock(nullptr)lastInstructionWasRet(false)destructorCallGenerated(false)genJumpingBoolCode(false)
  46     trueBlock(nullptr)falseBlock(nullptr)breakTarget(nullptr)continueTarget(nullptr)sequenceSecond(nullptr)currentFunction(nullptr)currentBlock(nullptr)
  47     breakTargetBlock(nullptr)continueTargetBlock(nullptr)lastAlloca(nullptr)currentClass(nullptr)basicBlockOpen(false)defaultDest(nullptr)currentCaseMap(nullptr)
  48     generateLineNumbers(false)currentTryBlockId(-1)nextTryBlockId(0)currentTryNextBlock(nullptr)handlerBlock(nullptr)cleanupBlock(nullptr)newCleanupNeeded(false)
  49     inTryBlock(false)prevWasTerminator(false)
  50 {
  51     emitter->SetEmittingDelegate(this);
  52 }
  53 
  54 void SystemXCodeGenerator::GenerateCode(void* boundCompileUnit)
  55 {
  56     BoundCompileUnit* compileUnit = static_cast<BoundCompileUnit*>(boundCompileUnit);
  57     compileUnit->Accept(*this);
  58 }
  59 
  60 void SystemXCodeGenerator::Visit(BoundCompileUnit& boundCompileUnit)
  61 {
  62     std::string intermediateFilePath = Path::ChangeExtension(boundCompileUnit.ObjectFilePath()".i");
  63     NativeModule nativeModule(emitterintermediateFilePath);
  64     compileUnitId = boundCompileUnit.Id();
  65     emitter->SetCompileUnitId(compileUnitId);
  66     emitter->SetCurrentSourceSpan(000);
  67     generateLineNumbers = false;
  68     symbolTable = &boundCompileUnit.GetSymbolTable();
  69     module = &boundCompileUnit.GetModule();
  70     compileUnit = &boundCompileUnit;
  71     nativeCompileUnit = static_cast<cmsxi::CompileUnit*>(nativeModule.module);
  72     nativeCompileUnit->SetId(compileUnitId);
  73     nativeCompileUnit->SetSourceFilePath(boundCompileUnit.SourceFilePath());
  74     ConstantArrayRepository& constantArrayRepository = boundCompileUnit.GetConstantArrayRepository();
  75     for (ConstantSymbol* constantSymbol : constantArrayRepository.ConstantArrays())
  76     {
  77         constantSymbol->ArrayIrObject(*emittertrue);
  78     }
  79     ConstantStructureRepository& constantStructureRepository = boundCompileUnit.GetConstantStructureRepository();
  80     for (ConstantSymbol* constantSymbol : constantStructureRepository.ConstantStructures())
  81     {
  82         constantSymbol->StructureIrObject(*emittertrue);
  83     }
  84     int n = boundCompileUnit.BoundNodes().size();
  85     for (int i = 0; i < n; ++i)
  86     {
  87         BoundNode* node = boundCompileUnit.BoundNodes()[i].get();
  88         node->Accept(*this);
  89     }
  90     nativeCompileUnit->Write();
  91     std::string intermediateCompileCommand;
  92     std::string errors;
  93     intermediateCompileCommand.append("cmsxic ").append(intermediateFilePath);
  94     try
  95     {
  96         Process::Redirections redirections = Process::Redirections::processStdErr;
  97         if (GetGlobalFlag(GlobalFlags::verbose))
  98         {
  99             redirections = redirections | Process::Redirections::processStdOut;
 100         }
 101         Process process(intermediateCompileCommandredirections);
 102         if (GetGlobalFlag(GlobalFlags::verbose))
 103         {
 104             while (!process.Eof(Process::StdHandle::stdOut))
 105             {
 106                 std::string line = process.ReadLine(Process::StdHandle::stdOut);
 107                 if (!line.empty())
 108                 {
 109                     LogMessage(module->LogStreamId()line);
 110                 }
 111             }
 112         }
 113         errors = process.ReadToEnd(Process::StdHandle::stdErr);
 114         process.WaitForExit();
 115         int exitCode = process.ExitCode();
 116         if (exitCode != 0)
 117         {
 118             throw std::runtime_error("executing '" + intermediateCompileCommand + "' failed with exit code: " + std::to_string(exitCode));
 119         }
 120     }
 121     catch (const std::exception& ex;)
 122     {
 123         throw std::runtime_error("compiling intermediate code '" + intermediateFilePath + "' failed: " + ex.what() + ":\nerrors:\n" + errors);
 124     }
 125     std::string assembleCommand;
 126     std::string assemblyFilePath = Path::ChangeExtension(boundCompileUnit.ObjectFilePath()".s");
 127     assembleCommand.append("cmsxas ").append(assemblyFilePath);
 128     try
 129     {
 130         Process::Redirections redirections = Process::Redirections::processStdErr;
 131         if (GetGlobalFlag(GlobalFlags::verbose))
 132         {
 133             redirections = redirections | Process::Redirections::processStdOut;
 134         }
 135         Process process(assembleCommandredirections);
 136         if (GetGlobalFlag(GlobalFlags::verbose))
 137         {
 138             while (!process.Eof(Process::StdHandle::stdOut))
 139             {
 140                 std::string line = process.ReadLine(Process::StdHandle::stdOut);
 141                 if (!line.empty())
 142                 {
 143                     LogMessage(module->LogStreamId()line);
 144                 }
 145             }
 146         }
 147         errors = process.ReadToEnd(Process::StdHandle::stdErr);
 148         process.WaitForExit();
 149         int exitCode = process.ExitCode();
 150         if (exitCode != 0)
 151         {
 152             throw std::runtime_error("executing '" + assembleCommand + "' failed with exit code: " + std::to_string(exitCode));
 153         }
 154     }
 155     catch (const std::exception& ex;)
 156     {
 157         throw std::runtime_error("assembling '" + assemblyFilePath + "' failed: " + ex.what() + ":\nerrors:\n" + errors);
 158     }
 159 }
 160 
 161 void SystemXCodeGenerator::Visit(BoundNamespace& boundNamespace)
 162 {
 163     int n = boundNamespace.Members().size();
 164     for (int i = 0; i < n; ++i)
 165     {
 166         BoundNode* node = boundNamespace.Members()[i].get();
 167         node->Accept(*this);
 168     }
 169 }
 170 
 171 void SystemXCodeGenerator::Visit(BoundClass& boundClass)
 172 {
 173     classStack.push(currentClass);
 174     currentClass = &boundClass;
 175     int n = boundClass.Members().size();
 176     for (int i = 0; i < n; ++i)
 177     {
 178         BoundNode* boundNode = boundClass.Members()[i].get();
 179         boundNode->Accept(*this);
 180     }
 181     currentClass = classStack.top();
 182     classStack.pop();
 183 }
 184 
 185 void SystemXCodeGenerator::Visit(BoundFunction& boundFunction)
 186 {
 187     if (!boundFunction.Body()) return;
 188     currentFunction = &boundFunction;
 189     FunctionSymbol* functionSymbol = boundFunction.GetFunctionSymbol();
 190     if (compileUnit->CodeGenerated(functionSymbol)) return;
 191     compileUnit->SetCodeGenerated(functionSymbol);
 192     void* functionType = functionSymbol->IrType(*emitter);
 193     destructorCallGenerated = false;
 194     lastInstructionWasRet = false;
 195     basicBlockOpen = false;
 196     lastAlloca = nullptr;
 197     handlerBlock = nullptr;
 198     cleanupBlock = nullptr;
 199     newCleanupNeeded = false;
 200     labeledStatementMap.clear();
 201     cleanups.clear();
 202     if (functionSymbol->HasSource())
 203     {
 204         generateLineNumbers = true;
 205         emitter->SetCurrentSourceSpan(boundFunction.Body()->GetSpan().line00);
 206     }
 207     else
 208     {
 209         generateLineNumbers = false;
 210         emitter->SetCurrentSourceSpan(000);
 211     }
 212     function = emitter->GetOrInsertFunction(ToUtf8(functionSymbol->MangledName())functionTypefunctionSymbol->DontThrow());
 213     if (functionSymbol->HasSource())
 214     {
 215         void* mdStruct = emitter->CreateMDStruct();
 216         emitter->AddMDItem(mdStruct"nodeType"emitter->CreateMDLong(funcInfoNodeType));
 217         emitter->AddMDItem(mdStruct"fullName"emitter->CreateMDString(ToUtf8(functionSymbol->FullName())));
 218         void* mdFile = emitter->GetMDStructRefForSourceFile(module->GetFilePath(functionSymbol->GetSpan().fileIndex));
 219         emitter->AddMDItem(mdStruct"sourceFile"mdFile);
 220         int mdId = emitter->GetMDStructId(mdStruct);
 221         emitter->SetFunctionMdId(functionmdId);
 222     }
 223     if (GetGlobalFlag(GlobalFlags::release) && functionSymbol->IsInline())
 224     {
 225         emitter->AddInlineFunctionAttribute(function);
 226         functionSymbol->SetLinkOnceOdrLinkage();
 227     }
 228     else if (functionSymbol->IsGeneratedFunction())
 229     {
 230         emitter->AddInlineFunctionAttribute(function);
 231         functionSymbol->SetLinkOnceOdrLinkage();
 232     }
 233     if (functionSymbol->HasLinkOnceOdrLinkage())
 234     {
 235         void* comdat = emitter->GetOrInsertAnyFunctionComdat(ToUtf8(functionSymbol->MangledName())function);
 236         emitter->SetFunctionLinkageToLinkOnceODRLinkage(function);
 237     }
 238     int32_t fileIndex = -1;
 239     boost::uuids::uuid functionId;
 240     if (functionSymbol->HasSource())
 241     {
 242         fileIndex = functionSymbol->GetSpan().fileIndex;
 243         functionId = functionSymbol->FunctionId();
 244     }
 245     emitter->SetFunction(functionfileIndexfunctionSymbol->SourceModuleId()functionId);
 246     void* entryBlock = emitter->CreateBasicBlock("entry");
 247     entryBasicBlock = entryBlock;
 248     emitter->SetCurrentBasicBlock(entryBlock);
 249     if (currentClass && !currentClass->IsInlineFunctionContainer())
 250     {
 251         ClassTypeSymbol* classTypeSymbol = currentClass->GetClassTypeSymbol();
 252         if (!emitter->IsVmtObjectCreated(classTypeSymbol))
 253         {
 254             classTypeSymbol->VmtObject(*emittertrue);
 255         }
 256         if (!emitter->IsStaticObjectCreated(classTypeSymbol))
 257         {
 258             classTypeSymbol->StaticObject(*emittertrue);
 259         }
 260     }
 261     int np = functionSymbol->Parameters().size();
 262     for (int i = 0; i < np; ++i)
 263     {
 264         ParameterSymbol* parameter = functionSymbol->Parameters()[i];
 265         void* allocaInst = emitter->CreateAlloca(parameter->GetType()->IrType(*emitter));
 266         emitter->SetIrObject(parameterallocaInst);
 267         lastAlloca = allocaInst;
 268     }
 269     if (functionSymbol->ReturnParam())
 270     {
 271         ParameterSymbol* parameter = functionSymbol->ReturnParam();
 272         void* allocaInst = emitter->CreateAlloca(parameter->GetType()->IrType(*emitter));
 273         emitter->SetIrObject(parameterallocaInst);
 274         lastAlloca = allocaInst;
 275     }
 276     int nlv = functionSymbol->LocalVariables().size();
 277     for (int i = 0; i < nlv; ++i)
 278     {
 279         LocalVariableSymbol* localVariable = functionSymbol->LocalVariables()[i];
 280         void* allocaInst = emitter->CreateAlloca(localVariable->GetType()->IrType(*emitter));
 281         emitter->SetIrObject(localVariableallocaInst);
 282         lastAlloca = allocaInst;
 283     }
 284     bool byValueComplexParams = false;
 285     for (int i = 0; i < np; ++i)
 286     {
 287         ParameterSymbol* parameter = functionSymbol->Parameters()[i];
 288         if (parameter->GetType()->IsClassTypeSymbol() || 
 289             (parameter->GetType()->GetSymbolType() == SymbolType::classDelegateTypeSymbol) || 
 290             (parameter->GetType()->GetSymbolType() == SymbolType::interfaceTypeSymbol))
 291         {
 292             byValueComplexParams = true;
 293             break;
 294         }
 295     }
 296     if (byValueComplexParams)
 297     {
 298         emitter->CreateSave();
 299     }
 300     for (int i = 0; i < np; ++i)
 301     {
 302         void* arg = emitter->GetFunctionArgument(functioni);
 303         ParameterSymbol* parameter = functionSymbol->Parameters()[i];
 304         if (parameter->GetType()->IsClassTypeSymbol())
 305         {
 306             ClassTypeSymbol* classType = static_cast<ClassTypeSymbol*>(parameter->GetType());
 307             FunctionSymbol* copyConstructor = classType->CopyConstructor();
 308             if (!copyConstructor)
 309             {
 310                 copyConstructor = compileUnit->GetCopyConstructorFor(classType->TypeId());
 311             }
 312             void* copyCtorType = copyConstructor->IrType(*emitter);
 313             void* callee = emitter->GetOrInsertFunction(ToUtf8(copyConstructor->MangledName())copyCtorTypecopyConstructor->DontThrow());
 314             std::vector<void*> args;
 315             args.push_back(parameter->IrObject(*emitter));
 316             args.push_back(arg);
 317             emitter->CreateCall(calleeargs);
 318         }
 319         else if (parameter->GetType()->GetSymbolType() == SymbolType::classDelegateTypeSymbol)
 320         {
 321             ClassDelegateTypeSymbol* classDelegateType = static_cast<ClassDelegateTypeSymbol*>(parameter->GetType());
 322             FunctionSymbol* copyConstructor = classDelegateType->CopyConstructor();
 323             if (!copyConstructor)
 324             {
 325                 throw std::runtime_error("internal error: class delegate type has no copy constructor");
 326             }
 327             std::vector<GenObject*> copyCtorArgs;
 328             NativeValue paramValue(parameter->IrObject(*emitter));
 329             copyCtorArgs.push_back(&paramValue);
 330             NativeValue argumentValue(arg);
 331             copyCtorArgs.push_back(&argumentValue);
 332             copyConstructor->GenerateCall(*emittercopyCtorArgsOperationFlags::noneboundFunction.Body()->GetSpan()boundFunction.Body()->ModuleId());
 333         }
 334         else if (parameter->GetType()->GetSymbolType() == SymbolType::interfaceTypeSymbol)
 335         {
 336             InterfaceTypeSymbol* interfaceType = static_cast<InterfaceTypeSymbol*>(parameter->GetType());
 337             FunctionSymbol* copyConstructor = interfaceType->CopyConstructor();
 338             if (!copyConstructor)
 339             {
 340                 copyConstructor = compileUnit->GetCopyConstructorFor(interfaceType->TypeId());
 341             }
 342             std::vector<GenObject*> copyCtorArgs;
 343             NativeValue paramValue(parameter->IrObject(*emitter));
 344             paramValue.SetType(interfaceType->AddPointer(Span()boost::uuids::nil_uuid()));
 345             copyCtorArgs.push_back(&paramValue);
 346             NativeValue argumentValue(arg);
 347             argumentValue.SetType(interfaceType->AddPointer(Span()boost::uuids::nil_uuid()));
 348             copyCtorArgs.push_back(&argumentValue);
 349             copyConstructor->GenerateCall(*emittercopyCtorArgsOperationFlags::noneboundFunction.Body()->GetSpan()boundFunction.Body()->ModuleId());
 350         }
 351         else
 352         {
 353             emitter->CreateStore(argparameter->IrObject(*emitter));
 354         }
 355     }
 356     if (functionSymbol->ReturnParam())
 357     {
 358         void* arg = emitter->GetFunctionArgument(functionnp);
 359         emitter->CreateStore(argfunctionSymbol->ReturnParam()->IrObject(*emitter));
 360     }
 361     for (BoundStatement* labeledStatement : boundFunction.LabeledStatements())
 362     {
 363         void* target = emitter->CreateBasicBlock(ToUtf8(labeledStatement->Label()));
 364         labeledStatementMap[labeledStatement] = target;
 365     }
 366     BoundCompoundStatement* body = boundFunction.Body();
 367     body->Accept(*this);
 368     BoundStatement* lastStatement = nullptr;
 369     if (!body->Statements().empty())
 370     {
 371         lastStatement = body->Statements().back().get();
 372     }
 373     if (!lastStatement || lastStatement->GetBoundNodeType() != BoundNodeType::boundReturnStatement || 
 374         lastStatement->GetBoundNodeType() == BoundNodeType::boundReturnStatement && destructorCallGenerated)
 375     {
 376         if (functionSymbol->ReturnType() && functionSymbol->ReturnType()->GetSymbolType() != SymbolType::voidTypeSymbol && !functionSymbol->ReturnsClassInterfaceOrClassDelegateByValue())
 377         {
 378             void* defaultValue = functionSymbol->ReturnType()->CreateDefaultIrValue(*emitter);
 379             emitter->CreateRet(defaultValue);
 380             lastInstructionWasRet = true;
 381         }
 382         else
 383         {
 384             emitter->CreateRetVoid();
 385             lastInstructionWasRet = true;
 386         }
 387     }
 388     GenerateCodeForCleanups();
 389     emitter->FinalizeFunction(functionfunctionSymbol->HasCleanup());
 390 }
 391 
 392 void SystemXCodeGenerator::Visit(BoundCompoundStatement& boundCompoundStatement)
 393 {
 394     if (generateLineNumbers)
 395     {
 396         emitter->SetCurrentSourceSpan(boundCompoundStatement.GetSpan().line00);
 397     }
 398     destructorCallGenerated = false;
 399     lastInstructionWasRet = false;
 400     basicBlockOpen = false;
 401     SetTarget(&boundCompoundStatement);
 402     BoundCompoundStatement* prevBlock = currentBlock;
 403     currentBlock = &boundCompoundStatement;
 404     blockDestructionMap[currentBlock] = std::vector<std::std::unique_ptr<BoundFunctionCall>>();
 405     blocks.push_back(currentBlock);
 406     int n = boundCompoundStatement.Statements().size();
 407     for (int i = 0; i < n; ++i)
 408     {
 409         BoundStatement* statement = boundCompoundStatement.Statements()[i].get();
 410         statement->Accept(*this);
 411     }
 412     ExitBlocks(prevBlock);
 413     blocks.pop_back();
 414     currentBlock = prevBlock;
 415 }
 416 
 417 void SystemXCodeGenerator::Visit(BoundSequenceStatement& boundSequenceStatement)
 418 {
 419     destructorCallGenerated = false;
 420     lastInstructionWasRet = false;
 421     basicBlockOpen = false;
 422     SetTarget(&boundSequenceStatement);
 423     BoundStatement* prevSequence = sequenceSecond;
 424     sequenceSecond = boundSequenceStatement.Second();
 425     boundSequenceStatement.First()->Accept(*this);
 426     sequenceSecond = prevSequence;
 427     if (!boundSequenceStatement.Second()->Generated())
 428     {
 429         boundSequenceStatement.Second()->Accept(*this);
 430     }
 431 }
 432 
 433 void SystemXCodeGenerator::Visit(BoundReturnStatement& boundReturnStatement)
 434 {
 435     if (generateLineNumbers)
 436     {
 437         emitter->SetCurrentSourceSpan(boundReturnStatement.GetSpan().line00);
 438     }
 439     destructorCallGenerated = false;
 440     lastInstructionWasRet = false;
 441     basicBlockOpen = false;
 442     SetTarget(&boundReturnStatement);
 443     BoundFunctionCall* returnFunctionCall = boundReturnStatement.ReturnFunctionCall();
 444     if (returnFunctionCall)
 445     {
 446         ExitBlocks(nullptr);
 447         boundReturnStatement.ReturnFunctionCall()->Accept(*this);
 448         void* returnValue = emitter->Stack().Pop();
 449         if (sequenceSecond)
 450         {
 451             sequenceSecond->SetGenerated();
 452             sequenceSecond->Accept(*this);
 453         }
 454         emitter->CreateRet(returnValue);
 455         lastInstructionWasRet = true;
 456     }
 457     else
 458     {
 459         ExitBlocks(nullptr);
 460         emitter->CreateRetVoid();
 461         lastInstructionWasRet = true;
 462     }
 463     BoundCompoundStatement* body = currentFunction->Body();
 464     BoundStatement* lastStatement = nullptr;
 465     if (!body->Statements().empty())
 466     {
 467         lastStatement = body->Statements().back().get();
 468     }
 469     if (lastStatement && lastStatement != &boundReturnStatement)
 470     {
 471         void* nextBlock = emitter->CreateBasicBlock("next");
 472         emitter->SetCurrentBasicBlock(nextBlock);
 473         basicBlockOpen = true;
 474         lastInstructionWasRet = false;
 475     }
 476 }
 477 
 478 void SystemXCodeGenerator::Visit(BoundGotoCaseStatement& boundGotoCaseStatement)
 479 {
 480     if (generateLineNumbers)
 481     {
 482         emitter->SetCurrentSourceSpan(boundGotoCaseStatement.GetSpan().line00);
 483     }
 484     destructorCallGenerated = false;
 485     lastInstructionWasRet = false;
 486     basicBlockOpen = false;
 487     SetTarget(&boundGotoCaseStatement);
 488     Assert(breakTargetBlock"break target not set");
 489     ExitBlocks(breakTargetBlock);
 490     IntegralValue integralCaseValue(boundGotoCaseStatement.CaseValue());
 491     auto it = currentCaseMap->find(integralCaseValue);
 492     if (it != currentCaseMap->cend())
 493     {
 494         void* caseDest = it->second;
 495         emitter->CreateBr(caseDest);
 496     }
 497     else
 498     {
 499         throw Exception("case not found"boundGotoCaseStatement.GetSpan()boundGotoCaseStatement.ModuleId());
 500     }
 501 }
 502 
 503 void SystemXCodeGenerator::Visit(BoundGotoDefaultStatement& boundGotoDefaultStatement)
 504 {
 505     if (generateLineNumbers)
 506     {
 507         emitter->SetCurrentSourceSpan(boundGotoDefaultStatement.GetSpan().line00);
 508     }
 509     destructorCallGenerated = false;
 510     lastInstructionWasRet = false;
 511     basicBlockOpen = false;
 512     SetTarget(&boundGotoDefaultStatement);
 513     Assert(breakTargetBlock"break target not set");
 514     ExitBlocks(breakTargetBlock);
 515     if (defaultDest)
 516     {
 517         emitter->CreateBr(defaultDest);
 518     }
 519     else
 520     {
 521         throw Exception("no default destination"boundGotoDefaultStatement.GetSpan()boundGotoDefaultStatement.ModuleId());
 522     }
 523 }
 524 
 525 void SystemXCodeGenerator::Visit(BoundBreakStatement& boundBreakStatement)
 526 {
 527     if (generateLineNumbers)
 528     {
 529         emitter->SetCurrentSourceSpan(boundBreakStatement.GetSpan().line00);
 530     }
 531     destructorCallGenerated = false;
 532     lastInstructionWasRet = false;
 533     basicBlockOpen = false;
 534     SetTarget(&boundBreakStatement);
 535     Assert(breakTarget && breakTargetBlock"break target not set");
 536     ExitBlocks(breakTargetBlock);
 537     emitter->CreateBr(breakTarget);
 538     if (!currentCaseMap)
 539     {
 540         void* nextBlock = emitter->CreateBasicBlock("next");
 541         emitter->SetCurrentBasicBlock(nextBlock);
 542         basicBlockOpen = true;
 543     }
 544 }
 545 
 546 void SystemXCodeGenerator::Visit(BoundContinueStatement& boundContinueStatement)
 547 {
 548     if (generateLineNumbers)
 549     {
 550         emitter->SetCurrentSourceSpan(boundContinueStatement.GetSpan().line00);
 551     }
 552     destructorCallGenerated = false;
 553     lastInstructionWasRet = false;
 554     basicBlockOpen = false;
 555     prevWasTerminator = false;
 556     SetTarget(&boundContinueStatement);
 557     Assert(continueTarget && continueTargetBlock"continue target not set");
 558     ExitBlocks(continueTargetBlock);
 559     emitter->CreateBr(continueTarget);
 560     void* nextBlock = emitter->CreateBasicBlock("next");
 561     emitter->SetCurrentBasicBlock(nextBlock);
 562     basicBlockOpen = true;
 563 }
 564 
 565 void SystemXCodeGenerator::Visit(BoundGotoStatement& boundGotoStatement)
 566 {
 567     if (generateLineNumbers)
 568     {
 569         emitter->SetCurrentSourceSpan(boundGotoStatement.GetSpan().line00);
 570     }
 571     destructorCallGenerated = false;
 572     lastInstructionWasRet = false;
 573     basicBlockOpen = false;
 574     prevWasTerminator = false;
 575     SetTarget(&boundGotoStatement);
 576     ExitBlocks(boundGotoStatement.TargetBlock());
 577     auto it = labeledStatementMap.find(boundGotoStatement.TargetStatement());
 578     if (it != labeledStatementMap.cend())
 579     {
 580         void* target = it->second;
 581         emitter->CreateBr(target);
 582     }
 583     else
 584     {
 585         throw Exception("goto target not found"boundGotoStatement.GetSpan()boundGotoStatement.ModuleId());
 586     }
 587     void* nextBlock = emitter->CreateBasicBlock("next");
 588     emitter->SetCurrentBasicBlock(nextBlock);
 589     basicBlockOpen = true;
 590 }
 591 
 592 void SystemXCodeGenerator::Visit(BoundIfStatement& boundIfStatement)
 593 {
 594     if (generateLineNumbers)
 595     {
 596         emitter->SetCurrentSourceSpan(boundIfStatement.GetSpan().line00);
 597     }
 598     destructorCallGenerated = false;
 599     lastInstructionWasRet = false;
 600     basicBlockOpen = false;
 601     SetTarget(&boundIfStatement);
 602     void* prevTrueBlock = trueBlock;
 603     void* prevFalseBlock = falseBlock;
 604     trueBlock = emitter->CreateBasicBlock("true");
 605     void* nextBlock = emitter->CreateBasicBlock("next");
 606     if (boundIfStatement.ElseS())
 607     {
 608         falseBlock = emitter->CreateBasicBlock("false");
 609     }
 610     else
 611     {
 612         falseBlock = nextBlock;
 613     }
 614     bool prevGenJumpingBoolCode = genJumpingBoolCode;
 615     genJumpingBoolCode = true;
 616     boundIfStatement.Condition()->Accept(*this);
 617     genJumpingBoolCode = prevGenJumpingBoolCode;
 618     emitter->SetCurrentBasicBlock(trueBlock);
 619     boundIfStatement.ThenS()->Accept(*this);
 620     emitter->CreateBr(nextBlock);
 621     if (boundIfStatement.ElseS())
 622     {
 623         emitter->SetCurrentBasicBlock(falseBlock);
 624         boundIfStatement.ElseS()->Accept(*this);
 625         emitter->CreateBr(nextBlock);
 626     }
 627     trueBlock = prevTrueBlock;
 628     falseBlock = prevFalseBlock;
 629     emitter->SetCurrentBasicBlock(nextBlock);
 630     basicBlockOpen = true;
 631 }
 632 
 633 void SystemXCodeGenerator::Visit(BoundWhileStatement& boundWhileStatement)
 634 {
 635     if (generateLineNumbers)
 636     {
 637         emitter->SetCurrentSourceSpan(boundWhileStatement.GetSpan().line00);
 638     }
 639     destructorCallGenerated = false;
 640     lastInstructionWasRet = false;
 641     basicBlockOpen = false;
 642     SetTarget(&boundWhileStatement);
 643     void* prevTrueBlock = trueBlock;
 644     void* prevFalseBlock = falseBlock;
 645     void* prevBreakTarget = breakTarget;
 646     void* prevContinueTarget = continueTarget;
 647     BoundCompoundStatement* prevBreakTargetBlock = breakTargetBlock;
 648     BoundCompoundStatement* prevContinueTargetBlock = continueTargetBlock;
 649     breakTargetBlock = currentBlock;
 650     continueTargetBlock = currentBlock;
 651     trueBlock = emitter->CreateBasicBlock("true");
 652     falseBlock = emitter->CreateBasicBlock("next");
 653     breakTarget = falseBlock;
 654     void* condBlock = emitter->CreateBasicBlock("cond");
 655     emitter->CreateBr(condBlock);
 656     emitter->SetCurrentBasicBlock(condBlock);
 657     continueTarget = condBlock;
 658     bool prevGenJumpingBoolCode = genJumpingBoolCode;
 659     genJumpingBoolCode = true;
 660     boundWhileStatement.Condition()->Accept(*this);
 661     genJumpingBoolCode = prevGenJumpingBoolCode;
 662     emitter->SetCurrentBasicBlock(trueBlock);
 663     boundWhileStatement.Statement()->Accept(*this);
 664     emitter->CreateBr(condBlock);
 665     emitter->SetCurrentBasicBlock(falseBlock);
 666     breakTargetBlock = prevBreakTargetBlock;
 667     continueTargetBlock = prevContinueTargetBlock;
 668     breakTarget = prevBreakTarget;
 669     continueTarget = prevContinueTarget;
 670     trueBlock = prevTrueBlock;
 671     falseBlock = prevFalseBlock;
 672 }
 673 
 674 void SystemXCodeGenerator::Visit(BoundDoStatement& boundDoStatement)
 675 {
 676     if (generateLineNumbers)
 677     {
 678         emitter->SetCurrentSourceSpan(boundDoStatement.GetSpan().line00);
 679     }
 680     destructorCallGenerated = false;
 681     lastInstructionWasRet = false;
 682     basicBlockOpen = false;
 683     SetTarget(&boundDoStatement);
 684     void* prevTrueBlock = trueBlock;
 685     void* prevFalseBlock = falseBlock;
 686     void* prevBreakTarget = breakTarget;
 687     void* prevContinueTarget = continueTarget;
 688     void* doBlock = emitter->CreateBasicBlock("do");
 689     void* condBlock = emitter->CreateBasicBlock("cond");
 690     BoundCompoundStatement* prevBreakTargetBlock = breakTargetBlock;
 691     BoundCompoundStatement* prevContinueTargetBlock = continueTargetBlock;
 692     breakTargetBlock = currentBlock;
 693     continueTargetBlock = currentBlock;
 694     trueBlock = doBlock;
 695     falseBlock = emitter->CreateBasicBlock("next");
 696     breakTarget = falseBlock;
 697     continueTarget = condBlock;
 698     emitter->CreateBr(doBlock);
 699     emitter->SetCurrentBasicBlock(doBlock);
 700     boundDoStatement.Statement()->Accept(*this);
 701     emitter->CreateBr(condBlock);
 702     emitter->SetCurrentBasicBlock(condBlock);
 703     bool prevGenJumpingBoolCode = genJumpingBoolCode;
 704     genJumpingBoolCode = true;
 705     boundDoStatement.Condition()->Accept(*this);
 706     genJumpingBoolCode = prevGenJumpingBoolCode;
 707     emitter->SetCurrentBasicBlock(falseBlock);
 708     basicBlockOpen = true;
 709     breakTargetBlock = prevBreakTargetBlock;
 710     continueTargetBlock = prevContinueTargetBlock;
 711     breakTarget = prevBreakTarget;
 712     continueTarget = prevContinueTarget;
 713     trueBlock = prevTrueBlock;
 714     falseBlock = prevFalseBlock;
 715 }
 716 
 717 void SystemXCodeGenerator::Visit(BoundForStatement& boundForStatement)
 718 {
 719     if (generateLineNumbers)
 720     {
 721         emitter->SetCurrentSourceSpan(boundForStatement.GetSpan().line00);
 722     }
 723     destructorCallGenerated = false;
 724     lastInstructionWasRet = false;
 725     basicBlockOpen = false;
 726     SetTarget(&boundForStatement);
 727     void* prevTrueBlock = trueBlock;
 728     void* prevFalseBlock = falseBlock;
 729     void* prevBreakTarget = breakTarget;
 730     void* prevContinueTarget = continueTarget;
 731     boundForStatement.InitS()->Accept(*this);
 732     void* condBlock = emitter->CreateBasicBlock("cond");
 733     void* actionBlock = emitter->CreateBasicBlock("action");
 734     void* loopBlock = emitter->CreateBasicBlock("loop");
 735     trueBlock = actionBlock;
 736     falseBlock = emitter->CreateBasicBlock("next");
 737     breakTarget = falseBlock;
 738     continueTarget = loopBlock;
 739     BoundCompoundStatement* prevBreakTargetBlock = breakTargetBlock;
 740     BoundCompoundStatement* prevContinueTargetBlock = continueTargetBlock;
 741     breakTargetBlock = currentBlock;
 742     continueTargetBlock = currentBlock;
 743     emitter->CreateBr(condBlock);
 744     emitter->SetCurrentBasicBlock(condBlock);
 745     bool prevGenJumpingBoolCode = genJumpingBoolCode;
 746     genJumpingBoolCode = true;
 747     boundForStatement.Condition()->Accept(*this);
 748     genJumpingBoolCode = prevGenJumpingBoolCode;
 749     emitter->SetCurrentBasicBlock(actionBlock);
 750     boundForStatement.ActionS()->Accept(*this);
 751     emitter->CreateBr(loopBlock);
 752     emitter->SetCurrentBasicBlock(loopBlock);
 753     boundForStatement.LoopS()->Accept(*this);
 754     emitter->CreateBr(condBlock);
 755     emitter->SetCurrentBasicBlock(falseBlock);
 756     basicBlockOpen = true;
 757     breakTargetBlock = prevBreakTargetBlock;
 758     continueTargetBlock = prevContinueTargetBlock;
 759     breakTarget = prevBreakTarget;
 760     continueTarget = prevContinueTarget;
 761     trueBlock = prevTrueBlock;
 762     falseBlock = prevFalseBlock;
 763 }
 764 
 765 void SystemXCodeGenerator::Visit(BoundSwitchStatement& boundSwitchStatement)
 766 {
 767     if (generateLineNumbers)
 768     {
 769         emitter->SetCurrentSourceSpan(boundSwitchStatement.GetSpan().line00);
 770     }
 771     destructorCallGenerated = false;
 772     lastInstructionWasRet = false;
 773     basicBlockOpen = false;
 774     SetTarget(&boundSwitchStatement);
 775     void* prevBreakTarget = breakTarget;
 776     BoundCompoundStatement* prevBreakTargetBlock = breakTargetBlock;
 777     breakTargetBlock = currentBlock;
 778     boundSwitchStatement.Condition()->Accept(*this);
 779     void* condition = emitter->Stack().Pop();
 780     void* prevDefaultDest = defaultDest;
 781     void* next = nullptr;
 782     if (boundSwitchStatement.DefaultStatement())
 783     {
 784         defaultDest = emitter->CreateBasicBlock("default");
 785         next = emitter->CreateBasicBlock("next");
 786     }
 787     else
 788     {
 789         defaultDest = emitter->CreateBasicBlock("next");
 790         next = defaultDest;
 791     }
 792     breakTarget = next;
 793     unsigned n = boundSwitchStatement.CaseStatements().size();
 794     void* switchInst = emitter->CreateSwitch(conditiondefaultDestn);
 795     std::std::unordered_map<IntegralValuevoid*IntegralValueHash>*prevCaseMap=currentCaseMap;
 796     std::unordered_map<IntegralValuevoid*IntegralValueHash> caseMap;
 797     currentCaseMap = &caseMap;
 798     for (unsigned i = 0; i < n; ++i)
 799     {
 800         const std::std::unique_ptr<BoundCaseStatement>&caseS=boundSwitchStatement.CaseStatements()[i];
 801         void* caseDest = emitter->CreateBasicBlock("case" + std::to_string(i));
 802         for (const std::std::unique_ptr<Value>&caseValue : caseS->CaseValues())
 803         {
 804             IntegralValue integralCaseValue(caseValue.get());
 805             caseMap[integralCaseValue] = caseDest;
 806             emitter->AddCase(switchInstcaseValue->IrValue(*emitter)caseDest);
 807         }
 808     }
 809     for (unsigned i = 0; i < n; ++i)
 810     {
 811         const std::std::unique_ptr<BoundCaseStatement>&caseS=boundSwitchStatement.CaseStatements()[i];
 812         caseS->Accept(*this);
 813         if (basicBlockOpen)
 814         {
 815             emitter->CreateBr(next);
 816             basicBlockOpen = false;
 817         }
 818     }
 819     if (boundSwitchStatement.DefaultStatement())
 820     {
 821         boundSwitchStatement.DefaultStatement()->Accept(*this);
 822         if (basicBlockOpen)
 823         {
 824             emitter->CreateBr(next);
 825             basicBlockOpen = false;
 826         }
 827     }
 828     emitter->SetCurrentBasicBlock(next);
 829     basicBlockOpen = true;
 830     currentCaseMap = prevCaseMap;
 831     defaultDest = prevDefaultDest;
 832     breakTargetBlock = prevBreakTargetBlock;
 833     breakTarget = prevBreakTarget;
 834 }
 835 
 836 void SystemXCodeGenerator::Visit(BoundCaseStatement& boundCaseStatement)
 837 {
 838     if (generateLineNumbers)
 839     {
 840         emitter->SetCurrentSourceSpan(boundCaseStatement.GetSpan().line00);
 841     }
 842     destructorCallGenerated = false;
 843     lastInstructionWasRet = false;
 844     basicBlockOpen = false;
 845     SetTarget(&boundCaseStatement);
 846     if (!boundCaseStatement.CaseValues().empty())
 847     {
 848         IntegralValue integralCaseValue(boundCaseStatement.CaseValues().front().get());
 849         auto it = currentCaseMap->find(integralCaseValue);
 850         if (it != currentCaseMap->cend())
 851         {
 852             void* caseDest = it->second;
 853             emitter->SetCurrentBasicBlock(caseDest);
 854             if (boundCaseStatement.CompoundStatement())
 855             {
 856                 boundCaseStatement.CompoundStatement()->Accept(*this);
 857             }
 858         }
 859         else
 860         {
 861             throw Exception("case not found"boundCaseStatement.GetSpan()boundCaseStatement.ModuleId());
 862         }
 863     }
 864     else
 865     {
 866         throw Exception("no cases"boundCaseStatement.GetSpan()boundCaseStatement.ModuleId());
 867     }
 868 
 869 }
 870 
 871 void SystemXCodeGenerator::Visit(BoundDefaultStatement& boundDefaultStatement)
 872 {
 873     if (generateLineNumbers)
 874     {
 875         emitter->SetCurrentSourceSpan(boundDefaultStatement.GetSpan().line00);
 876     }
 877     destructorCallGenerated = false;
 878     lastInstructionWasRet = false;
 879     basicBlockOpen = false;
 880     SetTarget(&boundDefaultStatement);
 881     if (defaultDest)
 882     {
 883         emitter->SetCurrentBasicBlock(defaultDest);
 884         if (boundDefaultStatement.CompoundStatement())
 885         {
 886             boundDefaultStatement.CompoundStatement()->Accept(*this);
 887         }
 888     }
 889     else
 890     {
 891         throw Exception("no default destination"boundDefaultStatement.GetSpan()boundDefaultStatement.ModuleId());
 892     }
 893 }
 894 
 895 void SystemXCodeGenerator::Visit(BoundConstructionStatement& boundConstructionStatement)
 896 {
 897     if (generateLineNumbers)
 898     {
 899         emitter->SetCurrentSourceSpan(boundConstructionStatement.GetSpan().line00);
 900     }
 901     destructorCallGenerated = false;
 902     lastInstructionWasRet = false;
 903     basicBlockOpen = false;
 904     SetTarget(&boundConstructionStatement);
 905     boundConstructionStatement.ConstructorCall()->Accept(*this);
 906     if (!boundConstructionStatement.ConstructorCall()->GetFunctionSymbol()->IsBasicTypeOperation())
 907     {
 908         int n = boundConstructionStatement.ConstructorCall()->Arguments().size();
 909         if (n > 0)
 910         {
 911             const std::std::unique_ptr<BoundExpression>&firstArgument=boundConstructionStatement.ConstructorCall()->Arguments()[0];
 912             TypeSymbol* firstArgumentBaseType = firstArgument->GetType()->BaseType();
 913             if (firstArgumentBaseType->IsClassTypeSymbol())
 914             {
 915                 if (firstArgument->GetType()->IsPointerType() && firstArgument->GetType()->RemovePointer(boundConstructionStatement.GetSpan()boundConstructionStatement.ModuleId())->IsClassTypeSymbol())
 916                 {
 917                     ClassTypeSymbol* classType = static_cast<ClassTypeSymbol*>(firstArgumentBaseType);
 918                     if (classType->Destructor())
 919                     {
 920                         newCleanupNeeded = true;
 921                         std::unique_ptr<BoundExpression> classPtrArgument(firstArgument->Clone());
 922                         std::unique_ptr<BoundFunctionCall> destructorCall(new BoundFunctionCall(currentBlock->EndSpan()currentBlock->ModuleId()classType->Destructor()));
 923                         destructorCall->AddArgument(std::move(classPtrArgument));
 924                         Assert(currentBlock"current block not set");
 925                         auto it = blockDestructionMap.find(currentBlock);
 926                         if (it != blockDestructionMap.cend())
 927                         {
 928                             std::std::vector<std::std::unique_ptr<BoundFunctionCall>>&destructorCallVec=it->second;
 929                             destructorCallVec.push_back(std::move(destructorCall));
 930                         }
 931                         else
 932                         {
 933                             Assert(false"block destruction not found");
 934                         }
 935                     }
 936                 }
 937             }
 938         }
 939     }
 940 }
 941 
 942 void SystemXCodeGenerator::Visit(BoundAssignmentStatement& boundAssignmentStatement)
 943 {
 944     if (generateLineNumbers)
 945     {
 946         emitter->SetCurrentSourceSpan(boundAssignmentStatement.GetSpan().line00);
 947     }
 948     destructorCallGenerated = false;
 949     lastInstructionWasRet = false;
 950     basicBlockOpen = false;
 951     SetTarget(&boundAssignmentStatement);
 952     boundAssignmentStatement.AssignmentCall()->Accept(*this);
 953 }
 954 
 955 void SystemXCodeGenerator::Visit(BoundExpressionStatement& boundExpressionStatement)
 956 {
 957     if (generateLineNumbers)
 958     {
 959         emitter->SetCurrentSourceSpan(boundExpressionStatement.GetSpan().line00);
 960     }
 961     destructorCallGenerated = false;
 962     lastInstructionWasRet = false;
 963     basicBlockOpen = false;
 964     SetTarget(&boundExpressionStatement);
 965     boundExpressionStatement.Expression()->Accept(*this);
 966     if (boundExpressionStatement.Expression()->HasValue())
 967     {
 968         emitter->Stack().Pop();
 969     }
 970 }
 971 
 972 void SystemXCodeGenerator::Visit(BoundInitializationStatement& boundInitializationStatement)
 973 {
 974     if (generateLineNumbers)
 975     {
 976         emitter->SetCurrentSourceSpan(boundInitializationStatement.GetSpan().line00);
 977     }
 978     destructorCallGenerated = false;
 979     lastInstructionWasRet = false;
 980     basicBlockOpen = false;
 981     SetTarget(&boundInitializationStatement);
 982     boundInitializationStatement.InitializationExpression()->Accept(*this);
 983     if (boundInitializationStatement.InitializationExpression()->HasValue())
 984     {
 985         emitter->Stack().Pop();
 986     }
 987 }
 988 
 989 void SystemXCodeGenerator::Visit(BoundEmptyStatement& boundEmptyStatement)
 990 {
 991     if (generateLineNumbers)
 992     {
 993         emitter->SetCurrentSourceSpan(boundEmptyStatement.GetSpan().line00);
 994     }
 995     destructorCallGenerated = false;
 996     lastInstructionWasRet = false;
 997     basicBlockOpen = false;
 998     SetTarget(&boundEmptyStatement);
 999     // todo
1000 }
1001 
1002 void SystemXCodeGenerator::Visit(BoundSetVmtPtrStatement& boundSetVmtPtrStatement)
1003 {
1004     destructorCallGenerated = false;
1005     lastInstructionWasRet = false;
1006     basicBlockOpen = false;
1007     SetTarget(&boundSetVmtPtrStatement);
1008     BoundExpression* classPtr = boundSetVmtPtrStatement.ClassPtr();
1009     TypeSymbol* type = classPtr->GetType()->BaseType();
1010     Assert(type->IsClassTypeSymbol()"class type expected");
1011     ClassTypeSymbol* classType = static_cast<ClassTypeSymbol*>(type);
1012     int32_t vmtPtrIndex = classType->VmtPtrIndex();
1013     Assert(vmtPtrIndex != -1"invalid vmt ptr index");
1014     classPtr->Accept(*this);
1015     void* classPtrValue = emitter->Stack().Pop();
1016     void* ptr = emitter->GetMemberVariablePtr(classPtrValuevmtPtrIndex);
1017     void* vmtPtr = emitter->CreateBitCast(boundSetVmtPtrStatement.ClassType()->VmtObject(*emitterfalse)emitter->GetIrTypeForVoidPtrType());
1018     emitter->CreateStore(vmtPtrptr);
1019 }
1020 
1021 void SystemXCodeGenerator::Visit(BoundThrowStatement& boundThrowStatement)
1022 {
1023     if (generateLineNumbers)
1024     {
1025         emitter->SetCurrentSourceSpan(boundThrowStatement.GetSpan().line00);
1026     }
1027     destructorCallGenerated = false;
1028     lastInstructionWasRet = false;
1029     basicBlockOpen = false;
1030     SetTarget(&boundThrowStatement);
1031     boundThrowStatement.ThrowCallExpr()->Accept(*this);
1032 }
1033 
1034 void SystemXCodeGenerator::Visit(BoundTryStatement& boundTryStatement)
1035 {
1036     if (generateLineNumbers)
1037     {
1038         emitter->SetCurrentSourceSpan(boundTryStatement.GetSpan().line00);
1039     }
1040     destructorCallGenerated = false;
1041     lastInstructionWasRet = false;
1042     basicBlockOpen = false;
1043     SetTarget(&boundTryStatement);
1044     void* prevHandlerBlock = handlerBlock;
1045     void* prevCleanupBlock = cleanupBlock;
1046     handlerBlock = emitter->CreateBasicBlock("handlers");
1047     cleanupBlock = nullptr;
1048     int64_t parentTryBlockId = currentTryBlockId;
1049     currentTryBlockId = nextTryBlockId++;
1050     void* nop1 = emitter->CreateNop();
1051     void* beginTry = emitter->CreateMDStruct();
1052     emitter->AddMDItem(beginTry"nodeType"emitter->CreateMDLong(beginTryNodeType));
1053     emitter->AddMDItem(beginTry"tryBlockId"emitter->CreateMDLong(currentTryBlockId));
1054     emitter->AddMDItem(beginTry"parentTryBlockId"emitter->CreateMDLong(parentTryBlockId));
1055     int beginTryId = emitter->GetMDStructId(beginTry);
1056     void* beginTryMdRef = emitter->CreateMDStructRef(beginTryId);
1057     emitter->SetMetadataRef(nop1beginTryMdRef);
1058     bool prevInTryBlock = inTryBlock;
1059     inTryBlock = true;
1060     boundTryStatement.TryBlock()->Accept(*this);
1061     inTryBlock = prevInTryBlock;
1062     void* nop2 = emitter->CreateNop();
1063     void* endTry = emitter->CreateMDStruct();
1064     emitter->AddMDItem(endTry"nodeType"emitter->CreateMDLong(endTryNodeType));
1065     emitter->AddMDItem(endTry"tryBlockId"emitter->CreateMDLong(currentTryBlockId));
1066     int endTryId = emitter->GetMDStructId(endTry);
1067     void* endTryMdRef = emitter->CreateMDStructRef(endTryId);
1068     emitter->SetMetadataRef(nop2endTryMdRef);
1069     void* tryNextBlock = emitter->CreateBasicBlock("tryNext");
1070     emitter->CreateBr(tryNextBlock);
1071     void* prevTryNextBlock = currentTryNextBlock;
1072     currentTryNextBlock = tryNextBlock;
1073     handlerBlock = prevHandlerBlock;
1074     for (const auto& c : boundTryStatement.Catches())
1075     {
1076         c->Accept(*this);
1077     }
1078     emitter->SetCurrentBasicBlock(tryNextBlock);
1079     currentTryBlockId = parentTryBlockId;
1080     currentTryNextBlock = prevTryNextBlock;
1081     cleanupBlock = prevCleanupBlock;
1082     basicBlockOpen = true;
1083 }
1084 
1085 void SystemXCodeGenerator::Visit(BoundCatchStatement& boundCatchStatement)
1086 {
1087     if (generateLineNumbers)
1088     {
1089         emitter->SetCurrentSourceSpan(boundCatchStatement.GetSpan().line00);
1090     }
1091     destructorCallGenerated = false;
1092     lastInstructionWasRet = false;
1093     basicBlockOpen = false;
1094     SetTarget(&boundCatchStatement);
1095     void* catchBlock = emitter->CreateBasicBlock("catch");
1096     emitter->SetCurrentBasicBlock(catchBlock);
1097     void* nop1 = emitter->CreateNop();
1098     void* catch_ = emitter->CreateMDStruct();
1099     emitter->AddMDItem(catch_"nodeType"emitter->CreateMDLong(catchNodeType));
1100     emitter->AddMDItem(catch_"tryBlockId"emitter->CreateMDLong(currentTryBlockId));
1101     emitter->AddMDItem(catch_"catchBlockId"emitter->CreateMDBasicBlockRef(catchBlock));
1102     const boost::uuids::uuid& uuid = compileUnit->GetUuid(boundCatchStatement.CatchedTypeUuidId());
1103     std::string uuidStr;
1104     for (const auto x : uuid)
1105     {
1106         uuidStr.append(soulng::util::ToHexString(x));
1107     }
1108     emitter->AddMDItem(catch_"catchedTypeId"emitter->CreateMDString(uuidStr));
1109     int catchId = emitter->GetMDStructId(catch_);
1110     void* catchMdRef = emitter->CreateMDStructRef(catchId);
1111     emitter->SetMetadataRef(nop1catchMdRef);
1112     boundCatchStatement.CatchBlock()->Accept(*this);
1113     emitter->CreateBr(currentTryNextBlock);
1114     emitter->SetCurrentBasicBlock(currentTryNextBlock);
1115 }
1116 
1117 void SystemXCodeGenerator::Visit(BoundRethrowStatement& boundRethrowStatement)
1118 {
1119     // TODO???
1120     if (generateLineNumbers)
1121     {
1122         emitter->SetCurrentSourceSpan(boundRethrowStatement.GetSpan().line00);
1123     }
1124     destructorCallGenerated = false;
1125     lastInstructionWasRet = false;
1126     basicBlockOpen = false;
1127     SetTarget(&boundRethrowStatement);
1128     void* resumeFunctionType = emitter->GetIrTypeForFunction(emitter->GetIrTypeForVoid()std::vector<void*>());
1129     void* callee = emitter->GetOrInsertFunction("do_resume"resumeFunctionTypefalse);
1130     emitter->CreateCall(calleestd::vector<void*>());
1131     emitter->CreateRetVoid();
1132 }
1133 
1134 void SystemXCodeGenerator::Visit(BoundParameter& boundParameter)
1135 {
1136     boundParameter.Load(*emitterOperationFlags::none);
1137     GenJumpingBoolCode();
1138 }
1139 
1140 void SystemXCodeGenerator::Visit(BoundLocalVariable& boundLocalVariable)
1141 {
1142     boundLocalVariable.Load(*emitterOperationFlags::none);
1143     GenJumpingBoolCode();
1144 }
1145 
1146 void SystemXCodeGenerator::Visit(BoundMemberVariable& boundMemberVariable)
1147 {
1148     boundMemberVariable.Load(*emitterOperationFlags::none);
1149     GenJumpingBoolCode();
1150 }
1151 
1152 void SystemXCodeGenerator::Visit(BoundConstant& boundConstant)
1153 {
1154     boundConstant.Load(*emitterOperationFlags::none);
1155     GenJumpingBoolCode();
1156 }
1157 
1158 void SystemXCodeGenerator::Visit(BoundEnumConstant& boundEnumConstant)
1159 {
1160     boundEnumConstant.Load(*emitterOperationFlags::none);
1161     GenJumpingBoolCode();
1162 }
1163 
1164 void SystemXCodeGenerator::Visit(BoundLiteral& boundLiteral)
1165 {
1166     boundLiteral.Load(*emitterOperationFlags::none);
1167     GenJumpingBoolCode();
1168 }
1169 
1170 void SystemXCodeGenerator::Visit(BoundTemporary& boundTemporary)
1171 {
1172     boundTemporary.Load(*emitterOperationFlags::none);
1173     GenJumpingBoolCode();
1174 }
1175 
1176 void SystemXCodeGenerator::Visit(BoundSizeOfExpression& boundSizeOfExpression)
1177 {
1178     boundSizeOfExpression.Load(*emitterOperationFlags::none);
1179 }
1180 
1181 void SystemXCodeGenerator::Visit(BoundAddressOfExpression& boundAddressOfExpression)
1182 {
1183     boundAddressOfExpression.Load(*emitterOperationFlags::none);
1184 }
1185 
1186 void SystemXCodeGenerator::Visit(BoundDereferenceExpression& boundDereferenceExpression)
1187 {
1188     boundDereferenceExpression.Load(*emitterOperationFlags::none);
1189     GenJumpingBoolCode();
1190 }
1191 
1192 void SystemXCodeGenerator::Visit(BoundReferenceToPointerExpression& boundReferenceToPointerExpression)
1193 {
1194     boundReferenceToPointerExpression.Load(*emitterOperationFlags::none);
1195 }
1196 
1197 void SystemXCodeGenerator::Visit(BoundFunctionCall& boundFunctionCall)
1198 {
1199     boundFunctionCall.Load(*emitterOperationFlags::none);
1200     GenJumpingBoolCode();
1201 }
1202 
1203 void SystemXCodeGenerator::Visit(BoundDelegateCall& boundDelegateCall)
1204 {
1205     boundDelegateCall.Load(*emitterOperationFlags::none);
1206     GenJumpingBoolCode();
1207 }
1208 
1209 void SystemXCodeGenerator::Visit(BoundClassDelegateCall& boundClassDelegateCall)
1210 {
1211     boundClassDelegateCall.Load(*emitterOperationFlags::none);
1212     GenJumpingBoolCode();
1213 }
1214 
1215 void SystemXCodeGenerator::Visit(BoundConversion& boundConversion)
1216 {
1217     boundConversion.Load(*emitterOperationFlags::none);
1218     GenJumpingBoolCode();
1219 }
1220 
1221 void SystemXCodeGenerator::Visit(BoundConstructExpression& boundConstructExpression)
1222 {
1223     boundConstructExpression.Load(*emitterOperationFlags::none);
1224     GenJumpingBoolCode();
1225 }
1226 
1227 void SystemXCodeGenerator::Visit(BoundConstructAndReturnTemporaryExpression& boundConstructAndReturnTemporaryExpression)
1228 {
1229     boundConstructAndReturnTemporaryExpression.Load(*emitterOperationFlags::none);
1230     GenJumpingBoolCode();
1231 }
1232 
1233 void SystemXCodeGenerator::Visit(BoundClassOrClassDelegateConversionResult& boundClassOrClassDelegateConversionResult)
1234 {
1235     boundClassOrClassDelegateConversionResult.Load(*emitterOperationFlags::none);
1236     GenJumpingBoolCode();
1237 }
1238 
1239 void SystemXCodeGenerator::Visit(BoundIsExpression& boundIsExpression)
1240 {
1241     boundIsExpression.Load(*emitterOperationFlags::none);
1242     GenJumpingBoolCode();
1243 }
1244 
1245 void SystemXCodeGenerator::Visit(BoundAsExpression& boundAsExpression)
1246 {
1247     boundAsExpression.Load(*emitterOperationFlags::none);
1248 }
1249 
1250 void SystemXCodeGenerator::Visit(BoundTypeNameExpression& boundTypeNameExpression)
1251 {
1252     boundTypeNameExpression.Load(*emitterOperationFlags::none);
1253 }
1254 
1255 void SystemXCodeGenerator::Visit(BoundBitCast& boundBitCast)
1256 {
1257     boundBitCast.Load(*emitterOperationFlags::none);
1258 }
1259 
1260 void SystemXCodeGenerator::Visit(BoundFunctionPtr& boundFunctionPtr)
1261 {
1262     boundFunctionPtr.Load(*emitterOperationFlags::none);
1263 }
1264 
1265 void SystemXCodeGenerator::Visit(BoundDisjunction& boundDisjunction)
1266 {
1267     if (genJumpingBoolCode)
1268     {
1269         Assert(trueBlock"true block not set");
1270         Assert(falseBlock"false block not set");
1271         void* rightBlock = emitter->CreateBasicBlock("right");
1272         void* prevFalseBlock = falseBlock;
1273         falseBlock = rightBlock;
1274         boundDisjunction.Left()->Accept(*this);
1275         emitter->SetCurrentBasicBlock(rightBlock);
1276         falseBlock = prevFalseBlock;
1277         boundDisjunction.Right()->Accept(*this);
1278         boundDisjunction.DestroyTemporaries(*emitter);
1279     }
1280 }
1281 
1282 void SystemXCodeGenerator::Visit(BoundConjunction& boundConjunction)
1283 {
1284     if (genJumpingBoolCode)
1285     {
1286         Assert(trueBlock"true block not set");
1287         Assert(falseBlock"false block not set");
1288         void* rightBlock = emitter->CreateBasicBlock("right");
1289         void* prevTrueBlock = trueBlock;
1290         trueBlock = rightBlock;
1291         boundConjunction.Left()->Accept(*this);
1292         trueBlock = prevTrueBlock;
1293         emitter->SetCurrentBasicBlock(rightBlock);
1294         boundConjunction.Right()->Accept(*this);
1295         boundConjunction.DestroyTemporaries(*emitter);
1296     }
1297 }
1298 
1299 void SystemXCodeGenerator::Visit(BoundGlobalVariable& boundGlobalVariable)
1300 {
1301     GlobalVariableSymbol* globalVariableSymbol = boundGlobalVariable.GetGlobalVariableSymbol();
1302     globalVariableSymbol->CreateIrObject(*emitter);
1303 }
1304 
1305 void SystemXCodeGenerator::GenJumpingBoolCode()
1306 {
1307     if (!genJumpingBoolCode) return;
1308     Assert(trueBlock"true block not set");
1309     Assert(falseBlock"false block not set");
1310     void* cond = emitter->Stack().Pop();
1311     if (sequenceSecond)
1312     {
1313         genJumpingBoolCode = false;
1314         sequenceSecond->SetGenerated();
1315         sequenceSecond->Accept(*this);
1316         genJumpingBoolCode = true;
1317     }
1318     emitter->CreateCondBr(condtrueBlockfalseBlock);
1319 }
1320 
1321 void SystemXCodeGenerator::SetTarget(BoundStatement* labeledStatement)
1322 {
1323     if (labeledStatement->Label().empty()) return;
1324     auto it = labeledStatementMap.find(labeledStatement);
1325     if (it != labeledStatementMap.cend())
1326     {
1327         void* target = it->second;
1328         emitter->CreateBr(target);
1329         emitter->SetCurrentBasicBlock(target);
1330     }
1331     else
1332     {
1333         throw Exception("target for labeled statement not found"labeledStatement->GetSpan()labeledStatement->ModuleId());
1334     }
1335 }
1336 
1337 void SystemXCodeGenerator::ExitBlocks(BoundCompoundStatement* targetBlock)
1338 {
1339     bool createBasicBlock = false;
1340     BoundStatement* lastStatement = nullptr;
1341     if (!currentFunction->Body()->Statements().empty())
1342     {
1343         lastStatement = currentFunction->Body()->Statements().back().get();
1344     }
1345     BoundStatement* currentBlockLastStatement = nullptr;
1346     if (currentBlock && !currentBlock->Statements().empty())
1347     {
1348         currentBlockLastStatement = currentBlock->Statements().back().get();
1349     }
1350     if (lastStatement && currentBlockLastStatement && lastStatement == currentBlockLastStatement && currentBlockLastStatement->GetBoundNodeType() == BoundNodeType::boundReturnStatement)
1351     {
1352         createBasicBlock = true;
1353     }
1354     int n = blocks.size();
1355     for (int i = n - 1; i >= 0; --i)
1356     {
1357         BoundCompoundStatement* block = blocks[i];
1358         if (block == targetBlock)
1359         {
1360             break;
1361         }
1362         auto it = blockDestructionMap.find(block);
1363         if (it != blockDestructionMap.cend())
1364         {
1365             std::std::vector<std::std::unique_ptr<BoundFunctionCall>>&destructorCallVec=it->second;
1366             int nd = destructorCallVec.size();
1367             for (int i = nd - 1; i >= 0; --i)
1368             {
1369                 std::std::unique_ptr<BoundFunctionCall>&destructorCall=destructorCallVec[i];
1370                 if (destructorCall)
1371                 {
1372                     if (createBasicBlock)
1373                     {
1374                         void* nextBlock = emitter->CreateBasicBlock("next");
1375                         if (!lastInstructionWasRet)
1376                         {
1377                             emitter->CreateBr(nextBlock);
1378                         }
1379                         emitter->SetCurrentBasicBlock(nextBlock);
1380                         createBasicBlock = false;
1381                     }
1382                     destructorCall->Accept(*this);
1383                     destructorCallGenerated = true;
1384                     newCleanupNeeded = true;
1385                 }
1386             }
1387         }
1388     }
1389 }
1390 
1391 void* SystemXCodeGenerator::GetGlobalStringPtr(int stringId)
1392 {
1393     auto it = utf8stringMap.find(stringId);
1394     if (it != utf8stringMap.cend())
1395     {
1396         return it->second;
1397     }
1398     else
1399     {
1400         void* stringValue = emitter->CreateGlobalStringPtr(compileUnit->GetUtf8String(stringId));
1401         utf8stringMap[stringId] = stringValue;
1402         return stringValue;
1403     }
1404 }
1405 
1406 void* SystemXCodeGenerator::GetGlobalWStringConstant(int stringId)
1407 {
1408     auto it = utf16stringMap.find(stringId);
1409     if (it != utf16stringMap.cend())
1410     {
1411         return it->second;
1412     }
1413     else
1414     {
1415         const std::u16string& str = compileUnit->GetUtf16String(stringId);
1416         uint64_t length = str.length();
1417         std::vector<void*> wcharConstants;
1418         for (char16_t c : str)
1419         {
1420             wcharConstants.push_back(emitter->CreateIrValueForUShort(static_cast<uint16_t>(c)));
1421         }
1422         wcharConstants.push_back(emitter->CreateIrValueForUShort(static_cast<uint16_t>(0)));
1423         void* arrayType = emitter->GetIrTypeForArrayType(emitter->GetIrTypeForUShort()length + 1);
1424         void* stringObject = emitter->GetOrInsertGlobal("wstring" + std::to_string(stringId) + "_" + compileUnitIdemitter->GetIrTypeForUShort());
1425         void* stringGlobal = stringObject;
1426         emitter->SetPrivateLinkage(stringGlobal);
1427         void* constant = emitter->CreateIrValueForConstantArray(arrayTypewcharConstants"w");
1428         emitter->SetInitializer(stringGlobalconstant);
1429         void* stringValue = stringGlobal;
1430         utf16stringMap[stringId] = stringValue;
1431         return stringValue;
1432     }
1433 }
1434 
1435 void* SystemXCodeGenerator::GetGlobalUStringConstant(int stringId)
1436 {
1437     auto it = utf32stringMap.find(stringId);
1438     if (it != utf32stringMap.cend())
1439     {
1440         return it->second;
1441     }
1442     else
1443     {
1444         const std::u32string& str = compileUnit->GetUtf32String(stringId);
1445         uint64_t length = str.length();
1446         std::vector<void*> ucharConstants;
1447         for (char32_t c : str)
1448         {
1449             ucharConstants.push_back(emitter->CreateIrValueForUInt(static_cast<uint32_t>(c)));
1450         }
1451         ucharConstants.push_back(emitter->CreateIrValueForUInt(static_cast<uint32_t>(0)));
1452         void* arrayType = emitter->GetIrTypeForArrayType(emitter->GetIrTypeForUInt()length + 1);
1453         void* stringObject = emitter->GetOrInsertGlobal("ustring" + std::to_string(stringId) + "_" + compileUnitIdemitter->GetIrTypeForUInt());
1454         void* stringGlobal = stringObject;
1455         emitter->SetPrivateLinkage(stringGlobal);
1456         void* constant = emitter->CreateIrValueForConstantArray(arrayTypeucharConstants"u");
1457         emitter->SetInitializer(stringGlobalconstant);
1458         void* stringValue = stringGlobal;
1459         utf32stringMap[stringId] = stringValue;
1460         return stringValue;
1461     }
1462 }
1463 
1464 void* SystemXCodeGenerator::GetGlobalUuidConstant(int uuidId)
1465 {
1466     auto it = uuidMap.find(uuidId);
1467     if (it != uuidMap.cend())
1468     {
1469         return it->second;
1470     }
1471     else
1472     {
1473         const boost::uuids::uuid& uuid = compileUnit->GetUuid(uuidId);
1474         uint64_t length = uuid.static_size();
1475         std::vector<void*> byteConstants;
1476         for (boost::uuids::uuid::value_type x : uuid)
1477         {
1478             byteConstants.push_back(emitter->CreateIrValueForByte(static_cast<int8_t>(x)));
1479         }
1480         void* arrayType = emitter->GetIrTypeForArrayType(emitter->GetIrTypeForByte()length);
1481         void* uuidObject = emitter->GetOrInsertGlobal("uuid" + std::to_string(uuidId) + "_" + compileUnitIdemitter->GetIrTypeForByte());
1482         void* uuidGlobal = uuidObject;
1483         emitter->SetPrivateLinkage(uuidGlobal);
1484         void* constant = emitter->CreateIrValueForConstantArray(arrayTypebyteConstants"b");
1485         emitter->SetInitializer(uuidGlobalconstant);
1486         void* uuidValue = uuidGlobal;
1487         uuidMap[uuidId] = uuidValue;
1488         return uuidValue;
1489     }
1490 }
1491 
1492 void* SystemXCodeGenerator::HandlerBlock()
1493 {
1494     return handlerBlock;
1495 }
1496 
1497 void* SystemXCodeGenerator::CleanupBlock()
1498 {
1499     return cleanupBlock;
1500 }
1501 
1502 bool SystemXCodeGenerator::NewCleanupNeeded()
1503 {
1504     return newCleanupNeeded;
1505 }
1506 
1507 bool SystemXCodeGenerator::InTryBlock() const
1508 {
1509     return inTryBlock;
1510 }
1511 
1512 int SystemXCodeGenerator::CurrentTryBlockId() const
1513 {
1514     return currentTryBlockId;
1515 }
1516 
1517 int SystemXCodeGenerator::Install(const std::string& str)
1518 {
1519     return compileUnit->Install(str);
1520 }
1521 
1522 int SystemXCodeGenerator::Install(const std::u16string& str)
1523 {
1524     return compileUnit->Install(str);
1525 }
1526 
1527 int SystemXCodeGenerator::Install(const std::u32string& str)
1528 {
1529     return compileUnit->Install(str);
1530 }
1531 
1532 void SystemXCodeGenerator::CreateCleanup()
1533 {
1534     cleanupBlock = emitter->CreateBasicBlock("cleanup");
1535     BoundCompoundStatement* targetBlock = nullptr;
1536     BoundStatement* parent = currentBlock->Parent();
1537     while (parent && parent->GetBoundNodeType() != BoundNodeType::boundTryStatement)
1538     {
1539         parent = parent->Parent();
1540     }
1541     if (parent)
1542     {
1543         targetBlock = parent->Block();
1544     }
1545     Cleanup* cleanup = new Cleanup(cleanupBlock);
1546     int n = blocks.size();
1547     for (int i = n - 1; i >= 0; --i)
1548     {
1549         BoundCompoundStatement* block = blocks[i];
1550         if (block == targetBlock)
1551         {
1552             break;
1553         }
1554         auto it = blockDestructionMap.find(block);
1555         if (it != blockDestructionMap.cend())
1556         {
1557             std::std::vector<std::std::unique_ptr<BoundFunctionCall>>&destructorCallVec=it->second;
1558             int nd = destructorCallVec.size();
1559             for (int i = nd - 1; i >= 0; --i)
1560             {
1561                 std::std::unique_ptr<BoundFunctionCall>&destructorCall=destructorCallVec[i];
1562                 if (destructorCall)
1563                 {
1564                     cleanup->destructors.push_back(std::unique_ptr<BoundFunctionCall>(static_cast<BoundFunctionCall*>(destructorCall->Clone())));
1565                 }
1566             }
1567         }
1568     }
1569     cleanups.push_back(std::unique_ptr<Cleanup>(cleanup));
1570     newCleanupNeeded = false;
1571 }
1572 
1573 void SystemXCodeGenerator::GenerateCodeForCleanups()
1574 {
1575     for (const std::std::unique_ptr<Cleanup>&cleanup : cleanups)
1576     {
1577         emitter->SetCurrentBasicBlock(cleanup->cleanupBlock);
1578         for (const std::std::unique_ptr<BoundFunctionCall>&destructorCall : cleanup->destructors)
1579         {
1580             destructorCall->Accept(*this);
1581         }
1582         void* resumeFunctionType = emitter->GetIrTypeForFunction(emitter->GetIrTypeForVoid()std::vector<void*>());
1583         void* callee = emitter->GetOrInsertFunction("do_resume"resumeFunctionTypefalse);
1584         emitter->CreateCall(calleestd::vector<void*>());
1585         emitter->CreateRetVoid();
1586     }
1587 }
1588 
1589 } } // namespace cmajor::codegensx