• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

nickg / nvc / 13887457702

16 Mar 2025 09:12PM UTC coverage: 92.285% (-0.04%) from 92.324%
13887457702

push

github

nickg
Tag Docker images on releases. Fixes #1165

68273 of 73981 relevant lines covered (92.28%)

423265.54 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

82.96
/src/mir/mir-type.c
1
//
2
//  Copyright (C) 2024-2025  Nick Gasson
3
//
4
//  This program is free software: you can redistribute it and/or modify
5
//  it under the terms of the GNU General Public License as published by
6
//  the Free Software Foundation, either version 3 of the License, or
7
//  (at your option) any later version.
8
//
9
//  This program is distributed in the hope that it will be useful,
10
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
//  GNU General Public License for more details.
13
//
14
//  You should have received a copy of the GNU General Public License
15
//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
16
//
17

18
#include "util.h"
19
#include "array.h"
20
#include "ident.h"
21
#include "mir/mir-node.h"
22
#include "mir/mir-priv.h"
23
#include "mir/mir-structs.h"
24
#include "thread.h"
25

26
#include <assert.h>
27
#include <float.h>
28
#include <inttypes.h>
29
#include <stdlib.h>
30

31
#define REPROBE_LIMIT 10
32

33
static inline int64_t sadd64(int64_t a, int64_t b)
4✔
34
{
35
   int64_t result;
4✔
36
   if (__builtin_add_overflow(a, b, &result))
4✔
37
      return b < 0 ? INT64_MIN : INT64_MAX;
2✔
38

39
   return result;
40
}
41

42
static inline int64_t ssub64(int64_t a, int64_t b)
×
43
{
44
   int64_t result;
×
45
   if (__builtin_sub_overflow(a, b, &result))
×
46
      return b > 0 ? INT64_MIN : INT64_MAX;
×
47

48
   return result;
49
}
50

51
static inline int64_t smul64(int64_t a, int64_t b)
×
52
{
53
   int64_t result;
×
54
   if (__builtin_mul_overflow(a, b, &result))
×
55
      return (a > 0 && b > 0) || (a < 0 && b < 0) ? INT64_MAX : INT64_MIN;
×
56

57
   return result;
58
}
59

60
static uint32_t mir_hash_type(mir_unit_t *mu, const type_data_t *td)
359,206✔
61
{
62
   uint32_t h = knuth_hash(td->class);
359,206✔
63

64
   switch (td->class) {
359,206✔
65
   case _MIR_INVALID_TYPE:
66
   case MIR_TYPE_OFFSET:
67
   case MIR_TYPE_LOCUS:
68
   case MIR_TYPE_CONVERSION:
69
   case MIR_TYPE_OPAQUE:
70
   case MIR_TYPE_TRIGGER:
71
      break;
72

73
   case MIR_TYPE_POINTER:
78,788✔
74
      h ^= mir_type_data(mu, td->u.pointer)->hash;
78,788✔
75
      break;
78,788✔
76

77
   case MIR_TYPE_SIGNAL:
25,156✔
78
      h ^= mir_type_data(mu, td->u.signal.base)->hash;
25,156✔
79
      break;
25,156✔
80

81
   case MIR_TYPE_INT:
86,968✔
82
      h ^= mix_bits_64(td->u.intg.low) >> 32;
86,968✔
83
      h ^= mix_bits_64(td->u.intg.high);
86,968✔
84
      break;
86,968✔
85

86
   case MIR_TYPE_REAL:
8,364✔
87
      h ^= mix_bits_64(FLOAT_BITS(td->u.real.low)) >> 32;
8,364✔
88
      h ^= mix_bits_64(FLOAT_BITS(td->u.real.high));
8,364✔
89
      break;
8,364✔
90

91
   case MIR_TYPE_CARRAY:
15,611✔
92
      h += knuth_hash(td->u.carray.size);
15,611✔
93
      h ^= mir_type_data(mu, td->u.carray.elem)->hash;
15,611✔
94
      break;
15,611✔
95

96
   case MIR_TYPE_UARRAY:
43,548✔
97
      h += knuth_hash(td->u.uarray.dims);
43,548✔
98
      h ^= mir_type_data(mu, td->u.uarray.elem)->hash;
43,548✔
99
      break;
43,548✔
100

101
   case MIR_TYPE_CONTEXT:
50,879✔
102
      h ^= ident_hash(td->u.context);
50,879✔
103
      break;
50,879✔
104

105
   case MIR_TYPE_ACCESS:
1,613✔
106
      h ^= mir_type_data(mu, td->u.access.to)->hash;
1,613✔
107
      break;
1,613✔
108

109
   case MIR_TYPE_RECORD:
5,622✔
110
      h ^= ident_hash(td->u.record.name);
5,622✔
111
      for (int i = 0; i < td->u.record.count; i++)
24,260✔
112
         h ^= mir_type_data(mu, td->u.record.fields[i])->hash;
18,638✔
113
      break;
114

115
   case MIR_TYPE_CLOSURE:
1,361✔
116
      if (!mir_is_null(td->u.closure.atype))
1,361✔
117
         h ^= mir_type_data(mu, td->u.closure.atype)->hash;
1,340✔
118
      h ^= mir_type_data(mu, td->u.closure.rtype)->hash;
1,361✔
119
      break;
1,361✔
120

121
   case MIR_TYPE_RESOLUTION:
1,341✔
122
   case MIR_TYPE_FILE:
123
      h ^= mir_type_data(mu, td->u.base)->hash;
1,341✔
124
      break;
1,341✔
125
   }
126

127
   return h;
359,206✔
128
}
129

