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

nickg / nvc / 13738584171

08 Mar 2025 12:57PM UTC coverage: 92.236% (-0.05%) from 92.281%
13738584171

push

github

nickg
Add a simple pointer provenance tracking scheme

52 of 53 new or added lines in 3 files covered. (98.11%)

230 existing lines in 7 files now uncovered.

68028 of 73754 relevant lines covered (92.24%)

433200.43 hits per line

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

82.99
/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

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

48
   return result;
49
}
50

UNCOV
51
static inline int64_t smul64(int64_t a, int64_t b)
×
52
{
UNCOV
53
   int64_t result;
×
UNCOV
54
   if (__builtin_mul_overflow(a, b, &result))
×
UNCOV
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)
379,973✔
61
{
62
   uint32_t h = knuth_hash(td->class);
379,973✔
63

64
   switch (td->class) {
379,973✔
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,617✔
74
      h ^= mir_type_data(mu, td->u.pointer)->hash;
78,617✔
75
      break;
78,617✔
76

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

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

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

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

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

101
   case MIR_TYPE_CONTEXT:
72,203✔
102
      h ^= ident_hash(td->u.context);
72,203✔
103
      break;
72,203✔
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,511✔
110
      h ^= ident_hash(td->u.record.name);
5,511✔
111
      for (int i = 0; i < td->u.record.count; i++)
23,885✔
112
         h ^= mir_type_data(mu, td->u.record.fields[i])->hash;
18,374✔
113
      break;
114

115
   case MIR_TYPE_CLOSURE:
1,355✔
116
      if (!mir_is_null(td->u.closure.atype))
1,355✔
117
         h ^= mir_type_data(mu, td->u.closure.atype)->hash;
1,334✔
118
      h ^= mir_type_data(mu, td->u.closure.rtype)->hash;
1,355✔
119
      break;
1,355✔
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;
379,973✔
128
}
129

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

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

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

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

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

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

156
   case MIR_TYPE_REAL:
7,949✔
157
      return a->u.real.low == b->u.real.low
7,949✔
158
         && a->u.real.high == b->u.real.high;
7,949✔
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,116✔
165
      return a->u.uarray.dims == b->u.uarray.dims
42,116✔
166
         && a->u.uarray.elem.bits == b->u.uarray.elem.bits;
42,116✔
167

168
   case MIR_TYPE_CONTEXT:
8,212,902✔
169
      return a->u.context == b->u.context;
8,212,902✔
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,139✔
175
      if (a->u.record.name != b->u.record.name)
7,139✔
176
         return false;
177
      else if (a->u.record.count != b->u.record.count)
3,772✔
178
         return false;
179
      else {
180
         for (int i = 0; i < a->u.record.count; i++) {
16,520✔
181
            if (a->u.record.fields[i].bits != b->u.record.fields[i].bits)
12,748✔
182
               return false;
183
         }
184

185
         return true;
186
      }
187

188
   case MIR_TYPE_CLOSURE:
763✔
189
      return a->u.closure.atype.bits == b->u.closure.atype.bits
763✔
190
         && a->u.closure.rtype.bits == b->u.closure.rtype.bits;
763✔
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,694,286✔
201
{
202
   mir_context_t *mc = mu->context;
5,694,286✔
203
   type_tab_t *tab = load_acquire(&mc->typetab);
5,694,286✔
204

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

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

211
   return td;
5,694,286✔
212
}
213

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

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

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

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

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

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

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

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

258
         for (int i = 0; i < src_r->count; i++) {
7,377✔
259
            mir_type_t pointer = mir_get_var_pointer(mu, src_r->fields[i]);
5,635✔
260
            dst_r->fields[i] = src->u.record.fields[i];
5,635✔
261
            dst_r->fields[i + src_r->count] = pointer;
5,635✔
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,120✔
277
      {
278
         const mir_signal_type_t *src_s = &src->u.signal;
3,120✔
279
         mir_signal_type_t *dst_s = &dst->u.signal;
3,120✔
280

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

286
   default:
74,931✔
287
      dst->u = src->u;
74,931✔
288
   }
289
}
91,187✔
290

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

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

314
               max_id = MAX((uint32_t)slot.id, max_id);
14,597✔
315

316
               for (int pos = from_td->hash & (to->max_types - 1), j = 1;;
14,597✔
317
                    pos = (pos + j) & (to->max_types - 1), j++) {
3,001✔
318
                  const type_slot_t exist = mir_type_slot(to, pos);
17,598✔
319
                  if (exist.marker == FREE_MARKER) {
17,598✔
320
                     *to_td = *from_td;
14,597✔
321
                     store_release(&(to->hashtab[pos].bits), slot.bits);
14,597✔
322
                     break;
14,597✔
323
                  }
324
                  else
325
                     assert(exist.marker == INUSE_MARKER);
3,001✔
326
               }
327
            }
