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

nickg / nvc / 14685578009

26 Apr 2025 08:04PM UTC coverage: 92.344% (-0.004%) from 92.348%
14685578009

push

github

nickg
Optimise iteration over object fields

112 of 121 new or added lines in 1 file covered. (92.56%)

42 existing lines in 2 files now uncovered.

69223 of 74962 relevant lines covered (92.34%)

392751.34 hits per line

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

96.01
/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
#elif defined __linux__ && defined ARCH_X86_64
155
#define JIT_CODE_MODEL LLVMCodeModelMedium
156
#else
157
#define JIT_CODE_MODEL LLVMCodeModelJITDefault
158
#endif
159

160
#if ENABLE_DWARF
161
#define DWARF_ONLY(x) x
162
#else
163
#define DWARF_ONLY(x)
164
#endif
165

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

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

193
typedef enum { CGEN_JIT, CGEN_AOT } cgen_mode_t;
194

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

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

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

240
   // Attributes requiring special handling
241
   FUNC_ATTR_PRESERVE_FP,
242
   FUNC_ATTR_DLLEXPORT,
243
} func_attr_t;
244

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

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

260
////////////////////////////////////////////////////////////////////////////////
261
// LLVM wrappers
262

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

268
static LLVMValueRef llvm_int8(llvm_obj_t *obj, int8_t i)
6,186,478✔
269
{
270
   return LLVMConstInt(obj->types[LLVM_INT8], i, false);
6,186,478✔
271
}
272

273
static LLVMValueRef llvm_int32(llvm_obj_t *obj, int32_t i)
565,170✔
274
{
275
   return LLVMConstInt(obj->types[LLVM_INT32], i, false);
565,170✔
276
}
277

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

283
static LLVMValueRef llvm_intptr(llvm_obj_t *obj, intptr_t i)
456,677✔
284
{
285
   return LLVMConstInt(obj->types[LLVM_INTPTR], i, false);
456,677✔
286
}
287

288
static LLVMValueRef llvm_ptr(llvm_obj_t *obj, void *ptr)
61,056✔
289
{
290
   return LLVMConstIntToPtr(llvm_intptr(obj, (intptr_t)ptr),
61,056✔
291
                            obj->types[LLVM_PTR]);
292
}
293

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

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

321
      const unsigned kind =
256,519✔
322
         LLVMGetEnumAttributeKindForName(names[attr], strlen(names[attr]));
256,519✔
323
      if (kind == 0)
256,519✔
324
         fatal_trace("Cannot get LLVM attribute for %s", names[attr]);
325

326
#ifdef LLVM_UWTABLE_HAS_ARGUMENT
327
      if (attr == FUNC_ATTR_UWTABLE)
328
         ref = LLVMCreateEnumAttribute(obj->context, kind, 2);
329
      else
330
#endif
331
         ref = LLVMCreateEnumAttribute(obj->context, kind, 0);
256,519✔
332
   }
333

334
   LLVMAddAttributeAtIndex(fn, param, ref);
256,519✔
335
}
336

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

347
   obj->types[LLVM_INTPTR] = LLVMIntPtrTypeInContext(obj->context,
9,267✔
348
                                                     obj->data_ref);
349

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

356
   obj->types[LLVM_STRTAB] = LLVMArrayType(obj->types[LLVM_INT8], 0);
9,267✔
357

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

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

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

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

411
   for (jit_size_t sz = JIT_SZ_8; sz <= JIT_SZ_64; sz++) {
46,335✔
412
      LLVMTypeRef fields[] = {
37,068✔
413
         obj->types[LLVM_INT8 + sz],
37,068✔
414
         obj->types[LLVM_INT1]
37,068✔
415
      };
416
      llvm_fn_t which = LLVM_PAIR_I8_I1 + sz;
37,068✔
417
      obj->types[which] = LLVMStructTypeInContext(obj->context, fields,
37,068✔
418
                                                  ARRAY_LEN(fields), false);
419
   }
420
}
9,267✔
421

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

427
   if (!opt_get_verbose(OPT_LLVM_VERBOSE, module_name))
18,534✔
428
      return;
18,534✔
429

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

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

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

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

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

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

465
   const char *passes[] = {
9,267✔
466
      "default<O0>", "default<O1>", "default<O2>", "default<O3>"
467
   };
468

469
   LLVM_CHECK(LLVMRunPasses, module, passes[olevel], target, options);
9,267✔
470

471
   LLVMDisposePassBuilderOptions(options);
9,267✔
472
#else
473
   LLVMPassManagerRef fpm = LLVMCreateFunctionPassManagerForModule(module);
474
   LLVMPassManagerRef mpm = LLVMCreatePassManager();
475

476
   LLVMInitializeFunctionPassManager(fpm);
477

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

482
   LLVMFinalizeFunctionPassManager(fpm);
483
   LLVMDisposePassManager(fpm);
484

485
   LLVMPassManagerBuilderRef builder = LLVMPassManagerBuilderCreate();
486
   LLVMPassManagerBuilderSetOptLevel(builder, olevel);
487
   LLVMPassManagerBuilderSetSizeLevel(builder, 0);
488

489
   if (olevel >= 2)
490
      LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 50);
491

492
   LLVMPassManagerBuilderPopulateModulePassManager(builder, mpm);
493
   LLVMPassManagerBuilderDispose(builder);
494

495
   LLVMRunPassManager(mpm, module);
496
   LLVMDisposePassManager(mpm);
497
#endif
498
}
9,267✔
499

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

509
   LLVMTargetMachineRef tm = LLVMCreateTargetMachine(target_ref, def_triple,
9,267✔
510
                                                     "", "",
511
                                                     LLVMCodeGenLevelDefault,
512
                                                     reloc, model);
513
   LLVMDisposeMessage(def_triple);
9,267✔
514

515
   return tm;
9,267✔
516
}
517

518
static LLVMBasicBlockRef llvm_append_block(llvm_obj_t *obj, LLVMValueRef fn,
260,996✔
519
                                           const char *name)
520
{
521
   return LLVMAppendBasicBlockInContext(obj->context, fn, name);
260,996✔
522
}
523

524
static LLVMValueRef llvm_add_fn(llvm_obj_t *obj, const char *name,
67,572✔
525
                                LLVMTypeRef type)
526
{
527
   LLVMValueRef fn = LLVMGetNamedFunction(obj->module, name);
67,572✔
528
   if (fn == NULL)
67,572✔
529
      fn = LLVMAddFunction(obj->module, name, type);
52,431✔
530

531
   return fn;
67,572✔
532
}
533

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

870
         const char *sym = NULL;
3,928✔
871
         switch (which) {
3,928✔
872
         case LLVM_SCHED_WAVEFORM: sym = "__nvc_sched_waveform"; break;
873
         case LLVM_TEST_EVENT: sym = "__nvc_test_event"; break;
123✔
874
         case LLVM_LAST_EVENT: sym = "__nvc_last_event"; break;
14✔
875
         case LLVM_SCHED_PROCESS: sym = "__nvc_sched_process"; break;
1,495✔
876
         default: break;
877
         }
878

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

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

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

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

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

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

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

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

961
   return (obj->fns[which] = fn);
29,485✔
962
}
963

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

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

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

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

993
static bool llvm_is_ptr(LLVMValueRef value)
1,095,190✔
994
{
995
   return LLVMGetTypeKind(LLVMTypeOf(value)) == LLVMPointerTypeKind;
1,095,190✔
996
}
997

998
#ifdef DEBUG
999
static void llvm_set_value_name(LLVMValueRef value, const char *name)
228,410✔
1000
{
1001
   size_t curlen;
228,410✔
1002
   LLVMGetValueName2(value, &curlen);
228,410✔
1003
   if (curlen == 0)
228,410✔
1004
      LLVMSetValueName(value, name);
181,590✔
1005
}
228,410✔
1006

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

1017
static void llvm_native_setup(void)
4,891✔
1018
{
1019
   LLVMInitializeNativeTarget();
4,891✔
1020
   LLVMInitializeNativeAsmPrinter();
4,891✔
1021

1022
   if (!LLVMIsMultithreaded())
4,891✔
1023
      fatal("LLVM was built without multithreaded support");
×
1024
}
4,891✔
1025

1026
////////////////////////////////////////////////////////////////////////////////
1027
// JIT IR to LLVM lowering
1028

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

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

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

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

1063
   va_end(ap);
1064
}
1065

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

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

1094
static cgen_reloc_t *cgen_find_reloc(cgen_reloc_t *list, reloc_kind_t kind,
80,668✔
1095
                                     int limit, uintptr_t key)
1096
{
1097
   for (int i = 0; i < limit; i++) {
245,718✔
1098
      if (list[i].kind == kind && list[i].key == key)
218,704✔
1099
         return &(list[i]);
53,654✔
1100
      else if (list[i].kind == RELOC_NULL)
165,050✔
1101
         break;
1102
   }
1103

1104
   return NULL;
1105
}
1106

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

1113
   LLVMValueRef array = LLVMBuildStructGEP2(obj->builder, func->descr_type,
14,953✔
1114
                                            func->descr, 4, "");
1115

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

1127
   return LLVMBuildLoad2(obj->builder, obj->types[LLVM_PTR], ptr, "");
14,953✔
1128
}
1129

1130
static LLVMValueRef cgen_rematerialise_object(llvm_obj_t *obj,
62,903✔
1131
                                              cgen_func_t *func,
1132
                                              object_t *locus)
1133
{
1134
   if (func->mode == CGEN_AOT) {
62,903✔
1135
      ident_t module;
43,835✔
1136
      ptrdiff_t offset;
43,835✔
1137
      object_locus(locus, &module, &offset);
43,835✔
1138

1139
      LOCAL_TEXT_BUF tb = tb_new();
87,670✔
1140
      tb_istr(tb, module);
43,835✔
1141

1142
      LLVMValueRef unit_str = llvm_const_string(obj, tb_get(tb));
43,835✔
1143

1144
      LLVMValueRef args[] = {
43,835✔
1145
         unit_str,
1146
         llvm_intptr(obj, offset),
43,835✔
1147
      };
1148
      return llvm_call_fn(obj, LLVM_GET_OBJECT, args, ARRAY_LEN(args));
43,835✔
1149
   }
1150
   else
1151
      return llvm_ptr(obj, locus);
19,068✔
1152
}
1153

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

1163
#ifdef DEBUG
1164
   ident_t name = jit_get_name(func->source->jit, handle);
457✔
1165
   char *valname LOCAL = xasprintf("%s.handle", istr(name));
914✔
1166
#else
1167
   const char *valname = "";
1168
#endif
1169

1170
   return LLVMBuildTrunc(obj->builder, intptr, obj->types[LLVM_INT32], valname);
457✔
1171
}
1172

1173
static LLVMValueRef cgen_get_value(llvm_obj_t *obj, cgen_block_t *cgb,
1,886,918✔
1174
                                   jit_value_t value)