130
static bool mir_compare_types(const type_data_t *a, const type_data_t *b)
1,651,611✔
131
{
132
   if (a->class != b->class)
1,651,611✔
133
      return false;
134

135
   switch (a->class) {
893,779✔
136
   case _MIR_INVALID_TYPE:
137
      return false;
138

139
   case MIR_TYPE_OFFSET:
32,720✔
140
   case MIR_TYPE_LOCUS:
141
   case MIR_TYPE_OPAQUE:
142
   case MIR_TYPE_CONVERSION:
143
   case MIR_TYPE_TRIGGER:
144
      return true;
32,720✔
145

146
   case MIR_TYPE_POINTER:
113,081✔
147
      return a->u.pointer.bits == b->u.pointer.bits;
113,081✔
148

149
   case MIR_TYPE_SIGNAL:
23,504✔
150
      return a->u.signal.base.bits == b->u.signal.base.bits;
23,504✔
151

152
   case MIR_TYPE_INT:
94,996✔
153
      return a->u.intg.low == b->u.intg.low
94,996✔
154
         && a->u.intg.high == b->u.intg.high;
117,459✔
155

156
   case MIR_TYPE_REAL:
7,974✔
157
      return a->u.real.low == b->u.real.low
7,974✔
158
         && a->u.real.high == b->u.real.high;
7,974✔
159

160
   case MIR_TYPE_CARRAY:
52,160✔
161
      return a->u.carray.size == b->u.carray.size
52,160✔
162
         && a->u.carray.elem.bits == b->u.carray.elem.bits;
52,160✔
163

164
   case MIR_TYPE_UARRAY:
42,222✔
165
      return a->u.uarray.dims == b->u.uarray.dims
42,222✔
166
         && a->u.uarray.elem.bits == b->u.uarray.elem.bits;
42,222✔
167

168
   case MIR_TYPE_CONTEXT:
516,187✔
169
      return a->u.context == b->u.context;
516,187✔
170

171
   case MIR_TYPE_ACCESS:
2,305✔
172
      return a->u.access.to.bits == b->u.access.to.bits;
2,305✔
173

174
   case MIR_TYPE_RECORD:
7,247✔
175
      if (a->u.record.name != b->u.record.name)
7,247✔
176
         return false;
177
      else if (a->u.record.count != b->u.record.count)
3,877✔
178
         return false;
179
      else {
180
         for (int i = 0; i < a->u.record.count; i++) {
16,877✔
181
            if (a->u.record.fields[i].bits != b->u.record.fields[i].bits)
13,000✔
182
               return false;
183
         }
184

185
         return true;
186
      }
187

188
   case MIR_TYPE_CLOSURE:
766✔
189
      return a->u.closure.atype.bits == b->u.closure.atype.bits
766✔
190
         && a->u.closure.rtype.bits == b->u.closure.rtype.bits;
766✔
191

192
   case MIR_TYPE_RESOLUTION:
617✔
193
   case MIR_TYPE_FILE:
194
      return a->u.base.bits == b->u.base.bits;
617✔
195
   }
196

197
   should_not_reach_here();
198
}
199

200
const type_data_t *mir_type_data(mir_unit_t *mu, mir_type_t type)
5,704,459✔
201
{
202
   mir_context_t *mc = mu->context;
5,704,459✔
203
   type_tab_t *tab = load_acquire(&mc->typetab);
5,704,459✔
204

205
   assert(type.tag == MIR_TAG_TYPE);
5,704,459✔
206
   assert(type.id < tab->max_types);
5,704,459✔
207

208
   const type_data_t *td = &(tab->types[type.id]);
5,704,459✔
209
   assert(td->class != _MIR_INVALID_TYPE);
5,704,459✔
210

211
   return td;
5,704,459✔
212
}
213

214
static void mir_install_type(mir_unit_t *mu, type_data_t *dst,
70,552✔
215
                             const type_data_t *src, uint32_t hash)
216
{
217
   dst->class = src->class;
70,552✔
218
   dst->repr  = src->repr;
70,552✔
219
   dst->hash  = hash;
70,552✔
220

221
   switch (src->class) {
70,552✔
222
   case MIR_TYPE_CARRAY:
7,325✔
223
      {
224
         const mir_carray_type_t *src_a = &src->u.carray;
7,325✔
225
         mir_carray_type_t *dst_a = &dst->u.carray;
7,325✔
226

227
         dst_a->elem    = src_a->elem;
7,325✔
228
         dst_a->size    = src_a->size;
7,325✔
229
         dst_a->pointer = mir_pointer_type(mu, src_a->elem);
7,325✔
230
      }
231
      break;
7,325✔
232

233
   case MIR_TYPE_UARRAY:
3,594✔
234
      {
235
         const mir_uarray_type_t *src_a = &src->u.uarray;
3,594✔
236
         mir_uarray_type_t *dst_a = &dst->u.uarray;
3,594✔
237

238
         dst_a->dims    = src_a->dims;
3,594✔
239
         dst_a->elem    = src_a->elem;
3,594✔
240

241
         if (mir_get_class(mu, src_a->elem) == MIR_TYPE_SIGNAL)
3,594✔
242
            dst_a->pointer = src_a->elem;
387✔
243
         else
244
            dst_a->pointer = mir_pointer_type(mu, src_a->elem);
3,207✔
245
      }
246
      break;
247

248
   case MIR_TYPE_RECORD:
1,748✔
249
      {
250
         const mir_record_type_t *src_r = &src->u.record;
1,748✔
251
         mir_record_type_t *dst_r = &dst->u.record;
1,748✔
252

253
         dst_r->name   = src_r->name;
1,748✔
254
         dst_r->count  = src_r->count;
1,748✔
255
         dst_r->fields = mir_malloc(mu->context, 0, src_r->count * 2,
1,748✔
256
                                    sizeof(mir_type_t));
257

258
         for (int i = 0; i < src_r->count; i++) {
7,395✔
259
            mir_type_t pointer = mir_get_var_pointer(mu, src_r->fields[i]);
5,647✔
260
            dst_r->fields[i] = src->u.record.fields[i];
5,647✔
261
            dst_r->fields[i + src_r->count] = pointer;
5,647✔
262
         }
263
      }
264
      break;
265

266
   case MIR_TYPE_ACCESS:
478✔
267
      {
268
         const mir_access_type_t *src_a = &src->u.access;
478✔
269
         mir_access_type_t *dst_a = &dst->u.access;
478✔
270

271
         dst_a->to      = src_a->to;
478✔
272
         dst_a->pointer = mir_pointer_type(mu, src_a->to);
478✔
273
      }
274
      break;
478✔
275

276
   case MIR_TYPE_SIGNAL:
3,104✔
277
      {
278
         const mir_signal_type_t *src_s = &src->u.signal;
3,104✔
279
         mir_signal_type_t *dst_s = &dst->u.signal;
3,104✔
280

281
         dst_s->base    = src_s->base;
3,104✔
282
         dst_s->pointer = mir_pointer_type(mu, src_s->base);
3,104✔
283
      }
284
      break;
3,104✔
285

286
   default:
54,303✔
287
      dst->u = src->u;
54,303✔
288
   }
289
}
70,552✔
290

291
__attribute__((always_inline))
292
static inline type_slot_t mir_type_slot(const type_tab_t *tab, int pos)
12,767,645✔
293
{
294
   return (type_slot_t) {
12,767,645✔
295
      .bits = load_acquire(&tab->hashtab[pos].bits)
12,767,645✔
296
   };
297
}
298