328
            break;
14,597✔
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 };
26,880✔
336
         if (atomic_cas(&(from->hashtab[i].bits), slot.bits, moved.bits))
26,880✔
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);
30✔
344

345
   DEBUG_ONLY(debugf("grew type table to %d slots, %d/%d in use", to->max_types,
30✔
346
                     max_id, from->max_types));
347
}
30✔
348

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

355
      if (from == to)
×
356
         break;
357

358
      thread_sleep(10);
×
359
   }
360
}
×
361

362
static void mir_grow_table(mir_context_t *mc, type_tab_t *cur)
30✔
363
{
364
   type_tab_t *newtab =
30✔
365
      xcalloc_flex(sizeof(type_tab_t), cur->max_types * 2, sizeof(type_data_t));
30✔
366
   newtab->max_types = cur->max_types * 2;
30✔
367
   newtab->hashtab = xcalloc_array(newtab->max_types, sizeof(uint32_t));
30✔
368

369
   if (atomic_cas(&mc->resizing, cur, newtab)) {
30✔
370
      mir_copy_table(cur, newtab);
30✔
371

372
      assert(atomic_load(&mc->resizing) == newtab);
30✔
373

374
      if (!atomic_cas(&mc->typetab, cur, newtab))
30✔
375
         should_not_reach_here();
376

377
      async_free(cur->hashtab);
30✔
378
      async_free(cur);
30✔
379
   }
380
   else {
381
      free(newtab);
×
382
      mir_wait_for_resize(mc);
×
383
   }
384
}
30✔
385

386
static mir_type_t mir_try_build_type(mir_unit_t *mu, const type_data_t *td,
380,007✔
387
                                     uint32_t hash)
388
{
389
   mir_context_t *mc = mu->context;
380,007✔
390
   type_tab_t *tab = load_acquire(&mc->typetab);
380,007✔
391

392
   assert(is_power_of_2(tab->max_types));
380,007✔
393

394
   for (int reprobe = 0, i = 1, pos = hash & (tab->max_types - 1);;
380,007✔
395
        pos = (pos + i) & (tab->max_types - 1), i++) {
46,769✔
396
      const type_slot_t slot = mir_type_slot(tab, pos);
426,776✔
397
      switch (slot.marker) {
426,776✔
398
      case BUSY_MARKER:
×
399
         spin_wait();
×
400
         return MIR_NULL_TYPE;
×
401
      case FREE_MARKER:
91,187✔
402
         {
403
            // Copy the type data before CAS-ing the slot to busy since
404
            // mir_install_type may allocate new types and deadlock
405
            type_data_t copy;
91,187✔
406
            mir_install_type(mu, &copy, td, hash);
91,187✔
407

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

415
               tab->types[id] = copy;
91,183✔
416
               store_release(&tab->hashtab[pos].bits, new.bits);
91,183✔
417
               return (mir_type_t){ .tag = MIR_TAG_TYPE, .id = id };
91,183✔
418
            }
419
            else {   // Raced for this slot, leak copy for now
420
               spin_wait();
4✔
421
               return MIR_NULL_TYPE;
4✔
422
            }
423
         }
424
      case INUSE_MARKER:
335,589✔
425
         if (hash != tab->types[slot.id].hash)
335,589✔
426
            break;
427
         else if (mir_compare_types(td, &(tab->types[slot.id])))
308,163✔
428
            return (mir_type_t){ .tag = MIR_TAG_TYPE, .id = slot.id };
288,790✔
429
         break;
430
      case MOVED_MARKER:
×
431
         mir_wait_for_resize(mc);
×
432
         return MIR_NULL_TYPE;
×
433
      }
434

435
      if (++reprobe == REPROBE_LIMIT) {
46,799✔
436
         mir_grow_table(mc, tab);
30✔
437
         return MIR_NULL_TYPE;
30✔
438
      }
439
   }
