1
2
3
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(emitter, intermediateFilePath);
64 compileUnitId = boundCompileUnit.Id();
65 emitter->SetCompileUnitId(compileUnitId);
66 emitter->SetCurrentSourceSpan(0, 0, 0);
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(*emitter, true);
78 }
79 ConstantStructureRepository& constantStructureRepository = boundCompileUnit.GetConstantStructureRepository();
80 for (ConstantSymbol* constantSymbol : constantStructureRepository.ConstantStructures())
81 {
82 constantSymbol->StructureIrObject(*emitter, true);
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(intermediateCompileCommand, redirections);
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(assembleCommand, redirections);
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().line, 0, 0);
206 }
207 else
208 {
209 generateLineNumbers = false;
210 emitter->SetCurrentSourceSpan(0, 0, 0);
211 }
212 function = emitter->GetOrInsertFunction(ToUtf8(functionSymbol->MangledName()), functionType, functionSymbol->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(function, mdId);
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(function, fileIndex, functionSymbol->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(*emitter, true);
255 }
256 if (!emitter->IsStaticObjectCreated(classTypeSymbol))
257 {
258 classTypeSymbol->StaticObject(*emitter, true);
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(parameter, allocaInst);
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(parameter, allocaInst);
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(localVariable, allocaInst);
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(function, i);
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()), copyCtorType, copyConstructor->DontThrow());
314 std::vector<void*> args;
315 args.push_back(parameter->IrObject(*emitter));
316 args.push_back(arg);
317 emitter->CreateCall(callee, args);
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(¶mValue);
330 NativeValue argumentValue(arg);
331 copyCtorArgs.push_back(&argumentValue);
332 copyConstructor->GenerateCall(*emitter, copyCtorArgs, OperationFlags::none, boundFunction.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(¶mValue);
346 NativeValue argumentValue(arg);
347 argumentValue.SetType(interfaceType->AddPointer(Span(), boost::uuids::nil_uuid()));
348 copyCtorArgs.push_back(&argumentValue);
349 copyConstructor->GenerateCall(*emitter, copyCtorArgs, OperationFlags::none, boundFunction.Body()->GetSpan(), boundFunction.Body()->ModuleId());
350 }
351 else
352 {
353 emitter->CreateStore(arg, parameter->IrObject(*emitter));
354 }
355 }
356 if (functionSymbol->ReturnParam())
357 {
358 void* arg = emitter->GetFunctionArgument(function, np);
359 emitter->CreateStore(arg, functionSymbol->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(function, functionSymbol->HasCleanup());
390 }
391
392 void SystemXCodeGenerator::Visit(BoundCompoundStatement& boundCompoundStatement)
393 {
394 if (generateLineNumbers)
395 {
396 emitter->SetCurrentSourceSpan(boundCompoundStatement.GetSpan().line, 0, 0);
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().line, 0, 0);
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().line, 0, 0);
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().line, 0, 0);
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().line, 0, 0);
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().line, 0, 0);
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().line, 0, 0);
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().line, 0, 0);
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().line, 0, 0);
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().line, 0, 0);
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().line, 0, 0);
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().line, 0, 0);
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(condition, defaultDest, n);
795 std::std::unordered_map<IntegralValue, void*, IntegralValueHash>*prevCaseMap=currentCaseMap;
796 std::unordered_map<IntegralValue, void*, 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(switchInst, caseValue->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().line, 0, 0);
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().line, 0, 0);
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().line, 0, 0);
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().line, 0, 0);
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().line, 0, 0);
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().line, 0, 0);
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().line, 0, 0);
994 }
995 destructorCallGenerated = false;
996 lastInstructionWasRet = false;
997 basicBlockOpen = false;
998 SetTarget(&boundEmptyStatement);
999
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(classPtrValue, vmtPtrIndex);
1017 void* vmtPtr = emitter->CreateBitCast(boundSetVmtPtrStatement.ClassType()->VmtObject(*emitter, false), emitter->GetIrTypeForVoidPtrType());
1018 emitter->CreateStore(vmtPtr, ptr);
1019 }
1020
1021 void SystemXCodeGenerator::Visit(BoundThrowStatement& boundThrowStatement)
1022 {
1023 if (generateLineNumbers)
1024 {
1025 emitter->SetCurrentSourceSpan(boundThrowStatement.GetSpan().line, 0, 0);
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().line, 0, 0);
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(nop1, beginTryMdRef);
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(nop2, endTryMdRef);
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().line, 0, 0);
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(nop1, catchMdRef);
1112 boundCatchStatement.CatchBlock()->Accept(*this);
1113 emitter->CreateBr(currentTryNextBlock);
1114 emitter->SetCurrentBasicBlock(currentTryNextBlock);
1115 }
1116
1117 void SystemXCodeGenerator::Visit(BoundRethrowStatement& boundRethrowStatement)
1118 {
1119
1120 if (generateLineNumbers)
1121 {
1122 emitter->SetCurrentSourceSpan(boundRethrowStatement.GetSpan().line, 0, 0);
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", resumeFunctionType, false);
1130 emitter->CreateCall(callee, std::vector<void*>());
1131 emitter->CreateRetVoid();
1132 }
1133
1134 void SystemXCodeGenerator::Visit(BoundParameter& boundParameter)
1135 {
1136 boundParameter.Load(*emitter, OperationFlags::none);
1137 GenJumpingBoolCode();
1138 }
1139
1140 void SystemXCodeGenerator::Visit(BoundLocalVariable& boundLocalVariable)
1141 {
1142 boundLocalVariable.Load(*emitter, OperationFlags::none);
1143 GenJumpingBoolCode();
1144 }
1145
1146 void SystemXCodeGenerator::Visit(BoundMemberVariable& boundMemberVariable)
1147 {
1148 boundMemberVariable.Load(*emitter, OperationFlags::none);
1149 GenJumpingBoolCode();
1150 }
1151
1152 void SystemXCodeGenerator::Visit(BoundConstant& boundConstant)
1153 {
1154 boundConstant.Load(*emitter, OperationFlags::none);
1155 GenJumpingBoolCode();
1156 }
1157
1158 void SystemXCodeGenerator::Visit(BoundEnumConstant& boundEnumConstant)
1159 {
1160 boundEnumConstant.Load(*emitter, OperationFlags::none);
1161 GenJumpingBoolCode();
1162 }
1163
1164 void SystemXCodeGenerator::Visit(BoundLiteral& boundLiteral)
1165 {
1166 boundLiteral.Load(*emitter, OperationFlags::none);
1167 GenJumpingBoolCode();
1168 }
1169
1170 void SystemXCodeGenerator::Visit(BoundTemporary& boundTemporary)
1171 {
1172 boundTemporary.Load(*emitter, OperationFlags::none);
1173 GenJumpingBoolCode();
1174 }
1175
1176 void SystemXCodeGenerator::Visit(BoundSizeOfExpression& boundSizeOfExpression)
1177 {
1178 boundSizeOfExpression.Load(*emitter, OperationFlags::none);
1179 }
1180
1181 void SystemXCodeGenerator::Visit(BoundAddressOfExpression& boundAddressOfExpression)
1182 {
1183 boundAddressOfExpression.Load(*emitter, OperationFlags::none);
1184 }
1185
1186 void SystemXCodeGenerator::Visit(BoundDereferenceExpression& boundDereferenceExpression)
1187 {
1188 boundDereferenceExpression.Load(*emitter, OperationFlags::none);
1189 GenJumpingBoolCode();
1190 }
1191
1192 void SystemXCodeGenerator::Visit(BoundReferenceToPointerExpression& boundReferenceToPointerExpression)
1193 {
1194 boundReferenceToPointerExpression.Load(*emitter, OperationFlags::none);
1195 }
1196
1197 void SystemXCodeGenerator::Visit(BoundFunctionCall& boundFunctionCall)
1198 {
1199 boundFunctionCall.Load(*emitter, OperationFlags::none);
1200 GenJumpingBoolCode();
1201 }
1202
1203 void SystemXCodeGenerator::Visit(BoundDelegateCall& boundDelegateCall)
1204 {
1205 boundDelegateCall.Load(*emitter, OperationFlags::none);
1206 GenJumpingBoolCode();
1207 }
1208
1209 void SystemXCodeGenerator::Visit(BoundClassDelegateCall& boundClassDelegateCall)
1210 {
1211 boundClassDelegateCall.Load(*emitter, OperationFlags::none);
1212 GenJumpingBoolCode();
1213 }
1214
1215 void SystemXCodeGenerator::Visit(BoundConversion& boundConversion)
1216 {
1217 boundConversion.Load(*emitter, OperationFlags::none);
1218 GenJumpingBoolCode();
1219 }
1220
1221 void SystemXCodeGenerator::Visit(BoundConstructExpression& boundConstructExpression)
1222 {
1223 boundConstructExpression.Load(*emitter, OperationFlags::none);
1224 GenJumpingBoolCode();
1225 }
1226
1227 void SystemXCodeGenerator::Visit(BoundConstructAndReturnTemporaryExpression& boundConstructAndReturnTemporaryExpression)
1228 {
1229 boundConstructAndReturnTemporaryExpression.Load(*emitter, OperationFlags::none);
1230 GenJumpingBoolCode();
1231 }
1232
1233 void SystemXCodeGenerator::Visit(BoundClassOrClassDelegateConversionResult& boundClassOrClassDelegateConversionResult)
1234 {
1235 boundClassOrClassDelegateConversionResult.Load(*emitter, OperationFlags::none);
1236 GenJumpingBoolCode();
1237 }
1238
1239 void SystemXCodeGenerator::Visit(BoundIsExpression& boundIsExpression)
1240 {
1241 boundIsExpression.Load(*emitter, OperationFlags::none);
1242 GenJumpingBoolCode();
1243 }
1244
1245 void SystemXCodeGenerator::Visit(BoundAsExpression& boundAsExpression)
1246 {
1247 boundAsExpression.Load(*emitter, OperationFlags::none);
1248 }
1249
1250 void SystemXCodeGenerator::Visit(BoundTypeNameExpression& boundTypeNameExpression)
1251 {
1252 boundTypeNameExpression.Load(*emitter, OperationFlags::none);
1253 }
1254
1255 void SystemXCodeGenerator::Visit(BoundBitCast& boundBitCast)
1256 {
1257 boundBitCast.Load(*emitter, OperationFlags::none);
1258 }
1259
1260 void SystemXCodeGenerator::Visit(BoundFunctionPtr& boundFunctionPtr)
1261 {
1262 boundFunctionPtr.Load(*emitter, OperationFlags::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(cond, trueBlock, falseBlock);
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) + "_" + compileUnitId, emitter->GetIrTypeForUShort());
1425 void* stringGlobal = stringObject;
1426 emitter->SetPrivateLinkage(stringGlobal);
1427 void* constant = emitter->CreateIrValueForConstantArray(arrayType, wcharConstants, "w");
1428 emitter->SetInitializer(stringGlobal, constant);
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) + "_" + compileUnitId, emitter->GetIrTypeForUInt());
1454 void* stringGlobal = stringObject;
1455 emitter->SetPrivateLinkage(stringGlobal);
1456 void* constant = emitter->CreateIrValueForConstantArray(arrayType, ucharConstants, "u");
1457 emitter->SetInitializer(stringGlobal, constant);
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) + "_" + compileUnitId, emitter->GetIrTypeForByte());
1482 void* uuidGlobal = uuidObject;
1483 emitter->SetPrivateLinkage(uuidGlobal);
1484 void* constant = emitter->CreateIrValueForConstantArray(arrayType, byteConstants, "b");
1485 emitter->SetInitializer(uuidGlobal, constant);
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", resumeFunctionType, false);
1584 emitter->CreateCall(callee, std::vector<void*>());
1585 emitter->CreateRetVoid();
1586 }
1587 }
1588
1589 } }