1 /*
2 * Copyright (c) 2005 - 2010, Nils R. Weller
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
26 */
27 #include "icode.h"
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <assert.h>
31 #include <stdarg.h>
32 #include <string.h>
33 #include <ctype.h>
34 #include <sys/mman.h>
35 #include <unistd.h>
36 #include "misc.h"
37 #include "token.h"
38 #include "control.h"
39 #include "decl.h"
40 #include "type.h"
41 #include "debug.h"
42 #include "defs.h"
43 #include "expr.h"
44 #include "error.h"
45 #include "subexpr.h"
46 #include "icode.h"
47 #include "symlist.h"
48 #include "typemap.h"
49 #include "reg.h"
50 #include "functions.h"
51 #include "backend.h" /* for get_sizeof() */
52 #include "scope.h"
53 #include "zalloc.h"
54 #include "cc1_main.h" /* flags */
55 #include "inlineasm.h"
56 #include "n_libc.h"
57
58 struct icode_instr *
alloc_icode_instr(void)59 alloc_icode_instr(void) {
60 static unsigned long seq;
61
62 #if USE_ZONE_ALLOCATOR
63 struct icode_instr *ret = zalloc_buf(Z_ICODE_INSTR);
64
65 ret->seqno = ++seq;
66
67 return ret;
68 #else
69 struct icode_instr *ret = n_xmalloc(sizeof *ret);
70 static struct icode_instr nullinstr;
71
72 *ret = nullinstr;
73 ret->seqno = ++seq;
74 return ret;
75 #endif
76 }
77
78 struct icode_list *
alloc_icode_list(void)79 alloc_icode_list(void) {
80 #if USE_ZONE_ALLOCATOR
81 return zalloc_buf(Z_ICODE_LIST);
82 #else
83 struct icode_list *ret = n_xmalloc(sizeof *ret);
84 static struct icode_list nullil;
85 *ret = nullil;
86 return ret;
87 #endif
88 }
89
90 struct icode_instr *
copy_icode_instr(struct icode_instr * ii)91 copy_icode_instr(struct icode_instr *ii) {
92 struct icode_instr *ret = alloc_icode_instr();
93 *ret = *ii;
94 return ret;
95 }
96
97 void
append_icode_list(struct icode_list * list,struct icode_instr * instr)98 append_icode_list(struct icode_list *list, struct icode_instr *instr) {
99 static unsigned long append_seqno;
100
101 instr->append_seqno = ++append_seqno;
102 if (list->tail == NULL) {
103 list->head = list->tail = instr;
104 } else {
105 list->tail->next = instr;
106 list->tail = instr;
107 }
108
109 /*
110 * XXX stuff below is a kludge to ensure that pointer pregs are
111 * always recorded properly
112 */
113 if (instr->src_vreg && instr->src_ptr_preg == NULL) {
114 if (instr->src_vreg->from_ptr) {
115 instr->src_ptr_preg
116 = instr->src_vreg->from_ptr->pregs[0];
117 } else if (instr->src_vreg->parent) {
118 struct vreg *vr2 =
119 get_parent_struct(instr->src_vreg);
120
121 /*
122 * 25/12/07: Always save parent struct, not
123 * just for pointers. Hmm, that raises the
124 * question of how reliable vr->parent is
125 * guaranteed to be in the backend anyway?
126 */
127 instr->src_parent_struct = vr2;
128 if (vr2->from_ptr) {
129 instr->src_ptr_preg
130 = vr2->from_ptr->pregs[0];
131 }
132 }
133 }
134 if (instr->dest_vreg && instr->dest_ptr_preg == NULL) {
135 if (instr->dest_vreg->from_ptr) {
136 instr->dest_ptr_preg
137 = instr->dest_vreg->from_ptr->pregs[0];
138 } else if (instr->dest_vreg->parent) {
139 struct vreg *vr2 =
140 get_parent_struct(instr->dest_vreg);
141 if (vr2->from_ptr) {
142 instr->dest_parent_struct = vr2;
143 instr->dest_ptr_preg
144 = vr2->from_ptr->pregs[0];
145 }
146 }
147 }
148 if (instr->type == INSTR_COPYSTRUCT) {
149 struct copystruct *cs = instr->dat;
150 struct vreg *structtop;
151
152 if (cs->src_vreg && cs->src_vreg->parent) {
153 structtop = get_parent_struct(cs->src_vreg);
154
155 /* 12/25/07: Always save, not just for pointers */
156 instr->src_parent_struct = structtop;
157 if (structtop->from_ptr) {
158 instr->src_ptr_preg =
159 structtop->from_ptr->pregs[0];
160 }
161 }
162 if (cs->dest_vreg && cs->dest_vreg->parent) {
163 structtop = get_parent_struct(cs->dest_vreg);
164 if (structtop->from_ptr) {
165 instr->dest_parent_struct = structtop;
166 instr->dest_ptr_preg =
167 structtop->from_ptr->pregs[0];
168 }
169 }
170 }
171 }
172
173 void
merge_icode_lists(struct icode_list * dest,struct icode_list * src)174 merge_icode_lists(struct icode_list *dest, struct icode_list *src) {
175 if (src->head == NULL) {
176 /* XXX ??? */
177 dest->res = src->res;
178 return;
179 }
180 if (dest->head == NULL) {
181 if (dest->tail != NULL) {
182 puts("icode list corruption detected");
183 exit(EXIT_FAILURE);
184 }
185 dest->head = src->head;
186 dest->tail = src->tail;
187 } else {
188 dest->tail->next = src->head;
189 if (src->tail != NULL) {
190 dest->tail = src->tail;
191 }
192 }
193 dest->res = src->res;
194 }
195
196 struct reg **
make_icode_pregs(struct vreg * vr,struct reg * r)197 make_icode_pregs(struct vreg *vr, struct reg *r) {
198 struct reg **ret;
199
200 if (vr == NULL || !vr->is_multi_reg_obj) {
201 ret = n_xmalloc(2 * sizeof *ret);
202 ret[0] = vr? vr->pregs[0]: r;
203 ret[1] = NULL;
204 } else {
205 ret = n_xmalloc(vr->is_multi_reg_obj * sizeof *ret);
206 if (vr->is_multi_reg_obj != 2) abort();
207 /* XXX hardcoded x86 */
208 ret[0] = vr->pregs[0];
209 ret[1] = vr->pregs[1];
210 }
211
212 return ret;
213 }
214
215 struct icode_instr *
generic_icode_make_instr(struct vreg * dest,struct vreg * src,int type)216 generic_icode_make_instr(struct vreg *dest, struct vreg *src, int type) {
217 struct icode_instr *ret = alloc_icode_instr();
218 ret->type = type;
219 ret->dest_vreg = dest;
220 if (dest != NULL) {
221 ret->dest_pregs = make_icode_pregs(dest, NULL);
222 }
223 ret->src_vreg = src;
224 if (src != NULL) {
225 ret->src_pregs = make_icode_pregs(src, NULL);
226 }
227 return ret;
228 }
229
230 static unsigned long lnum = 0;
231
232 unsigned long
get_label_count(void)233 get_label_count(void) {
234 return lnum;
235 }
236
237 struct icode_instr *
icode_make_label(const char * name)238 icode_make_label(const char *name) {
239 struct icode_instr *ret;
240 char buf[1024];
241
242 ret = alloc_icode_instr();
243 ret->type = INSTR_LABEL;
244
245 if (name == NULL) {
246 sprintf(buf, "L%lu", lnum++);
247 ret->dat = n_xstrdup(buf);
248 } else {
249 ret->dat = n_xstrdup(name);
250 }
251
252 return ret;
253 }
254
255 struct icode_instr *
icode_make_adj_allocated(int bytes)256 icode_make_adj_allocated(int bytes) {
257 struct icode_instr *ii = alloc_icode_instr();
258
259 ii->dat = n_xmemdup(&bytes, sizeof bytes);
260 ii->type = INSTR_ADJ_ALLOCATED;
261 return ii;
262 }
263
264 struct icode_instr *
icode_make_setreg(struct reg * r,int value)265 icode_make_setreg(struct reg *r, int value) {
266 struct icode_instr *ret = alloc_icode_instr();
267
268 ret->type = INSTR_SETREG;
269 ret->src_pregs = make_icode_pregs(NULL, r);
270 ret->dat = n_xmemdup(&value, sizeof value); /* XXX :-( */
271 return ret;
272 }
273
274 struct icode_instr *
icode_make_freestack(size_t bytes)275 icode_make_freestack(size_t bytes) {
276 struct icode_instr *ret = alloc_icode_instr();
277 ret->type = INSTR_FREESTACK;
278 ret->dat = n_xmemdup(&bytes, sizeof bytes);
279 return ret;
280 }
281
282
283 struct icode_instr *
icode_make_branch(struct icode_instr * dest,int btype,struct vreg * vr)284 icode_make_branch(struct icode_instr *dest, int btype, struct vreg *vr) {
285 struct icode_instr *ret = alloc_icode_instr();
286 ret->type = btype;
287 ret->dat = dest;
288 ret->dest_vreg = vr;
289 return ret;
290 }
291
292 struct icode_instr *
icode_make_call(const char * name)293 icode_make_call(const char *name) {
294 struct icode_instr *ret = alloc_icode_instr();
295 ret->type = INSTR_CALL;
296 ret->dat = (char *)name;
297 return ret;
298 }
299
300 struct icode_instr *
icode_make_call_indir(struct reg * r)301 icode_make_call_indir(struct reg *r) {
302 struct icode_instr *ret = alloc_icode_instr();
303 ret->type = INSTR_CALLINDIR;
304 ret->dat = r;
305 return ret;
306 }
307
308 void
icode_make_xchg(struct reg * r1,struct reg * r2,struct icode_list * il)309 icode_make_xchg(struct reg *r1, struct reg *r2, struct icode_list *il) {
310 struct icode_instr *ret = alloc_icode_instr();
311
312 ret->type = INSTR_XCHG;
313 ret->src_pregs = make_icode_pregs(NULL, r1);
314 ret->dest_pregs = make_icode_pregs(NULL, r2);
315 append_icode_list(il, ret);
316 }
317
318 void
icode_make_initialize_pic(struct function * f,struct icode_list * il)319 icode_make_initialize_pic(struct function *f, struct icode_list *il) {
320 struct icode_instr *ret = alloc_icode_instr();
321
322 ret->type = INSTR_INITIALIZE_PIC;
323 ret->dat = f;
324 append_icode_list(il, ret);
325 }
326
327 static struct icode_instr *
icode_make_load_vla(struct reg * r,struct type * ty)328 icode_make_load_vla(struct reg *r, struct type *ty) {
329 struct icode_instr *ii = alloc_icode_instr();
330
331 ii->type = INSTR_LOAD_VLA;
332 ii->dest_pregs = make_icode_pregs(NULL, r);
333 ii->dat = ty;
334 return ii;
335 }
336
337
338
339 static struct reg *
icode_prepare_loadstore(int is_load,struct reg * r,struct vreg * vr,struct vreg * parent_struct,struct vreg * protectme,struct icode_list * il,int * is_stack0)340 icode_prepare_loadstore(int is_load,
341 struct reg *r,
342 struct vreg *vr,
343 struct vreg *parent_struct,
344 struct vreg *protectme,
345 struct icode_list *il,
346 int *is_stack0) {
347
348 struct reg *ret = NULL;
349 int is_stack = 0;
350
351 /*
352 * Before any preparations are done, mark all other needed
353 * source/target registers unallocatable so they do not get
354 * trashed
355 *
356 * NOTE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
357 * If we load a multi-GPR item, that is done by calling
358 * icode_make_load() multiple times! The caller must therefore
359 * mark subsequent registers unallocatable himself! Otherwise
360 * the first load will only protect the first register but
361 * may trash subsequent ones
362 */
363 if (is_load) {
364 reg_set_unallocatable(r);
365 } else {
366 reg_set_unallocatable(protectme->pregs[0]);
367 if (protectme->is_multi_reg_obj) {
368 reg_set_unallocatable(protectme->pregs[1]);
369 }
370 }
371
372 if (IS_THREAD(vr->type->flags)) {
373 ret = ALLOC_GPR(curfunc, backend->get_ptr_size(),
374 il, NULL);
375 } else if (picflag && vreg_needs_pic_reloc(vr)) {
376 if (backend->need_pic_init) {
377 backend->icode_initialize_pic(curfunc, il);
378 curfunc->pic_initialized = 1;
379 }
380 ret = ALLOC_GPR(curfunc, backend->get_ptr_size(),
381 il, NULL);
382 } else {
383
384 /*
385 * This is not a TLS- or PIC-load, so we should need
386 * no register at all, unless the offset is too large!
387 */
388 if (arch_without_offset_limit()) {
389 goto out;
390 }
391
392 /*
393 * OK, we're on an arch with limited offsets. What we have
394 * to handle:
395 *
396 * - Stack variables. This is terrible because currently
397 * the final offsets are computed when it's too late. Therefore
398 * we always have to ensure that one register is allocated when
399 * we load/store a stack variable. This SUCKS and must be
400 * fixed!
401 *
402 * - Anonymous stack items (usually registers) - like for
403 * stack variables
404 *
405 * - Static struct members. Here we can check whether the
406 * offset is too large and, if necessary, compute the address
407 * in a register
408 *
409 * - Indirect struct members. Here we can check the offset
410 * and, if necessary, add it to the pointer register (which
411 * must already be resident)
412 */
413 if (vr->var_backed != NULL) {
414 if (vr->var_backed->dtype->storage == TOK_KEY_AUTO
415 || vr->var_backed->dtype->storage == 0) {
416 is_stack = 1;
417 } else if (vr->var_backed->dtype->storage !=
418 TOK_KEY_REGISTER) {
419 /*
420 * 12/24/07: Static variable! On some archs
421 * this always requires an extra register
422 */
423 if (backend->arch == ARCH_SPARC) {
424 if (is_load) {
425 /*
426 * The target load register can
427 * be used to hold the address,
428 * UNLESS it is an FPR!
429 */
430 if (is_floating_type(vr->type)) {
431 ret = ALLOC_GPR(curfunc,
432 backend->get_ptr_size(),
433 il, NULL);
434 }
435 } else {
436 /* XXX hmm already seems to be handled */
437 ;
438 }
439 } else if (backend->arch == ARCH_POWER) {
440 } else if (backend->arch == ARCH_MIPS) {
441 } else {
442 /*
443 * 02/11/08: Woah that unimpl() seems
444 * a bit strong, disallowing all static
445 * variable access regardless of offset!
446 */
447 /* unimpl();*/
448 }
449 }
450 } else if (parent_struct != NULL) {
451 struct decl *d = parent_struct->var_backed;
452
453 if (d != NULL
454 && vr->from_ptr == NULL
455 && (d->dtype->storage == TOK_KEY_AUTO
456 || d->dtype->storage == 0)) {
457 is_stack = 1;
458 #if 0
459 } else if (parent_struct->stack_addr != NULL) {
460 is_stack = 1;
461 #endif
462 } else if (vr->from_ptr || parent_struct->from_ptr || d != NULL) {
463 /*
464 * Parent is pointer or static struct
465 */
466 long off;
467
468 off = calc_offsets(vr);
469 if (off > backend->max_displacement) {
470 /* Offset too big */
471 ret = ALLOC_GPR(curfunc, backend->get_ptr_size(),
472 il, NULL);
473 }
474 } else {
475 unimpl();
476 }
477 } else if (vr->stack_addr != NULL) {
478 is_stack = 1;
479 }
480
481 if (is_stack) {
482 ret = ALLOC_GPR(curfunc, backend->get_ptr_size(),
483 il, NULL);
484 }
485 }
486
487 out:
488 *is_stack0 = is_stack;
489
490 /* Restore allocatability */
491 if (is_load) {
492 /*
493 * 07/13/09: This also restored allocatability for dedicated
494 * temp regs
495 */
496 if (!r->dedicated) {
497 reg_set_allocatable(r);
498 }
499 } else {
500 if (!protectme->pregs[0]->dedicated) {
501 reg_set_allocatable(protectme->pregs[0]);
502 }
503 if (protectme->is_multi_reg_obj) {
504 if (!protectme->pregs[1]->dedicated) {
505 reg_set_allocatable(protectme->pregs[1]);
506 }
507 }
508 }
509 return ret;
510 }
511
512 struct vreg *
promote_bitfield(struct vreg * vr,struct icode_list * il)513 promote_bitfield(struct vreg *vr, struct icode_list *il) {
514
515 /*
516 * 08/09/08: If this is a signed bitfield member, perform sign
517 * extension on it! We can do this comfortably by shifting left,
518 * then right. This requires ``expected'' arithmetic shift right
519 * behavior, which is not standard but works on all supported
520 * architectures
521 */
522 if (vr->type->tbit != NULL) {
523 decode_bitfield(vr->type, vr, il);
524 vr = vreg_disconnect(vr);
525 vreg_do_anonymify(vr);
526 }
527 return vr;
528 }
529
530 /*
531 * XXX pass vreg instead??
532 * Note that this really only deals with one register at a time -
533 * multi-register objects are dealt with in vreg_faultin()
534 */
535 void
icode_make_load(struct reg * r,struct vreg * parent_struct,int is_not_first_load,struct icode_list * il)536 icode_make_load(struct reg *r, struct vreg *parent_struct,
537 int is_not_first_load, struct icode_list *il) {
538
539 struct icode_instr *ret = alloc_icode_instr();
540 struct vreg *vr = r->vreg;
541 static struct reg *supportreg;
542 int is_stack = 0;
543
544 #if 0
545 if (vr->from_ptr == NULL
546 && vr->var_backed == NULL
547 && vr->stack_addr == NULL
548 && vr->parent == NULL) {
549 printf("vr %p is unbacked!\n", vr);
550 abort();
551 }
552 #endif
553 if (IS_VLA(vr->type->flags) && is_immediate_vla_type(vr->type)) {
554 if (vr->from_ptr != NULL
555 && vr->from_ptr->type->tlist->type == TN_POINTER_TO) {
556 /*
557 * 05/27/11: Loading VLA address through pointer to
558 * VLA;
559 * char (*p)[expr] = ...
560 * strcpy(*p, "hello");
561 * This is handled like an ordinary array load, i.e.
562 * the pointer already constitutes the address.
563 * XXX We should probably trash that icode_make_load_vla(0
564 * stuff and handle all VLA load instructions exactly
565 * like ordinary array load operations, and have the
566 * emitters sort out the access (accessing the metadata
567 * array address rather than a stack or static buffer).
568 * It's not clear (3 years after VLAs were introduced)
569 * why the distinction is so explicit in the frontend
570 * right now
571 */
572 ;
573 } else {
574 append_icode_list(il, icode_make_load_vla(r, vr->type));
575 return;
576 }
577 }
578
579 if (vr->parent != NULL && parent_struct == NULL) {
580 parent_struct = get_parent_struct(vr);
581 }
582
583 /*
584 * 11/24/07: Time for some load preparations! In particular,
585 * build source address in a register if we are using large
586 * offsets on RISC, generating PIC, or accessing TLS.
587 */
588 if (is_not_first_load) {
589 /*
590 * This is the second (or later) part of a multi-register
591 * load; All preparations have already been done at the
592 * first load (supportreg is static)
593 */
594 ;
595 } else {
596 supportreg = icode_prepare_loadstore(1, r, vr,
597 parent_struct, NULL, il, &is_stack);
598 }
599
600 if (supportreg != NULL) {
601 if (is_stack) {
602 /*
603 * It's not yet clear whether the register is needed;
604 * Only save it just in case
605 */
606 ret->dat = supportreg;
607 } else {
608 /*
609 * We definitely have to indirect
610 */
611 /* struct icode_instr *ii;*/
612 struct vreg *ptrvr;
613
614 /*ii =*/ (void) icode_make_addrof(supportreg, vr, il);
615 /* append_icode_list(il, ii);*/
616 ptrvr = vreg_back_by_ptr(vr, supportreg, 0);
617 parent_struct = NULL;
618 vr = ptrvr;
619
620 #if 1
621 if (sysflag == OS_OSX
622 && vr->type->tlist != NULL
623 && vr->type->tlist->type == TN_FUNCTION) {
624 /*
625 * 02/08/09: When loading the address of a
626 * function on OSX, the initial load already
627 * computes the final function addres (i.e.
628 * it doesn't create a pointer through which
629 * we have to indirect to get the result
630 * pointer). So return that
631 *
632 * XXX This only applies to locally defined
633 * functions (_foo) and not nonlazy symbol
634 * references (L_foo$non_lazy_ptr).
635 * Currently we always create a non_lazy_ptr
636 * entry even for local functions. This may
637 * be undesirable
638 */
639 icode_make_copyreg(r, supportreg, NULL, NULL, il);
640 return;
641 }
642 #endif
643 }
644 }
645
646 if (vr->from_const && vr->from_const->data2) {
647 /* Too big to be immediate */
648 struct ty_llong *tll;
649
650 tll = vr->from_const->data2;
651 tll->loaded = 1;
652 }
653 if (vr->type->code == TY_STRUCT && vr->type->tlist == NULL) {
654 puts("BUG: Attempt to load struct into register :-(");
655 abort();
656 }
657
658 /*
659 * 12/07/07: Order matters!!!! In foo->bar, the vreg has both
660 * from_ptr and parent set... Hmm.. why anyway?
661 */
662 if (vr->from_ptr) {
663 ret->src_ptr_preg = vr->from_ptr->pregs[0];
664 } else if (vr->parent != NULL && parent_struct != NULL) {
665 /* 12/25/07: Always save parent, not just for pointers */
666 ret->src_parent_struct = parent_struct;
667 if (parent_struct->from_ptr) {
668 ret->src_ptr_preg =
669 parent_struct->from_ptr->pregs[0];
670 }
671 }
672
673 ret->type = INSTR_LOAD;
674 ret->src_vreg = vr;
675 ret->src_pregs = make_icode_pregs(NULL, r);
676 if (!vr->var_backed
677 && !vr->from_const
678 && !vr->from_ptr
679 && !vr->parent
680 && !vr->stack_addr) {
681 #if VREG_SEQNO
682 printf("BUG: load from unbacked vreg %p [seq %d]\n", vr, vr->seqno);
683 #else
684 printf("BUG: load from unbacked vreg %p\n", vr);
685 #endif
686 printf("calling abort()\n");
687 abort();
688 #if 0
689 } else {
690 debug_print_vreg_backing(vr);
691 #endif
692 }
693
694 append_icode_list(il, ret);
695
696 if (supportreg != NULL) {
697 if (!vr->is_multi_reg_obj || is_not_first_load) {
698 free_preg(supportreg, il, 1, 0);
699 supportreg = NULL;
700 }
701 }
702 }
703
704 void
icode_make_load_addrlabel(struct reg * r,struct icode_instr * label,struct icode_list * il)705 icode_make_load_addrlabel(struct reg *r, struct icode_instr *label,
706 struct icode_list *il) {
707
708 struct icode_instr *ii;
709
710 ii = alloc_icode_instr();
711 ii->dest_pregs = make_icode_pregs(NULL, r);
712 ii->dat = label;
713 ii->type = INSTR_LOAD_ADDRLABEL;
714 append_icode_list(il, ii);
715 if (backend->icode_prepare_load_addrlabel != NULL) {
716 /*
717 * 12/25/08: For PPC: We have to create a TOC entry
718 * for the label
719 */
720 backend->icode_prepare_load_addrlabel(label);
721 }
722 }
723
724 void
icode_make_comp_goto(struct reg * addr,struct icode_list * il)725 icode_make_comp_goto(struct reg *addr, struct icode_list *il) {
726 struct icode_instr *ii;
727
728 ii = alloc_icode_instr();
729 ii->dat = addr;
730 ii->type = INSTR_COMP_GOTO;
731 append_icode_list(il, ii);
732 }
733
734
735 /*
736 * 04/07/08: Ripped this out of icode_make_store()
737 *
738 * This allocates us a stack block for saving registers. The
739 * list of blocks will be allocated later
740 *
741 * XXXXXXXXXXXXXXXXXXXXX Why do we have to go here to get
742 * convenient stack allocation which gives us a stack_block
743 * immediately (so it can be assigned to multiple vregs), and
744 * why is there no other nice way?
745 *
746 * Is there something that could break here? (Alignment)
747 *
748 * Should we generalize the concept?
749 */
750 struct stack_block *
icode_alloc_reg_stack_block(struct function * f,size_t size)751 icode_alloc_reg_stack_block(struct function *f, size_t size) {
752 struct stack_block *sb;
753
754 sb = make_stack_block(0, size);
755
756 if (f->regs_head == NULL) {
757 f->regs_head = f->regs_tail = sb;
758 } else {
759 f->regs_tail->next = sb;
760 f->regs_tail = f->regs_tail->next;
761 }
762 return sb;
763 }
764
765 /*
766 * Store current item to virtual register vr
767 * XXX this is complete messed up
768 * Store current item (INSTR_SETITEM) to vr
769 *
770 */
771 void
icode_make_store(struct function * f,struct vreg * dest,struct vreg * src,struct icode_list * il)772 icode_make_store(struct function *f,
773 struct vreg *dest, struct vreg *src, /* XXX order is WRONG!! */
774 struct icode_list *il) {
775
776 struct icode_instr *ret = alloc_icode_instr();
777 static struct reg *supportreg;
778 struct vreg *parent = NULL;
779 int is_stack = 0;
780
781 if (src->parent != NULL) {
782 parent = get_parent_struct(src);
783 if (src->from_ptr || parent->from_ptr) {
784 /*
785 * 12/12/07: This preparation of parent vreg and
786 * pointer was missing (but present in make_load!)
787 */
788 ret->src_parent_struct = parent;
789 if (src->from_ptr) {
790 ret->src_ptr_preg = parent->pregs[0];
791 } else {
792 ret->src_ptr_preg = parent->from_ptr->pregs[0];
793 }
794 }
795 }
796
797 /*
798 * 11/24/07: Time for some store preparations! In particular,
799 * build target address in a register if we are using large
800 * offsets on RISC, generating PIC, or accessing TLS.
801 */
802 supportreg = icode_prepare_loadstore(0, NULL, src, parent,
803 dest, il, &is_stack);
804
805 if (supportreg != NULL) {
806 if (is_stack) {
807 /*
808 * It's not yet clear whether the register is needed;
809 * Only save it just in case
810 */
811 ret->dat = supportreg;
812 } else {
813 /*
814 * We definitely have to indirect
815 */
816 /*struct icode_instr *ii;*/
817 struct vreg *ptrvr;
818
819 /*ii =*/ (void) icode_make_addrof(supportreg, src, il);
820 /* append_icode_list(il, ii);*/
821 ptrvr = vreg_back_by_ptr(src, supportreg, 0);
822 /* parent_struct = NULL;*/
823 src = ptrvr;
824 }
825 }
826
827 ret->type = INSTR_STORE;
828 ret->dest_vreg = dest;
829 ret->dest_pregs = make_icode_pregs(dest, NULL);
830 ret->src_vreg = src;
831
832 if (src != NULL) {
833 ret->src_pregs = make_icode_pregs(src, NULL);
834 if (src->type->code == TY_STRUCT
835 && src->type->tlist == NULL) {
836 puts("BUG: Attempt to store register to struct :-((((");
837 abort();
838 }
839 }
840
841 /*
842 * 12/10/07: Added
843 */
844 if (src->from_ptr) {
845 ret->src_ptr_preg = src->from_ptr->pregs[0];
846 } else if (src->parent != NULL && parent != NULL) {
847 ret->src_parent_struct = parent;
848 if (parent->from_ptr) {
849 ret->src_ptr_preg = parent->from_ptr->pregs[0];
850 }
851 }
852
853 if (src != NULL
854 && !src->var_backed
855 && !src->from_ptr
856 && !src->from_const
857 && !src->parent) {
858 /*
859 * Need to allocate anonymous storage
860 * for register
861 */
862 if (src->stack_addr == NULL) {
863 /* Offset will be patched later */
864 /* XXX long long !?!?!!! */
865 size_t size = src->pregs[0]->size;
866
867 if (src->is_multi_reg_obj) {
868 size += src->pregs[1]->size;
869 } else if (backend->arch == ARCH_SPARC) {
870 /*
871 * XXX hmm this seems wrong and ugly
872 */
873 if (src->pregs[0]->type == REG_FPR) {
874 switch (src->type->code) {
875 case TY_FLOAT:
876 size = 4;
877 break;
878 case TY_DOUBLE:
879 size = 8;
880 break;
881 case TY_LDOUBLE:
882 size = 16;
883 break;
884 default: unimpl();
885 }
886 }
887 }
888
889 src->stack_addr = icode_alloc_reg_stack_block(f, size);
890 }
891 } else if (src->from_ptr) {
892 vreg_faultin_protected(src, NULL, NULL, src->from_ptr, il, 0);
893 }
894 append_icode_list(il, ret);
895
896 if (supportreg != NULL) {
897 free_preg(supportreg, il, 1, 0);
898 supportreg = NULL;
899 }
900 }
901
902
903 struct icode_instr *
icode_make_sub(struct vreg * dest,struct vreg * src)904 icode_make_sub(struct vreg *dest, struct vreg *src) {
905 return generic_icode_make_instr(dest, src, INSTR_SUB);
906 }
907
908 struct icode_instr *
icode_make_neg(struct vreg * vr)909 icode_make_neg(struct vreg *vr) {
910 return generic_icode_make_instr(NULL, vr, INSTR_NEG);
911 }
912
913
914 struct icode_instr *
icode_make_add(struct vreg * dest,struct vreg * src)915 icode_make_add(struct vreg *dest, struct vreg *src) {
916 return generic_icode_make_instr(dest, src, INSTR_ADD);
917 }
918
919 struct icode_instr *
icode_make_div(struct vreg * dest,struct vreg * src)920 icode_make_div(struct vreg *dest, struct vreg *src) {
921 return generic_icode_make_instr(dest, src, INSTR_DIV);
922 }
923
924 struct icode_instr *
icode_make_mod(struct vreg * dest,struct vreg * src)925 icode_make_mod(struct vreg *dest, struct vreg *src) {
926 return generic_icode_make_instr(dest, src, INSTR_MOD);
927 }
928
929 struct icode_instr *
icode_make_mul(struct vreg * dest,struct vreg * src)930 icode_make_mul(struct vreg *dest, struct vreg *src) {
931 return generic_icode_make_instr(dest, src, INSTR_MUL);
932 }
933
934 struct icode_instr *
icode_make_shl(struct vreg * dest,struct vreg * src)935 icode_make_shl(struct vreg *dest, struct vreg *src) {
936 return generic_icode_make_instr(dest, src, INSTR_SHL);
937 }
938
939 struct icode_instr *
icode_make_shr(struct vreg * dest,struct vreg * src)940 icode_make_shr(struct vreg *dest, struct vreg *src) {
941 return generic_icode_make_instr(dest, src, INSTR_SHR);
942 }
943
944 struct icode_instr *
icode_make_and(struct vreg * dest,struct vreg * src)945 icode_make_and(struct vreg *dest, struct vreg *src) {
946 return generic_icode_make_instr(dest, src, INSTR_AND);
947 }
948
949 struct icode_instr *
icode_make_xor(struct vreg * dest,struct vreg * src)950 icode_make_xor(struct vreg *dest, struct vreg *src) {
951 struct icode_instr *ret = alloc_icode_instr();
952 ret->type = INSTR_XOR;
953 ret->dest_vreg = dest;
954 ret->dest_pregs = make_icode_pregs(dest, NULL);
955 if (src != NULL) {
956 ret->src_pregs = make_icode_pregs(src, NULL);
957 }
958 ret->src_vreg = src;
959 return ret;
960 }
961
962 struct icode_instr *
icode_make_not(struct vreg * vr)963 icode_make_not(struct vreg *vr) {
964 return generic_icode_make_instr(NULL, vr, INSTR_NOT);
965 }
966
967 struct icode_instr *
icode_make_or(struct vreg * dest,struct vreg * src)968 icode_make_or(struct vreg *dest, struct vreg *src) {
969 return generic_icode_make_instr(dest, src, INSTR_OR);
970 }
971
972 void
icode_make_preg_or(struct reg * dest,struct reg * src,struct icode_list * il)973 icode_make_preg_or(struct reg *dest, struct reg *src, struct icode_list *il) {
974 struct icode_instr *ret = alloc_icode_instr();
975 ret->type = INSTR_PREG_OR;
976 ret->dest_pregs = make_icode_pregs(NULL, dest);
977 ret->src_pregs = make_icode_pregs(NULL, src);
978 append_icode_list(il, ret);
979 }
980
981 struct icode_instr *
icode_make_push(struct vreg * vr,struct icode_list * il)982 icode_make_push(struct vreg *vr, struct icode_list *il) {
983 struct icode_instr *ret = alloc_icode_instr();
984
985 ret->type = INSTR_PUSH;
986
987 /*
988 * 12/06/07: Wow, the unconditional type->tlist->type check
989 * below crashed when passing ``ar[i]'' to printf(): The
990 * subscript operator removed the type node but kept the
991 * is_vla flag.
992 * XXX Maybe we should change that instead?
993 */
994 if (vr->type && IS_VLA(vr->type->flags) && vr->type->tlist != NULL) {
995 if (vr->type->tlist->type == TN_ARRAY_OF
996 || vr->type->tlist->type == TN_VARARRAY_OF) {
997 struct reg *r;
998
999 if (vr->pregs[0] == NULL
1000 || vr->pregs[0]->vreg != vr) {
1001 r = ALLOC_GPR(curfunc, backend->get_ptr_size(),
1002 il, 0);
1003 vreg_map_preg(vr, r);
1004 icode_make_load(r, NULL, 0, il);
1005 free_preg(r, il, 0, 0);
1006 }
1007 }
1008 }
1009 ret->src_vreg = vr;
1010 ret->src_pregs= make_icode_pregs(vr, NULL);
1011
1012 return ret;
1013 }
1014
1015 struct icode_instr *
icode_make_ret(struct vreg * vr)1016 icode_make_ret(struct vreg *vr) {
1017 struct icode_instr *ret = alloc_icode_instr();
1018 ret->type = INSTR_RET;
1019 #if 0
1020 if (vr != NULL) {
1021 /*ret->src_preg = vr->preg; seems never used*/
1022 ret->src_vreg = vr;
1023 }
1024 #endif
1025 ret->src_vreg = vr;
1026 return ret;
1027 }
1028
1029 struct icode_instr *
icode_make_indir(struct reg * r)1030 icode_make_indir(struct reg *r) {
1031 struct icode_instr *ret = alloc_icode_instr();
1032 ret->type = INSTR_INDIR;
1033 ret->dat = r;
1034 return ret;
1035 }
1036
1037 /*
1038 * vr = NULL means take address of next argument on stack in
1039 * variadic function
1040 */
1041 struct reg * /*icode_instr **/
icode_make_addrof(struct reg * r,struct vreg * vr,struct icode_list * il)1042 icode_make_addrof(struct reg *r, struct vreg *vr, struct icode_list *il) {
1043 struct icode_instr *ret;
1044
1045 ret = alloc_icode_instr();
1046 ret->type = INSTR_ADDROF;
1047 ret->src_vreg = vr;
1048
1049 /*
1050 * 06/15/09: This was needed for stale parent struct pointers
1051 * and such
1052 */
1053 if (vr != NULL) {
1054 (void) vreg_faultin_ptr(vr, il);
1055
1056 /*
1057 * 02/01/10: This ``from pointer'' load does not
1058 * work to load the address of a function in PIC
1059 * mode! That type of load has to load a base
1060 * address, then load the final address
1061 * indirectly. This fails for functions because
1062 * vreg_faultin_ptr() will recurse to
1063 * icode_make_addrof(), and then things are
1064 * going to get trashed because the address is
1065 * already assumed to have been loaded, which it
1066 * hasn't.
1067 *
1068 * The solution is to avoid icode_make_addrof()
1069 * for that particular case (the address-of
1070 * handling for functions in subexpr.c just
1071 * uses vreg_faultin() instead). There may be
1072 * other cases as well
1073 */
1074 }
1075 #if 0
1076 ret->dat = backend->alloc_gpr(curfunc, 4, il, NULL); /* XXX */
1077 #endif
1078 if (r != NULL) {
1079 ret->dat = r;
1080 } else {
1081 ret->dat = ALLOC_GPR(curfunc, backend->get_ptr_size(),
1082 il, NULL); /* XXX */
1083 }
1084
1085 append_icode_list(il, ret);
1086 return ret->dat;
1087 }
1088
1089 struct icode_instr *
icode_make_inc(struct vreg * vr)1090 icode_make_inc(struct vreg *vr) {
1091 return generic_icode_make_instr(NULL, vr, INSTR_INC);
1092 }
1093
1094 struct icode_instr *
icode_make_dec(struct vreg * vr)1095 icode_make_dec(struct vreg *vr) {
1096 return generic_icode_make_instr(NULL, vr, INSTR_DEC);
1097 }
1098
1099 /*
1100 * =====================================================
1101 * x86-specific instructions
1102 * =====================================================
1103 */
1104 void
icode_make_x86_fxch(struct reg * r,struct reg * r2,struct icode_list * il)1105 icode_make_x86_fxch(struct reg *r, struct reg *r2, struct icode_list *il) {
1106 struct icode_instr *ret = alloc_icode_instr();
1107 struct vreg *tmp = r2->vreg;
1108
1109 ret->type = INSTR_X86_FXCH;
1110 ret->src_pregs = make_icode_pregs(NULL, r);
1111 ret->dest_pregs = make_icode_pregs(NULL, r2);
1112 append_icode_list(il, ret);
1113 if (r->vreg != NULL) {
1114 r->vreg->pregs[0] = r2;
1115 r2->vreg = r->vreg;
1116 }
1117 if (tmp != NULL) {
1118 r->vreg = tmp;
1119 r->vreg->pregs[0] = r;
1120 }
1121 }
1122
1123 void
icode_make_asm(struct inline_asm_stmt * inl,struct icode_list * il)1124 icode_make_asm(struct inline_asm_stmt *inl, struct icode_list *il) {
1125 struct icode_instr *ret = alloc_icode_instr();
1126 ret->type = INSTR_ASM;
1127 ret->dat = inl;
1128 append_icode_list(il, ret);
1129 }
1130
1131 void
icode_make_x86_cdq(struct icode_list * il)1132 icode_make_x86_cdq(struct icode_list *il) {
1133 struct icode_instr *ret = alloc_icode_instr();
1134 ret->type = INSTR_X86_CDQ;
1135 append_icode_list(il, ret);
1136 }
1137
1138 void
icode_make_x86_ffree(struct reg * r,struct icode_list * il)1139 icode_make_x86_ffree(struct reg *r, struct icode_list *il) {
1140 struct icode_instr *ret = alloc_icode_instr();
1141 ret->type = INSTR_X86_FFREE;
1142 ret->src_pregs = make_icode_pregs(NULL, r);
1143 append_icode_list(il, ret);
1144 }
1145
1146 void
icode_make_x86_store_x87cw(struct vreg * vr,struct icode_list * il)1147 icode_make_x86_store_x87cw(struct vreg *vr, struct icode_list *il) {
1148 struct icode_instr *ii;
1149
1150 ii = generic_icode_make_instr(NULL, vr, INSTR_X86_FNSTCW);
1151 append_icode_list(il, ii);
1152 }
1153
1154 void
icode_make_x86_load_x87cw(struct vreg * vr,struct icode_list * il)1155 icode_make_x86_load_x87cw(struct vreg *vr, struct icode_list *il) {
1156 struct icode_instr *ii;
1157
1158 ii = generic_icode_make_instr(NULL, vr, INSTR_X86_FLDCW);
1159 append_icode_list(il, ii);
1160 }
1161
1162 void
icode_make_x86_fild(struct reg * r,struct vreg * vr,struct icode_list * il)1163 icode_make_x86_fild(struct reg *r,
1164 struct vreg *vr, struct icode_list *il) {
1165
1166 struct icode_instr *ii;
1167 struct filddata *fdat;
1168
1169 ii = generic_icode_make_instr(NULL, NULL, INSTR_X86_FILD);
1170 fdat = n_xmalloc(sizeof *fdat);
1171 fdat->r = r;
1172 fdat->vr = vr;
1173 ii->dat = fdat;
1174 append_icode_list(il, ii);
1175 }
1176
1177 void
icode_make_x86_fist(struct reg * r,struct vreg * vr,struct type * ty,struct icode_list * il)1178 icode_make_x86_fist(struct reg *r,
1179 struct vreg *vr, struct type *ty, struct icode_list *il) {
1180
1181 struct icode_instr *ii;
1182 struct fistdata *fdat;
1183
1184 ii = generic_icode_make_instr(NULL, NULL, INSTR_X86_FIST);
1185 fdat = n_xmalloc(sizeof *fdat);
1186 fdat->r = r;
1187 fdat->vr = vr;
1188 fdat->target_type = ty;
1189 ii->dat = fdat;
1190 append_icode_list(il, ii);
1191 }
1192
1193
1194 /*
1195 * =====================================================
1196 * MIPS-specific instructions
1197 * =====================================================
1198 */
1199
1200 void
icode_make_mips_mtc1(struct reg * dest,struct vreg * src,struct icode_list * il)1201 icode_make_mips_mtc1(
1202 struct reg *dest,
1203 struct vreg *src,
1204 struct icode_list *il) {
1205 struct icode_instr *ii;
1206
1207 ii = generic_icode_make_instr(NULL, src, INSTR_MIPS_MTC1);
1208 ii->dat = dest;
1209 append_icode_list(il, ii);
1210 }
1211
1212 void
icode_make_mips_mfc1(struct reg * dest,struct vreg * src,struct icode_list * il)1213 icode_make_mips_mfc1(
1214 struct reg *dest,
1215 struct vreg *src,
1216 struct icode_list *il) {
1217 struct icode_instr *ii;
1218
1219 ii = generic_icode_make_instr(NULL, src, INSTR_MIPS_MFC1);
1220 ii->dat = dest;
1221 append_icode_list(il, ii);
1222 }
1223
1224 void
icode_make_mips_cvt(struct vreg * dest,struct vreg * src,struct icode_list * il)1225 icode_make_mips_cvt(
1226 struct vreg *dest,
1227 struct vreg *src,
1228 struct icode_list *il) {
1229
1230 struct icode_instr *ii;
1231
1232 ii = generic_icode_make_instr(dest, src, INSTR_MIPS_CVT);
1233 append_icode_list(il, ii);
1234 }
1235
1236 void
icode_make_mips_trunc(struct vreg * dest,struct vreg * src,struct icode_list * il)1237 icode_make_mips_trunc(
1238 struct vreg *dest,
1239 struct vreg *src,
1240 struct icode_list *il) {
1241
1242 struct icode_instr *ii;
1243
1244 ii = generic_icode_make_instr(dest, src, INSTR_MIPS_TRUNC);
1245 append_icode_list(il, ii);
1246 }
1247
1248 void
icode_make_mips_make_32bit_mask(struct reg * r,struct icode_list * il)1249 icode_make_mips_make_32bit_mask(struct reg *r, struct icode_list *il) {
1250 struct icode_instr *ii = alloc_icode_instr();
1251
1252 ii->type = INSTR_MIPS_MAKE_32BIT_MASK;
1253 ii->dat = r;
1254 append_icode_list(il, ii);
1255 }
1256
1257 /*
1258 * =====================================================
1259 * PowerPC-specific instructions
1260 * =====================================================
1261 */
1262 void
icode_make_power_srawi(struct reg * dest,struct reg * src,int bits,struct icode_list * il)1263 icode_make_power_srawi(struct reg *dest, struct reg *src,
1264 int bits, struct icode_list *il) {
1265
1266 struct icode_instr *ii;
1267
1268 ii = generic_icode_make_instr(NULL, NULL, INSTR_POWER_SRAWI);
1269 ii->dest_pregs = make_icode_pregs(NULL, dest);
1270 ii->src_pregs = make_icode_pregs(NULL, src);
1271 ii->dat = n_xmemdup(&bits, sizeof(int));
1272 append_icode_list(il, ii);
1273 }
1274
1275 void
icode_make_power_rldicl(struct reg * dest,struct reg * src,int bits,struct icode_list * il)1276 icode_make_power_rldicl(struct reg *dest, struct reg *src,
1277 int bits, struct icode_list *il) {
1278
1279 struct icode_instr *ii;
1280
1281 ii = generic_icode_make_instr(NULL, NULL, INSTR_POWER_RLDICL);
1282 ii->dest_pregs = make_icode_pregs(NULL, dest);
1283 ii->src_pregs = make_icode_pregs(NULL, src);
1284 ii->dat = n_xmemdup(&bits, sizeof(int));
1285 append_icode_list(il, ii);
1286 }
1287
1288 void
icode_make_power_fcfid(struct reg * dest,struct reg * src,struct icode_list * il)1289 icode_make_power_fcfid(struct reg *dest, struct reg *src,
1290 struct icode_list *il) {
1291
1292 struct icode_instr *ii;
1293
1294 ii = generic_icode_make_instr(NULL, NULL, INSTR_POWER_FCFID);
1295 ii->dest_pregs = make_icode_pregs(NULL, dest);
1296 ii->src_pregs = make_icode_pregs(NULL, src);
1297 append_icode_list(il, ii);
1298 }
1299
1300 void
icode_make_power_frsp(struct reg * dest,struct icode_list * il)1301 icode_make_power_frsp(struct reg *dest, struct icode_list *il) {
1302 struct icode_instr *ii;
1303
1304 ii = generic_icode_make_instr(NULL, NULL, INSTR_POWER_FRSP);
1305 ii->dat = dest;
1306 append_icode_list(il, ii);
1307 }
1308
1309
1310 void
icode_make_power_slwi(struct reg * dest,struct reg * src,int bits,struct icode_list * il)1311 icode_make_power_slwi(struct reg *dest, struct reg *src,
1312 int bits, struct icode_list *il) {
1313 struct icode_instr *ii;
1314
1315 ii = generic_icode_make_instr(NULL, NULL, INSTR_POWER_SLWI);
1316 ii->dest_pregs = make_icode_pregs(NULL, dest);
1317 ii->src_pregs = make_icode_pregs(NULL, src);
1318 ii->dat = n_xmemdup(&bits, sizeof(int));
1319 append_icode_list(il, ii);
1320 }
1321
1322 void
icode_make_power_rlwinm(struct reg * dest,struct reg * src,int value,struct icode_list * il)1323 icode_make_power_rlwinm(struct reg *dest, struct reg *src, int
1324 value, struct icode_list *il) {
1325
1326 struct icode_instr *ii;
1327
1328 ii = generic_icode_make_instr(NULL, NULL, INSTR_POWER_RLWINM);
1329 ii->dest_pregs = make_icode_pregs(NULL, dest);
1330 ii->src_pregs = make_icode_pregs(NULL, src);
1331 ii->dat = n_xmemdup(&value, sizeof(int));
1332 append_icode_list(il, ii);
1333 }
1334
1335 void
icode_make_power_extsb(struct reg * r,struct icode_list * il)1336 icode_make_power_extsb(struct reg *r, struct icode_list *il) {
1337 struct icode_instr *ii;
1338
1339 ii = generic_icode_make_instr(NULL, NULL, INSTR_POWER_EXTSB);
1340 ii->dat = r;
1341 append_icode_list(il, ii);
1342 }
1343
1344 void
icode_make_power_extsh(struct reg * r,struct icode_list * il)1345 icode_make_power_extsh(struct reg *r, struct icode_list *il) {
1346 struct icode_instr *ii;
1347
1348 ii = generic_icode_make_instr(NULL, NULL, INSTR_POWER_EXTSH);
1349 ii->dat = r;
1350 append_icode_list(il, ii);
1351 }
1352
1353 void
icode_make_power_extsw(struct reg * r,struct icode_list * il)1354 icode_make_power_extsw(struct reg *r, struct icode_list *il) {
1355 struct icode_instr *ii;
1356
1357 ii = generic_icode_make_instr(NULL, NULL, INSTR_POWER_EXTSW);
1358 ii->dat = r;
1359 append_icode_list(il, ii);
1360 }
1361
1362
1363 void
icode_make_power_xoris(struct reg * dest,int val,struct icode_list * il)1364 icode_make_power_xoris(struct reg *dest, int val, struct icode_list *il) {
1365 struct icode_instr *ii;
1366
1367 ii = generic_icode_make_instr(NULL, NULL, INSTR_POWER_XORIS);
1368 ii->dest_pregs = make_icode_pregs(NULL, dest);
1369 ii->dat = n_xmemdup(&val, sizeof(int));
1370 append_icode_list(il, ii);
1371 }
1372
1373 void
icode_make_power_lis(struct reg * dest,int val,struct icode_list * il)1374 icode_make_power_lis(struct reg *dest, int val, struct icode_list *il) {
1375 struct icode_instr *ii;
1376
1377 ii = generic_icode_make_instr(NULL, NULL, INSTR_POWER_LIS);
1378 ii->dest_pregs = make_icode_pregs(NULL, dest);
1379 ii->dat = n_xmemdup(&val, sizeof(int));
1380 append_icode_list(il, ii);
1381 }
1382
1383 void
icode_make_power_loadup4(struct reg * dest,struct vreg * src,struct icode_list * il)1384 icode_make_power_loadup4(struct reg *dest, struct vreg *src,
1385 struct icode_list *il) {
1386
1387 struct icode_instr *ii;
1388
1389 ii = generic_icode_make_instr(NULL, src, INSTR_POWER_LOADUP4);
1390 ii->dest_pregs = make_icode_pregs(NULL, dest);
1391 append_icode_list(il, ii);
1392 }
1393
1394 void
icode_make_power_fctiwz(struct reg * r,int for_unsigned,struct icode_list * il)1395 icode_make_power_fctiwz(struct reg *r, int for_unsigned, struct icode_list *il) {
1396 struct icode_instr *ii;
1397
1398 ii = generic_icode_make_instr(NULL, NULL, INSTR_POWER_FCTIWZ);
1399 ii->dat = r;
1400 if (for_unsigned) {
1401 ii->hints |= HINT_INSTR_GENERIC_MODIFIER;
1402 }
1403 append_icode_list(il, ii);
1404 }
1405
1406 /*
1407 * =====================================================
1408 * SPARC-specific instructions
1409 * =====================================================
1410 */
1411
1412 void
icode_make_sparc_load_int_from_ldouble(struct reg * dest,struct vreg * src,struct icode_list * il)1413 icode_make_sparc_load_int_from_ldouble(struct reg *dest,
1414 struct vreg *src,
1415 struct icode_list *il) {
1416
1417 struct icode_instr *ii;
1418
1419 ii = generic_icode_make_instr(NULL, NULL,
1420 INSTR_SPARC_LOAD_INT_FROM_LDOUBLE);
1421 ii->src_vreg = src;
1422 ii->dat = dest;
1423 append_icode_list(il, ii);
1424 }
1425
1426 /*
1427 * =====================================================
1428 * AMD64-specific instructions
1429 * =====================================================
1430 */
1431 void
icode_make_amd64_cvtsi2sd(struct reg * dest,struct vreg * src,struct icode_list * il)1432 icode_make_amd64_cvtsi2sd(
1433 struct reg *dest,
1434 struct vreg *src,
1435 struct icode_list *il) {
1436
1437 struct icode_instr *ii;
1438
1439 ii = generic_icode_make_instr(NULL, src, INSTR_AMD64_CVTSI2SD);
1440 ii->dest_pregs = make_icode_pregs(NULL, dest);
1441 append_icode_list(il, ii);
1442 }
1443
1444 void
icode_make_amd64_cvtsi2sdq(struct reg * dest,struct vreg * src,struct icode_list * il)1445 icode_make_amd64_cvtsi2sdq(
1446 struct reg *dest,
1447 struct vreg *src,
1448 struct icode_list *il) {
1449
1450 struct icode_instr *ii;
1451
1452 ii = generic_icode_make_instr(NULL, src, INSTR_AMD64_CVTSI2SDQ);
1453 ii->dest_pregs = make_icode_pregs(NULL, dest);
1454 append_icode_list(il, ii);
1455 }
1456
1457 void
icode_make_amd64_cvtsi2ssq(struct reg * dest,struct vreg * src,struct icode_list * il)1458 icode_make_amd64_cvtsi2ssq(
1459 struct reg *dest,
1460 struct vreg *src,
1461 struct icode_list *il) {
1462
1463 struct icode_instr *ii;
1464
1465 ii = generic_icode_make_instr(NULL, src, INSTR_AMD64_CVTSI2SSQ);
1466 ii->dest_pregs = make_icode_pregs(NULL, dest);
1467 append_icode_list(il, ii);
1468 }
1469
1470 void
icode_make_amd64_cvtsi2ss(struct reg * dest,struct vreg * src,struct icode_list * il)1471 icode_make_amd64_cvtsi2ss(
1472 struct reg *dest,
1473 struct vreg *src,
1474 struct icode_list *il) {
1475
1476 struct icode_instr *ii;
1477
1478 ii = generic_icode_make_instr(NULL, src, INSTR_AMD64_CVTSI2SS);
1479 ii->dest_pregs = make_icode_pregs(NULL, dest);
1480 append_icode_list(il, ii);
1481 }
1482
1483 void
icode_make_amd64_cvttss2si(struct reg * dest,struct reg * src,struct icode_list * il)1484 icode_make_amd64_cvttss2si(
1485 struct reg *dest,
1486 struct reg *src,
1487 struct icode_list *il) {
1488
1489 struct icode_instr *ii;
1490
1491 ii = generic_icode_make_instr(NULL, NULL, INSTR_AMD64_CVTTSS2SI);
1492 ii->dest_pregs = make_icode_pregs(NULL, dest);
1493 ii->src_pregs = make_icode_pregs(NULL, src);
1494 append_icode_list(il, ii);
1495 }
1496
1497 void
icode_make_amd64_cvttsd2si(struct reg * dest,struct reg * src,struct icode_list * il)1498 icode_make_amd64_cvttsd2si(
1499 struct reg *dest,
1500 struct reg *src,
1501 struct icode_list *il) {
1502
1503 struct icode_instr *ii;
1504
1505 ii = generic_icode_make_instr(NULL, NULL, INSTR_AMD64_CVTTSD2SI);
1506 ii->dest_pregs = make_icode_pregs(NULL, dest);
1507 ii->src_pregs = make_icode_pregs(NULL, src);
1508 append_icode_list(il, ii);
1509 }
1510
1511 void
icode_make_amd64_cvttss2siq(struct reg * dest,struct reg * src,struct icode_list * il)1512 icode_make_amd64_cvttss2siq(
1513 struct reg *dest,
1514 struct reg *src,
1515 struct icode_list *il) {
1516
1517 struct icode_instr *ii;
1518
1519 ii = generic_icode_make_instr(NULL, NULL, INSTR_AMD64_CVTTSS2SIQ);
1520 ii->dest_pregs = make_icode_pregs(NULL, dest);
1521 ii->src_pregs = make_icode_pregs(NULL, src);
1522 append_icode_list(il, ii);
1523 }
1524
1525 void
icode_make_amd64_cvtss2sd(struct reg * r,struct icode_list * il)1526 icode_make_amd64_cvtss2sd(struct reg *r, struct icode_list *il) {
1527 struct icode_instr *ii;
1528
1529 ii = generic_icode_make_instr(NULL, NULL, INSTR_AMD64_CVTSS2SD);
1530 ii->dat = r;
1531 append_icode_list(il, ii);
1532 }
1533
1534 void
icode_make_amd64_cvttsd2siq(struct reg * dest,struct reg * src,struct icode_list * il)1535 icode_make_amd64_cvttsd2siq(
1536 struct reg *dest,
1537 struct reg *src,
1538 struct icode_list *il) {
1539
1540 struct icode_instr *ii;
1541
1542 ii = generic_icode_make_instr(NULL, NULL, INSTR_AMD64_CVTTSD2SIQ);
1543 ii->dest_pregs = make_icode_pregs(NULL, dest);
1544 ii->src_pregs = make_icode_pregs(NULL, src);
1545 append_icode_list(il, ii);
1546 }
1547
1548
1549 void
icode_make_amd64_cvtsd2ss(struct reg * r,struct icode_list * il)1550 icode_make_amd64_cvtsd2ss(struct reg *r, struct icode_list *il) {
1551 struct icode_instr *ii;
1552
1553 ii = generic_icode_make_instr(NULL, NULL, INSTR_AMD64_CVTSD2SS);
1554 ii->dat = r;
1555 append_icode_list(il, ii);
1556 }
1557
1558 void
icode_make_amd64_load_negmask(struct reg * dest,struct reg * support,int for_double,struct icode_list * il)1559 icode_make_amd64_load_negmask(struct reg *dest, struct reg *support, int for_double,
1560 struct icode_list *il) {
1561
1562 struct icode_instr *ii;
1563 static struct vreg dummyvr;
1564 struct amd64_negmask_data *dat = n_xmalloc(sizeof *dat);
1565
1566 ii = generic_icode_make_instr(NULL, NULL, INSTR_AMD64_LOAD_NEGMASK);
1567 /* ii->dat = r;*/
1568 dat->target_fpr = dest;
1569 dat->support_gpr = support;
1570 ii->dat = dat;
1571
1572 if (for_double) {
1573 /* XXX ugly kludge to distinguish between float and double */
1574 ii->src_vreg = &dummyvr;
1575 amd64_need_negmask |= 2;
1576 } else {
1577 amd64_need_negmask |= 1;
1578 }
1579
1580 append_icode_list(il, ii);
1581 }
1582
1583 void
icode_make_amd64_xorps(struct vreg * dest,struct reg * src,struct icode_list * il)1584 icode_make_amd64_xorps(struct vreg *dest, struct reg *src, struct icode_list *il) {
1585 struct icode_instr *ii;
1586
1587 ii = generic_icode_make_instr(dest, NULL, INSTR_AMD64_XORPS);
1588 ii->dat = src;
1589 append_icode_list(il, ii);
1590 }
1591
1592 void
icode_make_amd64_xorpd(struct vreg * dest,struct reg * src,struct icode_list * il)1593 icode_make_amd64_xorpd(struct vreg *dest, struct reg *src, struct icode_list *il) {
1594 struct icode_instr *ii;
1595
1596 ii = generic_icode_make_instr(dest, NULL, INSTR_AMD64_XORPD);
1597 ii->dat = src;
1598 append_icode_list(il, ii);
1599 }
1600
1601
1602 void
icode_make_amd64_ulong_to_float(struct reg * src_gpr,struct reg * temp,struct reg * dest_sse_reg,int code,struct icode_list * il)1603 icode_make_amd64_ulong_to_float(struct reg *src_gpr, struct reg *temp,
1604 struct reg *dest_sse_reg, int code, struct icode_list *il) {
1605
1606 struct icode_instr *ii;
1607 struct amd64_ulong_to_float *data = n_xmalloc(sizeof *data);
1608
1609 if (code == TY_LDOUBLE /* AMD64 */
1610 || backend->arch == ARCH_X86) {
1611 amd64_need_ulong_float_mask = 1;
1612 }
1613
1614 ii = generic_icode_make_instr(NULL, NULL, INSTR_AMD64_ULONG_TO_FLOAT);
1615 data->src_gpr = src_gpr;
1616 data->temp_gpr = temp;
1617 data->dest_sse_reg = dest_sse_reg;
1618 data->code = code;
1619 ii->dat = data;
1620 append_icode_list(il, ii);
1621 }
1622
1623 struct icode_instr *
icode_make_seqpoint(struct var_access * stores)1624 icode_make_seqpoint(struct var_access *stores) {
1625 struct icode_instr *ret = alloc_icode_instr();
1626 ret->type = INSTR_SEQPOINT;
1627 ret->dat = stores;
1628 return ret;
1629 }
1630
1631 extern int lastmapseq;
1632 extern struct vreg *poi;
1633
1634 void
icode_make_debug(struct icode_list * il,const char * fmt,...)1635 icode_make_debug(struct icode_list *il, const char *fmt, ...) {
1636 struct icode_instr *ret = alloc_icode_instr();
1637 char buf[2048];
1638 va_list va;
1639
1640 #define EXTRAMSG 0
1641 #if EXTRAMSG
1642 char extramsg[128];
1643
1644 *extramsg = 0;
1645
1646 if (poi)
1647 sprintf(extramsg, " eax %p / poi %p -> %p %p ", x86_gprs[0].vreg,poi,poi->pregs[0],poi->pregs[1]);
1648 #endif
1649
1650 va_start(va, fmt);
1651 vsprintf(buf, fmt, va);
1652 va_end(va);
1653
1654 #if EXTRAMSG
1655 strcat(buf, extramsg);
1656 #endif
1657
1658 ret->type = INSTR_DEBUG;
1659 ret->dat = n_xstrdup(buf);
1660
1661 append_icode_list(il, ret);
1662 }
1663
1664 void
icode_make_dbginfo_line(struct statement * stmt,struct icode_list * il)1665 icode_make_dbginfo_line(struct statement *stmt, struct icode_list *il) {
1666 struct icode_instr *ii = NULL;
1667 struct decl *dec;
1668 struct expr *ex;
1669
1670 if (!gflag) return;
1671
1672 switch (stmt->type) {
1673 case ST_CODE:
1674 ii = alloc_icode_instr();
1675 ii->type = INSTR_DBGINFO_LINE;
1676 ex = stmt->data;
1677 ii->dat = ex->tok;
1678 break;
1679 case ST_DECL:
1680 /* A declaration with initializer has ``code'' */
1681 dec = stmt->data;
1682 if (dec->init != NULL) {
1683 ii = alloc_icode_instr();
1684 ii->type = INSTR_DBGINFO_LINE;
1685 ex = dec->init->data;
1686 ii->dat = ex->tok;
1687 }
1688 break;
1689 default:
1690 abort();
1691 }
1692 if (ii != NULL) { /* XXX */
1693 append_icode_list(il, ii);
1694 }
1695 }
1696
1697
1698
1699 int unimpl_instr;
1700
1701 void
icode_make_unimpl(struct icode_list * il)1702 icode_make_unimpl(struct icode_list *il) {
1703 struct icode_instr *ii = alloc_icode_instr();
1704
1705 unimpl_instr = 1;
1706 ii->type = INSTR_UNIMPL;
1707 unimpl();
1708 append_icode_list(il, ii);
1709 }
1710
1711 void
icode_make_copyinit(struct decl * d,struct icode_list * il)1712 icode_make_copyinit(struct decl *d, struct icode_list *il) {
1713 struct icode_instr *ii = alloc_icode_instr();
1714
1715 ii->type = INSTR_COPYINIT;
1716 ii->dat = d;
1717 append_icode_list(il, ii);
1718 }
1719
1720
1721 void
icode_make_putstructregs(struct reg * firstreg,struct reg * ptrreg,struct vreg * vr,struct icode_list * il)1722 icode_make_putstructregs(struct reg *firstreg,
1723 struct reg *ptrreg,
1724 struct vreg *vr,
1725 struct icode_list *il) {
1726
1727 struct icode_instr *ii = alloc_icode_instr();
1728 struct putstructregs *ps = n_xmalloc(sizeof *ps);
1729
1730 ps->ptrreg = ptrreg;
1731 ps->destreg = firstreg;
1732 ps->src_vreg = vr;
1733
1734 ii->type = INSTR_PUTSTRUCTREGS;
1735 ii->dat = ps;
1736 append_icode_list(il, ii);
1737 }
1738
1739 /*
1740 * Copy struct src to struct dest. Both may be automatic, static,
1741 * indirect, etc. If dest is a null pointer, then it is assumed that
1742 * the current function returns a structure type, and src will be
1743 * copied to the hidden pointer for struct returns (hidden_pointer
1744 * member of ``struct function''). This only works with the MIPS
1745 * backend right now.
1746 *
1747 * If any argument comes from a pointer, that pointer will be loaded
1748 * into a register as necessary. Note that most backends currently
1749 * call memcpy() to copy structs, so it is essential to save all GPRs
1750 * as necessary (backend->invalidate_gprs().) Perhaps it would make
1751 * sense to add a backend->prepare_copystruct() for register saving.
1752 *
1753 * XXX seems dest_preg and src_preg are never used and conceptually
1754 * totally nonsense because a struct is never gpr-resident
1755 */
1756 void
icode_make_copystruct(struct vreg * dest,struct vreg * src,struct icode_list * il)1757 icode_make_copystruct(
1758 struct vreg *dest,
1759 struct vreg *src,
1760 struct icode_list *il) {
1761
1762 struct icode_instr *ii = alloc_icode_instr();
1763 struct copystruct *cs;
1764 struct vreg *stop;
1765 static struct copystruct nullcs;
1766
1767
1768 /*
1769 * 05/22/11: Zero-sized arrays are possible in GNU C;
1770 * struct foo { char x[0]; }
1771 * A gcc test suite case uses this and causes a crash
1772 * when passing such a struct to a function
1773 */
1774 if (src->size == 0) {
1775 /* Empty struct - nothing to do */
1776 return;
1777 }
1778
1779 cs = n_xmalloc(sizeof *cs);
1780 *cs = nullcs;
1781
1782 /* If source is indirect, do not trash pointer register */
1783 vreg_set_unallocatable(src);
1784
1785 cs->dest_vreg = dest;
1786 if (dest != NULL) {
1787 vreg_faultin_ptr(dest, il);
1788 cs->dest_preg = dest->pregs[0];
1789 if (dest->from_ptr) {
1790 cs->dest_from_ptr = dest->from_ptr->pregs[0];
1791 } else if (dest->parent
1792 && (stop = get_parent_struct(dest))->from_ptr) {
1793 cs->dest_from_ptr = NULL;
1794 cs->dest_from_ptr_struct = stop->from_ptr->pregs[0];
1795 } else {
1796 cs->dest_from_ptr = NULL;
1797 }
1798 vreg_set_unallocatable(dest);
1799 }
1800 cs->src_vreg = src;
1801 cs->src_preg = src->pregs[0];
1802
1803 vreg_faultin_ptr(src, il);
1804 vreg_set_allocatable(src);
1805 if (dest != NULL) {
1806 vreg_set_allocatable(dest);
1807 }
1808 if (src->from_ptr) {
1809 cs->src_from_ptr = src->from_ptr->pregs[0];
1810 } else if (src->parent
1811 && (stop = get_parent_struct(src))->from_ptr) {
1812 cs->src_from_ptr = NULL;
1813 cs->src_from_ptr_struct = stop->from_ptr->pregs[0];
1814 } else {
1815 cs->src_from_ptr = NULL;
1816 }
1817
1818 if (backend->icode_make_structreloc) {
1819 backend->icode_make_structreloc(cs, il);
1820 }
1821
1822 ii->type = INSTR_COPYSTRUCT;
1823 ii->dat = cs;
1824 append_icode_list(il, ii);
1825 }
1826
1827 /*
1828 * Intrinsically copy nbytes of src to dest. Currently dest and src must
1829 * be pointers or arrays. This is currently only used by __builtin_memcpy,
1830 * but should eventually replace INSTR_COPYSTRUCT and INSTR_COPYINIT.
1831 * If may_call_lib is set, the library memcpy() may be called, which
1832 * makes sense for huge data items (the primary point of __builtin_memcpy
1833 * is probably to avoid library dependencies.)
1834 */
1835 void
icode_make_intrinsic_memcpy_or_memset(int type,struct vreg * dest,struct vreg * src,struct vreg * nbytes,int may_call_lib,struct icode_list * il)1836 icode_make_intrinsic_memcpy_or_memset(int type,
1837 struct vreg *dest,
1838 struct vreg *src,
1839 struct vreg *nbytes,
1840 int may_call_lib,
1841 struct icode_list *il) {
1842
1843 struct icode_instr *ii = alloc_icode_instr();
1844 struct int_memcpy_data *imdata = n_xmalloc(sizeof *imdata);
1845 struct reg *dest_reg;
1846 struct reg *src_reg;
1847 struct reg *temp_reg;
1848
1849 ii->type = INSTR_INTRINSIC_MEMCPY;
1850
1851 imdata->type = type;
1852 if (src->type->tlist == NULL
1853 || src->type->tlist == NULL) {
1854 /*
1855 * In the future we should allow copying non-
1856 * pointer objects too (take the address here)
1857 * for convenient struct and initializer copying
1858 */
1859 if (type == BUILTIN_MEMCPY) {
1860 unimpl();
1861 }
1862 }
1863
1864
1865 vreg_faultin_ptr(dest, il);
1866 if (dest->from_ptr) {
1867 dest_reg = dest->from_ptr->pregs[0];
1868 } else {
1869 /* Array or function */
1870 dest_reg = dest->pregs[0];
1871 }
1872 reg_set_unallocatable(dest_reg);
1873
1874 if (type == BUILTIN_MEMCPY) {
1875 vreg_faultin_ptr(src, il);
1876 if (src->from_ptr) {
1877 src_reg = src->from_ptr->pregs[0];
1878 } else {
1879 /* Array or function */
1880 src_reg = src->pregs[0];
1881 }
1882 } else {
1883 vreg_faultin(NULL, NULL, src, il, 0);
1884 src_reg = src->pregs[0];
1885 }
1886 reg_set_unallocatable(src_reg);
1887
1888 /*
1889 * Now allocate temporary register for holding one byte. This
1890 * will be used for byte-wise simplistic copying by all
1891 * backends until more sophisticated implementations are
1892 * written. Then it will be time to have some sort of backend
1893 * flag which tells us whether such a temp reg is needed or
1894 * not, and what else may have to be done here
1895 *
1896 * 02/09/09: Allocation moved up before nbytes allocation.
1897 * This was needed on OSX with PIC code because otherwise we
1898 * may run out of GPRs. This is because ebx is reserved as PIC
1899 * register, eax to ecx may be allocated for the memcpy()
1900 * arguments, and then we have no registers left for the 1
1901 * byte temp reg because esi and edi are unusable for that
1902 * purpose! (Since they do not have 8bit sub registers)
1903 *
1904 * 02/09/09: OK this STILL failed in case there is only one
1905 * allocatable GPR, and that GPR was allocated the last time
1906 * alloc_gpr() got called.
1907 * So we have to relax the alloc_gpr() constraint which
1908 * prevents it from allocating the same GPR as during the
1909 * last invocation
1910 */
1911 backend->relax_alloc_gpr_order = 1;
1912 temp_reg = ALLOC_GPR(curfunc, 1, il, NULL);
1913 backend->relax_alloc_gpr_order = 0;
1914 if (temp_reg == NULL) {
1915 (void) fprintf(stderr, "BUG: Cannot allocate GPR\n");
1916 abort();
1917 }
1918
1919 reg_set_unallocatable(temp_reg);
1920
1921 vreg_faultin(NULL, NULL, nbytes, il, 0);
1922 reg_set_unallocatable(nbytes->pregs[0]);
1923
1924 #if 0
1925 /* 02/09/09: Allocation moved up */
1926 /*
1927 * Now allocate temporary register for holding one byte. This
1928 * will be used for byte-wise simplistic copying by all
1929 * backends until more sophisticated implementations are
1930 * written. Then it will be time to have some sort of backend
1931 * flag which tells us whether such a temp reg is needed or
1932 * not, and what else may have to be done here
1933 */
1934 temp_reg = ALLOC_GPR(curfunc, 1, il, NULL);
1935 #endif
1936
1937 reg_set_allocatable(dest_reg);
1938 reg_set_allocatable(src_reg);
1939 reg_set_allocatable(nbytes->pregs[0]);
1940 reg_set_allocatable(temp_reg);
1941
1942 imdata->dest_addr = dest_reg;
1943 imdata->src_addr = src_reg;
1944 imdata->nbytes = nbytes->pregs[0];
1945 imdata->temp_reg = temp_reg;
1946 if (may_call_lib /* && makes_sense_to_call_lib */) {
1947 imdata->dest_addr->used = 0;
1948 imdata->src_addr->used = 0;
1949 imdata->nbytes->used = 0;
1950 imdata->temp_reg->used = 0;
1951 backend->invalidate_gprs(il, 1, INV_FOR_FCALL);
1952 }
1953 ii->dat = imdata;
1954 append_icode_list(il, ii);
1955 }
1956
1957 void
icode_make_dealloca(struct stack_block * sb,struct icode_list * il)1958 icode_make_dealloca(struct stack_block *sb, struct icode_list *il) {
1959 struct icode_instr *ii = alloc_icode_instr();
1960 struct reg *r;
1961 struct type *st;
1962
1963 st = backend->get_size_t();
1964
1965 r = backend->get_abi_reg(0, st);
1966 if (r == NULL) {
1967 r = ALLOC_GPR(curfunc, backend->get_sizeof_type(st, 0), il, 0);
1968 }
1969
1970 ii->type = INSTR_DEALLOCA;
1971 ii->src_pregs = make_icode_pregs(NULL, r);
1972 ii->dat = sb;
1973 append_icode_list(il, ii);
1974 }
1975
1976 void
icode_make_alloca(struct reg * r,struct vreg * size_vr,struct stack_block * sb,struct icode_list * il)1977 icode_make_alloca(struct reg *r, struct vreg *size_vr,
1978 struct stack_block *sb,
1979 struct icode_list *il) {
1980
1981 struct allocadata *a = n_xmalloc(sizeof *a);
1982 struct icode_instr *ii = alloc_icode_instr();
1983
1984 /*
1985 * First we unconditionally free the hidden pointer slot
1986 * for this allocation. Such that
1987 *
1988 * for (i = 0; i < 10; ++i) {
1989 * void *p = __builtin_alloca(20);
1990 *
1991 * ... always performs a free() before overwriting the
1992 * saved pointer with a newly allocated one. This is OK
1993 * even at the first call because the save area is
1994 * initialized to all-null-pointers, and free(NULL) is ok
1995 *
1996 * XXX 08/09/07: This is completely wrong. Removed the
1997 * free, thus repeated allocas leak memory now. But better
1998 * than not having it work at all
1999 */
2000 backend->invalidate_gprs(il, 1, INV_FOR_FCALL);
2001 #if 0
2002 icode_make_dealloca(sb, il);
2003 #endif
2004
2005 reg_set_unallocatable(r);
2006 vreg_faultin(NULL, NULL, size_vr, il, 0);
2007 a->result_reg = r;
2008 a->size_reg = size_vr->pregs[0];
2009 a->addr = sb;
2010
2011 ii->dat = a;
2012 ii->type = INSTR_ALLOCA;
2013
2014 /*
2015 * Because the current implementation is carried out
2016 * using malloc() and free(), we have to save all
2017 * registers except for the size argument register!
2018 */
2019 a->result_reg->used = 0;
2020 a->size_reg->used = 0;
2021 reg_set_allocatable(r);
2022 backend->invalidate_gprs(il, 1, INV_FOR_FCALL);
2023 append_icode_list(il, ii);
2024 #if 0
2025 store_reg_to_stack_block(a->result_reg, a->addr);
2026 #endif
2027 }
2028
2029 void
icode_make_dealloc_vla(struct stack_block * sb,struct icode_list * il)2030 icode_make_dealloc_vla(struct stack_block *sb, struct icode_list *il) {
2031 struct icode_instr *ii = alloc_icode_instr();
2032
2033 #if 0
2034 r = backend->get_abi_reg(0, st);
2035 if (r == NULL) {
2036 r = ALLOC_GPR(curfunc, backend->get_sizeof_type(st, 0), il, 0);
2037 }
2038 #endif
2039
2040 ii->type = INSTR_DEALLOC_VLA;
2041 #if 0
2042 ii->src_pregs = make_icode_pregs(NULL, r);
2043 #endif
2044 ii->dat = sb;
2045 append_icode_list(il, ii);
2046 }
2047
2048 void
icode_make_alloc_vla(struct stack_block * sb,struct icode_list * il)2049 icode_make_alloc_vla(
2050 struct stack_block *sb,
2051 struct icode_list *il) {
2052
2053 struct allocadata *a = n_xmalloc(sizeof *a);
2054 struct icode_instr *ii = alloc_icode_instr();
2055
2056 /*
2057 * First we unconditionally free the hidden pointer slot
2058 * for this allocation. Such that
2059 *
2060 * for (i = 0; i < 10; ++i) {
2061 * void *p = __builtin_alloca(20);
2062 *
2063 * ... always performs a free() before overwriting the
2064 * saved pointer with a newly allocated one. This is OK
2065 * even at the first call because the save area is
2066 * initialized to all-null-pointers, and free(NULL) is ok
2067 */
2068 backend->invalidate_gprs(il, 1, INV_FOR_FCALL);
2069 icode_make_dealloc_vla(sb, il);
2070
2071 ii->dat = sb;
2072 ii->type = INSTR_ALLOC_VLA;
2073
2074 /*
2075 * Because the current implementation is carried out
2076 * using malloc() and free(), we have to save all
2077 * registers
2078 */
2079 backend->invalidate_gprs(il, 1, INV_FOR_FCALL);
2080 append_icode_list(il, ii);
2081 }
2082
2083 void
icode_make_builtin_frame_address(struct reg * r,struct reg * r2,size_t * n,struct icode_list * il)2084 icode_make_builtin_frame_address(struct reg *r, struct reg *r2,
2085 size_t *n, struct icode_list *il) {
2086
2087 struct icode_instr *ii = alloc_icode_instr();
2088 struct builtinframeaddressdata *dat = n_xmalloc(sizeof *dat);
2089
2090 ii->type = INSTR_BUILTIN_FRAME_ADDRESS;
2091 dat->result_reg = r;
2092 dat->temp_reg = r2;
2093 dat->count = n;
2094
2095 ii->dat = dat;
2096 append_icode_list(il, ii);
2097 }
2098
2099
2100 void
icode_make_put_vla_whole_size(struct reg * size,struct stack_block * sb,struct icode_list * il)2101 icode_make_put_vla_whole_size(struct reg *size, struct stack_block *sb,
2102 struct icode_list *il) {
2103
2104 struct icode_instr *ii = alloc_icode_instr();
2105 struct vlasizedata *dat = n_xmalloc(sizeof *dat);
2106
2107 ii->type = INSTR_PUT_VLA_SIZE;
2108 dat->size = size;
2109 dat->offset = backend->get_ptr_size();
2110 dat->blockaddr = sb;
2111 ii->dat = dat;
2112 append_icode_list(il, ii);
2113 }
2114
2115
2116 void
icode_make_put_vla_size(struct reg * size,struct stack_block * sb,int idx,struct icode_list * il)2117 icode_make_put_vla_size(struct reg *size, struct stack_block *sb,
2118 int idx, struct icode_list *il) {
2119
2120 struct icode_instr *ii = alloc_icode_instr();
2121 struct vlasizedata *dat = n_xmalloc(sizeof *dat);
2122 int offset;
2123
2124 offset = backend->get_ptr_size()
2125 + (1 + idx) * backend->get_sizeof_type(
2126 make_basic_type(TY_ULONG), NULL);
2127
2128 ii->type = INSTR_PUT_VLA_SIZE;
2129 dat->size = size;
2130 dat->blockaddr = sb;
2131 dat->offset = offset;
2132 ii->dat = dat;
2133 append_icode_list(il, ii);
2134 }
2135
2136 struct vreg *
icode_make_retr_vla_size(struct reg * size,struct stack_block * sb,int idx,struct icode_list * il)2137 icode_make_retr_vla_size(struct reg *size, struct stack_block *sb,
2138 int idx, struct icode_list *il) {
2139
2140 struct icode_instr *ii = alloc_icode_instr();
2141 struct vlasizedata *dat = n_xmalloc(sizeof *dat);
2142 struct vreg *ret;
2143 int offset;
2144
2145 offset = backend->get_ptr_size()
2146 + (1 + idx) * backend->get_sizeof_type(
2147 make_basic_type(TY_ULONG), NULL);
2148
2149
2150 ii->type = INSTR_RETR_VLA_SIZE;
2151 dat->size = size;
2152 dat->blockaddr = sb;
2153 dat->offset = offset;
2154 ii->dat = dat;
2155 append_icode_list(il, ii);
2156 ret = vreg_alloc(NULL, NULL, NULL, NULL);
2157 vreg_set_new_type(ret, make_basic_type(TY_ULONG));
2158 vreg_map_preg(ret, size);
2159 return ret;
2160 }
2161
2162 void
icode_make_allocstack(struct vreg * vr,size_t size,struct icode_list * il)2163 icode_make_allocstack(struct vreg *vr, size_t size, struct icode_list *il) {
2164 struct icode_instr *ii = alloc_icode_instr();
2165 struct allocstack *as = n_xmalloc(sizeof *as);
2166
2167 as->nbytes = size;
2168 as->patchme = vr;
2169
2170 ii->type = INSTR_ALLOCSTACK;
2171 ii->dat = as;
2172 append_icode_list(il, ii);
2173 }
2174
2175 /*
2176 * XXX should this really deal with multi-gpr objects?!
2177 */
2178 struct icode_instr *
icode_make_cmp(struct vreg * dest,struct vreg * src)2179 icode_make_cmp(struct vreg *dest, struct vreg *src) {
2180 struct icode_instr *ret = alloc_icode_instr();
2181
2182 ret->type = INSTR_CMP;
2183 ret->dest_vreg = dest;
2184 ret->dest_pregs = make_icode_pregs(dest, NULL);
2185 if (src != NULL) {
2186 ret->src_pregs = make_icode_pregs(src, NULL);
2187 ret->src_vreg = src;
2188 }
2189 return ret;
2190 }
2191
2192 void
icode_make_extend_sign(struct vreg * vr,struct type * to,struct type * from,struct icode_list * il)2193 icode_make_extend_sign(struct vreg *vr, struct type *to, struct type *from,
2194 struct icode_list *il) {
2195
2196 struct icode_instr *ret = alloc_icode_instr();
2197 struct extendsign *data = n_xmalloc(sizeof *data);
2198
2199 data->dest_preg = vr->pregs[0];
2200 data->dest_type = to;
2201 data->src_type = from;
2202 ret->dat = data;
2203 ret->type = INSTR_EXTEND_SIGN;
2204 append_icode_list(il, ret);
2205 }
2206
2207 /* XXX misleading order of to/from :/ */
2208 void
icode_make_conv_fp(struct reg * destr,struct reg * srcr,struct type * to,struct type * from,struct icode_list * il)2209 icode_make_conv_fp(struct reg *destr, struct reg *srcr,
2210 struct type *to, struct type *from,
2211 struct icode_list *il) {
2212
2213 struct icode_instr *ret = alloc_icode_instr();
2214 struct extendsign *data = n_xmalloc(sizeof *data);
2215
2216 data->dest_preg = destr;
2217 data->src_preg = srcr;
2218 data->dest_type = to;
2219 data->src_type = from;
2220 ret->dat = data;
2221 ret->type = INSTR_CONV_FP;
2222 append_icode_list(il, ret);
2223 }
2224
2225 void
icode_make_conv_to_ldouble(struct vreg * dest,struct vreg * src,struct icode_list * il)2226 icode_make_conv_to_ldouble(struct vreg *dest, struct vreg *src,
2227 struct icode_list *il) {
2228
2229 struct icode_instr *ii;
2230
2231 ii = generic_icode_make_instr(dest, src, INSTR_CONV_TO_LDOUBLE);
2232 append_icode_list(il, ii);
2233 }
2234
2235 void
icode_make_conv_from_ldouble(struct vreg * dest,struct vreg * src,struct icode_list * il)2236 icode_make_conv_from_ldouble(struct vreg *dest, struct vreg *src,
2237 struct icode_list *il) {
2238
2239 struct icode_instr *ii;
2240
2241 ii = generic_icode_make_instr(dest, src, INSTR_CONV_FROM_LDOUBLE);
2242 append_icode_list(il, ii);
2243 }
2244
2245
2246 struct icode_instr *
icode_make_jump(struct icode_instr * label)2247 icode_make_jump(struct icode_instr *label) {
2248 struct icode_instr *ret = alloc_icode_instr();
2249 ret->type = INSTR_JUMP;
2250 ret->dat = label;
2251 return ret;
2252 }
2253
2254 void
put_label_scope(struct label * l)2255 put_label_scope(struct label *l) {
2256 struct statement *stmt;
2257
2258 stmt = alloc_statement();
2259 stmt->type = ST_LABEL;
2260 stmt->data = l;
2261 append_statement(
2262 &curscope->code, &curscope->code_tail, stmt);
2263 append_label_list(&curfunc->labels_head, &curfunc->labels_tail, l);
2264 }
2265
2266
2267 void
put_expr_scope(struct expr * e)2268 put_expr_scope(struct expr *e) {
2269 struct statement *stmt;
2270
2271 stmt = alloc_statement();
2272 stmt->type = ST_CODE;
2273 stmt->data = e;
2274 append_statement(&curscope->code, &curscope->code_tail, stmt);
2275 }
2276
2277 void
put_ctrl_scope(struct control * c)2278 put_ctrl_scope(struct control *c) {
2279 struct statement *stmt;
2280
2281 stmt = alloc_statement();
2282 stmt->type = ST_CTRL;
2283 stmt->data = c;
2284 append_statement(&curscope->code, &curscope->code_tail, stmt);
2285 }
2286
2287 /*
2288 * XXX acts as fxch for x86 fp...is this ok?
2289 */
2290 void
icode_make_copyreg(struct reg * dest,struct reg * src,struct type * desttype,struct type * srctype,struct icode_list * il)2291 icode_make_copyreg(
2292 struct reg *dest,
2293 struct reg *src,
2294 struct type *desttype,
2295 struct type *srctype,
2296 struct icode_list *il) {
2297
2298 struct icode_instr *ii = alloc_icode_instr();
2299 struct copyreg *cr = n_xmalloc(sizeof *cr);
2300
2301 if (dest->type != src->type) abort();
2302 cr->src_preg = src;
2303 cr->dest_preg = dest;
2304 cr->src_type = srctype;
2305 cr->dest_type = desttype;
2306
2307 ii->type = INSTR_MOV;
2308 ii->dat = cr;
2309
2310 append_icode_list(il, ii);
2311 }
2312
2313 void
add_const_to_vreg(struct vreg * valist_vr,int size,struct icode_list * il)2314 add_const_to_vreg(struct vreg *valist_vr, int size, struct icode_list *il) {
2315 struct token *c;
2316 struct vreg *tmpvr;
2317 struct icode_instr *ii;
2318
2319 c = const_from_value(&size, NULL);
2320 tmpvr = vreg_alloc(NULL, c, NULL, NULL);
2321 vreg_faultin(NULL, NULL, tmpvr, il, 0);
2322 vreg_faultin_protected(tmpvr, NULL, NULL, /*valist->vreg*/valist_vr, il, 0);
2323 ii = icode_make_add( /*valist->vreg*/valist_vr, tmpvr);
2324 append_icode_list(il, ii);
2325 icode_make_store(curfunc, /*valist->vreg*/valist_vr,
2326 /*valist->vreg*/valist_vr, il);
2327 }
2328
2329