440
}
441

442
static mir_type_t mir_build_type(mir_unit_t *mu, const type_data_t *td)
379,973✔
443
{
444
   const uint32_t hash = mir_hash_type(mu, td);
379,973✔
445

446
   mir_type_t type;
380,007✔
447
   do {
380,007✔
448
      type = mir_try_build_type(mu, td, hash);
380,007✔
449
   } while (mir_is_null(type));
380,007✔
450

451
   return type;
379,973✔
452
}
453

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

468
   const type_data_t td = {
86,866✔
469
      .class = MIR_TYPE_INT,
470
      .repr = repr,
471
      .u = { .intg = { .low = low, .high = high } }
472
   };
473

474
   return mir_build_type(mu, &td);
86,866✔
475
}
476

477
mir_type_t mir_real_type(mir_unit_t *mu, double low, double high)
8,340✔
478
{
479
   const type_data_t td = {
8,340✔
480
      .class = MIR_TYPE_REAL,
481
      .u = { .real = { .low = low, .high = high } }
482
   };
483

484
   return mir_build_type(mu, &td);
8,340✔
485
}
486

487
mir_type_t mir_offset_type(mir_unit_t *mu)
78,837✔
488
{
489
   if (mir_is_null(mu->types.offset_type)) {
78,837✔
490
      const type_data_t td = {
22,821✔
491
         .class = MIR_TYPE_OFFSET,
492
         .repr = MIR_REPR_I64,
493
         .u = { .intg = { .low = INT64_MIN, .high = INT64_MAX } }
494
      };
495

496
      mu->types.offset_type = mir_build_type(mu, &td);
22,821✔
497
   }
498

499
   return mu->types.offset_type;
78,837✔
500
}
501

502
mir_type_t mir_locus_type(mir_unit_t *mu)
65,908✔
503
{
504
   if (mir_is_null(mu->types.locus_type)) {
65,908✔
505
      const type_data_t td = { .class = MIR_TYPE_LOCUS };
16,085✔
506
      mu->types.locus_type = mir_build_type(mu, &td);
16,085✔
507
   }
508

509
   return mu->types.locus_type;
65,908✔
510
}
511

512
mir_type_t mir_conversion_type(mir_unit_t *mu)
564✔
513
{
514
   if (mir_is_null(mu->types.conversion_type)) {
564✔
515
      const type_data_t td = { .class = MIR_TYPE_CONVERSION };
425✔
516
      mu->types.conversion_type = mir_build_type(mu, &td);
425✔
517
   }
518

519
   return mu->types.conversion_type;
564✔
520
}
521

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

529
   return mu->types.trigger_type;
362✔
530
}
531

532
mir_type_t mir_self_type(mir_unit_t *mu)
32,469✔
533
{
534
   if (mir_is_null(mu->types.self_type)) {
32,469✔
535
      const type_data_t td = {
31,482✔
536
         .class = MIR_TYPE_CONTEXT,
537
         .u.context = mu->name,
31,482✔
538
      };
539

540
      mu->types.self_type = mir_build_type(mu, &td);
31,482✔
541
   }
542

543
   return mu->types.self_type;
32,469✔
544
}
545

546
mir_type_t mir_bool_type(mir_unit_t *mu)
161,991✔
547
{
548
   if (mir_is_null(mu->types.bool_type))
161,991✔
549
      mu->types.bool_type = mir_int_type(mu, 0, 1);
13,294✔
550

551
   return mu->types.bool_type;
161,991✔
552
}
553

554
mir_type_t mir_time_type(mir_unit_t *mu)
330✔
555
{
556
   if (mir_is_null(mu->types.time_type))
330✔
557
      mu->types.time_type = mir_int_type(mu, INT64_MIN, INT64_MAX);
180✔
558

559
   return mu->types.time_type;
330✔
560
}
561

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

