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

nickg / nvc / 13775379932

10 Mar 2025 09:11PM UTC coverage: 92.318% (-0.001%) from 92.319%
13775379932

push

github

nickg
Fix crash when nvc -i called with no arguments

4 of 6 new or added lines in 1 file covered. (66.67%)

34 existing lines in 2 files now uncovered.

68075 of 73740 relevant lines covered (92.32%)

432883.26 hits per line

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

96.16
/src/jit/jit-llvm.c
1
//
2
//  Copyright (C) 2022-2023  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 "hash.h"
21
#include "ident.h"
22
#include "jit/jit-llvm.h"
23
#include "jit/jit-priv.h"
24
#include "lib.h"
25
#include "object.h"
26
#include "option.h"
27
#include "rt/rt.h"
28
#include "thread.h"
29

30
#include <assert.h>
31
#include <libgen.h>
32
#include <stdlib.h>
33
#include <limits.h>
34
#include <string.h>
35
#include <stdint.h>
36

37
#include <llvm-c/Analysis.h>
38
#include <llvm-c/Core.h>
39
#include <llvm-c/DebugInfo.h>
40
#include <llvm-c/Error.h>
41
#include <llvm-c/TargetMachine.h>
42

43
#if LLVM_HAS_PASS_BUILDER
44
#include <llvm-c/Transforms/PassBuilder.h>
45
#else
46
#include <llvm-c/Transforms/Scalar.h>
47
#include <llvm-c/Transforms/PassManagerBuilder.h>
48
#endif
49

50
typedef enum {
51
   LLVM_VOID,
52
   LLVM_PTR,
53
   LLVM_INT1,
54
   LLVM_INT8,
55
   LLVM_INT16,
56
   LLVM_INT32,
57
   LLVM_INT64,
58
   LLVM_INTPTR,
59
   LLVM_DOUBLE,
60

61
   LLVM_PAIR_I8_I1,
62
   LLVM_PAIR_I16_I1,
63
   LLVM_PAIR_I32_I1,
64
   LLVM_PAIR_I64_I1,
65

66
   LLVM_ENTRY_FN,
67
   LLVM_ANCHOR,
68
   LLVM_TLAB,
69
   LLVM_AOT_RELOC,
70
   LLVM_STRTAB,
71

72
   LLVM_LAST_TYPE
73
} llvm_type_t;
74

75
typedef enum {
76
   LLVM_ADD_OVERFLOW_S8,
77
   LLVM_ADD_OVERFLOW_S16,
78
   LLVM_ADD_OVERFLOW_S32,
79
   LLVM_ADD_OVERFLOW_S64,
80

81
   LLVM_ADD_OVERFLOW_U8,
82
   LLVM_ADD_OVERFLOW_U16,
83
   LLVM_ADD_OVERFLOW_U32,
84
   LLVM_ADD_OVERFLOW_U64,
85

86
   LLVM_SUB_OVERFLOW_S8,
87
   LLVM_SUB_OVERFLOW_S16,
88
   LLVM_SUB_OVERFLOW_S32,
89
   LLVM_SUB_OVERFLOW_S64,
90

91
   LLVM_SUB_OVERFLOW_U8,
92
   LLVM_SUB_OVERFLOW_U16,
93
   LLVM_SUB_OVERFLOW_U32,
94
   LLVM_SUB_OVERFLOW_U64,
95

96
   LLVM_MUL_OVERFLOW_S8,
97
   LLVM_MUL_OVERFLOW_S16,
98
   LLVM_MUL_OVERFLOW_S32,
99
   LLVM_MUL_OVERFLOW_S64,
100

101
   LLVM_MUL_OVERFLOW_U8,
102
   LLVM_MUL_OVERFLOW_U16,
103
   LLVM_MUL_OVERFLOW_U32,
104
   LLVM_MUL_OVERFLOW_U64,
105

106
   LLVM_EXP_OVERFLOW_S8,
107
   LLVM_EXP_OVERFLOW_S16,
108
   LLVM_EXP_OVERFLOW_S32,
109
   LLVM_EXP_OVERFLOW_S64,
110

111
   LLVM_EXP_OVERFLOW_U8,
112
   LLVM_EXP_OVERFLOW_U16,
113
   LLVM_EXP_OVERFLOW_U32,
114
   LLVM_EXP_OVERFLOW_U64,
115

116
   LLVM_ADD_SAT_U8,
117
   LLVM_ADD_SAT_U16,
118
   LLVM_ADD_SAT_U32,
119
   LLVM_ADD_SAT_U64,
120

121
   LLVM_MEMSET_U8,
122
   LLVM_MEMSET_U16,
123
   LLVM_MEMSET_U32,
124
   LLVM_MEMSET_U64,
125

126
   LLVM_POW_F64,
127
   LLVM_COPYSIGN_F64,
128
   LLVM_MEMSET_INLINE,
129
   LLVM_MEMCPY_INLINE,
130

131
   LLVM_DO_EXIT,
132
   LLVM_PUTPRIV,
133
   LLVM_MSPACE_ALLOC,
134
   LLVM_GET_OBJECT,
135
   LLVM_TLAB_ALLOC,
136
   LLVM_SCHED_WAVEFORM,
137
   LLVM_TEST_EVENT,
138
   LLVM_LAST_EVENT,
139
   LLVM_SCHED_PROCESS,
140

141
   LLVM_LAST_FN,
142
} llvm_fn_t;
143

144
typedef struct _cgen_func  cgen_func_t;
145
typedef struct _cgen_block cgen_block_t;
146

147
#define DEBUG_METADATA_VERSION 3
148
#define CLOSED_WORLD           1
149
#define ARGCACHE_SIZE          6
150
#define ENABLE_DWARF           0
151

152
#if defined __APPLE__ && defined ARCH_ARM64
153
#define JIT_CODE_MODEL LLVMCodeModelDefault
154
#else
155
#define JIT_CODE_MODEL LLVMCodeModelJITDefault
156
#endif
157

158
#if ENABLE_DWARF
159
#define DWARF_ONLY(x) x
160
#else
161
#define DWARF_ONLY(x)
162
#endif
163

164
typedef struct _llvm_obj {
165
   LLVMModuleRef         module;
166
   LLVMContextRef        context;
167
   LLVMTargetMachineRef  target;
168
   LLVMBuilderRef        builder;
169
#if ENABLE_DWARF
170
   LLVMDIBuilderRef      debuginfo;
171
   LLVMMetadataRef       debugcu;
172
#endif
173
   LLVMTargetDataRef     data_ref;
174
   LLVMTypeRef           types[LLVM_LAST_TYPE];
175
   LLVMValueRef          fns[LLVM_LAST_FN];
176
   LLVMTypeRef           fntypes[LLVM_LAST_FN];
177
   LLVMValueRef          strtab;
178
   pack_writer_t        *pack_writer;
179
} llvm_obj_t;
180

181
typedef struct _cgen_block {
182
   LLVMBasicBlockRef  bbref;
183
   LLVMValueRef       inflags;
184
   LLVMValueRef       outflags;
185
   LLVMValueRef      *inregs;
186
   LLVMValueRef      *outregs;
187
   jit_block_t       *source;
188
   cgen_func_t       *func;
189
} cgen_block_t;
190

191
typedef enum { CGEN_JIT, CGEN_AOT } cgen_mode_t;
192

193
typedef struct {
194
   reloc_kind_t kind;
195
   unsigned     nth;
196
   LLVMValueRef str;
197
   uintptr_t    key;
198
} cgen_reloc_t;
199

200
typedef struct _cgen_func {
201
   LLVMValueRef     llvmfn;
202
   LLVMValueRef     args;
203
   LLVMValueRef     argcache[ARGCACHE_SIZE];
204
   LLVMValueRef     irpos;
205
   LLVMValueRef     tlab;
206
   LLVMValueRef     anchor;
207
   LLVMValueRef     cpool;
208
   LLVMTypeRef      cpool_type;
209
   LLVMValueRef     descr;
210
   LLVMTypeRef      descr_type;
211
   LLVMTypeRef      reloc_type;
212
   LLVMMetadataRef  debugmd;
213
   cgen_block_t    *blocks;
214
   jit_func_t      *source;
215
   jit_cfg_t       *cfg;
216
   char            *name;
217
   loc_t            last_loc;
218
   bit_mask_t       ptr_mask;
219
   cgen_mode_t      mode;
220
   cgen_reloc_t    *relocs;
221
} cgen_func_t;
222

223
typedef enum {
224
   FUNC_ATTR_NOUNWIND,
225
   FUNC_ATTR_NORETURN,
226
   FUNC_ATTR_READONLY,
227
   FUNC_ATTR_NOCAPTURE,
228
   FUNC_ATTR_BYVAL,
229
   FUNC_ATTR_UWTABLE,
230
   FUNC_ATTR_NOINLINE,
231
   FUNC_ATTR_WRITEONLY,
232
   FUNC_ATTR_NONNULL,
233
   FUNC_ATTR_COLD,
234
   FUNC_ATTR_OPTNONE,
235
   FUNC_ATTR_NOALIAS,
236
   FUNC_ATTR_INLINE,
237

238
   // Attributes requiring special handling
239
   FUNC_ATTR_PRESERVE_FP,
240
   FUNC_ATTR_DLLEXPORT,
241
} func_attr_t;
242

243
#define LLVM_CHECK(op, ...) do {                        \
244
      LLVMErrorRef error = op(__VA_ARGS__);             \
245
      if (unlikely(error != LLVMErrorSuccess)) {        \
246
         char *msg = LLVMGetErrorMessage(error);        \
247
         fatal(#op " failed: %s", msg);                 \
248
      }                                                 \
249
   } while (0)
250

251
#ifdef LLVM_HAS_OPAQUE_POINTERS
252
#define PTR(x) x
253
#else
254
#define PTR(x) \
255
   LLVMBuildPointerCast(obj->builder, (x), obj->types[LLVM_PTR], "")
256
#endif
257

258
////////////////////////////////////////////////////////////////////////////////
259
// LLVM wrappers
260

261
static LLVMValueRef llvm_int1(llvm_obj_t *obj, bool b)
22,277✔
262
{
263
   return LLVMConstInt(obj->types[LLVM_INT1], b, false);
22,277✔
264
}
265

266
static LLVMValueRef llvm_int8(llvm_obj_t *obj, int8_t i)
6,091,933✔
267
{
268
   return LLVMConstInt(obj->types[LLVM_INT8], i, false);
6,091,933✔
269
}
270

271
static LLVMValueRef llvm_int32(llvm_obj_t *obj, int32_t i)
558,767✔
272
{
273
   return LLVMConstInt(obj->types[LLVM_INT32], i, false);
558,767✔
274
}
275

276
static LLVMValueRef llvm_int64(llvm_obj_t *obj, int64_t i)
552,407✔
277
{
278
   return LLVMConstInt(obj->types[LLVM_INT64], i, false);
552,407✔
279
}
280

281
static LLVMValueRef llvm_intptr(llvm_obj_t *obj, intptr_t i)
443,712✔
282
{
283
   return LLVMConstInt(obj->types[LLVM_INTPTR], i, false);
443,712✔
284
}
285

286
static LLVMValueRef llvm_ptr(llvm_obj_t *obj, void *ptr)
59,944✔
287
{
288
   return LLVMConstIntToPtr(llvm_intptr(obj, (intptr_t)ptr),
59,944✔
289
                            obj->types[LLVM_PTR]);
290
}
291

292
static LLVMValueRef llvm_real(llvm_obj_t *obj, double r)
5,861✔
293
{
294
   return LLVMConstReal(obj->types[LLVM_DOUBLE], r);
5,861✔
295
}
296

297
static void llvm_add_func_attr(llvm_obj_t *obj, LLVMValueRef fn,
273,590✔
298
                               func_attr_t attr, int param)
299
{
300
   LLVMAttributeRef ref;
273,590✔
301
   if (attr == FUNC_ATTR_DLLEXPORT) {
273,590✔
302
#ifdef IMPLIB_REQUIRED
303
      LLVMSetDLLStorageClass(fn, LLVMDLLExportStorageClass);
304
#endif
305
      return;
306
   }
307
   else if (attr == FUNC_ATTR_PRESERVE_FP) {
251,377✔
308
      ref = LLVMCreateStringAttribute(obj->context, "frame-pointer",
×
309
                                      13, "all", 3);
310
   }
311
   else {
312
      const char *names[] = {
251,377✔
313
         "nounwind", "noreturn", "readonly", "nocapture", "byval",
314
         "uwtable", "noinline", "writeonly", "nonnull", "cold", "optnone",
315
         "noalias", "inlinehint",
316
      };
317
      assert(attr < ARRAY_LEN(names));
251,377✔
318

319
      const unsigned kind =
251,377✔
320
         LLVMGetEnumAttributeKindForName(names[attr], strlen(names[attr]));
251,377✔
321
      if (kind == 0)
251,377✔
322
         fatal_trace("Cannot get LLVM attribute for %s", names[attr]);
323

324
#ifdef LLVM_UWTABLE_HAS_ARGUMENT
325
      if (attr == FUNC_ATTR_UWTABLE)
326
         ref = LLVMCreateEnumAttribute(obj->context, kind, 2);
327
      else
328
#endif
329
         ref = LLVMCreateEnumAttribute(obj->context, kind, 0);
251,377✔
330
   }
331

332
   LLVMAddAttributeAtIndex(fn, param, ref);
251,377✔
333
}
334

335
static void llvm_register_types(llvm_obj_t *obj)
9,132✔
336
{
337
   obj->types[LLVM_VOID]   = LLVMVoidTypeInContext(obj->context);
9,132✔
338
   obj->types[LLVM_INT1]   = LLVMInt1TypeInContext(obj->context);
9,132✔
339
   obj->types[LLVM_INT8]   = LLVMInt8TypeInContext(obj->context);
9,132✔
340
   obj->types[LLVM_INT16]  = LLVMInt16TypeInContext(obj->context);
9,132✔
341
   obj->types[LLVM_INT32]  = LLVMInt32TypeInContext(obj->context);
9,132✔
342
   obj->types[LLVM_INT64]  = LLVMInt64TypeInContext(obj->context);
9,132✔
343
   obj->types[LLVM_DOUBLE] = LLVMDoubleTypeInContext(obj->context);
9,132✔
344

345
   obj->types[LLVM_INTPTR] = LLVMIntPtrTypeInContext(obj->context,
9,132✔
346
                                                     obj->data_ref);
347

348
#ifdef LLVM_HAS_OPAQUE_POINTERS
349
   obj->types[LLVM_PTR] = LLVMPointerTypeInContext(obj->context, 0);
350
#else
351
   obj->types[LLVM_PTR] = LLVMPointerType(obj->types[LLVM_INT8], 0);
9,132✔
352
#endif
353

354
   obj->types[LLVM_STRTAB] = LLVMArrayType(obj->types[LLVM_INT8], 0);
9,132✔
355

356
   {
357
      LLVMTypeRef fields[] = {
9,132✔
358
         obj->types[LLVM_PTR],                     // Mspace object
9,132✔
359
         obj->types[LLVM_INT32],                   // Allocation pointer
9,132✔
360
         obj->types[LLVM_INT32],                   // Limit pointer
361
         LLVMArrayType(obj->types[LLVM_INT8], 0),  // Data
9,132✔
362
      };
363
      obj->types[LLVM_TLAB] = LLVMStructTypeInContext(obj->context, fields,
9,132✔
364
                                                      ARRAY_LEN(fields), false);
365
   }
366

367
   {
368
      LLVMTypeRef atypes[] = {
9,132✔
369
         obj->types[LLVM_PTR],    // Function
9,132✔
370
         obj->types[LLVM_PTR],    // Anchor
371
#ifdef LLVM_HAS_OPAQUE_POINTERS
372
         obj->types[LLVM_PTR],    // Arguments
373
#else
374
         LLVMPointerType(obj->types[LLVM_INT64], 0),
9,132✔
375
#endif
376
#ifdef LLVM_HAS_OPAQUE_POINTERS
377
         obj->types[LLVM_PTR]     // TLAB pointer
378
#else
379
         LLVMPointerType(obj->types[LLVM_TLAB], 0)
9,132✔
380
#endif
381
      };
382
      obj->types[LLVM_ENTRY_FN] = LLVMFunctionType(obj->types[LLVM_VOID],
9,132✔
383
                                                   atypes, ARRAY_LEN(atypes),
384
                                                   false);
385
   }
386

387
   {
388
      LLVMTypeRef fields[] = {
9,132✔
389
         obj->types[LLVM_INT32],   // Kind
9,132✔
390
         obj->types[LLVM_INTPTR],  // Data pointer
9,132✔
391
      };
392
      obj->types[LLVM_AOT_RELOC] = LLVMStructTypeInContext(obj->context, fields,
9,132✔
393
                                                           ARRAY_LEN(fields),
394
                                                           false);
395
   }
396

397
   {
398
      LLVMTypeRef fields[] = {
9,132✔
399
         obj->types[LLVM_PTR],    // Caller
9,132✔
400
         obj->types[LLVM_PTR],    // Function
401
         obj->types[LLVM_INT32],  // IR position
9,132✔
402
         obj->types[LLVM_INT32]   // TLAB watermark
403
      };
404
      obj->types[LLVM_ANCHOR] = LLVMStructTypeInContext(obj->context, fields,
9,132✔
405
                                                        ARRAY_LEN(fields),
406
                                                        false);
407
   }
408

409
   for (jit_size_t sz = JIT_SZ_8; sz <= JIT_SZ_64; sz++) {
45,660✔
410
      LLVMTypeRef fields[] = {
36,528✔
411
         obj->types[LLVM_INT8 + sz],
36,528✔
412
         obj->types[LLVM_INT1]
36,528✔
413
      };
414
      llvm_fn_t which = LLVM_PAIR_I8_I1 + sz;
36,528✔
415
      obj->types[which] = LLVMStructTypeInContext(obj->context, fields,
36,528✔
416
                                                  ARRAY_LEN(fields), false);
417
   }
418
}
9,132✔
419

420
static void llvm_dump_module(LLVMModuleRef module, const char *tag)
18,264✔
421
{
422
   size_t length;
18,264✔
423
   const char *module_name = LLVMGetModuleIdentifier(module, &length);
18,264✔
424

425
   if (!opt_get_verbose(OPT_LLVM_VERBOSE, module_name))
18,264✔
426
      return;
18,264✔
427

428
   LOCAL_TEXT_BUF tb = tb_new();
×
429
   tb_printf(tb, "%s.%s.ll", module_name, tag);
×
430

431
   char *error;
×
432
   if (LLVMPrintModuleToFile(module, tb_get(tb), &error))
×
433
      fatal("Failed to write LLVM IR file: %s", error);
×
434

435
   debugf("wrote LLVM IR for %s to %s", module_name, tb_get(tb));
×
436
}
437

438
static void llvm_verify_module(LLVMModuleRef module)
9,132✔
439
{
440
#ifdef DEBUG
441
   if (LLVMVerifyModule(module, LLVMPrintMessageAction, NULL)) {
9,132✔
442
      size_t len;
×
443
      const char *name = LLVMGetModuleIdentifier(module, &len);
×
444
      fatal("LLVM verification failed for %s", name);
×
445
   }
446
#endif
447
}
9,132✔
448

449
static void llvm_optimise(LLVMModuleRef module, LLVMTargetMachineRef target,
9,132✔
450
                          llvm_opt_level_t olevel)
451
{
452
   assert(olevel >= LLVM_O0 && olevel <= LLVM_O3);
9,132✔
453

454
#if LLVM_HAS_PASS_BUILDER
455
   LLVMPassBuilderOptionsRef options = LLVMCreatePassBuilderOptions();
9,132✔
456
   LLVMPassBuilderOptionsSetDebugLogging(options, false);
9,132✔
457
   LLVMPassBuilderOptionsSetLoopVectorization(options, false);
9,132✔
458
   LLVMPassBuilderOptionsSetLoopInterleaving(options, false);
9,132✔
459
   LLVMPassBuilderOptionsSetSLPVectorization(options, false);
9,132✔
460
   LLVMPassBuilderOptionsSetLoopUnrolling(options, false);
9,132✔
461
   LLVMPassBuilderOptionsSetCallGraphProfile(options, false);
9,132✔
462

463
   const char *passes[] = {
9,132✔
464
      "default<O0>", "default<O1>", "default<O2>", "default<O3>"
465
   };
466

467
   LLVM_CHECK(LLVMRunPasses, module, passes[olevel], target, options);
9,132✔
468

469
   LLVMDisposePassBuilderOptions(options);
9,132✔
470
#else
471
   LLVMPassManagerRef fpm = LLVMCreateFunctionPassManagerForModule(module);
472
   LLVMPassManagerRef mpm = LLVMCreatePassManager();
473

474
   LLVMInitializeFunctionPassManager(fpm);
475

476
   for (LLVMValueRef fn = LLVMGetFirstFunction(module);
477
        fn != NULL; fn = LLVMGetNextFunction(fn))
478
      LLVMRunFunctionPassManager(fpm, fn);
479

480
   LLVMFinalizeFunctionPassManager(fpm);
481
   LLVMDisposePassManager(fpm);
482

483
   LLVMPassManagerBuilderRef builder = LLVMPassManagerBuilderCreate();
484
   LLVMPassManagerBuilderSetOptLevel(builder, olevel);
485
   LLVMPassManagerBuilderSetSizeLevel(builder, 0);
486

487
   if (olevel >= 2)
488
      LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 50);
489

490
   LLVMPassManagerBuilderPopulateModulePassManager(builder, mpm);
491
   LLVMPassManagerBuilderDispose(builder);
492

493
   LLVMRunPassManager(mpm, module);
494
   LLVMDisposePassManager(mpm);
495
#endif
496
}
9,132✔
497

498
static LLVMTargetMachineRef llvm_target_machine(LLVMRelocMode reloc,
9,132✔
499
                                                LLVMCodeModel model)
500
{
501
   char *def_triple = LLVMGetDefaultTargetTriple();
9,132✔
502
   char *error;
9,132✔
503
   LLVMTargetRef target_ref;
9,132✔
504
   if (LLVMGetTargetFromTriple(def_triple, &target_ref, &error))
9,132✔
505
      fatal("failed to get LLVM target for %s: %s", def_triple, error);
×
506

507
   LLVMTargetMachineRef tm = LLVMCreateTargetMachine(target_ref, def_triple,
9,132✔
508
                                                     "", "",
509
                                                     LLVMCodeGenLevelDefault,
510
                                                     reloc, model);
511
   LLVMDisposeMessage(def_triple);
9,132✔
512

513
   return tm;
9,132✔
514
}
515

516
static LLVMBasicBlockRef llvm_append_block(llvm_obj_t *obj, LLVMValueRef fn,
259,311✔
517
                                           const char *name)
518
{
519
   return LLVMAppendBasicBlockInContext(obj->context, fn, name);
259,311✔
520
}
521

522
static LLVMValueRef llvm_add_fn(llvm_obj_t *obj, const char *name,
66,530✔
523
                                LLVMTypeRef type)
524
{
525
   LLVMValueRef fn = LLVMGetNamedFunction(obj->module, name);
66,530✔
526
   if (fn == NULL)
66,530✔
527
      fn = LLVMAddFunction(obj->module, name, type);
51,580✔
528

529
   return fn;
66,530✔
530
}
531

