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

nickg / nvc / 13741295555

08 Mar 2025 07:54PM UTC coverage: 92.319% (+0.08%) from 92.236%
13741295555

push

github

nickg
Pass mir_context_t around explicitly

33 of 38 new or added lines in 3 files covered. (86.84%)

542 existing lines in 5 files now uncovered.

68074 of 73738 relevant lines covered (92.32%)

433184.62 hits per line

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

93.41
/src/jit/jit-exits.c
1
//
2
//  Copyright (C) 2022-2024  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 "diag.h"
20
#include "jit/jit-exits.h"
21
#include "jit/jit-ffi.h"
22
#include "jit/jit-priv.h"
23
#include "jit/jit.h"
24
#include "lib.h"
25
#include "object.h"
26
#include "psl/psl-node.h"
27
#include "rt/assert.h"
28
#include "rt/mspace.h"
29
#include "rt/rt.h"
30
#include "rt/structs.h"
31
#include "type.h"
32

33
#include <assert.h>
34
#include <ctype.h>
35
#include <errno.h>
36
#include <float.h>
37
#include <inttypes.h>
38
#include <stdio.h>
39
#include <stdlib.h>
40
#include <string.h>
41

42
void x_index_fail(int64_t value, int64_t left, int64_t right, int8_t dir,
53✔
43
                  tree_t where, tree_t hint)
44
{
45
   type_t type = tree_type(hint);
53✔
46

47
   LOCAL_TEXT_BUF tb = tb_new();
53✔
48
   tb_cat(tb, "index ");
53✔
49
   to_string(tb, type, value);
53✔
50
   tb_printf(tb, " outside of %s range ", type_pp(type));
53✔
51
   to_string(tb, type, left);
53✔
52
   tb_cat(tb, dir == RANGE_TO ? " to " : " downto ");
66✔
53
   to_string(tb, type, right);
53✔
54

55
   jit_msg(tree_loc(where), DIAG_FATAL, "%s", tb_get(tb));
53✔
56
}
×
57

58
void x_length_fail(int64_t left, int64_t right, int32_t dim, tree_t where)
100✔
59
{
60
   const tree_kind_t kind = tree_kind(where);
100✔
61

62
   LOCAL_TEXT_BUF tb = tb_new();
100✔
63
   switch (kind) {
100✔
64
   case T_PORT_DECL:
14✔
65
   case T_GENERIC_DECL:
66
   case T_PARAM_DECL:
67
   case T_PARAM:
68
      tb_cat(tb, "actual");
14✔
69
      break;
14✔
70
   case T_CASE:
3✔
71
   case T_MATCH_CASE:
72
      tb_cat(tb, "expression");
3✔
73
      break;
3✔
74
   case T_ASSOC:
6✔
75
      tb_cat(tb, "choice");
6✔
76
      break;
6✔
77
   case T_AGGREGATE:
12✔
78
      tb_cat(tb, "aggregate");
12✔
79
      break;
12✔
80
   case T_EXTERNAL_NAME:
3✔
81
      {
82
         tree_t last = tree_part(where, tree_parts(where) - 1);
3✔
83
         tb_printf(tb, "object %s", istr(tree_ident(last)));
3✔
84
      }
85
      break;
3✔
86
   default:
62✔
87
      tb_cat(tb, "value");
62✔
88
      break;
62✔
89
   }
90

91
   tb_printf(tb, " length %"PRIi64, right);
100✔
92
   if (dim > 0)
100✔
93
      tb_printf(tb, " for dimension %d", dim);
3✔
94
   tb_cat(tb, " does not match ");
100✔
95

96
   switch (kind) {
100✔
97
   case T_PORT_DECL:
×
98
      tb_printf(tb, "port %s", istr(tree_ident(where)));
×
99
      break;
×
100
   case T_PARAM_DECL:
6✔
101
      tb_printf(tb, "parameter %s", istr(tree_ident(where)));
6✔
102
      break;
6✔
103
   case T_GENERIC_DECL:
1✔
104
      tb_printf(tb, "generic %s", istr(tree_ident(where)));
1✔
105
      break;
1✔
106
   case T_VAR_DECL:
6✔
107
      tb_printf(tb, "variable %s", istr(tree_ident(where)));
6✔
108
      break;
6✔
109
   case T_CONST_DECL:
3✔
110
      tb_printf(tb, "constant %s", istr(tree_ident(where)));
3✔
111
      break;
3✔
112
   case T_SIGNAL_DECL:
3✔
113
      tb_printf(tb, "signal %s", istr(tree_ident(where)));
3✔
114
      break;
3✔
115
   case T_REF:
20✔
116
      tb_printf(tb, "%s %s", class_str(class_of(where)),
20✔
117
                istr(tree_ident(where)));
118
      break;
20✔
119
   case T_FIELD_DECL:
3✔
120
      tb_printf(tb, "field %s", istr(tree_ident(where)));
3✔
121
      break;
3✔
122
   case T_ALIAS:
3✔
123
      tb_printf(tb, "alias %s", istr(tree_ident(where)));
3✔
124
      break;
3✔
125
   case T_CASE:
3✔
126
   case T_MATCH_CASE:
127
      tb_cat(tb, "case choice");
3✔
128
      break;
3✔
129
   case T_ASSOC:
6✔
130
      tb_cat(tb, "expected");
6✔
131
      break;
6✔
132
   case T_PARAM:
7✔
133
      tb_cat(tb, "formal");
7✔
134
      break;
7✔
135
   case T_EXTERNAL_NAME:
3✔
136
      tb_cat(tb, "external name subtype indication");
3✔
137
      break;
3✔
138
   case T_TYPE_CONV:
18✔
139
   case T_ATTR_REF:
140
   case T_AGGREGATE:
141
      tb_printf(tb, "subtype %s", type_pp(tree_type(where)));
18✔
142
      break;
18✔
143
   default:
18✔
144
      tb_cat(tb, "target");
18✔
145
      break;
18✔
146
   }
147

148
   tb_printf(tb, " length %"PRIi64, left);
100✔
149

150
   jit_msg(tree_loc(where), DIAG_FATAL, "%s", tb_get(tb));
100✔
151
}
×
152