567
   return mu->types.double_type;
2✔
568
}
569

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

575
   return mu->types.string_type;
812✔
576
}
577

578
mir_type_t mir_pointer_type(mir_unit_t *mu, mir_type_t to)
78,617✔
579
{
580
   MIR_ASSERT(mir_get_class(mu, to) != MIR_TYPE_CARRAY,
78,617✔
581
              "cannot get pointer to carray type");
582

583
   const type_data_t td = {
78,617✔
584
      .class = MIR_TYPE_POINTER,
585
      .u = { .pointer = to }
586
   };
587

588
   return mir_build_type(mu, &td);
78,617✔
589
}
590

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

598
   return mir_build_type(mu, &td);
1,613✔
599
}
600

601
mir_type_t mir_opaque_type(mir_unit_t *mu)
394✔
602
{
603
   const type_data_t td = {
394✔
604
      .class = MIR_TYPE_OPAQUE,
605
   };
606

607
   return mir_build_type(mu, &td);
394✔
608
}
609

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

624
   return mir_build_type(mu, &td);
5,511✔
625
}
626

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

639
   return mir_build_type(mu, &td);
1,355✔
640
}
641

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

649
   return mir_build_type(mu, &td);
983✔
650
}
651

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

659
   return mir_build_type(mu, &td);
358✔
660
}
661

662
mir_type_t mir_carray_type(mir_unit_t *mu, int size, mir_type_t elem)
15,612✔
663
{
664
   MIR_ASSERT(mir_get_class(mu, elem) != MIR_TYPE_CARRAY,
15,612✔
665
              "array types may not be nested");
666

667
   const type_data_t td = {
15,612✔
668
      .class = MIR_TYPE_CARRAY,
669
      .u = {
670
         .carray = {
671
            .size = size,
672
            .elem = elem,
673
         }
674
      }
675
   };
676

677
   return mir_build_type(mu, &td);
15,612✔
678
}
679

680
mir_type_t mir_uarray_type(mir_unit_t *mu, int ndim, mir_type_t elem)
43,440✔
681
{
682
   MIR_ASSERT(mir_get_class(mu, elem) != MIR_TYPE_CARRAY,
43,440✔
683
              "array types may not be nested");
684

685
   const type_data_t td = {
43,440✔
686
      .class = MIR_TYPE_UARRAY,
687
      .u = {
688
         .uarray = {
689
            .dims = ndim,
690
            .elem = elem,
691
         }
692
      }
693
   };
694

695
   return mir_build_type(mu, &td);
43,440✔
696
}
697

698
mir_type_t mir_signal_type(mir_unit_t *mu, mir_type_t base)
25,123✔
699
{
700
   const type_data_t td = {
25,123✔
701
      .class = MIR_TYPE_SIGNAL,
702
      .u = { .signal = { .base = base } }
703
   };
704

705
   return mir_build_type(mu, &td);
25,123✔
706
}
707

708
mir_type_t mir_context_type(mir_unit_t *mu, ident_t name)
40,721✔
709
{
710
   const type_data_t td = {
40,721✔
711
      .class = MIR_TYPE_CONTEXT,
712
      .u = { .context = name }
713
   };
714

715
   return mir_build_type(mu, &td);
40,721✔
716
}
717

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

732
mir_type_t mir_get_elem(mir_unit_t *mu, mir_type_t type)
390,459✔
733
{
734
   const type_data_t *td = mir_type_data(mu, type);
390,459✔
735
   switch (td->class) {
390,459✔
736
   case MIR_TYPE_UARRAY:
172,746✔
737
      return td->u.uarray.elem;
172,746✔
738
   case MIR_TYPE_CARRAY:
116,604✔
739
      return td->u.carray.elem;
116,604✔
740
   case MIR_TYPE_ACCESS:
410✔
741
      return td->u.access.to;
410✔
742
   case MIR_TYPE_POINTER:
100,699✔
743
      return td->u.pointer;
100,699✔
744
   default:
×
745
      return MIR_NULL_TYPE;
×
746
   }
747
}
748

