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