299
static void mir_copy_table(type_tab_t *from, type_tab_t *to)
16✔
300
{
301
   uint32_t max_id = 0;
16✔
302
   for (int i = 0; i < from->max_types; i++) {
7,440✔
303
      for (;;) {
7,424✔
304
         const type_slot_t slot = mir_type_slot(from, i);
7,424✔
305
         switch (slot.marker) {
7,424✔
306
         case BUSY_MARKER:
×
307
            spin_wait();
×
308
            continue;
×
309
         case INUSE_MARKER:
3,729✔
310
            {
311
               const type_data_t *from_td = &(from->types[slot.id]);
3,729✔
312
               type_data_t *to_td = &(to->types[slot.id]);
3,729✔
313

314
               max_id = MAX((uint32_t)slot.id, max_id);
3,729✔
315

316
               for (int pos = from_td->hash & (to->max_types - 1);;
3,729✔
317
                    pos = (pos + 1) & (to->max_types - 1)) {
816✔
318
                  const type_slot_t exist = mir_type_slot(to, pos);
4,545✔
319
                  if (exist.marker == FREE_MARKER) {
4,545✔
320
                     *to_td = *from_td;
3,729✔
321
                     store_release(&(to->hashtab[pos].bits), slot.bits);
3,729✔
322
                     break;
3,729✔
323
                  }
324
                  else
325
                     assert(exist.marker == INUSE_MARKER);
816✔
326
               }
327
            }
328
            break;
3,729✔
329
         case FREE_MARKER:
330
            break;
331
         default:
×
332
            should_not_reach_here();
333
         }
334

335
         const type_slot_t moved = { .marker = MOVED_MARKER, .id = slot.id };
7,424✔
336
         if (atomic_cas(&(from->hashtab[i].bits), slot.bits, moved.bits))
7,424✔
337
            break;
338
         else
339
            assert(slot.marker == FREE_MARKER);   // Raced to move free slot
×
340
      }
341
   }
342

343
   atomic_store(&to->next_id, max_id + 1);
16✔
344
}
16✔
345

346
static void mir_wait_for_resize(mir_context_t *mc)
×
347
{
348
   for (;;) {
×
349
      type_tab_t *from = atomic_load(&mc->typetab);
×
350
      type_tab_t *to = atomic_load(&mc->resizing);
×
351

352
      if (from == to)
×
353
         break;
354

355
      thread_sleep(10);
×
356
   }
357
}
×
358

359
static void mir_grow_table(mir_context_t *mc, type_tab_t *cur)
16✔
360
{
361
   type_tab_t *newtab =
16✔
362
      xcalloc_flex(sizeof(type_tab_t), cur->max_types * 2, sizeof(type_data_t));
16✔
363
   newtab->max_types = cur->max_types * 2;
16✔
364
   newtab->hashtab = xcalloc_array(newtab->max_types, sizeof(uint32_t));
16✔
365

366
   if (atomic_cas(&mc->resizing, cur, newtab)) {
16✔
367
      mir_copy_table(cur, newtab);
16✔
368

369
      assert(atomic_load(&mc->resizing) == newtab);
16✔
370

371
      if (!atomic_cas(&mc->typetab, cur, newtab))
16✔
372
         should_not_reach_here();
373

374
      async_free(cur->hashtab);
16✔
375
      async_free(cur);
16✔
376
   }
377
   else {
378
      free(newtab);
×
379
      mir_wait_for_resize(mc);
×
380
   }
381
}
16✔
382

383
static mir_type_t mir_try_build_type(mir_unit_t *mu, const type_data_t *td,
359,225✔
384
                                     uint32_t hash)
385
{
386
   mir_context_t *mc = mu->context;
359,225✔
387
   type_tab_t *tab = load_acquire(&mc->typetab);
359,225✔
388

389
   assert(is_power_of_2(tab->max_types));
359,225✔
390

391
   if (tab->next_id > tab->max_types / 2) {
359,225✔
392
      mir_grow_table(mc, tab);
16✔
393
      return MIR_NULL_TYPE;
16✔
394
   }
395

396
   for (int pos = hash & (tab->max_types - 1);;
359,209✔
397
        pos = (pos + 1) & (tab->max_types - 1)) {
41,275✔
398
      const type_slot_t slot = mir_type_slot(tab, pos);
400,484✔
399
      switch (slot.marker) {
400,484✔
400
      case BUSY_MARKER:
×
401
         spin_wait();
×
402
         return MIR_NULL_TYPE;
×
403
      case FREE_MARKER:
70,552✔
404
         {
405
            // Copy the type data before CAS-ing the slot to busy since
406
            // mir_install_type may allocate new types and deadlock
407
            type_data_t copy;
70,552✔
408
            mir_install_type(mu, &copy, td, hash);
70,552✔
409

410
            const type_slot_t busy = { .marker = BUSY_MARKER };
70,552✔
411
            if (atomic_cas(&tab->hashtab[pos].bits, slot.bits, busy.bits)) {
70,552✔
412
               const uint32_t id = atomic_fetch_add(&tab->next_id, 1);
70,549✔
413
               const type_slot_t new = { .marker = INUSE_MARKER, .id = id };
70,549✔
414
               if (unlikely(new.id != id))
70,549✔
415
                  fatal_trace("too many types");
416

417
               tab->types[id] = copy;
70,549✔
418
               store_release(&tab->hashtab[pos].bits, new.bits);
70,549✔
419
               return (mir_type_t){ .tag = MIR_TAG_TYPE, .id = id };
70,549✔
420
            }
421
            else {   // Raced for this slot, leak copy for now
422
               spin_wait();
3✔
423
               return MIR_NULL_TYPE;
3✔
424
            }
425
         }
426
      case INUSE_MARKER:
329,932✔
427
         if (hash != tab->types[slot.id].hash)
329,932✔
428
            break;
429
         else if (mir_compare_types(td, &(tab->types[slot.id])))
308,129✔
430
            return (mir_type_t){ .tag = MIR_TAG_TYPE, .id = slot.id };
288,657✔
431
         break;
432
      case MOVED_MARKER:
×
433
         mir_wait_for_resize(mc);
×
434
         return MIR_NULL_TYPE;
×
435
      }
436
   }
437
}
438

439
static mir_type_t mir_build_type(mir_unit_t *mu, const type_data_t *td)
359,206✔
440
{
441
   const uint32_t hash = mir_hash_type(mu, td);
359,206✔
442

443
   mir_type_t type;
359,225✔
444
   do {
359,225✔
445
      type = mir_try_build_type(mu, td, hash);
359,225✔
446
   } while (mir_is_null(type));
359,225✔
447

448
   return type;
359,206✔
449
}
450