749
mir_type_t mir_get_pointer(mir_unit_t *mu, mir_type_t type)
294,411✔
750
{
751
   const type_data_t *td = mir_type_data(mu, type);
294,411✔
752
   switch (td->class) {
294,411✔
753
   case MIR_TYPE_SIGNAL:
14,338✔
754
      return td->u.signal.pointer;
14,338✔
755
   case MIR_TYPE_POINTER:
231,730✔
756
      return td->u.pointer;
231,730✔
757
   case MIR_TYPE_UARRAY:
24,249✔
758
      return td->u.uarray.pointer;
24,249✔
759
   case MIR_TYPE_CARRAY:
20,948✔
760
      return td->u.carray.pointer;
20,948✔
761
   case MIR_TYPE_ACCESS:
1,507✔
762
      return td->u.access.pointer;
1,507✔
763
   default:
1,639✔
764
      return MIR_NULL_TYPE;
1,639✔
765
   }
766
}
767

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

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

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

801
mir_class_t mir_get_class(mir_unit_t *mu, mir_type_t type)
2,210,291✔
802
{
803
   return mir_type_data(mu, type)->class;
2,210,291✔
804
}
805

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

818
const mir_type_t *mir_get_fields(mir_unit_t *mu, mir_type_t type, size_t *count)
61,259✔
819
{
820
   const type_data_t *td = mir_type_data(mu, type);
61,259✔
821
   assert(td->class == MIR_TYPE_RECORD);
61,259✔
822

823
   if (count != NULL) *count = td->u.record.count;
61,259✔
824
   return td->u.record.fields;
61,259✔
825
}
826

827
static uint32_t mir_hash_stamp(mir_unit_t *mu, const stamp_data_t *sd)
163,632✔
828
{
829
   uint32_t h = sd->kind;
163,632✔
830

831
   switch (sd->kind) {
163,632✔
832
   case _MIR_INVALID_STAMP:
833
      break;
834

835
   case MIR_STAMP_INT:
72,873✔
836
      h ^= mix_bits_64(sd->u.intg.low) >> 32;
72,873✔
837
      h ^= mix_bits_64(sd->u.intg.high);
72,873✔
838
      break;
72,873✔
839

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

845
   case MIR_STAMP_POINTER:
69,858✔
846
      h += knuth_hash(sd->u.pointer.memory);
69,858✔
847
      if (!mir_is_null(sd->u.pointer.elem))
69,858✔
848
         h ^= mir_stamp_data(mu, sd->u.pointer.elem)->hash;
20,502✔
849
      break;
850
   }
851

852
   return h;
163,632✔
853
}
854

855
static bool mir_compare_stamps(const stamp_data_t *a, const stamp_data_t *b)
74,034✔
856
{
857
   if (a->kind != b->kind)
74,034✔
858
      return false;
859

860
   switch (a->kind) {
74,034✔
861
   case _MIR_INVALID_STAMP:
862
      return false;
863

864
   case MIR_STAMP_INT:
33,005✔
865
      return a->u.intg.low == b->u.intg.low
33,005✔
866
         && a->u.intg.high == b->u.intg.high;
33,005✔
867

868
   case MIR_STAMP_REAL:
2,267✔
869
      return a->u.real.low == b->u.real.low
2,267✔
870
         && a->u.real.high == b->u.real.high;
2,267✔
871

872
   case MIR_STAMP_POINTER:
38,762✔
873
      return a->u.pointer.memory == b->u.pointer.memory
38,762✔
874
         && a->u.pointer.elem.bits == b->u.pointer.elem.bits;
38,762✔
875
   }
876

877
   should_not_reach_here();
878
}
879

880
static mir_stamp_t mir_build_stamp(mir_unit_t *mu, const stamp_data_t *sd)
163,632✔
881
{
882
   const uint32_t hash = mir_hash_stamp(mu, sd);
163,632✔
883

884
   for (int i = 0; i < mu->stamps.count; i++) {
2,206,282✔
885
      const stamp_data_t *other = &(mu->stamps.items[i]);
2,116,684✔
886
      if (other->hash == hash && mir_compare_stamps(other, sd))
2,116,684✔
887
         return (mir_stamp_t){ .tag = MIR_TAG_STAMP, .id = i };
74,034✔
888
   }
889

890
   mir_stamp_t s = { .tag = MIR_TAG_STAMP, .id  = mu->stamps.count };
89,598✔
891

892
   stamp_data_t new = {
89,598✔
893
      .kind = sd->kind,
89,598✔
894
      .hash = hash,
895
      .u    = sd->u,
896
   };
897
   APUSH(mu->stamps, new);
89,598✔
898

899
   return s;
89,598✔
900
}
901