1175
{
1176
   switch (value.kind) {
1,886,918✔
1177
   case JIT_VALUE_REG:
866,873✔
1178
      assert(value.reg < cgb->func->source->nregs);
866,873✔
1179
      assert(cgb->outregs[value.reg] != NULL);
866,873✔
1180
      return cgb->outregs[value.reg];
1181
   case JIT_VALUE_INT64:
528,439✔
1182
      return llvm_int64(obj, value.int64);
528,439✔
1183
   case JIT_VALUE_DOUBLE:
7,235✔
1184
      return llvm_real(obj, value.dval);
7,235✔
1185
   case JIT_ADDR_CPOOL:
13,457✔
1186
      assert(value.int64 >= 0 && value.int64 <= cgb->func->source->cpoolsz);
13,457✔
1187
      if (cgb->func->mode == CGEN_AOT) {
13,457✔
1188
         LLVMValueRef indexes[] = {
8,986✔
1189
            llvm_intptr(obj, 0),
8,986✔
1190
            llvm_intptr(obj, value.int64)
8,986✔
1191
         };
1192
         return LLVMBuildInBoundsGEP2(obj->builder, cgb->func->cpool_type,
8,986✔
1193
                                      cgb->func->cpool, indexes,
8,986✔
1194
                                      ARRAY_LEN(indexes), "");
1195
      }
1196
      else
1197
         return llvm_ptr(obj, cgb->func->source->cpool + value.int64);
4,471✔
1198
   case JIT_ADDR_REG:
305,909✔
1199
      {
1200
         assert(value.reg < cgb->func->source->nregs);
305,909✔
1201
         LLVMValueRef ptr = cgb->outregs[value.reg];
305,909✔
1202

1203
         if (value.disp == 0)
305,909✔
1204
            return ptr;
1205
         else if (llvm_is_ptr(ptr)) {
215,459✔
1206
            LLVMValueRef indexes[] = { llvm_intptr(obj, value.disp) };
202,648✔
1207
            return LLVMBuildGEP2(obj->builder,
202,648✔
1208
                                 obj->types[LLVM_INT8],
1209
                                 ptr, indexes, 1, "");
1210
         }
1211
         else {
1212
            LLVMValueRef disp = llvm_int64(obj, value.disp);
12,811✔
1213
            return LLVMBuildAdd(obj->builder, ptr, disp, "");
12,811✔
1214
         }
1215
      }
1216
   case JIT_VALUE_EXIT:
76,976✔
1217
      return llvm_int32(obj, value.exit);
76,976✔
1218
   case JIT_VALUE_HANDLE:
4,469✔
1219
      if (cgb->func->mode == CGEN_AOT && value.handle != JIT_HANDLE_INVALID)
4,469✔
1220
         return cgen_rematerialise_handle(obj, cgb->func, value.handle);
457✔
1221
      else
1222
         return llvm_int32(obj, value.handle);
4,012✔
1223
   case JIT_ADDR_ABS:
18,728✔
1224
      return llvm_ptr(obj, (void *)(intptr_t)value.int64);
18,728✔
1225
   case JIT_ADDR_COVER:
1,929✔
1226
      if (cgb->func->mode == CGEN_AOT) {
1,929✔
1227
         LLVMValueRef ptr =
1,567✔
1228
            cgen_load_from_reloc(obj, cgb->func, RELOC_COVER, 0);
1,567✔
1229
         LLVMValueRef base = LLVMBuildLoad2(obj->builder,
1,567✔
1230
                                            obj->types[LLVM_PTR], ptr, "");
1231
         LLVMValueRef indexes[] = {
1,567✔
1232
            llvm_intptr(obj, value.int64)
1,567✔
1233
         };
1234
         return LLVMBuildGEP2(obj->builder, obj->types[LLVM_INT32],
1,567✔
1235
                              base, indexes, 1, "");
1236
      }
1237
      else
1238
         return llvm_ptr(obj, jit_get_cover_ptr(cgb->func->source->jit, value));
362✔
1239
   case JIT_VALUE_LOCUS:
62,903✔
1240
      return cgen_rematerialise_object(obj, cgb->func, value.locus);
62,903✔
1241
   default:
×
1242
      fatal_trace("cannot handle value kind %d", value.kind);
1243
   }
1244
}
1245

1246
static LLVMValueRef cgen_coerce_value(llvm_obj_t *obj, cgen_block_t *cgb,
410,079✔
1247
                                      jit_value_t value, llvm_type_t type)
1248
{
1249
   LLVMValueRef raw = cgen_get_value(obj, cgb, value);
410,079✔
1250
   LLVMTypeRef lltype = LLVMTypeOf(raw);
410,079✔
1251

1252
   switch (type) {
410,079✔
1253
   case LLVM_PTR:
297,995✔
1254
      if (LLVMGetTypeKind(lltype) == LLVMIntegerTypeKind)
297,995✔
1255
         return LLVMBuildIntToPtr(obj->builder, raw, obj->types[LLVM_PTR], "");
34✔
1256
      else
1257
         return raw;
1258

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

1273
            if (bits2 == 1) {
97,823✔
1274
               LLVMValueRef zero = LLVMConstInt(lltype, 0, false);
2,181✔
1275
               return LLVMBuildICmp(obj->builder, LLVMIntNE, raw, zero, "");
2,181✔
1276
            }
1277
            else if (bits1 < bits2)
95,642✔
1278
               return LLVMBuildSExt(obj->builder, raw, obj->types[type], "");
190✔
1279
            else if (bits1 == bits2)
95,452✔
1280
               return raw;
1281
            else
1282
               return LLVMBuildTrunc(obj->builder, raw, obj->types[type], "");
48,876✔
1283
         }
1284
      case LLVMDoubleTypeKind:
507✔
1285
         return LLVMBuildBitCast(obj->builder, raw, obj->types[type], "");
507✔
1286
      default:
×
1287
         LLVMDumpType(lltype);
×
1288
         fatal_trace("cannot coerce type to integer");
1289
      }
1290
      break;
9,054✔
1291

1292
   case LLVM_DOUBLE:
9,054✔
1293
      return LLVMBuildBitCast(obj->builder, raw, obj->types[type], "");
9,054✔
1294

1295
   default:
1296
      return raw;
1297
   }
1298
}
1299

1300
static void cgen_pointer_result(llvm_obj_t *obj, cgen_block_t *cgb,
99,065✔
1301
                                jit_ir_t *ir, LLVMValueRef value)
1302
{
1303
   assert(llvm_is_ptr(value));
99,065✔
1304

1305
   if (mask_test(&cgb->func->ptr_mask, ir->result)) {
99,065✔
1306
      DEBUG_ONLY(llvm_set_value_name(value, cgen_reg_name(ir->result)));
98,998✔
1307
      cgb->outregs[ir->result] = PTR(value);
98,998✔
1308
   }
1309
   else
1310
      cgb->outregs[ir->result] = LLVMBuildPtrToInt(obj->builder, value,
67✔
1311
                                                   obj->types[LLVM_INT64],
1312
                                                   cgen_reg_name(ir->result));
1313
}
99,065✔
1314

1315
static void cgen_sext_result(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir,
168,040✔
1316
                             LLVMValueRef value)
1317
{
1318
   LLVMTypeRef type = LLVMTypeOf(value);
168,040✔
1319
   switch (LLVMGetTypeKind(type)) {
168,040✔
1320
   case LLVMIntegerTypeKind:
136,392✔
1321
      if (LLVMGetIntTypeWidth(type) == 64) {
136,392✔
1322
         DEBUG_ONLY(llvm_set_value_name(value, cgen_reg_name(ir->result)));
87,474✔
1323
         cgb->outregs[ir->result] = value;
87,474✔
1324
      }
1325
      else
1326
         cgb->outregs[ir->result] = LLVMBuildSExt(obj->builder, value,
48,918✔
1327
                                                  obj->types[LLVM_INT64],
1328
                                                  cgen_reg_name(ir->result));
48,918✔
1329
      break;
1330

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

1337
   case LLVMPointerTypeKind:
29,724✔
1338
      cgen_pointer_result(obj, cgb, ir, value);
29,724✔
1339
      break;
29,724✔
1340

1341
   default:
×
1342
      LLVMDumpType(type);
×
1343
      fatal_trace("unhandled LLVM type kind in cgen_sext_result");
1344
   }
1345
}
168,040✔
1346

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

1363
   default:
×
1364
      LLVMDumpType(type);
×
1365
      fatal_trace("unhandled LLVM type kind in cgen_sext_result");
1366
   }
1367
}
75,694✔
1368

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

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

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

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

1394
static void cgen_op_recv(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
102,053✔
1395
{
1396
   assert(ir->arg1.kind == JIT_VALUE_INT64);
102,053✔
1397
   const int nth = ir->arg1.int64;
102,053✔
1398

1399
   LLVMValueRef ptr;
102,053✔
1400
   if (nth < ARGCACHE_SIZE)
102,053✔
1401
      ptr = cgb->func->argcache[nth];
98,882✔
1402
   else {
1403
      assert(nth < JIT_MAX_ARGS);
3,171✔
1404
      LLVMValueRef indexes[] = { llvm_intptr(obj, nth) };
3,171✔
1405
      ptr = LLVMBuildInBoundsGEP2(obj->builder, obj->types[LLVM_INT64],
6,342✔
1406
                                  cgb->func->args, indexes, ARRAY_LEN(indexes),
3,171✔
1407
                                  cgen_arg_name(nth));
1408
   }
1409

1410
   llvm_type_t type =
204,106✔
1411
      mask_test(&cgb->func->ptr_mask, ir->result) ? LLVM_PTR : LLVM_INT64;
102,053✔
1412

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

1421
   cgb->outregs[ir->result] = LLVMBuildLoad2(obj->builder, obj->types[type],
102,053✔
1422
                                             cast, cgen_reg_name(ir->result));
102,053✔
1423
   LLVMSetAlignment(cgb->outregs[ir->result], sizeof(int64_t));
102,053✔
1424
}
102,053✔
1425

1426
static void cgen_op_send(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
588,873✔
1427
{
1428
   assert(ir->arg1.kind == JIT_VALUE_INT64);
588,873✔
1429
   const int nth = ir->arg1.int64;
588,873✔
1430

1431
   LLVMValueRef value = cgen_get_value(obj, cgb, ir->arg2);
588,873✔
1432

1433
   LLVMValueRef ptr;
588,873✔
1434
   if (nth < ARGCACHE_SIZE)
588,873✔
1435
      ptr = cgb->func->argcache[nth];
543,764✔
1436
   else {
1437
      assert(nth < JIT_MAX_ARGS);
45,109✔
1438
      LLVMValueRef indexes[] = { llvm_int32(obj, nth) };
45,109✔
1439
      LLVMTypeRef int64_type = obj->types[LLVM_INT64];
45,109✔
1440
#ifdef LLVM_HAS_OPAQUE_POINTERS
1441
      LLVMValueRef args_cast = cgb->func->args;
1442
#else
1443
      LLVMTypeRef args_ptr_type = LLVMPointerType(int64_type, 0);
45,109✔
1444
      LLVMValueRef args_cast =
45,109✔
1445
         LLVMBuildPointerCast(obj->builder, cgb->func->args, args_ptr_type, "");
45,109✔
1446
#endif
1447
      ptr = LLVMBuildInBoundsGEP2(obj->builder, int64_type,
45,109✔
1448
                                  args_cast, indexes, ARRAY_LEN(indexes),
1449
                                  cgen_arg_name(nth));
1450
   }
1451

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

1460
   LLVMSetAlignment(store, sizeof(int64_t));
588,873✔
1461
}
588,873✔
1462

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

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

1477
   LLVMSetAlignment(store, 1 << ir->size);
92,198✔
1478
}
92,198✔
1479

1480
static void cgen_op_load(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
171,107✔
1481
{
1482
   LLVMValueRef ptr = cgen_coerce_value(obj, cgb, ir->arg1, LLVM_PTR);
171,107✔
1483

1484
   llvm_type_t type = mask_test(&cgb->func->ptr_mask, ir->result)
171,107✔
1485
      ? LLVM_PTR : LLVM_INT8 + ir->size;
171,107✔
1486

1487
#ifndef LLVM_HAS_OPAQUE_POINTERS
1488
   LLVMTypeRef ptr_type = LLVMPointerType(obj->types[type], 0);
171,107✔
1489
   ptr = LLVMBuildPointerCast(obj->builder, ptr, ptr_type, "");
171,107✔
1490
#endif
1491

1492
   if (type == LLVM_INT64) {
171,107✔
1493
      LLVMValueRef value = LLVMBuildLoad2(obj->builder, obj->types[type],
85,222✔
1494
                                          ptr, cgen_reg_name(ir->result));
85,222✔
1495
      LLVMSetAlignment(value, 1 << ir->size);
85,222✔
1496
      cgb->outregs[ir->result] = value;
85,222✔
1497
   }
1498
   else {
1499
      LLVMValueRef tmp =
85,885✔
1500
         LLVMBuildLoad2(obj->builder, obj->types[type], ptr, "");
85,885✔
1501
      LLVMSetAlignment(tmp, 1 << ir->size);
85,885✔
1502
      if (ir->op == J_ULOAD)
85,885✔
1503
         cgen_zext_result(obj, cgb, ir, tmp);
13,905✔
1504
      else
1505
         cgen_sext_result(obj, cgb, ir, tmp);
71,980✔
1506
   }
1507
}
171,107✔
1508

1509
static void cgen_op_add(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
74,574✔
1510
{
1511
   llvm_fn_t fn = LLVM_LAST_FN;
74,574✔
1512
   if (ir->cc == JIT_CC_O)
74,574✔
1513
      fn = LLVM_ADD_OVERFLOW_S8 + ir->size;
1,455✔
1514
   else if (ir->cc == JIT_CC_C)
73,119✔
1515
      fn = LLVM_ADD_OVERFLOW_U8 + ir->size;
6✔
1516

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

1522
      LLVMValueRef args[] = { arg1, arg2 };
1,461✔
1523
      LLVMValueRef pair = llvm_call_fn(obj, fn, args, 2);
1,461✔
1524

1525
      LLVMValueRef result = LLVMBuildExtractValue(obj->builder, pair, 0, "");
1,461✔
1526
      cgb->outflags = LLVMBuildExtractValue(obj->builder, pair, 1, "FLAGS");
1,461✔
1527

1528
      if (ir->cc == JIT_CC_C)
1,461✔
1529
         cgen_zext_result(obj, cgb, ir, result);
6✔
1530
      else
1531
         cgen_sext_result(obj, cgb, ir, result);
1,455✔
1532
   }
1533
   else {
1534
      LLVMValueRef arg1 = cgen_get_value(obj, cgb, ir->arg1);
73,113✔
1535
      LLVMValueRef arg2 = cgen_get_value(obj, cgb, ir->arg2);
73,113✔
1536

1537
      if (llvm_is_ptr(arg1)) {
73,113✔
1538
         LLVMValueRef indexes[] = { arg2 };
5,848✔
1539
         LLVMValueRef ptr = LLVMBuildGEP2(obj->builder, obj->types[LLVM_INT8],
5,848✔
1540
                                          arg1, indexes, 1, "");
1541
         cgen_pointer_result(obj, cgb, ir, ptr);
5,848✔
1542
      }
1543
      else if (mask_test(&cgb->func->ptr_mask, ir->result)) {
67,265✔
1544
         LLVMValueRef base =
16,802✔
1545
            LLVMBuildIntToPtr(obj->builder, arg1, obj->types[LLVM_PTR], "");
16,802✔
1546
         LLVMValueRef indexes[] = { arg2 };
16,802✔
1547
         LLVMValueRef ptr = LLVMBuildGEP2(obj->builder, obj->types[LLVM_INT8],
16,802✔
1548
                                          base, indexes, 1, "");
1549
         cgen_pointer_result(obj, cgb, ir, ptr);
16,802✔
1550
      }
1551
      else
1552
         cgb->outregs[ir->result] = LLVMBuildAdd(obj->builder, arg1, arg2,
50,463✔
1553
                                                 cgen_reg_name(ir->result));
1554
   }
1555
}
74,574✔
1556

1557
static void cgen_op_sub(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
30,402✔
1558
{
1559
   llvm_fn_t fn = LLVM_LAST_FN;
30,402✔
1560
   if (ir->cc == JIT_CC_O)
30,402✔
1561
      fn = LLVM_SUB_OVERFLOW_S8 + ir->size;
974✔
1562
   else if (ir->cc == JIT_CC_C)
29,428✔
1563
      fn = LLVM_SUB_OVERFLOW_U8 + ir->size;
×
1564

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

1570
      LLVMValueRef args[] = { arg1, arg2 };
974✔
1571
      LLVMValueRef pair = llvm_call_fn(obj, fn, args, 2);
974✔
1572

1573
      LLVMValueRef result = LLVMBuildExtractValue(obj->builder, pair, 0, "");
974✔
1574
      cgb->outflags = LLVMBuildExtractValue(obj->builder, pair, 1, "FLAGS");
974✔
1575

1576
      if (ir->cc == JIT_CC_C)
974✔
1577
         cgen_zext_result(obj, cgb, ir, result);
×
1578
      else
1579
         cgen_sext_result(obj, cgb, ir, result);
974✔
1580
   }
1581
   else {
1582
      LLVMValueRef arg1 = cgen_get_value(obj, cgb, ir->arg1);
29,428✔
1583
      LLVMValueRef arg2 = cgen_get_value(obj, cgb, ir->arg2);
29,428✔
1584
      cgb->outregs[ir->result] = LLVMBuildSub(obj->builder, arg1, arg2,
29,428✔
1585
                                              cgen_reg_name(ir->result));
29,428✔
1586
   }
1587
}
30,402✔
1588

1589
static void cgen_op_mul(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
1,383✔
1590
{
1591
   llvm_fn_t fn = LLVM_LAST_FN;
1,383✔
1592
   if (ir->cc == JIT_CC_O)
1,383✔
1593
      fn = LLVM_MUL_OVERFLOW_S8 + ir->size;
234✔
1594
   else if (ir->cc == JIT_CC_C)
1,149✔
1595
      fn = LLVM_MUL_OVERFLOW_U8 + ir->size;
×
1596

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

1602
      LLVMValueRef args[] = { arg1, arg2 };
234✔
1603
      LLVMValueRef pair = llvm_call_fn(obj, fn, args, 2);
234✔
1604

1605
      LLVMValueRef result = LLVMBuildExtractValue(obj->builder, pair, 0, "");
234✔
1606
      cgb->outflags = LLVMBuildExtractValue(obj->builder, pair, 1, "FLAGS");
234✔
1607

1608
      if (ir->cc == JIT_CC_C)
234✔
1609
         cgen_zext_result(obj, cgb, ir, result);
×
1610
      else
1611
         cgen_sext_result(obj, cgb, ir, result);
234✔
1612
   }
1613
   else {
1614
      LLVMValueRef arg1 = cgen_get_value(obj, cgb, ir->arg1);
1,149✔
1615
      LLVMValueRef arg2 = cgen_get_value(obj, cgb, ir->arg2);
1,149✔
1616
      cgb->outregs[ir->result] = LLVMBuildMul(obj->builder, arg1, arg2,
1,149✔
1617
                                              cgen_reg_name(ir->result));
1,149✔
1618
   }
1619
}
1,383✔
1620

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

1626
   cgb->outregs[ir->result] = LLVMBuildSDiv(obj->builder, arg1, arg2,
502✔
1627
                                            cgen_reg_name(ir->result));
502✔
1628
}
502✔
1629

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

1635
   cgb->outregs[ir->result] = LLVMBuildSRem(obj->builder, arg1, arg2,
190✔
1636
                                            cgen_reg_name(ir->result));
190✔
1637
}
190✔
1638

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

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

1648
static void cgen_op_asr(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
18,326✔
1649
{
1650
   LLVMValueRef arg1 = cgen_get_value(obj, cgb, ir->arg1);
18,326✔
1651
   LLVMValueRef arg2 = cgen_get_value(obj, cgb, ir->arg2);
18,326✔
1652

1653
   cgb->outregs[ir->result] = LLVMBuildAShr(obj->builder, arg1, arg2,
18,326✔
1654
                                            cgen_reg_name(ir->result));
18,326✔
1655
}
18,326✔
1656

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1735
   LLVMValueRef logical = LLVMBuildAnd(obj->builder, arg1, arg2, "");
3,571✔
1736
   cgen_zext_result(obj, cgb, ir, logical);
3,571✔
1737
}
3,571✔
1738

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

1744
   LLVMValueRef logical = LLVMBuildOr(obj->builder, arg1, arg2, "");
1,610✔
1745
   cgen_zext_result(obj, cgb, ir, logical);
1,610✔
1746
}
1,610✔
1747

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

1753
   LLVMValueRef logical = LLVMBuildXor(obj->builder, arg1, arg2, "");
25,693✔
1754
   cgen_zext_result(obj, cgb, ir, logical);
25,693✔
1755
}
25,693✔
1756

1757
static void cgen_op_ret(llvm_obj_t *obj, jit_ir_t *ir)
40,416✔
1758
{
1759
   LLVMBuildRetVoid(obj->builder);
40,416✔
1760
}
40,416✔
1761

1762
static void cgen_op_jump(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
109,902✔
1763
{
1764
   if (ir->cc == JIT_CC_NONE) {
109,902✔
1765
      assert(cgb->source->out.count == 1);
27,112✔
1766
      LLVMBasicBlockRef dest =
54,224✔
1767
         cgb->func->blocks[jit_get_edge(&(cgb->source->out), 0)].bbref;
27,112✔
1768
      LLVMBuildBr(obj->builder, dest);
27,112✔
1769
   }
1770
   else if (ir->cc == JIT_CC_T) {
82,790✔
1771
      assert(cgb->source->out.count == 2);
67,624✔
1772
      LLVMBasicBlockRef dest_t =
135,248✔
1773
         cgb->func->blocks[jit_get_edge(&(cgb->source->out), 1)].bbref;
67,624✔
1774
      LLVMBasicBlockRef dest_f = (cgb + 1)->bbref;
67,624✔
1775
      LLVMBuildCondBr(obj->builder, cgb->outflags, dest_t, dest_f);
67,624✔
1776
   }
1777
   else if (ir->cc == JIT_CC_F) {
15,166✔
1778
      assert(cgb->source->out.count == 2);
15,166✔
1779
      LLVMBasicBlockRef dest_t =
30,332✔
1780
         cgb->func->blocks[jit_get_edge(&(cgb->source->out), 1)].bbref;
15,166✔
1781
      LLVMBasicBlockRef dest_f = (cgb + 1)->bbref;
15,166✔
1782
      LLVMBuildCondBr(obj->builder, cgb->outflags, dest_f, dest_t);
15,166✔
1783
   }
1784
   else
1785
      cgen_abort(cgb, ir, "unhandled jump condition code");
×
1786
}
109,902✔
1787

1788
static void cgen_op_cmp(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
128,845✔
1789
{
1790
   LLVMValueRef arg1 = cgen_get_value(obj, cgb, ir->arg1);
128,845✔
1791
   LLVMValueRef arg2 = cgen_get_value(obj, cgb, ir->arg2);
128,845✔
1792

1793
   const bool arg1_ptr = llvm_is_ptr(arg1);
128,845✔
1794
   const bool arg2_ptr = llvm_is_ptr(arg2);
128,845✔
1795

1796
   if (arg1_ptr && !arg2_ptr)
128,845✔
1797
      arg2 = LLVMBuildIntToPtr(obj->builder, arg2, obj->types[LLVM_PTR], "");
10,270✔
1798
   else if (!arg1_ptr && arg2_ptr)
118,575✔
1799
      arg1 = LLVMBuildIntToPtr(obj->builder, arg1, obj->types[LLVM_PTR], "");
9,569✔
1800

1801
   LLVMIntPredicate pred = cgen_int_pred(cgb, ir);
128,845✔
1802
   cgb->outflags = LLVMBuildICmp(obj->builder, pred, arg1, arg2, "FLAGS");
128,845✔
1803
}
128,845✔
1804

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

1810
   const bool arg1_ptr = llvm_is_ptr(arg1);
11,601✔
1811
   const bool arg2_ptr = llvm_is_ptr(arg2);
11,601✔
1812

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

1818
   LLVMIntPredicate pred = cgen_int_pred(cgb, ir);
11,601✔
1819
   LLVMValueRef cmp = LLVMBuildICmp(obj->builder, pred, arg1, arg2, "");
11,601✔
1820

1821
   cgb->outflags = LLVMBuildAnd(obj->builder, cgb->outflags, cmp, "FLAGS");
11,601✔
1822
}
11,601✔
1823

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

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

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

1838
   LLVMRealPredicate pred = cgen_real_pred(cgb, ir);
699✔
1839
   LLVMValueRef cmp = LLVMBuildFCmp(obj->builder, pred, arg1, arg2, "");
699✔
1840

1841
   cgb->outflags = LLVMBuildAnd(obj->builder, cgb->outflags, cmp, "FLAGS");
699✔
1842
}
699✔
1843

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

1849
static void cgen_op_csel(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
43,041✔
1850
{
1851
   LLVMValueRef arg1 = cgen_get_value(obj, cgb, ir->arg1);
43,041✔
1852
   LLVMValueRef arg2 = cgen_get_value(obj, cgb, ir->arg2);
43,041✔
1853

1854
   LLVMValueRef result =
43,041✔
1855
      LLVMBuildSelect(obj->builder, cgb->outflags, arg1, arg2, "");
43,041✔
1856

1857
   cgen_sext_result(obj, cgb, ir, result);
43,041✔
1858
}
43,041✔
1859

1860
static void cgen_op_call(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
37,706✔
1861
{
1862
   cgen_sync_irpos(obj, cgb, ir);
37,706✔
1863

1864
   jit_func_t *callee = jit_get_func(cgb->func->source->jit, ir->arg1.handle);
37,706✔
1865

1866
   LLVMValueRef entry = NULL, fptr = NULL;
37,706✔
1867
   if (cgb->func->mode == CGEN_AOT) {
37,706✔
1868
      cgen_reloc_t *reloc = cgen_find_reloc(cgb->func->relocs, RELOC_FUNC,
25,381✔
1869
                                            INT_MAX, ir->arg1.handle);
25,381✔
1870
      assert(reloc != NULL);
25,381✔
1871

1872
      LLVMValueRef array =
25,381✔
1873
         LLVMBuildStructGEP2(obj->builder, cgb->func->descr_type,
25,381✔
1874
                             cgb->func->descr, 4, "");
1875

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

1887
      fptr = LLVMBuildLoad2(obj->builder, obj->types[LLVM_PTR], ptr, "");
25,381✔
1888

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

1900
   if (entry == NULL) {
37,706✔
1901
      // Must have acquire semantics to synchronise with installing new code
1902
      entry = LLVMBuildLoad2(obj->builder, obj->types[LLVM_PTR], fptr, "entry");
22,371✔
1903
      LLVMSetAlignment(entry, sizeof(void *));
22,371✔
1904
      LLVMSetOrdering(entry, LLVMAtomicOrderingAcquire);
22,371✔
1905
   }
1906

1907
#ifndef LLVM_HAS_OPAQUE_POINTERS
1908
   LLVMTypeRef ptr_type = LLVMPointerType(obj->types[LLVM_ENTRY_FN], 0);
37,706✔
1909
   entry = LLVMBuildPointerCast(obj->builder, entry, ptr_type, "");
37,706✔
1910
#endif
1911

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

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

1926
   if (llvm_is_ptr(ptr))
19,813✔
1927
      cgen_pointer_result(obj, cgb, ir, ptr);
8,749✔
1928
   else
1929
      cgen_zext_result(obj, cgb, ir, ptr);
11,064✔
1930
}
19,813✔
1931

1932
static void cgen_op_mov(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
48,525✔
1933
{
1934
   LLVMValueRef value = cgen_get_value(obj, cgb, ir->arg1);
48,525✔
1935
   cgen_sext_result(obj, cgb, ir, value);
48,525✔
1936
}
48,525✔
1937

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

1944
   cgb->outregs[ir->result] = neg;
5,961✔
1945
}
5,961✔
1946

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

1954
   cgb->outregs[ir->result] = clamp;
11,381✔
1955
}
11,381✔
1956

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

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

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

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

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

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

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

1989
   cgen_sext_result(obj, cgb, ir, real);
63✔
1990
}
63✔
1991

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

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

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

2019
   LLVMBuildMemMove(obj->builder, dest, 0, src, 0, count);
7,555✔
2020
}
7,555✔
2021

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

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

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

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

2070
static void cgen_macro_exit(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
88,202✔
2071
{
2072
   cgen_sync_irpos(obj, cgb, ir);
88,202✔
2073

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

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

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

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

2119
   default:
76,976✔
2120
      {
2121
         LLVMValueRef which = cgen_get_value(obj, cgb, ir->arg1);
76,976✔
2122

2123
         LLVMValueRef args[] = {
76,976✔
2124
            which,
2125
            PTR(cgb->func->anchor),
76,976✔
2126
            cgb->func->args,
76,976✔
2127
            cgb->func->tlab,
76,976✔
2128
         };
2129
         llvm_call_fn(obj, LLVM_DO_EXIT, args, ARRAY_LEN(args));
76,976✔
2130
      }
2131
      break;
76,976✔
2132
   }
2133
}
88,202✔
2134

2135
static void cgen_macro_galloc(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
406✔
2136
{
2137
   cgen_sync_irpos(obj, cgb, ir);
406✔
2138

2139
   LLVMValueRef size = cgen_get_value(obj, cgb, ir->arg1);
406✔
2140

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

2148
   cgen_pointer_result(obj, cgb, ir, ptr);
406✔
2149
}
406✔
2150

2151
static void cgen_macro_lalloc(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
16,415✔
2152
{
2153
   cgen_sync_irpos(obj, cgb, ir);
16,415✔
2154

2155
   LLVMValueRef size = cgen_get_value(obj, cgb, ir->arg1);
16,415✔
2156

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

2165
   cgen_pointer_result(obj, cgb, ir, ptr);
16,415✔
2166
}
16,415✔
2167

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

2174
   assert(ir->arg2.kind == JIT_VALUE_INT64);
5,616✔
2175

2176
   LLVMValueRef ptr;
5,616✔
2177
   if (ir->arg2.int64 <= 8)
5,616✔
2178
      ptr = LLVMBuildAlloca(obj->builder, obj->types[LLVM_INT64], "");
1,914✔
2179
   else
2180
      ptr = LLVMBuildArrayAlloca(obj->builder, obj->types[LLVM_INT8],
3,702✔
2181
                                 llvm_intptr(obj, ir->arg2.int64), "");
2182

2183
   LLVMPositionBuilderAtEnd(obj->builder, old_bb);
5,616✔
2184

2185
   cgen_pointer_result(obj, cgb, ir, ptr);
5,616✔
2186
}
5,616✔
2187

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

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

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

2209
   cgen_pointer_result(obj, cgb, ir, ptr);
15,505✔
2210
}
15,505✔
2211

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

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

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

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

2243
   LLVMBasicBlockRef elsebb = (cgb + 1)->bbref;
3,134✔
2244

2245
   LLVMValueRef test = cgb->outregs[ir->result];
3,134✔
2246
   assert(test != NULL);
3,134✔
2247

2248
   jit_ir_t *last = cgb->func->source->irbuf + cgb->source->last;
3,134✔
2249

2250
   const int numcases = last - ir + 1;
3,134✔
2251
   assert(cgb->source->out.count == numcases + 1);
3,134✔
2252

2253
   LLVMValueRef stmt = LLVMBuildSwitch(obj->builder, test, elsebb, numcases);
3,134✔
2254

2255
   for (int nth = 0; nth < numcases; ir++, nth++) {
15,580✔
2256
      assert(ir->op == MACRO_CASE);
12,446✔
2257

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

2262
      LLVMAddCase(stmt, onval, dest);
12,446✔
2263
   }
2264
}
2265

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

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

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

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

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

2305
   LLVMBuildRetVoid(obj->builder);
179✔
2306
}
179✔
2307

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

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

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

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

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

2327
static void cgen_ir(llvm_obj_t *obj, cgen_block_t *cgb, jit_ir_t *ir)
2,358,299✔
2328
{
2329
   switch (ir->op) {
2,358,299✔
2330
   case J_RECV:
102,053✔
2331
      cgen_op_recv(obj, cgb, ir);
102,053✔
2332
      break;
102,053✔
2333
   case J_SEND:
588,873✔
2334
      cgen_op_send(obj, cgb, ir);
588,873✔
2335
      break;
588,873✔
2336
   case J_STORE:
92,198✔
2337
      cgen_op_store(obj, cgb, ir);
92,198✔
2338
      break;
92,198✔
2339
   case J_LOAD:
171,107✔
2340
   case J_ULOAD:
2341
      cgen_op_load(obj, cgb, ir);
171,107✔
2342
      break;
171,107✔
2343
   case J_ADD:
74,574✔
2344
      cgen_op_add(obj, cgb, ir);
74,574✔
2345
      break;
74,574✔
2346
   case J_SUB:
30,402✔
2347
      cgen_op_sub(obj, cgb, ir);
30,402✔
2348
      break;
30,402✔
2349
   case J_MUL:
1,383✔
2350
      cgen_op_mul(obj, cgb, ir);
1,383✔
2351
      break;
1,383✔
2352
   case J_DIV:
502✔
2353
      cgen_op_div(obj, cgb, ir);
502✔
2354
      break;
502✔
2355
   case J_REM:
190✔
2356
      cgen_op_rem(obj, cgb, ir);
190✔
2357
      break;
190✔
2358
   case J_SHL:
9,182✔
2359
      cgen_op_shl(obj, cgb, ir);
9,182✔
2360
      break;
9,182✔
2361
   case J_ASR:
18,326✔
2362
      cgen_op_asr(obj, cgb, ir);
18,326✔
2363
      break;
18,326✔
2364
   case J_FADD:
245✔
2365
      cgen_op_fadd(obj, cgb, ir);
245✔
2366
      break;
245✔
2367
   case J_FSUB:
266✔
2368
      cgen_op_fsub(obj, cgb, ir);
266✔
2369
      break;
266✔
2370
   case J_FMUL:
528✔
2371
      cgen_op_fmul(obj, cgb, ir);
528✔
2372
      break;
528✔
2373
   case J_FDIV:
187✔
2374
      cgen_op_fdiv(obj, cgb, ir);
187✔
2375
      break;
187✔
2376
   case J_FNEG:
304✔
2377
      cgen_op_fneg(obj, cgb, ir);
304✔
2378
      break;
304✔
2379
   case J_FCVTNS:
58✔
2380
      cgen_op_fcvtns(obj, cgb, ir);
58✔
2381
      break;
58✔
2382
   case J_SCVTF:
152✔
2383
      cgen_op_scvtf(obj, cgb, ir);
152✔
2384
      break;
152✔
2385
   case J_NOT:
2,181✔
2386
      cgen_op_not(obj, cgb, ir);
2,181✔
2387
      break;
2,181✔
2388
   case J_AND:
3,571✔
2389
      cgen_op_and(obj, cgb, ir);
3,571✔
2390
      break;
3,571✔
2391
   case J_OR:
1,610✔
2392
      cgen_op_or(obj, cgb, ir);
1,610✔
2393
      break;
1,610✔
2394
   case J_XOR:
25,693✔
2395
      cgen_op_xor(obj, cgb, ir);
25,693✔
2396
      break;
25,693✔
2397
   case J_RET:
40,416✔
2398
      cgen_op_ret(obj, ir);
40,416✔
2399
      break;
40,416✔
2400
   case J_JUMP:
109,902✔
2401
      cgen_op_jump(obj, cgb, ir);
109,902✔
2402
      break;
109,902✔
2403
   case J_CMP:
128,845✔
2404
      cgen_op_cmp(obj, cgb, ir);
128,845✔
2405
      break;
128,845✔
2406
   case J_CCMP:
11,601✔
2407
      cgen_op_ccmp(obj, cgb, ir);
11,601✔
2408
      break;
11,601✔
2409
   case J_FCMP:
2,358✔
2410
      cgen_op_fcmp(obj, cgb, ir);
2,358✔
2411
      break;
2,358✔
2412
   case J_FCCMP:
699✔
2413
      cgen_op_fccmp(obj, cgb, ir);
699✔
2414
      break;
699✔
2415
   case J_CSET:
17,656✔
2416
      cgen_op_cset(obj, cgb, ir);
17,656✔
2417
      break;
17,656✔
2418
   case J_CSEL:
43,041✔
2419
      cgen_op_csel(obj, cgb, ir);
43,041✔
2420
      break;
43,041✔
2421
   case J_CALL:
37,706✔
2422
      cgen_op_call(obj, cgb, ir);
37,706✔
2423
      break;
37,706✔
2424
   case J_LEA:
19,813✔
2425
      cgen_op_lea(obj, cgb, ir);
19,813✔
2426
      break;
19,813✔
2427
   case J_MOV:
48,525✔
2428
      cgen_op_mov(obj, cgb, ir);
48,525✔
2429
      break;
48,525✔
2430
   case J_NEG:
5,961✔
2431
      cgen_op_neg(obj, cgb, ir);
5,961✔
2432
      break;
5,961✔
2433
   case J_CLAMP:
11,381✔
2434
      cgen_op_clamp(obj, cgb, ir);
11,381✔
2435
      break;
11,381✔
2436
   case J_DEBUG:
2437
      DWARF_ONLY(cgen_debug_loc(obj, cgb->func, &(ir->arg1.loc)));
2438
      break;
2439
   case J_TRAP:
2440
   case J_NOP:
2441
      break;
2442
   case MACRO_EXP:
94✔
2443
      cgen_macro_exp(obj, cgb, ir);
94✔
2444
      break;
94✔
2445
   case MACRO_FEXP:
63✔
2446
      cgen_macro_fexp(obj, cgb, ir);
63✔
2447
      break;
63✔
2448
   case MACRO_COPY:
3,164✔
2449
      cgen_macro_copy(obj, cgb, ir);
3,164✔
2450
      break;
3,164✔
2451
   case MACRO_MOVE:
7,555✔
2452
      cgen_macro_move(obj, cgb, ir);
7,555✔
2453
      break;
7,555✔
2454
   case MACRO_BZERO:
3,212✔
2455
      cgen_macro_bzero(obj, cgb, ir);
3,212✔
2456
      break;
3,212✔
2457
   case MACRO_MEMSET:
1,196✔
2458
      cgen_macro_memset(obj, cgb, ir);
1,196✔
2459
      break;
1,196✔
2460
   case MACRO_EXIT:
88,202✔
2461
      cgen_macro_exit(obj, cgb, ir);
88,202✔
2462
      break;
88,202✔
2463
   case MACRO_GALLOC:
406✔
2464
      cgen_macro_galloc(obj, cgb, ir);
406✔
2465
      break;
406✔
2466
   case MACRO_LALLOC:
16,415✔
2467
      cgen_macro_lalloc(obj, cgb, ir);
16,415✔
2468
      break;
16,415✔
2469
   case MACRO_SALLOC:
5,616✔
2470
      cgen_macro_salloc(obj, cgb, ir);
5,616✔
2471
      break;
5,616✔
2472
   case MACRO_GETPRIV:
15,505✔
2473
      cgen_macro_getpriv(obj, cgb, ir);
15,505✔
2474
      break;
15,505✔
2475
   case MACRO_PUTPRIV:
6,915✔
2476
      cgen_macro_putpriv(obj, cgb, ir);
6,915✔
2477
      break;
6,915✔
2478
   case MACRO_CASE:
12,446✔
2479
      cgen_macro_case(obj, cgb, ir);
12,446✔
2480
      break;
12,446✔
2481
   case MACRO_TRIM:
2,494✔
2482
      cgen_macro_trim(obj, cgb, ir);
2,494✔
2483
      break;
2,494✔
2484
   case MACRO_REEXEC:
179✔
2485
      cgen_macro_reexec(obj, cgb, ir);
179✔
2486
      break;
179✔
2487
   case MACRO_SADD:
1,929✔
2488
      cgen_macro_sadd(obj, cgb, ir);
1,929✔
2489
      break;
1,929✔
2490
   default:
×
2491
      cgen_abort(cgb, ir, "cannot generate LLVM for %s", jit_op_name(ir->op));
×
2492
   }
2493
}
2,358,299✔
2494

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

2500
   for (int i = 0; i < cfg->nblocks; i++) {
240,670✔
2501
#ifdef DEBUG
2502
      char name[32];
217,918✔
2503
      checked_sprintf(name, sizeof(name), "BB%d", i);
217,918✔
2504
#else
2505
      const char *name = "";
2506
#endif
2507

2508
      cgen_block_t *cgb = &(func->blocks[i]);
217,918✔
2509
      cgb->bbref  = llvm_append_block(obj, func->llvmfn, name);
217,918✔
2510
      cgb->source = &(cfg->blocks[i]);
217,918✔
2511
      cgb->func   = func;
217,918✔
2512

2513
      cgb->inregs  = xcalloc_array(func->source->nregs, sizeof(LLVMValueRef));
217,918✔
2514
      cgb->outregs = xcalloc_array(func->source->nregs, sizeof(LLVMValueRef));
217,918✔
2515
   }
2516
}
22,752✔
2517

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

2523
   LLVMValueRef func_arg = LLVMGetParam(func->llvmfn, 0);
22,752✔
2524
   LLVMSetValueName(func_arg, "func");
22,752✔
2525

2526
   LLVMValueRef caller_arg = LLVMGetParam(func->llvmfn, 1);
22,752✔
2527
   LLVMSetValueName(caller_arg, "caller");
22,752✔
2528

2529
   LLVMValueRef caller_ptr = LLVMBuildStructGEP2(obj->builder, type,
22,752✔
2530
                                                 func->anchor, 0, "");
2531
   LLVMBuildStore(obj->builder, caller_arg, caller_ptr);
22,752✔
2532

2533
   LLVMValueRef func_ptr = LLVMBuildStructGEP2(obj->builder, type,
22,752✔
2534
                                               func->anchor, 1, "");
2535
   LLVMBuildStore(obj->builder, func_arg, func_ptr);
22,752✔
2536

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

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

2551
static void cgen_aot_cpool(llvm_obj_t *obj, cgen_func_t *func)
14,809✔
2552
{
2553
   jit_func_t *f = func->source;
14,809✔
2554

2555
   LOCAL_TEXT_BUF tb = tb_new();
29,618✔
2556
   tb_istr(tb, f->name);
14,809✔
2557
   tb_cat(tb, ".cpool");
14,809✔
2558

2559
   LLVMTypeRef array_type = LLVMArrayType(obj->types[LLVM_INT8], f->cpoolsz);
14,809✔
2560

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

2566
   LLVMValueRef *data LOCAL = xmalloc_array(f->cpoolsz, sizeof(LLVMValueRef));
14,809✔
2567
   for (int i = 0; i < f->cpoolsz; i++)
534,999✔
2568
      data[i] = llvm_int8(obj, f->cpool[i]);
520,190✔
2569

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

2574
   func->cpool = global;
14,809✔
2575
   func->cpool_type = array_type;
14,809✔
2576
}
14,809✔
2577

2578
static LLVMValueRef cgen_debug_irbuf(llvm_obj_t *obj, jit_func_t *f)
14,809✔
2579
{
2580
   LOCAL_TEXT_BUF tb = tb_new();
29,618✔
2581
   tb_istr(tb, f->name);
14,809✔
2582
   tb_cat(tb, ".debug");
14,809✔
2583

2584
   size_t size = 0;
14,809✔
2585
   uint8_t *buf LOCAL = NULL;
29,618✔
2586
   pack_writer_emit(obj->pack_writer, f->jit, f->handle, &buf, &size);
14,809✔
2587

2588
   LLVMValueRef *data LOCAL = xmalloc_array(size, sizeof(LLVMValueRef));
14,809✔
2589
   for (size_t i = 0; i < size; i++)
5,677,885✔
2590
      data[i] = llvm_int8(obj, buf[i]);
5,663,076✔
2591

2592
   LLVMTypeRef array_type = LLVMArrayType(obj->types[LLVM_INT8], size);
14,809✔
2593

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

2599
   LLVMValueRef init = LLVMConstArray(obj->types[LLVM_INT8], data, size);
14,809✔
2600
   LLVMSetInitializer(global, init);
14,809✔
2601

2602
   return global;
14,809✔
2603
}
2604

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

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

2615
   A(cgen_reloc_t) relocs = AINIT;
14,809✔
2616

2617
   for (int i = 0; i < func->source->nirs; i++) {
1,634,379✔
2618
      jit_ir_t *ir = &(func->source->irbuf[i]);
1,619,570✔
2619
      if (ir->op == J_CALL || ir->op == MACRO_GETPRIV
1,619,570✔
2620
          || ir->op == MACRO_PUTPRIV) {
1,584,786✔
2621
         // Special handling of JIT_VALUE_HANDLE arguments
2622
         reloc_kind_t kind = ir->op == J_CALL ? RELOC_FUNC : RELOC_PRIVDATA;
38,310✔
2623
         if (cgen_find_reloc(relocs.items, kind, relocs.count,
38,310✔
2624
                             ir->arg1.handle) == NULL) {
38,310✔
2625
            jit_func_t *f = jit_get_func(func->source->jit, ir->arg1.handle);
26,420✔
2626
            const cgen_reloc_t r = {
52,840✔
2627
               .kind = kind,
2628
               .str  = cgen_reloc_str(obj, istr(f->name)),
26,420✔
2629
               .key  = ir->arg1.handle,
26,420✔
2630
               .nth  = relocs.count,
26,420✔
2631
            };
2632
            APUSH(relocs, r);
26,420✔
2633
         }
2634
      }
2635
      else {
2636
         jit_value_t args[2] = { ir->arg1, ir->arg2 };
1,581,260✔
2637
         for (int j = 0; j < ARRAY_LEN(args); j++) {
4,743,780✔
2638
            if (args[j].kind == JIT_VALUE_HANDLE
3,162,520✔
2639
                && args[j].handle != JIT_HANDLE_INVALID) {
542✔
2640
               if (cgen_find_reloc(relocs.items, RELOC_HANDLE, relocs.count,
457✔
2641
                                   args[j].handle) == NULL) {
2642
                  ident_t name = jit_get_name(func->source->jit,
377✔
2643
                                              args[j].handle);
2644

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

2668
   APUSH(relocs, (cgen_reloc_t){ .kind = RELOC_NULL });
14,809✔
2669
   func->relocs = relocs.items;
14,809✔
2670

2671
   func->reloc_type = LLVMArrayType(obj->types[LLVM_AOT_RELOC], relocs.count);
14,809✔
2672

2673
   LLVMValueRef *reloc_elems LOCAL =
29,618✔
2674
      xmalloc_array(relocs.count, sizeof(LLVMValueRef));
14,809✔
2675

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

2685
   LLVMValueRef reloc_array = LLVMConstArray(obj->types[LLVM_AOT_RELOC],
14,809✔
2686
                                             reloc_elems, relocs.count);
2687

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

2698
   char *name LOCAL = xasprintf("%s.descr", func->name);
29,618✔
2699
   func->descr = LLVMAddGlobal(obj->module, func->descr_type, name);
14,809✔
2700
#ifdef IMPLIB_REQUIRED
2701
   LLVMSetDLLStorageClass(func->descr, LLVMDLLExportStorageClass);
2702
#endif
2703

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

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

2721
   char *basec LOCAL = xstrdup(file_path);
2722
   char *dirc LOCAL = xstrdup(file_path);
2723

2724
   const char *file = basename(basec);
2725
   const size_t file_len = strlen(file);
2726

2727
   const char *dir = dirname(dirc);
2728
   const size_t dir_len = strlen(dir);
2729

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

2734
static void cgen_must_be_pointer(cgen_func_t *func, jit_value_t value)
296,799✔
2735
{
2736
   switch (value.kind) {
296,799✔
2737
   case JIT_VALUE_REG:
291,613✔
2738
   case JIT_ADDR_REG:
2739
      mask_set(&(func->ptr_mask), value.reg);
291,613✔
2740
      break;
2741
   default:
2742
      break;
2743
   }
2744
}
296,799✔
2745

2746
static void cgen_pointer_mask(cgen_func_t *func)
22,752✔
2747
{
2748
   mask_init(&(func->ptr_mask), func->source->nregs);
22,752✔
2749

2750
   for (int i = 0; i < func->source->nirs; i++) {
2,381,051✔
2751
      jit_ir_t *ir = &(func->source->irbuf[i]);
2,358,299✔
2752

2753
      switch (ir->op) {
2,358,299✔
2754
      case J_LOAD:
176,248✔
2755
      case J_ULOAD:
2756
      case MACRO_BZERO:
2757
      case MACRO_SADD:
2758
         cgen_must_be_pointer(func, ir->arg1);
176,248✔
2759
         break;
176,248✔
2760
      case J_STORE:
99,113✔
2761
      case MACRO_PUTPRIV:
2762
         cgen_must_be_pointer(func, ir->arg2);
99,113✔
2763
         break;
99,113✔
2764
      case MACRO_COPY:
10,719✔
2765
      case MACRO_MOVE:
2766
         cgen_must_be_pointer(func, ir->arg1);
10,719✔
2767
         cgen_must_be_pointer(func, ir->arg2);
10,719✔
2768
         break;
10,719✔
2769
      case J_ADD:
123,099✔
2770
      case J_MOV:
2771
         // Propagate pointer argument to result
2772
         if (ir->arg1.kind == JIT_VALUE_REG
123,099✔
2773
             && mask_test(&(func->ptr_mask), ir->arg1.reg))
110,372✔
2774
            mask_set(&(func->ptr_mask), ir->result);
19,768✔
2775
         break;
2776
      case J_LEA:
57,755✔
2777
      case MACRO_GETPRIV:
2778
      case MACRO_LALLOC:
2779
      case MACRO_SALLOC:
2780
      case MACRO_GALLOC:
2781
         mask_set(&(func->ptr_mask), ir->result);
57,755✔
2782
         break;
2783
      default:
2784
         break;
2785
      }
2786
   }
2787
}
22,752✔
2788

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

2794
   for (int i = 0; i < ARGCACHE_SIZE; i++) {
159,264✔
2795
      LLVMValueRef indexes[] = { llvm_int32(obj, i) };
136,512✔
2796
      func->argcache[i] = LLVMBuildInBoundsGEP2(obj->builder,
136,512✔
2797
                                                obj->types[LLVM_INT64],
2798
                                                func->args, indexes,
2799
                                                ARRAY_LEN(indexes),
2800
                                                cgen_arg_name(i));
2801
   }
2802

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

2809
static void cgen_fix_liveout_types(llvm_obj_t *obj, cgen_block_t *cgb)
217,918✔
2810
{
2811
   for (int j = 0; j < cgb->func->source->nregs; j++) {
27,229,948✔
2812
      if (!mask_test(&cgb->source->liveout, j))
27,012,030✔
2813
         continue;
25,845,395✔
2814

2815
      const bool want_ptr = mask_test(&cgb->func->ptr_mask, j);
1,166,635✔
2816
      if (want_ptr && !llvm_is_ptr(cgb->outregs[j])) {
1,166,635✔
2817
         LLVMValueRef last = LLVMGetBasicBlockTerminator(cgb->bbref);
17✔
2818
         if (last != NULL)
17✔
2819
            LLVMPositionBuilderBefore(obj->builder, last);
17✔
2820

2821
         cgb->outregs[j] = LLVMBuildIntToPtr(obj->builder,
34✔
2822
                                             cgb->outregs[j],
17✔
2823
                                             obj->types[LLVM_PTR],
2824
                                             cgen_reg_name(j));
2825
      }
2826
   }
2827
}
217,918✔
2828

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

2835
   bool has_reexec = false;
22,752✔
2836
   for (int i = 0; i < cfg->nblocks; i++) {
240,312✔
2837
      jit_block_t *bb = &(cfg->blocks[i]);
217,739✔
2838
      if (func->source->irbuf[bb->last].op == MACRO_REEXEC) {
217,739✔
2839
         has_reexec = true;
2840
         break;
2841
      }
2842
   }
2843

2844
   if (!has_reexec)
22,752✔
2845
      return;
22,573✔
2846

2847
   LLVMValueRef fptr = LLVMGetParam(func->llvmfn, 0);
179✔
2848

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

2855
   LLVMBasicBlockRef reexec_bb = llvm_append_block(obj, func->llvmfn, "reexec");
179✔
2856
   LLVMBasicBlockRef cont_bb = llvm_append_block(obj, func->llvmfn, "cont");
179✔
2857

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

2862
   LLVMPositionBuilderAtEnd(obj->builder, reexec_bb);
179✔
2863

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

2869
   LLVMValueRef anchor = LLVMGetParam(func->llvmfn, 1);
179✔
2870

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

2881
   LLVMBuildRetVoid(obj->builder);
179✔
2882

2883
   LLVMPositionBuilderAtEnd(obj->builder, cont_bb);
179✔
2884
}
2885

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

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

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

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

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

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

2930
   LLVMSetSubprogram(func->llvmfn, func->debugmd);
2931

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

2935
   if (func->mode == CGEN_AOT) {
22,752✔
2936
      cgen_aot_cpool(obj, func);
14,809✔
2937
      cgen_aot_descr(obj, func);
14,809✔
2938
   }
2939

2940
   LLVMBasicBlockRef entry_bb = llvm_append_block(obj, func->llvmfn, "entry");
22,752✔
2941
   LLVMPositionBuilderAtEnd(obj->builder, entry_bb);
22,752✔
2942

2943
   func->args = LLVMGetParam(func->llvmfn, 2);
22,752✔
2944
   LLVMSetValueName(func->args, "args");
22,752✔
2945

2946
   func->tlab = LLVMGetParam(func->llvmfn, 3);
22,752✔
2947
   LLVMSetValueName(func->tlab, "tlab");
22,752✔
2948

2949
   cgen_frame_anchor(obj, func);
22,752✔
2950
   cgen_cache_args(obj, func);
22,752✔
2951

2952
   jit_cfg_t *cfg = func->cfg = jit_get_cfg(func->source);
22,752✔
2953
   cgen_reexecute_guard(obj, func, cfg);
22,752✔
2954
   cgen_basic_blocks(obj, func, cfg);
22,752✔
2955

2956
   entry_bb = LLVMGetInsertBlock(obj->builder);
22,752✔
2957

2958
   cgen_pointer_mask(func);
22,752✔
2959

2960
   cgen_block_t *cgb = func->blocks;
22,752✔
2961

2962
   LLVMValueRef zero_flag = llvm_int1(obj, false);
22,752✔
2963

2964
   int maxin = 0;
22,752✔
2965
   for (int i = 0; i < func->source->nirs; i++) {
2,381,051✔
2966
      if (i == cgb->source->first) {
2,358,299✔
2967
         LLVMPositionBuilderAtEnd(obj->builder, cgb->bbref);
217,918✔
2968

2969
         cgen_block_t *dom = NULL;
217,918✔
2970
         if (cgb->source->in.count == 1)
217,918✔
2971
            dom = &(func->blocks[jit_get_edge(&cgb->source->in, 0)]);
145,192✔
2972

2973
         cgb->inflags = zero_flag;
217,918✔
2974

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

2988
         cgb->outflags = cgb->inflags;
217,918✔
2989

2990
         for (int j = 0; j < func->source->nregs; j++) {
27,229,948✔
2991
            if (mask_test(&cgb->source->livein, j)) {
27,012,030✔
2992
               if (dom != NULL && dom < cgb) {
1,199,581✔
2993
                  assert(dom->outregs[j] != NULL);
795,145✔
2994
                  cgb->inregs[j] = cgb->outregs[j] = dom->outregs[j];
795,145✔
2995
                  continue;
795,145✔
2996
               }
2997

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

3008
         maxin = MAX(maxin, cgb->source->in.count);
217,918✔
3009
      }
3010

3011
      assert(i >= cgb->source->first && i <= cgb->source->last);
2,358,299✔
3012

3013
      cgen_ir(obj, cgb, &(func->source->irbuf[i]));
2,358,299✔
3014

3015
      if (i == cgb->source->last) {
2,358,299✔
3016
         cgen_fix_liveout_types(obj, cgb);
217,918✔
3017

3018
         if (LLVMGetBasicBlockTerminator(cgb->bbref) == NULL) {
217,918✔
3019
            if (cgb->source->aborts)
64,287✔
3020
               LLVMBuildUnreachable(obj->builder);
32,133✔
3021
            else {
3022
               // Fall through to next block
3023
               assert(!cgb->source->returns);
32,154✔
3024
               assert(cgb + 1 < func->blocks + cfg->nblocks);
32,154✔
3025
               LLVMBuildBr(obj->builder, (cgb + 1)->bbref);
32,154✔
3026
            }
3027
         }
3028

3029
         cgb++;
217,918✔
3030
      }
3031
   }
3032

3033
   LLVMValueRef *phi_in LOCAL = xmalloc_array(maxin, sizeof(LLVMValueRef));
45,504✔
3034
   LLVMBasicBlockRef *phi_bb LOCAL =
22,752✔
3035
      xmalloc_array(maxin, sizeof(LLVMBasicBlockRef));
22,752✔
3036

3037
   for (int i = 0; i < cfg->nblocks; i++) {
240,670✔
3038
      jit_block_t *bb = &(cfg->blocks[i]);
217,918✔
3039
      cgen_block_t *cgb = &(func->blocks[i]);
217,918✔
3040

3041
      if (bb->in.count == 0)
217,918✔
3042
         continue;
26,198✔
3043

3044
      // Flags
3045
      if (mask_test(&cgb->source->livein, func->source->nregs)
191,720✔
3046
          && LLVMIsAPHINode(cgb->inflags)
6,327✔
3047
          && LLVMGetInstructionParent(cgb->inflags) == cgb->bbref) {
4,923✔
3048

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

3057
      // Live-in registers
3058
      for (int j = 0; j < func->source->nregs; j++) {
26,456,804✔
3059
         if (cgb->inregs[j] != NULL && LLVMIsAPHINode(cgb->inregs[j])
26,265,084✔
3060
             && LLVMGetInstructionParent(cgb->inregs[j]) == cgb->bbref) {
916,092✔
3061

3062
            for (int k = 0; k < bb->in.count; k++) {
1,194,613✔
3063
               const int edge = jit_get_edge(&bb->in, k);
797,087✔
3064
               assert(func->blocks[edge].outregs[j] != NULL);
797,087✔
3065
               phi_in[k] = func->blocks[edge].outregs[j];
797,087✔
3066
               phi_bb[k] = func->blocks[edge].bbref;
797,087✔
3067
            }
3068
            LLVMAddIncoming(cgb->inregs[j], phi_in, phi_bb, bb->in.count);
397,526✔
3069
         }
3070
      }
3071
   }
3072

3073
   for (int i = 0; i < cfg->nblocks; i++) {
240,670✔
3074
      cgen_block_t *cgb = &(func->blocks[i]);
217,918✔
3075
      free(cgb->inregs);
217,918✔
3076
      free(cgb->outregs);
217,918✔
3077
      cgb->inregs = cgb->outregs = NULL;
217,918✔
3078
   }
3079

3080
   LLVMPositionBuilderAtEnd(obj->builder, entry_bb);
22,752✔
3081
   LLVMBuildBr(obj->builder, func->blocks[0].bbref);
22,752✔
3082

3083
   jit_free_cfg(func->source);
22,752✔
3084
   func->cfg = cfg = NULL;
22,752✔
3085

3086
   mask_free(&(func->ptr_mask));
22,752✔
3087

3088
   free(func->blocks);
22,752✔
3089
   func->blocks = NULL;
22,752✔
3090

3091
   free(func->relocs);
22,752✔
3092
   func->relocs = NULL;
22,752✔
3093
}
22,752✔
3094

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

3100
#ifdef PRESERVE_FRAME_POINTER
3101
   llvm_add_func_attr(obj, fn, FUNC_ATTR_PRESERVE_FP, 0);
3102
#endif
3103

3104
   LLVMBasicBlockRef entry = llvm_append_block(obj, fn, "");
6,357✔
3105

3106
   LLVMPositionBuilderAtEnd(obj->builder, entry);
6,357✔
3107

3108
   LLVMValueRef tlab = LLVMGetParam(fn, 0);
6,357✔
3109
   LLVMSetValueName(tlab, "tlab");
6,357✔
3110

3111
   LLVMValueRef bytes = LLVMGetParam(fn, 1);
6,357✔
3112
   LLVMSetValueName(bytes, "bytes");
6,357✔
3113

3114
   LLVMValueRef anchor = LLVMGetParam(fn, 2);
6,357✔
3115
   LLVMSetValueName(anchor, "anchor");
6,357✔
3116

3117
   LLVMBasicBlockRef fast_bb = llvm_append_block(obj, fn, "");
6,357✔
3118
   LLVMBasicBlockRef slow_bb = llvm_append_block(obj, fn, "");
6,357✔
3119

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

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

3130
   LLVMValueRef bytes_trunc = LLVMBuildTrunc(obj->builder, bytes,
6,357✔
3131
                                             obj->types[LLVM_INT32], "");
3132

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

3139
   LLVMValueRef next = LLVMBuildAdd(obj->builder, alloc, align_up, "");
6,357✔
3140

3141
   LLVMValueRef over = LLVMBuildICmp(obj->builder, LLVMIntUGT, next, limit, "");
6,357✔
3142
   LLVMBuildCondBr(obj->builder, over, slow_bb, fast_bb);
6,357✔
3143

3144
   LLVMPositionBuilderAtEnd(obj->builder, fast_bb);
6,357✔
3145

3146
   LLVMBuildStore(obj->builder, next, alloc_ptr);
6,357✔
3147

3148
   LLVMValueRef base =
6,357✔
3149
      LLVMBuildStructGEP2(obj->builder, obj->types[LLVM_TLAB], tlab, 3, "");
6,357✔
3150

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

3157
   LLVMBuildRet(obj->builder, fast_ptr);
6,357✔
3158

3159
   LLVMPositionBuilderAtEnd(obj->builder, slow_bb);
6,357✔
3160

3161
   LLVMValueRef args[] = { bytes, anchor };
6,357✔
3162
   LLVMValueRef slow_ptr = llvm_call_fn(obj, LLVM_MSPACE_ALLOC, args,
6,357✔
3163
                                        ARRAY_LEN(args));
3164

3165
   LLVMBuildRet(obj->builder, slow_ptr);
6,357✔
3166
}
6,357✔
3167

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

3174
#ifdef PRESERVE_FRAME_POINTER
3175
   llvm_add_func_attr(obj, fn, FUNC_ATTR_PRESERVE_FP, 0);
3176
#endif
3177

3178
   LLVMBasicBlockRef entry = llvm_append_block(obj, fn, "entry");
32✔
3179

3180
   LLVMPositionBuilderAtEnd(obj->builder, entry);
32✔
3181

3182
   LLVMValueRef x0 = LLVMGetParam(fn, 0);
32✔
3183
   LLVMSetValueName(x0, "x0");
32✔
3184

3185
   LLVMValueRef y0 = LLVMGetParam(fn, 1);
32✔
3186
   LLVMSetValueName(y0, "y0");
32✔
3187

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

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

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

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

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

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

3209
   LLVMPositionBuilderAtEnd(obj->builder, header);
32✔
3210

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

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

3220
   LLVMPositionBuilderAtEnd(obj->builder, body);
32✔
3221

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

3226
   LLVMPositionBuilderAtEnd(obj->builder, accum);
32✔
3227

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

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

3238
   LLVMPositionBuilderAtEnd(obj->builder, tail);
32✔
3239

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

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

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

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

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

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

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

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

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

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

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

3280
   LLVMBuildBr(obj->builder, header);
32✔
3281

3282
   LLVMPositionBuilderAtEnd(obj->builder, exit);
32✔
3283

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

3288
   LLVMBuildRet(obj->builder, pair);
32✔
3289
}
32✔
3290

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

3297
#ifdef PRESERVE_FRAME_POINTER
3298
   llvm_add_func_attr(obj, fn, FUNC_ATTR_PRESERVE_FP, 0);
3299
#endif
3300

3301
   LLVMBasicBlockRef entry = llvm_append_block(obj, fn, "entry");
235✔
3302

3303
   LLVMPositionBuilderAtEnd(obj->builder, entry);
235✔
3304

3305
   LLVMValueRef dest = LLVMGetParam(fn, 0);
235✔
3306
   LLVMSetValueName(dest, "dest");
235✔
3307

3308
   LLVMValueRef value = LLVMGetParam(fn, 1);
235✔
3309
   LLVMSetValueName(value, "value");
235✔
3310

3311
   LLVMValueRef bytes = LLVMGetParam(fn, 2);
235✔
3312
   LLVMSetValueName(bytes, "bytes");
235✔
3313

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

3318
   LLVMBasicBlockRef body = llvm_append_block(obj, fn, "body");
235✔
3319
   LLVMBasicBlockRef exit = llvm_append_block(obj, fn, "exit");
235✔
3320

3321
   LLVMTypeRef type = obj->types[LLVM_INT8 + sz];
235✔
3322

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

3326
   LLVMPositionBuilderAtEnd(obj->builder, body);
235✔
3327

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

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

3337
   LLVMBuildStore(obj->builder, value, cast);
235✔
3338

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

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

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

3350
   LLVMPositionBuilderAtEnd(obj->builder, exit);
235✔
3351

3352
   LLVMBuildRetVoid(obj->builder);
235✔
3353
}
235✔
3354

3355
////////////////////////////////////////////////////////////////////////////////
3356
// JIT plugin interface
3357

3358
typedef struct {
3359
   code_cache_t *code;
3360
} llvm_jit_state_t;
3361

3362
static void *jit_llvm_init(jit_t *jit)
3,567✔
3363
{
3364
   llvm_native_setup();
3,567✔
3365

3366
   llvm_jit_state_t *state = xcalloc(sizeof(llvm_jit_state_t));
3,567✔
3367
   state->code = code_cache_new();
3,567✔
3368

3369
   return state;
3,567✔
3370
}
3371

3372
static void jit_llvm_cgen(jit_t *j, jit_handle_t handle, void *context)
7,943✔
3373
{
3374
   llvm_jit_state_t *state = context;
7,943✔
3375

3376
   jit_func_t *f = jit_get_func(j, handle);
7,943✔
3377

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

3384
   const uint64_t start_us = get_timestamp_us();
7,943✔
3385

3386
   LLVMTargetMachineRef tm = llvm_target_machine(LLVMRelocDefault,
7,943✔
3387
                                                 JIT_CODE_MODEL);
3388

3389
   llvm_obj_t obj = {
7,943✔
3390
      .context = LLVMContextCreate(),
7,943✔
3391
      .target  = tm,
3392
   };
3393

3394
   LOCAL_TEXT_BUF tb = tb_new();
7,943✔
3395
   tb_istr(tb, f->name);
7,943✔
3396

3397
   obj.module    = LLVMModuleCreateWithNameInContext(tb_get(tb), obj.context);
7,943✔
3398
   obj.builder   = LLVMCreateBuilderInContext(obj.context);
7,943✔
3399
   obj.data_ref  = LLVMCreateTargetDataLayout(tm);
7,943✔
3400

3401
#if ENABLE_DWARF
3402
   obj.debuginfo = LLVMCreateDIBuilderDisallowUnresolved(obj.module);
3403
#endif
3404

3405
   llvm_register_types(&obj);
7,943✔
3406

3407
   cgen_func_t func = {
7,943✔
3408
      .name   = tb_claim(tb),
7,943✔
3409
      .source = f,
3410
      .mode   = CGEN_JIT,
3411
   };
3412

3413
   cgen_function(&obj, &func);
7,943✔
3414

3415
   llvm_obj_finalise(&obj, LLVM_O0);
7,943✔
3416

3417
   if (jit_is_shutdown(f->jit))
7,943✔
UNCOV
3418
      goto skip_emit;
×
3419

3420
   LLVMMemoryBufferRef buf;
7,943✔
3421
   char *error;
7,943✔
3422
   if (LLVMTargetMachineEmitToMemoryBuffer(tm, obj.module, LLVMObjectFile,
7,943✔
3423
                                           &error, &buf))
UNCOV
3424
     fatal("failed to generate native code: %s", error);
×
3425

3426
   if (jit_is_shutdown(f->jit))
7,943✔
3427
      goto skip_load;
×
3428

3429
   const size_t objsz = LLVMGetBufferSize(buf);
7,943✔
3430

3431
   code_blob_t *blob = code_blob_new(state->code, f->name, objsz);
7,943✔
3432
   if (blob == NULL)
7,943✔
UNCOV
3433
      return;
×
3434

3435
   const uint8_t *base = blob->wptr;
7,943✔
3436
   const void *entry_addr = blob->wptr;
7,943✔
3437

3438
   code_load_object(blob, LLVMGetBufferStart(buf), objsz);
7,943✔
3439

3440
   const size_t size = blob->wptr - base;
7,943✔
3441
   code_blob_finalise(blob, &(f->entry));
7,943✔
3442

3443
   if (opt_get_int(OPT_JIT_LOG)) {
7,943✔
UNCOV
3444
      const uint64_t end_us = get_timestamp_us();
×
UNCOV
3445
      debugf("%s at %p [%zu bytes in %"PRIi64" us]", func.name,
×
3446
             entry_addr, size, end_us - start_us);
3447
   }
3448

3449
 skip_load:
7,943✔
3450
   LLVMDisposeMemoryBuffer(buf);
7,943✔
3451

3452
 skip_emit:
7,943✔
3453
   LLVMDisposeTargetData(obj.data_ref);
7,943✔
3454
   LLVMDisposeTargetMachine(tm);
7,943✔
3455
   LLVMDisposeBuilder(obj.builder);
7,943✔
3456
   DWARF_ONLY(LLVMDisposeDIBuilder(obj.debuginfo));
7,943✔
3457
   LLVMContextDispose(obj.context);
7,943✔
3458
   free(func.name);
7,943✔
3459
}
3460

3461
static void jit_llvm_cleanup(void *context)
3,565✔
3462
{
3463
   llvm_jit_state_t *state = context;
3,565✔
3464
   code_cache_free(state->code);
3,565✔
3465
   free(state);
3,565✔
3466
}
3,565✔
3467

3468
static const jit_plugin_t jit_llvm = {
3469
   .init    = jit_llvm_init,
3470
   .cgen    = jit_llvm_cgen,
3471
   .cleanup = jit_llvm_cleanup
3472
};
3473

3474
void jit_register_llvm_plugin(jit_t *j)
4,860✔
3475
{
3476
   const int threshold = opt_get_int(OPT_JIT_THRESHOLD);
4,860✔
3477
   if (threshold > 0)
4,860✔
3478
      jit_add_tier(j, threshold, &jit_llvm);
3,567✔
3479
   else if (threshold < 0)
1,293✔
UNCOV
3480
      warnf("invalid NVC_JIT_THRESOLD setting %d", threshold);
×
3481
}
4,860✔
3482

3483
////////////////////////////////////////////////////////////////////////////////
3484
// Ahead-of-time code generation
3485

3486
llvm_obj_t *llvm_obj_new(const char *name)
1,324✔
3487
{
3488
   llvm_native_setup();
1,324✔
3489

3490
   llvm_obj_t *obj = xcalloc(sizeof(llvm_obj_t));
1,324✔
3491
   obj->context     = LLVMContextCreate();
1,324✔
3492
   obj->module      = LLVMModuleCreateWithNameInContext(name, obj->context);
1,324✔
3493
   obj->builder     = LLVMCreateBuilderInContext(obj->context);
1,324✔
3494
   obj->target      = llvm_target_machine(LLVMRelocPIC, LLVMCodeModelDefault);
1,324✔
3495
   obj->data_ref    = LLVMCreateTargetDataLayout(obj->target);
1,324✔
3496
   obj->pack_writer = pack_writer_new();
1,324✔
3497

3498
#if ENABLE_DWARF
3499
   obj->debuginfo = LLVMCreateDIBuilderDisallowUnresolved(obj->module);
3500
#endif
3501

3502
   char *triple = LLVMGetTargetMachineTriple(obj->target);
1,324✔
3503
   LLVMSetTarget(obj->module, triple);
1,324✔
3504
   LLVMDisposeMessage(triple);
1,324✔
3505

3506
   LLVMSetModuleDataLayout(obj->module, obj->data_ref);
1,324✔
3507

3508
   llvm_register_types(obj);
1,324✔
3509

3510
#if ENABLE_DWARF
3511
   llvm_add_module_flag(obj, "Debug Info Version", DEBUG_METADATA_VERSION);
3512
#ifdef __APPLE__
3513
   llvm_add_module_flag(obj, "Dwarf Version", 2);
3514
#else
3515
   llvm_add_module_flag(obj, "Dwarf Version", 4);
3516
#endif
3517
#endif
3518

3519
   obj->strtab = LLVMAddGlobal(obj->module, obj->types[LLVM_STRTAB],
1,324✔
3520
                               "placeholder_strtab");
3521
   LLVMSetGlobalConstant(obj->strtab, true);
1,324✔
3522
   LLVMSetLinkage(obj->strtab, LLVMPrivateLinkage);
1,324✔
3523

3524
   return obj;
1,324✔
3525
}
3526

3527
void llvm_add_abi_version(llvm_obj_t *obj)
1,230✔
3528
{
3529
   LLVMValueRef abi_version =
1,230✔
3530
      LLVMAddGlobal(obj->module, obj->types[LLVM_INT32], "__nvc_abi_version");
1,230✔
3531
   LLVMSetInitializer(abi_version, llvm_int32(obj, RT_ABI_VERSION));
1,230✔
3532
   LLVMSetGlobalConstant(abi_version, true);
1,230✔
3533
#ifdef IMPLIB_REQUIRED
3534
   LLVMSetDLLStorageClass(abi_version, LLVMDLLExportStorageClass);
3535
#endif
3536
}
1,230✔
3537

3538
void llvm_aot_compile(llvm_obj_t *obj, jit_t *j, jit_handle_t handle)
14,809✔
3539
{
3540
   DEBUG_ONLY(const uint64_t start_us = get_timestamp_us());
14,809✔
3541

3542
   jit_func_t *f = jit_get_func(j, handle);
14,809✔
3543
   jit_fill_irbuf(f);
14,809✔
3544

3545
   LOCAL_TEXT_BUF tb = safe_symbol(f->name);
14,809✔
3546

3547
   cgen_func_t func = {
14,809✔
3548
      .name   = tb_claim(tb),
14,809✔
3549
      .source = f,
3550
      .mode   = CGEN_AOT,
3551
   };
3552

3553
   cgen_function(obj, &func);
14,809✔
3554

3555
#ifdef DEBUG
3556
   const uint64_t end_us = get_timestamp_us();
14,809✔
3557
   if (end_us - start_us > 100000)
14,809✔
3558
      debugf("compiled %s [%"PRIi64" us]", func.name, end_us - start_us);
2✔
3559
#endif
3560

3561
   free(func.name);
14,809✔
3562
}
14,809✔
3563

3564
static void llvm_finalise_string_table(llvm_obj_t *obj)
9,267✔
3565
{
3566
   if (obj->pack_writer == NULL)
9,267✔
3567
      return;
7,943✔
3568

3569
   const char *strtab;
1,324✔
3570
   size_t len;
1,324✔
3571
   pack_writer_string_table(obj->pack_writer, &strtab, &len);
1,324✔
3572

3573
   LLVMValueRef init =
1,324✔
3574
      LLVMConstStringInContext(obj->context, strtab, len - 1, false);
1,324✔
3575
   LLVMTypeRef array_type = LLVMArrayType(obj->types[LLVM_INT8], len);
1,324✔
3576
   LLVMValueRef global = LLVMAddGlobal(obj->module, array_type, "strtab");
1,324✔
3577
   LLVMSetGlobalConstant(global, true);
1,324✔
3578
   LLVMSetInitializer(global, init);
1,324✔
3579
   LLVMSetLinkage(global, LLVMPrivateLinkage);
1,324✔
3580

3581
   LLVMReplaceAllUsesWith(obj->strtab, global);
1,324✔
3582
   LLVMDeleteGlobal(obj->strtab);
1,324✔
3583
}
3584

3585
void llvm_obj_finalise(llvm_obj_t *obj, llvm_opt_level_t olevel)
9,267✔
3586
{
3587
   if (obj->fns[LLVM_TLAB_ALLOC] != NULL)
9,267✔
3588
      cgen_tlab_alloc_body(obj);
6,357✔
3589

3590
   for (jit_size_t sz = JIT_SZ_8; sz <= JIT_SZ_64; sz++) {
46,335✔
3591
      if (obj->fns[LLVM_EXP_OVERFLOW_S8 + sz] != NULL)
37,068✔
3592
         cgen_exp_overflow_body(obj, LLVM_EXP_OVERFLOW_S8 + sz, sz,
30✔
3593
                                LLVM_MUL_OVERFLOW_S8);
3594
      if (obj->fns[LLVM_EXP_OVERFLOW_U8 + sz] != NULL)
37,068✔
3595
         cgen_exp_overflow_body(obj, LLVM_EXP_OVERFLOW_U8 + sz, sz,
2✔
3596
                                LLVM_MUL_OVERFLOW_U8);
3597
      if (obj->fns[LLVM_MEMSET_U8 + sz] != NULL)
37,068✔
3598
         cgen_memset_body(obj, LLVM_MEMSET_U8 + sz, sz,
235✔
3599
                          LLVM_MUL_OVERFLOW_U8);
3600
   }
3601

3602
   llvm_finalise_string_table(obj);
9,267✔
3603

3604
   DWARF_ONLY(LLVMDIBuilderFinalize(obj->debuginfo));
9,267✔
3605

3606
   llvm_dump_module(obj->module, "initial");
9,267✔
3607
   llvm_verify_module(obj->module);
9,267✔
3608
   llvm_optimise(obj->module, obj->target, olevel);
9,267✔
3609
   llvm_dump_module(obj->module, "final");
9,267✔
3610
}
9,267✔
3611

3612
void llvm_obj_emit(llvm_obj_t *obj, const char *path)
1,324✔
3613
{
3614
   char *error;
1,324✔
3615
   if (LLVMTargetMachineEmitToFile(obj->target, obj->module, (char *)path,
1,324✔
3616
                                   LLVMObjectFile, &error))
UNCOV
3617
      fatal("Failed to write object file: %s", error);
×
3618

3619
   LLVMDisposeTargetData(obj->data_ref);
1,324✔
3620
   LLVMDisposeTargetMachine(obj->target);
1,324✔
3621
   LLVMDisposeBuilder(obj->builder);
1,324✔
3622
   LLVMDisposeModule(obj->module);
1,324✔
3623
   LLVMContextDispose(obj->context);
1,324✔
3624

3625
   pack_writer_free(obj->pack_writer);
1,324✔
3626

3627
   free(obj);
1,324✔
3628
}
1,324✔
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