532
static LLVMValueRef llvm_get_fn(llvm_obj_t *obj, llvm_fn_t which)
163,614✔
533
{
534
   if (obj->fns[which] != NULL)
163,614✔
535
      return obj->fns[which];
536

537
   LLVMValueRef fn = NULL;
29,225✔
538
   switch (which) {
29,225✔
539
   case LLVM_ADD_OVERFLOW_S8:
461✔
540
   case LLVM_ADD_OVERFLOW_S16:
541
   case LLVM_ADD_OVERFLOW_S32:
542
   case LLVM_ADD_OVERFLOW_S64:
543
      {
544
         jit_size_t sz = which - LLVM_ADD_OVERFLOW_S8;
461✔
545
         LLVMTypeRef int_type = obj->types[LLVM_INT8 + sz];
461✔
546
         LLVMTypeRef pair_type = obj->types[LLVM_PAIR_I8_I1 + sz];
461✔
547
         LLVMTypeRef args[] = { int_type, int_type };
461✔
548
         obj->fntypes[which] = LLVMFunctionType(pair_type, args,
461✔
549
                                                ARRAY_LEN(args), false);
550

551
         static const char *names[] = {
461✔
552
            "llvm.sadd.with.overflow.i8",
553
            "llvm.sadd.with.overflow.i16",
554
            "llvm.sadd.with.overflow.i32",
555
            "llvm.sadd.with.overflow.i64"
556
         };
557
         fn = llvm_add_fn(obj, names[sz], obj->fntypes[which]);
461✔
558
      }
559
      break;
461✔
560

561
   case LLVM_ADD_OVERFLOW_U8:
3✔
562
   case LLVM_ADD_OVERFLOW_U16:
563
   case LLVM_ADD_OVERFLOW_U32:
564
   case LLVM_ADD_OVERFLOW_U64:
565
      {
566
         jit_size_t sz = which - LLVM_ADD_OVERFLOW_U8;
3✔
567
         LLVMTypeRef int_type = obj->types[LLVM_INT8 + sz];
3✔
568
         LLVMTypeRef pair_type = obj->types[LLVM_PAIR_I8_I1 + sz];
3✔
569
         LLVMTypeRef args[] = { int_type, int_type };
3✔
570
         obj->fntypes[which] = LLVMFunctionType(pair_type, args,
3✔
571
                                                ARRAY_LEN(args), false);
572

573
         static const char *names[] = {
3✔
574
            "llvm.uadd.with.overflow.i8",
575
            "llvm.uadd.with.overflow.i16",
576
            "llvm.uadd.with.overflow.i32",
577
            "llvm.uadd.with.overflow.i64"
578
         };
579
         fn = llvm_add_fn(obj, names[sz], obj->fntypes[which]);
3✔
580
      }
581
      break;
3✔
582

583
   case LLVM_SUB_OVERFLOW_S8:
121✔
584
   case LLVM_SUB_OVERFLOW_S16:
585
   case LLVM_SUB_OVERFLOW_S32:
586
   case LLVM_SUB_OVERFLOW_S64:
587
      {
588
         jit_size_t sz = which - LLVM_SUB_OVERFLOW_S8;
121✔
589
         LLVMTypeRef int_type = obj->types[LLVM_INT8 + sz];
121✔
590
         LLVMTypeRef pair_type = obj->types[LLVM_PAIR_I8_I1 + sz];
121✔
591
         LLVMTypeRef args[] = { int_type, int_type };
121✔
592
         obj->fntypes[which] = LLVMFunctionType(pair_type, args,
121✔
593
                                                ARRAY_LEN(args), false);
594

595
         static const char *names[] = {
121✔
596
            "llvm.ssub.with.overflow.i8",
597
            "llvm.ssub.with.overflow.i16",
598
            "llvm.ssub.with.overflow.i32",
599
            "llvm.ssub.with.overflow.i64"
600
         };
601
         fn = llvm_add_fn(obj, names[sz], obj->fntypes[which]);
121✔
602
      }
603
      break;
121✔
604

605
   case LLVM_SUB_OVERFLOW_U8:
×
606
   case LLVM_SUB_OVERFLOW_U16:
607
   case LLVM_SUB_OVERFLOW_U32:
608
   case LLVM_SUB_OVERFLOW_U64:
609
      {
610
         jit_size_t sz = which - LLVM_SUB_OVERFLOW_U8;
×
611
         LLVMTypeRef int_type = obj->types[LLVM_INT8 + sz];
×
612
         LLVMTypeRef pair_type = obj->types[LLVM_PAIR_I8_I1 + sz];
×
613
         LLVMTypeRef args[] = { int_type, int_type };
×
614
         obj->fntypes[which] = LLVMFunctionType(pair_type, args,
×
615
                                                ARRAY_LEN(args), false);
616

617
         static const char *names[] = {
×
618
            "llvm.usub.with.overflow.i8",
619
            "llvm.usub.with.overflow.i16",
620
            "llvm.usub.with.overflow.i32",
621
            "llvm.usub.with.overflow.i64"
622
         };
623
         fn = llvm_add_fn(obj, names[sz], obj->fntypes[which]);
×
624
      }
625
      break;
×
626

627
   case LLVM_MUL_OVERFLOW_S8:
109✔
628
   case LLVM_MUL_OVERFLOW_S16:
629
   case LLVM_MUL_OVERFLOW_S32:
630
   case LLVM_MUL_OVERFLOW_S64:
631
      {
632
         jit_size_t sz = which - LLVM_MUL_OVERFLOW_S8;
109✔
633
         LLVMTypeRef int_type = obj->types[LLVM_INT8 + sz];
109✔
634
         LLVMTypeRef pair_type = obj->types[LLVM_PAIR_I8_I1 + sz];
109✔
635
         LLVMTypeRef args[] = { int_type, int_type };
109✔
636
         obj->fntypes[which] = LLVMFunctionType(pair_type, args,
109✔
637
                                                ARRAY_LEN(args), false);
638

639
         static const char *names[] = {
109✔
640
            "llvm.smul.with.overflow.i8",
641
            "llvm.smul.with.overflow.i16",
642
            "llvm.smul.with.overflow.i32",
643
            "llvm.smul.with.overflow.i64"
644
         };
645
         fn = llvm_add_fn(obj, names[sz], obj->fntypes[which]);
109✔
646
      }
647
      break;
109✔
648

649
   case LLVM_MUL_OVERFLOW_U8:
5✔
650
   case LLVM_MUL_OVERFLOW_U16:
651
   case LLVM_MUL_OVERFLOW_U32:
652
   case LLVM_MUL_OVERFLOW_U64:
653
      {
654
         jit_size_t sz = which - LLVM_MUL_OVERFLOW_U8;
5✔
655
         LLVMTypeRef int_type = obj->types[LLVM_INT8 + sz];
5✔
656
         LLVMTypeRef pair_type = obj->types[LLVM_PAIR_I8_I1 + sz];
5✔
657
         LLVMTypeRef args[] = { int_type, int_type };
5✔
658
         obj->fntypes[which] = LLVMFunctionType(pair_type, args,
5✔
659
                                                ARRAY_LEN(args), false);
660

661
         static const char *names[] = {
5✔
662
            "llvm.umul.with.overflow.i8",
663
            "llvm.umul.with.overflow.i16",
664
            "llvm.umul.with.overflow.i32",
665
            "llvm.umul.with.overflow.i64"
666
         };
667
         fn = llvm_add_fn(obj, names[sz], obj->fntypes[which]);
5✔
668
      }
669
      break;
5✔
670

671
   case LLVM_EXP_OVERFLOW_S8:
30✔
672
   case LLVM_EXP_OVERFLOW_S16:
673
   case LLVM_EXP_OVERFLOW_S32:
674
   case LLVM_EXP_OVERFLOW_S64:
675
      {
676
         jit_size_t sz = which - LLVM_EXP_OVERFLOW_S8;
30✔
677
         LLVMTypeRef int_type = obj->types[LLVM_INT8 + sz];
30✔
678
         LLVMTypeRef pair_type = obj->types[LLVM_PAIR_I8_I1 + sz];
30✔
679
         LLVMTypeRef args[] = { int_type, int_type };
30✔
680
         obj->fntypes[which] = LLVMFunctionType(pair_type, args,
30✔
681
                                                ARRAY_LEN(args), false);
682

683
         static const char *names[] = {
30✔
684
            "nvc.sexp.with.overflow.i16",
685
            "nvc.sexp.with.overflow.i16",
686
            "nvc.sexp.with.overflow.i32",
687
            "nvc.sexp.with.overflow.i64"
688
         };
689
         fn = llvm_add_fn(obj, names[sz], obj->fntypes[which]);
30✔
690
         llvm_add_func_attr(obj, fn, FUNC_ATTR_NOUNWIND, -1);
30✔
691
      }
692
      break;
30✔
693

694
   case LLVM_EXP_OVERFLOW_U8:
2✔
695
   case LLVM_EXP_OVERFLOW_U16:
696
   case LLVM_EXP_OVERFLOW_U32:
697
   case LLVM_EXP_OVERFLOW_U64:
698
      {
699
         jit_size_t sz = which - LLVM_EXP_OVERFLOW_U8;
2✔
700
         LLVMTypeRef int_type = obj->types[LLVM_INT8 + sz];
2✔
701
         LLVMTypeRef pair_type = obj->types[LLVM_PAIR_I8_I1 + sz];
2✔
702
         LLVMTypeRef args[] = { int_type, int_type };
2✔
703
         obj->fntypes[which] = LLVMFunctionType(pair_type, args,
2✔
704
                                                ARRAY_LEN(args), false);
705

706
         static const char *names[] = {
2✔
707
            "nvc.uexp.with.overflow.i16",
708
            "nvc.uexp.with.overflow.i16",
709
            "nvc.uexp.with.overflow.i32",
710
            "nvc.uexp.with.overflow.i64"
711
         };
712
         fn = llvm_add_fn(obj, names[sz], obj->fntypes[which]);
2✔
713
      }
714
      break;
2✔
715

716
   case LLVM_ADD_SAT_U8:
146✔
717
   case LLVM_ADD_SAT_U16:
718
   case LLVM_ADD_SAT_U32:
719
   case LLVM_ADD_SAT_U64:
720
      {
721
         jit_size_t sz = which - LLVM_ADD_SAT_U8;
146✔
722
         LLVMTypeRef int_type = obj->types[LLVM_INT8 + sz];
146✔
723
         LLVMTypeRef args[] = { int_type, int_type };
146✔
724
         obj->fntypes[which] = LLVMFunctionType(int_type, args,
146✔
725
                                                ARRAY_LEN(args), false);
726

727
         static const char *names[] = {
146✔
728
            "llvm.uadd.sat.i8",
729
            "llvm.uadd.sat.i16",
730
            "llvm.uadd.sat.i32",
731
            "llvm.uadd.sat.i64"
732
         };
733
         fn = llvm_add_fn(obj, names[sz], obj->fntypes[which]);
146✔
734
      }
735
      break;
146✔
736

737
   case LLVM_MEMSET_U8:
235✔
738
   case LLVM_MEMSET_U16:
739
   case LLVM_MEMSET_U32:
740
   case LLVM_MEMSET_U64:
741
      {
742
         jit_size_t sz = which - LLVM_MEMSET_U8;
235✔
743
         LLVMTypeRef args[] = {
235✔
744
            obj->types[LLVM_PTR],
235✔
745
            obj->types[LLVM_INT8 + sz],
235✔
746
            obj->types[LLVM_INT64]
235✔
747
         };
748
         obj->fntypes[which] = LLVMFunctionType(obj->types[LLVM_VOID], args,
235✔
749
                                                ARRAY_LEN(args), false);
750

751
         static const char *names[] = {
235✔
752
            NULL,   // Use regular memset instead
753
            "nvc.memset.i16",
754
            "nvc.memset.i32",
755
            "nvc.memset.i64"
756
         };
757
         fn = llvm_add_fn(obj, names[sz], obj->fntypes[which]);
235✔
758
      }
759
      break;
235✔
760

761
   case LLVM_POW_F64:
14✔
762
      {
763
         LLVMTypeRef args[] = {
14✔
764
            obj->types[LLVM_DOUBLE],
14✔
765
            obj->types[LLVM_DOUBLE]
766
         };
767
         obj->fntypes[which] = LLVMFunctionType(obj->types[LLVM_DOUBLE],
14✔
768
                                                args, ARRAY_LEN(args), false);
769

770
         fn = llvm_add_fn(obj, "llvm.pow.f64", obj->fntypes[which]);
14✔
771
      }
772
      break;
14✔
773

774
   case LLVM_COPYSIGN_F64:
36✔
775
      {
776
         LLVMTypeRef args[] = {
36✔
777
            obj->types[LLVM_DOUBLE],
36✔
778
            obj->types[LLVM_DOUBLE]
779
         };
780
         obj->fntypes[which] = LLVMFunctionType(obj->types[LLVM_DOUBLE],
36✔
781
                                                args, ARRAY_LEN(args), false);
782

783
         fn = llvm_add_fn(obj, "llvm.copysign.f64", obj->fntypes[which]);
36✔
784
      }
785
      break;
36✔
786

787
   case LLVM_MEMSET_INLINE:
×
788
      {
789
         LLVMTypeRef args[] = {
×
790
            obj->types[LLVM_PTR],
×
791
            obj->types[LLVM_INT8],
×
792
            obj->types[LLVM_INT64],
×
793
            obj->types[LLVM_INT1],
×
794
         };
795
         obj->fntypes[which] = LLVMFunctionType(obj->types[LLVM_VOID],
×
796
                                                args, ARRAY_LEN(args), false);
797

798
         fn = llvm_add_fn(obj, "llvm.memset.inline.p0.i64",
×
799
                          obj->fntypes[which]);
800
      }
801
      break;
×
802

803
   case LLVM_MEMCPY_INLINE:
×
804
      {
805
         LLVMTypeRef args[] = {
×
806
            obj->types[LLVM_PTR],
×
807
            obj->types[LLVM_PTR],
808
            obj->types[LLVM_INT64],
×
809
            obj->types[LLVM_INT1],
×
810
         };
811
         obj->fntypes[which] = LLVMFunctionType(obj->types[LLVM_VOID],
×
812
                                                args, ARRAY_LEN(args), false);
813

814
         fn = llvm_add_fn(obj, "llvm.memcpy.inline.p0.p0.i64",
×
815
                          obj->fntypes[which]);
816
      }
817
      break;
×
818

819
   case LLVM_DO_EXIT:
6,905✔
820
      {
821
         LLVMTypeRef args[] = {
6,905✔
822
            obj->types[LLVM_INT32],
6,905✔
823
            obj->types[LLVM_PTR],
6,905✔
824
#ifdef LLVM_HAS_OPAQUE_POINTERS
825
            obj->types[LLVM_PTR],
826
#else
827
            LLVMPointerType(obj->types[LLVM_INT64], 0),
6,905✔
828
#endif
829
#ifdef LLVM_HAS_OPAQUE_POINTERS
830
            obj->types[LLVM_PTR],
831
#else
832
            LLVMPointerType(obj->types[LLVM_TLAB], 0),
6,905✔
833
#endif
834
         };
835
         obj->fntypes[which] = LLVMFunctionType(obj->types[LLVM_VOID], args,
6,905✔
836
                                                ARRAY_LEN(args), false);
837

838
         fn = llvm_add_fn(obj, "__nvc_do_exit", obj->fntypes[which]);
6,905✔
839
         llvm_add_func_attr(obj, fn, FUNC_ATTR_NOUNWIND, -1);
6,905✔
840
         llvm_add_func_attr(obj, fn, FUNC_ATTR_READONLY, 2);
6,905✔
841
         llvm_add_func_attr(obj, fn, FUNC_ATTR_NOCAPTURE, 2);
6,905✔
842
         llvm_add_func_attr(obj, fn, FUNC_ATTR_NOCAPTURE, 3);
6,905✔
843
         llvm_add_func_attr(obj, fn, FUNC_ATTR_NOCAPTURE, 4);
6,905✔
844
      }
845
      break;
6,905✔
846

847
   case LLVM_SCHED_WAVEFORM:
3,864✔
848
   case LLVM_TEST_EVENT:
849
   case LLVM_LAST_EVENT:
850
   case LLVM_SCHED_PROCESS:
851
      {
852
         LLVMTypeRef args[] = {
3,864✔
853
            obj->types[LLVM_PTR],
3,864✔
854
#ifdef LLVM_HAS_OPAQUE_POINTERS
855
            obj->types[LLVM_PTR],
856
#else
857
            LLVMPointerType(obj->types[LLVM_INT64], 0),
3,864✔
858
#endif
859
#ifdef LLVM_HAS_OPAQUE_POINTERS
860
            obj->types[LLVM_PTR],
861
#else
862
            LLVMPointerType(obj->types[LLVM_TLAB], 0),
3,864✔
863
#endif
864
         };
865
         obj->fntypes[which] = LLVMFunctionType(obj->types[LLVM_VOID], args,
3,864✔
866
                                                ARRAY_LEN(args), false);
867

868
         const char *sym = NULL;
3,864✔
869
         switch (which) {
3,864✔
870
         case LLVM_SCHED_WAVEFORM: sym = "__nvc_sched_waveform"; break;
871
         case LLVM_TEST_EVENT: sym = "__nvc_test_event"; break;
110✔
872
         case LLVM_LAST_EVENT: sym = "__nvc_last_event"; break;
11✔
873
         case LLVM_SCHED_PROCESS: sym = "__nvc_sched_process"; break;
1,471✔
874
         default: break;
875
         }
876

877
         fn = llvm_add_fn(obj, sym, obj->fntypes[which]);
3,864✔
878
         llvm_add_func_attr(obj, fn, FUNC_ATTR_NOUNWIND, -1);
3,864✔
879
         llvm_add_func_attr(obj, fn, FUNC_ATTR_READONLY, 1);
3,864✔
880
         llvm_add_func_attr(obj, fn, FUNC_ATTR_NOCAPTURE, 1);
3,864✔
881
         llvm_add_func_attr(obj, fn, FUNC_ATTR_NOCAPTURE, 2);
3,864✔
882
         llvm_add_func_attr(obj, fn, FUNC_ATTR_NOCAPTURE, 3);
3,864✔
883
      }
884
      break;
3,864✔
885

886
   case LLVM_PUTPRIV:
3,371✔
887
      {
888
         LLVMTypeRef args[] = {
3,371✔
889
            obj->types[LLVM_INT32],
3,371✔
890
            obj->types[LLVM_PTR]
3,371✔
891
         };
892
         obj->fntypes[which] = LLVMFunctionType(obj->types[LLVM_VOID], args,
3,371✔
893
                                                ARRAY_LEN(args), false);
894

895
         fn = llvm_add_fn(obj, "__nvc_putpriv", obj->fntypes[which]);
3,371✔
896
         llvm_add_func_attr(obj, fn, FUNC_ATTR_NOUNWIND, -1);
3,371✔
897
      }
898
      break;
3,371✔
899

900
   case LLVM_MSPACE_ALLOC:
6,367✔
901
      {
902
         LLVMTypeRef args[] = {
6,367✔
903
            obj->types[LLVM_INTPTR],
6,367✔
904
#ifdef LLVM_HAS_OPAQUE_POINTERS
905
            obj->types[LLVM_PTR],
906
#else
907
            LLVMPointerType(obj->types[LLVM_ANCHOR], 0),
6,367✔
908
#endif
909
         };
910
         obj->fntypes[which] = LLVMFunctionType(obj->types[LLVM_PTR], args,
6,367✔
911
                                                ARRAY_LEN(args), false);
912

913
         fn = llvm_add_fn(obj, "__nvc_mspace_alloc", obj->fntypes[which]);
6,367✔
914
         llvm_add_func_attr(obj, fn, FUNC_ATTR_NOUNWIND, -1);
6,367✔
915
      }
916
      break;
6,367✔
917

918
   case LLVM_GET_OBJECT:
1,252✔
919
      {
920
         LLVMTypeRef args[] = {
1,252✔
921
            obj->types[LLVM_PTR],
1,252✔
922
            obj->types[LLVM_INTPTR]
1,252✔
923
         };
924
         obj->fntypes[which] = LLVMFunctionType(obj->types[LLVM_PTR], args,
1,252✔
925
                                                ARRAY_LEN(args), false);
926
         fn = llvm_add_fn(obj, "__nvc_get_object", obj->fntypes[which]);
1,252✔
927
         llvm_add_func_attr(obj, fn, FUNC_ATTR_NOUNWIND, -1);
1,252✔
928
         llvm_add_func_attr(obj, fn, FUNC_ATTR_NOCAPTURE, 1);
1,252✔
929
         llvm_add_func_attr(obj, fn, FUNC_ATTR_READONLY, 1);
1,252✔
930
      }
931
      break;
1,252✔
932

933
   case LLVM_TLAB_ALLOC:
6,304✔
934
      {
935
         LLVMTypeRef args[] = {
6,304✔
936
#ifdef LLVM_HAS_OPAQUE_POINTERS
937
            obj->types[LLVM_PTR],
938
#else
939
            LLVMPointerType(obj->types[LLVM_TLAB], 0),
6,304✔
940
#endif
941
            obj->types[LLVM_INTPTR],
6,304✔
942
#ifdef LLVM_HAS_OPAQUE_POINTERS
943
            obj->types[LLVM_PTR],
944
#else
945
            LLVMPointerType(obj->types[LLVM_ANCHOR], 0),
6,304✔
946
#endif
947
         };
948
         obj->fntypes[which] = LLVMFunctionType(obj->types[LLVM_PTR], args,
6,304✔
949
                                                ARRAY_LEN(args), false);
950
         fn = llvm_add_fn(obj, "tlab_alloc", obj->fntypes[which]);
6,304✔
951
         llvm_add_func_attr(obj, fn, FUNC_ATTR_NOUNWIND, -1);
6,304✔
952
      }
953
      break;
6,304✔
954

955
   default:
×
956
      fatal_trace("cannot generate prototype for function %d", which);
957
   }
958

959
   return (obj->fns[which] = fn);
29,225✔
960
}
961

962
static LLVMValueRef llvm_call_fn(llvm_obj_t *obj, llvm_fn_t which,
163,582✔
963
                                 LLVMValueRef *args, unsigned count)
964
{
965
   LLVMValueRef fn = llvm_get_fn(obj, which);
163,582✔
966
   return LLVMBuildCall2(obj->builder, obj->fntypes[which], fn,
163,582✔
967
                         args, count, "");
968
}
969

970
static LLVMValueRef llvm_const_string(llvm_obj_t *obj, const char *str)
43,602✔
971
{
972
   const unsigned off = pack_writer_get_string(obj->pack_writer, str);
43,602✔
973

974
   LLVMValueRef indexes[] = {
43,602✔
975
      llvm_int32(obj, 0),
43,602✔
976
      llvm_int32(obj, off)
43,602✔
977
   };
978
   return LLVMBuildGEP2(obj->builder, obj->types[LLVM_STRTAB], obj->strtab,
43,602✔
979
                        indexes, ARRAY_LEN(indexes), "string");
980
}
981

982
#if ENABLE_DWARF
983
static void llvm_add_module_flag(llvm_obj_t *obj, const char *key, int value)
984
{
985
   LLVMAddModuleFlag(obj->module, LLVMModuleFlagBehaviorWarning,
986
                     key, strlen(key),
987
                     LLVMValueAsMetadata(llvm_int32(obj, value)));
988
}
989
#endif
990

991
static bool llvm_is_ptr(LLVMValueRef value)
1,078,676✔
992
{
993
   return LLVMGetTypeKind(LLVMTypeOf(value)) == LLVMPointerTypeKind;
1,078,676✔
994
}
995

996
#ifdef DEBUG
997
static void llvm_set_value_name(LLVMValueRef value, const char *name)
225,420✔
998
{
999
   size_t curlen;
225,420✔
1000
   LLVMGetValueName2(value, &curlen);
225,420✔
1001
   if (curlen == 0)
225,420✔
1002
      LLVMSetValueName(value, name);
179,256✔
1003
}
225,420✔
1004

1005
__attribute__((unused))
1006
static void llvm_dump_value(const char *tag, LLVMValueRef value)
1007
{
1008
   fprintf(stderr, "%s: ", tag);
1009
   fflush(stderr);
1010
   LLVMDumpValue(value);
1011
   fprintf(stderr, "\n");
1012
}
1013
#endif
1014

1015
static void llvm_native_setup(void)
4,840✔
1016
{
1017
   LLVMInitializeNativeTarget();
4,840✔
1018
   LLVMInitializeNativeAsmPrinter();
4,840✔
1019

1020
   if (!LLVMIsMultithreaded())
4,840✔
UNCOV
1021
      fatal("LLVM was built without multithreaded support");
×
1022
}
4,840✔
1023