902
const stamp_data_t *mir_stamp_data(mir_unit_t *mu, mir_stamp_t stamp)
56,870✔
903
{
904
   assert(stamp.tag == MIR_TAG_STAMP);
56,870✔
905
   return AREF(mu->stamps, stamp.id);
56,870✔
906
}
907

908
mir_stamp_t mir_int_stamp(mir_unit_t *mu, int64_t low, int64_t high)
72,873✔
909
{
910
   assert(low <= high);
72,873✔
911

912
   const stamp_data_t sd = {
72,873✔
913
      .kind = MIR_STAMP_INT,
914
      .u = { .intg = { .low = low, .high = high } }
915
   };
916

917
   return mir_build_stamp(mu, &sd);
72,873✔
918
}
919

920
mir_stamp_t mir_real_stamp(mir_unit_t *mu, double low, double high)
20,901✔
921
{
922
   assert(low <= high);
20,901✔
923

924
   const stamp_data_t sd = {
20,901✔
925
      .kind = MIR_STAMP_REAL,
926
      .u = { .real = { .low = low, .high = high } }
927
   };
928

929
   return mir_build_stamp(mu, &sd);
20,901✔
930
}
931

932
mir_stamp_t mir_pointer_stamp(mir_unit_t *mu, mir_mem_t mem, mir_stamp_t elem)
69,858✔
933
{
934
   const stamp_data_t sd = {
69,858✔
935
      .kind = MIR_STAMP_POINTER,
936
      .u = { .pointer = { .memory = mem, .elem = elem } },
937
   };
938

939
   return mir_build_stamp(mu, &sd);
69,858✔
940
}
941

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

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

953
   default:
954
      return false;
955
   }
956
}
957

958
mir_stamp_t mir_stamp_elem(mir_unit_t *mu, mir_stamp_t stamp)
117,065✔
959
{
960
   if (mir_is_null(stamp))
117,065✔
961
      return MIR_NULL_STAMP;
83,148✔
962

963
   const stamp_data_t *sd = mir_stamp_data(mu, stamp);
33,917✔
964
   switch (sd->kind) {
33,917✔
965
   case MIR_STAMP_POINTER:
33,915✔
966
      return sd->u.pointer.elem;
33,915✔
967
   default:
2✔
968
      return MIR_NULL_STAMP;
2✔
969
   }
970
}
971

972
mir_stamp_t mir_stamp_add(mir_unit_t *mu, mir_stamp_t left, mir_stamp_t right)
14,850✔
973
{
974
   if (mir_is_null(left) || mir_is_null(right))
14,850✔
975
      return MIR_NULL_STAMP;
14,848✔
976

977
   const stamp_data_t *lsd = mir_stamp_data(mu, left);
2✔
978
   const stamp_data_t *rsd = mir_stamp_data(mu, right);
2✔
979

980
   assert(lsd->kind == rsd->kind);
2✔
981

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

988
         return mir_int_stamp(mu, low, high);
2✔
989
      }
990

991
   case MIR_STAMP_REAL:
×
992
      {
993
         const double low  = lsd->u.real.low + rsd->u.real.low;
×
994
         const double high = lsd->u.real.high + rsd->u.real.high;
×
995

996
         return mir_real_stamp(mu, low, high);
×
997
      }
998

999
   default:
×
1000
      should_not_reach_here();
1001
   }
1002
}
1003