451
mir_type_t mir_int_type(mir_unit_t *mu, int64_t low, int64_t high)
86,968✔
452
{
453
   mir_repr_t repr;
86,968✔
454
   switch (bits_for_range(low, high)) {
86,968✔
455
   case 64: repr = low < 0 ? MIR_REPR_I64 : MIR_REPR_U64; break;
11,457✔
456
   case 32: repr = low < 0 ? MIR_REPR_I32 : MIR_REPR_U32; break;
21,536✔
457
   case 16: repr = low < 0 ? MIR_REPR_I16 : MIR_REPR_U16; break;
30✔
458
   case 8:  repr = low < 0 ? MIR_REPR_I8 : MIR_REPR_U8; break;
22,195✔
459
   case 1:  repr = MIR_REPR_U1; break;
460
   case 0:  repr = MIR_REPR_I64; break;    // Null range
×
461
   default:
×
462
      fatal_trace("cannot represent %"PRIi64"..%"PRIi64, low, high);
463
   }
464

465
   const type_data_t td = {
86,968✔
466
      .class = MIR_TYPE_INT,
467
      .repr = repr,
468
      .u = { .intg = { .low = low, .high = high } }
469
   };
470

471
   return mir_build_type(mu, &td);
86,968✔
472
}
473

474
mir_type_t mir_real_type(mir_unit_t *mu, double low, double high)
8,364✔
475
{
476
   const type_data_t td = {
8,364✔
477
      .class = MIR_TYPE_REAL,
478
      .u = { .real = { .low = low, .high = high } }
479
   };
480

481
   return mir_build_type(mu, &td);
8,364✔
482
}
483

484
mir_type_t mir_offset_type(mir_unit_t *mu)
79,004✔
485
{
486
   if (mir_is_null(mu->types.offset_type)) {
79,004✔
487
      const type_data_t td = {
22,823✔
488
         .class = MIR_TYPE_OFFSET,
489
         .repr = MIR_REPR_I64,
490
         .u = { .intg = { .low = INT64_MIN, .high = INT64_MAX } }
491
      };
492

493
      mu->types.offset_type = mir_build_type(mu, &td);
22,823✔
494
   }
495

496
   return mu->types.offset_type;
79,004✔
497
}
498

499
mir_type_t mir_locus_type(mir_unit_t *mu)
65,909✔
500
{
501
   if (mir_is_null(mu->types.locus_type)) {
65,909✔
502
      const type_data_t td = { .class = MIR_TYPE_LOCUS };
16,068✔
503
      mu->types.locus_type = mir_build_type(mu, &td);
16,068✔
504
   }
505

506
   return mu->types.locus_type;
65,909✔
507
}
508

509
mir_type_t mir_conversion_type(mir_unit_t *mu)
576✔
510
{
511
   if (mir_is_null(mu->types.conversion_type)) {
576✔
512
      const type_data_t td = { .class = MIR_TYPE_CONVERSION };
437✔
513
      mu->types.conversion_type = mir_build_type(mu, &td);
437✔
514
   }
515

516
   return mu->types.conversion_type;
576✔
517
}
518

519
mir_type_t mir_trigger_type(mir_unit_t *mu)
362✔
520
{
521
   if (mir_is_null(mu->types.trigger_type)) {
362✔
522
      const type_data_t td = { .class = MIR_TYPE_TRIGGER };
227✔
523
      mu->types.trigger_type = mir_build_type(mu, &td);
227✔
524
   }
525

526
   return mu->types.trigger_type;
362✔
527
}
528

529
mir_type_t mir_self_type(mir_unit_t *mu)
11,076✔
530
{
531
   if (mir_is_null(mu->types.self_type)) {
11,076✔
532
      const type_data_t td = {
10,084✔
533
         .class = MIR_TYPE_CONTEXT,
534
         .u.context = mu->name,
10,084✔
535
      };
536

537
      mu->types.self_type = mir_build_type(mu, &td);
10,084✔
538
   }
539

540
   return mu->types.self_type;
11,076✔
541
}
542

543
mir_type_t mir_bool_type(mir_unit_t *mu)
162,213✔
544
{
545
   if (mir_is_null(mu->types.bool_type))
162,213✔
546
      mu->types.bool_type = mir_int_type(mu, 0, 1);
13,329✔
547

548
   return mu->types.bool_type;
162,213✔
549
}
550

551
mir_type_t mir_time_type(mir_unit_t *mu)
396✔
552
{
553
   if (mir_is_null(mu->types.time_type))
396✔
554
      mu->types.time_type = mir_int_type(mu, INT64_MIN, INT64_MAX);
206✔
555

556
   return mu->types.time_type;
396✔
557
}
558

559
mir_type_t mir_double_type(mir_unit_t *mu)
2✔
560
{
561
   if (mir_is_null(mu->types.double_type))
2✔
562
      mu->types.double_type = mir_real_type(mu, -DBL_MAX, DBL_MAX);
2✔
563

564
   return mu->types.double_type;
2✔
565
}
566

567
mir_type_t mir_string_type(mir_unit_t *mu)
812✔
568
{
569
   if (mir_is_null(mu->types.string_type))
812✔
570
      mu->types.string_type = mir_uarray_type(mu, 1, mir_int_type(mu, 0, 255));
482✔
571

572
   return mu->types.string_type;
812✔
573
}
574

575
mir_type_t mir_pointer_type(mir_unit_t *mu, mir_type_t to)
78,788✔
576
{
577
   MIR_ASSERT(mir_get_class(mu, to) != MIR_TYPE_CARRAY,
78,788✔
578
              "cannot get pointer to carray type");
579

580
   const type_data_t td = {
78,788✔
581
      .class = MIR_TYPE_POINTER,
582
      .u = { .pointer = to }
583
   };
584

585
   return mir_build_type(mu, &td);
78,788✔
586
}
587

588
mir_type_t mir_access_type(mir_unit_t *mu, mir_type_t to)
1,613✔
589
{
590
   const type_data_t td = {
1,613✔
591
      .class = MIR_TYPE_ACCESS,
592
      .u = { .access = { .to = to } },
593
   };
594

595
   return mir_build_type(mu, &td);
1,613✔
596
}
597

598
mir_type_t mir_opaque_type(mir_unit_t *mu)
400✔
599
{
600
   const type_data_t td = {
400✔
601
      .class = MIR_TYPE_OPAQUE,
602
   };
603

604
   return mir_build_type(mu, &td);
400✔
605
}
606

607
mir_type_t mir_record_type(mir_unit_t *mu, ident_t name,
5,622✔
608
                           const mir_type_t *fields, unsigned count)
609
{
610
   const type_data_t td = {
5,622✔
611
      .class = MIR_TYPE_RECORD,
612
      .u = {
613
         .record = {
614
            .name   = name,
615
            .fields = (mir_type_t *)fields,   // Copied in mir_install_type
616
            .count  = count
617
         }
618
      }
619
   };
620

621
   return mir_build_type(mu, &td);
5,622✔
622
}
623

624
mir_type_t mir_closure_type(mir_unit_t *mu, mir_type_t atype, mir_type_t rtype)
1,361✔
625
{
626
   const type_data_t td = {
1,361✔
627
      .class = MIR_TYPE_CLOSURE,
628
      .u = {
629
         .closure = {
630
            .atype = atype,
631
            .rtype = rtype
632
         }
633
      },
634
   };
635

636
   return mir_build_type(mu, &td);
1,361✔
637
}
638

