1
2
3
4
5
6 #include <cmajor/symbols/VariableSymbol.hpp>
7 #include <cmajor/symbols/TypeSymbol.hpp>
8 #include <cmajor/symbols/SymbolTable.hpp>
9 #include <cmajor/symbols/SymbolWriter.hpp>
10 #include <cmajor/symbols/SymbolReader.hpp>
11 #include <cmajor/symbols/Exception.hpp>
12 #include <cmajor/symbols/SymbolCollector.hpp>
13 #include <cmajor/symbols/Module.hpp>
14 #include <soulng/util/Unicode.hpp>
15 #include <soulng/util/Sha1.hpp>
16 #include <algorithm>
17
18 namespace cmajor { namespace symbols {
19
20 using namespace soulng::unicode;
21
22 VariableSymbol::VariableSymbol(SymbolType symbolType_, const Span& span_, const boost::uuids::uuid& sourceModuleId_, const std::u32string& name_) :
23 Symbol(symbolType_, span_, sourceModuleId_, name_), type()
24 {
25 }
26
27 void VariableSymbol::Write(SymbolWriter& writer)
28 {
29 Symbol::Write(writer);
30 writer.GetBinaryWriter().Write(type->TypeId());
31 }
32
33 void VariableSymbol::Read(SymbolReader& reader)
34 {
35 Symbol::Read(reader);
36 boost::uuids::uuid typeId;
37 reader.GetBinaryReader().ReadUuid(typeId);
38 reader.GetSymbolTable()->EmplaceTypeRequest(reader, this, typeId, 0);
39 }
40
41 void VariableSymbol::EmplaceType(TypeSymbol* typeSymbol, int index)
42 {
43 Assert(index == 0, "invalid emplace type index");
44 type = typeSymbol;
45 }
46
47 const ContainerScope* VariableSymbol::GetTypeScope() const
48 {
49 if (type)
50 {
51 return type->BaseType()->GetContainerScope();
52 }
53 else
54 {
55 return nullptr;
56 }
57 }
58
59 ContainerScope* VariableSymbol::GetTypeScope()
60 {
61 if (type)
62 {
63 return type->BaseType()->GetContainerScope();
64 }
65 else
66 {
67 return nullptr;
68 }
69 }
70
71 void VariableSymbol::Check()
72 {
73 Symbol::Check();
74 if (!type)
75 {
76 throw SymbolCheckException("variable symbol contains null type pointer", GetSpan(), SourceModuleId());
77 }
78 }
79
80 std::string VariableSymbol::GetSymbolHelp() const
81 {
82 if (!type) return std::string();
83 std::string help = "(";
84 help.append(GetSymbolCategoryDescription()).append(") ");
85 help.append(ToUtf8(type->FullName())).append(" ");
86 help.append(ToUtf8(FullName()));
87 return help;
88 }
89
90 ParameterSymbol::ParameterSymbol(const Span& span_, const boost::uuids::uuid& sourceModuleId_, const std::u32string& name_) :
91 VariableSymbol(SymbolType::parameterSymbol, span_, sourceModuleId_, name_), artificialName(false)
92 {
93 }
94
95 void ParameterSymbol::Write(SymbolWriter& writer)
96 {
97 VariableSymbol::Write(writer);
98 writer.GetBinaryWriter().Write(artificialName);
99 }
100
101 void ParameterSymbol::Read(SymbolReader& reader)
102 {
103 VariableSymbol::Read(reader);
104 artificialName = reader.GetBinaryReader().ReadBool();
105 }
106
107 bool ParameterSymbol::IsExportSymbol() const
108 {
109 return VariableSymbol::IsExportSymbol();
110 }
111
112 std::u32string ParameterSymbol::CodeName() const
113 {
114 if (artificialName)
115 {
116 return std::u32string();
117 }
118 return VariableSymbol::CodeName();
119 }
120
121 std::std::unique_ptr<sngxml::dom::Element>ParameterSymbol::CreateDomElement(TypeMap&typeMap)
122 {
123 std::unique_ptr<sngxml::dom::Element> element(new sngxml::dom::Element(U"ParameterSymbol"));
124 if (GetType())
125 {
126 std::unique_ptr<sngxml::dom::Element> typeElement(new sngxml::dom::Element(U"type"));
127 int typeId = typeMap.GetOrInsertType(GetType());
128 typeElement->SetAttribute(U"ref", U"type_" + ToUtf32(std::to_string(typeId)));
129 element->AppendChild(std::unique_ptr<sngxml::dom::Node>(typeElement.release()));
130 }
131 return element;
132 }
133
134 ParameterSymbol* ParameterSymbol::Clone() const
135 {
136 ParameterSymbol* clone = new ParameterSymbol(GetSpan(), SourceModuleId(), Name());
137 clone->SetType(const_cast<TypeSymbol*>(GetType()));
138 clone->artificialName = artificialName;
139 return clone;
140 }
141
142 std::string ParameterSymbol::GetSymbolHelp() const
143 {
144 if (!GetType()) return std::string();
145 std::string help = "(";
146 help.append(GetSymbolCategoryDescription()).append(") ");
147 help.append(ToUtf8(GetType()->FullName())).append(" ");
148 help.append(ToUtf8(Name()));
149 return help;
150 }
151
152 LocalVariableSymbol::LocalVariableSymbol(const Span& span_, const boost::uuids::uuid& sourceModuleId_, const std::u32string& name_) :
153 VariableSymbol(SymbolType::localVariableSymbol, span_, sourceModuleId_, name_)
154 {
155 }
156
157 std::std::unique_ptr<sngxml::dom::Element>LocalVariableSymbol::CreateDomElement(TypeMap&typeMap)
158 {
159 std::unique_ptr<sngxml::dom::Element> element(new sngxml::dom::Element(U"LocalVariableSymbol"));
160 if (GetType())
161 {
162 std::unique_ptr<sngxml::dom::Element> typeElement(new sngxml::dom::Element(U"type"));
163 int typeId = typeMap.GetOrInsertType(GetType());
164 typeElement->SetAttribute(U"ref", U"type_" + ToUtf32(std::to_string(typeId)));
165 element->AppendChild(std::unique_ptr<sngxml::dom::Node>(typeElement.release()));
166 }
167 return element;
168 }
169
170 std::string LocalVariableSymbol::GetSymbolHelp() const
171 {
172 if (!GetType()) return std::string();
173 std::string help = "(";
174 help.append(GetSymbolCategoryDescription()).append(") ");
175 help.append(ToUtf8(GetType()->FullName())).append(" ");
176 help.append(ToUtf8(Name()));
177 return help;
178 }
179
180 MemberVariableSymbol::MemberVariableSymbol(const Span& span_, const boost::uuids::uuid& sourceModuleId_, const std::u32string& name_) :
181 VariableSymbol(SymbolType::memberVariableSymbol, span_, sourceModuleId_, name_), layoutIndex(-1)
182 {
183 }
184
185 void MemberVariableSymbol::Write(SymbolWriter& writer)
186 {
187 VariableSymbol::Write(writer);
188 writer.GetBinaryWriter().Write(layoutIndex);
189 }
190
191 void MemberVariableSymbol::Read(SymbolReader& reader)
192 {
193 VariableSymbol::Read(reader);
194 layoutIndex = reader.GetBinaryReader().ReadInt();
195 }
196
197 bool MemberVariableSymbol::IsExportSymbol() const
198 {
199 return VariableSymbol::IsExportSymbol();
200 }
201
202 void MemberVariableSymbol::Accept(SymbolCollector* collector)
203 {
204 if (IsProject() && Access() == SymbolAccess::public_)
205 {
206 collector->AddMemberVariable(this);
207 }
208 }
209
210 void MemberVariableSymbol::Dump(CodeFormatter& formatter)
211 {
212 formatter.WriteLine(ToUtf8(Name()));
213 formatter.WriteLine("full name: " + ToUtf8(FullNameWithSpecifiers()));
214 formatter.WriteLine("mangled name: " + ToUtf8(MangledName()));
215 formatter.WriteLine("type: " + ToUtf8(GetType()->FullName()));
216 formatter.WriteLine("layout index: " + std::to_string(layoutIndex));
217 }
218
219 std::string MemberVariableSymbol::Syntax() const
220 {
221 std::string syntax = GetSpecifierStr();
222 if (!syntax.empty())
223 {
224 syntax.append(1, ' ');
225 }
226 syntax.append(ToUtf8(GetType()->DocName()));
227 syntax.append(1, ' ');
228 syntax.append(ToUtf8(DocName()));
229 syntax.append(1, ';');
230 return syntax;
231 }
232
233 void MemberVariableSymbol::SetSpecifiers(Specifiers specifiers)
234 {
235 Specifiers accessSpecifiers = specifiers & Specifiers::access_;
236 SetAccess(accessSpecifiers);
237 if ((specifiers & Specifiers::static_) != Specifiers::none)
238 {
239 SetStatic();
240 }
241 if ((specifiers & Specifiers::virtual_) != Specifiers::none)
242 {
243 throw Exception("member variable cannot be virtual", GetSpan(), SourceModuleId());
244 }
245 if ((specifiers & Specifiers::override_) != Specifiers::none)
246 {
247 throw Exception("member variable cannot be override", GetSpan(), SourceModuleId());
248 }
249 if ((specifiers & Specifiers::abstract_) != Specifiers::none)
250 {
251 throw Exception("member variable cannot be abstract", GetSpan(), SourceModuleId());
252 }
253 if ((specifiers & Specifiers::inline_) != Specifiers::none)
254 {
255 throw Exception("member variable cannot be inline", GetSpan(), SourceModuleId());
256 }
257 if ((specifiers & Specifiers::explicit_) != Specifiers::none)
258 {
259 throw Exception("member variable cannot be explicit", GetSpan(), SourceModuleId());
260 }
261 if ((specifiers & Specifiers::external_) != Specifiers::none)
262 {
263 throw Exception("member variable cannot be external", GetSpan(), SourceModuleId());
264 }
265 if ((specifiers & Specifiers::suppress_) != Specifiers::none)
266 {
267 throw Exception("member variable cannot be suppressed", GetSpan(), SourceModuleId());
268 }
269 if ((specifiers & Specifiers::default_) != Specifiers::none)
270 {
271 throw Exception("member variable cannot be default", GetSpan(), SourceModuleId());
272 }
273 if ((specifiers & Specifiers::constexpr_) != Specifiers::none)
274 {
275 throw Exception("member variable cannot be constexpr", GetSpan(), SourceModuleId());
276 }
277 if ((specifiers & Specifiers::cdecl_) != Specifiers::none)
278 {
279 throw Exception("member variable cannot be cdecl", GetSpan(), SourceModuleId());
280 }
281 if ((specifiers & Specifiers::nothrow_) != Specifiers::none)
282 {
283 throw Exception("member variable cannot be nothrow", GetSpan(), SourceModuleId());
284 }
285 if ((specifiers & Specifiers::throw_) != Specifiers::none)
286 {
287 throw Exception("member variable cannot be throw", GetSpan(), SourceModuleId());
288 }
289 if ((specifiers & Specifiers::new_) != Specifiers::none)
290 {
291 throw Exception("member variable cannot be new", GetSpan(), SourceModuleId());
292 }
293 if ((specifiers & Specifiers::const_) != Specifiers::none)
294 {
295 throw Exception("member variable cannot be const", GetSpan(), SourceModuleId());
296 }
297 if ((specifiers & Specifiers::unit_test_) != Specifiers::none)
298 {
299 throw Exception("member variable cannot be unit_test", GetSpan(), SourceModuleId());
300 }
301 }
302
303 void* MemberVariableSymbol::GetDIMemberType(Emitter& emitter, uint64_t offsetInBits)
304 {
305 Assert(layoutIndex != -1, "invalid layout index");
306 Assert(Parent() && Parent()->IsClassTypeSymbol(), "parent class type expected");
307 ClassTypeSymbol* parentClassType = static_cast<ClassTypeSymbol*>(Parent());
308 std::pair<boost::uuids::uuid, int32_t> memberVariableId = std::make_pair(parentClassType->TypeId(), layoutIndex);
309 void* localDIType = emitter.GetDIMemberType(memberVariableId);
310 if (!localDIType)
311 {
312 uint64_t sizeInBits = GetType()->SizeInBits(emitter);
313 uint32_t alignInBits = GetType()->AlignmentInBits(emitter);
314 void* scope = parentClassType->GetDIType(emitter);
315 localDIType = emitter.CreateDIMemberType(scope, ToUtf8(Name()), GetSpan(), SourceModuleId(), sizeInBits, alignInBits, offsetInBits, GetType()->GetDIType(emitter));
316 emitter.SetDIMemberType(memberVariableId, localDIType);
317 }
318 return localDIType;
319 }
320
321 std::std::unique_ptr<sngxml::dom::Element>MemberVariableSymbol::CreateDomElement(TypeMap&typeMap)
322 {
323 std::unique_ptr<sngxml::dom::Element> element(new sngxml::dom::Element(U"MemberVariableSymbol"));
324 if (GetType())
325 {
326 std::unique_ptr<sngxml::dom::Element> typeElement(new sngxml::dom::Element(U"type"));
327 int typeId = typeMap.GetOrInsertType(GetType());
328 typeElement->SetAttribute(U"ref", U"type_" + ToUtf32(std::to_string(typeId)));
329 element->AppendChild(std::unique_ptr<sngxml::dom::Node>(typeElement.release()));
330 }
331 return element;
332 }
333
334 void MemberVariableSymbol::Check()
335 {
336 VariableSymbol::Check();
337 if (layoutIndex == -1)
338 {
339 throw SymbolCheckException("member variable symbol contains invalid layout index", GetSpan(), SourceModuleId());
340 }
341 }
342
343 GlobalVariableGroupSymbol::GlobalVariableGroupSymbol(const Span& span_, const boost::uuids::uuid& sourceModuleId_, const std::u32string& name_) :
344 Symbol(SymbolType::globalVariableGroupSymbol, span_, sourceModuleId_, name_)
345 {
346 }
347
348 void GlobalVariableGroupSymbol::ComputeMangledName()
349 {
350 std::u32string mangledName = ToUtf32(TypeString());
351 mangledName.append(1, U'_').append(ToUtf32(GetSha1MessageDigest(ToUtf8(FullNameWithSpecifiers()))));
352 SetMangledName(mangledName);
353 }
354
355 void GlobalVariableGroupSymbol::AddGlobalVariable(GlobalVariableSymbol* globalVariableSymbol)
356 {
357 std::pair<GlobalVariableSymbol*, std::string> key(globalVariableSymbol, globalVariableSymbol->CompileUnitFilePath());
358 if (globalVariableSymbols.empty())
359 {
360 globalVariableSymbols.push_back(key);
361 globalVariableSymbol->SetGlobalVariableGroup(this);
362 }
363 else
364 {
365 for (const std::std::pair<GlobalVariableSymbol*, std::string>&p : globalVariableSymbols)
366 {
367 if (p.first->Access() == SymbolAccess::internal_ || p.first->Access() == SymbolAccess::public_)
368 {
369 if (globalVariableSymbol->Access() == SymbolAccess::internal_ || globalVariableSymbol->Access() == SymbolAccess::public_)
370 {
371 throw Exception("global variable group '" + ToUtf8(Name()) +
372 "' already has public or internal global variable with the given name defined in the source file " + p.second,
373 globalVariableSymbol->GetSpan(), globalVariableSymbol->SourceModuleId(), GetSpan(), SourceModuleId());
374 }
375 }
376 else
377 {
378 if (p.second == globalVariableSymbol->CompileUnitFilePath())
379 {
380 throw Exception("global variable group '" + ToUtf8(Name()) + "' already has global variable with the given name and compile unit",
381 globalVariableSymbol->GetSpan(), globalVariableSymbol->SourceModuleId(), GetSpan(), SourceModuleId());
382 }
383 }
384 }
385 std::vector<std::std::pair<GlobalVariableSymbol*, std::string>>::const_iteratorit=std::find(globalVariableSymbols.cbegin(), globalVariableSymbols.cend(), key);
386 if (it == globalVariableSymbols.cend())
387 {
388 globalVariableSymbols.push_back(key);
389 globalVariableSymbol->SetGlobalVariableGroup(this);
390 }
391 else
392 {
393 throw Exception("global variable group '" + ToUtf8(Name()) + "' already has global variable with the given name and compile unit",
394 globalVariableSymbol->GetSpan(), globalVariableSymbol->SourceModuleId(), GetSpan(), SourceModuleId());
395 }
396 }
397 }
398
399 void GlobalVariableGroupSymbol::RemoveGlobalVariable(GlobalVariableSymbol* globalVariableSymbol)
400 {
401 std::pair<GlobalVariableSymbol*, std::string> key(globalVariableSymbol, globalVariableSymbol->CompileUnitFilePath());
402 auto end = std::remove(globalVariableSymbols.begin(), globalVariableSymbols.end(), key);
403 globalVariableSymbols.erase(end, globalVariableSymbols.end());
404 }
405
406 bool GlobalVariableGroupSymbol::IsEmpty() const
407 {
408 return globalVariableSymbols.empty();
409 }
410
411 void GlobalVariableGroupSymbol::CollectGlobalVariables(const std::string& compileUnitFilePath, std::std::vector<GlobalVariableSymbol*>&globalVariables) const
412 {
413 for (const std::std::pair<GlobalVariableSymbol*, std::string>&p : globalVariableSymbols)
414 {
415 if (p.second == compileUnitFilePath)
416 {
417 globalVariables.push_back(p.first);
418 return;
419 }
420 }
421 for (const std::std::pair<GlobalVariableSymbol*, std::string>&p : globalVariableSymbols)
422 {
423 if (p.first->Access() == SymbolAccess::public_ || p.first->Access() == SymbolAccess::internal_)
424 {
425 globalVariables.push_back(p.first);
426 return;
427 }
428 }
429 for (const std::std::pair<GlobalVariableSymbol*, std::string>&p : globalVariableSymbols)
430 {
431 globalVariables.push_back(p.first);
432 }
433 }
434
435 const ContainerScope* GlobalVariableGroupSymbol::GetTypeScope() const
436 {
437 for (const std::std::pair<GlobalVariableSymbol*, std::string>&p : globalVariableSymbols)
438 {
439 return p.first->GetTypeScope();
440 }
441 return nullptr;
442 }
443
444 ContainerScope* GlobalVariableGroupSymbol::GetTypeScope()
445 {
446 for (const std::std::pair<GlobalVariableSymbol*, std::string>&p : globalVariableSymbols)
447 {
448 return p.first->GetTypeScope();
449 }
450 return nullptr;
451 }
452
453 std::string GlobalVariableGroupSymbol::GetSymbolHelp() const
454 {
455 if (globalVariableSymbols.size() == 1)
456 {
457 return globalVariableSymbols.front().first->GetSymbolHelp();
458 }
459 std::string help = "(";
460 help.append(GetSymbolCategoryDescription()).append(") ");
461 help.append(ToUtf8(FullName())).append(" (").append(std::to_string(globalVariableSymbols.size())).append(" global variables)");
462 return help;
463 }
464
465 std::u32string MakeGlobalVariableName(const std::u32string& groupName, const std::string& compileUnitId)
466 {
467 std::u32string name = groupName;
468 name.append(1, '_').append(ToUtf32(compileUnitId));
469 return name;
470 }
471
472 GlobalVariableSymbol::GlobalVariableSymbol(const Span& span_, const boost::uuids::uuid& sourceModuleId_, const std::u32string& groupName_, const std::string& compileUnitId, const std::string& compileUnitFilePath_) :
473 VariableSymbol(SymbolType::globalVariableSymbol, span_, sourceModuleId_, MakeGlobalVariableName(groupName_, compileUnitId)), groupName(groupName_), compileUnitFilePath(compileUnitFilePath_),
474 globalVariableGroup(nullptr)
475 {
476 }
477
478 GlobalVariableSymbol::GlobalVariableSymbol(const Span& span_, const boost::uuids::uuid& sourceModuleId_, const std::u32string& name_) :
479 VariableSymbol(SymbolType::globalVariableSymbol, span_, sourceModuleId_, name_), globalVariableGroup(nullptr)
480 {
481 }
482
483 void GlobalVariableSymbol::Write(SymbolWriter& writer)
484 {
485 VariableSymbol::Write(writer);
486 writer.GetBinaryWriter().Write(groupName);
487 writer.GetBinaryWriter().Write(compileUnitFilePath);
488 bool hasInitializer = initializer != nullptr;
489 bool privateAccess = Access() == SymbolAccess::private_;
490 writer.GetBinaryWriter().Write(hasInitializer);
491 if (hasInitializer && !privateAccess)
492 {
493 WriteValue(initializer.get(), writer.GetBinaryWriter());
494 }
495 }
496
497 void GlobalVariableSymbol::Read(SymbolReader& reader)
498 {
499 VariableSymbol::Read(reader);
500 groupName = reader.GetBinaryReader().ReadUtf32String();
501 compileUnitFilePath = reader.GetBinaryReader().ReadUtf8String();
502 bool hasInitializer = reader.GetBinaryReader().ReadBool();
503 bool privateAccess = Access() == SymbolAccess::private_;
504 if (hasInitializer && !privateAccess)
505 {
506 initializer = ReadValue(reader.GetBinaryReader(), GetSpan(), SourceModuleId());
507 initializer->SetType(GetType());
508 }
509 }
510
511 bool GlobalVariableSymbol::IsExportSymbol() const
512 {
513 return VariableSymbol::IsExportSymbol();
514 }
515
516 void GlobalVariableSymbol::Accept(SymbolCollector* collector)
517 {
518 if (IsProject() && Access() == SymbolAccess::public_)
519 {
520 collector->AddGlobalVariable(this);
521 }
522 }
523
524 void GlobalVariableSymbol::Dump(CodeFormatter& formatter)
525 {
526 formatter.WriteLine(ToUtf8(Name()));
527 formatter.WriteLine("group name: " + ToUtf8(groupName));
528 formatter.WriteLine("full name: " + ToUtf8(FullNameWithSpecifiers()));
529 formatter.WriteLine("mangled name: " + ToUtf8(MangledName()));
530 formatter.WriteLine("type: " + ToUtf8(GetType()->FullName()));
531 }
532
533 std::string GlobalVariableSymbol::Syntax() const
534 {
535 std::string syntax = GetSpecifierStr();
536 if (!syntax.empty())
537 {
538 syntax.append(1, ' ');
539 }
540 syntax.append(ToUtf8(GetType()->DocName()));
541 syntax.append(1, ' ');
542 syntax.append(ToUtf8(DocName()));
543 syntax.append(1, ';');
544 return syntax;
545 }
546
547 void GlobalVariableSymbol::ComputeMangledName()
548 {
549 std::u32string mangledName = ToUtf32(TypeString());
550 mangledName.append(1, U'_').append(Name());
551 SetMangledName(mangledName);
552 }
553
554 void GlobalVariableSymbol::SetSpecifiers(Specifiers specifiers)
555 {
556 Specifiers accessSpecifiers = specifiers & Specifiers::access_;
557 SetAccess(accessSpecifiers);
558 if ((specifiers & Specifiers::static_) != Specifiers::none)
559 {
560 throw Exception("global variable cannot be static", GetSpan(), SourceModuleId());
561 }
562 if ((specifiers & Specifiers::virtual_) != Specifiers::none)
563 {
564 throw Exception("global variable cannot be virtual", GetSpan(), SourceModuleId());
565 }
566 if ((specifiers & Specifiers::override_) != Specifiers::none)
567 {
568 throw Exception("global variable cannot be override", GetSpan(), SourceModuleId());
569 }
570 if ((specifiers & Specifiers::abstract_) != Specifiers::none)
571 {
572 throw Exception("global variable cannot be abstract", GetSpan(), SourceModuleId());
573 }
574 if ((specifiers & Specifiers::inline_) != Specifiers::none)
575 {
576 throw Exception("global variable cannot be inline", GetSpan(), SourceModuleId());
577 }
578 if ((specifiers & Specifiers::explicit_) != Specifiers::none)
579 {
580 throw Exception("global variable cannot be explicit", GetSpan(), SourceModuleId());
581 }
582 if ((specifiers & Specifiers::external_) != Specifiers::none)
583 {
584 throw Exception("global variable cannot be external", GetSpan(), SourceModuleId());
585 }
586 if ((specifiers & Specifiers::suppress_) != Specifiers::none)
587 {
588 throw Exception("global variable cannot be suppressed", GetSpan(), SourceModuleId());
589 }
590 if ((specifiers & Specifiers::default_) != Specifiers::none)
591 {
592 throw Exception("global variable cannot be default", GetSpan(), SourceModuleId());
593 }
594 if ((specifiers & Specifiers::constexpr_) != Specifiers::none)
595 {
596 throw Exception("global variable cannot be constexpr", GetSpan(), SourceModuleId());
597 }
598 if ((specifiers & Specifiers::cdecl_) != Specifiers::none)
599 {
600 throw Exception("global variable cannot be cdecl", GetSpan(), SourceModuleId());
601 }
602 if ((specifiers & Specifiers::nothrow_) != Specifiers::none)
603 {
604 throw Exception("global variable cannot be nothrow", GetSpan(), SourceModuleId());
605 }
606 if ((specifiers & Specifiers::throw_) != Specifiers::none)
607 {
608 throw Exception("global variable cannot be throw", GetSpan(), SourceModuleId());
609 }
610 if ((specifiers & Specifiers::new_) != Specifiers::none)
611 {
612 throw Exception("global variable cannot be new", GetSpan(), SourceModuleId());
613 }
614 if ((specifiers & Specifiers::const_) != Specifiers::none)
615 {
616 throw Exception("global variable cannot be const", GetSpan(), SourceModuleId());
617 }
618 if ((specifiers & Specifiers::unit_test_) != Specifiers::none)
619 {
620 throw Exception("global variable cannot be unit_test", GetSpan(), SourceModuleId());
621 }
622 }
623
624 void GlobalVariableSymbol::SetInitializer(std::std::unique_ptr<Value>&&initializer_)
625 {
626 initializer = std::move(initializer_);
627 }
628
629 void* GlobalVariableSymbol::IrObject(Emitter& emitter)
630 {
631 return emitter.GetOrInsertGlobal(ToUtf8(MangledName()), GetType()->IrType(emitter));
632 }
633
634 void GlobalVariableSymbol::CreateIrObject(Emitter& emitter)
635 {
636 void* irObject = IrObject(emitter);
637 void* init = nullptr;
638 if (initializer == nullptr)
639 {
640 init = GetType()->CreateDefaultIrValue(emitter);
641 }
642 else
643 {
644 init = initializer->IrValue(emitter);
645 }
646 emitter.SetInitializer(irObject, init);
647 }
648
649 std::std::unique_ptr<Symbol>GlobalVariableSymbol::RemoveFromParent()
650 {
651 std::unique_ptr<Symbol> symbol = VariableSymbol::RemoveFromParent();
652 if (globalVariableGroup)
653 {
654 globalVariableGroup->RemoveGlobalVariable(this);
655 if (globalVariableGroup->IsEmpty())
656 {
657 std::unique_ptr<Symbol> globalVariableGroupSymbol = globalVariableGroup->RemoveFromParent();
658 }
659 }
660 return symbol;
661 }
662
663 } }