1
2 #include "config.h"
3
4 #include <stdio.h>
5 #include <string.h>
6 #include <stdlib.h>
7 #include <stdarg.h>
8
9 #include <orc/orcprogram.h>
10 #include <orc/orcdebug.h>
11 #include <orc/orcinternal.h>
12
13 #ifdef HAVE_VALGRIND_VALGRIND_H
14 #include <valgrind/valgrind.h>
15 #endif
16
17 /**
18 * SECTION:orccompiler
19 * @title: OrcCompiler
20 * @short_description: Compile Orc programs
21 *
22 * OrcCompiler is the object used to convert Orc programs contained
23 * in an OrcProgram object into assembly code and object code.
24 *
25 * The OrcCompileResult enum is used to indicate whether or not
26 * a compilation attempt was successful or not. The macros
27 * ORC_COMPILE_RESULT_IS_SUCCESSFUL() and ORC_COMPILE_RESULT_IS_FATAL()
28 * should be used instead of checking values directly.
29 *
30 * When a program is compiled, the compiler calls the functions
31 * contained in various OrcRule structures. These functions generate
32 * assembly and object instructions by calling ORC_ASM_CODE()
33 * or functions that use ORC_ASM_CODE() internally.
34 */
35
36 static void orc_compiler_assign_rules (OrcCompiler *compiler);
37 static void orc_compiler_global_reg_alloc (OrcCompiler *compiler);
38 static void orc_compiler_rewrite_insns (OrcCompiler *compiler);
39 static void orc_compiler_rewrite_vars (OrcCompiler *compiler);
40 static void orc_compiler_rewrite_vars2 (OrcCompiler *compiler);
41 static int orc_compiler_dup_temporary (OrcCompiler *compiler, int var, int j);
42 static int orc_compiler_new_temporary (OrcCompiler *compiler, int size);
43 static void orc_compiler_check_sizes (OrcCompiler *compiler);
44
45 static char **_orc_compiler_flag_list;
46 int _orc_compiler_flag_backup;
47 int _orc_compiler_flag_emulate;
48 int _orc_compiler_flag_debug;
49 int _orc_compiler_flag_randomize;
50
51 void
_orc_compiler_init(void)52 _orc_compiler_init (void)
53 {
54 const char *envvar;
55
56 envvar = getenv ("ORC_CODE");
57 if (envvar != NULL) {
58 _orc_compiler_flag_list = strsplit (envvar, ',');
59 }
60
61 _orc_compiler_flag_backup = orc_compiler_flag_check ("backup");
62 _orc_compiler_flag_emulate = orc_compiler_flag_check ("emulate");
63 _orc_compiler_flag_debug = orc_compiler_flag_check ("debug");
64 _orc_compiler_flag_randomize = orc_compiler_flag_check ("randomize");
65 }
66
67 int
orc_compiler_flag_check(const char * flag)68 orc_compiler_flag_check (const char *flag)
69 {
70 int i;
71
72 if (_orc_compiler_flag_list == NULL) return FALSE;
73
74 for (i=0;_orc_compiler_flag_list[i];i++){
75 if (strcmp (_orc_compiler_flag_list[i], flag) == 0) return TRUE;
76 }
77 return FALSE;
78 }
79
80 static int
orc_compiler_allocate_register(OrcCompiler * compiler,int data_reg)81 orc_compiler_allocate_register (OrcCompiler *compiler, int data_reg)
82 {
83 int i;
84 int roff;
85 int reg;
86 int offset;
87
88 if (data_reg) {
89 offset = compiler->target->data_register_offset;
90 } else {
91 offset = ORC_GP_REG_BASE;
92 }
93
94 roff = 0;
95 if (_orc_compiler_flag_randomize) {
96 /* for testing */
97 roff = rand()&0x1f;
98 }
99
100 for(i=0;i<32;i++){
101 reg = offset + ((roff + i)&0x1f);
102 if (compiler->valid_regs[reg] &&
103 !compiler->save_regs[reg] &&
104 compiler->alloc_regs[reg] == 0) {
105 compiler->alloc_regs[reg]++;
106 compiler->used_regs[reg] = 1;
107 return reg;
108 }
109 }
110 for(i=0;i<32;i++){
111 reg = offset + ((roff + i)&0x1f);
112 if (compiler->valid_regs[reg] &&
113 compiler->alloc_regs[reg] == 0) {
114 compiler->alloc_regs[reg]++;
115 compiler->used_regs[reg] = 1;
116 return reg;
117 }
118 }
119
120 if (data_reg || !compiler->allow_gp_on_stack) {
121 orc_compiler_error (compiler, "register overflow for %s register",
122 data_reg ? "vector" : "gp");
123 compiler->result = ORC_COMPILE_RESULT_UNKNOWN_COMPILE;
124 }
125
126 return 0;
127 }
128
129 /**
130 * orc_program_compile:
131 * @program: the OrcProgram to compile
132 *
133 * Compiles an Orc program for the current CPU. If successful,
134 * executable code for the program was generated and can be
135 * executed.
136 *
137 * The return value indicates various levels of success or failure.
138 * Success can be determined by checking for a true value of the
139 * macro ORC_COMPILE_RESULT_IS_SUCCESSFUL() on the return value. This
140 * indicates that executable code was generated. If the macro
141 * ORC_COMPILE_RESULT_IS_FATAL() on the return value evaluates to
142 * true, then there was a syntactical error in the program. If the
143 * result is neither successful nor fatal, the program can still be
144 * emulated.
145 *
146 * Returns: an OrcCompileResult
147 */
148 OrcCompileResult
orc_program_compile(OrcProgram * program)149 orc_program_compile (OrcProgram *program)
150 {
151 return orc_program_compile_for_target (program, orc_target_get_default ());
152 }
153
154 /**
155 * orc_program_compile_for_target:
156 * @program: the OrcProgram to compile
157 *
158 * Compiles an Orc program for the given target, using the
159 * default target flags for that target.
160 *
161 * Returns: an OrcCompileResult
162 */
163 OrcCompileResult
orc_program_compile_for_target(OrcProgram * program,OrcTarget * target)164 orc_program_compile_for_target (OrcProgram *program, OrcTarget *target)
165 {
166 unsigned int flags;
167
168 if (target) {
169 flags = target->get_default_flags ();
170 } else {
171 flags = 0;
172 }
173
174 return orc_program_compile_full (program, target, flags);
175 }
176
177 /**
178 * orc_program_compile_full:
179 * @program: the OrcProgram to compile
180 *
181 * Compiles an Orc program for the given target, using the
182 * given target flags.
183 *
184 * Returns: an OrcCompileResult
185 */
186 OrcCompileResult
orc_program_compile_full(OrcProgram * program,OrcTarget * target,unsigned int flags)187 orc_program_compile_full (OrcProgram *program, OrcTarget *target,
188 unsigned int flags)
189 {
190 OrcCompiler *compiler;
191 int i;
192 OrcCompileResult result;
193 const char *error_msg;
194
195 ORC_INFO("initializing compiler for program \"%s\"", program->name);
196 error_msg = orc_program_get_error (program);
197 if (error_msg && strcmp (error_msg, "")) {
198 ORC_WARNING ("program %s failed to compile, reason: %s",
199 program->name, error_msg);
200 return ORC_COMPILE_RESULT_UNKNOWN_PARSE;
201 }
202
203 if (program->orccode) {
204 orc_code_free (program->orccode);
205 program->orccode = NULL;
206 }
207
208 if (program->asm_code) {
209 free (program->asm_code);
210 program->asm_code = NULL;
211 }
212
213 compiler = malloc (sizeof(OrcCompiler));
214 memset (compiler, 0, sizeof(OrcCompiler));
215
216 if (program->backup_func) {
217 program->code_exec = program->backup_func;
218 } else {
219 program->code_exec = (void *)orc_executor_emulate;
220 }
221
222 compiler->program = program;
223 compiler->target = target;
224 compiler->target_flags = flags;
225
226 {
227 ORC_LOG("variables");
228 for(i=0;i<ORC_N_VARIABLES;i++){
229 if (program->vars[i].size > 0) {
230 ORC_LOG("%d: %s size %d type %d alloc %d", i,
231 program->vars[i].name,
232 program->vars[i].size,
233 program->vars[i].vartype,
234 program->vars[i].alloc);
235 }
236 }
237 ORC_LOG("instructions");
238 for(i=0;i<program->n_insns;i++){
239 ORC_LOG("%d: %s %d %d %d %d", i,
240 program->insns[i].opcode->name,
241 program->insns[i].dest_args[0],
242 program->insns[i].dest_args[1],
243 program->insns[i].src_args[0],
244 program->insns[i].src_args[1]);
245 }
246 }
247
248 memcpy (compiler->insns, program->insns,
249 program->n_insns * sizeof(OrcInstruction));
250 compiler->n_insns = program->n_insns;
251
252 memcpy (compiler->vars, program->vars,
253 ORC_N_VARIABLES * sizeof(OrcVariable));
254 memset (compiler->vars + ORC_N_VARIABLES, 0,
255 (ORC_N_COMPILER_VARIABLES - ORC_N_VARIABLES) * sizeof(OrcVariable));
256 compiler->n_temp_vars = program->n_temp_vars;
257 compiler->n_dup_vars = 0;
258
259 for(i=0;i<32;i++) {
260 compiler->valid_regs[i] = 1;
261 }
262
263 orc_compiler_check_sizes (compiler);
264 if (compiler->error) goto error;
265
266 if (compiler->target) {
267 compiler->target->compiler_init (compiler);
268 }
269
270 orc_compiler_rewrite_insns (compiler);
271 if (compiler->error) goto error;
272
273 orc_compiler_rewrite_vars (compiler);
274 if (compiler->error) goto error;
275
276 #if 0
277 {
278 ORC_ERROR("variables");
279 for(i=0;i<ORC_N_VARIABLES;i++){
280 if (compiler->vars[i].size > 0) {
281 ORC_ERROR("%d: %s size %d type %d alloc %d [%d,%d]", i,
282 compiler->vars[i].name,
283 compiler->vars[i].size,
284 compiler->vars[i].vartype,
285 compiler->vars[i].alloc,
286 compiler->vars[i].first_use,
287 compiler->vars[i].last_use);
288 }
289 }
290 ORC_ERROR("instructions");
291 for(i=0;i<compiler->n_insns;i++){
292 ORC_ERROR("%d: %s %d %d %d %d", i,
293 compiler->insns[i].opcode->name,
294 compiler->insns[i].dest_args[0],
295 compiler->insns[i].dest_args[1],
296 compiler->insns[i].src_args[0],
297 compiler->insns[i].src_args[1]);
298 }
299 }
300 #endif
301 program->orccode = orc_code_new ();
302
303 program->orccode->is_2d = program->is_2d;
304 program->orccode->constant_n = program->constant_n;
305 program->orccode->constant_m = program->constant_m;
306 program->orccode->exec = program->code_exec;
307
308 program->orccode->n_insns = compiler->n_insns;
309 program->orccode->insns = malloc(sizeof(OrcInstruction) * compiler->n_insns);
310 memcpy (program->orccode->insns, compiler->insns,
311 sizeof(OrcInstruction) * compiler->n_insns);
312
313 program->orccode->vars = malloc (sizeof(OrcCodeVariable) * ORC_N_COMPILER_VARIABLES);
314 memset (program->orccode->vars, 0,
315 sizeof(OrcCodeVariable) * ORC_N_COMPILER_VARIABLES);
316 for(i=0;i<ORC_N_COMPILER_VARIABLES;i++){
317 program->orccode->vars[i].vartype = compiler->vars[i].vartype;
318 program->orccode->vars[i].size = compiler->vars[i].size;
319 program->orccode->vars[i].value = compiler->vars[i].value;
320 }
321
322 if (program->backup_func && (_orc_compiler_flag_backup || target == NULL)) {
323 orc_compiler_error (compiler, "Compilation disabled, using backup");
324 compiler->result = ORC_COMPILE_RESULT_UNKNOWN_COMPILE;
325 goto error;
326 }
327
328 if (_orc_compiler_flag_emulate || target == NULL) {
329 program->code_exec = (void *)orc_executor_emulate;
330 program->orccode->exec = (void *)orc_executor_emulate;
331 orc_compiler_error (compiler, "Compilation disabled, using emulation");
332 compiler->result = ORC_COMPILE_RESULT_UNKNOWN_COMPILE;
333 goto error;
334 }
335
336 if (compiler->target) {
337 orc_compiler_global_reg_alloc (compiler);
338
339 orc_compiler_rewrite_vars2 (compiler);
340 }
341 if (compiler->error) goto error;
342
343 orc_compiler_assign_rules (compiler);
344 if (compiler->error) goto error;
345
346 ORC_INFO("allocating code memory");
347 compiler->code = malloc(65536);
348 compiler->codeptr = compiler->code;
349
350 if (compiler->error) goto error;
351
352 ORC_INFO("compiling for target \"%s\"", compiler->target->name);
353 compiler->target->compile (compiler);
354 if (compiler->error) {
355 compiler->result = ORC_COMPILE_RESULT_UNKNOWN_COMPILE;
356 goto error;
357 }
358
359 program->orccode->code_size = compiler->codeptr - compiler->code;
360 orc_code_allocate_codemem (program->orccode, program->orccode->code_size);
361
362 memcpy (program->orccode->code, compiler->code, program->orccode->code_size);
363
364 #ifdef VALGRIND_DISCARD_TRANSLATIONS
365 VALGRIND_DISCARD_TRANSLATIONS (program->orccode->exec,
366 program->orccode->code_size);
367 #endif
368
369 if (compiler->target->flush_cache) {
370 compiler->target->flush_cache (program->orccode);
371 }
372
373 program->code_exec = program->orccode->exec;
374
375 program->asm_code = compiler->asm_code;
376
377 result = compiler->result;
378 for (i=0;i<compiler->n_dup_vars;i++){
379 free(compiler->vars[ORC_VAR_T1 + compiler->n_temp_vars + i].name);
380 compiler->vars[ORC_VAR_T1 + compiler->n_temp_vars + i].name = NULL;
381 }
382 free (compiler->code);
383 compiler->code = NULL;
384 if (compiler->output_insns) free (compiler->output_insns);
385 free (compiler);
386 ORC_INFO("finished compiling (success)");
387
388 return result;
389 error:
390
391 if (compiler->error_msg) {
392 ORC_WARNING ("program %s failed to compile, reason: %s",
393 program->name, compiler->error_msg);
394 } else {
395 ORC_WARNING("program %s failed to compile, reason %d",
396 program->name, compiler->result);
397 }
398 result = compiler->result;
399 orc_program_set_error (program, compiler->error_msg);
400 free (compiler->error_msg);
401 if (result == 0) {
402 result = ORC_COMPILE_RESULT_UNKNOWN_COMPILE;
403 }
404 if (compiler->asm_code) {
405 free (compiler->asm_code);
406 compiler->asm_code = NULL;
407 }
408 for (i=0;i<compiler->n_dup_vars;i++){
409 free(compiler->vars[ORC_VAR_T1 + compiler->n_temp_vars + i].name);
410 compiler->vars[ORC_VAR_T1 + compiler->n_temp_vars + i].name = NULL;
411 }
412 free (compiler->code);
413 compiler->code = NULL;
414 if (compiler->output_insns) free (compiler->output_insns);
415 free (compiler);
416 ORC_INFO("finished compiling (fail)");
417 return result;
418 }
419
420 static void
orc_compiler_check_sizes(OrcCompiler * compiler)421 orc_compiler_check_sizes (OrcCompiler *compiler)
422 {
423 int i;
424 int j;
425 int max_size = 1;
426
427 for(i=0;i<compiler->n_insns;i++) {
428 OrcInstruction *insn = compiler->insns + i;
429 OrcStaticOpcode *opcode = insn->opcode;
430 int multiplier = 1;
431
432 if (insn->flags & ORC_INSTRUCTION_FLAG_X2) {
433 multiplier = 2;
434 } else if (insn->flags & ORC_INSTRUCTION_FLAG_X4) {
435 multiplier = 4;
436 }
437
438 for(j=0;j<ORC_STATIC_OPCODE_N_DEST;j++){
439 if (opcode->dest_size[j] == 0) continue;
440 if (multiplier * opcode->dest_size[j] !=
441 compiler->vars[insn->dest_args[j]].size) {
442 ORC_COMPILER_ERROR (compiler, "size mismatch, opcode %s dest[%d] is %d should be %d",
443 opcode->name, j, compiler->vars[insn->dest_args[j]].size,
444 multiplier * opcode->dest_size[j]);
445 compiler->result = ORC_COMPILE_RESULT_UNKNOWN_PARSE;
446 return;
447 }
448 max_size = MAX(max_size, multiplier * opcode->dest_size[j]);
449 }
450 for(j=0;j<ORC_STATIC_OPCODE_N_SRC;j++){
451 if (opcode->src_size[j] == 0) continue;
452 if (multiplier * opcode->src_size[j] !=
453 compiler->vars[insn->src_args[j]].size &&
454 compiler->vars[insn->src_args[j]].vartype != ORC_VAR_TYPE_PARAM &&
455 compiler->vars[insn->src_args[j]].vartype != ORC_VAR_TYPE_CONST) {
456 ORC_COMPILER_ERROR(compiler, "size mismatch, opcode %s src[%d] is %d should be %d",
457 opcode->name, j, compiler->vars[insn->src_args[j]].size,
458 multiplier * opcode->src_size[j]);
459 compiler->result = ORC_COMPILE_RESULT_UNKNOWN_PARSE;
460 return;
461 }
462 if (opcode->flags & ORC_STATIC_OPCODE_SCALAR && j >= 1 &&
463 compiler->vars[insn->src_args[j]].vartype != ORC_VAR_TYPE_PARAM &&
464 compiler->vars[insn->src_args[j]].vartype != ORC_VAR_TYPE_CONST) {
465 ORC_COMPILER_ERROR(compiler, "opcode %s requires const or param source",
466 opcode->name);
467 compiler->result = ORC_COMPILE_RESULT_UNKNOWN_PARSE;
468 return;
469 }
470 max_size = MAX(max_size, multiplier * opcode->src_size[j]);
471 }
472 if (opcode->flags & ORC_STATIC_OPCODE_SCALAR &&
473 opcode->src_size[1] == 0 &&
474 compiler->vars[insn->src_args[0]].vartype != ORC_VAR_TYPE_PARAM &&
475 compiler->vars[insn->src_args[0]].vartype != ORC_VAR_TYPE_CONST) {
476 ORC_COMPILER_ERROR(compiler, "opcode %s requires const or param source",
477 opcode->name);
478 compiler->result = ORC_COMPILE_RESULT_UNKNOWN_PARSE;
479 return;
480 }
481 }
482 compiler->max_var_size = max_size;
483 }
484
485 static OrcStaticOpcode *
get_load_opcode_for_size(int size)486 get_load_opcode_for_size (int size)
487 {
488 switch (size) {
489 case 1:
490 return orc_opcode_find_by_name ("loadb");
491 case 2:
492 return orc_opcode_find_by_name ("loadw");
493 case 4:
494 return orc_opcode_find_by_name ("loadl");
495 case 8:
496 return orc_opcode_find_by_name ("loadq");
497 default:
498 ORC_ASSERT(0);
499 }
500 return NULL;
501 }
502
503 static OrcStaticOpcode *
get_loadp_opcode_for_size(int size)504 get_loadp_opcode_for_size (int size)
505 {
506 switch (size) {
507 case 1:
508 return orc_opcode_find_by_name ("loadpb");
509 case 2:
510 return orc_opcode_find_by_name ("loadpw");
511 case 4:
512 return orc_opcode_find_by_name ("loadpl");
513 case 8:
514 return orc_opcode_find_by_name ("loadpq");
515 default:
516 ORC_ASSERT(0);
517 }
518 return NULL;
519 }
520
521 static OrcStaticOpcode *
get_store_opcode_for_size(int size)522 get_store_opcode_for_size (int size)
523 {
524 switch (size) {
525 case 1:
526 return orc_opcode_find_by_name ("storeb");
527 case 2:
528 return orc_opcode_find_by_name ("storew");
529 case 4:
530 return orc_opcode_find_by_name ("storel");
531 case 8:
532 return orc_opcode_find_by_name ("storeq");
533 default:
534 ORC_ASSERT(0);
535 }
536 return NULL;
537 }
538
539 static void
orc_compiler_rewrite_insns(OrcCompiler * compiler)540 orc_compiler_rewrite_insns (OrcCompiler *compiler)
541 {
542 int i;
543 int j;
544 OrcStaticOpcode *opcode;
545 OrcProgram *program = compiler->program;
546
547 compiler->n_insns = 0;
548 for(j=0;j<program->n_insns;j++){
549 OrcInstruction insn;
550 OrcInstruction *xinsn;
551
552 memcpy (&insn, program->insns + j, sizeof(OrcInstruction));
553 opcode = insn.opcode;
554
555 if (!(opcode->flags & ORC_STATIC_OPCODE_LOAD)) {
556 for(i=0;i<ORC_STATIC_OPCODE_N_SRC;i++){
557 OrcVariable *var;
558
559 if (opcode->src_size[i] == 0) continue;
560 var = compiler->vars + insn.src_args[i];
561
562 if (i > 0 && (opcode->flags & ORC_STATIC_OPCODE_SCALAR) &&
563 (!compiler->load_params || var->vartype != ORC_VAR_TYPE_PARAM))
564 continue;
565
566 if (var->vartype == ORC_VAR_TYPE_SRC ||
567 var->vartype == ORC_VAR_TYPE_DEST) {
568 OrcInstruction *cinsn;
569
570 cinsn = compiler->insns + compiler->n_insns;
571 compiler->n_insns++;
572
573 cinsn->flags = insn.flags;
574 cinsn->flags |= ORC_INSN_FLAG_ADDED;
575 cinsn->flags &= ~(ORC_INSTRUCTION_FLAG_X2|ORC_INSTRUCTION_FLAG_X4);
576 cinsn->opcode = get_load_opcode_for_size (var->size);
577 cinsn->dest_args[0] = orc_compiler_new_temporary (compiler,
578 var->size);
579 cinsn->src_args[0] = insn.src_args[i];
580 insn.src_args[i] = cinsn->dest_args[0];
581 } else if (var->vartype == ORC_VAR_TYPE_CONST ||
582 var->vartype == ORC_VAR_TYPE_PARAM) {
583 OrcInstruction *cinsn;
584 int l, multiplier, loaded;
585
586 multiplier = 1;
587 if (insn.flags & ORC_INSTRUCTION_FLAG_X2) {
588 multiplier = 2;
589 }
590 if (insn.flags & ORC_INSTRUCTION_FLAG_X4) {
591 multiplier = 4;
592 }
593
594 loaded = -1;
595 for(l=0;l<ORC_N_COMPILER_VARIABLES;l++){
596 if (compiler->vars[l].name == NULL) continue;
597 if (!compiler->vars[l].has_parameter) continue;
598 if (compiler->vars[l].parameter != insn.src_args[i]) continue;
599 if (compiler->vars[l].size != opcode->src_size[i] * multiplier) continue;
600 loaded = l;
601 break;
602 }
603 if (loaded != -1) {
604 insn.src_args[i] = loaded;
605 continue;
606 }
607 cinsn = compiler->insns + compiler->n_insns;
608 compiler->n_insns++;
609
610 cinsn->flags = insn.flags;
611 cinsn->flags |= ORC_INSN_FLAG_ADDED;
612 cinsn->opcode = get_loadp_opcode_for_size (opcode->src_size[i]);
613 cinsn->dest_args[0] = orc_compiler_new_temporary (compiler,
614 opcode->src_size[i] * multiplier);
615 if (var->vartype == ORC_VAR_TYPE_CONST) {
616 compiler->vars[cinsn->dest_args[0]].flags |=
617 ORC_VAR_FLAG_VOLATILE_WORKAROUND;
618 }
619 compiler->vars[cinsn->dest_args[0]].has_parameter = TRUE;
620 compiler->vars[cinsn->dest_args[0]].parameter = insn.src_args[i];
621 cinsn->src_args[0] = insn.src_args[i];
622 insn.src_args[i] = cinsn->dest_args[0];
623 }
624 }
625 }
626
627 xinsn = compiler->insns + compiler->n_insns;
628 memcpy (xinsn, &insn, sizeof(OrcInstruction));
629 compiler->n_insns++;
630
631 if (!(opcode->flags & ORC_STATIC_OPCODE_STORE)) {
632 for(i=0;i<ORC_STATIC_OPCODE_N_DEST;i++){
633 OrcVariable *var;
634
635 if (opcode->dest_size[i] == 0) continue;
636
637 var = compiler->vars + insn.dest_args[i];
638 if (var->vartype == ORC_VAR_TYPE_DEST) {
639 OrcInstruction *cinsn;
640
641 cinsn = compiler->insns + compiler->n_insns;
642 compiler->n_insns++;
643
644 cinsn->flags = xinsn->flags;
645 cinsn->flags |= ORC_INSN_FLAG_ADDED;
646 cinsn->flags &= ~(ORC_INSTRUCTION_FLAG_X2|ORC_INSTRUCTION_FLAG_X4);
647 cinsn->opcode = get_store_opcode_for_size (var->size);
648 cinsn->src_args[0] = orc_compiler_new_temporary (compiler, var->size);
649 cinsn->dest_args[0] = xinsn->dest_args[i];
650 xinsn->dest_args[i] = cinsn->src_args[0];
651 }
652 }
653 }
654
655 }
656 }
657
658 static void
orc_compiler_assign_rules(OrcCompiler * compiler)659 orc_compiler_assign_rules (OrcCompiler *compiler)
660 {
661 int i;
662
663 for(i=0;i<compiler->n_insns;i++) {
664 OrcInstruction *insn = compiler->insns + i;
665
666 insn->rule = orc_target_get_rule (compiler->target, insn->opcode,
667 compiler->target_flags);
668
669 if (insn->rule == NULL || insn->rule->emit == NULL) {
670 orc_compiler_error (compiler, "no code generation rule for %s on "
671 "target %s", insn->opcode->name, compiler->target->name);
672 compiler->result = ORC_COMPILE_RESULT_UNKNOWN_COMPILE;
673 return;
674 }
675 }
676 }
677
678 int
orc_compiler_get_temp_reg(OrcCompiler * compiler)679 orc_compiler_get_temp_reg (OrcCompiler *compiler)
680 {
681 int j;
682
683 for(j=0;j<ORC_N_REGS;j++){
684 compiler->alloc_regs[j] = 0;
685 }
686 for(j=0;j<ORC_N_COMPILER_VARIABLES;j++){
687 if (!compiler->vars[j].alloc) continue;
688
689 ORC_DEBUG("var %d: %d %d %d", j, compiler->vars[j].alloc,
690 compiler->vars[j].first_use,
691 compiler->vars[j].last_use);
692
693 if (compiler->vars[j].first_use == -1) {
694 compiler->alloc_regs[compiler->vars[j].alloc] = 1;
695 } else if (compiler->vars[j].first_use <= compiler->insn_index &&
696 compiler->vars[j].last_use >= compiler->insn_index) {
697 compiler->alloc_regs[compiler->vars[j].alloc] = 1;
698 }
699 }
700 for(j=0;j<compiler->n_constants;j++){
701 if (compiler->constants[j].alloc_reg) {
702 compiler->alloc_regs[compiler->constants[j].alloc_reg] = 1;
703 }
704 }
705
706 ORC_DEBUG("at insn %d %s", compiler->insn_index,
707 compiler->insns[compiler->insn_index].opcode->name);
708
709 for(j=compiler->min_temp_reg;j<ORC_VEC_REG_BASE+32;j++){
710 if (compiler->valid_regs[j] && !compiler->alloc_regs[j]) {
711 compiler->min_temp_reg = j+1;
712 if (compiler->max_used_temp_reg < j) compiler->max_used_temp_reg = j;
713 return j;
714 }
715 }
716
717 orc_compiler_error (compiler, "no temporary register available");
718 compiler->result = ORC_COMPILE_RESULT_UNKNOWN_COMPILE;
719
720 return 0;
721 }
722
723 static void
orc_compiler_rewrite_vars(OrcCompiler * compiler)724 orc_compiler_rewrite_vars (OrcCompiler *compiler)
725 {
726 int j;
727 int k;
728 OrcInstruction *insn;
729 OrcStaticOpcode *opcode;
730 int var;
731 int actual_var;
732
733 for(j=0;j<ORC_N_COMPILER_VARIABLES;j++){
734 if (compiler->vars[j].alloc) continue;
735 compiler->vars[j].last_use = -1;
736 }
737 for(j=0;j<compiler->n_insns;j++){
738 insn = compiler->insns + j;
739 opcode = insn->opcode;
740
741 /* set up args */
742 for(k=0;k<ORC_STATIC_OPCODE_N_SRC;k++){
743 if (opcode->src_size[k] == 0) continue;
744
745 var = insn->src_args[k];
746 if (compiler->vars[var].vartype == ORC_VAR_TYPE_DEST) {
747 compiler->vars[var].load_dest = TRUE;
748 }
749 if (compiler->vars[var].vartype == ORC_VAR_TYPE_SRC ||
750 compiler->vars[var].vartype == ORC_VAR_TYPE_DEST ||
751 compiler->vars[var].vartype == ORC_VAR_TYPE_CONST ||
752 compiler->vars[var].vartype == ORC_VAR_TYPE_PARAM) {
753 continue;
754 }
755
756 actual_var = var;
757 if (compiler->vars[var].replaced) {
758 actual_var = compiler->vars[var].replacement;
759 insn->src_args[k] = actual_var;
760 }
761
762 if (!compiler->vars[var].used) {
763 if (compiler->vars[var].vartype == ORC_VAR_TYPE_TEMP) {
764 ORC_COMPILER_ERROR(compiler, "using uninitialized temp var at line %d", insn->line);
765 compiler->result = ORC_COMPILE_RESULT_UNKNOWN_PARSE;
766 }
767 compiler->vars[var].used = TRUE;
768 compiler->vars[var].first_use = j;
769 }
770 compiler->vars[actual_var].last_use = j;
771 }
772
773 for(k=0;k<ORC_STATIC_OPCODE_N_DEST;k++){
774 if (opcode->dest_size[k] == 0) continue;
775
776 var = insn->dest_args[k];
777
778 if (compiler->vars[var].vartype == ORC_VAR_TYPE_DEST) {
779 continue;
780 }
781 if (compiler->vars[var].vartype == ORC_VAR_TYPE_SRC) {
782 ORC_COMPILER_ERROR(compiler,"using src var as dest at line %d", insn->line);
783 compiler->result = ORC_COMPILE_RESULT_UNKNOWN_PARSE;
784 }
785 if (compiler->vars[var].vartype == ORC_VAR_TYPE_CONST) {
786 ORC_COMPILER_ERROR(compiler,"using const var as dest at line %d", insn->line);
787 compiler->result = ORC_COMPILE_RESULT_UNKNOWN_PARSE;
788 }
789 if (compiler->vars[var].vartype == ORC_VAR_TYPE_PARAM) {
790 ORC_COMPILER_ERROR(compiler,"using param var as dest at line %d", insn->line);
791 compiler->result = ORC_COMPILE_RESULT_UNKNOWN_PARSE;
792 }
793 if (opcode->flags & ORC_STATIC_OPCODE_ACCUMULATOR) {
794 if (compiler->vars[var].vartype != ORC_VAR_TYPE_ACCUMULATOR) {
795 ORC_COMPILER_ERROR(compiler,"accumulating opcode to non-accumulator dest at line %d", insn->line);
796 compiler->result = ORC_COMPILE_RESULT_UNKNOWN_PARSE;
797 }
798 } else {
799 if (compiler->vars[var].vartype == ORC_VAR_TYPE_ACCUMULATOR) {
800 ORC_COMPILER_ERROR(compiler,"non-accumulating opcode to accumulator dest at line %d", insn->line);
801 compiler->result = ORC_COMPILE_RESULT_UNKNOWN_PARSE;
802 }
803 }
804
805 actual_var = var;
806 if (compiler->vars[var].replaced) {
807 actual_var = compiler->vars[var].replacement;
808 insn->dest_args[k] = actual_var;
809 }
810
811 if (!compiler->vars[var].used) {
812 compiler->vars[actual_var].used = TRUE;
813 compiler->vars[actual_var].first_use = j;
814 } else {
815 #if 0
816 if (compiler->vars[var].vartype == ORC_VAR_TYPE_DEST) {
817 ORC_COMPILER_ERROR(compiler,"writing dest more than once at line %d", insn->line);
818 compiler->result = ORC_COMPILE_RESULT_UNKNOWN_PARSE;
819 }
820 #endif
821 if (compiler->vars[var].vartype == ORC_VAR_TYPE_TEMP) {
822 actual_var = orc_compiler_dup_temporary (compiler, var, j);
823 compiler->vars[var].replaced = TRUE;
824 compiler->vars[var].replacement = actual_var;
825 insn->dest_args[k] = actual_var;
826 compiler->vars[actual_var].used = TRUE;
827 compiler->vars[actual_var].first_use = j;
828 }
829 }
830 compiler->vars[actual_var].last_use = j;
831 }
832 }
833 }
834
835 static void
orc_compiler_global_reg_alloc(OrcCompiler * compiler)836 orc_compiler_global_reg_alloc (OrcCompiler *compiler)
837 {
838 int i;
839 OrcVariable *var;
840
841 for(i=0;i<ORC_N_COMPILER_VARIABLES;i++){
842 var = compiler->vars + i;
843 if (var->name == NULL) continue;
844 switch (var->vartype) {
845 case ORC_VAR_TYPE_CONST:
846 break;
847 case ORC_VAR_TYPE_PARAM:
848 break;
849 case ORC_VAR_TYPE_SRC:
850 var->ptr_register = orc_compiler_allocate_register (compiler, FALSE);
851 if (compiler->need_mask_regs) {
852 var->mask_alloc = orc_compiler_allocate_register (compiler, TRUE);
853 var->ptr_offset = orc_compiler_allocate_register (compiler, FALSE);
854 var->aligned_data = orc_compiler_allocate_register (compiler, TRUE);
855 }
856 if (var->need_offset_reg) {
857 var->ptr_offset = orc_compiler_allocate_register (compiler, FALSE);
858 }
859 break;
860 case ORC_VAR_TYPE_DEST:
861 var->ptr_register = orc_compiler_allocate_register (compiler, FALSE);
862 break;
863 case ORC_VAR_TYPE_ACCUMULATOR:
864 var->first_use = -1;
865 var->last_use = -1;
866 var->alloc = orc_compiler_allocate_register (compiler, TRUE);
867 break;
868 case ORC_VAR_TYPE_TEMP:
869 break;
870 default:
871 orc_compiler_error (compiler, "bad vartype");
872 compiler->result = ORC_COMPILE_RESULT_UNKNOWN_PARSE;
873 break;
874 }
875
876 if (compiler->error) break;
877 }
878
879 for(i=0;i<compiler->n_insns;i++){
880 OrcInstruction *insn = compiler->insns + i;
881 OrcStaticOpcode *opcode = insn->opcode;
882
883 if (opcode->flags & ORC_STATIC_OPCODE_INVARIANT) {
884 var = compiler->vars + insn->dest_args[0];
885
886 var->first_use = -1;
887 var->last_use = -1;
888 var->alloc = orc_compiler_allocate_register (compiler, TRUE);
889 insn->flags |= ORC_INSN_FLAG_INVARIANT;
890 }
891
892 if (opcode->flags & ORC_STATIC_OPCODE_ITERATOR) {
893 compiler->has_iterator_opcode = TRUE;
894 }
895 }
896
897 if (compiler->alloc_loop_counter && !compiler->error) {
898 compiler->loop_counter = orc_compiler_allocate_register (compiler, FALSE);
899 /* FIXME massive hack */
900 if (compiler->loop_counter == 0) {
901 compiler->error = FALSE;
902 compiler->result = ORC_COMPILE_RESULT_OK;
903 }
904 }
905 }
906
907 static void
orc_compiler_rewrite_vars2(OrcCompiler * compiler)908 orc_compiler_rewrite_vars2 (OrcCompiler *compiler)
909 {
910 int i;
911 int j;
912 int k;
913
914 for(j=0;j<compiler->n_insns;j++){
915 #if 1
916 /* must be true to chain src1 to dest:
917 * - rule must handle it
918 * - src1 must be last_use
919 * - only one dest
920 */
921 if (compiler->insns[j].flags & ORC_INSN_FLAG_INVARIANT) continue;
922
923 if (!(compiler->insns[j].opcode->flags & ORC_STATIC_OPCODE_ACCUMULATOR)) {
924 int src1 = compiler->insns[j].src_args[0];
925 int dest;
926
927 if (compiler->insns[j].opcode->dest_size[1] == 0)
928 dest = compiler->insns[j].dest_args[0];
929 else
930 dest = compiler->insns[j].dest_args[1];
931
932 if (compiler->vars[src1].last_use == j) {
933 if (compiler->vars[src1].first_use == j) {
934 k = orc_compiler_allocate_register (compiler, TRUE);
935 compiler->vars[src1].alloc = k;
936 }
937 compiler->alloc_regs[compiler->vars[src1].alloc]++;
938 compiler->vars[dest].alloc = compiler->vars[src1].alloc;
939 }
940 }
941 #endif
942
943 if (0) {
944 /* immediate operand, don't load */
945 int src2 = compiler->insns[j].src_args[1];
946 compiler->vars[src2].alloc = 1;
947 } else {
948 int src2 = compiler->insns[j].src_args[1];
949 if (src2 != -1 && compiler->vars[src2].alloc == 1) {
950 compiler->vars[src2].alloc = 0;
951 }
952 }
953
954 for(i=0;i<ORC_N_COMPILER_VARIABLES;i++){
955 if (compiler->vars[i].name == NULL) continue;
956 if (compiler->vars[i].last_use == -1) continue;
957 if (compiler->vars[i].first_use == j) {
958 if (compiler->vars[i].alloc) continue;
959 k = orc_compiler_allocate_register (compiler, TRUE);
960 compiler->vars[i].alloc = k;
961 }
962 }
963 for(i=0;i<ORC_N_COMPILER_VARIABLES;i++){
964 if (compiler->vars[i].name == NULL) continue;
965 if (compiler->vars[i].last_use == j) {
966 compiler->alloc_regs[compiler->vars[i].alloc]--;
967 }
968 }
969 }
970
971 }
972
973 static int
orc_compiler_dup_temporary(OrcCompiler * compiler,int var,int j)974 orc_compiler_dup_temporary (OrcCompiler *compiler, int var, int j)
975 {
976 int i = ORC_VAR_T1 + compiler->n_temp_vars + compiler->n_dup_vars;
977
978 compiler->vars[i].vartype = ORC_VAR_TYPE_TEMP;
979 compiler->vars[i].size = compiler->vars[var].size;
980 compiler->vars[i].name = malloc (strlen(compiler->vars[var].name) + 10);
981 sprintf(compiler->vars[i].name, "%s.dup%d", compiler->vars[var].name, j);
982 compiler->n_dup_vars++;
983
984 return i;
985 }
986
987 static int
orc_compiler_new_temporary(OrcCompiler * compiler,int size)988 orc_compiler_new_temporary (OrcCompiler *compiler, int size)
989 {
990 int i = ORC_VAR_T1 + compiler->n_temp_vars + compiler->n_dup_vars;
991
992 compiler->vars[i].vartype = ORC_VAR_TYPE_TEMP;
993 compiler->vars[i].size = size;
994 compiler->vars[i].name = malloc (10);
995 sprintf(compiler->vars[i].name, "tmp%d", i);
996 compiler->n_dup_vars++;
997
998 return i;
999 }
1000
1001 #if 0
1002 static void
1003 orc_compiler_dump_asm (OrcCompiler *compiler)
1004 {
1005 printf("%s", compiler->asm_code);
1006 }
1007 #endif
1008
1009 /**
1010 * orc_compiler_append_code:
1011 * @p: an OrcCompiler object
1012 * @fmt: a printf-style format string
1013 * @...: optional printf-style arguments
1014 *
1015 * Generates a string using sprintf() on the given format and
1016 * arguments, and appends that string to the generated assembly
1017 * code for the compiler.
1018 *
1019 * This function is used by the ORC_ASM_CODE() macro.
1020 *
1021 * This function is useful in a function implementing an OrcRule
1022 * or implementing a target.
1023 */
1024 void
orc_compiler_append_code(OrcCompiler * p,const char * fmt,...)1025 orc_compiler_append_code (OrcCompiler *p, const char *fmt, ...)
1026 {
1027 char tmp[200];
1028 va_list varargs;
1029 int n;
1030
1031 va_start (varargs, fmt);
1032 vsnprintf(tmp, 200 - 1, fmt, varargs);
1033 va_end (varargs);
1034
1035 n = strlen (tmp);
1036 p->asm_code = realloc (p->asm_code, p->asm_code_len + n + 1);
1037 memcpy (p->asm_code + p->asm_code_len, tmp, n + 1);
1038 p->asm_code_len += n;
1039 }
1040
1041 int
orc_compiler_label_new(OrcCompiler * compiler)1042 orc_compiler_label_new (OrcCompiler *compiler)
1043 {
1044 return compiler->n_labels++;
1045 }
1046
1047 static void
orc_compiler_load_constant(OrcCompiler * compiler,int reg,int size,int value)1048 orc_compiler_load_constant (OrcCompiler *compiler, int reg, int size,
1049 int value)
1050 {
1051 compiler->target->load_constant (compiler, reg, size, value);
1052 }
1053
1054 static void
orc_compiler_load_constant_long(OrcCompiler * compiler,int reg,OrcConstant * constant)1055 orc_compiler_load_constant_long (OrcCompiler *compiler, int reg,
1056 OrcConstant *constant)
1057 {
1058 compiler->target->load_constant_long (compiler, reg, constant);
1059 }
1060
1061 int
orc_compiler_get_temp_constant(OrcCompiler * compiler,int size,int value)1062 orc_compiler_get_temp_constant (OrcCompiler *compiler, int size, int value)
1063 {
1064 int tmp;
1065
1066 tmp = orc_compiler_get_temp_reg (compiler);
1067 orc_compiler_load_constant (compiler, tmp, size, value);
1068 return tmp;
1069 }
1070
1071 int
orc_compiler_get_constant(OrcCompiler * compiler,int size,int value)1072 orc_compiler_get_constant (OrcCompiler *compiler, int size, int value)
1073 {
1074 int i;
1075 int tmp;
1076 unsigned int v = value;
1077
1078 if (size < 4) {
1079 if (size < 2) {
1080 v &= 0xff;
1081 v |= (v<<8);
1082 }
1083 v &= 0xffff;
1084 v |= (v<<16);
1085 }
1086
1087 for(i=0;i<compiler->n_constants;i++){
1088 if (compiler->constants[i].is_long == FALSE &&
1089 compiler->constants[i].value == v) {
1090 break;
1091 }
1092 }
1093 if (i == compiler->n_constants) {
1094 compiler->n_constants++;
1095 compiler->constants[i].value = v;
1096 compiler->constants[i].alloc_reg = 0;
1097 compiler->constants[i].use_count = 0;
1098 compiler->constants[i].is_long = FALSE;
1099 }
1100
1101 compiler->constants[i].use_count++;
1102
1103 if (compiler->constants[i].alloc_reg != 0) {;
1104 return compiler->constants[i].alloc_reg;
1105 }
1106 tmp = orc_compiler_get_temp_reg (compiler);
1107 orc_compiler_load_constant (compiler, tmp, size, value);
1108 return tmp;
1109 }
1110
1111 int
orc_compiler_get_constant_long(OrcCompiler * compiler,orc_uint32 a,orc_uint32 b,orc_uint32 c,orc_uint32 d)1112 orc_compiler_get_constant_long (OrcCompiler *compiler,
1113 orc_uint32 a, orc_uint32 b, orc_uint32 c, orc_uint32 d)
1114 {
1115 int tmp;
1116
1117 tmp = orc_compiler_try_get_constant_long (compiler, a, b, c, d);
1118 if (tmp == ORC_REG_INVALID) {
1119 tmp = orc_compiler_get_temp_reg (compiler);
1120 orc_compiler_load_constant_long (compiler, tmp,
1121 &compiler->constants[compiler->n_constants - 1]);
1122 }
1123 return tmp;
1124 }
1125
1126 int
orc_compiler_try_get_constant_long(OrcCompiler * compiler,orc_uint32 a,orc_uint32 b,orc_uint32 c,orc_uint32 d)1127 orc_compiler_try_get_constant_long (OrcCompiler *compiler,
1128 orc_uint32 a, orc_uint32 b, orc_uint32 c, orc_uint32 d)
1129 {
1130 int i;
1131
1132 for(i=0;i<compiler->n_constants;i++){
1133 if (compiler->constants[i].is_long == TRUE &&
1134 compiler->constants[i].full_value[0] == a &&
1135 compiler->constants[i].full_value[1] == b &&
1136 compiler->constants[i].full_value[2] == c &&
1137 compiler->constants[i].full_value[3] == d) {
1138 break;
1139 }
1140 }
1141 if (i == compiler->n_constants) {
1142 compiler->n_constants++;
1143 compiler->constants[i].full_value[0] = a;
1144 compiler->constants[i].full_value[1] = b;
1145 compiler->constants[i].full_value[2] = c;
1146 compiler->constants[i].full_value[3] = d;
1147 compiler->constants[i].is_long = TRUE;
1148 compiler->constants[i].alloc_reg = 0;
1149 compiler->constants[i].use_count = 0;
1150 }
1151
1152 compiler->constants[i].use_count++;
1153
1154 if (compiler->constants[i].alloc_reg != 0) {;
1155 return compiler->constants[i].alloc_reg;
1156 }
1157 return ORC_REG_INVALID;
1158 }
1159
1160
1161 int
orc_compiler_get_constant_reg(OrcCompiler * compiler)1162 orc_compiler_get_constant_reg (OrcCompiler *compiler)
1163 {
1164 int j;
1165
1166 for(j=0;j<ORC_N_REGS;j++){
1167 compiler->alloc_regs[j] = 0;
1168 }
1169 for(j=0;j<ORC_N_COMPILER_VARIABLES;j++){
1170 if (!compiler->vars[j].alloc) continue;
1171
1172 ORC_DEBUG("var %d: %d %d %d", j, compiler->vars[j].alloc,
1173 compiler->vars[j].first_use,
1174 compiler->vars[j].last_use);
1175
1176 if (compiler->vars[j].first_use == -1) {
1177 compiler->alloc_regs[compiler->vars[j].alloc] = 1;
1178 } else if (compiler->vars[j].last_use != -1) {
1179 compiler->alloc_regs[compiler->vars[j].alloc] = 1;
1180 }
1181 }
1182 for(j=0;j<compiler->n_constants;j++){
1183 if (compiler->constants[j].alloc_reg) {
1184 compiler->alloc_regs[compiler->constants[j].alloc_reg] = 1;
1185 }
1186 }
1187 if (compiler->max_used_temp_reg < compiler->min_temp_reg)
1188 compiler->max_used_temp_reg = compiler->min_temp_reg;
1189
1190 for(j=ORC_VEC_REG_BASE;j<=compiler->max_used_temp_reg;j++) {
1191 compiler->alloc_regs[j] = 1;
1192 }
1193
1194 for(j=compiler->max_used_temp_reg;j<ORC_VEC_REG_BASE+32;j++){
1195 if (compiler->valid_regs[j] && !compiler->alloc_regs[j]) {
1196 return j;
1197 }
1198 }
1199
1200 return 0;
1201 }
1202
1203 #define ORC_COMPILER_ERROR_BUFFER_SIZE 200
1204
1205 static void
orc_compiler_error_valist(OrcCompiler * compiler,const char * fmt,va_list args)1206 orc_compiler_error_valist (OrcCompiler *compiler, const char *fmt,
1207 va_list args)
1208 {
1209 char *s;
1210
1211 if (compiler->error_msg) return;
1212
1213 s = malloc (ORC_COMPILER_ERROR_BUFFER_SIZE);
1214 vsprintf (s, fmt, args);
1215 compiler->error_msg = s;
1216 compiler->error = TRUE;
1217 compiler->result = ORC_COMPILE_RESULT_UNKNOWN_COMPILE;
1218 }
1219
1220 void
orc_compiler_error(OrcCompiler * compiler,const char * fmt,...)1221 orc_compiler_error (OrcCompiler *compiler, const char *fmt, ...)
1222 {
1223 va_list var_args;
1224
1225 va_start (var_args, fmt);
1226 orc_compiler_error_valist (compiler, fmt, var_args);
1227 va_end (var_args);
1228 }
1229
1230 void
orc_compiler_emit_invariants(OrcCompiler * compiler)1231 orc_compiler_emit_invariants (OrcCompiler *compiler)
1232 {
1233 int j;
1234 OrcInstruction *insn;
1235 OrcStaticOpcode *opcode;
1236 OrcRule *rule;
1237
1238 for(j=0;j<compiler->n_insns;j++){
1239 insn = compiler->insns + j;
1240 opcode = insn->opcode;
1241
1242 if (!(insn->flags & ORC_INSN_FLAG_INVARIANT)) continue;
1243
1244 ORC_ASM_CODE(compiler,"# %d: %s\n", j, opcode->name);
1245
1246 compiler->insn_shift = compiler->loop_shift;
1247 if (insn->flags & ORC_INSTRUCTION_FLAG_X2) {
1248 compiler->insn_shift += 1;
1249 }
1250 if (insn->flags & ORC_INSTRUCTION_FLAG_X4) {
1251 compiler->insn_shift += 2;
1252 }
1253
1254 rule = insn->rule;
1255 if (rule && rule->emit) {
1256 rule->emit (compiler, rule->emit_user, insn);
1257 } else {
1258 orc_compiler_error (compiler, "no code generation rule for %s",
1259 opcode->name);
1260 }
1261 }
1262 }
1263