153
void x_range_fail(int64_t value, int64_t left, int64_t right, int8_t dir,
48✔
154
                  tree_t where, tree_t hint)
155
{
156
   // Hint tree may be an array type conversion
157
   type_t type = type_elem_recur(tree_type(hint));
48✔
158

159
   LOCAL_TEXT_BUF tb = tb_new();
48✔
160
   tb_cat(tb, "value ");
48✔
161
   to_string(tb, type, value);
48✔
162
   tb_printf(tb, " outside of %s range ", type_pp(type));
48✔
163
   to_string(tb, type, left);
48✔
164
   tb_cat(tb, dir == RANGE_TO ? " to " : " downto ");
48✔
165
   to_string(tb, type, right);
48✔
166

167
   switch (tree_kind(hint)) {
48✔
168
   case T_SIGNAL_DECL:
26✔
169
   case T_CONST_DECL:
170
   case T_VAR_DECL:
171
   case T_REF:
172
      tb_printf(tb, " for %s %s", class_str(class_of(hint)),
26✔
173
                istr(tree_ident(hint)));
174
      break;
26✔
175
   case T_PORT_DECL:
×
176
      tb_printf(tb, " for port %s", istr(tree_ident(hint)));
×
177
      break;
×
178
   case T_PARAM_DECL:
3✔
179
      tb_printf(tb, " for parameter %s", istr(tree_ident(hint)));
3✔
180
      break;
3✔
181
   case T_GENERIC_DECL:
1✔
182
      tb_printf(tb, " for generic %s", istr(tree_ident(hint)));
1✔
183
      break;
1✔
184
   case T_ATTR_REF:
3✔
185
      tb_printf(tb, " for attribute '%s", istr(tree_ident(hint)));
3✔
186
      break;
3✔
187
   default:
188
      break;
189
   }
190

191
   jit_msg(tree_loc(where), DIAG_FATAL, "%s", tb_get(tb));
48✔
192
}
×
193

194
void x_exponent_fail(int64_t value, tree_t where)
412✔
195
{
196
   jit_msg(tree_loc(where), DIAG_FATAL, "negative exponent %"PRIi64
412✔
197
           " only allowed for floating-point types", value);
198
}
×
199

200
void x_overflow(int64_t lhs, int64_t rhs, tree_t where)
19✔
201
{
202
   LOCAL_TEXT_BUF tb = tb_new();
19✔
203
   if (tree_kind(where) == T_FCALL) {
19✔
204
      switch (tree_subkind(tree_ref(where))) {
19✔
205
      case S_ADD:
6✔
206
         tb_printf(tb, "%"PRIi64" + %"PRIi64, lhs, rhs);
6✔
207
         break;
6✔
208
      case S_MUL:
5✔
209
         tb_printf(tb, "%"PRIi64" * %"PRIi64, lhs, rhs);
5✔
210
         break;
5✔
211
      case S_SUB:
2✔
212
         tb_printf(tb, "%"PRIi64" - %"PRIi64, lhs, rhs);
2✔
213
         break;
2✔
214
      case S_NEGATE:
1✔
215
         tb_printf(tb, "-(%"PRIi64")", lhs);
1✔
216
         break;
1✔
217
      case S_EXP:
5✔
218
         tb_printf(tb, "%"PRIi64" ** %"PRIi64, lhs, rhs);
5✔
219
         break;
5✔
220
      }
221
   }
222

223
   jit_msg(tree_loc(where), DIAG_FATAL,
19✔
224
           "result of %s cannot be represented as %s",
225
           tb_get(tb), type_pp(tree_type(where)));
226
}
×
227

228
void x_null_deref(tree_t where)
4✔
229
{
230
   jit_msg(tree_loc(where), DIAG_FATAL, "null access dereference");
4✔
231
}
×
232

233
void x_div_zero(tree_t where)
10✔
234
{
235
   jit_msg(tree_loc(where), DIAG_FATAL, "division by zero");
10✔
236
}
×
237

238
void x_unreachable(tree_t where)
7✔
239
{
240
   if (where != NULL && tree_kind(where) == T_FUNC_BODY)
7✔
241
      jit_msg(tree_loc(where), DIAG_FATAL, "function %s did not return a value",
4✔
242
              istr(tree_ident(where)));
243
   else
244
      jit_msg(NULL, DIAG_FATAL, "executed unreachable instruction");
3✔
245
}
×
246