1024
////////////////////////////////////////////////////////////////////////////////
1025
// JIT IR to LLVM lowering
1026

1027
static const char *cgen_reg_name(jit_reg_t reg)
1,002,642✔
1028
{
1029
#ifdef DEBUG
1030
   static volatile int uniq = 0;
1,002,642✔
1031
   static __thread char buf[32];
1,002,642✔
1032
   checked_sprintf(buf, sizeof(buf), "R%d.%d", reg, relaxed_add(&uniq, 1));
1,002,642✔
1033
   return buf;
1,002,642✔
1034
#else
1035
   return "";
1036
#endif
1037
}
1038

1039
static const char *cgen_arg_name(int nth)
181,356✔
1040
{
1041
#ifdef DEBUG
1042
   static volatile int uniq = 0;
181,356✔
1043
   static __thread char buf[32];
181,356✔
1044
   checked_sprintf(buf, sizeof(buf), "A%d.%d", nth, relaxed_add(&uniq, 1));
181,356✔
1045
   return buf;
181,356✔
1046
#else
1047
   return "";
1048
#endif
1049
}
1050

1051
__attribute__((noreturn))
UNCOV
1052
static void cgen_abort(cgen_block_t *cgb, jit_ir_t *ir, const char *fmt, ...)
×
1053
{
UNCOV
1054
   va_list ap;
×
UNCOV
1055
   va_start(ap, fmt);
×
1056

UNCOV
1057
   char *text LOCAL = xvasprintf(fmt, ap);
×
UNCOV
1058
   jit_dump_with_mark(cgb->func->source, ir - cgb->func->source->irbuf, false);
×
1059
   fatal_trace("%s", text);
1060

1061
   va_end(ap);
1062
}
1063

1064
static LLVMRealPredicate cgen_real_pred(cgen_block_t *cgb, jit_ir_t *ir)
2,359✔
1065
{
1066
   switch (ir->cc) {
2,359✔
1067
   case JIT_CC_EQ: return LLVMRealUEQ;
1068
   case JIT_CC_NE: return LLVMRealUNE;
1069
   case JIT_CC_GT: return LLVMRealUGT;
1070
   case JIT_CC_LT: return LLVMRealULT;
1071
   case JIT_CC_LE: return LLVMRealULE;
1072
   case JIT_CC_GE: return LLVMRealUGE;
UNCOV
1073
   default:
×
UNCOV
1074
      cgen_abort(cgb, ir, "unhandled fcmp condition code");
×
1075
   }
1076
}
1077

1078
static LLVMIntPredicate cgen_int_pred(cgen_block_t *cgb, jit_ir_t *ir)
139,529✔
1079
{
1080
   switch (ir->cc) {
139,529✔
1081
   case JIT_CC_EQ: return LLVMIntEQ;
1082
   case JIT_CC_NE: return LLVMIntNE;
1083
   case JIT_CC_GT: return LLVMIntSGT;
1084
   case JIT_CC_LT: return LLVMIntSLT;
1085
   case JIT_CC_LE: return LLVMIntSLE;
1086
   case JIT_CC_GE: return LLVMIntSGE;
UNCOV
1087
   default:
×
UNCOV
1088
      cgen_abort(cgb, ir, "unhandled cmp condition code");
×
1089
   }
1090
}
1091

1092
static cgen_reloc_t *cgen_find_reloc(cgen_reloc_t *list, reloc_kind_t kind,
80,936✔
1093
                                     int limit, uintptr_t key)
1094
{
1095
   for (int i = 0; i < limit; i++) {
250,410✔
1096
      if (list[i].kind == kind && list[i].key == key)
223,646✔
1097
         return &(list[i]);
54,172✔
1098
      else if (list[i].kind == RELOC_NULL)
169,474✔
1099
         break;
1100
   }
1101

1102
   return NULL;
1103
}
1104

1105
static LLVMValueRef cgen_load_from_reloc(llvm_obj_t *obj, cgen_func_t *func,
15,724✔
1106
                                         reloc_kind_t kind, uintptr_t key)
1107
{
1108
   cgen_reloc_t *reloc = cgen_find_reloc(func->relocs, kind, INT_MAX, key);
15,724✔
1109
   assert(reloc != NULL);
15,724✔
1110

1111
   LLVMValueRef array = LLVMBuildStructGEP2(obj->builder, func->descr_type,
15,724✔
1112
                                            func->descr, 4, "");
1113

1114
   LLVMValueRef indexes[] = {
15,724✔
1115
      llvm_intptr(obj, 0),
15,724✔
1116
      llvm_intptr(obj, reloc->nth)
15,724✔
1117
   };
1118
   LLVMValueRef elem =
15,724✔
1119
      LLVMBuildInBoundsGEP2(obj->builder, func->reloc_type, array,
15,724✔
1120
                            indexes, ARRAY_LEN(indexes), "");
1121
   LLVMValueRef ptr =
15,724✔
1122
      LLVMBuildStructGEP2(obj->builder, obj->types[LLVM_AOT_RELOC],
15,724✔
1123
                          elem, 1, "");
1124

1125
   return LLVMBuildLoad2(obj->builder, obj->types[LLVM_PTR], ptr, "");
15,724✔
1126
}
1127

1128
static LLVMValueRef cgen_rematerialise_object(llvm_obj_t *obj,
61,966✔
1129
                                              cgen_func_t *func,
1130
                                              object_t *locus)
1131
{
1132
   if (func->mode == CGEN_AOT) {
61,966✔
1133
      ident_t module;
43,602✔
1134
      ptrdiff_t offset;
43,602✔
1135
      object_locus(locus, &module, &offset);
43,602✔
1136

1137
      LOCAL_TEXT_BUF tb = tb_new();
87,204✔
1138
      tb_istr(tb, module);
43,602✔
1139

1140
      LLVMValueRef unit_str = llvm_const_string(obj, tb_get(tb));
43,602✔
1141

1142
      LLVMValueRef args[] = {
43,602✔
1143
         unit_str,
1144
         llvm_intptr(obj, offset),
43,602✔
1145
      };
1146
      return llvm_call_fn(obj, LLVM_GET_OBJECT, args, ARRAY_LEN(args));
43,602✔
1147
   }
1148
   else
1149
      return llvm_ptr(obj, locus);
18,364✔
1150
}
1151

1152
static LLVMValueRef cgen_rematerialise_handle(llvm_obj_t *obj,
1,513✔
1153
                                              cgen_func_t *func,
1154
                                              jit_handle_t handle)
1155
{
1156
   LLVMValueRef ptr =
1,513✔
1157
      cgen_load_from_reloc(obj, func, RELOC_HANDLE, handle);
1,513✔
1158
   LLVMValueRef intptr =
1,513✔
1159
      LLVMBuildPtrToInt(obj->builder, ptr, obj->types[LLVM_INTPTR], "");
1,513✔
1160

1161
#ifdef DEBUG
1162
   ident_t name = jit_get_name(func->source->jit, handle);
1,513✔
1163
   char *valname LOCAL = xasprintf("%s.handle", istr(name));
3,026✔
1164
#else
1165
   const char *valname = "";
1166
#endif
1167

1168
   return LLVMBuildTrunc(obj->builder, intptr, obj->types[LLVM_INT32], valname);
1,513✔
1169
}
1170

1171
static LLVMValueRef cgen_get_value(llvm_obj_t *obj, cgen_block_t *cgb,
1,856,766✔
1172
                                   jit_value_t value)
1173
{
1174
   switch (value.kind) {
1,856,766✔
1175
   case JIT_VALUE_REG:
849,664✔
1176
      assert(value.reg < cgb->func->source->nregs);
849,664✔
1177
      assert(cgb->outregs[value.reg] != NULL);
849,664✔
1178
      return cgb->outregs[value.reg];
1179
   case JIT_VALUE_INT64:
528,667✔
1180
      return llvm_int64(obj, value.int64);
528,667✔
1181
   case JIT_VALUE_DOUBLE:
5,803✔
1182
      return llvm_real(obj, value.dval);
5,803✔
1183
   case JIT_ADDR_CPOOL:
13,366✔
1184
      assert(value.int64 >= 0 && value.int64 <= cgb->func->source->cpoolsz);
13,366✔
1185
      if (cgb->func->mode == CGEN_AOT) {
13,366✔
1186
         LLVMValueRef indexes[] = {
8,854✔
1187
            llvm_intptr(obj, 0),
8,854✔
1188
            llvm_intptr(obj, value.int64)
8,854✔
1189
         };
1190
         return LLVMBuildInBoundsGEP2(obj->builder, cgb->func->cpool_type,
8,854✔
1191
                                      cgb->func->cpool, indexes,
8,854✔
1192
                                      ARRAY_LEN(indexes), "");
1193
      }
1194
      else
1195
         return llvm_ptr(obj, cgb->func->source->cpool + value.int64);
4,512✔
1196
   case JIT_ADDR_REG:
293,860✔
1197
      {
1198
         assert(value.reg < cgb->func->source->nregs);
293,860✔
1199
         LLVMValueRef ptr = cgb->outregs[value.reg];
293,860✔
1200

1201
         if (value.disp == 0)
293,860✔
1202
            return ptr;
1203
         else if (llvm_is_ptr(ptr)) {
204,275✔
1204
            LLVMValueRef indexes[] = { llvm_intptr(obj, value.disp) };
191,718✔
1205
            return LLVMBuildGEP2(obj->builder,
191,718✔
1206
                                 obj->types[LLVM_INT8],
1207
                                 ptr, indexes, 1, "");
1208
         }
1209
         else {
1210
            LLVMValueRef disp = llvm_int64(obj, value.disp);
12,557✔
1211
            return LLVMBuildAdd(obj->builder, ptr, disp, "");
12,557✔
1212
         }
1213
      }
1214
   case JIT_VALUE_EXIT:
76,506✔
1215
      return llvm_int32(obj, value.exit);
76,506✔
1216
   case JIT_VALUE_HANDLE:
6,527✔
1217
      if (cgb->func->mode == CGEN_AOT && value.handle != JIT_HANDLE_INVALID)
6,527✔
1218
         return cgen_rematerialise_handle(obj, cgb->func, value.handle);
1,513✔
1219
      else
1220
         return llvm_int32(obj, value.handle);
5,014✔
1221
   case JIT_ADDR_ABS:
18,478✔
1222
      return llvm_ptr(obj, (void *)(intptr_t)value.int64);
18,478✔
1223
   case JIT_ADDR_COVER:
1,929✔
1224
      if (cgb->func->mode == CGEN_AOT) {
1,929✔
1225
         LLVMValueRef ptr =
1,567✔
1226
            cgen_load_from_reloc(obj, cgb->func, RELOC_COVER, 0);
1,567✔
1227
         LLVMValueRef base = LLVMBuildLoad2(obj->builder,
1,567✔
1228
                                            obj->types[LLVM_PTR], ptr, "");
1229
         LLVMValueRef indexes[] = {
1,567✔
1230
            llvm_intptr(obj, value.int64)
1,567✔
1231
         };
1232
         return LLVMBuildGEP2(obj->builder, obj->types[LLVM_INT32],
1,567✔
1233
                              base, indexes, 1, "");
1234
      }
1235
      else
1236
         return llvm_ptr(obj, jit_get_cover_ptr(cgb->func->source->jit, value));
362✔
1237
   case JIT_VALUE_LOCUS:
61,966✔
1238
      return cgen_rematerialise_object(obj, cgb->func, value.locus);
61,966✔
UNCOV
1239
   default:
×
1240
      fatal_trace("cannot handle value kind %d", value.kind);
1241
   }
1242
}
1243

1244
static LLVMValueRef cgen_coerce_value(llvm_obj_t *obj, cgen_block_t *cgb,
397,751✔
1245
                                      jit_value_t value, llvm_type_t type)
1246
{
1247
   LLVMValueRef raw = cgen_get_value(obj, cgb, value);
397,751✔
1248
   LLVMTypeRef lltype = LLVMTypeOf(raw);
397,751✔
1249

1250
   switch (type) {
397,751✔
1251
   case LLVM_PTR:
286,287✔
1252
      if (LLVMGetTypeKind(lltype) == LLVMIntegerTypeKind)
286,287✔
1253
         return LLVMBuildIntToPtr(obj->builder, raw, obj->types[LLVM_PTR], "");
34✔
1254
      else
1255
         return raw;
1256

1257
   case LLVM_INTPTR:
103,806✔
1258
   case LLVM_INT64:
1259
   case LLVM_INT32:
1260
   case LLVM_INT16:
1261
   case LLVM_INT8:
1262
   case LLVM_INT1:
1263
      switch (LLVMGetTypeKind(lltype)) {
103,806✔
1264
      case LLVMPointerTypeKind:
4,485✔
1265
         return LLVMBuildIntToPtr(obj->builder, raw, obj->types[LLVM_PTR], "");
4,485✔
1266
      case LLVMIntegerTypeKind:
98,814✔
1267
         {
1268
            const int bits1 = LLVMGetIntTypeWidth(lltype);
98,814✔
1269
            const int bits2 = LLVMGetIntTypeWidth(obj->types[type]);
98,814✔
1270

1271
            if (bits2 == 1) {
98,814✔
1272
               LLVMValueRef zero = LLVMConstInt(lltype, 0, false);
2,173✔
1273
               return LLVMBuildICmp(obj->builder, LLVMIntNE, raw, zero, "");
2,173✔
1274
            }
1275
            else if (bits1 < bits2)
96,641✔
1276
               return LLVMBuildSExt(obj->builder, raw, obj->types[type], "");
×
1277
            else if (bits1 == bits2)
96,641✔
1278
               return raw;
1279
            else
1280
               return LLVMBuildTrunc(obj->builder, raw, obj->types[type], "");
50,586✔
1281
         }
1282
      case LLVMDoubleTypeKind:
507✔
1283
         return LLVMBuildBitCast(obj->builder, raw, obj->types[type], "");
507✔
UNCOV
1284
      default:
×
UNCOV
1285
         LLVMDumpType(lltype);
×
1286
         fatal_trace("cannot coerce type to integer");
1287
      }
1288
      break;
7,658✔
1289

1290
   case LLVM_DOUBLE:
7,658✔
1291
      return LLVMBuildBitCast(obj->builder, raw, obj->types[type], "");
7,658✔
1292

1293
   default:
1294
      return raw;
1295
   }
1296
}
1297

1298
static void cgen_pointer_result(llvm_obj_t *obj, cgen_block_t *cgb,
97,435✔
1299
                                jit_ir_t *ir, LLVMValueRef value)
1300
{
1301
   assert(llvm_is_ptr(value));
97,435✔
1302

1303
   if (mask_test(&cgb->func->ptr_mask, ir->result)) {
97,435✔
1304
      DEBUG_ONLY(llvm_set_value_name(value, cgen_reg_name(ir->result)));
97,372✔
1305
      cgb->outregs[ir->result] = PTR(value);
97,372✔
1306
   }
1307
   else
1308
      cgb->outregs[ir->result] = LLVMBuildPtrToInt(obj->builder, value,
63✔
1309
                                                   obj->types[LLVM_INT64],
1310
                                                   cgen_reg_name(ir->result));
1311
}
97,435✔
1312

1313
static void cgen_sext_result(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir,
164,581✔
1314
                             LLVMValueRef value)
1315
{
1316
   LLVMTypeRef type = LLVMTypeOf(value);
164,581✔
1317
   switch (LLVMGetTypeKind(type)) {
164,581✔
1318
   case LLVMIntegerTypeKind:
133,422✔
1319
      if (LLVMGetIntTypeWidth(type) == 64) {
133,422✔
1320
         DEBUG_ONLY(llvm_set_value_name(value, cgen_reg_name(ir->result)));
86,573✔
1321
         cgb->outregs[ir->result] = value;
86,573✔
1322
      }
1323
      else
1324
         cgb->outregs[ir->result] = LLVMBuildSExt(obj->builder, value,
46,849✔
1325
                                                  obj->types[LLVM_INT64],
1326
                                                  cgen_reg_name(ir->result));
46,849✔
1327
      break;
1328

1329
   case LLVMDoubleTypeKind:
1,924✔
1330
      cgb->outregs[ir->result] = LLVMBuildBitCast(obj->builder, value,
1,924✔
1331
                                                  obj->types[LLVM_INT64],
1332
                                                  cgen_reg_name(ir->result));
1,924✔
1333
      break;
1,924✔
1334

1335
   case LLVMPointerTypeKind:
29,235✔
1336
      cgen_pointer_result(obj, cgb, ir, value);
29,235✔
1337
      break;
29,235✔
1338

UNCOV
1339
   default:
×
UNCOV
1340
      LLVMDumpType(type);
×
1341
      fatal_trace("unhandled LLVM type kind in cgen_sext_result");
1342
   }
1343
}
164,581✔
1344

1345
static void cgen_zext_result(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir,
75,821✔
1346
                             LLVMValueRef value)
1347
{
1348
   LLVMTypeRef type = LLVMTypeOf(value);
75,821✔
1349
   switch (LLVMGetTypeKind(type)) {
75,821✔
1350
   case LLVMIntegerTypeKind:
75,821✔
1351
      if (LLVMGetIntTypeWidth(type) == 64) {
75,821✔
1352
         DEBUG_ONLY(llvm_set_value_name(value, cgen_reg_name(ir->result)));
41,475✔
1353
         cgb->outregs[ir->result] = value;
41,475✔
1354
      }
1355
      else
1356
         cgb->outregs[ir->result] = LLVMBuildZExt(obj->builder, value,
34,346✔
1357
                                                  obj->types[LLVM_INT64],
1358
                                                  cgen_reg_name(ir->result));
34,346✔
1359
      break;
75,821✔
1360

UNCOV
1361
   default:
×
UNCOV
1362
      LLVMDumpType(type);
×
1363
      fatal_trace("unhandled LLVM type kind in cgen_sext_result");
1364
   }
1365
}
75,821✔
1366