1004
mir_stamp_t mir_stamp_sub(mir_unit_t *mu, mir_stamp_t left, mir_stamp_t right)
19,956✔
1005
{
1006
   if (mir_is_null(left) || mir_is_null(right))
19,956✔
1007
      return MIR_NULL_STAMP;
19,956✔
1008

UNCOV
1009
   const stamp_data_t *lsd = mir_stamp_data(mu, left);
×
UNCOV
1010
   const stamp_data_t *rsd = mir_stamp_data(mu, right);
×
1011

UNCOV
1012
   assert(lsd->kind == rsd->kind);
×
1013

UNCOV
1014
   switch (lsd->kind) {
×
UNCOV
1015
   case MIR_STAMP_INT:
×
1016
      {
UNCOV
1017
         const int64_t low  = ssub64(lsd->u.intg.low, rsd->u.intg.high);
×
UNCOV
1018
         const int64_t high = ssub64(lsd->u.intg.high, rsd->u.intg.low);
×
1019

UNCOV
1020
         return mir_int_stamp(mu, low, high);
×
1021
      }
1022

1023
   case MIR_STAMP_REAL:
×
1024
      {
1025
         const double low  = lsd->u.real.low - rsd->u.real.high;
×
1026
         const double high = lsd->u.real.high - rsd->u.real.low;
×
1027

1028
         return mir_real_stamp(mu, low, high);
×
1029
      }
1030

1031
   default:
×
1032
      should_not_reach_here();
1033
   }
1034
}
1035

1036
mir_stamp_t mir_stamp_mul(mir_unit_t *mu, mir_stamp_t left, mir_stamp_t right)
2,092✔
1037
{
1038
   if (mir_is_null(left) || mir_is_null(right))
2,092✔
1039
      return MIR_NULL_STAMP;
2,092✔
1040

UNCOV
1041
   const stamp_data_t *lsd = mir_stamp_data(mu, left);
×
UNCOV
1042
   const stamp_data_t *rsd = mir_stamp_data(mu, right);
×
1043

UNCOV
1044
   assert(lsd->kind == rsd->kind);
×
1045

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

UNCOV
1054
         int64_t min = MIN(MIN(ll, lh), MIN(hl, hh));
×
UNCOV
1055
         int64_t max = MAX(MAX(ll, lh), MAX(hl, hh));
×
1056

UNCOV
1057
         return mir_int_stamp(mu, min, max);
×
1058
      }
1059

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

1067
         double min = MIN(MIN(ll, lh), MIN(hl, hh));
×
1068
         double max = MAX(MAX(ll, lh), MAX(hl, hh));
×
1069

1070
         return mir_real_stamp(mu, min, max);
×
1071
      }
1072

1073
   default:
×
1074
      should_not_reach_here();
1075
   }
1076
}
1077

1078
mir_stamp_t mir_stamp_div(mir_unit_t *mu, mir_stamp_t left, mir_stamp_t right)
885✔
1079
{
1080
   if (mir_is_null(left) || mir_is_null(right))
885✔
1081
      return MIR_NULL_STAMP;
871✔
1082

1083
   return MIR_NULL_STAMP;  // TODO
14✔
1084
}
1085

1086
mir_stamp_t mir_stamp_rem(mir_unit_t *mu, mir_stamp_t left, mir_stamp_t right)
97✔
1087
{
1088
   if (mir_is_null(left) || mir_is_null(right))
97✔
1089
      return MIR_NULL_STAMP;
95✔
1090

1091
   const stamp_data_t *lsd = mir_stamp_data(mu, left);
2✔
1092
   const stamp_data_t *rsd = mir_stamp_data(mu, right);
2✔
1093

1094
   assert(lsd->kind == rsd->kind);
2✔
1095

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

1103
   default:
×
1104
      should_not_reach_here();
1105
   }
1106
}
1107

1108
mir_stamp_t mir_stamp_cmp(mir_unit_t *mu, mir_cmp_t cmp, mir_stamp_t left,
33,545✔
1109
                          mir_stamp_t right)
1110
{
1111
   if (mir_is_null(left) || mir_is_null(right))
33,545✔
1112
      return MIR_NULL_STAMP;
33,467✔
1113

1114
   const stamp_data_t *lsd = mir_stamp_data(mu, left);
78✔
1115
   const stamp_data_t *rsd = mir_stamp_data(mu, right);
78✔
1116

1117
   assert(lsd->kind == rsd->kind);
78✔
1118

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

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

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

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

1160
         default:
×
1161
            should_not_reach_here();
1162
         }
