GCC Code Coverage Report


Directory: src/
File: src/frontend/function-scope.cpp
Date: 2025-10-15 09:43:47
Exec Total Coverage
Lines: 354 379 93.4%
Functions: 61 62 98.4%
Branches: 67 84 79.8%

Line Branch Exec Source
1
2 #include <gyoji-frontend.hpp>
3 #include <gyoji-frontend/function-scope.hpp>
4 #include <sstream>
5
6 using namespace Gyoji::frontend::lowering;
7
8 ///////////////////////////////////////////////////
9 // Graph-theoretic utilities just to walk graphs
10 // and find intersections, differences.
11 ///////////////////////////////////////////////////
12 24 static void walk_priors(
13 const std::map<size_t, size_t> & backward_edges,
14 size_t start_point,
15 std::map<size_t, size_t> & priors)
16 {
17 24 size_t p = start_point;
18 while (p >= 0) {
19 110 priors.insert(std::pair(p,p));
20 110 const auto & it = backward_edges.find(p);
21
2/2
✓ Branch 2 taken 24 times.
✓ Branch 3 taken 86 times.
110 if (it == backward_edges.end()) {
22 24 break;
23 }
24 86 p = it->second;
25 86 }
26 24 }
27
28 static void
29 12 evaluate_scope_changes(
30 const std::vector<const ScopeOperation*> & flat,
31 const std::map<size_t, size_t> & prior_to_goto,
32 const std::map<size_t, size_t> & prior_to_label,
33 std::vector<const ScopeOperation*> & skipped_initializations,
34 std::vector<const ScopeOperation*> & unwind_variables
35 )
36 {
37
2/2
✓ Branch 5 taken 56 times.
✓ Branch 6 taken 12 times.
68 for (const auto & lp : prior_to_label) {
38
2/2
✓ Branch 3 taken 20 times.
✓ Branch 4 taken 36 times.
56 if (prior_to_goto.find(lp.first) == prior_to_goto.end()) {
39 20 const ScopeOperation *op = flat.at(lp.first);
40
2/2
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 10 times.
20 if (op->get_type() == ScopeOperation::VAR_DECL) {
41 10 skipped_initializations.push_back(op);
42 }
43 }
44 }
45
2/2
✓ Branch 5 taken 54 times.
✓ Branch 6 taken 12 times.
66 for (const auto & gp : prior_to_goto) {
46
2/2
✓ Branch 3 taken 18 times.
✓ Branch 4 taken 36 times.
54 if (prior_to_label.find(gp.first) == prior_to_label.end()) {
47 18 const ScopeOperation *op = flat.at(gp.first);
48
2/2
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 10 times.
18 if (op->get_type() == ScopeOperation::VAR_DECL) {
49 8 unwind_variables.push_back(op);
50 }
51 }
52 }
53 // We reverse the list because
54 // we should unwind the variables
55 // in the reverse order they were declared in.
56 12 std::reverse(unwind_variables.begin(), unwind_variables.end());
57 12 }
58
59 ///////////////////////////////////////////////////
60 // ScopeOperation
61 ///////////////////////////////////////////////////
62 946 ScopeOperation::ScopeOperation(
63 ScopeOperationType _type,
64 const Gyoji::context::SourceReference & _source_ref
65 946 )
66 946 : type(_type)
67 946 , source_ref(_source_ref)
68 946 {}
69
70 946 ScopeOperation::~ScopeOperation()
71 946 {}
72
73 const ScopeOperation::ScopeOperationType &
74 86 ScopeOperation::get_type() const
75 86 { return type; }
76
77 const std::string &
78 18 ScopeOperation::get_label_name() const
79 18 { return label_name; }
80
81 const std::string &
82 40 ScopeOperation::get_goto_label() const
83 40 { return goto_label; }
84
85 const FunctionPoint &
86 4 ScopeOperation::get_goto_point() const
87 4 { return *goto_point; }
88
89 const std::string &
90 46 ScopeOperation::get_variable_name() const
91 46 { return variable_name; }
92
93 Gyoji::owned<ScopeOperation>
94 858 ScopeOperation::create_variable(
95 std::string _variable_name,
96 const Gyoji::mir::Type *_variable_type,
97 const Gyoji::context::SourceReference & _source_ref
98 )
99 {
100 858 auto op = Gyoji::owned<ScopeOperation>(new ScopeOperation(ScopeOperation::VAR_DECL, _source_ref));
101 858 op->variable_name = _variable_name;
102 858 op->variable_type = _variable_type;
103 858 return op;
104 }
105 Gyoji::owned<ScopeOperation>
106 10 ScopeOperation::create_label(
107 std::string _label_name,
108 const Gyoji::context::SourceReference & _source_ref
109 )
110 {
111 10 auto op = Gyoji::owned<ScopeOperation>(new ScopeOperation(ScopeOperation::LABEL_DEFINITION, _source_ref));
112 10 op->label_name = _label_name;
113 10 return op;
114 }
115
116 Gyoji::owned<ScopeOperation>
117 12 ScopeOperation::create_goto(
118 std::string _goto_label,
119 Gyoji::owned<FunctionPoint> _goto_point,
120 const Gyoji::context::SourceReference & _source_ref
121 )
122 {
123 12 auto op = Gyoji::owned<ScopeOperation>(new ScopeOperation(ScopeOperation::GOTO_DEFINITION, _source_ref));
124 12 op->goto_label = _goto_label;
125 12 op->goto_point = std::move(_goto_point);
126 12 return op;
127 }
128
129 Gyoji::owned<ScopeOperation>
130 66 ScopeOperation::create_child(
131 Gyoji::owned<Scope> _child,
132 const Gyoji::context::SourceReference & _source_ref
133 )
134 {
135 66 auto op = Gyoji::owned<ScopeOperation>(new ScopeOperation(ScopeOperation::CHILD_SCOPE, _source_ref));
136 66 op->child = std::move(_child);
137 66 return op;
138 }
139
140 const Gyoji::context::SourceReference &
141 12 ScopeOperation::get_source_ref() const
142 12 { return source_ref; }
143
144 ///////////////////////////////////////////////////
145 // Scope
146 ///////////////////////////////////////////////////
147 334 Scope::Scope()
148 334 : parent(nullptr)
149 334 , scope_is_loop(false)
150 334 , loop_break_blockid(0)
151 334 , loop_continue_blockid(0)
152 334 {}
153
154 4 Scope::Scope(
155 bool _is_loop,
156 size_t _loop_break_blockid,
157 size_t _loop_continue_blockid
158 4 )
159 4 : parent(nullptr)
160 4 , scope_is_loop(_is_loop)
161 4 , loop_break_blockid(_loop_break_blockid)
162 4 , loop_continue_blockid(_loop_continue_blockid)
163 4 {}
164
165 338 Scope::~Scope()
166 338 {}
167
168 void
169 946 Scope::add_operation(Gyoji::owned<ScopeOperation> op)
170 {
171 946 operations.push_back(std::move(op));
172 946 }
173
174 #if 0
175 void
176 Scope::add_variable(std::string name, const Gyoji::mir::Type *type, const Gyoji::context::SourceReference & source_ref)
177 {
178 }
179 #endif
180
181 const LocalVariable *
182 2230 Scope::get_variable(std::string name) const
183 {
184 2230 const auto & it = variables.find(name);
185
2/2
✓ Branch 2 taken 1052 times.
✓ Branch 3 taken 1178 times.
2230 if (it == variables.end()) {
186 1052 return nullptr;
187 }
188 1178 return it->second.get();
189 }
190
191 bool
192 22 Scope::is_loop() const
193 {
194 22 return scope_is_loop;
195 }
196 size_t
197 2 Scope::get_loop_break_blockid() const
198 2 { return loop_break_blockid; }
199
200 size_t
201 2 Scope::get_loop_continue_blockid() const
202 2 { return loop_continue_blockid; }
203
204 const std::map<std::string, Gyoji::owned<LocalVariable>> &
205 334 Scope::get_variables() const
206 334 { return variables; }
207
208 ///////////////////////////////////////////////////
209 // ScopeTracker
210 ///////////////////////////////////////////////////
211 272 ScopeTracker::ScopeTracker(const Gyoji::context::CompilerContext & _compiler_context)
212 272 : root(std::make_unique<Scope>())
213 272 , compiler_context(_compiler_context)
214 272 , tracker_prior_point()
215 272 , tracker_backward_edges()
216 544 , tracker_flat()
217 {
218 272 tracker_prior_point.push_back((size_t)-1);
219 272 current = root.get();
220 272 }
221
222 272 ScopeTracker::~ScopeTracker()
223 {
224 272 }
225
226
227 void
228 62 ScopeTracker::scope_push(const Gyoji::context::SourceReference & _source_ref)
229 {
230 62 auto child_scope = std::make_unique<Scope>();
231 62 Scope *new_current = child_scope.get();
232 62 child_scope->parent = current;
233 62 auto child_op = ScopeOperation::create_child(std::move(child_scope), _source_ref);
234 62 current->add_operation(std::move(child_op));
235 62 current = new_current;
236 62 tracker_prior_point.push_back(tracker_prior_point.back());
237 62 }
238 void
239 4 ScopeTracker::scope_push_loop(const Gyoji::context::SourceReference & _source_ref, size_t _loop_break_blockid, size_t _loop_continue_blockid)
240 {
241 4 auto child_scope = std::make_unique<Scope>(true, _loop_break_blockid, _loop_continue_blockid);
242 4 Scope *new_current = child_scope.get();
243 4 child_scope->parent = current;
244 4 auto child_op = ScopeOperation::create_child(std::move(child_scope), _source_ref);
245 4 current->add_operation(std::move(child_op));
246 4 current = new_current;
247 4 tracker_prior_point.push_back(tracker_prior_point.back());
248 4 }
249
250
251 void
252 66 ScopeTracker::scope_pop()
253 {
254 66 current = current->parent;
255 66 tracker_prior_point.pop_back();
256 66 }
257
258
259 const FunctionLabel *
260 16 ScopeTracker::get_label(std::string name) const
261 {
262 16 const auto & it_forward_declared = labels_forward_declared.find(name);
263
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 16 times.
16 if (it_forward_declared != labels_forward_declared.end()) {
264 return it_forward_declared->second.get();
265 }
266 16 const auto & it = labels.find(name);
267
2/2
✓ Branch 2 taken 14 times.
✓ Branch 3 taken 2 times.
16 if (it != labels.end()) {
268 14 return it->second.get();
269 }
270 2 return nullptr;
271 }
272
273 void
274 2 ScopeTracker::label_define(
275 std::string label_name,
276 const Gyoji::context::SourceReference & _source_ref
277 )
278 {
279 2 const auto & it_forward_declared = labels_forward_declared.find(label_name);
280
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if (it_forward_declared == labels_forward_declared.end()) {
281 fprintf(stderr, "Compiler Bug! We are attempting to resolve the definition of a forward-declared label, but it wasn't forward-declared.\n");
282 exit(1);
283 return;
284 }
285 2 it_forward_declared->second->resolve(_source_ref);
286 2 labels.insert(std::pair(label_name, std::move(it_forward_declared->second)));
287 2 labels_forward_declared.erase(it_forward_declared);
288
289 2 auto op = ScopeOperation::create_label(label_name, _source_ref);
290 2 tracker_label_locations.insert(std::pair(op->get_label_name(), tracker_flat.size()));
291 2 add_flat_op(op.get());
292
293 2 add_operation(std::move(op));
294 2 }
295
296 void
297 8 ScopeTracker::label_define(
298 std::string label_name,
299 size_t label_blockid,
300 const Gyoji::context::SourceReference & _source_ref
301 )
302 {
303 8 Gyoji::owned<FunctionLabel> new_label = std::make_unique<FunctionLabel>(label_blockid);
304 8 new_label->resolve(_source_ref);
305 8 labels.insert(std::pair(label_name, std::move(new_label)));
306
307 8 auto op = ScopeOperation::create_label(label_name, _source_ref);
308 8 tracker_label_locations.insert(std::pair(op->get_label_name(), tracker_flat.size()));
309 8 add_flat_op(op.get());
310 8 add_operation(std::move(op));
311 8 }
312
313 // Use this for 'goto' to say we want a label, but we
314 // don't yet know where it will live, so put it on the
315 // notfound labels list.
316 void
317 2 ScopeTracker::label_declare(std::string label_name, size_t label_blockid)
318 {
319 2 Gyoji::owned<FunctionLabel> new_label = std::make_unique<FunctionLabel>(label_blockid);
320 2 labels_forward_declared.insert(std::pair(label_name, std::move(new_label)));
321 2 }
322
323 void
324 880 ScopeTracker::add_flat_op(const ScopeOperation *op)
325 {
326
2/2
✓ Branch 1 taken 610 times.
✓ Branch 2 taken 270 times.
880 if (tracker_prior_point.back() != (size_t)-1) {
327 610 tracker_backward_edges.insert(std::pair(tracker_flat.size(), tracker_prior_point.back()));
328 }
329 880 tracker_prior_point.back() = tracker_flat.size();
330 880 tracker_flat.push_back(op);
331 880 }
332
333
334 void
335 12 ScopeTracker::add_goto(
336 std::string goto_label,
337 Gyoji::owned<FunctionPoint> goto_point,
338 const Gyoji::context::SourceReference & _source_ref
339 )
340 {
341 // TODO:
342 // Check if this label exists and jump to that
343 // label if it does. If it doesn't, forward declare it.
344 // and put it in the 'forward declared' labels list.
345 12 auto op = ScopeOperation::create_goto(goto_label, std::move(goto_point), _source_ref);
346 12 tracker_goto_labels_at.insert(std::pair(tracker_flat.size(), op->get_goto_label()));
347 12 add_flat_op(op.get());
348 12 add_operation(std::move(op));
349 12 }
350
351 const LocalVariable *
352 2102 ScopeTracker::get_variable(std::string variable_name) const
353 {
354 // Walk up from the current scope up to the root and
355 // see if this variable is defined anywhere.
356 2102 const Scope *s = current;
357
2/2
✓ Branch 0 taken 2230 times.
✓ Branch 1 taken 924 times.
3154 while (s) {
358 2230 const LocalVariable *existing_local_variable = s->get_variable(variable_name);
359
2/2
✓ Branch 0 taken 1178 times.
✓ Branch 1 taken 1052 times.
2230 if (existing_local_variable != nullptr) {
360 1178 return existing_local_variable;
361 }
362 1052 s = s->parent;
363 }
364 924 return nullptr;
365 }
366
367 std::vector<std::string>
368 284 ScopeTracker::get_variables_to_unwind_for_root() const
369 {
370 284 std::vector<std::string> variables_to_unwind;
371 284 const Scope *s = current;
372
2/2
✓ Branch 0 taken 302 times.
✓ Branch 1 taken 284 times.
586 while (s) {
373
2/2
✓ Branch 6 taken 888 times.
✓ Branch 7 taken 302 times.
1190 for (const auto & it : s->get_variables()) {
374 888 variables_to_unwind.push_back(it.first);
375 }
376 302 s = s->parent;
377 }
378 284 return variables_to_unwind;
379 }
380
381 std::vector<std::string>
382 32 ScopeTracker::get_variables_to_unwind_for_scope() const
383 {
384 32 std::vector<std::string> variables_to_unwind;
385 32 const Scope *s = current;
386
2/2
✓ Branch 6 taken 14 times.
✓ Branch 7 taken 32 times.
46 for (const auto & it : s->get_variables()) {
387 14 variables_to_unwind.push_back(it.first);
388 }
389 32 return variables_to_unwind;
390 }
391
392 std::vector<std::string>
393 2 ScopeTracker::get_variables_to_unwind_for_break() const
394 {
395 2 std::vector<std::string> variables_to_unwind;
396 2 const Scope *s = current;
397
3/6
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
2 while (s && s->is_loop()) {
398 for (const auto & it : s->get_variables()) {
399 variables_to_unwind.push_back(it.first);
400 }
401 s = s->parent;
402 }
403 2 return variables_to_unwind;
404
405 }
406
407 const Scope *
408 ScopeTracker::get_current() const
409 { return current; }
410
411 bool
412 860 ScopeTracker::add_variable(std::string variable_name, const Gyoji::mir::Type *mir_type, const Gyoji::context::SourceReference & source_ref)
413 {
414 // Walk up from the current scope up to the root and
415 // see if this variable is defined anywhere.
416 860 const LocalVariable *maybe_existing = get_variable(variable_name);
417
418
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 858 times.
860 if (maybe_existing != nullptr) {
419 2 std::unique_ptr<Gyoji::context::Error> error = std::make_unique<Gyoji::context::Error>("Duplicate Local Variable.");
420 4 error->add_message(source_ref,
421 4 std::string("Variable with name ") + variable_name + " is already in scope and cannot be duplicated.");
422 4 error->add_message(maybe_existing->get_source_ref(),
423 "First declared here.");
424
425 2 compiler_context
426 2 .get_errors()
427 2 .add_error(std::move(error));
428 2 return false;
429 2 }
430
431
432 // Variable was not declared earlier, so we add it to
433 // the current scope.
434 858 Gyoji::owned<LocalVariable> local_variable = std::make_unique<LocalVariable>(mir_type, source_ref);
435 858 current->variables.insert(std::pair(variable_name, std::move(local_variable)));
436
437 858 auto local_var_op = ScopeOperation::create_variable(variable_name, mir_type, source_ref);
438 858 add_flat_op(local_var_op.get());
439 858 add_operation(std::move(local_var_op));
440
441 858 return true;
442 858 }
443
444
445 // TODO: We should give a better interface
446 // here so we can easily declare locals, labels, gotos.
447 void
448 880 ScopeTracker::add_operation(Gyoji::owned<ScopeOperation> op)
449 {
450 880 current->add_operation(std::move(op));
451 880 }
452
453
454 // Now from this, I can evaluate
455 // what's legal. We only need to add the 'SourceReference'
456 // stuff in order to produce good errors for this.
457 void
458 6 ScopeTracker::dump() const
459 {
460 6 Scope *s = root.get();
461 6 fprintf(stderr, "{\n");
462 6 s->dump(0);
463 6 fprintf(stderr, "}\n");
464
2/2
✓ Branch 1 taken 48 times.
✓ Branch 2 taken 6 times.
54 for (size_t i = 0; i < tracker_flat.size(); i++) {
465 48 const auto & op = tracker_flat.at(i);
466
3/5
✓ Branch 1 taken 30 times.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 10 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
48 switch (op->get_type()) {
467 30 case ScopeOperation::VAR_DECL:
468 30 fprintf(stderr, "%ld Var decl %s\n", i, op->get_variable_name().c_str());
469 30 break;
470 8 case ScopeOperation::LABEL_DEFINITION:
471 8 fprintf(stderr, "%ld label %s\n", i, op->get_label_name().c_str());
472 8 break;
473 10 case ScopeOperation::GOTO_DEFINITION:
474 10 fprintf(stderr, "%ld goto %s\n", i, op->get_goto_label().c_str());
475 10 break;
476 case ScopeOperation::CHILD_SCOPE:
477 fprintf(stderr, "This should not be here\n");
478 exit(1);
479 }
480 }
481 6 }
482
483 bool
484 4 ScopeTracker::is_in_loop() const
485 {
486 4 const Scope *s = current;
487
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 while (s) {
488
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 6 times.
10 if (s->is_loop()) {
489 4 return true;
490 }
491 6 s = s->parent;
492 }
493 return false;
494 }
495
496 size_t
497 2 ScopeTracker::get_loop_break_blockid() const
498 {
499 2 const Scope *s = current;
500
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 while (s) {
501
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
4 if (s->is_loop()) {
502 2 return s->get_loop_break_blockid();
503 }
504 2 s = s->parent;
505 }
506 return 0;
507 }
508
509 size_t
510 2 ScopeTracker::get_loop_continue_blockid() const
511 {
512 2 const Scope *s = current;
513
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 while (s) {
514
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 4 times.
6 if (s->is_loop()) {
515 2 return s->get_loop_continue_blockid();
516 }
517 4 s = s->parent;
518 }
519 return 0;
520 }
521
522 bool
523 272 ScopeTracker::check(
524 std::vector<std::pair<const ScopeOperation*, std::vector<const ScopeOperation*>>> & goto_fixups
525 ) const
526 {
527 272 bool ok = true;
528
2/2
✓ Branch 5 taken 12 times.
✓ Branch 6 taken 272 times.
284 for (const auto & goto_point : tracker_goto_labels_at) {
529 12 const ScopeOperation *goto_operation = tracker_flat.at(goto_point.first);
530 12 const FunctionLabel *function_label = get_label(goto_operation->get_goto_label());
531
3/6
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 12 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 12 times.
12 if (function_label == nullptr || !function_label->is_resolved()) {
532 std::unique_ptr<Gyoji::context::Error> error = std::make_unique<Gyoji::context::Error>("Goto for an un-defined label.");
533 error->add_message(goto_operation->get_source_ref(),
534 std::string("Goto label ") + goto_operation->get_goto_label() + " had an undefined destination.");
535 compiler_context
536 .get_errors()
537 .add_error(std::move(error));
538 ok = false;
539 continue;
540 }
541
542 12 std::map<size_t, size_t> prior_to_goto;
543 12 walk_priors(tracker_backward_edges, goto_point.first, prior_to_goto);
544
545 12 std::map<size_t, size_t> prior_to_label;
546 12 const auto it = tracker_label_locations.find(goto_point.second);
547
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
12 if (it == tracker_label_locations.end()) {
548 fprintf(stderr, "This is a bug, we have a defined label, but no location for it\n");
549 exit(1);
550 }
551 12 size_t label_point = it->second;
552
553 12 walk_priors(tracker_backward_edges, label_point, prior_to_label);
554
555 12 std::vector<const ScopeOperation*> skipped_initializations;
556 12 std::vector<const ScopeOperation*> unwind_variables;
557
558 12 evaluate_scope_changes(tracker_flat, prior_to_goto, prior_to_label, skipped_initializations, unwind_variables);
559
560
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 8 times.
12 if (skipped_initializations.size() > 0) {
561 4 std::unique_ptr<Gyoji::context::Error> error = std::make_unique<Gyoji::context::Error>("Goto would skip initialization.");
562 8 error->add_message(goto_operation->get_source_ref(),
563 16 std::string("Goto label ") + goto_operation->get_goto_label() + std::string(" would skip initialization of variables in destination scope."));
564 8 error->add_message(function_label->get_source_ref(),
565 "Label declared here.");
566 8 error->add_message(skipped_initializations.at(0)->get_source_ref(),
567 "Skipped initialization occurs here.");
568 4 compiler_context
569 4 .get_errors()
570 4 .add_error(std::move(error));
571 4 ok = false;
572 4 }
573
574 12 goto_fixups.push_back(std::pair(goto_operation, unwind_variables));
575
2/2
✓ Branch 5 taken 8 times.
✓ Branch 6 taken 12 times.
20 for (const auto & s : unwind_variables) {
576 8 fprintf(stderr, "Unwind %s\n", s->get_variable_name().c_str());
577 }
578 12 }
579 272 return ok;
580 }
581
582 void
583 64 ScopeOperation::dump(int indent) const
584 {
585 64 std::string pad(indent*8, ' ');
586
587
4/5
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 16 times.
✗ Branch 4 not taken.
64 switch (type) {
588 30 case ScopeOperation::VAR_DECL:
589 {
590 60 std::string var = pad + std::string("var ") + variable_name;
591 30 fprintf(stderr, "%s\n", var.c_str());
592 30 }
593 30 break;
594 8 case ScopeOperation::LABEL_DEFINITION:
595 {
596 16 std::string var = pad + std::string("label ") + label_name;
597 8 fprintf(stderr, "%s\n", var.c_str());
598 8 }
599 8 break;
600 10 case ScopeOperation::GOTO_DEFINITION:
601 {
602 20 std::string var = pad + std::string("goto ") + goto_label;
603 10 fprintf(stderr, "%s\n", var.c_str());
604 10 }
605 10 break;
606 16 case ScopeOperation::CHILD_SCOPE:
607 {
608 16 std::string open = pad + "{";
609 16 fprintf(stderr, "%s\n", open.c_str());
610 16 child->dump(indent+1);
611 16 std::string close = pad + "}";
612 16 fprintf(stderr, "%s\n", close.c_str());
613 16 }
614 16 break;
615 }
616 64 }
617
618 void
619 22 Scope::dump(int indent) const
620 {
621 22 std::string pad(indent*8, ' ');
622
2/2
✓ Branch 5 taken 64 times.
✓ Branch 6 taken 22 times.
86 for (const auto & op : operations) {
623 64 op->dump(indent+1);
624 }
625 22 }
626
627 ///////////////////////////////////////////
628 858 LocalVariable::LocalVariable(
629 const Gyoji::mir::Type *_type,
630 const Gyoji::context::SourceReference & _source_ref
631 858 )
632 858 : type(_type)
633 858 , source_ref(_source_ref)
634 858 {}
635
636 858 LocalVariable::~LocalVariable()
637 858 {}
638
639 const Gyoji::mir::Type *
640 2352 LocalVariable::get_type() const
641 2352 { return type; }
642
643 const Gyoji::context::SourceReference &
644 2 LocalVariable::get_source_ref() const
645 2 { return source_ref; }
646
647 /////////////////////////////////////
648 // FunctionLabel
649 /////////////////////////////////////
650 10 FunctionLabel::FunctionLabel(
651 size_t _block_id
652 10 )
653 10 : resolved(false)
654 10 , block_id(_block_id)
655 10 , src_ref(nullptr)
656 10 {}
657 10 FunctionLabel::~FunctionLabel()
658 10 {}
659
660 const Gyoji::context::SourceReference &
661 4 FunctionLabel::get_source_ref() const
662 4 { return *src_ref; }
663
664 size_t
665 2 FunctionLabel::get_block() const
666 2 { return block_id; }
667
668 bool
669 12 FunctionLabel::is_resolved() const
670 12 { return resolved; }
671
672 void
673 10 FunctionLabel::resolve(const Gyoji::context::SourceReference & _src_ref)
674 {
675 10 resolved = true;
676 10 src_ref = &_src_ref;
677 10 }
678
679 ////////////////////////////////////////////////
680 // FunctionPoint
681 ////////////////////////////////////////////////
682 12 FunctionPoint::FunctionPoint(size_t _basic_block_id, size_t _location)
683 12 : basic_block_id(_basic_block_id)
684 12 , location(_location)
685 12 {}
686 12 FunctionPoint::~FunctionPoint()
687 12 {}
688
689 size_t
690 2 FunctionPoint::get_basic_block_id() const
691 2 { return basic_block_id; }
692
693 size_t
694 2 FunctionPoint::get_location() const
695 2 { return location; }
696