247
void x_func_wait(void)
7✔
248
{
249
   jit_stack_trace_t *trace = jit_stack_trace();
7✔
250
   tree_t inner = tree_from_object(trace->frames[0].object);
7✔
251
   free(trace);
7✔
252

253
   const char *what;
7✔
254
   switch (tree_kind(inner)) {
7✔
255
   case T_PROC_BODY: what = "call to protected type method"; break;
256
   case T_PROCESS: what = "process with sensitivity list"; break;
3✔
257
   default: what = "function call";
1✔
258
   }
259

260
   jit_msg(NULL, DIAG_FATAL, "cannot wait inside %s", what);
7✔
261
}
×
262

263
void x_instance_name(attr_kind_t kind, text_buf_t *tb)
1,312✔
264
{
265
   assert(kind == ATTR_INSTANCE_NAME || kind == ATTR_PATH_NAME);
1,312✔
266

267
   jit_stack_trace_t *trace LOCAL = jit_stack_trace();
2,624✔
268
   for (int i = 0; i < trace->count; i++) {
1,312✔
269
      tree_t where = tree_from_object(trace->frames[i].object);
1,312✔
270
      if (where == NULL)
1,312✔
271
         continue;
×
272

273
      switch (tree_kind(where)) {
1,312✔
274
      case T_BLOCK:
1,018✔
275
         {
276
            tree_t hier = tree_decl(where, 0);
1,018✔
277
            assert(tree_kind(hier) == T_HIER);
1,018✔
278

279
            ident_t inst = tree_ident(hier);
1,018✔
280

281
            if (kind == ATTR_PATH_NAME)
1,018✔
282
               instance_name_to_path(tb, istr(inst));
581✔
283
            else
284
               tb_istr(tb, inst);
437✔
285
         }
286
         return;
287

288
      case T_PACKAGE:
294✔
289
      case T_PACK_BODY:
290
      case T_PACK_INST:
291
         {
292
            tb_append(tb, ':');
294✔
293
            tb_istr(tb, tree_ident(primary_unit_of(where)));
294✔
294
            tb_replace(tb, '.', ':');
294✔
295
            tb_downcase(tb);
294✔
296
         }
297
         return;
294✔
298

299
      default:
300
         break;
301
      }
302
   }
303

304
   fatal_trace("cannot get instance name");
305
}
306

307
////////////////////////////////////////////////////////////////////////////////
308
// Entry point from interpreter or JIT compiled code
309

310
DLLEXPORT
311
void __nvc_sched_waveform(jit_anchor_t *anchor, jit_scalar_t *args,
3,700,269✔
312
                          tlab_t *tlab)
313
{
314
   jit_thread_local_t *thread = jit_attach_thread(anchor);
3,700,269✔
315

316
   sig_shared_t *shared = args[0].pointer;
3,700,269✔
317
   int32_t       offset = args[1].integer;
3,700,269✔
318
   int32_t       count  = args[2].integer;
3,700,269✔
319
   jit_scalar_t  value  = { .integer = args[3].integer };
3,700,269✔
320
   int64_t       after  = args[4].integer;
3,700,269✔
321
   int64_t       reject = args[5].integer;
3,700,269✔
322
   bool          scalar = args[6].integer;
3,700,269✔
323

324
   if (scalar)
3,700,269✔
325
      x_sched_waveform_s(shared, offset, value.integer, after, reject);
3,385,507✔
326
   else
327
      x_sched_waveform(shared, offset, value.pointer, count,
314,762✔
328
                       after, reject);
329

330
   thread->anchor = NULL;
3,700,263✔
331
}
3,700,263✔
332

333
DLLEXPORT
334
void __nvc_test_event(jit_anchor_t *anchor, jit_scalar_t *args, tlab_t *tlab)
400✔
335
{
336
   jit_thread_local_t *thread = jit_attach_thread(anchor);
400✔
337

338
   sig_shared_t *shared = args[0].pointer;
400✔
339
   int32_t       offset = args[1].integer;
400✔
340
   int32_t       count  = args[2].integer;
400✔
341

342
   args[0].integer = x_test_net_event(shared, offset, count);
400✔
343

344
   thread->anchor = NULL;
400✔
345
}
400✔
346

347
DLLEXPORT
348
void __nvc_last_event(jit_anchor_t *anchor, jit_scalar_t *args, tlab_t *tlab)
57✔
349
{
350
   jit_thread_local_t *thread = jit_attach_thread(anchor);
57✔
351

352
   sig_shared_t *shared = args[0].pointer;
57✔
353
   uint32_t      offset = args[1].integer;
57✔
354
   uint32_t      count  = args[2].integer;
57✔
355

356
   args[0].integer = x_last_event(shared, offset, count);
57✔
357

358
   thread->anchor = NULL;
57✔
359
}
57✔
360

361
DLLEXPORT
362
void __nvc_sched_process(jit_anchor_t *anchor, jit_scalar_t *args, tlab_t *tlab)
322,473✔
363
{
364
   jit_thread_local_t *thread = jit_attach_thread(anchor);
322,473✔
365

366
   int64_t after = args[0].integer;
322,473✔
367

368
   x_sched_process(after);
322,473✔
369

370
   thread->anchor = NULL;
322,470✔
371
}
322,470✔
372

373
DLLEXPORT
374
void __nvc_do_exit(jit_exit_t which, jit_anchor_t *anchor, jit_scalar_t *args,
1,540,782✔
375
                   tlab_t *tlab)