639
mir_type_t mir_resolution_type(mir_unit_t *mu, mir_type_t base)
983✔
640
{
641
   const type_data_t td = {
983✔
642
      .class = MIR_TYPE_RESOLUTION,
643
      .u = { .base = base },
644
   };
645

646
   return mir_build_type(mu, &td);
983✔
647
}
648

649
mir_type_t mir_file_type(mir_unit_t *mu, mir_type_t base)
358✔
650
{
651
   const type_data_t td = {
358✔
652
      .class = MIR_TYPE_FILE,
653
      .u = { .base = base },
654
   };
655

656
   return mir_build_type(mu, &td);
358✔
657
}
658

659
mir_type_t mir_carray_type(mir_unit_t *mu, int size, mir_type_t elem)
15,611✔
660
{
661
   MIR_ASSERT(mir_get_class(mu, elem) != MIR_TYPE_CARRAY,
15,611✔
662
              "array types may not be nested");
663

664
   const type_data_t td = {
15,611✔
665
      .class = MIR_TYPE_CARRAY,
666
      .u = {
667
         .carray = {
668
            .size = size,
669
            .elem = elem,
670
         }
671
      }
672
   };
673

674
   return mir_build_type(mu, &td);
15,611✔
675
}
676

677
mir_type_t mir_uarray_type(mir_unit_t *mu, int ndim, mir_type_t elem)
43,548✔
678
{
679
   MIR_ASSERT(mir_get_class(mu, elem) != MIR_TYPE_CARRAY,
43,548✔
680
              "array types may not be nested");
681

682
   const type_data_t td = {
43,548✔
683
      .class = MIR_TYPE_UARRAY,
684
      .u = {
685
         .uarray = {
686
            .dims = ndim,
687
            .elem = elem,
688
         }
689
      }
690
   };
691

692
   return mir_build_type(mu, &td);
43,548✔
693
}
694

695
mir_type_t mir_signal_type(mir_unit_t *mu, mir_type_t base)
25,156✔
696
{
697
   const type_data_t td = {
25,156✔
698
      .class = MIR_TYPE_SIGNAL,
699
      .u = { .signal = { .base = base } }
700
   };
701

702
   return mir_build_type(mu, &td);
25,156✔
703
}
704

705
mir_type_t mir_context_type(mir_unit_t *mu, ident_t name)
40,795✔
706
{
707
   const type_data_t td = {
40,795✔
708
      .class = MIR_TYPE_CONTEXT,
709
      .u = { .context = name }
710
   };
711

712
   return mir_build_type(mu, &td);
40,795✔
713
}
714

715
mir_type_t mir_get_base(mir_unit_t *mu, mir_type_t type)
1,180✔
716
{
717
   const type_data_t *td = mir_type_data(mu, type);
1,180✔
718
   switch (td->class) {
1,180✔
719
   case MIR_TYPE_SIGNAL:
×
720
      return td->u.signal.base;
×
721
   case MIR_TYPE_RESOLUTION:
1,180✔
722
   case MIR_TYPE_FILE:
723
      return td->u.base;
1,180✔
724
   default:
×
725
      return MIR_NULL_TYPE;
×
726
   }
727
}
728

729
mir_type_t mir_get_elem(mir_unit_t *mu, mir_type_t type)
391,632✔
730
{
731
   const type_data_t *td = mir_type_data(mu, type);
391,632✔
732
   switch (td->class) {
391,632✔
733
   case MIR_TYPE_UARRAY:
173,252✔
734
      return td->u.uarray.elem;
173,252✔
735
   case MIR_TYPE_CARRAY:
116,602✔
736
      return td->u.carray.elem;
116,602✔
737
   case MIR_TYPE_ACCESS:
410✔
738
      return td->u.access.to;
410✔
739
   case MIR_TYPE_POINTER:
101,368✔
740
      return td->u.pointer;
101,368✔
741
   default:
×
742
      return MIR_NULL_TYPE;
×
743
   }
744
}
745

746
mir_type_t mir_get_pointer(mir_unit_t *mu, mir_type_t type)
295,016✔
747
{
748
   const type_data_t *td = mir_type_data(mu, type);
295,016✔
749
   switch (td->class) {
295,016✔
750
   case MIR_TYPE_SIGNAL:
14,404✔
751
      return td->u.signal.pointer;
14,404✔
752
   case MIR_TYPE_POINTER:
232,168✔
753
      return td->u.pointer;
232,168✔
754
   case MIR_TYPE_UARRAY:
24,351✔
755
      return td->u.uarray.pointer;
24,351✔
756
   case MIR_TYPE_CARRAY:
20,947✔
757
      return td->u.carray.pointer;
20,947✔
758
   case MIR_TYPE_ACCESS:
1,507✔
759
      return td->u.access.pointer;
1,507✔
760
   default:
1,639✔
761
      return MIR_NULL_TYPE;
1,639✔
762
   }
763
}
764

765
mir_type_t mir_get_var_pointer(mir_unit_t *mu, mir_type_t type)
57,114✔
766
{
767
   const type_data_t *td = mir_type_data(mu, type);
57,114✔
768
   switch (td->class) {
57,114✔
769
   case MIR_TYPE_CARRAY:
5,727✔
770
      return td->u.carray.pointer;
5,727✔
771
   default:
51,387✔
772
      return mir_pointer_type(mu, type);
51,387✔
773
   }
774
}
775

776
unsigned mir_get_dims(mir_unit_t *mu, mir_type_t type)
104,400✔
777
{
778
   const type_data_t *td = mir_type_data(mu, type);
104,400✔
779
   switch (td->class) {
104,400✔
780
   case MIR_TYPE_UARRAY:
104,400✔
781
      return td->u.uarray.dims;
104,400✔
782
   default:
×
783
      should_not_reach_here();
784
   }
785
}
786

787
unsigned mir_get_size(mir_unit_t *mu, mir_type_t type)
77,078✔
788
{
789
   const type_data_t *td = mir_type_data(mu, type);
77,078✔
790
   switch (td->class) {
77,078✔
791
   case MIR_TYPE_CARRAY:
77,078✔
792
      return td->u.carray.size;
77,078✔
793
   default:
×
794
      should_not_reach_here();
795
   }
796
}
797

798
mir_class_t mir_get_class(mir_unit_t *mu, mir_type_t type)
2,215,251✔
799
{
800
   return mir_type_data(mu, type)->class;
2,215,251✔
801
}
802