1163
      }
1164

1165
   case MIR_STAMP_REAL:
25✔
1166
      return MIR_NULL_STAMP;
25✔
1167

1168
   default:
×
1169
      should_not_reach_here();
1170
   }
1171
}
1172

1173
mir_stamp_t mir_stamp_union(mir_unit_t *mu, mir_stamp_t left, mir_stamp_t right)
12,311✔
1174
{
1175
   if (mir_is_null(left))
12,311✔
1176
      return right;
11,565✔
1177
   else if (mir_is_null(right))
746✔
1178
      return left;
×
1179

1180
   const stamp_data_t *lsd = mir_stamp_data(mu, left);
746✔
1181
   const stamp_data_t *rsd = mir_stamp_data(mu, right);
746✔
1182

1183
   assert(lsd->kind == rsd->kind);
746✔
1184

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

1191
         return mir_int_stamp(mu, low, high);
746✔
1192
      }
1193

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

1199
         return mir_real_stamp(mu, low, high);
×
1200
      }
1201

1202
   default:
×
1203
      should_not_reach_here();
1204
   }
1205
}
1206

1207
bool mir_stamp_const(mir_unit_t *mu, mir_stamp_t stamp, int64_t *cval)
33,545✔
1208
{
1209
   if (mir_is_null(stamp))
33,545✔
1210
      return false;
1211

1212
   const stamp_data_t *sd = mir_stamp_data(mu, stamp);
2✔
1213

1214
   if (sd->kind != MIR_STAMP_INT || sd->u.intg.low != sd->u.intg.high)
2✔
1215
      return false;
1216

1217
   *cval = sd->u.intg.low;
2✔
1218
   return true;
2✔
1219
}
1220

1221
bool mir_same_type(mir_unit_t *mu, mir_type_t a, mir_type_t b)
92,671✔
1222
{
1223
   if (mir_is_null(a) && mir_is_null(b))
92,671✔
1224
      return true;
1225
   else if (mir_is_null(a)) {
90,536✔
1226
      const type_data_t *btd = mir_type_data(mu, b);
7,460✔
1227
      return btd->class == MIR_TYPE_OFFSET || btd->class == MIR_TYPE_INT;
7,460✔
1228
   }
1229
   else if (mir_is_null(b)) {
83,076✔
1230
      const type_data_t *atd = mir_type_data(mu, a);
16,882✔
1231
      return atd->class == MIR_TYPE_OFFSET || atd->class == MIR_TYPE_INT;
16,882✔
1232
   }
1233
   else
1234
      return mir_equals(a, b);
66,194✔
1235
}
1236

1237
void mir_free_types(type_tab_t *tab)
8,854✔
1238
{
1239
#ifdef DEBUG
1240
   for (int i = 0; i < tab->max_types; i++) {
2,302,358✔
1241
      const type_slot_t islot = mir_type_slot(tab, i);
2,293,504✔
1242
      assert(islot.marker == FREE_MARKER || islot.marker == INUSE_MARKER);
2,293,504✔
1243

1244
      if (islot.marker == INUSE_MARKER) {
2,293,504✔
1245
         const type_data_t *itd = &(tab->types[islot.id]);
91,158✔
1246
         for (int j = 0; j < i; j++) {
37,552,297✔
1247
            const type_slot_t jslot = mir_type_slot(tab, j);
37,461,139✔
1248
            if (jslot.marker == INUSE_MARKER) {
37,461,139✔
1249
               const type_data_t *jtd = &(tab->types[jslot.id]);
10,680,597✔
1250
               if (mir_compare_types(itd, jtd))
10,680,597✔
1251
                  fatal_trace("duplicate types in table at %d (%d => %08x) "
1252
                              "and %d (%d => %08x)", i, islot.id, itd->hash,
×
1253
                              j, jslot.id, jtd->hash);
×
1254
            }
1255
         }
1256
      }
1257
   }
1258
#endif
1259

1260
   free(tab->hashtab);
8,854✔
1261
   free(tab);
8,854✔
1262
}
8,854✔
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