376
{
377
   jit_thread_local_t *thread = jit_attach_thread(anchor);
1,540,782✔
378

379
   switch (which) {
1,540,782✔
380
   case JIT_EXIT_ASSERT_FAIL:
939✔
381
      {
382
         uint8_t  *msg        = args[0].pointer;
939✔
383
         int32_t   len        = args[1].integer;
939✔
384
         int32_t   severity   = args[2].integer;
939✔
385
         int64_t   hint_left  = args[3].integer;
939✔
386
         int64_t   hint_right = args[4].integer;
939✔
387
         int8_t    hint_valid = args[5].integer;
939✔
388
         object_t *where      = args[6].pointer;
939✔
389

390
         x_assert_fail(msg, len, severity, hint_left, hint_right,
939✔
391
                       hint_valid, where);
392
      }
393
      break;
939✔
394

395
   case JIT_EXIT_REPORT:
3,992✔
396
      {
397
         uint8_t  *msg      = args[0].pointer;
3,992✔
398
         int32_t   len      = args[1].integer;
3,992✔
399
         int32_t   severity = args[2].integer;
3,992✔
400
         object_t *where    = args[3].pointer;
3,992✔
401

402
         x_report(msg, len, severity, where);
3,992✔
403
      }
404
      break;
3,992✔
405

406
   case JIT_EXIT_INIT_SIGNAL:
35,395✔
407
      {
408
         int64_t      count  = args[0].integer;
35,395✔
409
         int32_t      size   = args[1].integer;
35,395✔
410
         jit_scalar_t value  = { .integer = args[2].integer };
35,395✔
411
         int32_t      flags  = args[3].integer;
35,395✔
412
         tree_t       where  = args[4].pointer;
35,395✔
413
         int32_t      offset = args[5].integer;
35,395✔
414
         bool         scalar = args[6].integer;
35,395✔
415

416
         args[0].pointer = x_init_signal(count, size, value, scalar,
35,395✔
417
                                         flags, where, offset);
418
      }
419
      break;
35,394✔
420

421
   case JIT_EXIT_IMPLICIT_SIGNAL:
100✔
422
      {
423
         int32_t       count   = args[0].integer;
100✔
424
         int32_t       size    = args[1].integer;
100✔
425
         tree_t        where   = args[2].pointer;
100✔
426
         int32_t       kind    = args[3].integer;
100✔
427
         jit_handle_t  handle  = args[4].integer;
100✔
428
         void         *context = args[5].pointer;
100✔
429
         int64_t       delay   = args[6].integer;
100✔
430

431
         ffi_closure_t closure = { handle, context };
100✔
432
         args[0].pointer = x_implicit_signal(count, size, where, kind,
100✔
433
                                             &closure, delay);
434
      }
435
      break;
100✔
436

437
   case JIT_EXIT_RESOLVE_SIGNAL:
6,684✔
438
      {
439
         sig_shared_t *shared  = args[0].pointer;
6,684✔
440
         jit_handle_t  handle  = args[1].integer;
6,684✔
441
         void         *context = args[2].pointer;
6,684✔
442
         int32_t       ileft   = args[3].integer;
6,684✔
443
         int32_t       nlits   = args[4].integer;
6,684✔
444
         int32_t       flags   = args[5].integer;
6,684✔
445

446
         x_resolve_signal(shared, handle, context, ileft, nlits, flags);
6,684✔
447
      }
448
      break;
6,684✔
449

450
   case JIT_EXIT_DRIVE_SIGNAL:
13,828✔
451
      {
452
         sig_shared_t *ss     = args[0].pointer;
13,828✔
453
         int32_t       offset = args[1].integer;
13,828✔
454
         int32_t       count  = args[2].integer;
13,828✔
455

456
         x_drive_signal(ss, offset, count);
13,828✔
457
      }
458
      break;
13,828✔
459

460
   case JIT_EXIT_TRANSFER_SIGNAL:
1,160✔
461
      {
462
         sig_shared_t *target    = args[0].pointer;
1,160✔
463
         int32_t       toffset   = args[1].integer;
1,160✔
464
         sig_shared_t *source    = args[2].pointer;
1,160✔
465
         int32_t       soffset   = args[3].integer;
1,160✔
466
         int32_t       count     = args[4].integer;
1,160✔
467
         int64_t       after     = args[5].integer;
1,160✔
468
         int64_t       reject    = args[6].integer;
1,160✔
469

470
         x_transfer_signal(target, toffset, source, soffset,
1,160✔
471
                           count, after, reject);
472
      }
473
      break;
1,160✔
474

475
   case JIT_EXIT_MAP_SIGNAL:
7,814✔
476
      {
477
         sig_shared_t  *src_ss     = args[0].pointer;
7,814✔
478
         uint32_t       src_offset = args[1].integer;
7,814✔
479
         sig_shared_t  *dst_ss     = args[2].pointer;
7,814✔
480
         uint32_t       dst_offset = args[3].integer;
7,814✔
481
         uint32_t       count      = args[4].integer;
7,814✔
482

483
         x_map_signal(src_ss, src_offset, dst_ss, dst_offset, count);
7,814✔
484
      }
485
      break;
7,814✔
486

487
   case JIT_EXIT_MAP_CONST:
605✔
488
      {
489
         sig_shared_t *dst_ss     = args[0].pointer;
605✔
490
         uint32_t      dst_offset = args[1].integer;
605✔
491
         jit_scalar_t  initval    = { .integer = args[2].integer };
605✔
492
         uint32_t      dst_count  = args[3].integer;
605✔
493
         bool          scalar     = args[4].integer;
605✔
494

495
         const void *vptr = scalar ? &initval.integer : initval.pointer;
605✔
496

497
         x_map_const(dst_ss, dst_offset, vptr, dst_count);
605✔
498
      }
499
      break;
605✔
500

501
   case JIT_EXIT_MAP_IMPLICIT:
80✔
502
      {
503
         sig_shared_t  *src_ss     = args[0].pointer;
80✔
504
         uint32_t       src_offset = args[1].integer;
80✔
505
         sig_shared_t  *dst_ss     = args[2].pointer;
80✔
506
         uint32_t       dst_offset = args[3].integer;
80✔
507
         uint32_t       count      = args[4].integer;
80✔
508

509
         x_map_implicit(src_ss, src_offset, dst_ss, dst_offset, count);
80✔
510
      }
511
      break;
80✔
512

513
   case JIT_EXIT_SCHED_PROCESS:
107,499✔
514
      __nvc_sched_process(anchor, args, tlab);
107,499✔
515
      break;
107,499✔
516

517
   case JIT_EXIT_SCHED_WAVEFORM:
1,230,646✔
518
      __nvc_sched_waveform(anchor, args, tlab);
1,230,646✔
519
      break;
1,230,646✔
520

521
   case JIT_EXIT_SCHED_EVENT:
41,243✔
522
      {
523
         sig_shared_t *shared  = args[0].pointer;
41,243✔
524
         int32_t       offset  = args[1].integer;
41,243✔
525
         int32_t       count   = args[2].integer;
41,243✔
526

527
         x_sched_event(shared, offset, count);
41,243✔
528
      }
529
      break;
41,243✔
530

531
   case JIT_EXIT_ALIAS_SIGNAL:
5,630✔
532
      {
533
         sig_shared_t *ss    = args[0].pointer;
5,630✔
534
         tree_t        where = args[1].pointer;
5,630✔
535

536
         x_alias_signal(ss, where);
5,630✔
537
      }
538
      break;
5,630✔
539

540
   case JIT_EXIT_DISCONNECT:
45✔
541
      {
542
         sig_shared_t *shared = args[0].pointer;
45✔
543
         int32_t       offset = args[1].integer;
45✔
544
         int32_t       count  = args[2].integer;
45✔
545
         int64_t       reject = args[3].integer;
45✔
546
         int64_t       after  = args[4].integer;
45✔
547

548
         x_disconnect(shared, offset, count, after, reject);
45✔
549
      }
550
      break;
45✔
551

552
   case JIT_EXIT_UNREACHABLE:
7✔
553
      {
554
         tree_t where = args[0].pointer;
7✔
555
         x_unreachable(where);
7✔
556
      }
557
      break;
7✔
558

559
   case JIT_EXIT_OVERFLOW:
19✔
560
      {
561
         int32_t lhs   = args[0].integer;
19✔
562
         int32_t rhs   = args[1].integer;
19✔
563
         tree_t  where = args[2].pointer;
19✔
564

565
         x_overflow(lhs, rhs, where);
19✔
566
      }
567
      break;
19✔
568

569
   case JIT_EXIT_INDEX_FAIL:
53✔
570
      {
571
         int64_t      value = args[0].integer;
53✔
572
         int64_t      left  = args[1].integer;
53✔
573
         int64_t      right = args[2].integer;
53✔
574
         range_kind_t dir   = args[3].integer;
53✔
575
         tree_t       where = args[4].pointer;
53✔
576
         tree_t       hint  = args[5].pointer;
53✔
577

578
         x_index_fail(value, left, right, dir, where, hint);
53✔
579
      }
580
      break;
53✔
581

582
   case JIT_EXIT_RANGE_FAIL:
48✔
583
      {
584
         int64_t      value = args[0].integer;
48✔
585
         int64_t      left  = args[1].integer;
48✔
586
         int64_t      right = args[2].integer;
48✔
587
         range_kind_t dir   = args[3].integer;
48✔
588
         tree_t       where = args[4].pointer;
48✔
589
         tree_t       hint  = args[5].pointer;
48✔
590

591
         x_range_fail(value, left, right, dir, where, hint);
48✔
592
      }
593
      break;
48✔
594

595
   case JIT_EXIT_FORCE:
90✔
596
      {
597
         sig_shared_t *shared = args[0].pointer;
90✔
598
         int32_t       offset = args[1].integer;
90✔
599
         int32_t       count  = args[2].integer;
90✔
600
         jit_scalar_t  value  = { .integer = args[3].integer };
90✔
601
         bool          scalar = args[4].integer;
90✔
602

603
         if (scalar)
90✔
604
            x_force(shared, offset, count, &value.integer);
72✔
605
         else
606
            x_force(shared, offset, count, value.pointer);
18✔
607
      }
608
      break;
90✔
609

610
   case JIT_EXIT_RELEASE:
30✔
611
      {
612
         sig_shared_t *shared = args[0].pointer;
30✔
613
         int32_t       offset = args[1].integer;
30✔
614
         int32_t       count  = args[2].integer;
30✔
615

616
         x_release(shared, offset, count);
30✔
617
      }
618
      break;
30✔
619

620
   case JIT_EXIT_DEPOSIT_SIGNAL:
273✔
621
      {
622
         sig_shared_t *shared = args[0].pointer;
273✔
623
         int32_t       offset = args[1].integer;
273✔
624
         int32_t       count  = args[2].integer;
273✔
625
         jit_scalar_t  value  = { .integer = args[3].integer };
273✔
626
         bool          scalar = args[4].integer;
273✔
627

628
         if (scalar)
273✔
629
            x_deposit_signal(shared, offset, count, &value.integer);
×
630
         else
631
            x_deposit_signal(shared, offset, count, value.pointer);
273✔
632
      }
633
      break;
273✔
634

635
   case JIT_EXIT_PUT_CONVERSION:
12,576✔
636
      {
637
         rt_conv_func_t *cf     = args[0].pointer;
12,576✔
638
         sig_shared_t   *shared = args[1].pointer;
12,576✔
639
         int32_t         offset = args[2].integer;
12,576✔
640
         int32_t         count  = args[3].integer;
12,576✔
641
         jit_scalar_t    value  = { .integer = args[4].integer };
12,576✔
642
         bool            scalar = args[5].integer;
12,576✔
643

644
         if (scalar)
12,576✔
645
            x_put_conversion(cf, shared, offset, count, &value.integer);
531✔
646
         else
647
            x_put_conversion(cf, shared, offset, count, value.pointer);
12,045✔
648
      }
649
      break;
12,576✔
650

651
   case JIT_EXIT_PUSH_SCOPE:
6,881✔
652
      {
653
         tree_t          where = args[0].pointer;
6,881✔
654
         int32_t         size  = args[1].integer;
6,881✔
655
         rt_scope_kind_t kind  = args[2].integer;
6,881✔
656

657
         x_push_scope(where, size, kind);
6,881✔
658
      }
659
      break;
6,881✔
660

661
   case JIT_EXIT_POP_SCOPE:
6,881✔
662
      x_pop_scope();
6,881✔
663
      break;
6,881✔
664

665
   case JIT_EXIT_FUNC_WAIT:
7✔
666
      x_func_wait();
7✔
667
      break;
7✔
668

669
   case JIT_EXIT_DIV_ZERO:
10✔
670
      {
671
         tree_t where = args[0].pointer;
10✔
672
         x_div_zero(where);
10✔
673
      }
674
      break;
10✔
675

676
   case JIT_EXIT_LENGTH_FAIL:
100✔
677
      {
678
         int32_t left  = args[0].integer;
100✔
679
         int32_t right = args[1].integer;
100✔
680
         int32_t dim   = args[2].integer;
100✔
681
         tree_t  where = args[3].pointer;
100✔
682

683
         x_length_fail(left, right, dim, where);
100✔
684
      }
685
      break;
100✔
686

687
   case JIT_EXIT_NULL_DEREF:
4✔
688
      {
689
         tree_t where = args[0].pointer;
4✔
690
         x_null_deref(where);
4✔
691
      }
692
      break;
4✔
693

694
   case JIT_EXIT_EXPONENT_FAIL:
412✔
695
      {
696
         int32_t value = args[0].integer;
412✔
697
         tree_t  where = args[1].pointer;
412✔
698

699
         x_exponent_fail(value, where);
412✔
700
      }
701
      break;
412✔
702

703
   case JIT_EXIT_FILE_OPEN:
1,566✔
704
      {
705
         int8_t   *status     = args[0].pointer;
1,566✔
706
         void    **_fp        = args[1].pointer;
1,566✔
707
         uint8_t  *name_bytes = args[2].pointer;
1,566✔
708
         int32_t   name_len   = args[3].integer;
1,566✔
709
         int32_t   mode       = args[4].integer;
1,566✔
710

711
         x_file_open(status, _fp, name_bytes, name_len, mode);
1,566✔
712
      }
713
      break;
1,566✔
714

715
   case JIT_EXIT_FILE_READ:
1,521✔
716
      {
717
         void    **_fp   = args[0].pointer;
1,521✔
718
         uint8_t  *data  = args[1].pointer;
1,521✔
719
         int64_t   size  = args[2].integer;
1,521✔
720
         int64_t   count = args[3].integer;
1,521✔
721

722
         args[0].integer = x_file_read(_fp, data, size, count);
1,521✔
723
      }
724
      break;
1,518✔
725

726
   case JIT_EXIT_FILE_WRITE:
8,392✔
727
      {
728
         void         **_fp    = args[0].pointer;
8,392✔
729
         jit_scalar_t   data   = { .integer = args[1].integer };
8,392✔
730
         size_t         size   = args[2].integer;
8,392✔
731
         size_t         count  = args[3].integer;
8,392✔
732
         bool           scalar = args[4].integer;
8,392✔
733

734
         if (scalar)
8,392✔
735
            x_file_write(_fp, &data.integer, size, count);
819✔
736
         else
737
            x_file_write(_fp, data.pointer, size, count);
7,573✔
738
      }
739
      break;
8,386✔
740

741
   case JIT_EXIT_DEBUG_OUT:
×
742
      {
743
         int64_t value = args[0].integer;
×
744
         debugf("DEBUG %"PRIi64, value);
×
745
      }
746
      break;
×
747

748
   case JIT_EXIT_LAST_EVENT:
23✔
749
      __nvc_last_event(anchor, args, tlab);
23✔
750
      break;
23✔
751

752
   case JIT_EXIT_LAST_ACTIVE:
36✔
753
      {
754
         sig_shared_t *shared = args[0].pointer;
36✔
755
         uint32_t      offset = args[1].integer;
36✔
756
         uint32_t      count  = args[2].integer;
36✔
757

758
         args[0].integer = x_last_active(shared, offset, count);
36✔
759
      }
760
      break;
36✔
761

762
   case JIT_EXIT_TEST_EVENT:
149✔
763
      __nvc_test_event(anchor, args, tlab);
149✔
764
      break;
149✔
765

766
   case JIT_EXIT_TEST_ACTIVE:
264✔
767
      {
768
         sig_shared_t *shared = args[0].pointer;
264✔
769
         int32_t       offset = args[1].integer;
264✔
770
         int32_t       count  = args[2].integer;
264✔
771

772
         args[0].integer = x_test_net_active(shared, offset, count);
264✔
773
      }
774
      break;
264✔
775

776
   case JIT_EXIT_DRIVING:
33✔
777
      {
778
         sig_shared_t *shared = args[0].pointer;
33✔
779
         int32_t       offset = args[1].integer;
33✔
780
         int32_t       count  = args[2].integer;
33✔
781

782
         args[0].integer = x_driving(shared, offset, count);
33✔
783
      }
784
      break;
30✔
785

786
   case JIT_EXIT_DRIVING_VALUE:
702✔
787
      {
788
         sig_shared_t *shared = args[0].pointer;
702✔
789
         int32_t       offset = args[1].integer;
702✔
790
         int32_t       count  = args[2].integer;
702✔
791

792
         args[0].pointer = x_driving_value(shared, offset, count);
702✔
793
      }
794
      break;
702✔
795

796
   case JIT_EXIT_COVER_TOGGLE:
625✔
797
      {
798
         sig_shared_t *shared = args[0].pointer;
625✔
799
         int32_t       tag    = args[1].integer;
625✔
800

801
         x_cover_setup_toggle_cb(shared, tag);
625✔
802
      }
803
      break;
625✔
804

805
   case JIT_EXIT_COVER_STATE:
24✔
806
      {
807
         sig_shared_t *shared = args[0].pointer;
24✔
808
         int64_t      low     = args[1].integer;
24✔
809
         int32_t      tag     = args[2].integer;
24✔
810

811
         x_cover_setup_state_cb(shared, low, tag);
24✔
812
      }
813
      break;
24✔
814

815
   case JIT_EXIT_PROCESS_INIT:
165✔
816
      {
817
         jit_handle_t handle = args[0].integer;
165✔
818
         tree_t       where  = args[1].pointer;
165✔
819

820
         x_process_init(handle, where);
165✔
821
      }
822
      break;
165✔
823

824
   case JIT_EXIT_CLEAR_EVENT:
35,422✔
825
      {
826
         sig_shared_t *shared = args[0].pointer;
35,422✔
827
         int32_t       offset = args[1].integer;
35,422✔
828
         int32_t       count  = args[2].integer;
35,422✔
829

830
         x_clear_event(shared, offset, count);
35,422✔
831
      }
832
      break;
35,422✔
833

834
   case JIT_EXIT_ENTER_STATE:
3,171✔
835
      {
836
         int32_t state  = args[0].integer;
3,171✔
837
         bool    strong = !!args[1].integer;
3,171✔
838

839
         x_enter_state(state, strong);
3,171✔
840
      }
841
      break;
3,171✔
842

843
   case JIT_EXIT_REFLECT_VALUE:
48✔
844
      {
845
         void         *context = args[0].pointer;
48✔
846
         jit_scalar_t  value   = args[1];
48✔
847
         tree_t        where   = args[2].pointer;
48✔
848

849
         args[0].pointer = x_reflect_value(context, value, where, args + 3);
48✔
850
      }
851
      break;
48✔
852

853
   case JIT_EXIT_REFLECT_SUBTYPE:
42✔
854
      {
855
         void   *context = args[0].pointer;
42✔
856
         tree_t  where   = args[1].pointer;
42✔
857

858
         args[0].pointer = x_reflect_subtype(context, where, args + 3);
42✔
859
      }
860
      break;
42✔
861

862
   case JIT_EXIT_FUNCTION_TRIGGER:
262✔
863
      {
864
         jit_handle_t handle = args[0].integer;
262✔
865
         unsigned     nargs  = args[1].integer;
262✔
866

867
         args[0].pointer = x_function_trigger(handle, nargs, args + 2);
262✔
868
      }
869
      break;
262✔
870

871
   case JIT_EXIT_OR_TRIGGER:
33✔
872
      {
873
         void *left  = args[0].pointer;
33✔
874
         void *right = args[1].pointer;
33✔
875

876
         args[0].pointer = x_or_trigger(left, right);
33✔
877
      }
878
      break;
33✔
879

880
   case JIT_EXIT_CMP_TRIGGER:
45✔
881
      {
882
         sig_shared_t *shared = args[0].pointer;
45✔
883
         int32_t       offset = args[1].integer;
45✔
884
         int64_t       right  = args[2].integer;
45✔
885

886
         args[0].pointer = x_cmp_trigger(shared, offset, right);
45✔
887
      }
888
      break;
45✔
889

890
   case JIT_EXIT_ADD_TRIGGER:
362✔
891
      {
892
         void *trigger = args[0].pointer;
362✔
893

894
         if (trigger != NULL)
362✔
895
            x_add_trigger(trigger);
362✔
896
      }
897
      break;
898

899
   case JIT_EXIT_PORT_CONVERSION:
378✔
900
      {
901
         jit_handle_t  handle1  = args[0].integer;
378✔
902
         void         *context1 = args[1].pointer;
378✔
903
         jit_handle_t  handle2  = args[2].integer;
378✔
904
         void         *context2 = args[3].pointer;
378✔
905

906
         ffi_closure_t driving = { handle1, context1 };
378✔
907
         ffi_closure_t effective = { handle2, context2 };
378✔
908
         args[0].pointer = x_port_conversion(&driving, &effective);
378✔
909
      }
910
      break;
378✔
911

912
   case JIT_EXIT_CONVERT_IN:
770✔
913
      {
914
         void         *conv   = args[0].pointer;
770✔
915
         sig_shared_t *shared = args[1].pointer;
770✔
916
         int32_t       offset = args[2].integer;
770✔
917
         int32_t       count  = args[3].integer;
770✔
918

919
         if (conv != NULL)
770✔
920
            x_convert_in(conv, shared, offset, count);
770✔
921
      }
922
      break;
923

924
   case JIT_EXIT_CONVERT_OUT:
958✔
925
      {
926
         void         *conv   = args[0].pointer;
958✔
927
         sig_shared_t *shared = args[1].pointer;
958✔
928
         int32_t       offset = args[2].integer;
958✔
929
         int32_t       count  = args[3].integer;
958✔
930

931
         if (conv != NULL)
958✔
932
            x_convert_out(conv, shared, offset, count);
958✔
933
      }
934
      break;
935

936
   case JIT_EXIT_BIND_FOREIGN:
1,019✔
937
      {
938
         const uint8_t *spec   = args[0].pointer;
1,019✔
939
         size_t         length = args[1].integer;
1,019✔
940
         tree_t         where  = args[2].pointer;
1,019✔
941

942
         jit_bind_foreign(anchor->func, spec, length, where);
1,019✔
943
      }
944
      break;
1,019✔
945

946
   case JIT_EXIT_INSTANCE_NAME:
1,312✔
947
      {
948
         const attr_kind_t kind = args[0].integer;
1,312✔
949

950
         LOCAL_TEXT_BUF tb = tb_new();
2,624✔
951
         x_instance_name(kind, tb);
1,312✔
952
         ffi_return_string(tb_get(tb), args, tlab);
1,312✔
953
      }
954
      break;
1,312✔
955

956
   case JIT_EXIT_BIND_EXTERNAL:
166✔
957
      {
958
         tree_t       where = args[0].pointer;
166✔
959
         jit_handle_t scope = args[1].integer;
166✔
960

961
         x_bind_external(where, scope, args);
166✔
962
      }
963
      break;
166✔
964

965
   case JIT_EXIT_SYSCALL:
243✔
966
      {
967
         vlog_node_t where = args[0].pointer;
243✔
968
         jit_do_syscall(where, anchor, args, tlab);
243✔
969
      }
970
      break;
243✔
971

972
   default:
×
973
      fatal_trace("unhandled exit %s", jit_exit_name(which));
974
   }
975

976
   thread->anchor = NULL;
1,539,440✔
977
}
1,539,440✔
978