803
mir_repr_t mir_get_repr(mir_unit_t *mu, mir_type_t type)
429,223✔
804
{
805
   const type_data_t *td = mir_type_data(mu, type);
429,223✔
806
   switch (td->class) {
429,223✔
807
   case MIR_TYPE_INT:
429,223✔
808
   case MIR_TYPE_OFFSET:
809
      return td->repr;
429,223✔
810
   default:
×
811
      should_not_reach_here();
812
   }
813
}
814

815
const mir_type_t *mir_get_fields(mir_unit_t *mu, mir_type_t type, size_t *count)
61,642✔
816
{
817
   const type_data_t *td = mir_type_data(mu, type);
61,642✔
818
   assert(td->class == MIR_TYPE_RECORD);
61,642✔
819

820
   if (count != NULL) *count = td->u.record.count;
61,642✔
821
   return td->u.record.fields;
61,642✔
822
}
823

824
static uint32_t mir_hash_stamp(mir_unit_t *mu, const stamp_data_t *sd)
163,724✔
825
{
826
   uint32_t h = sd->kind;
163,724✔
827

828
   switch (sd->kind) {
163,724✔
829
   case _MIR_INVALID_STAMP:
830
      break;
831

832
   case MIR_STAMP_INT:
72,906✔
833
      h ^= mix_bits_64(sd->u.intg.low) >> 32;
72,906✔
834
      h ^= mix_bits_64(sd->u.intg.high);
72,906✔
835
      break;
72,906✔
836

837
   case MIR_STAMP_REAL:
20,901✔
838
      h ^= mix_bits_64(FLOAT_BITS(sd->u.real.low)) >> 32;
20,901✔
839
      h ^= mix_bits_64(FLOAT_BITS(sd->u.real.high));
20,901✔
840
      break;
20,901✔
841

842
   case MIR_STAMP_POINTER:
69,917✔
843
      h += knuth_hash(sd->u.pointer.memory);
69,917✔
844
      if (!mir_is_null(sd->u.pointer.elem))
69,917✔
845
         h ^= mir_stamp_data(mu, sd->u.pointer.elem)->hash;
20,501✔
846
      break;
847
   }
848

849
   return h;
163,724✔
850
}
851

852
static bool mir_compare_stamps(const stamp_data_t *a, const stamp_data_t *b)
74,069✔
853
{
854
   if (a->kind != b->kind)
74,069✔
855
      return false;
856

857
   switch (a->kind) {
74,069✔
858
   case _MIR_INVALID_STAMP:
859
      return false;
860

861
   case MIR_STAMP_INT:
33,008✔
862
      return a->u.intg.low == b->u.intg.low
33,008✔
863
         && a->u.intg.high == b->u.intg.high;
33,008✔
864

865
   case MIR_STAMP_REAL:
2,267✔
866
      return a->u.real.low == b->u.real.low
2,267✔
867
         && a->u.real.high == b->u.real.high;
2,267✔
868

869
   case MIR_STAMP_POINTER:
38,794✔
870
      return a->u.pointer.memory == b->u.pointer.memory
38,794✔
871
         && a->u.pointer.elem.bits == b->u.pointer.elem.bits;
38,794✔
872
   }
873

874
   should_not_reach_here();
875
}
876

877
static mir_stamp_t mir_build_stamp(mir_unit_t *mu, const stamp_data_t *sd)
163,724✔
878
{
879
   const uint32_t hash = mir_hash_stamp(mu, sd);
163,724✔
880

881
   for (int i = 0; i < mu->stamps.count; i++) {
2,206,354✔
882
      const stamp_data_t *other = &(mu->stamps.items[i]);
2,116,699✔
883
      if (other->hash == hash && mir_compare_stamps(other, sd))
2,116,699✔
884
         return (mir_stamp_t){ .tag = MIR_TAG_STAMP, .id = i };
74,069✔
885
   }
886

887
   mir_stamp_t s = { .tag = MIR_TAG_STAMP, .id  = mu->stamps.count };
89,655✔
888

889
   stamp_data_t new = {
89,655✔
890
      .kind = sd->kind,
89,655✔
891
      .hash = hash,
892
      .u    = sd->u,
893
   };
894
   APUSH(mu->stamps, new);
89,655✔
895

896
   return s;
89,655✔
897
}
898

899
const stamp_data_t *mir_stamp_data(mir_unit_t *mu, mir_stamp_t stamp)
56,919✔
900
{
901
   assert(stamp.tag == MIR_TAG_STAMP);
56,919✔
902
   return AREF(mu->stamps, stamp.id);
56,919✔
903
}
904

905
mir_stamp_t mir_int_stamp(mir_unit_t *mu, int64_t low, int64_t high)
72,906✔
906
{
907
   assert(low <= high);
72,906✔
908

909
   const stamp_data_t sd = {
72,906✔
910
      .kind = MIR_STAMP_INT,
911
      .u = { .intg = { .low = low, .high = high } }
912
   };
913

914
   return mir_build_stamp(mu, &sd);
72,906✔
915
}
916

917
mir_stamp_t mir_real_stamp(mir_unit_t *mu, double low, double high)
20,901✔
918
{
919
   assert(low <= high);
20,901✔
920

921
   const stamp_data_t sd = {
20,901✔
922
      .kind = MIR_STAMP_REAL,
923
      .u = { .real = { .low = low, .high = high } }
924
   };
925

926
   return mir_build_stamp(mu, &sd);
20,901✔
927
}
928

929
mir_stamp_t mir_pointer_stamp(mir_unit_t *mu, mir_mem_t mem, mir_stamp_t elem)
69,917✔
930
{
931
   const stamp_data_t sd = {
69,917✔
932
      .kind = MIR_STAMP_POINTER,
933
      .u = { .pointer = { .memory = mem, .elem = elem } },
934
   };
935

936
   return mir_build_stamp(mu, &sd);
69,917✔
937
}
938

939
bool mir_is_top(mir_unit_t *mu, mir_type_t type, mir_stamp_t stamp)
×
940
{
941
   const type_data_t *td = mir_type_data(mu, type);
×
942
   const stamp_data_t *sd = mir_stamp_data(mu, stamp);
×
943

944
   switch (td->class) {
×
945
   case MIR_TYPE_INT:
×
946
   case MIR_TYPE_OFFSET:
947
      return sd->u.intg.low <= td->u.intg.low
×
948
         && sd->u.intg.high >= td->u.intg.high;
×
949

950
   default:
951
      return false;
952
   }
953
}
954

955
mir_stamp_t mir_stamp_elem(mir_unit_t *mu, mir_stamp_t stamp)
117,307✔
956
{
957
   if (mir_is_null(stamp))
117,307✔
958
      return MIR_NULL_STAMP;
83,366✔
959

960
   const stamp_data_t *sd = mir_stamp_data(mu, stamp);
33,941✔
961
   switch (sd->kind) {
33,941✔
962
   case MIR_STAMP_POINTER:
33,939✔
963
      return sd->u.pointer.elem;
33,939✔
964
   default:
2✔
965
      return MIR_NULL_STAMP;
2✔
966
   }
967
}
968

