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