979
////////////////////////////////////////////////////////////////////////////////
980
// Entry points from AOT compiled code
981

982
DLLEXPORT
983
void _debug_out(intptr_t val, int32_t reg)
×
984
{
985
   printf("DEBUG: r%d val=%"PRIxPTR"\n", reg, val);
×
986
   fflush(stdout);
×
987
}
×
988

989
DLLEXPORT
990
void _debug_dump(const uint8_t *ptr, int32_t len)
×
991
{
992
   printf("---- %p ----\n", ptr);
×
993

994
   if (ptr != NULL) {
×
995
      for (int i = 0; i < len; i++)
×
996
         printf("%02x%c", ptr[i], (i % 8 == 7) ? '\n' : ' ');
×
997
      if (len % 8 != 0)
×
998
         printf("\n");
×
999
   }
1000

1001
   fflush(stdout);
×
1002
}
×
1003

1004
DLLEXPORT
1005
void *__nvc_mspace_alloc(uintptr_t size, jit_anchor_t *anchor)
39,565,436✔
1006
{
1007
   jit_thread_local_t *thread = jit_attach_thread(anchor);
39,565,436✔
1008

1009
   if (unlikely(size > UINT32_MAX)) {
39,565,436✔
1010
      jit_msg(NULL, DIAG_FATAL, "attempting to allocate %zu byte object "
2✔
1011
              "which is larger than the maximum supported %u bytes",
1012
              size, UINT32_MAX);
1013
      __builtin_unreachable();
×
1014
   }
1015
   else if (size == 0)
39,565,434✔
1016
      size = 1;   // Never return a NULL pointer
1017

1018
   void *ptr = jit_mspace_alloc(size);
39,565,434✔
1019

1020
   thread->anchor = NULL;
39,565,432✔
1021
   return ptr;
39,565,432✔
1022
}
1023

1024
DLLEXPORT
UNCOV
1025
void __nvc_putpriv(jit_handle_t handle, void *data)
×
1026
{
UNCOV
1027
   jit_t *j = jit_for_thread();
×
UNCOV
1028
   jit_func_t *f = jit_get_func(j, handle);
×
1029

UNCOV
1030
   store_release(jit_get_privdata_ptr(j, f), data);
×
UNCOV
1031
}
×
1032

1033
DLLEXPORT
1034
object_t *__nvc_get_object(const char *unit, ptrdiff_t offset)
28,602✔
1035
{
1036
   return object_from_locus(ident_new(unit), offset, lib_load_handler);
28,602✔
1037
}
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