969
mir_stamp_t mir_stamp_add(mir_unit_t *mu, mir_stamp_t left, mir_stamp_t right)
14,865✔
970
{
971
   if (mir_is_null(left) || mir_is_null(right))
14,865✔
972
      return MIR_NULL_STAMP;
14,863✔
973

974
   const stamp_data_t *lsd = mir_stamp_data(mu, left);
2✔
975
   const stamp_data_t *rsd = mir_stamp_data(mu, right);
2✔
976

977
   assert(lsd->kind == rsd->kind);
2✔
978

979
   switch (lsd->kind) {
2✔
980
   case MIR_STAMP_INT:
2✔
981
      {
982
         const int64_t low  = sadd64(lsd->u.intg.low, rsd->u.intg.low);
2✔
983
         const int64_t high = sadd64(lsd->u.intg.high, rsd->u.intg.high);
2✔
984

985
         return mir_int_stamp(mu, low, high);
2✔
986
      }
987

988
   case MIR_STAMP_REAL:
×
989
      {
990
         const double low  = lsd->u.real.low + rsd->u.real.low;
×
991
         const double high = lsd->u.real.high + rsd->u.real.high;
×
992

993
         return mir_real_stamp(mu, low, high);
×
994
      }
995

996
   default:
×
997
      should_not_reach_here();
998
   }
999
}
1000

1001
mir_stamp_t mir_stamp_sub(mir_unit_t *mu, mir_stamp_t left, mir_stamp_t right)
19,977✔
1002
{
1003
   if (mir_is_null(left) || mir_is_null(right))
19,977✔
1004
      return MIR_NULL_STAMP;
19,977✔
1005

1006
   const stamp_data_t *lsd = mir_stamp_data(mu, left);
×
1007
   const stamp_data_t *rsd = mir_stamp_data(mu, right);
×
1008

1009
   assert(lsd->kind == rsd->kind);
×
1010

1011
   switch (lsd->kind) {
×
1012
   case MIR_STAMP_INT:
×
1013
      {
1014
         const int64_t low  = ssub64(lsd->u.intg.low, rsd->u.intg.high);
×
1015
         const int64_t high = ssub64(lsd->u.intg.high, rsd->u.intg.low);
×
1016

1017
         return mir_int_stamp(mu, low, high);
×
1018
      }
1019

1020
   case MIR_STAMP_REAL:
×
1021
      {
1022
         const double low  = lsd->u.real.low - rsd->u.real.high;
×
1023
         const double high = lsd->u.real.high - rsd->u.real.low;
×
1024

1025
         return mir_real_stamp(mu, low, high);
×
1026
      }
1027

1028
   default:
×
1029
      should_not_reach_here();
1030
   }
1031
}
1032

1033
mir_stamp_t mir_stamp_mul(mir_unit_t *mu, mir_stamp_t left, mir_stamp_t right)
2,092✔
1034
{
1035
   if (mir_is_null(left) || mir_is_null(right))
2,092✔
1036
      return MIR_NULL_STAMP;
2,092✔
1037

1038
   const stamp_data_t *lsd = mir_stamp_data(mu, left);
×
1039
   const stamp_data_t *rsd = mir_stamp_data(mu, right);
×
1040

1041
   assert(lsd->kind == rsd->kind);
×
1042

1043
   switch (lsd->kind) {
×
1044
   case MIR_STAMP_INT:
×
1045
      {
1046
         const int64_t ll = smul64(lsd->u.intg.low, rsd->u.intg.low);
×
1047
         const int64_t lh = smul64(lsd->u.intg.low, rsd->u.intg.high);
×
1048
         const int64_t hl = smul64(lsd->u.intg.high, rsd->u.intg.low);
×
1049
         const int64_t hh = smul64(lsd->u.intg.high, rsd->u.intg.high);
×
1050

1051
         int64_t min = MIN(MIN(ll, lh), MIN(hl, hh));
×
1052
         int64_t max = MAX(MAX(ll, lh), MAX(hl, hh));
×
1053

1054
         return mir_int_stamp(mu, min, max);
×
1055
      }
1056

1057
   case MIR_STAMP_REAL:
×
1058
      {
1059
         const double ll = lsd->u.real.low * rsd->u.real.low;
×
1060
         const double lh = lsd->u.real.low * rsd->u.real.high;
×
1061
         const double hl = lsd->u.real.high * rsd->u.real.low;
×
1062
         const double hh = lsd->u.real.high * rsd->u.real.high;
×
1063

1064
         double min = MIN(MIN(ll, lh), MIN(hl, hh));
×
1065
         double max = MAX(MAX(ll, lh), MAX(hl, hh));
×
1066

1067
         return mir_real_stamp(mu, min, max);
×
1068
      }
1069

1070
   default:
×
1071
      should_not_reach_here();
1072
   }
1073
}
1074

1075
mir_stamp_t mir_stamp_div(mir_unit_t *mu, mir_stamp_t left, mir_stamp_t right)
885✔
1076
{
1077
   if (mir_is_null(left) || mir_is_null(right))
885✔
1078
      return MIR_NULL_STAMP;
871✔
1079

1080
   return MIR_NULL_STAMP;  // TODO
14✔
1081
}
1082

1083
mir_stamp_t mir_stamp_rem(mir_unit_t *mu, mir_stamp_t left, mir_stamp_t right)
97✔
1084
{
1085
   if (mir_is_null(left) || mir_is_null(right))
97✔
1086
      return MIR_NULL_STAMP;
95✔
1087

1088
   const stamp_data_t *lsd = mir_stamp_data(mu, left);
2✔
1089
   const stamp_data_t *rsd = mir_stamp_data(mu, right);
2✔
1090

1091
   assert(lsd->kind == rsd->kind);
2✔
1092

1093
   switch (lsd->kind) {
2✔
1094
   case MIR_STAMP_INT:
2✔
1095
      if (lsd->u.intg.low >= 0 && rsd->u.intg.high > 0)
2✔
1096
         return mir_int_stamp(mu, 0, rsd->u.intg.high - 1);
1✔
1097
      else
1098
         return MIR_NULL_STAMP;
1✔
1099

1100
   default:
×
1101
      should_not_reach_here();
1102
   }
1103
}
1104

1105
mir_stamp_t mir_stamp_cmp(mir_unit_t *mu, mir_cmp_t cmp, mir_stamp_t left,
33,629✔
1106
                          mir_stamp_t right)