1367
static void cgen_sync_irpos(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
140,961✔
1368
{
1369
   const unsigned irpos = ir - cgb->func->source->irbuf;
140,961✔
1370
   LLVMBuildStore(obj->builder, llvm_int32(obj, irpos), cgb->func->irpos);
140,961✔
1371
}
140,961✔
1372

1373
#if ENABLE_DWARF
1374
static void cgen_debug_loc(llvm_obj_t *obj, cgen_func_t *func, const loc_t *loc)
1375
{
1376
   if (loc_eq(loc, &(func->last_loc)))
1377
      return;
1378

1379
   LLVMMetadataRef dloc = LLVMDIBuilderCreateDebugLocation(
1380
      obj->context, loc->first_line, loc->first_column,
1381
      func->debugmd, NULL);
1382

1383
#ifdef LLVM_HAVE_SET_CURRENT_DEBUG_LOCATION_2
1384
   LLVMSetCurrentDebugLocation2(obj->builder, dloc);
1385
#else
1386
   LLVMValueRef md = LLVMMetadataAsValue(obj->context, dloc);
1387
   LLVMSetCurrentDebugLocation(obj->builder, md);
1388
#endif
1389
}
1390
#endif
1391

1392
static void cgen_op_recv(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
100,364✔
1393
{
1394
   assert(ir->arg1.kind == JIT_VALUE_INT64);
100,364✔
1395
   const int nth = ir->arg1.int64;
100,364✔
1396

1397
   LLVMValueRef ptr;
100,364✔
1398
   if (nth < ARGCACHE_SIZE)
100,364✔
1399
      ptr = cgb->func->argcache[nth];
97,202✔
1400
   else {
1401
      assert(nth < JIT_MAX_ARGS);
3,162✔
1402
      LLVMValueRef indexes[] = { llvm_intptr(obj, nth) };
3,162✔
1403
      ptr = LLVMBuildInBoundsGEP2(obj->builder, obj->types[LLVM_INT64],
6,324✔
1404
                                  cgb->func->args, indexes, ARRAY_LEN(indexes),
3,162✔
1405
                                  cgen_arg_name(nth));
1406
   }
1407

1408
   llvm_type_t type =
200,728✔
1409
      mask_test(&cgb->func->ptr_mask, ir->result) ? LLVM_PTR : LLVM_INT64;
100,364✔
1410

1411
#ifdef LLVM_HAS_OPAQUE_POINTERS
1412
   LLVMValueRef cast = ptr;
1413
#else
1414
   LLVMTypeRef ptr_type = LLVMPointerType(obj->types[type], 0);
100,364✔
1415
   LLVMValueRef cast =
100,364✔
1416
      LLVMBuildPointerCast(obj->builder, ptr, ptr_type, "");
100,364✔
1417
#endif
1418

1419
   cgb->outregs[ir->result] = LLVMBuildLoad2(obj->builder, obj->types[type],
100,364✔
1420
                                             cast, cgen_reg_name(ir->result));
100,364✔
1421
   LLVMSetAlignment(cgb->outregs[ir->result], sizeof(int64_t));
100,364✔
1422
}
100,364✔
1423

1424
static void cgen_op_send(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
583,653✔
1425
{
1426
   assert(ir->arg1.kind == JIT_VALUE_INT64);
583,653✔
1427
   const int nth = ir->arg1.int64;
583,653✔
1428

1429
   LLVMValueRef value = cgen_get_value(obj, cgb, ir->arg2);
583,653✔
1430

1431
   LLVMValueRef ptr;
583,653✔
1432
   if (nth < ARGCACHE_SIZE)
583,653✔
1433
      ptr = cgb->func->argcache[nth];
538,737✔
1434
   else {
1435
      assert(nth < JIT_MAX_ARGS);
44,916✔
1436
      LLVMValueRef indexes[] = { llvm_int32(obj, nth) };
44,916✔
1437
      LLVMTypeRef int64_type = obj->types[LLVM_INT64];
44,916✔
1438
#ifdef LLVM_HAS_OPAQUE_POINTERS
1439
      LLVMValueRef args_cast = cgb->func->args;
1440
#else
1441
      LLVMTypeRef args_ptr_type = LLVMPointerType(int64_type, 0);
44,916✔
1442
      LLVMValueRef args_cast =
44,916✔
1443
         LLVMBuildPointerCast(obj->builder, cgb->func->args, args_ptr_type, "");
44,916✔
1444
#endif
1445
      ptr = LLVMBuildInBoundsGEP2(obj->builder, int64_type,
44,916✔
1446
                                  args_cast, indexes, ARRAY_LEN(indexes),
1447
                                  cgen_arg_name(nth));
1448
   }
1449

1450
#ifdef LLVM_HAS_OPAQUE_POINTERS
1451
   LLVMValueRef store = LLVMBuildStore(obj->builder, value, ptr);
1452
#else
1453
   LLVMTypeRef ptr_type = LLVMPointerType(LLVMTypeOf(value), 0);
583,653✔
1454
   LLVMValueRef cast = LLVMBuildPointerCast(obj->builder, ptr, ptr_type, "");
583,653✔
1455
   LLVMValueRef store = LLVMBuildStore(obj->builder, value, cast);
583,653✔
1456
#endif
1457

1458
   LLVMSetAlignment(store, sizeof(int64_t));
583,653✔
1459
}
583,653✔
1460

1461
static void cgen_op_store(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
91,263✔
1462
{
1463
   llvm_type_t type   = LLVM_INT8 + ir->size;
91,263✔
1464
   LLVMValueRef value = cgen_coerce_value(obj, cgb, ir->arg1, type);
91,263✔
1465
   LLVMValueRef ptr   = cgen_coerce_value(obj, cgb, ir->arg2, LLVM_PTR);
91,263✔
1466

1467
#ifdef LLVM_HAS_OPAQUE_POINTERS
1468
   LLVMValueRef store = LLVMBuildStore(obj->builder, value, ptr);
1469
#else
1470
   LLVMTypeRef ptr_type = LLVMPointerType(LLVMTypeOf(value), 0);
91,263✔
1471
   LLVMValueRef cast = LLVMBuildPointerCast(obj->builder, ptr, ptr_type, "");
91,263✔
1472
   LLVMValueRef store = LLVMBuildStore(obj->builder, value, cast);
91,263✔
1473
#endif
1474

1475
   LLVMSetAlignment(store, 1 << ir->size);
91,263✔
1476
}
91,263✔
1477

1478
static void cgen_op_load(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
160,454✔
1479
{
1480
   LLVMValueRef ptr = cgen_coerce_value(obj, cgb, ir->arg1, LLVM_PTR);
160,454✔
1481

1482
   llvm_type_t type = mask_test(&cgb->func->ptr_mask, ir->result)
160,454✔
1483
      ? LLVM_PTR : LLVM_INT8 + ir->size;
160,454✔
1484

1485
#ifndef LLVM_HAS_OPAQUE_POINTERS
1486
   LLVMTypeRef ptr_type = LLVMPointerType(obj->types[type], 0);
160,454✔
1487
   ptr = LLVMBuildPointerCast(obj->builder, ptr, ptr_type, "");
160,454✔
1488
#endif
1489

1490
   if (type == LLVM_INT64) {
160,454✔
1491
      LLVMValueRef value = LLVMBuildLoad2(obj->builder, obj->types[type],
77,333✔
1492
                                          ptr, cgen_reg_name(ir->result));
77,333✔
1493
      LLVMSetAlignment(value, 1 << ir->size);
77,333✔
1494
      cgb->outregs[ir->result] = value;
77,333✔
1495
   }
1496
   else {
1497
      LLVMValueRef tmp =
83,121✔
1498
         LLVMBuildLoad2(obj->builder, obj->types[type], ptr, "");
83,121✔
1499
      LLVMSetAlignment(tmp, 1 << ir->size);
83,121✔
1500
      if (ir->op == J_ULOAD)
83,121✔
1501
         cgen_zext_result(obj, cgb, ir, tmp);
14,412✔
1502
      else
1503
         cgen_sext_result(obj, cgb, ir, tmp);
68,709✔
1504
   }
1505
}
160,454✔
1506

1507
static void cgen_op_add(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
73,863✔
1508
{
1509
   llvm_fn_t fn = LLVM_LAST_FN;
73,863✔
1510
   if (ir->cc == JIT_CC_O)
73,863✔
1511
      fn = LLVM_ADD_OVERFLOW_S8 + ir->size;
1,458✔
1512
   else if (ir->cc == JIT_CC_C)
72,405✔
1513
      fn = LLVM_ADD_OVERFLOW_U8 + ir->size;
12✔
1514

1515
   if (fn != LLVM_LAST_FN) {
1,470✔
1516
      llvm_type_t type = LLVM_INT8 + ir->size;
1,470✔
1517
      LLVMValueRef arg1 = cgen_coerce_value(obj, cgb, ir->arg1, type);
1,470✔
1518
      LLVMValueRef arg2 = cgen_coerce_value(obj, cgb, ir->arg2, type);
1,470✔
1519

1520
      LLVMValueRef args[] = { arg1, arg2 };
1,470✔
1521
      LLVMValueRef pair = llvm_call_fn(obj, fn, args, 2);
1,470✔
1522

1523
      LLVMValueRef result = LLVMBuildExtractValue(obj->builder, pair, 0, "");
1,470✔
1524
      cgb->outflags = LLVMBuildExtractValue(obj->builder, pair, 1, "FLAGS");
1,470✔
1525

1526
      if (ir->cc == JIT_CC_C)
1,470✔
1527
         cgen_zext_result(obj, cgb, ir, result);
12✔
1528
      else
1529
         cgen_sext_result(obj, cgb, ir, result);
1,458✔
1530
   }
1531
   else {
1532
      LLVMValueRef arg1 = cgen_get_value(obj, cgb, ir->arg1);
72,393✔
1533
      LLVMValueRef arg2 = cgen_get_value(obj, cgb, ir->arg2);
72,393✔
1534

1535
      if (llvm_is_ptr(arg1)) {
72,393✔
1536
         LLVMValueRef indexes[] = { arg2 };
5,705✔
1537
         LLVMValueRef ptr = LLVMBuildGEP2(obj->builder, obj->types[LLVM_INT8],
5,705✔
1538
                                          arg1, indexes, 1, "");
1539
         cgen_pointer_result(obj, cgb, ir, ptr);
5,705✔
1540
      }
1541
      else if (mask_test(&cgb->func->ptr_mask, ir->result)) {
66,688✔
1542
         LLVMValueRef base =
16,560✔
1543
            LLVMBuildIntToPtr(obj->builder, arg1, obj->types[LLVM_PTR], "");
16,560✔
1544
         LLVMValueRef indexes[] = { arg2 };
16,560✔
1545
         LLVMValueRef ptr = LLVMBuildGEP2(obj->builder, obj->types[LLVM_INT8],
16,560✔
1546
                                          base, indexes, 1, "");
1547
         cgen_pointer_result(obj, cgb, ir, ptr);
16,560✔
1548
      }
1549
      else
1550
         cgb->outregs[ir->result] = LLVMBuildAdd(obj->builder, arg1, arg2,
50,128✔
1551
                                                 cgen_reg_name(ir->result));
1552
   }
1553
}
73,863✔
1554

1555
static void cgen_op_sub(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
28,952✔
1556
{
1557
   llvm_fn_t fn = LLVM_LAST_FN;
28,952✔
1558
   if (ir->cc == JIT_CC_O)
28,952✔
1559
      fn = LLVM_SUB_OVERFLOW_S8 + ir->size;
1,825✔
1560
   else if (ir->cc == JIT_CC_C)
27,127✔
UNCOV
1561
      fn = LLVM_SUB_OVERFLOW_U8 + ir->size;
×
1562

1563
   if (fn != LLVM_LAST_FN) {
1,825✔
1564
      llvm_type_t type = LLVM_INT8 + ir->size;
1,825✔
1565
      LLVMValueRef arg1 = cgen_coerce_value(obj, cgb, ir->arg1, type);
1,825✔
1566
      LLVMValueRef arg2 = cgen_coerce_value(obj, cgb, ir->arg2, type);
1,825✔
1567

1568
      LLVMValueRef args[] = { arg1, arg2 };
1,825✔
1569
      LLVMValueRef pair = llvm_call_fn(obj, fn, args, 2);
1,825✔
1570

1571
      LLVMValueRef result = LLVMBuildExtractValue(obj->builder, pair, 0, "");
1,825✔
1572
      cgb->outflags = LLVMBuildExtractValue(obj->builder, pair, 1, "FLAGS");
1,825✔
1573

1574
      if (ir->cc == JIT_CC_C)
1,825✔
UNCOV
1575
         cgen_zext_result(obj, cgb, ir, result);
×
1576
      else
1577
         cgen_sext_result(obj, cgb, ir, result);
1,825✔
1578
   }
1579
   else {
1580
      LLVMValueRef arg1 = cgen_get_value(obj, cgb, ir->arg1);
27,127✔
1581
      LLVMValueRef arg2 = cgen_get_value(obj, cgb, ir->arg2);
27,127✔
1582
      cgb->outregs[ir->result] = LLVMBuildSub(obj->builder, arg1, arg2,
27,127✔
1583
                                              cgen_reg_name(ir->result));
27,127✔
1584
   }
1585
}
28,952✔
1586

1587
static void cgen_op_mul(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
1,365✔
1588
{
1589
   llvm_fn_t fn = LLVM_LAST_FN;
1,365✔
1590
   if (ir->cc == JIT_CC_O)
1,365✔
1591
      fn = LLVM_MUL_OVERFLOW_S8 + ir->size;
232✔
1592
   else if (ir->cc == JIT_CC_C)
1,133✔
1593
      fn = LLVM_MUL_OVERFLOW_U8 + ir->size;
6✔
1594

1595
   if (fn != LLVM_LAST_FN) {
238✔
1596
      llvm_type_t type = LLVM_INT8 + ir->size;
238✔
1597
      LLVMValueRef arg1 = cgen_coerce_value(obj, cgb, ir->arg1, type);
238✔
1598
      LLVMValueRef arg2 = cgen_coerce_value(obj, cgb, ir->arg2, type);
238✔
1599

1600
      LLVMValueRef args[] = { arg1, arg2 };
238✔
1601
      LLVMValueRef pair = llvm_call_fn(obj, fn, args, 2);
238✔
1602

1603
      LLVMValueRef result = LLVMBuildExtractValue(obj->builder, pair, 0, "");
238✔
1604
      cgb->outflags = LLVMBuildExtractValue(obj->builder, pair, 1, "FLAGS");
238✔
1605

1606
      if (ir->cc == JIT_CC_C)
238✔
1607
         cgen_zext_result(obj, cgb, ir, result);
6✔
1608
      else
1609
         cgen_sext_result(obj, cgb, ir, result);
232✔
1610
   }
1611
   else {
1612
      LLVMValueRef arg1 = cgen_get_value(obj, cgb, ir->arg1);
1,127✔
1613
      LLVMValueRef arg2 = cgen_get_value(obj, cgb, ir->arg2);
1,127✔
1614
      cgb->outregs[ir->result] = LLVMBuildMul(obj->builder, arg1, arg2,
1,127✔
1615
                                              cgen_reg_name(ir->result));
1,127✔
1616
   }
1617
}
1,365✔
1618

1619
static void cgen_op_div(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
500✔
1620
{
1621
   LLVMValueRef arg1 = cgen_get_value(obj, cgb, ir->arg1);
500✔
1622
   LLVMValueRef arg2 = cgen_get_value(obj, cgb, ir->arg2);
500✔
1623

1624
   cgb->outregs[ir->result] = LLVMBuildSDiv(obj->builder, arg1, arg2,
500✔
1625
                                            cgen_reg_name(ir->result));
500✔
1626
}
500✔
1627

1628
static void cgen_op_rem(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
183✔
1629
{
1630
   LLVMValueRef arg1 = cgen_get_value(obj, cgb, ir->arg1);
183✔
1631
   LLVMValueRef arg2 = cgen_get_value(obj, cgb, ir->arg2);
183✔
1632

1633
   cgb->outregs[ir->result] = LLVMBuildSRem(obj->builder, arg1, arg2,
183✔
1634
                                            cgen_reg_name(ir->result));
183✔
1635
}
183✔
1636

1637
static void cgen_op_shl(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
9,052✔
1638
{
1639
   LLVMValueRef arg1 = cgen_get_value(obj, cgb, ir->arg1);
9,052✔
1640
   LLVMValueRef arg2 = cgen_get_value(obj, cgb, ir->arg2);
9,052✔
1641

1642
   cgb->outregs[ir->result] = LLVMBuildShl(obj->builder, arg1, arg2,
9,052✔
1643
                                           cgen_reg_name(ir->result));
9,052✔
1644
}
9,052✔
1645

1646
static void cgen_op_asr(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
17,909✔
1647
{
1648
   LLVMValueRef arg1 = cgen_get_value(obj, cgb, ir->arg1);
17,909✔
1649
   LLVMValueRef arg2 = cgen_get_value(obj, cgb, ir->arg2);
17,909✔
1650

1651
   cgb->outregs[ir->result] = LLVMBuildAShr(obj->builder, arg1, arg2,
17,909✔
1652
                                            cgen_reg_name(ir->result));
17,909✔
1653
}
17,909✔
1654

1655
static void cgen_op_fadd(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
245✔
1656
{
1657
   LLVMValueRef arg1 = cgen_coerce_value(obj, cgb, ir->arg1, LLVM_DOUBLE);
245✔
1658
   LLVMValueRef arg2 = cgen_coerce_value(obj, cgb, ir->arg2, LLVM_DOUBLE);
245✔
1659

1660
   LLVMValueRef real = LLVMBuildFAdd(obj->builder, arg1, arg2, "");
245✔
1661
   cgen_sext_result(obj, cgb, ir, real);
245✔
1662
}
245✔
1663

1664
static void cgen_op_fsub(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
266✔
1665
{
1666
   LLVMValueRef arg1 = cgen_coerce_value(obj, cgb, ir->arg1, LLVM_DOUBLE);
266✔
1667
   LLVMValueRef arg2 = cgen_coerce_value(obj, cgb, ir->arg2, LLVM_DOUBLE);
266✔
1668

1669
   LLVMValueRef real = LLVMBuildFSub(obj->builder, arg1, arg2, "");
266✔
1670
   cgen_sext_result(obj, cgb, ir, real);
266✔
1671
}
266✔
1672

1673
static void cgen_op_fmul(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
528✔
1674
{
1675
   LLVMValueRef arg1 = cgen_coerce_value(obj, cgb, ir->arg1, LLVM_DOUBLE);
528✔
1676
   LLVMValueRef arg2 = cgen_coerce_value(obj, cgb, ir->arg2, LLVM_DOUBLE);
528✔
1677

1678
   LLVMValueRef real = LLVMBuildFMul(obj->builder, arg1, arg2, "");
528✔
1679
   cgen_sext_result(obj, cgb, ir, real);
528✔
1680
}
528✔
1681

1682
static void cgen_op_fdiv(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
187✔
1683
{
1684
   LLVMValueRef arg1 = cgen_coerce_value(obj, cgb, ir->arg1, LLVM_DOUBLE);
187✔
1685
   LLVMValueRef arg2 = cgen_coerce_value(obj, cgb, ir->arg2, LLVM_DOUBLE);
187✔
1686

1687
   LLVMValueRef real = LLVMBuildFDiv(obj->builder, arg1, arg2, "");
187✔
1688
   cgen_sext_result(obj, cgb, ir, real);
187✔
1689
}
187✔
1690

1691
static void cgen_op_fneg(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
304✔
1692
{
1693
   LLVMValueRef arg1 = cgen_coerce_value(obj, cgb, ir->arg1, LLVM_DOUBLE);
304✔
1694

1695
   LLVMValueRef real = LLVMBuildFNeg(obj->builder, arg1, "");
304✔
1696
   cgen_sext_result(obj, cgb, ir, real);
304✔
1697
}
304✔
1698

1699
static void cgen_op_fcvtns(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
58✔
1700
{
1701
   LLVMValueRef arg1 = cgen_coerce_value(obj, cgb, ir->arg1, LLVM_DOUBLE);
58✔
1702

1703
   LLVMValueRef args[] = { llvm_real(obj, 0.5), arg1 };
58✔
1704
   LLVMValueRef half = llvm_call_fn(obj, LLVM_COPYSIGN_F64, args, 2);
58✔
1705
   LLVMValueRef rounded = LLVMBuildFAdd(obj->builder, arg1, half, "");
58✔
1706

1707
   cgb->outregs[ir->result] = LLVMBuildFPToSI(obj->builder, rounded,
58✔
1708
                                              obj->types[LLVM_INT64],
1709
                                              cgen_reg_name(ir->result));
58✔
1710
}
58✔
1711

1712
static void cgen_op_scvtf(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
152✔
1713
{
1714
   LLVMValueRef arg1 = cgen_get_value(obj, cgb, ir->arg1);
152✔
1715

1716
   LLVMValueRef real = LLVMBuildSIToFP(obj->builder, arg1,
152✔
1717
                                       obj->types[LLVM_DOUBLE], "");
1718
   cgen_sext_result(obj, cgb, ir, real);
152✔
1719
}
152✔
1720

1721
static void cgen_op_not(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
2,173✔
1722
{
1723
   LLVMValueRef arg1 = cgen_coerce_value(obj, cgb, ir->arg1, LLVM_INT1);
2,173✔
1724
   LLVMValueRef logical = LLVMBuildNot(obj->builder, arg1, "");
2,173✔
1725
   cgen_zext_result(obj, cgb, ir, logical);
2,173✔
1726
}
2,173✔
1727

1728
static void cgen_op_and(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
3,700✔
1729
{
1730
   LLVMValueRef arg1 = cgen_get_value(obj, cgb, ir->arg1);
3,700✔
1731
   LLVMValueRef arg2 = cgen_get_value(obj, cgb, ir->arg2);
3,700✔
1732

1733
   LLVMValueRef logical = LLVMBuildAnd(obj->builder, arg1, arg2, "");
3,700✔
1734
   cgen_zext_result(obj, cgb, ir, logical);
3,700✔
1735
}
3,700✔
1736

1737
static void cgen_op_or(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
1,590✔
1738
{
1739
   LLVMValueRef arg1 = cgen_get_value(obj, cgb, ir->arg1);
1,590✔
1740
   LLVMValueRef arg2 = cgen_get_value(obj, cgb, ir->arg2);
1,590✔
1741

1742
   LLVMValueRef logical = LLVMBuildOr(obj->builder, arg1, arg2, "");
1,590✔
1743
   cgen_zext_result(obj, cgb, ir, logical);
1,590✔
1744
}
1,590✔
1745

1746
static void cgen_op_xor(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
25,347✔
1747
{
1748
   LLVMValueRef arg1 = cgen_get_value(obj, cgb, ir->arg1);
25,347✔
1749
   LLVMValueRef arg2 = cgen_get_value(obj, cgb, ir->arg2);
25,347✔
1750

1751
   LLVMValueRef logical = LLVMBuildXor(obj->builder, arg1, arg2, "");
25,347✔
1752
   cgen_zext_result(obj, cgb, ir, logical);
25,347✔
1753
}
25,347✔
1754

1755
static void cgen_op_ret(llvm_obj_t *obj, jit_ir_t *ir)
39,508✔
1756
{
1757
   LLVMBuildRetVoid(obj->builder);
39,508✔
1758
}
39,508✔
1759

1760
static void cgen_op_jump(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
109,684✔
1761
{
1762
   if (ir->cc == JIT_CC_NONE) {
109,684✔
1763
      assert(cgb->source->out.count == 1);
26,925✔
1764
      LLVMBasicBlockRef dest =
53,850✔
1765
         cgb->func->blocks[jit_get_edge(&(cgb->source->out), 0)].bbref;
26,925✔
1766
      LLVMBuildBr(obj->builder, dest);
26,925✔
1767
   }
1768
   else if (ir->cc == JIT_CC_T) {
82,759✔
1769
      assert(cgb->source->out.count == 2);
66,627✔
1770
      LLVMBasicBlockRef dest_t =
133,254✔
1771
         cgb->func->blocks[jit_get_edge(&(cgb->source->out), 1)].bbref;
66,627✔
1772
      LLVMBasicBlockRef dest_f = (cgb + 1)->bbref;
66,627✔
1773
      LLVMBuildCondBr(obj->builder, cgb->outflags, dest_t, dest_f);
66,627✔
1774
   }
1775
   else if (ir->cc == JIT_CC_F) {
16,132✔
1776
      assert(cgb->source->out.count == 2);
16,132✔
1777
      LLVMBasicBlockRef dest_t =
32,264✔
1778
         cgb->func->blocks[jit_get_edge(&(cgb->source->out), 1)].bbref;
16,132✔
1779
      LLVMBasicBlockRef dest_f = (cgb + 1)->bbref;
16,132✔
1780
      LLVMBuildCondBr(obj->builder, cgb->outflags, dest_f, dest_t);
16,132✔
1781
   }
1782
   else
UNCOV
1783
      cgen_abort(cgb, ir, "unhandled jump condition code");
×
1784
}
109,684✔
1785

1786
static void cgen_op_cmp(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
127,813✔
1787
{
1788
   LLVMValueRef arg1 = cgen_get_value(obj, cgb, ir->arg1);
127,813✔
1789
   LLVMValueRef arg2 = cgen_get_value(obj, cgb, ir->arg2);
127,813✔
1790

1791
   const bool arg1_ptr = llvm_is_ptr(arg1);
127,813✔
1792
   const bool arg2_ptr = llvm_is_ptr(arg2);
127,813✔
1793

1794
   if (arg1_ptr && !arg2_ptr)
127,813✔
1795
      arg2 = LLVMBuildIntToPtr(obj->builder, arg2, obj->types[LLVM_PTR], "");
10,184✔
1796
   else if (!arg1_ptr && arg2_ptr)
117,629✔
1797
      arg1 = LLVMBuildIntToPtr(obj->builder, arg1, obj->types[LLVM_PTR], "");
9,486✔
1798

1799
   LLVMIntPredicate pred = cgen_int_pred(cgb, ir);
127,813✔
1800
   cgb->outflags = LLVMBuildICmp(obj->builder, pred, arg1, arg2, "FLAGS");
127,813✔
1801
}
127,813✔
1802

1803
static void cgen_op_ccmp(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
11,716✔
1804
{
1805
   LLVMValueRef arg1 = cgen_get_value(obj, cgb, ir->arg1);
11,716✔
1806
   LLVMValueRef arg2 = cgen_get_value(obj, cgb, ir->arg2);
11,716✔
1807

1808
   const bool arg1_ptr = llvm_is_ptr(arg1);
11,716✔
1809
   const bool arg2_ptr = llvm_is_ptr(arg2);
11,716✔
1810

1811
   if (arg1_ptr && !arg2_ptr)
11,716✔
UNCOV
1812
      arg2 = LLVMBuildIntToPtr(obj->builder, arg2, obj->types[LLVM_PTR], "");
×
1813
   else if (!arg1_ptr && arg2_ptr)
11,716✔
UNCOV
1814
      arg1 = LLVMBuildIntToPtr(obj->builder, arg1, obj->types[LLVM_PTR], "");
×
1815

1816
   LLVMIntPredicate pred = cgen_int_pred(cgb, ir);
11,716✔
1817
   LLVMValueRef cmp = LLVMBuildICmp(obj->builder, pred, arg1, arg2, "");
11,716✔
1818

1819
   cgb->outflags = LLVMBuildAnd(obj->builder, cgb->outflags, cmp, "FLAGS");
11,716✔
1820
}
11,716✔
1821

1822
static void cgen_op_fcmp(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
2,009✔
1823
{
1824
   LLVMValueRef arg1 = cgen_coerce_value(obj, cgb, ir->arg1, LLVM_DOUBLE);
2,009✔
1825
   LLVMValueRef arg2 = cgen_coerce_value(obj, cgb, ir->arg2, LLVM_DOUBLE);
2,009✔
1826

1827
   LLVMRealPredicate pred = cgen_real_pred(cgb, ir);
2,009✔
1828
   cgb->outflags = LLVMBuildFCmp(obj->builder, pred, arg1, arg2, "FLAGS");
2,009✔
1829
}
2,009✔
1830

1831
static void cgen_op_fccmp(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
350✔
1832
{
1833
   LLVMValueRef arg1 = cgen_coerce_value(obj, cgb, ir->arg1, LLVM_DOUBLE);
350✔
1834
   LLVMValueRef arg2 = cgen_coerce_value(obj, cgb, ir->arg2, LLVM_DOUBLE);
350✔
1835

1836
   LLVMRealPredicate pred = cgen_real_pred(cgb, ir);
350✔
1837
   LLVMValueRef cmp = LLVMBuildFCmp(obj->builder, pred, arg1, arg2, "");
350✔
1838

1839
   cgb->outflags = LLVMBuildAnd(obj->builder, cgb->outflags, cmp, "FLAGS");
350✔
1840
}
350✔
1841

1842
static void cgen_op_cset(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
17,735✔
1843
{
1844
   cgen_zext_result(obj, cgb, ir, cgb->outflags);
17,735✔
1845
}
17,735✔
1846

1847
static void cgen_op_csel(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
42,608✔
1848
{
1849
   LLVMValueRef arg1 = cgen_get_value(obj, cgb, ir->arg1);
42,608✔
1850
   LLVMValueRef arg2 = cgen_get_value(obj, cgb, ir->arg2);
42,608✔
1851

1852
   LLVMValueRef result =
42,608✔
1853
      LLVMBuildSelect(obj->builder, cgb->outflags, arg1, arg2, "");
42,608✔
1854

1855
   cgen_sext_result(obj, cgb, ir, result);
42,608✔
1856
}
42,608✔
1857

1858
static void cgen_op_call(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
36,867✔
1859
{
1860
   cgen_sync_irpos(obj, cgb, ir);
36,867✔
1861

1862
   jit_func_t *callee = jit_get_func(cgb->func->source->jit, ir->arg1.handle);
36,867✔
1863

1864
   LLVMValueRef entry = NULL, fptr = NULL;
36,867✔
1865
   if (cgb->func->mode == CGEN_AOT) {
36,867✔
1866
      cgen_reloc_t *reloc = cgen_find_reloc(cgb->func->relocs, RELOC_FUNC,
24,744✔
1867
                                            INT_MAX, ir->arg1.handle);
24,744✔
1868
      assert(reloc != NULL);
24,744✔
1869

1870
      LLVMValueRef array =
24,744✔
1871
         LLVMBuildStructGEP2(obj->builder, cgb->func->descr_type,
24,744✔
1872
                             cgb->func->descr, 4, "");
1873

1874
      LLVMValueRef indexes[] = {
24,744✔
1875
         llvm_intptr(obj, 0),
24,744✔
1876
         llvm_intptr(obj, reloc->nth)
24,744✔
1877
      };
1878
      LLVMValueRef elem =
24,744✔
1879
         LLVMBuildInBoundsGEP2(obj->builder, cgb->func->reloc_type, array,
24,744✔
1880
                               indexes, ARRAY_LEN(indexes), "");
1881
      LLVMValueRef ptr =
24,744✔
1882
         LLVMBuildStructGEP2(obj->builder, obj->types[LLVM_AOT_RELOC],
24,744✔
1883
                             elem, 1, "");
1884

1885
      fptr = LLVMBuildLoad2(obj->builder, obj->types[LLVM_PTR], ptr, "");
24,744✔
1886

1887
#if CLOSED_WORLD
1888
      // Do not generate direct calls for intrinsics
1889
      if (callee->entry == jit_interp) {
24,744✔
1890
         LOCAL_TEXT_BUF symbol = safe_symbol(callee->name);
15,092✔
1891
         entry = llvm_add_fn(obj, tb_get(symbol), obj->types[LLVM_ENTRY_FN]);
15,092✔
1892
      }
1893
#endif
1894
   }
1895
   else
1896
      fptr = llvm_ptr(obj, callee);
12,123✔
1897

1898
   if (entry == NULL) {
36,867✔
1899
      // Must have acquire semantics to synchronise with installing new code
1900
      entry = LLVMBuildLoad2(obj->builder, obj->types[LLVM_PTR], fptr, "entry");
21,775✔
1901
      LLVMSetAlignment(entry, sizeof(void *));
21,775✔
1902
      LLVMSetOrdering(entry, LLVMAtomicOrderingAcquire);
21,775✔
1903
   }
1904

1905
#ifndef LLVM_HAS_OPAQUE_POINTERS
1906
   LLVMTypeRef ptr_type = LLVMPointerType(obj->types[LLVM_ENTRY_FN], 0);
36,867✔
1907
   entry = LLVMBuildPointerCast(obj->builder, entry, ptr_type, "");
36,867✔
1908
#endif
1909

1910
   LLVMValueRef args[] = {
36,867✔
1911
      fptr,
1912
      PTR(cgb->func->anchor),
36,867✔
1913
      cgb->func->args,
36,867✔
1914
      cgb->func->tlab,
36,867✔
1915
   };
1916
   LLVMBuildCall2(obj->builder, obj->types[LLVM_ENTRY_FN], entry,
36,867✔
1917
                  args, ARRAY_LEN(args), "");
1918
}
36,867✔
1919

1920
static void cgen_op_lea(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
19,256✔
1921
{
1922
   LLVMValueRef ptr = cgen_get_value(obj, cgb, ir->arg1);
19,256✔
1923

1924
   if (llvm_is_ptr(ptr))
19,256✔
1925
      cgen_pointer_result(obj, cgb, ir, ptr);
8,418✔
1926
   else
1927
      cgen_zext_result(obj, cgb, ir, ptr);
10,838✔
1928
}
19,256✔
1929

1930
static void cgen_op_mov(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
47,918✔
1931
{
1932
   LLVMValueRef value = cgen_get_value(obj, cgb, ir->arg1);
47,918✔
1933
   cgen_sext_result(obj, cgb, ir, value);
47,918✔
1934
}
47,918✔
1935

1936
static void cgen_op_neg(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
5,979✔
1937
{
1938
   LLVMValueRef arg1 = cgen_get_value(obj, cgb, ir->arg1);
5,979✔
1939
   LLVMValueRef neg =
5,979✔
1940
      LLVMBuildNeg(obj->builder, arg1, cgen_reg_name(ir->result));
5,979✔
1941

1942
   cgb->outregs[ir->result] = neg;
5,979✔
1943
}
5,979✔
1944

1945
static void cgen_op_clamp(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
11,183✔
1946
{
1947
   LLVMValueRef arg1 = cgen_get_value(obj, cgb, ir->arg1);
11,183✔
1948
   LLVMValueRef zero = llvm_int64(obj, 0);
11,183✔
1949
   LLVMValueRef isneg = LLVMBuildICmp(obj->builder, LLVMIntSLT, arg1, zero, "");
11,183✔
1950
   LLVMValueRef clamp = LLVMBuildSelect(obj->builder, isneg, zero, arg1, "");
11,183✔
1951

1952
   cgb->outregs[ir->result] = clamp;
11,183✔
1953
}
11,183✔
1954

1955
static void cgen_macro_exp(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
94✔
1956
{
1957
   llvm_fn_t fn = LLVM_EXP_OVERFLOW_S64;
94✔
1958
   if (ir->cc == JIT_CC_O)
94✔
1959
      fn = LLVM_EXP_OVERFLOW_S8 + ir->size;
86✔
1960
   else if (ir->cc == JIT_CC_C)
8✔
1961
      fn = LLVM_EXP_OVERFLOW_U8 + ir->size;
8✔
1962

1963
   llvm_type_t type = LLVM_INT8 + ir->size;
94✔
1964
   LLVMValueRef arg1 = cgen_coerce_value(obj, cgb, ir->arg1, type);
94✔
1965
   LLVMValueRef arg2 = cgen_coerce_value(obj, cgb, ir->arg2, type);
94✔
1966

1967
   LLVMValueRef args[] = { arg1, arg2 };
94✔
1968
   LLVMValueRef pair = llvm_call_fn(obj, fn, args, 2);
94✔
1969

1970
   LLVMValueRef result = LLVMBuildExtractValue(obj->builder, pair, 0, "");
94✔
1971
   cgb->outflags = LLVMBuildExtractValue(obj->builder, pair, 1, "FLAGS");
94✔
1972

1973
   if (ir->cc == JIT_CC_C)
94✔
1974
      cgen_zext_result(obj, cgb, ir, result);
8✔
1975
   else
1976
      cgen_sext_result(obj, cgb, ir, result);
86✔
1977
}
94✔
1978

1979
static void cgen_macro_fexp(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
63✔
1980
{
1981
   LLVMValueRef arg1 = cgen_coerce_value(obj, cgb, ir->arg1, LLVM_DOUBLE);
63✔
1982
   LLVMValueRef arg2 = cgen_coerce_value(obj, cgb, ir->arg2, LLVM_DOUBLE);
63✔
1983

1984
   LLVMValueRef args[] = { arg1, arg2 };
63✔
1985
   LLVMValueRef real = llvm_call_fn(obj, LLVM_POW_F64, args, 2);
63✔
1986

1987
   cgen_sext_result(obj, cgb, ir, real);
63✔
1988
}
63✔
1989

1990
static void cgen_macro_copy(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
3,168✔
1991
{
1992
   LLVMValueRef count = cgb->outregs[ir->result];
3,168✔
1993
   LLVMValueRef dest  = cgen_coerce_value(obj, cgb, ir->arg1, LLVM_PTR);
3,168✔
1994
   LLVMValueRef src   = cgen_coerce_value(obj, cgb, ir->arg2, LLVM_PTR);
3,168✔
1995

1996
#ifdef LLVM_HAS_OPAQUE_POINTERS
1997
   if (LLVMIsConstant(count) && LLVMConstIntGetZExtValue(count) <= 64) {
1998
      LLVMValueRef args[] = {
1999
         dest,
2000
         src,
2001
         count,
2002
         llvm_int1(obj, 0),
2003
      };
2004
      llvm_call_fn(obj, LLVM_MEMCPY_INLINE, args, ARRAY_LEN(args));
2005
   }
2006
   else
2007
#endif
2008
      LLVMBuildMemCpy(obj->builder, dest, 0, src, 0, count);
3,168✔
2009
}
3,168✔
2010

2011
static void cgen_macro_move(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
7,515✔
2012
{
2013
   LLVMValueRef count = cgb->outregs[ir->result];
7,515✔
2014
   LLVMValueRef dest  = cgen_coerce_value(obj, cgb, ir->arg1, LLVM_PTR);
7,515✔
2015
   LLVMValueRef src   = cgen_coerce_value(obj, cgb, ir->arg2, LLVM_PTR);
7,515✔
2016

2017
   LLVMBuildMemMove(obj->builder, dest, 0, src, 0, count);
7,515✔
2018
}
7,515✔
2019

2020
static void cgen_macro_bzero(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
3,212✔
2021
{
2022
   LLVMValueRef count = cgb->outregs[ir->result];
3,212✔
2023
   LLVMValueRef dest  = cgen_coerce_value(obj, cgb, ir->arg1, LLVM_PTR);
3,212✔
2024

2025
#ifdef LLVM_HAS_OPAQUE_POINTERS
2026
   if (LLVMIsConstant(count) && LLVMConstIntGetZExtValue(count) <= 64) {
2027
      LLVMValueRef args[] = {
2028
         dest,
2029
         llvm_int8(obj, 0),
2030
         count,
2031
         llvm_int1(obj, 0),
2032
      };
2033
      llvm_call_fn(obj, LLVM_MEMSET_INLINE, args, ARRAY_LEN(args));
2034
   }
2035
   else
2036
#endif
2037
      LLVMBuildMemSet(obj->builder, PTR(dest), llvm_int8(obj, 0), count, 0);
3,212✔
2038
}
3,212✔
2039

2040
static void cgen_macro_memset(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
1,187✔
2041
{
2042
   LLVMValueRef count = cgb->outregs[ir->result];
1,187✔
2043
   LLVMValueRef dest  = cgen_coerce_value(obj, cgb, ir->arg1, LLVM_PTR);
1,187✔
2044
   LLVMValueRef value = cgen_coerce_value(obj, cgb, ir->arg2,
2,374✔
2045
                                          LLVM_INT8 + ir->size);
1,187✔
2046

2047
   if (ir->size == JIT_SZ_8) {
1,187✔
2048
#ifdef LLVM_HAS_OPAQUE_POINTERSS
2049
      if (LLVMIsConstant(count) && LLVMConstIntGetZExtValue(count) <= 64) {
2050
         LLVMValueRef args[] = {
2051
            dest,
2052
            value,
2053
            count,
2054
            llvm_int1(obj, 0),
2055
         };
2056
         llvm_call_fn(obj, LLVM_MEMSET_INLINE, args, ARRAY_LEN(args));
2057
      }
2058
      else
2059
#endif
2060
         LLVMBuildMemSet(obj->builder, PTR(dest), value, count, 0);
653✔
2061
   }
2062
   else {
2063
      LLVMValueRef args[] = { dest, value, count, };
534✔
2064
      llvm_call_fn(obj, LLVM_MEMSET_U8 + ir->size, args, ARRAY_LEN(args));
534✔
2065
   }
2066
}
1,187✔
2067

2068
static void cgen_macro_exit(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
87,411✔
2069
{
2070
   cgen_sync_irpos(obj, cgb, ir);
87,411✔
2071

2072
   switch (ir->arg1.exit) {
87,411✔
2073
   case JIT_EXIT_SCHED_WAVEFORM:
7,123✔
2074
      {
2075
         LLVMValueRef args[] = {
7,123✔
2076
            PTR(cgb->func->anchor),
7,123✔
2077
            cgb->func->args,
7,123✔
2078
            cgb->func->tlab,
7,123✔
2079
         };
2080
         llvm_call_fn(obj, LLVM_SCHED_WAVEFORM, args, ARRAY_LEN(args));
7,123✔
2081
      }
2082
      break;
7,123✔
2083

2084
   case JIT_EXIT_TEST_EVENT:
233✔
2085
      {
2086
         LLVMValueRef args[] = {
233✔
2087
            PTR(cgb->func->anchor),
233✔
2088
            cgb->func->args,
233✔
2089
            cgb->func->tlab,
233✔
2090
         };
2091
         llvm_call_fn(obj, LLVM_TEST_EVENT, args, ARRAY_LEN(args));
233✔
2092
      }
2093
      break;
233✔
2094

2095
   case JIT_EXIT_LAST_EVENT:
22✔
2096
      {
2097
         LLVMValueRef args[] = {
22✔
2098
            PTR(cgb->func->anchor),
22✔
2099
            cgb->func->args,
22✔
2100
            cgb->func->tlab,
22✔
2101
         };
2102
         llvm_call_fn(obj, LLVM_LAST_EVENT, args, ARRAY_LEN(args));
22✔
2103
      }
2104
      break;
22✔
2105

2106
   case JIT_EXIT_SCHED_PROCESS:
3,527✔
2107
      {
2108
         LLVMValueRef args[] = {
3,527✔
2109
            PTR(cgb->func->anchor),
3,527✔
2110
            cgb->func->args,
3,527✔
2111
            cgb->func->tlab,
3,527✔
2112
         };
2113
         llvm_call_fn(obj, LLVM_SCHED_PROCESS, args, ARRAY_LEN(args));
3,527✔
2114
      }
2115
      break;
3,527✔
2116

2117
   default:
76,506✔
2118
      {
2119
         LLVMValueRef which = cgen_get_value(obj, cgb, ir->arg1);
76,506✔
2120

2121
         LLVMValueRef args[] = {
76,506✔
2122
            which,
2123
            PTR(cgb->func->anchor),
76,506✔
2124
            cgb->func->args,
76,506✔
2125
            cgb->func->tlab,
76,506✔
2126
         };
2127
         llvm_call_fn(obj, LLVM_DO_EXIT, args, ARRAY_LEN(args));
76,506✔
2128
      }
2129
      break;
76,506✔
2130
   }
2131
}
87,411✔
2132

2133
static void cgen_macro_galloc(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
403✔
2134
{
2135
   cgen_sync_irpos(obj, cgb, ir);
403✔
2136

2137
   LLVMValueRef size = cgen_get_value(obj, cgb, ir->arg1);
403✔
2138

2139
   LLVMValueRef args[] = {
403✔
2140
      LLVMBuildTrunc(obj->builder, size, obj->types[LLVM_INTPTR], ""),
403✔
2141
      cgb->func->anchor
403✔
2142
   };
2143
   LLVMValueRef ptr = llvm_call_fn(obj, LLVM_MSPACE_ALLOC, args,
403✔
2144
                                   ARRAY_LEN(args));
2145

2146
   cgen_pointer_result(obj, cgb, ir, ptr);
403✔
2147
}
403✔
2148

2149
static void cgen_macro_lalloc(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
16,280✔
2150
{
2151
   cgen_sync_irpos(obj, cgb, ir);
16,280✔
2152

2153
   LLVMValueRef size = cgen_get_value(obj, cgb, ir->arg1);
16,280✔
2154

2155
   LLVMValueRef args[] = {
16,280✔
2156
      cgb->func->tlab,
16,280✔
2157
      LLVMBuildTrunc(obj->builder, size, obj->types[LLVM_INTPTR], ""),
16,280✔
2158
      cgb->func->anchor
16,280✔
2159
   };
2160
   LLVMValueRef ptr = llvm_call_fn(obj, LLVM_TLAB_ALLOC, args,
16,280✔
2161
                                   ARRAY_LEN(args));
2162

2163
   cgen_pointer_result(obj, cgb, ir, ptr);
16,280✔
2164
}
16,280✔
2165

2166
static void cgen_macro_salloc(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
5,590✔
2167
{
2168
   LLVMBasicBlockRef old_bb = LLVMGetInsertBlock(obj->builder);
5,590✔
2169
   LLVMBasicBlockRef first_bb = LLVMGetFirstBasicBlock(cgb->func->llvmfn);
5,590✔
2170
   LLVMPositionBuilderAtEnd(obj->builder, first_bb);
5,590✔
2171

2172
   assert(ir->arg2.kind == JIT_VALUE_INT64);
5,590✔
2173

2174
   LLVMValueRef ptr;
5,590✔
2175
   if (ir->arg2.int64 <= 8)
5,590✔
2176
      ptr = LLVMBuildAlloca(obj->builder, obj->types[LLVM_INT64], "");
1,903✔
2177
   else
2178
      ptr = LLVMBuildArrayAlloca(obj->builder, obj->types[LLVM_INT8],
3,687✔
2179
                                 llvm_intptr(obj, ir->arg2.int64), "");
2180

2181
   LLVMPositionBuilderAtEnd(obj->builder, old_bb);
5,590✔
2182

2183
   cgen_pointer_result(obj, cgb, ir, ptr);
5,590✔
2184
}
5,590✔
2185

2186
static void cgen_macro_getpriv(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
15,244✔
2187
{
2188
   LLVMValueRef ptrptr;
15,244✔
2189
   if (cgb->func->mode == CGEN_JIT) {
15,244✔
2190
      jit_func_t *f = jit_get_func(cgb->func->source->jit, ir->arg1.handle);
6,105✔
2191
      ptrptr = llvm_ptr(obj, jit_get_privdata_ptr(f->jit, f));
6,105✔
2192
   }
2193
   else
2194
      ptrptr = cgen_load_from_reloc(obj, cgb->func, RELOC_PRIVDATA,
9,139✔
2195
                                    ir->arg1.handle);
9,139✔
2196

2197
#ifndef LLVM_HAS_OPAQUE_POINTERS
2198
   LLVMTypeRef ptr_type = LLVMPointerType(obj->types[LLVM_PTR], 0);
15,244✔
2199
   ptrptr = LLVMBuildPointerCast(obj->builder, ptrptr, ptr_type, "");
15,244✔
2200
#endif
2201

2202
   LLVMValueRef ptr =
15,244✔
2203
      LLVMBuildLoad2(obj->builder, obj->types[LLVM_PTR], ptrptr, "p2");
15,244✔
2204
   LLVMSetAlignment(ptr, sizeof(void *));
15,244✔
2205
   LLVMSetOrdering(ptr, LLVMAtomicOrderingAcquire);
15,244✔
2206

2207
   cgen_pointer_result(obj, cgb, ir, ptr);
15,244✔
2208
}
15,244✔
2209

2210
static void cgen_macro_putpriv(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
6,876✔
2211
{
2212
   LLVMValueRef value = cgen_coerce_value(obj, cgb, ir->arg2, LLVM_PTR);
6,876✔
2213

2214
   if (cgb->func->mode == CGEN_AOT) {
6,876✔
2215
      LLVMValueRef ptr = cgen_load_from_reloc(obj, cgb->func, RELOC_PRIVDATA,
7,010✔
2216
                                              ir->arg1.handle);
3,505✔
2217
#ifndef LLVM_HAS_OPAQUE_POINTERS
2218
      LLVMTypeRef ptr_type = LLVMPointerType(obj->types[LLVM_PTR], 0);
3,505✔
2219
      ptr = LLVMBuildPointerCast(obj->builder, ptr, ptr_type, "");
3,505✔
2220
#endif
2221

2222
      LLVMValueRef store = LLVMBuildStore(obj->builder, value, ptr);
3,505✔
2223
      LLVMSetAlignment(store, sizeof(void *));
3,505✔
2224
      LLVMSetOrdering(store, LLVMAtomicOrderingRelease);
3,505✔
2225
   }
2226
   else {
2227
      LLVMValueRef args[] = {
3,371✔
2228
         cgen_get_value(obj, cgb, ir->arg1),
3,371✔
2229
         value,
2230
      };
2231
      llvm_call_fn(obj, LLVM_PUTPRIV, args, ARRAY_LEN(args));
3,371✔
2232
   }
2233
}
6,876✔
2234

2235
static void cgen_macro_case(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
12,184✔
2236
{
2237
   jit_ir_t *first = cgb->func->source->irbuf + cgb->source->first;
12,184✔
2238
   if (ir > first && (ir - 1)->op == MACRO_CASE)
12,184✔
2239
      return;    // Combined into previous $CASE
2240

2241
   LLVMBasicBlockRef elsebb = (cgb + 1)->bbref;
3,081✔
2242

2243
   LLVMValueRef test = cgb->outregs[ir->result];
3,081✔
2244
   assert(test != NULL);
3,081✔
2245

2246
   jit_ir_t *last = cgb->func->source->irbuf + cgb->source->last;
3,081✔
2247

2248
   const int numcases = last - ir + 1;
3,081✔
2249
   assert(cgb->source->out.count == numcases + 1);
3,081✔
2250

2251
   LLVMValueRef stmt = LLVMBuildSwitch(obj->builder, test, elsebb, numcases);
3,081✔
2252

2253
   for (int nth = 0; nth < numcases; ir++, nth++) {
15,265✔
2254
      assert(ir->op == MACRO_CASE);
12,184✔
2255

2256
      LLVMValueRef onval = cgen_get_value(obj, cgb, ir->arg1);
12,184✔
2257
      LLVMBasicBlockRef dest =
24,368✔
2258
         cgb->func->blocks[jit_get_edge(&(cgb->source->out), nth + 1)].bbref;
12,184✔
2259

2260
      LLVMAddCase(stmt, onval, dest);
12,184✔
2261
   }
2262
}
2263

2264
static void cgen_macro_trim(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
2,487✔
2265
{
2266
   LLVMValueRef watermark_ptr = LLVMBuildStructGEP2(obj->builder,
4,974✔
2267
                                                    obj->types[LLVM_ANCHOR],
2268
                                                    cgb->func->anchor, 3, "");
2,487✔
2269
   LLVMValueRef watermark = LLVMBuildLoad2(obj->builder,
2,487✔
2270
                                           obj->types[LLVM_INT32],
2271
                                           watermark_ptr, "");
2272
   LLVMValueRef alloc_ptr = LLVMBuildStructGEP2(obj->builder,
4,974✔
2273
                                                obj->types[LLVM_TLAB],
2274
                                                cgb->func->tlab, 2, "");
2,487✔
2275
   LLVMBuildStore(obj->builder, watermark, alloc_ptr);
2,487✔
2276
}
2,487✔
2277

2278
static void cgen_macro_reexec(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
176✔
2279
{
2280
   LLVMValueRef fptr = LLVMGetParam(cgb->func->llvmfn, 0);
176✔
2281

2282
   // Must have acquire semantics to synchronise with installing new code
2283
   LLVMValueRef entry =
176✔
2284
      LLVMBuildLoad2(obj->builder, obj->types[LLVM_PTR], fptr, "entry");
176✔
2285
   LLVMSetAlignment(entry, sizeof(void *));
176✔
2286
   LLVMSetOrdering(entry, LLVMAtomicOrderingAcquire);
176✔
2287

2288
#ifndef LLVM_HAS_OPAQUE_POINTERS
2289
   LLVMTypeRef ptr_type = LLVMPointerType(obj->types[LLVM_ENTRY_FN], 0);
176✔
2290
   entry = LLVMBuildPointerCast(obj->builder, entry, ptr_type, "");
176✔
2291
#endif
2292

2293
   LLVMValueRef args[] = {
176✔
2294
      fptr,
2295
      LLVMGetParam(cgb->func->llvmfn, 1),
176✔
2296
      cgb->func->args,
176✔
2297
      cgb->func->tlab,
176✔
2298
   };
2299
   LLVMValueRef call = LLVMBuildCall2(obj->builder, obj->types[LLVM_ENTRY_FN],
176✔
2300
                                      entry, args, ARRAY_LEN(args), "");
2301
   LLVMSetTailCall(call, true);
176✔
2302

2303
   LLVMBuildRetVoid(obj->builder);
176✔
2304
}
176✔
2305

2306
static void cgen_macro_sadd(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
1,929✔
2307
{
2308
   LLVMValueRef ptr = cgen_coerce_value(obj, cgb, ir->arg1, LLVM_PTR);
1,929✔
2309
   llvm_type_t type = LLVM_INT8 + ir->size;
1,929✔
2310

2311
#ifndef LLVM_HAS_OPAQUE_POINTERS
2312
   LLVMTypeRef ptr_type = LLVMPointerType(obj->types[type], 0);
1,929✔
2313
   ptr = LLVMBuildPointerCast(obj->builder, ptr, ptr_type, "");
1,929✔
2314
#endif
2315

2316
   LLVMValueRef cur = LLVMBuildLoad2(obj->builder, obj->types[type], ptr, "");
1,929✔
2317
   LLVMValueRef addend = cgen_coerce_value(obj, cgb, ir->arg2, type);
1,929✔
2318

2319
   LLVMValueRef args[] = { cur, addend };
1,929✔
2320
   LLVMValueRef sat = llvm_call_fn(obj, LLVM_ADD_SAT_U8 + ir->size, args, 2);
1,929✔
2321

2322
   LLVMBuildStore(obj->builder, sat, ptr);
1,929✔
2323
}
1,929✔
2324

2325
static void cgen_ir(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
2,322,203✔
2326
{
2327
   switch (ir->op) {
2,322,203✔
2328
   case J_RECV:
100,364✔
2329
      cgen_op_recv(obj, cgb, ir);
100,364✔
2330
      break;
100,364✔
2331
   case J_SEND:
583,653✔
2332
      cgen_op_send(obj, cgb, ir);
583,653✔
2333
      break;
583,653✔
2334
   case J_STORE:
91,263✔
2335
      cgen_op_store(obj, cgb, ir);
91,263✔
2336
      break;
91,263✔
2337
   case J_LOAD:
160,454✔
2338
   case J_ULOAD:
2339
      cgen_op_load(obj, cgb, ir);
160,454✔
2340
      break;
160,454✔
2341
   case J_ADD:
73,863✔
2342
      cgen_op_add(obj, cgb, ir);
73,863✔
2343
      break;
73,863✔
2344
   case J_SUB:
28,952✔
2345
      cgen_op_sub(obj, cgb, ir);
28,952✔
2346
      break;
28,952✔
2347
   case J_MUL:
1,365✔
2348
      cgen_op_mul(obj, cgb, ir);
1,365✔
2349
      break;
1,365✔
2350
   case J_DIV:
500✔
2351
      cgen_op_div(obj, cgb, ir);
500✔
2352
      break;
500✔
2353
   case J_REM:
183✔
2354
      cgen_op_rem(obj, cgb, ir);
183✔
2355
      break;
183✔
2356
   case J_SHL:
9,052✔
2357
      cgen_op_shl(obj, cgb, ir);
9,052✔
2358
      break;
9,052✔
2359
   case J_ASR:
17,909✔
2360
      cgen_op_asr(obj, cgb, ir);
17,909✔
2361
      break;
17,909✔
2362
   case J_FADD:
245✔
2363
      cgen_op_fadd(obj, cgb, ir);
245✔
2364
      break;
245✔
2365
   case J_FSUB:
266✔
2366
      cgen_op_fsub(obj, cgb, ir);
266✔
2367
      break;
266✔
2368
   case J_FMUL:
528✔
2369
      cgen_op_fmul(obj, cgb, ir);
528✔
2370
      break;
528✔
2371
   case J_FDIV:
187✔
2372
      cgen_op_fdiv(obj, cgb, ir);
187✔
2373
      break;
187✔
2374
   case J_FNEG:
304✔
2375
      cgen_op_fneg(obj, cgb, ir);
304✔
2376
      break;
304✔
2377
   case J_FCVTNS:
58✔
2378
      cgen_op_fcvtns(obj, cgb, ir);
58✔
2379
      break;
58✔
2380
   case J_SCVTF:
152✔
2381
      cgen_op_scvtf(obj, cgb, ir);
152✔
2382
      break;
152✔
2383
   case J_NOT:
2,173✔
2384
      cgen_op_not(obj, cgb, ir);
2,173✔
2385
      break;
2,173✔
2386
   case J_AND:
3,700✔
2387
      cgen_op_and(obj, cgb, ir);
3,700✔
2388
      break;
3,700✔
2389
   case J_OR:
1,590✔
2390
      cgen_op_or(obj, cgb, ir);
1,590✔
2391
      break;
1,590✔
2392
   case J_XOR:
25,347✔
2393
      cgen_op_xor(obj, cgb, ir);
25,347✔
2394
      break;
25,347✔
2395
   case J_RET:
39,508✔
2396
      cgen_op_ret(obj, ir);
39,508✔
2397
      break;
39,508✔
2398
   case J_JUMP:
109,684✔
2399
      cgen_op_jump(obj, cgb, ir);
109,684✔
2400
      break;
109,684✔
2401
   case J_CMP:
127,813✔
2402
      cgen_op_cmp(obj, cgb, ir);
127,813✔
2403
      break;
127,813✔
2404
   case J_CCMP:
11,716✔
2405
      cgen_op_ccmp(obj, cgb, ir);
11,716✔
2406
      break;
11,716✔
2407
   case J_FCMP:
2,009✔
2408
      cgen_op_fcmp(obj, cgb, ir);
2,009✔
2409
      break;
2,009✔
2410
   case J_FCCMP:
350✔
2411
      cgen_op_fccmp(obj, cgb, ir);
350✔
2412
      break;
350✔
2413
   case J_CSET:
17,735✔
2414
      cgen_op_cset(obj, cgb, ir);
17,735✔
2415
      break;
17,735✔
2416
   case J_CSEL:
42,608✔
2417
      cgen_op_csel(obj, cgb, ir);
42,608✔
2418
      break;
42,608✔
2419
   case J_CALL:
36,867✔
2420
      cgen_op_call(obj, cgb, ir);
36,867✔
2421
      break;
36,867✔
2422
   case J_LEA:
19,256✔
2423
      cgen_op_lea(obj, cgb, ir);
19,256✔
2424
      break;
19,256✔
2425
   case J_MOV:
47,918✔
2426
      cgen_op_mov(obj, cgb, ir);
47,918✔
2427
      break;
47,918✔
2428
   case J_NEG:
5,979✔
2429
      cgen_op_neg(obj, cgb, ir);
5,979✔
2430
      break;
5,979✔
2431
   case J_CLAMP:
11,183✔
2432
      cgen_op_clamp(obj, cgb, ir);
11,183✔
2433
      break;
11,183✔
2434
   case J_DEBUG:
2435
      DWARF_ONLY(cgen_debug_loc(obj, cgb->func, &(ir->arg1.loc)));
2436
      break;
2437
   case J_TRAP:
2438
   case J_NOP:
2439
      break;
2440
   case MACRO_EXP:
94✔
2441
      cgen_macro_exp(obj, cgb, ir);
94✔
2442
      break;
94✔
2443
   case MACRO_FEXP:
63✔
2444
      cgen_macro_fexp(obj, cgb, ir);
63✔
2445
      break;
63✔
2446
   case MACRO_COPY:
3,168✔
2447
      cgen_macro_copy(obj, cgb, ir);
3,168✔
2448
      break;
3,168✔
2449
   case MACRO_MOVE:
7,515✔
2450
      cgen_macro_move(obj, cgb, ir);
7,515✔
2451
      break;
7,515✔
2452
   case MACRO_BZERO:
3,212✔
2453
      cgen_macro_bzero(obj, cgb, ir);
3,212✔
2454
      break;
3,212✔
2455
   case MACRO_MEMSET:
1,187✔
2456
      cgen_macro_memset(obj, cgb, ir);
1,187✔
2457
      break;
1,187✔
2458
   case MACRO_EXIT:
87,411✔
2459
      cgen_macro_exit(obj, cgb, ir);
87,411✔
2460
      break;
87,411✔
2461
   case MACRO_GALLOC:
403✔
2462
      cgen_macro_galloc(obj, cgb, ir);
403✔
2463
      break;
403✔
2464
   case MACRO_LALLOC:
16,280✔
2465
      cgen_macro_lalloc(obj, cgb, ir);
16,280✔
2466
      break;
16,280✔
2467
   case MACRO_SALLOC:
5,590✔
2468
      cgen_macro_salloc(obj, cgb, ir);
5,590✔
2469
      break;
5,590✔
2470
   case MACRO_GETPRIV:
15,244✔
2471
      cgen_macro_getpriv(obj, cgb, ir);
15,244✔
2472
      break;
15,244✔
2473
   case MACRO_PUTPRIV:
6,876✔
2474
      cgen_macro_putpriv(obj, cgb, ir);
6,876✔
2475
      break;
6,876✔
2476
   case MACRO_CASE:
12,184✔
2477
      cgen_macro_case(obj, cgb, ir);
12,184✔
2478
      break;
12,184✔
2479
   case MACRO_TRIM:
2,487✔
2480
      cgen_macro_trim(obj, cgb, ir);
2,487✔
2481
      break;
2,487✔
2482
   case MACRO_REEXEC:
176✔
2483
      cgen_macro_reexec(obj, cgb, ir);
176✔
2484
      break;
176✔
2485
   case MACRO_SADD:
1,929✔
2486
      cgen_macro_sadd(obj, cgb, ir);
1,929✔
2487
      break;
1,929✔
UNCOV
2488
   default:
×
UNCOV
2489
      cgen_abort(cgb, ir, "cannot generate LLVM for %s", jit_op_name(ir->op));
×
2490
   }
2491
}
2,322,203✔
2492

2493
static void cgen_basic_blocks(llvm_obj_t *obj, cgen_func_t *func,
22,213✔
2494
                              jit_cfg_t *cfg)
2495
{
2496
   func->blocks = xcalloc_array(cfg->nblocks, sizeof(cgen_block_t));
22,213✔
2497

2498
   for (int i = 0; i < cfg->nblocks; i++) {
239,150✔
2499
#ifdef DEBUG
2500
      char name[32];
216,937✔
2501
      checked_sprintf(name, sizeof(name), "BB%d", i);
216,937✔
2502
#else
2503
      const char *name = "";
2504
#endif
2505

2506
      cgen_block_t *cgb = &(func->blocks[i]);
216,937✔
2507
      cgb->bbref  = llvm_append_block(obj, func->llvmfn, name);
216,937✔
2508
      cgb->source = &(cfg->blocks[i]);
216,937✔
2509
      cgb->func   = func;
216,937✔
2510

2511
      cgb->inregs  = xcalloc_array(func->source->nregs, sizeof(LLVMValueRef));
216,937✔
2512
      cgb->outregs = xcalloc_array(func->source->nregs, sizeof(LLVMValueRef));
216,937✔
2513
   }
2514
}
22,213✔
2515

2516
static void cgen_frame_anchor(llvm_obj_t *obj, cgen_func_t *func)
22,213✔
2517
{
2518
   LLVMTypeRef type = obj->types[LLVM_ANCHOR];
22,213✔
2519
   func->anchor = LLVMBuildAlloca(obj->builder, type, "anchor");
22,213✔
2520

2521
   LLVMValueRef func_arg = LLVMGetParam(func->llvmfn, 0);
22,213✔
2522
   LLVMSetValueName(func_arg, "func");
22,213✔
2523

2524
   LLVMValueRef caller_arg = LLVMGetParam(func->llvmfn, 1);
22,213✔
2525
   LLVMSetValueName(caller_arg, "caller");
22,213✔
2526

2527
   LLVMValueRef caller_ptr = LLVMBuildStructGEP2(obj->builder, type,
22,213✔
2528
                                                 func->anchor, 0, "");
2529
   LLVMBuildStore(obj->builder, caller_arg, caller_ptr);
22,213✔
2530

2531
   LLVMValueRef func_ptr = LLVMBuildStructGEP2(obj->builder, type,
22,213✔
2532
                                               func->anchor, 1, "");
2533
   LLVMBuildStore(obj->builder, func_arg, func_ptr);
22,213✔
2534

2535
   LLVMValueRef irpos_ptr = LLVMBuildStructGEP2(obj->builder, type,
22,213✔
2536
                                                func->anchor, 2, "");
2537
   LLVMBuildStore(obj->builder, llvm_int32(obj, 0), irpos_ptr);
22,213✔
2538

2539
   LLVMValueRef watermark_ptr = LLVMBuildStructGEP2(obj->builder, type,
22,213✔
2540
                                                    func->anchor, 3, "");
2541
   LLVMValueRef alloc_ptr = LLVMBuildStructGEP2(obj->builder,
22,213✔
2542
                                                obj->types[LLVM_TLAB],
2543
                                                func->tlab, 2, "");
2544
   LLVMValueRef alloc = LLVMBuildLoad2(obj->builder, obj->types[LLVM_INT32],
22,213✔
2545
                                       alloc_ptr, "");
2546
   LLVMBuildStore(obj->builder, alloc, watermark_ptr);
22,213✔
2547
}
22,213✔
2548

2549
static void cgen_aot_cpool(llvm_obj_t *obj, cgen_func_t *func)
14,389✔
2550
{
2551
   jit_func_t *f = func->source;
14,389✔
2552

2553
   LOCAL_TEXT_BUF tb = tb_new();
28,778✔
2554
   tb_istr(tb, f->name);
14,389✔
2555
   tb_cat(tb, ".cpool");
14,389✔
2556

2557
   LLVMTypeRef array_type = LLVMArrayType(obj->types[LLVM_INT8], f->cpoolsz);
14,389✔
2558

2559
   LLVMValueRef global = LLVMAddGlobal(obj->module, array_type, tb_get(tb));
14,389✔
2560
   LLVMSetLinkage(global, LLVMPrivateLinkage);
14,389✔
2561
   LLVMSetGlobalConstant(global, true);
14,389✔
2562
   LLVMSetUnnamedAddr(global, true);
14,389✔
2563

2564
   LLVMValueRef *data LOCAL = xmalloc_array(f->cpoolsz, sizeof(LLVMValueRef));
14,389✔
2565
   for (int i = 0; i < f->cpoolsz; i++)
535,113✔
2566
      data[i] = llvm_int8(obj, f->cpool[i]);
520,724✔
2567

2568
   LLVMValueRef init =
14,389✔
2569
      LLVMConstArray(obj->types[LLVM_INT8], data, f->cpoolsz);
14,389✔
2570
   LLVMSetInitializer(global, init);
14,389✔
2571

2572
   func->cpool = global;
14,389✔
2573
   func->cpool_type = array_type;
14,389✔
2574
}
14,389✔
2575

2576
static LLVMValueRef cgen_debug_irbuf(llvm_obj_t *obj, jit_func_t *f)
14,389✔
2577
{
2578
   LOCAL_TEXT_BUF tb = tb_new();
28,778✔
2579
   tb_istr(tb, f->name);
14,389✔
2580
   tb_cat(tb, ".debug");
14,389✔
2581

2582
   size_t size = 0;
14,389✔
2583
   uint8_t *buf LOCAL = NULL;
28,778✔
2584
   pack_writer_emit(obj->pack_writer, f->jit, f->handle, &buf, &size);
14,389✔
2585

2586
   LLVMValueRef *data LOCAL = xmalloc_array(size, sizeof(LLVMValueRef));
14,389✔
2587
   for (size_t i = 0; i < size; i++)
5,582,386✔
2588
      data[i] = llvm_int8(obj, buf[i]);
5,567,997✔
2589

2590
   LLVMTypeRef array_type = LLVMArrayType(obj->types[LLVM_INT8], size);
14,389✔
2591

2592
   LLVMValueRef global = LLVMAddGlobal(obj->module, array_type, tb_get(tb));
14,389✔
2593
   LLVMSetLinkage(global, LLVMPrivateLinkage);
14,389✔
2594
   LLVMSetGlobalConstant(global, true);
14,389✔
2595
   LLVMSetUnnamedAddr(global, true);
14,389✔
2596

2597
   LLVMValueRef init = LLVMConstArray(obj->types[LLVM_INT8], data, size);
14,389✔
2598
   LLVMSetInitializer(global, init);
14,389✔
2599

2600
   return global;
14,389✔
2601
}
2602

2603
static LLVMValueRef cgen_reloc_str(llvm_obj_t *obj, const char *str)
26,547✔
2604
{
2605
   const unsigned off = pack_writer_get_string(obj->pack_writer, str);
26,547✔
2606
   return llvm_intptr(obj, off);
26,547✔
2607
}
2608

2609
static void cgen_aot_descr(llvm_obj_t *obj, cgen_func_t *func)
14,389✔
2610
{
2611
   LLVMValueRef irbuf = cgen_debug_irbuf(obj, func->source);
14,389✔
2612

2613
   A(cgen_reloc_t) relocs = AINIT;
14,389✔
2614

2615
   for (int i = 0; i < func->source->nirs; i++) {
1,608,666✔
2616
      jit_ir_t *ir = &(func->source->irbuf[i]);
1,594,277✔
2617
      if (ir->op == J_CALL || ir->op == MACRO_GETPRIV
1,594,277✔
2618
          || ir->op == MACRO_PUTPRIV) {
1,560,394✔
2619
         // Special handling of JIT_VALUE_HANDLE arguments
2620
         reloc_kind_t kind = ir->op == J_CALL ? RELOC_FUNC : RELOC_PRIVDATA;
37,388✔
2621
         if (cgen_find_reloc(relocs.items, kind, relocs.count,
37,388✔
2622
                             ir->arg1.handle) == NULL) {
37,388✔
2623
            jit_func_t *f = jit_get_func(func->source->jit, ir->arg1.handle);
25,925✔
2624
            const cgen_reloc_t r = {
51,850✔
2625
               .kind = kind,
2626
               .str  = cgen_reloc_str(obj, istr(f->name)),
25,925✔
2627
               .key  = ir->arg1.handle,
25,925✔
2628
               .nth  = relocs.count,
25,925✔
2629
            };
2630
            APUSH(relocs, r);
25,925✔
2631
         }
2632
      }
2633
      else {
2634
         jit_value_t args[2] = { ir->arg1, ir->arg2 };
1,556,889✔
2635
         for (int j = 0; j < ARRAY_LEN(args); j++) {
4,670,667✔
2636
            if (args[j].kind == JIT_VALUE_HANDLE
3,113,778✔
2637
                && args[j].handle != JIT_HANDLE_INVALID) {
1,596✔
2638
               if (cgen_find_reloc(relocs.items, RELOC_HANDLE, relocs.count,
1,513✔
2639
                                   args[j].handle) == NULL) {
2640
                  ident_t name = jit_get_name(func->source->jit,
622✔
2641
                                              args[j].handle);
2642

2643
                  const cgen_reloc_t r = {
1,244✔
2644
                     .kind = RELOC_HANDLE,
2645
                     .str  = cgen_reloc_str(obj, istr(name)),
622✔
2646
                     .key  = args[j].handle,
622✔
2647
                     .nth  = relocs.count,
622✔
2648
                  };
2649
                  APUSH(relocs, r);
622✔
2650
               }
2651
            }
2652
            else if (args[j].kind == JIT_ADDR_COVER) {
3,112,265✔
2653
               if (cgen_find_reloc(relocs.items, RELOC_COVER,
1,567✔
2654
                                   relocs.count, 0) == NULL) {
1,567✔
2655
                  const cgen_reloc_t r = {
217✔
2656
                     .kind = RELOC_COVER,
2657
                     .nth  = relocs.count,
2658
                  };
2659
                  APUSH(relocs, r);
3,113,778✔
2660
               }
2661
            }
2662
         }
2663
      }
2664
   }
2665

2666
   APUSH(relocs, (cgen_reloc_t){ .kind = RELOC_NULL });
14,389✔
2667
   func->relocs = relocs.items;
14,389✔
2668

2669
   func->reloc_type = LLVMArrayType(obj->types[LLVM_AOT_RELOC], relocs.count);
14,389✔
2670

2671
   LLVMValueRef *reloc_elems LOCAL =
28,778✔
2672
      xmalloc_array(relocs.count, sizeof(LLVMValueRef));
14,389✔
2673

2674
   for (int i = 0; i < relocs.count; i++) {
55,542✔
2675
      LLVMValueRef fields[] = {
41,153✔
2676
         llvm_int32(obj, relocs.items[i].kind),
41,153✔
2677
         relocs.items[i].str ?: llvm_intptr(obj, 0)
41,153✔
2678
      };
2679
      reloc_elems[i] = LLVMConstNamedStruct(obj->types[LLVM_AOT_RELOC],
41,153✔
2680
                                            fields, ARRAY_LEN(fields));
2681
   }
2682

2683
   LLVMValueRef reloc_array = LLVMConstArray(obj->types[LLVM_AOT_RELOC],
14,389✔
2684
                                             reloc_elems, relocs.count);
2685

2686
   LLVMTypeRef ftypes[] = {
14,389✔
2687
      obj->types[LLVM_PTR],     // Entry function
14,389✔
2688
      obj->types[LLVM_PTR],     // String table
2689
      obj->types[LLVM_PTR],     // JIT pack buffer
2690
      obj->types[LLVM_PTR],     // Constant pool
2691
      func->reloc_type          // Relocations list
14,389✔
2692
   };
2693
   func->descr_type = LLVMStructTypeInContext(obj->context, ftypes,
14,389✔
2694
                                              ARRAY_LEN(ftypes), false);
2695

2696
   char *name LOCAL = xasprintf("%s.descr", func->name);
28,778✔
2697
   func->descr = LLVMAddGlobal(obj->module, func->descr_type, name);
14,389✔
2698
#ifdef IMPLIB_REQUIRED
2699
   LLVMSetDLLStorageClass(func->descr, LLVMDLLExportStorageClass);
2700
#endif
2701

2702
   LLVMValueRef fields[] = {
14,389✔
2703
      PTR(func->llvmfn),
14,389✔
2704
      PTR(obj->strtab),
14,389✔
2705
      PTR(irbuf),
14,389✔
2706
      PTR(func->cpool),
14,389✔
2707
      reloc_array,
2708
   };
2709
   LLVMValueRef init = LLVMConstNamedStruct(func->descr_type,
14,389✔
2710
                                            fields, ARRAY_LEN(fields));
2711
   LLVMSetInitializer(func->descr, init);
14,389✔
2712
}
14,389✔
2713

2714
#if ENABLE_DWARF
2715
static LLVMMetadataRef cgen_debug_file(llvm_obj_t *obj, const loc_t *loc)
2716
{
2717
   const char *file_path = loc_file_str(loc) ?: "";
2718

2719
   char *basec LOCAL = xstrdup(file_path);
2720
   char *dirc LOCAL = xstrdup(file_path);
2721

2722
   const char *file = basename(basec);
2723
   const size_t file_len = strlen(file);
2724

2725
   const char *dir = dirname(dirc);
2726
   const size_t dir_len = strlen(dir);
2727

2728
   return LLVMDIBuilderCreateFile(obj->debuginfo, file, file_len, dir, dir_len);
2729
}
2730
#endif
2731

2732
static void cgen_must_be_pointer(cgen_func_t *func, jit_value_t value)
285,100✔
2733
{
2734
   switch (value.kind) {
285,100✔
2735
   case JIT_VALUE_REG:
279,910✔
2736
   case JIT_ADDR_REG:
2737
      mask_set(&(func->ptr_mask), value.reg);
279,910✔
2738
      break;
2739
   default:
2740
      break;
2741
   }
2742
}
285,100✔
2743

2744
static void cgen_pointer_mask(cgen_func_t *func)
22,213✔
2745
{
2746
   mask_init(&(func->ptr_mask), func->source->nregs);
22,213✔
2747

2748
   for (int i = 0; i < func->source->nirs; i++) {
2,344,416✔
2749
      jit_ir_t *ir = &(func->source->irbuf[i]);
2,322,203✔
2750

2751
      switch (ir->op) {
2,322,203✔
2752
      case J_LOAD:
165,595✔
2753
      case J_ULOAD:
2754
      case MACRO_BZERO:
2755
      case MACRO_SADD:
2756
         cgen_must_be_pointer(func, ir->arg1);
165,595✔
2757
         break;
165,595✔
2758
      case J_STORE:
98,139✔
2759
      case MACRO_PUTPRIV:
2760
         cgen_must_be_pointer(func, ir->arg2);
98,139✔
2761
         break;
98,139✔
2762
      case MACRO_COPY:
10,683✔
2763
      case MACRO_MOVE:
2764
         cgen_must_be_pointer(func, ir->arg1);
10,683✔
2765
         cgen_must_be_pointer(func, ir->arg2);
10,683✔
2766
         break;
10,683✔
2767
      case J_ADD:
121,781✔
2768
      case J_MOV:
2769
         // Propagate pointer argument to result
2770
         if (ir->arg1.kind == JIT_VALUE_REG
121,781✔
2771
             && mask_test(&(func->ptr_mask), ir->arg1.reg))
109,135✔
2772
            mask_set(&(func->ptr_mask), ir->result);
19,259✔
2773
         break;
2774
      case J_LEA:
56,773✔
2775
      case MACRO_GETPRIV:
2776
      case MACRO_LALLOC:
2777
      case MACRO_SALLOC:
2778
      case MACRO_GALLOC:
2779
         mask_set(&(func->ptr_mask), ir->result);
56,773✔
2780
         break;
2781
      default:
2782
         break;
2783
      }
2784
   }
2785
}
22,213✔
2786

2787
static void cgen_cache_args(llvm_obj_t *obj, cgen_func_t *func)
22,213✔
2788
{
2789
   // Attempt to limit the number of getelementptr instructions
2790
   // generated for the argument array
2791

2792
   for (int i = 0; i < ARGCACHE_SIZE; i++) {
155,491✔
2793
      LLVMValueRef indexes[] = { llvm_int32(obj, i) };
133,278✔
2794
      func->argcache[i] = LLVMBuildInBoundsGEP2(obj->builder,
133,278✔
2795
                                                obj->types[LLVM_INT64],
2796
                                                func->args, indexes,
2797
                                                ARRAY_LEN(indexes),
2798
                                                cgen_arg_name(i));
2799
   }
2800

2801
   // Also cache the IR position pointer in the anchor
2802
   func->irpos = LLVMBuildStructGEP2(obj->builder,
22,213✔
2803
                                     obj->types[LLVM_ANCHOR],
2804
                                     func->anchor, 2, "irpos");
2805
}
22,213✔
2806

2807
static void cgen_fix_liveout_types(llvm_obj_t *obj, cgen_block_t *cgb)
216,937✔
2808
{
2809
   for (int j = 0; j < cgb->func->source->nregs; j++) {
27,684,484✔
2810
      if (!mask_test(&cgb->source->liveout, j))
27,467,547✔
2811
         continue;
26,301,997✔
2812

2813
      const bool want_ptr = mask_test(&cgb->func->ptr_mask, j);
1,165,550✔
2814
      if (want_ptr && !llvm_is_ptr(cgb->outregs[j])) {
1,165,550✔
2815
         LLVMValueRef last = LLVMGetBasicBlockTerminator(cgb->bbref);
19✔
2816
         if (last != NULL)
19✔
2817
            LLVMPositionBuilderBefore(obj->builder, last);
19✔
2818

2819
         cgb->outregs[j] = LLVMBuildIntToPtr(obj->builder,
38✔
2820
                                             cgb->outregs[j],
19✔
2821
                                             obj->types[LLVM_PTR],
2822
                                             cgen_reg_name(j));
2823
      }
2824
   }
2825
}
216,937✔
2826

2827
static void cgen_reexecute_guard(llvm_obj_t *obj, cgen_func_t *func,
22,213✔
2828
                                 jit_cfg_t *cfg)
2829
{
2830
   // Jump to the real entry if it may be modified at runtime
2831
   // (e.g. bound to a foreign function)
2832

2833
   bool has_reexec = false;
22,213✔
2834
   for (int i = 0; i < cfg->nblocks; i++) {
238,798✔
2835
      jit_block_t *bb = &(cfg->blocks[i]);
216,761✔
2836
      if (func->source->irbuf[bb->last].op == MACRO_REEXEC) {
216,761✔
2837
         has_reexec = true;
2838
         break;
2839
      }
2840
   }
2841

2842
   if (!has_reexec)
22,213✔
2843
      return;
22,037✔
2844

2845
   LLVMValueRef fptr = LLVMGetParam(func->llvmfn, 0);
176✔
2846

2847
   // Must have acquire semantics to synchronise with installing new code
2848
   LLVMValueRef entry =
176✔
2849
      LLVMBuildLoad2(obj->builder, obj->types[LLVM_PTR], fptr, "entry");
176✔
2850
   LLVMSetAlignment(entry, sizeof(void *));
176✔
2851
   LLVMSetOrdering(entry, LLVMAtomicOrderingAcquire);
176✔
2852

2853
   LLVMBasicBlockRef reexec_bb = llvm_append_block(obj, func->llvmfn, "reexec");
176✔
2854
   LLVMBasicBlockRef cont_bb = llvm_append_block(obj, func->llvmfn, "cont");
176✔
2855

2856
   LLVMValueRef changed = LLVMBuildICmp(obj->builder, LLVMIntNE, entry,
176✔
2857
                                        PTR(func->llvmfn), "changed");
2858
   LLVMBuildCondBr(obj->builder, changed, reexec_bb, cont_bb);
176✔
2859

2860
   LLVMPositionBuilderAtEnd(obj->builder, reexec_bb);
176✔
2861

2862
#ifndef LLVM_HAS_OPAQUE_POINTERS
2863
   LLVMTypeRef ptr_type = LLVMPointerType(obj->types[LLVM_ENTRY_FN], 0);
176✔
2864
   entry = LLVMBuildPointerCast(obj->builder, entry, ptr_type, "");
176✔
2865
#endif
2866

2867
   LLVMValueRef anchor = LLVMGetParam(func->llvmfn, 1);
176✔
2868

2869
   LLVMValueRef args[] = {
176✔
2870
      fptr,
2871
      anchor,
2872
      func->args,
176✔
2873
      func->tlab,
176✔
2874
   };
2875
   LLVMValueRef call = LLVMBuildCall2(obj->builder, obj->types[LLVM_ENTRY_FN],
176✔
2876
                                      entry, args, ARRAY_LEN(args), "");
2877
   LLVMSetTailCall(call, true);
176✔
2878

2879
   LLVMBuildRetVoid(obj->builder);
176✔
2880

2881
   LLVMPositionBuilderAtEnd(obj->builder, cont_bb);
176✔
2882
}
2883

2884
static void cgen_function(llvm_obj_t *obj, cgen_func_t *func)
22,213✔
2885
{
2886
   func->llvmfn = llvm_add_fn(obj, func->name, obj->types[LLVM_ENTRY_FN]);
22,213✔
2887
   llvm_add_func_attr(obj, func->llvmfn, FUNC_ATTR_NOUNWIND, -1);
22,213✔
2888
   llvm_add_func_attr(obj, func->llvmfn, FUNC_ATTR_UWTABLE, -1);
22,213✔
2889
   llvm_add_func_attr(obj, func->llvmfn, FUNC_ATTR_DLLEXPORT, -1);
22,213✔
2890
   llvm_add_func_attr(obj, func->llvmfn, FUNC_ATTR_READONLY, 1);
22,213✔
2891
   llvm_add_func_attr(obj, func->llvmfn, FUNC_ATTR_NONNULL, 1);
22,213✔
2892
   llvm_add_func_attr(obj, func->llvmfn, FUNC_ATTR_READONLY, 2);
22,213✔
2893
   llvm_add_func_attr(obj, func->llvmfn, FUNC_ATTR_NOALIAS, 3);
22,213✔
2894
   llvm_add_func_attr(obj, func->llvmfn, FUNC_ATTR_NONNULL, 3);
22,213✔
2895
   llvm_add_func_attr(obj, func->llvmfn, FUNC_ATTR_NOALIAS, 4);
22,213✔
2896

2897
#ifdef PRESERVE_FRAME_POINTER
2898
   llvm_add_func_attr(obj, func->llvmfn, FUNC_ATTR_PRESERVE_FP, -1);
2899
#endif
2900

2901
#if ENABLE_DWARF
2902
   LLVMMetadataRef file_ref =
2903
      cgen_debug_file(obj, &(func->source->object->loc));
2904

2905
   if (obj->debugcu == NULL) {
2906
      obj->debugcu = LLVMDIBuilderCreateCompileUnit(
2907
         obj->debuginfo, LLVMDWARFSourceLanguageAda83,
2908
         file_ref, PACKAGE, sizeof(PACKAGE) - 1,
2909
         opt_get_int(OPT_OPTIMISE), "", 0,
2910
         0, "", 0,
2911
         LLVMDWARFEmissionFull, 0, false, false
2912
#if LLVM_CREATE_CU_HAS_SYSROOT
2913
         , "/", 1, "", 0
2914
#endif
2915
      );
2916
   }
2917

2918
   LLVMMetadataRef dtype = LLVMDIBuilderCreateSubroutineType(
2919
      obj->debuginfo, file_ref, NULL, 0, 0);
2920
   const size_t namelen = strlen(func->name);
2921

2922
   func->debugmd = LLVMDIBuilderCreateFunction(
2923
      obj->debuginfo, obj->debugcu, func->name, namelen,
2924
      func->name, namelen, file_ref,
2925
      func->source->object->loc.first_line, dtype, true, true,
2926
      1, 0, opt_get_int(OPT_OPTIMISE));
2927

2928
   LLVMSetSubprogram(func->llvmfn, func->debugmd);
2929

2930
   cgen_debug_loc(obj, func, &(func->source->object->loc));
2931
#endif  // ENABLE_DWARF
2932

2933
   if (func->mode == CGEN_AOT) {
22,213✔
2934
      cgen_aot_cpool(obj, func);
14,389✔
2935
      cgen_aot_descr(obj, func);
14,389✔
2936
   }
2937

2938
   LLVMBasicBlockRef entry_bb = llvm_append_block(obj, func->llvmfn, "entry");
22,213✔
2939
   LLVMPositionBuilderAtEnd(obj->builder, entry_bb);
22,213✔
2940

2941
   func->args = LLVMGetParam(func->llvmfn, 2);
22,213✔
2942
   LLVMSetValueName(func->args, "args");
22,213✔
2943

2944
   func->tlab = LLVMGetParam(func->llvmfn, 3);
22,213✔
2945
   LLVMSetValueName(func->tlab, "tlab");
22,213✔
2946

2947
   cgen_frame_anchor(obj, func);
22,213✔
2948
   cgen_cache_args(obj, func);
22,213✔
2949

2950
   jit_cfg_t *cfg = func->cfg = jit_get_cfg(func->source);
22,213✔
2951
   cgen_reexecute_guard(obj, func, cfg);
22,213✔
2952
   cgen_basic_blocks(obj, func, cfg);
22,213✔
2953

2954
   entry_bb = LLVMGetInsertBlock(obj->builder);
22,213✔
2955

2956
   cgen_pointer_mask(func);
22,213✔
2957

2958
   cgen_block_t *cgb = func->blocks;
22,213✔
2959

2960
   LLVMValueRef zero_flag = llvm_int1(obj, false);
22,213✔
2961

2962
   int maxin = 0;
22,213✔
2963
   for (int i = 0; i < func->source->nirs; i++) {
2,344,416✔
2964
      if (i == cgb->source->first) {
2,322,203✔
2965
         LLVMPositionBuilderAtEnd(obj->builder, cgb->bbref);
216,937✔
2966

2967
         cgen_block_t *dom = NULL;
216,937✔
2968
         if (cgb->source->in.count == 1)
216,937✔
2969
            dom = &(func->blocks[jit_get_edge(&cgb->source->in, 0)]);
144,636✔
2970

2971
         cgb->inflags = zero_flag;
216,937✔
2972

2973
         if (mask_test(&cgb->source->livein, func->source->nregs)) {
216,937✔
2974
             if (dom != NULL && dom < cgb) {
6,364✔
2975
                // Skip generating a phi instruction if there is just
2976
                // one dominating block
2977
                assert(dom->outflags != NULL);
1,400✔
2978
                cgb->inflags = dom->outflags;
1,400✔
2979
             }
2980
             else if (cgb->source->in.count > 0) {
4,964✔
2981
                LLVMTypeRef int1_type = obj->types[LLVM_INT1];
4,964✔
2982
                cgb->inflags = LLVMBuildPhi(obj->builder, int1_type, "FLAGS");
4,964✔
2983
             }
2984
         }
2985

2986
         cgb->outflags = cgb->inflags;
216,937✔
2987

2988
         for (int j = 0; j < func->source->nregs; j++) {
27,684,484✔
2989
            if (mask_test(&cgb->source->livein, j)) {
27,467,547✔
2990
               if (dom != NULL && dom < cgb) {
1,198,335✔
2991
                  assert(dom->outregs[j] != NULL);
794,074✔
2992
                  cgb->inregs[j] = cgb->outregs[j] = dom->outregs[j];
794,074✔
2993
                  continue;
794,074✔
2994
               }
2995

2996
               llvm_type_t type =
808,522✔
2997
                  mask_test(&func->ptr_mask, j) ? LLVM_PTR : LLVM_INT64;
404,261✔
2998
               const char *name = cgen_reg_name(j);
404,261✔
2999
               LLVMValueRef init = cgb->source->in.count == 0
808,522✔
3000
                  ? LLVMConstNull(obj->types[type])
6,916✔
3001
                  : LLVMBuildPhi(obj->builder, obj->types[type], name);
404,261✔
3002
               cgb->inregs[j] = cgb->outregs[j] = init;
404,261✔
3003
            }
3004
         }
3005

3006
         maxin = MAX(maxin, cgb->source->in.count);
216,937✔
3007
      }
3008

3009
      assert(i >= cgb->source->first && i <= cgb->source->last);
2,322,203✔
3010

3011
      cgen_ir(obj, cgb, &(func->source->irbuf[i]));
2,322,203✔
3012

3013
      if (i == cgb->source->last) {
2,322,203✔
3014
         cgen_fix_liveout_types(obj, cgb);
216,937✔
3015

3016
         if (LLVMGetBasicBlockTerminator(cgb->bbref) == NULL) {
216,937✔
3017
            if (cgb->source->aborts)
64,488✔
3018
               LLVMBuildUnreachable(obj->builder);
32,062✔
3019
            else {
3020
               // Fall through to next block
3021
               assert(!cgb->source->returns);
32,426✔
3022
               assert(cgb + 1 < func->blocks + cfg->nblocks);
32,426✔
3023
               LLVMBuildBr(obj->builder, (cgb + 1)->bbref);
32,426✔
3024
            }
3025
         }
3026

3027
         cgb++;
216,937✔
3028
      }
3029
   }
3030

3031
   LLVMValueRef *phi_in LOCAL = xmalloc_array(maxin, sizeof(LLVMValueRef));
44,426✔
3032
   LLVMBasicBlockRef *phi_bb LOCAL =
22,213✔
3033
      xmalloc_array(maxin, sizeof(LLVMBasicBlockRef));
22,213✔
3034

3035
   for (int i = 0; i < cfg->nblocks; i++) {
239,150✔
3036
      jit_block_t *bb = &(cfg->blocks[i]);
216,937✔
3037
      cgen_block_t *cgb = &(func->blocks[i]);
216,937✔
3038

3039
      if (bb->in.count == 0)
216,937✔
3040
         continue;
25,630✔
3041

3042
      // Flags
3043
      if (mask_test(&cgb->source->livein, func->source->nregs)
191,307✔
3044
          && LLVMIsAPHINode(cgb->inflags)
6,364✔
3045
          && LLVMGetInstructionParent(cgb->inflags) == cgb->bbref) {
4,964✔
3046

3047
         for (int j = 0; j < bb->in.count; j++) {
14,892✔
3048
            const int edge = jit_get_edge(&bb->in, j);
9,928✔
3049
            phi_in[j] = func->blocks[edge].outflags;
9,928✔
3050
            phi_bb[j] = func->blocks[edge].bbref;
9,928✔
3051
         }
3052
         LLVMAddIncoming(cgb->inflags, phi_in, phi_bb, bb->in.count);
4,964✔
3053
      }
3054

3055
      // Live-in registers
3056
      for (int j = 0; j < func->source->nregs; j++) {
26,929,700✔
3057
         if (cgb->inregs[j] != NULL && LLVMIsAPHINode(cgb->inregs[j])
26,738,393✔
3058
             && LLVMGetInstructionParent(cgb->inregs[j]) == cgb->bbref) {
915,996✔
3059

3060
            for (int k = 0; k < bb->in.count; k++) {
1,193,957✔
3061
               const int edge = jit_get_edge(&bb->in, k);
796,612✔
3062
               assert(func->blocks[edge].outregs[j] != NULL);
796,612✔
3063
               phi_in[k] = func->blocks[edge].outregs[j];
796,612✔
3064
               phi_bb[k] = func->blocks[edge].bbref;
796,612✔
3065
            }
3066
            LLVMAddIncoming(cgb->inregs[j], phi_in, phi_bb, bb->in.count);
397,345✔
3067
         }
3068
      }
3069
   }
3070

3071
   for (int i = 0; i < cfg->nblocks; i++) {
239,150✔
3072
      cgen_block_t *cgb = &(func->blocks[i]);
216,937✔
3073
      free(cgb->inregs);
216,937✔
3074
      free(cgb->outregs);
216,937✔
3075
      cgb->inregs = cgb->outregs = NULL;
216,937✔
3076
   }
3077

3078
   LLVMPositionBuilderAtEnd(obj->builder, entry_bb);
22,213✔
3079
   LLVMBuildBr(obj->builder, func->blocks[0].bbref);
22,213✔
3080

3081
   jit_free_cfg(func->source);
22,213✔
3082
   func->cfg = cfg = NULL;
22,213✔
3083

3084
   mask_free(&(func->ptr_mask));
22,213✔
3085

3086
   free(func->blocks);
22,213✔
3087
   func->blocks = NULL;
22,213✔
3088

3089
   free(func->relocs);
22,213✔
3090
   func->relocs = NULL;
22,213✔
3091
}
22,213✔
3092

3093
static void cgen_tlab_alloc_body(llvm_obj_t *obj)
6,304✔
3094
{
3095
   LLVMValueRef fn = obj->fns[LLVM_TLAB_ALLOC];
6,304✔
3096
   LLVMSetLinkage(fn, LLVMPrivateLinkage);
6,304✔
3097

3098
#ifdef PRESERVE_FRAME_POINTER
3099
   llvm_add_func_attr(obj, fn, FUNC_ATTR_PRESERVE_FP, 0);
3100
#endif
3101

3102
   LLVMBasicBlockRef entry = llvm_append_block(obj, fn, "");
6,304✔
3103

3104
   LLVMPositionBuilderAtEnd(obj->builder, entry);
6,304✔
3105

3106
   LLVMValueRef tlab = LLVMGetParam(fn, 0);
6,304✔
3107
   LLVMSetValueName(tlab, "tlab");
6,304✔
3108

3109
   LLVMValueRef bytes = LLVMGetParam(fn, 1);
6,304✔
3110
   LLVMSetValueName(bytes, "bytes");
6,304✔
3111

3112
   LLVMValueRef anchor = LLVMGetParam(fn, 2);
6,304✔
3113
   LLVMSetValueName(anchor, "anchor");
6,304✔
3114

3115
   LLVMBasicBlockRef fast_bb = llvm_append_block(obj, fn, "");
6,304✔
3116
   LLVMBasicBlockRef slow_bb = llvm_append_block(obj, fn, "");
6,304✔
3117

3118
   LLVMValueRef alloc_ptr =
6,304✔
3119
      LLVMBuildStructGEP2(obj->builder, obj->types[LLVM_TLAB], tlab, 1, "");
6,304✔
3120
   LLVMValueRef limit_ptr =
6,304✔
3121
      LLVMBuildStructGEP2(obj->builder, obj->types[LLVM_TLAB], tlab, 2, "");
6,304✔
3122

3123
   LLVMValueRef alloc =
6,304✔
3124
      LLVMBuildLoad2(obj->builder, obj->types[LLVM_INT32], alloc_ptr, "");
6,304✔
3125
   LLVMValueRef limit =
6,304✔
3126
      LLVMBuildLoad2(obj->builder, obj->types[LLVM_INT32], limit_ptr, "");
6,304✔
3127

3128
   LLVMValueRef bytes_trunc = LLVMBuildTrunc(obj->builder, bytes,
6,304✔
3129
                                             obj->types[LLVM_INT32], "");
3130

3131
   LLVMValueRef align_mask = llvm_int32(obj, RT_ALIGN_MASK);
6,304✔
3132
   LLVMValueRef align_up =
6,304✔
3133
      LLVMBuildAnd(obj->builder,
6,304✔
3134
                   LLVMBuildAdd(obj->builder, bytes_trunc, align_mask, ""),
3135
                   LLVMConstNot(align_mask), "");
3136

3137
   LLVMValueRef next = LLVMBuildAdd(obj->builder, alloc, align_up, "");
6,304✔
3138

3139
   LLVMValueRef over = LLVMBuildICmp(obj->builder, LLVMIntUGT, next, limit, "");
6,304✔
3140
   LLVMBuildCondBr(obj->builder, over, slow_bb, fast_bb);
6,304✔
3141

3142
   LLVMPositionBuilderAtEnd(obj->builder, fast_bb);
6,304✔
3143

3144
   LLVMBuildStore(obj->builder, next, alloc_ptr);
6,304✔
3145

3146
   LLVMValueRef base =
6,304✔
3147
      LLVMBuildStructGEP2(obj->builder, obj->types[LLVM_TLAB], tlab, 3, "");
6,304✔
3148

3149
   LLVMValueRef indexes[] = { alloc };
6,304✔
3150
   LLVMValueRef fast_ptr = LLVMBuildInBoundsGEP2(obj->builder,
6,304✔
3151
                                                 obj->types[LLVM_INT8],
3152
                                                 base, indexes,
3153
                                                 ARRAY_LEN(indexes), "");
3154

3155
   LLVMBuildRet(obj->builder, fast_ptr);
6,304✔
3156

3157
   LLVMPositionBuilderAtEnd(obj->builder, slow_bb);
6,304✔
3158

3159
   LLVMValueRef args[] = { bytes, anchor };
6,304✔
3160
   LLVMValueRef slow_ptr = llvm_call_fn(obj, LLVM_MSPACE_ALLOC, args,
6,304✔
3161
                                        ARRAY_LEN(args));
3162

3163
   LLVMBuildRet(obj->builder, slow_ptr);
6,304✔
3164
}
6,304✔
3165

3166
static void cgen_exp_overflow_body(llvm_obj_t *obj, llvm_fn_t which,
32✔
3167
                                   jit_size_t sz, llvm_fn_t mulbase)
3168
{
3169
   LLVMValueRef fn = obj->fns[which];
32✔
3170
   LLVMSetLinkage(fn, LLVMPrivateLinkage);
32✔
3171

3172
#ifdef PRESERVE_FRAME_POINTER
3173
   llvm_add_func_attr(obj, fn, FUNC_ATTR_PRESERVE_FP, 0);
3174
#endif
3175

3176
   LLVMBasicBlockRef entry = llvm_append_block(obj, fn, "entry");
32✔
3177

3178
   LLVMPositionBuilderAtEnd(obj->builder, entry);
32✔
3179

3180
   LLVMValueRef x0 = LLVMGetParam(fn, 0);
32✔
3181
   LLVMSetValueName(x0, "x0");
32✔
3182

3183
   LLVMValueRef y0 = LLVMGetParam(fn, 1);
32✔
3184
   LLVMSetValueName(y0, "y0");
32✔
3185

3186
   LLVMTypeRef int_type = obj->types[LLVM_INT8 + sz];
32✔
3187
   LLVMTypeRef pair_type = obj->types[LLVM_PAIR_I8_I1 + sz];
32✔
3188

3189
   LLVMValueRef mulfn = llvm_get_fn(obj, mulbase + sz);
32✔
3190
   LLVMTypeRef multype = obj->fntypes[mulbase + sz];
32✔
3191

3192
   LLVMValueRef zero = LLVMConstInt(int_type, 0, false);
32✔
3193
   LLVMValueRef one = LLVMConstInt(int_type, 1, false);
32✔
3194

3195
   LLVMValueRef r0 = one;
32✔
3196
   LLVMValueRef o0 = llvm_int1(obj, false);
32✔
3197
   LLVMValueRef xo0 = llvm_int1(obj, false);
32✔
3198

3199
   LLVMBasicBlockRef header = llvm_append_block(obj, fn, "header");
32✔
3200
   LLVMBasicBlockRef body = llvm_append_block(obj, fn, "body");
32✔
3201
   LLVMBasicBlockRef accum = llvm_append_block(obj, fn, "accum");
32✔
3202
   LLVMBasicBlockRef tail = llvm_append_block(obj, fn, "tail");
32✔
3203
   LLVMBasicBlockRef exit = llvm_append_block(obj, fn, "exit");
32✔
3204

3205
   LLVMBuildBr(obj->builder, header);
32✔
3206

3207
   LLVMPositionBuilderAtEnd(obj->builder, header);
32✔
3208

3209
   LLVMValueRef x1 = LLVMBuildPhi(obj->builder, int_type, "x1");
32✔
3210
   LLVMValueRef y1 = LLVMBuildPhi(obj->builder, int_type, "y1");
32✔
3211
   LLVMValueRef r1 = LLVMBuildPhi(obj->builder, int_type, "r1");
32✔
3212
   LLVMValueRef o1 = LLVMBuildPhi(obj->builder, obj->types[LLVM_INT1], "o1");
32✔
3213
   LLVMValueRef xo1 = LLVMBuildPhi(obj->builder, obj->types[LLVM_INT1], "xo1");
32✔
3214

3215
   LLVMValueRef test1 = LLVMBuildICmp(obj->builder, LLVMIntEQ, y1, zero, "");
32✔
3216
   LLVMBuildCondBr(obj->builder, test1, exit, body);
32✔
3217

3218
   LLVMPositionBuilderAtEnd(obj->builder, body);
32✔
3219

3220
   LLVMValueRef lsb = LLVMBuildAnd(obj->builder, y1, one, "");
32✔
3221
   LLVMValueRef test2 = LLVMBuildICmp(obj->builder, LLVMIntEQ, lsb, zero, "");
32✔
3222
   LLVMBuildCondBr(obj->builder, test2, tail, accum);
32✔
3223

3224
   LLVMPositionBuilderAtEnd(obj->builder, accum);
32✔
3225

3226
   LLVMValueRef r2_args[] = { r1, x1 };
32✔
3227
   LLVMValueRef r2_pair = LLVMBuildCall2(obj->builder, multype, mulfn, r2_args,
32✔
3228
                                         ARRAY_LEN(r2_args), "");
3229
   LLVMValueRef r2 = LLVMBuildExtractValue(obj->builder, r2_pair, 0, "r2");
32✔
3230
   LLVMValueRef r2_ovf = LLVMBuildExtractValue(obj->builder, r2_pair, 1, "");
32✔
3231
   LLVMValueRef tmp = LLVMBuildOr(obj->builder, o1, xo1, "");
32✔
3232
   LLVMValueRef o2 = LLVMBuildOr(obj->builder, tmp, r2_ovf, "o2");
32✔
3233

3234
   LLVMBuildBr(obj->builder, tail);
32✔
3235

3236
   LLVMPositionBuilderAtEnd(obj->builder, tail);
32✔
3237

3238
   LLVMValueRef r3 = LLVMBuildPhi(obj->builder, int_type, "r3");
32✔
3239

3240
   LLVMValueRef r3_in[] = { r1, r2 };
32✔
3241
   LLVMBasicBlockRef r3_bb[] = { body, accum };
32✔
3242
   LLVMAddIncoming(r3, r3_in, r3_bb, 2);
32✔
3243

3244
   LLVMValueRef o3 = LLVMBuildPhi(obj->builder, obj->types[LLVM_INT1], "o3");
32✔
3245

3246
   LLVMValueRef o3_in[] = { o1, o2 };
32✔
3247
   LLVMBasicBlockRef o3_bb[] = { body, accum };
32✔
3248
   LLVMAddIncoming(o3, o3_in, o3_bb, 2);
32✔
3249

3250
   LLVMValueRef r1_in[] = { r0, r3 };
32✔
3251
   LLVMBasicBlockRef r1_bb[] = { entry, tail };
32✔
3252
   LLVMAddIncoming(r1, r1_in, r1_bb, 2);
32✔
3253

3254
   LLVMValueRef y2 = LLVMBuildLShr(obj->builder, y1, one, "y2");
32✔
3255

3256
   LLVMValueRef x2_args[] = { x1, x1 };
32✔
3257
   LLVMValueRef x2_pair = LLVMBuildCall2(obj->builder, multype, mulfn, x2_args,
32✔
3258
                                         ARRAY_LEN(x2_args), "");
3259
   LLVMValueRef x2 = LLVMBuildExtractValue(obj->builder, x2_pair, 0, "x2");
32✔
3260
   LLVMValueRef xo2 = LLVMBuildExtractValue(obj->builder, x2_pair, 1, "");
32✔
3261

3262
   LLVMValueRef x1_in[] = { x0, x2 };
32✔
3263
   LLVMBasicBlockRef x1_bb[] = { entry, tail };
32✔
3264
   LLVMAddIncoming(x1, x1_in, x1_bb, 2);
32✔
3265

3266
   LLVMValueRef y1_in[] = { y0, y2 };
32✔
3267
   LLVMBasicBlockRef y1_bb[] = { entry, tail };
32✔
3268
   LLVMAddIncoming(y1, y1_in, y1_bb, 2);
32✔
3269

3270
   LLVMValueRef o1_in[] = { o0, o3 };
32✔
3271
   LLVMBasicBlockRef o1_bb[] = { entry, tail };
32✔
3272
   LLVMAddIncoming(o1, o1_in, o1_bb, 2);
32✔
3273

3274
   LLVMValueRef xo1_in[] = { xo0, xo2 };
32✔
3275
   LLVMBasicBlockRef xo1_bb[] = { entry, tail };
32✔
3276
   LLVMAddIncoming(xo1, xo1_in, xo1_bb, 2);
32✔
3277

3278
   LLVMBuildBr(obj->builder, header);
32✔
3279

3280
   LLVMPositionBuilderAtEnd(obj->builder, exit);
32✔
3281

3282
   LLVMValueRef pair = LLVMConstNull(pair_type);
32✔
3283
   pair = LLVMBuildInsertValue(obj->builder, pair, r1, 0, "");
32✔
3284
   pair = LLVMBuildInsertValue(obj->builder, pair, o1, 1, "");
32✔
3285

3286
   LLVMBuildRet(obj->builder, pair);
32✔
3287
}
32✔
3288

3289
static void cgen_memset_body(llvm_obj_t *obj, llvm_fn_t which,
235✔
3290
                             jit_size_t sz, llvm_fn_t mulbase)
3291
{
3292
   LLVMValueRef fn = obj->fns[which];
235✔
3293
   LLVMSetLinkage(fn, LLVMPrivateLinkage);
235✔
3294

3295
#ifdef PRESERVE_FRAME_POINTER
3296
   llvm_add_func_attr(obj, fn, FUNC_ATTR_PRESERVE_FP, 0);
3297
#endif
3298

3299
   LLVMBasicBlockRef entry = llvm_append_block(obj, fn, "entry");
235✔
3300

3301
   LLVMPositionBuilderAtEnd(obj->builder, entry);
235✔
3302

3303
   LLVMValueRef dest = LLVMGetParam(fn, 0);
235✔
3304
   LLVMSetValueName(dest, "dest");
235✔
3305

3306
   LLVMValueRef value = LLVMGetParam(fn, 1);
235✔
3307
   LLVMSetValueName(value, "value");
235✔
3308

3309
   LLVMValueRef bytes = LLVMGetParam(fn, 2);
235✔
3310
   LLVMSetValueName(bytes, "bytes");
235✔
3311

3312
   LLVMValueRef indexes1[] = { bytes };
235✔
3313
   LLVMValueRef eptr = LLVMBuildGEP2(obj->builder, obj->types[LLVM_INT8],
235✔
3314
                                     dest, indexes1, 1, "eptr");
3315

3316
   LLVMBasicBlockRef body = llvm_append_block(obj, fn, "body");
235✔
3317
   LLVMBasicBlockRef exit = llvm_append_block(obj, fn, "exit");
235✔
3318

3319
   LLVMTypeRef type = obj->types[LLVM_INT8 + sz];
235✔
3320

3321
   LLVMValueRef zero = LLVMBuildIsNull(obj->builder, bytes, "");
235✔
3322
   LLVMBuildCondBr(obj->builder, zero, exit, body);
235✔
3323

3324
   LLVMPositionBuilderAtEnd(obj->builder, body);
235✔
3325

3326
   LLVMValueRef ptr = LLVMBuildPhi(obj->builder, obj->types[LLVM_PTR], "ptr");
235✔
3327

3328
#ifndef LLVM_HAS_OPAQUE_POINTERS
3329
   LLVMTypeRef ptr_type = LLVMPointerType(type, 0);
235✔
3330
   LLVMValueRef cast = LLVMBuildPointerCast(obj->builder, ptr, ptr_type, "");
235✔
3331
#else
3332
   LLVMValueRef cast = ptr;
3333
#endif
3334

3335
   LLVMBuildStore(obj->builder, value, cast);
235✔
3336

3337
   LLVMValueRef indexes2[] = { llvm_intptr(obj, 1) };
235✔
3338
   LLVMValueRef next = LLVMBuildGEP2(obj->builder, type, cast, indexes2, 1, "");
235✔
3339

3340
   LLVMValueRef ptr_in[] = { dest, PTR(next) };
235✔
3341
   LLVMBasicBlockRef ptr_bb[] = { entry, body };
235✔
3342
   LLVMAddIncoming(ptr, ptr_in, ptr_bb, 2);
235✔
3343

3344
   LLVMValueRef cont =
235✔
3345
      LLVMBuildICmp(obj->builder, LLVMIntULT, PTR(next), eptr, "");
235✔
3346
   LLVMBuildCondBr(obj->builder, cont, body, exit);
235✔
3347

3348
   LLVMPositionBuilderAtEnd(obj->builder, exit);
235✔
3349

3350
   LLVMBuildRetVoid(obj->builder);
235✔
3351
}
235✔
3352

3353
////////////////////////////////////////////////////////////////////////////////
3354
// JIT plugin interface
3355

3356
typedef struct {
3357
   code_cache_t *code;
3358
} llvm_jit_state_t;
3359

3360
static void *jit_llvm_init(jit_t *jit)
3,532✔
3361
{
3362
   llvm_native_setup();
3,532✔
3363

3364
   llvm_jit_state_t *state = xcalloc(sizeof(llvm_jit_state_t));
3,532✔
3365
   state->code = code_cache_new();
3,532✔
3366

3367
   return state;
3,532✔
3368
}
3369

3370
static void jit_llvm_cgen(jit_t *j, jit_handle_t handle, void *context)
7,824✔
3371
{
3372
   llvm_jit_state_t *state = context;
7,824✔
3373

3374
   jit_func_t *f = jit_get_func(j, handle);
7,824✔
3375

3376
#ifdef DEBUG
3377
   const char *only = getenv("NVC_JIT_ONLY");
7,824✔
3378
   if (only != NULL && !icmp(f->name, only))
7,824✔
UNCOV
3379
      return;
×
3380
#endif
3381

3382
   const uint64_t start_us = get_timestamp_us();
7,824✔
3383

3384
   LLVMTargetMachineRef tm = llvm_target_machine(LLVMRelocDefault,
7,824✔
3385
                                                 JIT_CODE_MODEL);
3386

3387
   llvm_obj_t obj = {
7,824✔
3388
      .context = LLVMContextCreate(),
7,824✔
3389
      .target  = tm,
3390
   };
3391

3392
   LOCAL_TEXT_BUF tb = tb_new();
7,824✔
3393
   tb_istr(tb, f->name);
7,824✔
3394

3395
   obj.module    = LLVMModuleCreateWithNameInContext(tb_get(tb), obj.context);
7,824✔
3396
   obj.builder   = LLVMCreateBuilderInContext(obj.context);
7,824✔
3397
   obj.data_ref  = LLVMCreateTargetDataLayout(tm);
7,824✔
3398

3399
#if ENABLE_DWARF
3400
   obj.debuginfo = LLVMCreateDIBuilderDisallowUnresolved(obj.module);
3401
#endif
3402

3403
   llvm_register_types(&obj);
7,824✔
3404

3405
   cgen_func_t func = {
7,824✔
3406
      .name   = tb_claim(tb),
7,824✔
3407
      .source = f,
3408
      .mode   = CGEN_JIT,
3409
   };
3410

3411
   cgen_function(&obj, &func);
7,824✔
3412

3413
   llvm_obj_finalise(&obj, LLVM_O0);
7,824✔
3414

3415
   LLVMMemoryBufferRef buf;
7,824✔
3416
   char *error;
7,824✔
3417
   if (LLVMTargetMachineEmitToMemoryBuffer(tm, obj.module, LLVMObjectFile,
7,824✔
3418
                                           &error, &buf))
UNCOV
3419
     fatal("failed to generate native code: %s", error);
×
3420

3421
   const size_t objsz = LLVMGetBufferSize(buf);
7,824✔
3422

3423
   code_blob_t *blob = code_blob_new(state->code, f->name, objsz);
7,824✔
3424
   if (blob == NULL)
7,824✔
UNCOV
3425
      return;
×
3426

3427
   const uint8_t *base = blob->wptr;
7,824✔
3428
   const void *entry_addr = blob->wptr;
7,824✔
3429

3430
   code_load_object(blob, LLVMGetBufferStart(buf), objsz);
7,824✔
3431

3432
   const size_t size = blob->wptr - base;
7,824✔
3433
   code_blob_finalise(blob, &(f->entry));
7,824✔
3434

3435
   if (opt_get_int(OPT_JIT_LOG)) {
7,824✔
UNCOV
3436
      const uint64_t end_us = get_timestamp_us();
×
UNCOV
3437
      debugf("%s at %p [%zu bytes in %"PRIi64" us]", func.name,
×
3438
             entry_addr, size, end_us - start_us);
3439
   }
3440

3441
   LLVMDisposeMemoryBuffer(buf);
7,824✔
3442
   LLVMDisposeTargetData(obj.data_ref);
7,824✔
3443
   LLVMDisposeTargetMachine(tm);
7,824✔
3444
   LLVMDisposeBuilder(obj.builder);
7,824✔
3445
   DWARF_ONLY(LLVMDisposeDIBuilder(obj.debuginfo));
7,824✔
3446
   LLVMContextDispose(obj.context);
7,824✔
3447
   free(func.name);
7,824✔
3448
}
3449

3450
static void jit_llvm_cleanup(void *context)
3,530✔
3451
{
3452
   llvm_jit_state_t *state = context;
3,530✔
3453
   code_cache_free(state->code);
3,530✔
3454
   free(state);
3,530✔
3455
}
3,530✔
3456

3457
static const jit_plugin_t jit_llvm = {
3458
   .init    = jit_llvm_init,
3459
   .cgen    = jit_llvm_cgen,
3460
   .cleanup = jit_llvm_cleanup
3461
};
3462

3463
void jit_register_llvm_plugin(jit_t *j)
4,814✔
3464
{
3465
   const int threshold = opt_get_int(OPT_JIT_THRESHOLD);
4,814✔
3466
   if (threshold > 0)
4,814✔
3467
      jit_add_tier(j, threshold, &jit_llvm);
3,532✔
3468
   else if (threshold < 0)
1,282✔
UNCOV
3469
      warnf("invalid NVC_JIT_THRESOLD setting %d", threshold);
×
3470
}
4,814✔
3471

3472
////////////////////////////////////////////////////////////////////////////////
3473
// Ahead-of-time code generation
3474

3475
llvm_obj_t *llvm_obj_new(const char *name)
1,308✔
3476
{
3477
   llvm_native_setup();
1,308✔
3478

3479
   llvm_obj_t *obj = xcalloc(sizeof(llvm_obj_t));
1,308✔
3480
   obj->context     = LLVMContextCreate();
1,308✔
3481
   obj->module      = LLVMModuleCreateWithNameInContext(name, obj->context);
1,308✔
3482
   obj->builder     = LLVMCreateBuilderInContext(obj->context);
1,308✔
3483
   obj->target      = llvm_target_machine(LLVMRelocPIC, LLVMCodeModelDefault);
1,308✔
3484
   obj->data_ref    = LLVMCreateTargetDataLayout(obj->target);
1,308✔
3485
   obj->pack_writer = pack_writer_new();
1,308✔
3486

3487
#if ENABLE_DWARF
3488
   obj->debuginfo = LLVMCreateDIBuilderDisallowUnresolved(obj->module);
3489
#endif
3490

3491
   char *triple = LLVMGetTargetMachineTriple(obj->target);
1,308✔
3492
   LLVMSetTarget(obj->module, triple);
1,308✔
3493
   LLVMDisposeMessage(triple);
1,308✔
3494

3495
   LLVMSetModuleDataLayout(obj->module, obj->data_ref);
1,308✔
3496

3497
   llvm_register_types(obj);
1,308✔
3498

3499
#if ENABLE_DWARF
3500
   llvm_add_module_flag(obj, "Debug Info Version", DEBUG_METADATA_VERSION);
3501
#ifdef __APPLE__
3502
   llvm_add_module_flag(obj, "Dwarf Version", 2);
3503
#else
3504
   llvm_add_module_flag(obj, "Dwarf Version", 4);
3505
#endif
3506
#endif
3507

3508
   obj->strtab = LLVMAddGlobal(obj->module, obj->types[LLVM_STRTAB],
1,308✔
3509
                               "placeholder_strtab");
3510
   LLVMSetGlobalConstant(obj->strtab, true);
1,308✔
3511
   LLVMSetLinkage(obj->strtab, LLVMPrivateLinkage);
1,308✔
3512

3513
   return obj;
1,308✔
3514
}
3515

3516
void llvm_add_abi_version(llvm_obj_t *obj)
1,218✔
3517
{
3518
   LLVMValueRef abi_version =
1,218✔
3519
      LLVMAddGlobal(obj->module, obj->types[LLVM_INT32], "__nvc_abi_version");
1,218✔
3520
   LLVMSetInitializer(abi_version, llvm_int32(obj, RT_ABI_VERSION));
1,218✔
3521
   LLVMSetGlobalConstant(abi_version, true);
1,218✔
3522
#ifdef IMPLIB_REQUIRED
3523
   LLVMSetDLLStorageClass(abi_version, LLVMDLLExportStorageClass);
3524
#endif
3525
}
1,218✔
3526

3527
void llvm_aot_compile(llvm_obj_t *obj, jit_t *j, jit_handle_t handle)
14,389✔
3528
{
3529
   DEBUG_ONLY(const uint64_t start_us = get_timestamp_us());
14,389✔
3530

3531
   jit_func_t *f = jit_get_func(j, handle);
14,389✔
3532
   jit_fill_irbuf(f);
14,389✔
3533

3534
   LOCAL_TEXT_BUF tb = safe_symbol(f->name);
14,389✔
3535

3536
   cgen_func_t func = {
14,389✔
3537
      .name   = tb_claim(tb),
14,389✔
3538
      .source = f,
3539
      .mode   = CGEN_AOT,
3540
   };
3541

3542
   cgen_function(obj, &func);
14,389✔
3543

3544
#ifdef DEBUG
3545
   const uint64_t end_us = get_timestamp_us();
14,389✔
3546
   if (end_us - start_us > 100000)
14,389✔
3547
      debugf("compiled %s [%"PRIi64" us]", func.name, end_us - start_us);
2✔
3548
#endif
3549

3550
   free(func.name);
14,389✔
3551
}
14,389✔
3552

3553
static void llvm_finalise_string_table(llvm_obj_t *obj)
9,132✔
3554
{
3555
   if (obj->pack_writer == NULL)
9,132✔
3556
      return;
7,824✔
3557

3558
   const char *strtab;
1,308✔
3559
   size_t len;
1,308✔
3560
   pack_writer_string_table(obj->pack_writer, &strtab, &len);
1,308✔
3561

3562
   LLVMValueRef init =
1,308✔
3563
      LLVMConstStringInContext(obj->context, strtab, len - 1, false);
1,308✔
3564
   LLVMTypeRef array_type = LLVMArrayType(obj->types[LLVM_INT8], len);
1,308✔
3565
   LLVMValueRef global = LLVMAddGlobal(obj->module, array_type, "strtab");
1,308✔
3566
   LLVMSetGlobalConstant(global, true);
1,308✔
3567
   LLVMSetInitializer(global, init);
1,308✔
3568
   LLVMSetLinkage(global, LLVMPrivateLinkage);
1,308✔
3569

3570
   LLVMReplaceAllUsesWith(obj->strtab, global);
1,308✔
3571
   LLVMDeleteGlobal(obj->strtab);
1,308✔
3572
}
3573

3574
void llvm_obj_finalise(llvm_obj_t *obj, llvm_opt_level_t olevel)
9,132✔
3575
{
3576
   if (obj->fns[LLVM_TLAB_ALLOC] != NULL)
9,132✔
3577
      cgen_tlab_alloc_body(obj);
6,304✔
3578

3579
   for (jit_size_t sz = JIT_SZ_8; sz <= JIT_SZ_64; sz++) {
45,660✔
3580
      if (obj->fns[LLVM_EXP_OVERFLOW_S8 + sz] != NULL)
36,528✔
3581
         cgen_exp_overflow_body(obj, LLVM_EXP_OVERFLOW_S8 + sz, sz,
30✔
3582
                                LLVM_MUL_OVERFLOW_S8);
3583
      if (obj->fns[LLVM_EXP_OVERFLOW_U8 + sz] != NULL)
36,528✔
3584
         cgen_exp_overflow_body(obj, LLVM_EXP_OVERFLOW_U8 + sz, sz,
2✔
3585
                                LLVM_MUL_OVERFLOW_U8);
3586
      if (obj->fns[LLVM_MEMSET_U8 + sz] != NULL)
36,528✔
3587
         cgen_memset_body(obj, LLVM_MEMSET_U8 + sz, sz,
235✔
3588
                          LLVM_MUL_OVERFLOW_U8);
3589
   }
3590

3591
   llvm_finalise_string_table(obj);
9,132✔
3592

3593
   DWARF_ONLY(LLVMDIBuilderFinalize(obj->debuginfo));
9,132✔
3594

3595
   llvm_dump_module(obj->module, "initial");
9,132✔
3596
   llvm_verify_module(obj->module);
9,132✔
3597
   llvm_optimise(obj->module, obj->target, olevel);
9,132✔
3598
   llvm_dump_module(obj->module, "final");
9,132✔
3599
}
9,132✔
3600

3601
void llvm_obj_emit(llvm_obj_t *obj, const char *path)
1,308✔
3602
{
3603
   char *error;
1,308✔
3604
   if (LLVMTargetMachineEmitToFile(obj->target, obj->module, (char *)path,
1,308✔
3605
                                   LLVMObjectFile, &error))
UNCOV
3606
      fatal("Failed to write object file: %s", error);
×
3607

3608
   LLVMDisposeTargetData(obj->data_ref);
1,308✔
3609
   LLVMDisposeTargetMachine(obj->target);
1,308✔
3610
   LLVMDisposeBuilder(obj->builder);
1,308✔
3611
   LLVMDisposeModule(obj->module);
1,308✔
3612
   LLVMContextDispose(obj->context);
1,308✔
3613

3614
   pack_writer_free(obj->pack_writer);
1,308✔
3615

3616
   free(obj);
1,308✔
3617
}
1,308✔
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