GCC Code Coverage Report


Directory: src/
File: src/mir/type.cpp
Date: 2025-10-24 11:14:59
Exec Total Coverage
Lines: 225 255 88.2%
Functions: 40 48 83.3%
Branches: 116 123 94.3%

Line Branch Exec Source
1 /* Copyright 2025 Jonathan S. Arney
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * https://github.com/jarney/gyoji/blob/master/LICENSE
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include <gyoji-mir/types.hpp>
16 #include <variant>
17 #include <stdio.h>
18 #include <gyoji-misc/jstring.hpp>
19
20 using namespace Gyoji::context;
21 using namespace Gyoji::mir;
22
23 ////////////////////////////////////////
24 // Type
25 ////////////////////////////////////////
26 12 Type::Type(
27 std::string _name,
28 std::string _simple_name,
29 TypeType _type,
30 bool _complete,
31 const SourceReference & _source_ref
32 12 )
33 12 : name(_name)
34 12 , simple_name(_simple_name)
35 12 , type(_type)
36 12 , complete(_complete)
37 12 , declared_source_ref(&_source_ref)
38 12 , defined_source_ref(&_source_ref)
39 12 , pointer_or_ref(nullptr)
40 12 , array_length(1)
41 12 , return_type(nullptr)
42 12 , argument_types()
43 12 , members()
44 12 , class_type(nullptr)
45 12 , function_pointer_type(nullptr)
46 12 {}
47 562 Type::Type(
48 std::string _name,
49 TypeType _type,
50 bool _complete,
51 const SourceReference & _source_ref
52 562 )
53 562 : name(_name)
54 562 , simple_name(_name)
55 562 , type(_type)
56 562 , complete(_complete)
57 562 , declared_source_ref(&_source_ref)
58 562 , defined_source_ref(&_source_ref)
59 562 , pointer_or_ref(nullptr)
60 562 , array_length(1)
61 562 , return_type(nullptr)
62 562 , argument_types()
63 562 , members()
64 562 , class_type(nullptr)
65 562 , function_pointer_type(nullptr)
66 562 {}
67 6 Type::Type(
68 std::string _name,
69 std::string _simple_name,
70 const SourceReference & _source_ref,
71 6 const Type & _other)
72 6 : name(_name)
73 6 , simple_name(_simple_name)
74 6 , type(_other.type)
75 6 , complete(_other.complete)
76 6 , declared_source_ref(&_source_ref)
77 6 , defined_source_ref(&_source_ref)
78 6 , pointer_or_ref(_other.pointer_or_ref)
79 6 , array_length(_other.array_length)
80 6 , return_type(_other.return_type)
81 6 , argument_types(_other.argument_types)
82 6 , members(_other.members)
83 6 , class_type(nullptr)
84 6 , function_pointer_type(nullptr)
85 {
86 6 }
87
88 580 Type::~Type()
89 580 {}
90
91 bool
92 1458 Type::is_complete() const
93 1458 { return complete; }
94
95 bool
96 1098 Type::is_primitive() const
97 {
98 return
99 2138 (type == TYPE_PRIMITIVE_u8) ||
100
2/2
✓ Branch 0 taken 982 times.
✓ Branch 1 taken 58 times.
1040 (type == TYPE_PRIMITIVE_u16) ||
101
2/2
✓ Branch 0 taken 924 times.
✓ Branch 1 taken 58 times.
982 (type == TYPE_PRIMITIVE_u32) ||
102
2/2
✓ Branch 0 taken 866 times.
✓ Branch 1 taken 58 times.
924 (type == TYPE_PRIMITIVE_u64) ||
103
104
2/2
✓ Branch 0 taken 808 times.
✓ Branch 1 taken 58 times.
866 (type == TYPE_PRIMITIVE_i8) ||
105
2/2
✓ Branch 0 taken 750 times.
✓ Branch 1 taken 58 times.
808 (type == TYPE_PRIMITIVE_i16) ||
106
2/2
✓ Branch 0 taken 692 times.
✓ Branch 1 taken 58 times.
750 (type == TYPE_PRIMITIVE_i32) ||
107
2/2
✓ Branch 0 taken 634 times.
✓ Branch 1 taken 58 times.
692 (type == TYPE_PRIMITIVE_i64) ||
108
109
2/2
✓ Branch 0 taken 576 times.
✓ Branch 1 taken 58 times.
634 (type == TYPE_PRIMITIVE_f32) ||
110
2/2
✓ Branch 0 taken 518 times.
✓ Branch 1 taken 58 times.
576 (type == TYPE_PRIMITIVE_f64) ||
111
112
4/4
✓ Branch 0 taken 1040 times.
✓ Branch 1 taken 58 times.
✓ Branch 2 taken 460 times.
✓ Branch 3 taken 58 times.
2598 (type == TYPE_PRIMITIVE_bool) ||
113
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 402 times.
1558 (type == TYPE_PRIMITIVE_void)
114 ;
115 }
116
117 bool
118 864 Type::is_pointer() const
119 864 { return (type == TYPE_POINTER); }
120
121 bool
122 732 Type::is_reference() const
123 732 { return (type == TYPE_REFERENCE); }
124
125 bool
126 1024 Type::is_numeric() const
127 {
128 return
129 1972 (type == TYPE_PRIMITIVE_u8) ||
130
2/2
✓ Branch 0 taken 820 times.
✓ Branch 1 taken 128 times.
948 (type == TYPE_PRIMITIVE_u16) ||
131
2/2
✓ Branch 0 taken 652 times.
✓ Branch 1 taken 168 times.
820 (type == TYPE_PRIMITIVE_u32) ||
132
2/2
✓ Branch 0 taken 564 times.
✓ Branch 1 taken 88 times.
652 (type == TYPE_PRIMITIVE_u64) ||
133
134
2/2
✓ Branch 0 taken 488 times.
✓ Branch 1 taken 76 times.
564 (type == TYPE_PRIMITIVE_i8) ||
135
2/2
✓ Branch 0 taken 360 times.
✓ Branch 1 taken 128 times.
488 (type == TYPE_PRIMITIVE_i16) ||
136
2/2
✓ Branch 0 taken 232 times.
✓ Branch 1 taken 128 times.
360 (type == TYPE_PRIMITIVE_i32) ||
137
2/2
✓ Branch 0 taken 144 times.
✓ Branch 1 taken 88 times.
232 (type == TYPE_PRIMITIVE_i64) ||
138
139
4/4
✓ Branch 0 taken 948 times.
✓ Branch 1 taken 76 times.
✓ Branch 2 taken 80 times.
✓ Branch 3 taken 64 times.
2052 (type == TYPE_PRIMITIVE_f32) ||
140
1/2
✓ Branch 0 taken 80 times.
✗ Branch 1 not taken.
1104 (type == TYPE_PRIMITIVE_f64);
141 }
142
143 bool
144 1498 Type::is_integer() const
145 {
146 return
147 2896 (type == TYPE_PRIMITIVE_u8) ||
148
2/2
✓ Branch 0 taken 1188 times.
✓ Branch 1 taken 210 times.
1398 (type == TYPE_PRIMITIVE_u16) ||
149
2/2
✓ Branch 0 taken 924 times.
✓ Branch 1 taken 264 times.
1188 (type == TYPE_PRIMITIVE_u32) ||
150
2/2
✓ Branch 0 taken 764 times.
✓ Branch 1 taken 160 times.
924 (type == TYPE_PRIMITIVE_u64) ||
151
152
2/2
✓ Branch 0 taken 664 times.
✓ Branch 1 taken 100 times.
764 (type == TYPE_PRIMITIVE_i8) ||
153
2/2
✓ Branch 0 taken 474 times.
✓ Branch 1 taken 190 times.
664 (type == TYPE_PRIMITIVE_i16) ||
154
4/4
✓ Branch 0 taken 1398 times.
✓ Branch 1 taken 100 times.
✓ Branch 2 taken 284 times.
✓ Branch 3 taken 190 times.
3180 (type == TYPE_PRIMITIVE_i32) ||
155
2/2
✓ Branch 0 taken 140 times.
✓ Branch 1 taken 144 times.
1782 (type == TYPE_PRIMITIVE_i64);
156 }
157
158 bool
159 680 Type::is_signed() const
160 {
161 return
162 1292 (type == TYPE_PRIMITIVE_i8) ||
163
2/2
✓ Branch 0 taken 488 times.
✓ Branch 1 taken 124 times.
612 (type == TYPE_PRIMITIVE_i16) ||
164
4/4
✓ Branch 0 taken 612 times.
✓ Branch 1 taken 68 times.
✓ Branch 2 taken 364 times.
✓ Branch 3 taken 124 times.
1656 (type == TYPE_PRIMITIVE_i32) ||
165
2/2
✓ Branch 0 taken 84 times.
✓ Branch 1 taken 280 times.
1044 (type == TYPE_PRIMITIVE_i64);
166 }
167
168 bool
169 376 Type::is_unsigned() const
170 {
171 return
172 704 (type == TYPE_PRIMITIVE_u8) ||
173
2/2
✓ Branch 0 taken 224 times.
✓ Branch 1 taken 104 times.
328 (type == TYPE_PRIMITIVE_u16) ||
174
4/4
✓ Branch 0 taken 328 times.
✓ Branch 1 taken 48 times.
✓ Branch 2 taken 96 times.
✓ Branch 3 taken 128 times.
800 (type == TYPE_PRIMITIVE_u32) ||
175
2/2
✓ Branch 0 taken 84 times.
✓ Branch 1 taken 12 times.
472 (type == TYPE_PRIMITIVE_u64);
176 }
177
178 bool
179 260 Type::is_float() const
180 {
181 return
182
2/2
✓ Branch 0 taken 214 times.
✓ Branch 1 taken 46 times.
474 (type == TYPE_PRIMITIVE_f32) ||
183
2/2
✓ Branch 0 taken 90 times.
✓ Branch 1 taken 124 times.
474 (type == TYPE_PRIMITIVE_f64);
184 }
185
186 bool
187 40 Type::is_bool() const
188 {
189 return
190 40 (type == TYPE_PRIMITIVE_bool);
191 }
192
193 bool
194 478 Type::is_void() const
195 {
196 return
197 478 (type == TYPE_PRIMITIVE_void);
198 }
199 bool
200 302 Type::is_enum() const
201 302 { return (type == TYPE_ENUM); }
202
203 bool
204 2670 Type::is_composite() const
205 2670 { return (type == TYPE_COMPOSITE); }
206 bool
207 1296 Type::is_anonymous() const
208 1296 { return (type == TYPE_ANONYMOUS_STRUCTURE); }
209
210 bool
211 236 Type::is_function_pointer() const
212 236 { return (type == TYPE_FUNCTION_POINTER); }
213
214 bool
215 Type::is_array() const
216 { return (type == TYPE_ARRAY); }
217
218 size_t
219 832 Type::get_primitive_size() const
220 {
221
4/5
✓ Branch 0 taken 140 times.
✓ Branch 1 taken 200 times.
✓ Branch 2 taken 296 times.
✓ Branch 3 taken 196 times.
✗ Branch 4 not taken.
832 switch (type) {
222 140 case TYPE_PRIMITIVE_u8:
223 case TYPE_PRIMITIVE_i8:
224 140 return 1;
225 200 case TYPE_PRIMITIVE_u16:
226 case TYPE_PRIMITIVE_i16:
227 200 return 2;
228 296 case TYPE_PRIMITIVE_u32:
229 case TYPE_PRIMITIVE_i32:
230 case TYPE_PRIMITIVE_f32:
231 296 return 4;
232 196 case TYPE_PRIMITIVE_u64:
233 case TYPE_PRIMITIVE_i64:
234 case TYPE_PRIMITIVE_f64:
235 196 return 8;
236 default:
237 fprintf(stderr, "Compiler Bug! This function should only be called for integer and floating-point types\n");
238 exit(1);
239 }
240 return 0;
241
242 }
243
244
245 Type::TypeType
246 1978 Type::get_type() const
247 1978 { return type; }
248 const std::string &
249 16368 Type::get_name() const
250 16368 { return name; }
251
252 const std::string &
253 10 Type::get_simple_name() const
254 10 { return simple_name; }
255
256 const std::vector<TypeMember> &
257 36 Type::get_members() const
258 36 { return members; }
259
260 const std::map<std::string, TypeMethod> &
261 18 Type::get_methods() const
262 18 { return methods; }
263
264 const TypeMember *
265 44 Type::member_get(const std::string & member_name) const
266 {
267 44 const auto it = members_by_name.find(member_name);
268
2/2
✓ Branch 2 taken 26 times.
✓ Branch 3 taken 18 times.
44 if (it == members_by_name.end()) {
269 26 return nullptr;
270 }
271 18 return it->second;
272 }
273
274 const TypeMethod *
275 2 Type::method_get(const std::string & method_name) const
276 {
277 2 const auto it = methods.find(method_name);
278
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
2 if (it == methods.end()) {
279 return nullptr;
280 }
281 2 return &it->second;
282 }
283
284 const TypeMethod *
285 Type::method_get_destructor() const
286 {
287 return method_get(std::string("~") + simple_name);
288 }
289
290
291 const Type *
292 76 Type::get_pointer_target() const
293 76 { return pointer_or_ref; }
294
295 size_t
296 Type::get_array_length() const
297 { return array_length; }
298
299 const Type*
300 652 Type::get_return_type() const
301 652 { return return_type; }
302
303 const std::vector<Argument> &
304 664 Type::get_argument_types() const
305 {
306 664 return argument_types;
307 }
308
309 bool
310 346 Type::is_unsafe() const
311 {
312 346 return m_is_unsafe;
313 }
314
315 const Type *
316 Type::get_class_type() const
317 {
318 return class_type;
319 }
320 const Type *
321 Type::get_function_pointer_type() const
322 {
323 return function_pointer_type;
324 }
325
326 void
327 72 Type::complete_pointer_definition(const Type *_type, const SourceReference & _source_ref)
328 {
329 72 complete = true;
330 72 pointer_or_ref = _type;
331 72 defined_source_ref = &_source_ref;
332 72 }
333
334 void
335 Type::complete_array_definition(const Type *_type, size_t _array_length, const Gyoji::context::SourceReference & _source_ref)
336 {
337 complete = true;
338 pointer_or_ref = _type;
339 array_length = _array_length;
340 defined_source_ref = &_source_ref;
341 }
342
343 void
344 22 Type::complete_composite_definition(
345 std::vector<TypeMember> _members,
346 std::map<std::string, TypeMethod> _methods,
347 const SourceReference & _source_ref)
348 {
349 22 complete = true;
350 22 members = _members;
351 22 methods = _methods;
352
2/2
✓ Branch 4 taken 52 times.
✓ Branch 5 taken 22 times.
74 for (const TypeMember & member : members) {
353 52 members_by_name.insert(std::pair(member.get_name(), &member));
354 }
355 22 defined_source_ref = &_source_ref;
356 22 }
357
358 void
359 118 Type::complete_function_pointer_definition(
360 const Type *_return_type,
361 const std::vector<Argument> & _argument_types,
362 bool _is_unsafe,
363 const Gyoji::context::SourceReference & _source_ref
364 )
365 {
366 118 complete = true;
367 118 return_type = _return_type;
368 118 argument_types = _argument_types;
369 118 m_is_unsafe = _is_unsafe;
370 118 defined_source_ref = &_source_ref;
371 118 }
372
373 const SourceReference &
374 Type::get_declared_source_ref() const
375 { return *declared_source_ref; }
376
377 const SourceReference &
378 6 Type::get_defined_source_ref() const
379 6 { return *defined_source_ref; }
380
381 void
382 580 Type::dump(FILE *out) const
383 {
384 580 std::string type_desc("unknown");
385
386
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 578 times.
580 if (!is_complete()) {
387 4 type_desc = std::string("class (forward declaration)");
388 }
389
2/2
✓ Branch 1 taken 360 times.
✓ Branch 2 taken 218 times.
578 else if (is_primitive()) {
390 720 type_desc = std::string("primitive");
391 }
392
2/2
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 200 times.
218 else if (is_composite()) {
393 36 type_desc = std::string("class");
394 }
395
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 196 times.
200 else if (is_anonymous()) {
396 8 type_desc = std::string("anonymous structure");
397 }
398
2/2
✓ Branch 1 taken 72 times.
✓ Branch 2 taken 124 times.
196 else if (is_pointer()) {
399 72 type_desc = std::string("pointer");
400 216 type_desc += std::string(" to ") + pointer_or_ref->get_name();
401 }
402
2/2
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 118 times.
124 else if (is_reference()) {
403 6 type_desc = std::string("reference");
404 18 type_desc += std::string(" to ") + pointer_or_ref->get_name();
405 }
406
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 118 times.
118 else if (is_enum()) {
407 type_desc = std::string("enum");
408 }
409
1/2
✓ Branch 1 taken 118 times.
✗ Branch 2 not taken.
118 else if (is_function_pointer()) {
410 118 std::string desc;
411 118 desc = desc + return_type->get_name();
412 118 std::vector<std::string> arglist;
413
2/2
✓ Branch 5 taken 190 times.
✓ Branch 6 taken 118 times.
308 for (const Argument & arg : argument_types) {
414 190 arglist.push_back(arg.get_type()->get_name());
415 }
416 236 desc = desc + std::string("(*)");
417 708 desc = desc + std::string("(") + Gyoji::misc::join(arglist, ",") + std::string(")");
418 118 type_desc = std::string("function-pointer ") + desc;
419 118 }
420 else if (is_array()) {
421 type_desc = std::string("array ");
422 type_desc += pointer_or_ref->get_name() + std::string("[") + std::to_string(array_length) + std::string("]");
423 }
424 else {
425 fprintf(stderr, "Compiler Bug! Unknown type of type when dumping types.\n");
426 exit(1);
427 }
428
429
6/6
✓ Branch 1 taken 560 times.
✓ Branch 2 taken 20 times.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 556 times.
✓ Branch 6 taken 24 times.
✓ Branch 7 taken 556 times.
580 if (is_composite() || is_anonymous()) {
430 24 fprintf(out, " %s : %s {\n", name.c_str(), type_desc.c_str());
431
2/2
✓ Branch 5 taken 52 times.
✓ Branch 6 taken 24 times.
76 for (const auto & m : members) {
432 52 fprintf(out, " %s : %s\n", m.get_name().c_str(), m.get_type()->get_name().c_str());
433 }
434
2/2
✓ Branch 5 taken 8 times.
✓ Branch 6 taken 24 times.
32 for (const auto & m : methods) {
435 8 fprintf(out, " %s : %s\n", m.first.c_str(), m.second.get_class_type()->get_name().c_str());
436 8 fprintf(out, " ret %s\n", m.second.get_return_type()->get_name().c_str());
437
2/2
✓ Branch 6 taken 12 times.
✓ Branch 7 taken 8 times.
20 for (const auto & arg : m.second.get_arguments()) {
438 12 fprintf(out, " arg %s\n", arg.get_type()->get_name().c_str());
439 }
440 }
441 24 fprintf(out, " }\n");
442 }
443 else {
444 556 fprintf(out, " %s : %s\n", name.c_str(), type_desc.c_str());
445 }
446 580 }
447
448
449 /////////////////////////
450 // Argument
451 /////////////////////////
452 586 Argument::Argument(
453 const Type *_argument_type,
454 const Gyoji::context::SourceReference & _source_ref
455 586 )
456 586 : argument_type(_argument_type)
457 586 , source_ref(&_source_ref)
458 586 {}
459 1132 Argument::Argument(const Argument & _other)
460 1132 : argument_type(_other.argument_type)
461 1132 , source_ref(_other.source_ref)
462 1132 {}
463 1718 Argument::~Argument()
464 1718 {}
465 const Type*
466 1204 Argument::get_type() const
467 1204 { return argument_type; }
468
469 const Gyoji::context::SourceReference &
470 Argument::get_source_ref() const
471 { return *source_ref; }
472
473