1107
{
1108
   if (mir_is_null(left) || mir_is_null(right))
33,629✔
1109
      return MIR_NULL_STAMP;
33,551✔
1110

1111
   const stamp_data_t *lsd = mir_stamp_data(mu, left);
78✔
1112
   const stamp_data_t *rsd = mir_stamp_data(mu, right);
78✔
1113

1114
   assert(lsd->kind == rsd->kind);
78✔
1115

1116
   switch (lsd->kind) {
78✔
1117
   case MIR_STAMP_INT:
53✔
1118
      {
1119
         const int64_t a = lsd->u.intg.low;
53✔
1120
         const int64_t b = lsd->u.intg.high;
53✔
1121
         const int64_t c = rsd->u.intg.low;
53✔
1122
         const int64_t d = rsd->u.intg.high;
53✔
1123

1124
         int trueval = 1;
53✔
1125
         switch (cmp) {
53✔
1126
         case MIR_CMP_EQ:
51✔
1127
            trueval = 0;
51✔
1128
            // Fall-through
1129
         case MIR_CMP_NEQ:
51✔
1130
            if (MAX(a, c) <= MIN(b, d))
51✔
1131
               return MIR_NULL_STAMP;    // Ranges overlap
51✔
1132
            else
1133
               return mir_int_stamp(mu, trueval, trueval);
×
1134

1135
         case MIR_CMP_GEQ:
1✔
1136
            trueval = 0;
1✔
1137
            // Fall-through
1138
         case MIR_CMP_LT:
2✔
1139
            if (b < c)
2✔
1140
               return mir_int_stamp(mu, trueval, trueval);
×
1141
            else if (a >= d)
2✔
1142
               return mir_int_stamp(mu, !trueval, !trueval);
2✔
1143
            else
1144
               return MIR_NULL_STAMP;
×
1145

1146
         case MIR_CMP_LEQ:
×
1147
            trueval = 0;
×
1148
            // Fall-through
1149
         case MIR_CMP_GT:
×
1150
            if (a > d)
×
1151
               return mir_int_stamp(mu, trueval, trueval);
×
1152
            else if (b <= c)
×
1153
               return mir_int_stamp(mu, !trueval, !trueval);
×
1154
            else
1155
               return MIR_NULL_STAMP;
×
1156

1157
         default:
×
1158
            should_not_reach_here();
1159
         }
1160
      }
1161

1162
   case MIR_STAMP_REAL:
25✔
1163
      return MIR_NULL_STAMP;
25✔
1164

1165
   default:
×
1166
      should_not_reach_here();
1167
   }
1168
}
1169

1170
mir_stamp_t mir_stamp_union(mir_unit_t *mu, mir_stamp_t left, mir_stamp_t right)
12,383✔
1171
{
1172
   if (mir_is_null(left))
12,383✔
1173
      return right;
11,637✔
1174
   else if (mir_is_null(right))
746✔
1175
      return left;
×
1176

1177
   const stamp_data_t *lsd = mir_stamp_data(mu, left);
746✔
1178
   const stamp_data_t *rsd = mir_stamp_data(mu, right);
746✔
1179

1180
   assert(lsd->kind == rsd->kind);
746✔
1181

1182
   switch (lsd->kind) {
746✔
1183
   case MIR_STAMP_INT:
746✔
1184
      {
1185
         const int64_t low  = MIN(lsd->u.intg.low, rsd->u.intg.low);
746✔
1186
         const int64_t high = MAX(lsd->u.intg.high, rsd->u.intg.high);
746✔
1187

1188
         return mir_int_stamp(mu, low, high);
746✔
1189
      }
1190

1191
   case MIR_STAMP_REAL:
×
1192
      {
1193
         const double low  = MIN(lsd->u.real.low, rsd->u.real.low);
×
1194
         const double high = MAX(lsd->u.real.high, rsd->u.real.high);
×
1195

1196
         return mir_real_stamp(mu, low, high);
×
1197
      }
1198

1199
   default:
×
1200
      should_not_reach_here();
1201
   }
1202
}
1203

1204
bool mir_stamp_const(mir_unit_t *mu, mir_stamp_t stamp, int64_t *cval)
33,629✔
1205
{
1206
   if (mir_is_null(stamp))
33,629✔
1207
      return false;
1208

1209
   const stamp_data_t *sd = mir_stamp_data(mu, stamp);
2✔
1210

1211
   if (sd->kind != MIR_STAMP_INT || sd->u.intg.low != sd->u.intg.high)
2✔
1212
      return false;
1213

1214
   *cval = sd->u.intg.low;
2✔
1215
   return true;
2✔
1216
}
1217

1218
bool mir_same_type(mir_unit_t *mu, mir_type_t a, mir_type_t b)
92,819✔
1219
{
1220
   if (mir_is_null(a) && mir_is_null(b))
92,819✔
1221
      return true;
1222
   else if (mir_is_null(a)) {
90,684✔
1223
      const type_data_t *btd = mir_type_data(mu, b);
7,460✔
1224
      return btd->class == MIR_TYPE_OFFSET || btd->class == MIR_TYPE_INT;
7,460✔
1225
   }
1226
   else if (mir_is_null(b)) {
83,224✔
1227
      const type_data_t *atd = mir_type_data(mu, a);
16,900✔
1228
      return atd->class == MIR_TYPE_OFFSET || atd->class == MIR_TYPE_INT;
16,900✔
1229
   }
1230
   else
1231
      return mir_equals(a, b);
66,324✔
1232
}
1233

1234
void mir_free_types(type_tab_t *tab)
8,765✔
1235
{
1236
#ifdef DEBUG
1237
   for (int i = 0; i < tab->max_types; i++) {
2,260,029✔
1238
      const type_slot_t islot = mir_type_slot(tab, i);
2,251,264✔
1239
      assert(islot.marker == FREE_MARKER || islot.marker == INUSE_MARKER);
2,251,264✔
1240

1241
      if (islot.marker == INUSE_MARKER) {
2,251,264✔
1242
         const type_data_t *itd = &(tab->types[islot.id]);
70,533✔
1243
         for (int j = 0; j < i; j++) {
10,174,461✔
1244
            const type_slot_t jslot = mir_type_slot(tab, j);
10,103,928✔
1245
            if (jslot.marker == INUSE_MARKER) {
10,103,928✔
1246
               const type_data_t *jtd = &(tab->types[jslot.id]);
1,343,482✔
1247
               if (mir_compare_types(itd, jtd))
1,343,482✔
1248
                  fatal_trace("duplicate types in table at %d (%d => %08x) "
1249
                              "and %d (%d => %08x)", i, islot.id, itd->hash,
×
1250
                              j, jslot.id, jtd->hash);
×
1251
            }
1252
         }
1253
      }
1254
   }
1255
#endif
1256

1257
   free(tab->hashtab);
8,765✔
1258
   free(tab);
8,765✔
1259
}
8,765✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc