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

nickg / nvc / 6383422048

02 Oct 2023 05:25PM UTC coverage: 91.231% (+0.008%) from 91.223%
6383422048

push

github

nickg
Handle $MOVE with overlapping regions in x86 backend

9 of 9 new or added lines in 1 file covered. (100.0%)

48709 of 53391 relevant lines covered (91.23%)

623692.98 hits per line

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

82.09
/src/eval.c
1
//
2
//  Copyright (C) 2013-2022  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 "common.h"
20
#include "diag.h"
21
#include "eval.h"
22
#include "hash.h"
23
#include "ident.h"
24
#include "jit/jit.h"
25
#include "lib.h"
26
#include "lower.h"
27
#include "option.h"
28
#include "phase.h"
29
#include "rt/cover.h"
30
#include "rt/mspace.h"
31
#include "tree.h"
32
#include "type.h"
33
#include "vcode.h"
34

35
#include <assert.h>
36
#include <stdint.h>
37
#include <stdlib.h>
38
#include <stdarg.h>
39
#include <inttypes.h>
40
#include <string.h>
41
#include <math.h>
42

43
typedef enum {
44
   EVAL_WARN    = (1 << 2),
45
   EVAL_VERBOSE = (1 << 3),
46
} eval_flags_t;
47

48
struct _eval {
49
   jit_t        *jit;
50
};
51

52
#define ITER_LIMIT 10000
53

54
static const char *eval_expr_name(tree_t expr)
×
55
{
56
   const tree_kind_t kind = tree_kind(expr);
×
57
   if (kind == T_FCALL)
×
58
      return istr(tree_ident(expr));
×
59
   else
60
      return tree_kind_str(kind);
×
61
}
62

63
static tree_t eval_value_to_tree(jit_scalar_t value, type_t type,
8,057✔
64
                                 const loc_t *loc)
65
{
66
   tree_t tree = NULL;
8,057✔
67

68
   if (type_is_enum(type)) {
8,057✔
69
      type_t base = type_base_recur(type);
2,101✔
70
      if ((unsigned)value.integer >= type_enum_literals(base))
2,101✔
71
         fatal_at(loc, "enum position %"PRIi64" out of range for type %s",
×
72
                  value.integer, type_pp(base));
73

74
      tree_t lit = type_enum_literal(base, value.integer);
2,101✔
75

76
      tree = tree_new(T_REF);
2,101✔
77
      tree_set_ref(tree, lit);
2,101✔
78
      tree_set_ident(tree, tree_ident(lit));
2,101✔
79
   }
80
   else if (type_is_integer(type)) {
5,956✔
81
      tree = tree_new(T_LITERAL);
138✔
82
      tree_set_subkind(tree, L_INT);
138✔
83
      tree_set_ival(tree, value.integer);
138✔
84
   }
85
   else if (type_is_real(type)) {
5,818✔
86
      tree = tree_new(T_LITERAL);
5,802✔
87
      tree_set_subkind(tree, L_REAL);
5,802✔
88
      tree_set_dval(tree, value.real);
5,802✔
89
   }
90
   else if (type_is_physical(type)) {
16✔
91
      tree = tree_new(T_LITERAL);
16✔
92
      tree_set_subkind(tree, L_PHYSICAL);
16✔
93
      tree_set_ival(tree, value.integer);
16✔
94
   }
95
   else
96
      fatal_trace("cannot convert 0x%"PRIx64" to %s", value.integer,
×
97
                  type_pp(type));
98

99
   tree_set_type(tree, type);
8,057✔
100
   tree_set_loc(tree, loc);
8,057✔
101
   return tree;
8,057✔
102
}
103

104
static tree_t eval_do_fold(jit_t *jit, tree_t expr, lower_unit_t *parent,
9,474✔
105
                           void *context)
106
{
107
   vcode_unit_t thunk = lower_thunk(parent, expr);
9,474✔
108
   if (thunk == NULL)
9,474✔
109
      return expr;
110

111
   const bool verbose = opt_get_verbose(OPT_EVAL_VERBOSE, NULL);
8,475✔
112

113
   jit_scalar_t result;
8,475✔
114
   const bool finished = jit_call_thunk(jit, thunk, &result, context);
8,475✔
115

116
   vcode_unit_unref(thunk);
8,472✔
117
   thunk = NULL;
8,472✔
118

119
   if (finished) {
8,472✔
120
      if (verbose) {
8,057✔
121
         diag_t *d = diag_new(DIAG_DEBUG, tree_loc(expr));
×
122
         diag_printf(d, "evaluating %s returned ", eval_expr_name(expr));
×
123
         if (llabs(result.integer) < 1024)
×
124
            diag_printf(d, "%"PRIi64, result.integer);
×
125
         else
126
            diag_printf(d, "0x%"PRIx64, result.integer);
×
127
         diag_emit(d);
×
128
      }
129

130
      return eval_value_to_tree(result, tree_type(expr), tree_loc(expr));
8,057✔
131
   }
132
   else if (verbose) {
415✔
133
      diag_t *d = diag_new(DIAG_DEBUG, tree_loc(expr));
×
134
      diag_printf(d, "failed to evaluate %s", eval_expr_name(expr));
×
135
      diag_emit(d);
×
136
   }
137

138
   return expr;
139
}
140

141
tree_t eval_try_fold(jit_t *jit, tree_t expr, lower_unit_t *parent,
9,424✔
142
                     void *context)
143
{
144
   const bool verbose = opt_get_verbose(OPT_EVAL_VERBOSE, NULL);
9,424✔
145
   jit_set_silent(jit, !verbose);
9,424✔
146

147
   tree_t result = eval_do_fold(jit, expr, parent, context);
9,424✔
148

149
   jit_set_silent(jit, false);
9,421✔
150

151
   return result;
9,421✔
152
}
153

154
tree_t eval_must_fold(jit_t *jit, tree_t expr, lower_unit_t *parent,
50✔
155
                      void *context)
156
{
157
   return eval_do_fold(jit, expr, parent, context);
50✔
158
}
159

160
static bool eval_not_possible(tree_t t, const char *why)
4,892✔
161
{
162
   if (opt_get_verbose(OPT_EVAL_VERBOSE, NULL))
4,892✔
163
      warn_at(tree_loc(t), "%s prevents constant folding", why);
×
164

165
   return false;
4,892✔
166
}
167

168
bool eval_possible(tree_t t, unit_registry_t *ur)
72,162✔
169
{
170
   switch (tree_kind(t)) {
78,793✔
171
   case T_FCALL:
41,270✔
172
      {
173
         const tree_flags_t flags = tree_flags(t);
41,270✔
174
         if (!(flags & (TREE_F_LOCALLY_STATIC | TREE_F_GLOBALLY_STATIC)))
41,270✔
175
            return eval_not_possible(t, "non-static expression");
77✔
176

177
         tree_t decl = tree_ref(t);
41,193✔
178
         const subprogram_kind_t kind = tree_subkind(decl);
41,193✔
179
         if (kind == S_FOREIGN)
41,193✔
180
            return eval_not_possible(t, "call to foreign function");
57✔
181
         else if (tree_flags(decl) & TREE_F_IMPURE)
41,136✔
182
            return eval_not_possible(t, "call to impure function");
×
183
         else if (kind != S_USER && !is_open_coded_builtin(kind)
41,136✔
184
                  && unit_registry_get(ur, tree_ident2(decl)) == NULL)
2,518✔
185
            return eval_not_possible(t, "not yet lowered predef");
138✔
186
         else if (kind == S_USER && !is_package(tree_container(decl)))
40,998✔
187
            return eval_not_possible(t, "subprogram not in package");
648✔
188

189
         const int nparams = tree_params(t);
40,350✔
190
         for (int i = 0; i < nparams; i++) {
56,349✔
191
            tree_t p = tree_value(tree_param(t, i));
45,732✔
192
            if (!eval_possible(p, ur))
45,732✔
193
               return false;
194
            else if (tree_kind(p) == T_FCALL && type_is_scalar(tree_type(p)))
16,662✔
195
               return false;  // Would have been folded already if possible
196
         }
197

198
         return true;
199
      }
200

201
   case T_LITERAL:
202
   case T_STRING:
203
      return true;
204

205
   case T_TYPE_CONV:
327✔
206
      return eval_possible(tree_value(t), ur);
327✔
207

208
   case T_QUALIFIED:
2,286✔
209
      return eval_possible(tree_value(t), ur);
2,286✔
210

211
   case T_REF:
13,915✔
212
      {
213
         tree_t decl = tree_ref(t);
13,915✔
214
         switch (tree_kind(decl)) {
13,915✔
215
         case T_UNIT_DECL:
216
         case T_ENUM_LIT:
217
            return true;
218

219
         case T_CONST_DECL:
2,290✔
220
            if (tree_has_value(decl))
2,290✔
221
               return eval_possible(tree_value(decl), ur);
2,271✔
222
            else
223
               return false;
224

225
         default:
3,944✔
226
            return eval_not_possible(t, "reference");
3,944✔
227
         }
228
      }
229

230
   case T_RECORD_REF:
386✔
231
      return eval_possible(tree_value(t), ur);
386✔
232

233
   case T_ARRAY_REF:
1,421✔
234
      {
235
         const int nparams = tree_params(t);
1,421✔
236
         for (int i = 0; i < nparams; i++) {
2,805✔
237
            if (!eval_possible(tree_value(tree_param(t, i)), ur))
1,444✔
238
               return false;
239
         }
240

241
         return eval_possible(tree_value(t), ur);
1,361✔
242
      }
243

244
   case T_AGGREGATE:
1,458✔
245
      {
246
         const int nassocs = tree_assocs(t);
1,458✔
247
         for (int i = 0; i < nassocs; i++) {
9,618✔
248
            if (!eval_possible(tree_value(tree_assoc(t, i)), ur))
8,184✔
249
               return false;
250
         }
251

252
         return true;
253
      }
254

255
   case T_ATTR_REF:
1,870✔
256
      {
257
         if (tree_subkind(t) == ATTR_USER)
1,870✔
258
            return eval_not_possible(t, "user defined attribute");
×
259

260
         if (!eval_possible(tree_name(t), ur))
1,870✔
261
            return false;
262

263
         const int nparams = tree_params(t);
×
264
         for (int i = 0; i < nparams; i++) {
×
265
            if (!eval_possible(tree_value(tree_param(t, i)), ur))
×
266
               return false;
267
         }
268

269
         return true;
270
      }
271

272
   default:
28✔
273
      return eval_not_possible(t, tree_kind_str(tree_kind(t)));
28✔
274
   }
275
}
276

277
tree_t eval_case(jit_t *jit, tree_t stmt, lower_unit_t *parent, void *context)
9✔
278
{
279
   assert(tree_kind(stmt) == T_CASE_GENERATE);
9✔
280

281
   vcode_unit_t thunk = lower_case_generate_thunk(parent, stmt);
9✔
282

283
   jit_scalar_t result = { .integer = -1 };
9✔
284
   if (!jit_call_thunk(jit, thunk, &result, context))
9✔
285
      error_at(tree_loc(tree_value(stmt)), "generate expression is not static");
×
286

287
   vcode_unit_unref(thunk);
9✔
288

289
   if (result.integer == -1)
9✔
290
      return NULL;
291
   else
292
      return tree_stmt(stmt, result.integer);
9✔
293
}
294

295
void *eval_instance(jit_t *jit, ident_t name, void *context)
6,751✔
296
{
297
   jit_handle_t h = jit_lazy_compile(jit, name);
6,751✔
298
   if (h == JIT_HANDLE_INVALID)
6,751✔
299
      fatal_trace("failed to compile instance %s", istr(name));
×
300

301
   jit_scalar_t result;
6,751✔
302
   if (!jit_try_call(jit, h, &result, context, context))
6,751✔
303
      return NULL;
304

305
   return result.pointer;
6,742✔
306
}
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

© 2026 Coveralls, Inc