Print this page
11972 resync smatch
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/tools/smatch/src/compile-i386.c
+++ new/usr/src/tools/smatch/src/compile-i386.c
1 1 /*
2 2 * sparse/compile-i386.c
3 3 *
4 4 * Copyright (C) 2003 Transmeta Corp.
5 5 * 2003 Linus Torvalds
6 6 * Copyright 2003 Jeff Garzik
7 7 *
8 8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 9 * of this software and associated documentation files (the "Software"), to deal
10 10 * in the Software without restriction, including without limitation the rights
11 11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 12 * copies of the Software, and to permit persons to whom the Software is
13 13 * furnished to do so, subject to the following conditions:
14 14 *
15 15 * The above copyright notice and this permission notice shall be included in
16 16 * all copies or substantial portions of the Software.
17 17 *
18 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 24 * THE SOFTWARE.
25 25 *
26 26 * x86 backend
27 27 *
28 28 * TODO list:
29 29 * in general, any non-32bit SYM_BASETYPE is unlikely to work.
30 30 * complex initializers
31 31 * bitfields
32 32 * global struct/union variables
33 33 * addressing structures, and members of structures (as opposed to
34 34 * scalars) on the stack. Requires smarter stack frame allocation.
35 35 * labels / goto
36 36 * any function argument that isn't 32 bits (or promoted to such)
37 37 * inline asm
38 38 * floating point
39 39 *
40 40 */
41 41 #include <stdarg.h>
42 42 #include <stdlib.h>
43 43 #include <stdio.h>
44 44 #include <string.h>
45 45 #include <ctype.h>
46 46 #include <unistd.h>
47 47 #include <fcntl.h>
48 48 #include <assert.h>
49 49
50 50 #include "lib.h"
51 51 #include "allocate.h"
52 52 #include "token.h"
53 53 #include "parse.h"
54 54 #include "symbol.h"
55 55 #include "scope.h"
56 56 #include "expression.h"
57 57 #include "target.h"
58 58 #include "compile.h"
59 59 #include "bitmap.h"
60 60 #include "version.h"
61 61
62 62 struct textbuf {
63 63 unsigned int len; /* does NOT include terminating null */
64 64 char *text;
65 65 struct textbuf *next;
66 66 struct textbuf *prev;
67 67 };
68 68
69 69 struct loop_stack {
70 70 int continue_lbl;
71 71 int loop_bottom_lbl;
72 72 struct loop_stack *next;
73 73 };
74 74
75 75 struct atom;
76 76 struct storage;
77 77 DECLARE_PTR_LIST(str_list, struct atom);
78 78 DECLARE_PTR_LIST(atom_list, struct atom);
79 79 DECLARE_PTR_LIST(storage_list, struct storage);
80 80
81 81 struct function {
82 82 int stack_size;
83 83 int pseudo_nr;
84 84 struct storage_list *pseudo_list;
85 85 struct atom_list *atom_list;
86 86 struct str_list *str_list;
87 87 struct loop_stack *loop_stack;
88 88 struct symbol **argv;
89 89 unsigned int argc;
90 90 int ret_target;
91 91 };
92 92
93 93 enum storage_type {
94 94 STOR_PSEUDO, /* variable stored on the stack */
95 95 STOR_ARG, /* function argument */
96 96 STOR_SYM, /* a symbol we can directly ref in the asm */
97 97 STOR_REG, /* scratch register */
98 98 STOR_VALUE, /* integer constant */
99 99 STOR_LABEL, /* label / jump target */
100 100 STOR_LABELSYM, /* label generated from symbol's pointer value */
101 101 };
102 102
103 103 struct reg_info {
104 104 const char *name;
105 105 struct storage *contains;
106 106 const unsigned char aliases[12];
107 107 #define own_regno aliases[0]
108 108 };
109 109
110 110 struct storage {
111 111 enum storage_type type;
112 112 unsigned long flags;
113 113
114 114 /* STOR_REG */
115 115 struct reg_info *reg;
116 116 struct symbol *ctype;
117 117
118 118 union {
119 119 /* STOR_PSEUDO */
120 120 struct {
121 121 int pseudo;
122 122 int offset;
123 123 int size;
124 124 };
125 125 /* STOR_ARG */
126 126 struct {
127 127 int idx;
128 128 };
129 129 /* STOR_SYM */
130 130 struct {
131 131 struct symbol *sym;
132 132 };
133 133 /* STOR_VALUE */
134 134 struct {
135 135 long long value;
136 136 };
137 137 /* STOR_LABEL */
138 138 struct {
139 139 int label;
140 140 };
141 141 /* STOR_LABELSYM */
142 142 struct {
143 143 struct symbol *labelsym;
144 144 };
145 145 };
146 146 };
147 147
148 148 enum {
149 149 STOR_LABEL_VAL = (1 << 0),
150 150 STOR_WANTS_FREE = (1 << 1),
151 151 };
152 152
153 153 struct symbol_private {
154 154 struct storage *addr;
155 155 };
156 156
157 157 enum atom_type {
158 158 ATOM_TEXT,
159 159 ATOM_INSN,
160 160 ATOM_CSTR,
161 161 };
162 162
163 163 struct atom {
164 164 enum atom_type type;
165 165 union {
166 166 /* stuff for text */
167 167 struct {
168 168 char *text;
169 169 unsigned int text_len; /* w/o terminating null */
170 170 };
171 171
172 172 /* stuff for insns */
173 173 struct {
174 174 char insn[32];
175 175 char comment[40];
176 176 struct storage *op1;
177 177 struct storage *op2;
178 178 };
179 179
180 180 /* stuff for C strings */
181 181 struct {
182 182 struct string *string;
183 183 int label;
184 184 };
185 185 };
↓ open down ↓ |
185 lines elided |
↑ open up ↑ |
186 186 };
187 187
188 188
189 189 static struct function *current_func = NULL;
190 190 static struct textbuf *unit_post_text = NULL;
191 191 static const char *current_section;
192 192
193 193 static void emit_comment(const char * fmt, ...) FORMAT_ATTR(1);
194 194 static void emit_move(struct storage *src, struct storage *dest,
195 195 struct symbol *ctype, const char *comment);
196 -static int type_is_signed(struct symbol *sym);
197 196 static struct storage *x86_address_gen(struct expression *expr);
198 197 static struct storage *x86_symbol_expr(struct symbol *sym);
199 198 static void x86_symbol(struct symbol *sym);
200 199 static struct storage *x86_statement(struct statement *stmt);
201 200 static struct storage *x86_expression(struct expression *expr);
202 201
203 202 enum registers {
204 203 NOREG,
205 204 AL, DL, CL, BL, AH, DH, CH, BH, // 8-bit
206 205 AX, DX, CX, BX, SI, DI, BP, SP, // 16-bit
207 206 EAX, EDX, ECX, EBX, ESI, EDI, EBP, ESP, // 32-bit
208 207 EAX_EDX, ECX_EBX, ESI_EDI, // 64-bit
209 208 };
210 209
211 210 /* This works on regno's, reg_info's and hardreg_storage's */
212 211 #define byte_reg(reg) ((reg) - 16)
213 212 #define highbyte_reg(reg) ((reg)-12)
214 213 #define word_reg(reg) ((reg)-8)
215 214
216 215 #define REGINFO(nr, str, conflicts...) [nr] = { .name = str, .aliases = { nr , conflicts } }
217 216
218 217 static struct reg_info reg_info_table[] = {
219 218 REGINFO( AL, "%al", AX, EAX, EAX_EDX),
220 219 REGINFO( DL, "%dl", DX, EDX, EAX_EDX),
221 220 REGINFO( CL, "%cl", CX, ECX, ECX_EBX),
222 221 REGINFO( BL, "%bl", BX, EBX, ECX_EBX),
223 222 REGINFO( AH, "%ah", AX, EAX, EAX_EDX),
224 223 REGINFO( DH, "%dh", DX, EDX, EAX_EDX),
225 224 REGINFO( CH, "%ch", CX, ECX, ECX_EBX),
226 225 REGINFO( BH, "%bh", BX, EBX, ECX_EBX),
227 226 REGINFO( AX, "%ax", AL, AH, EAX, EAX_EDX),
228 227 REGINFO( DX, "%dx", DL, DH, EDX, EAX_EDX),
229 228 REGINFO( CX, "%cx", CL, CH, ECX, ECX_EBX),
230 229 REGINFO( BX, "%bx", BL, BH, EBX, ECX_EBX),
231 230 REGINFO( SI, "%si", ESI, ESI_EDI),
232 231 REGINFO( DI, "%di", EDI, ESI_EDI),
233 232 REGINFO( BP, "%bp", EBP),
234 233 REGINFO( SP, "%sp", ESP),
235 234 REGINFO(EAX, "%eax", AL, AH, AX, EAX_EDX),
236 235 REGINFO(EDX, "%edx", DL, DH, DX, EAX_EDX),
237 236 REGINFO(ECX, "%ecx", CL, CH, CX, ECX_EBX),
238 237 REGINFO(EBX, "%ebx", BL, BH, BX, ECX_EBX),
239 238 REGINFO(ESI, "%esi", SI, ESI_EDI),
240 239 REGINFO(EDI, "%edi", DI, ESI_EDI),
241 240 REGINFO(EBP, "%ebp", BP),
242 241 REGINFO(ESP, "%esp", SP),
243 242 REGINFO(EAX_EDX, "%eax:%edx", AL, AH, AX, EAX, DL, DH, DX, EDX),
244 243 REGINFO(ECX_EBX, "%ecx:%ebx", CL, CH, CX, ECX, BL, BH, BX, EBX),
245 244 REGINFO(ESI_EDI, "%esi:%edi", SI, ESI, DI, EDI),
246 245 };
247 246
248 247 #define REGSTORAGE(nr) [nr] = { .type = STOR_REG, .reg = reg_info_table + (nr) }
249 248
250 249 static struct storage hardreg_storage_table[] = {
251 250 REGSTORAGE(AL), REGSTORAGE(DL), REGSTORAGE(CL), REGSTORAGE(BL),
252 251 REGSTORAGE(AH), REGSTORAGE(DH), REGSTORAGE(CH), REGSTORAGE(BH),
253 252 REGSTORAGE(AX), REGSTORAGE(DX), REGSTORAGE(CX), REGSTORAGE(BX),
254 253 REGSTORAGE(SI), REGSTORAGE(DI), REGSTORAGE(BP), REGSTORAGE(SP),
255 254 REGSTORAGE(EAX), REGSTORAGE(EDX), REGSTORAGE(ECX), REGSTORAGE(EBX),
256 255 REGSTORAGE(ESI), REGSTORAGE(EDI), REGSTORAGE(EBP), REGSTORAGE(ESP),
257 256 REGSTORAGE(EAX_EDX), REGSTORAGE(ECX_EBX), REGSTORAGE(ESI_EDI),
258 257 };
259 258
260 259 #define REG_EAX (&hardreg_storage_table[EAX])
261 260 #define REG_ECX (&hardreg_storage_table[ECX])
262 261 #define REG_EDX (&hardreg_storage_table[EDX])
263 262 #define REG_ESP (&hardreg_storage_table[ESP])
264 263 #define REG_DL (&hardreg_storage_table[DL])
265 264 #define REG_DX (&hardreg_storage_table[DX])
266 265 #define REG_AL (&hardreg_storage_table[AL])
267 266 #define REG_AX (&hardreg_storage_table[AX])
268 267
269 268 static DECLARE_BITMAP(regs_in_use, 256);
270 269
271 270 static inline struct storage * reginfo_reg(struct reg_info *info)
272 271 {
273 272 return hardreg_storage_table + info->own_regno;
274 273 }
275 274
276 275 static struct storage * get_hardreg(struct storage *reg, int clear)
277 276 {
278 277 struct reg_info *info = reg->reg;
279 278 const unsigned char *aliases;
280 279 int regno;
281 280
282 281 aliases = info->aliases;
283 282 while ((regno = *aliases++) != NOREG) {
284 283 if (test_bit(regno, regs_in_use))
285 284 goto busy;
286 285 if (clear)
287 286 reg_info_table[regno].contains = NULL;
288 287 }
289 288 set_bit(info->own_regno, regs_in_use);
290 289 return reg;
291 290 busy:
292 291 fprintf(stderr, "register %s is busy\n", info->name);
293 292 if (regno + reg_info_table != info)
294 293 fprintf(stderr, " conflicts with %s\n", reg_info_table[regno].name);
295 294 exit(1);
296 295 }
297 296
298 297 static void put_reg(struct storage *reg)
299 298 {
300 299 struct reg_info *info = reg->reg;
301 300 int regno = info->own_regno;
302 301
303 302 if (test_and_clear_bit(regno, regs_in_use))
304 303 return;
305 304 fprintf(stderr, "freeing already free'd register %s\n", reg_info_table[regno].name);
306 305 }
307 306
308 307 struct regclass {
309 308 const char *name;
310 309 const unsigned char regs[30];
311 310 };
312 311
313 312 static struct regclass regclass_8 = { "8-bit", { AL, DL, CL, BL, AH, DH, CH, BH }};
314 313 static struct regclass regclass_16 = { "16-bit", { AX, DX, CX, BX, SI, DI, BP }};
315 314 static struct regclass regclass_32 = { "32-bit", { EAX, EDX, ECX, EBX, ESI, EDI, EBP }};
316 315 static struct regclass regclass_64 = { "64-bit", { EAX_EDX, ECX_EBX, ESI_EDI }};
317 316
318 317 static struct regclass regclass_32_8 = { "32-bit bytes", { EAX, EDX, ECX, EBX }};
319 318
320 319 static struct regclass *get_regclass_bits(int bits)
321 320 {
322 321 switch (bits) {
323 322 case 8: return ®class_8;
324 323 case 16: return ®class_16;
325 324 case 64: return ®class_64;
326 325 default: return ®class_32;
327 326 }
328 327 }
329 328
330 329 static struct regclass *get_regclass(struct expression *expr)
331 330 {
332 331 return get_regclass_bits(expr->ctype->bit_size);
333 332 }
334 333
335 334 static int register_busy(int regno)
336 335 {
337 336 if (!test_bit(regno, regs_in_use)) {
338 337 struct reg_info *info = reg_info_table + regno;
339 338 const unsigned char *regs = info->aliases+1;
340 339
341 340 while ((regno = *regs) != NOREG) {
342 341 regs++;
343 342 if (test_bit(regno, regs_in_use))
344 343 goto busy;
345 344 }
346 345 return 0;
347 346 }
348 347 busy:
349 348 return 1;
350 349 }
351 350
352 351 static struct storage *get_reg(struct regclass *class)
353 352 {
354 353 const unsigned char *regs = class->regs;
355 354 int regno;
356 355
357 356 while ((regno = *regs) != NOREG) {
358 357 regs++;
359 358 if (register_busy(regno))
360 359 continue;
361 360 return get_hardreg(hardreg_storage_table + regno, 1);
362 361 }
363 362 fprintf(stderr, "Ran out of %s registers\n", class->name);
364 363 exit(1);
365 364 }
366 365
367 366 static struct storage *get_reg_value(struct storage *value, struct regclass *class)
368 367 {
369 368 struct reg_info *info;
370 369 struct storage *reg;
371 370
372 371 /* Do we already have it somewhere */
373 372 info = value->reg;
374 373 if (info && info->contains == value) {
375 374 emit_comment("already have register %s", info->name);
376 375 return get_hardreg(hardreg_storage_table + info->own_regno, 0);
377 376 }
378 377
379 378 reg = get_reg(class);
380 379 emit_move(value, reg, value->ctype, "reload register");
381 380 info = reg->reg;
382 381 info->contains = value;
383 382 value->reg = info;
384 383 return reg;
385 384 }
386 385
387 386 static struct storage *temp_from_bits(unsigned int bit_size)
388 387 {
389 388 return get_reg(get_regclass_bits(bit_size));
390 389 }
391 390
392 391 static inline unsigned int pseudo_offset(struct storage *s)
393 392 {
394 393 if (s->type != STOR_PSEUDO)
395 394 return 123456; /* intentionally bogus value */
396 395
397 396 return s->offset;
398 397 }
399 398
400 399 static inline unsigned int arg_offset(struct storage *s)
401 400 {
402 401 if (s->type != STOR_ARG)
403 402 return 123456; /* intentionally bogus value */
404 403
405 404 /* FIXME: this is wrong wrong wrong */
406 405 return current_func->stack_size + ((1 + s->idx) * 4);
407 406 }
408 407
409 408 static const char *pretty_offset(int ofs)
410 409 {
411 410 static char esp_buf[64];
412 411
413 412 if (ofs)
414 413 sprintf(esp_buf, "%d(%%esp)", ofs);
415 414 else
416 415 strcpy(esp_buf, "(%esp)");
417 416
418 417 return esp_buf;
419 418 }
420 419
421 420 static void stor_sym_init(struct symbol *sym)
422 421 {
423 422 struct storage *stor;
424 423 struct symbol_private *priv;
425 424
426 425 priv = calloc(1, sizeof(*priv) + sizeof(*stor));
427 426 if (!priv)
428 427 die("OOM in stor_sym_init");
429 428
430 429 stor = (struct storage *) (priv + 1);
431 430
432 431 priv->addr = stor;
433 432 stor->type = STOR_SYM;
434 433 stor->sym = sym;
435 434 }
436 435
437 436 static const char *stor_op_name(struct storage *s)
438 437 {
439 438 static char name[32];
440 439
441 440 switch (s->type) {
442 441 case STOR_PSEUDO:
443 442 strcpy(name, pretty_offset((int) pseudo_offset(s)));
444 443 break;
↓ open down ↓ |
238 lines elided |
↑ open up ↑ |
445 444 case STOR_ARG:
446 445 strcpy(name, pretty_offset((int) arg_offset(s)));
447 446 break;
448 447 case STOR_SYM:
449 448 strcpy(name, show_ident(s->sym->ident));
450 449 break;
451 450 case STOR_REG:
452 451 strcpy(name, s->reg->name);
453 452 break;
454 453 case STOR_VALUE:
455 - sprintf(name, "$%Ld", s->value);
454 + sprintf(name, "$%lld", s->value);
456 455 break;
457 456 case STOR_LABEL:
458 457 sprintf(name, "%s.L%d", s->flags & STOR_LABEL_VAL ? "$" : "",
459 458 s->label);
460 459 break;
461 460 case STOR_LABELSYM:
462 461 sprintf(name, "%s.LS%p", s->flags & STOR_LABEL_VAL ? "$" : "",
463 462 s->labelsym);
464 463 break;
465 464 }
466 465
467 466 return name;
468 467 }
469 468
470 469 static struct atom *new_atom(enum atom_type type)
471 470 {
472 471 struct atom *atom;
473 472
474 473 atom = calloc(1, sizeof(*atom)); /* TODO: chunked alloc */
475 474 if (!atom)
476 475 die("nuclear OOM");
477 476
478 477 atom->type = type;
479 478
480 479 return atom;
481 480 }
482 481
483 482 static inline void push_cstring(struct function *f, struct string *str,
484 483 int label)
485 484 {
486 485 struct atom *atom;
487 486
488 487 atom = new_atom(ATOM_CSTR);
489 488 atom->string = str;
490 489 atom->label = label;
491 490
492 491 add_ptr_list(&f->str_list, atom); /* note: _not_ atom_list */
493 492 }
494 493
495 494 static inline void push_atom(struct function *f, struct atom *atom)
496 495 {
497 496 add_ptr_list(&f->atom_list, atom);
498 497 }
499 498
500 499 static void push_text_atom(struct function *f, const char *text)
501 500 {
502 501 struct atom *atom = new_atom(ATOM_TEXT);
503 502
504 503 atom->text = strdup(text);
505 504 atom->text_len = strlen(text);
506 505
507 506 push_atom(f, atom);
508 507 }
509 508
510 509 static struct storage *new_storage(enum storage_type type)
511 510 {
512 511 struct storage *stor;
513 512
514 513 stor = calloc(1, sizeof(*stor));
515 514 if (!stor)
516 515 die("OOM in new_storage");
517 516
518 517 stor->type = type;
519 518
520 519 return stor;
521 520 }
522 521
523 522 static struct storage *stack_alloc(int n_bytes)
524 523 {
525 524 struct function *f = current_func;
526 525 struct storage *stor;
527 526
528 527 assert(f != NULL);
529 528
530 529 stor = new_storage(STOR_PSEUDO);
531 530 stor->type = STOR_PSEUDO;
532 531 stor->pseudo = f->pseudo_nr;
533 532 stor->offset = f->stack_size; /* FIXME: stack req. natural align */
534 533 stor->size = n_bytes;
535 534 f->stack_size += n_bytes;
536 535 f->pseudo_nr++;
537 536
538 537 add_ptr_list(&f->pseudo_list, stor);
539 538
540 539 return stor;
541 540 }
542 541
543 542 static struct storage *new_labelsym(struct symbol *sym)
544 543 {
545 544 struct storage *stor;
546 545
547 546 stor = new_storage(STOR_LABELSYM);
548 547
549 548 if (stor) {
550 549 stor->flags |= STOR_WANTS_FREE;
551 550 stor->labelsym = sym;
552 551 }
553 552
554 553 return stor;
555 554 }
556 555
557 556 static struct storage *new_val(long long value)
558 557 {
559 558 struct storage *stor;
560 559
561 560 stor = new_storage(STOR_VALUE);
562 561
563 562 if (stor) {
564 563 stor->flags |= STOR_WANTS_FREE;
565 564 stor->value = value;
566 565 }
567 566
568 567 return stor;
569 568 }
570 569
571 570 static int new_label(void)
572 571 {
573 572 static int label = 0;
574 573 return ++label;
575 574 }
576 575
577 576 static void textbuf_push(struct textbuf **buf_p, const char *text)
578 577 {
579 578 struct textbuf *tmp, *list = *buf_p;
580 579 unsigned int text_len = strlen(text);
581 580 unsigned int alloc_len = text_len + 1 + sizeof(*list);
582 581
583 582 tmp = calloc(1, alloc_len);
584 583 if (!tmp)
585 584 die("OOM on textbuf alloc");
586 585
587 586 tmp->text = ((void *) tmp) + sizeof(*tmp);
588 587 memcpy(tmp->text, text, text_len + 1);
589 588 tmp->len = text_len;
590 589
591 590 /* add to end of list */
592 591 if (!list) {
593 592 list = tmp;
594 593 tmp->prev = tmp;
595 594 } else {
596 595 tmp->prev = list->prev;
597 596 tmp->prev->next = tmp;
598 597 list->prev = tmp;
599 598 }
600 599 tmp->next = list;
601 600
602 601 *buf_p = list;
603 602 }
604 603
605 604 static void textbuf_emit(struct textbuf **buf_p)
606 605 {
607 606 struct textbuf *tmp, *list = *buf_p;
608 607
609 608 while (list) {
610 609 tmp = list;
611 610 if (tmp->next == tmp)
612 611 list = NULL;
613 612 else {
614 613 tmp->prev->next = tmp->next;
615 614 tmp->next->prev = tmp->prev;
616 615 list = tmp->next;
617 616 }
618 617
619 618 fputs(tmp->text, stdout);
620 619
621 620 free(tmp);
622 621 }
623 622
624 623 *buf_p = list;
625 624 }
626 625
627 626 static void insn(const char *insn, struct storage *op1, struct storage *op2,
628 627 const char *comment_in)
629 628 {
630 629 struct function *f = current_func;
631 630 struct atom *atom = new_atom(ATOM_INSN);
632 631
633 632 assert(insn != NULL);
634 633
635 634 strcpy(atom->insn, insn);
636 635 if (comment_in && (*comment_in))
637 636 strncpy(atom->comment, comment_in,
638 637 sizeof(atom->comment) - 1);
639 638
640 639 atom->op1 = op1;
641 640 atom->op2 = op2;
642 641
643 642 push_atom(f, atom);
644 643 }
645 644
646 645 static void emit_comment(const char *fmt, ...)
647 646 {
648 647 struct function *f = current_func;
649 648 static char tmpbuf[100] = "\t# ";
650 649 va_list args;
651 650 int i;
652 651
653 652 va_start(args, fmt);
654 653 i = vsnprintf(tmpbuf+3, sizeof(tmpbuf)-4, fmt, args);
655 654 va_end(args);
656 655 tmpbuf[i+3] = '\n';
657 656 tmpbuf[i+4] = '\0';
658 657 push_text_atom(f, tmpbuf);
659 658 }
660 659
661 660 static void emit_label (int label, const char *comment)
662 661 {
663 662 struct function *f = current_func;
664 663 char s[64];
665 664
666 665 if (!comment)
667 666 sprintf(s, ".L%d:\n", label);
668 667 else
669 668 sprintf(s, ".L%d:\t\t\t\t\t# %s\n", label, comment);
670 669
671 670 push_text_atom(f, s);
672 671 }
673 672
674 673 static void emit_labelsym (struct symbol *sym, const char *comment)
675 674 {
676 675 struct function *f = current_func;
677 676 char s[64];
678 677
679 678 if (!comment)
680 679 sprintf(s, ".LS%p:\n", sym);
681 680 else
682 681 sprintf(s, ".LS%p:\t\t\t\t# %s\n", sym, comment);
683 682
684 683 push_text_atom(f, s);
685 684 }
686 685
687 686 void emit_unit_begin(const char *basename)
688 687 {
689 688 printf("\t.file\t\"%s\"\n", basename);
690 689 }
691 690
692 691 void emit_unit_end(void)
693 692 {
694 693 textbuf_emit(&unit_post_text);
695 694 printf("\t.ident\t\"sparse silly x86 backend (version %s)\"\n", SPARSE_VERSION);
696 695 }
697 696
698 697 /* conditionally switch sections */
699 698 static void emit_section(const char *s)
700 699 {
701 700 if (s == current_section)
702 701 return;
703 702 if (current_section && (!strcmp(s, current_section)))
704 703 return;
705 704
706 705 printf("\t%s\n", s);
707 706 current_section = s;
708 707 }
709 708
710 709 static void emit_insn_atom(struct function *f, struct atom *atom)
711 710 {
712 711 char s[128];
713 712 char comment[64];
714 713 struct storage *op1 = atom->op1;
715 714 struct storage *op2 = atom->op2;
716 715
717 716 if (atom->comment[0])
718 717 sprintf(comment, "\t\t# %s", atom->comment);
719 718 else
720 719 comment[0] = 0;
721 720
722 721 if (atom->op2) {
723 722 char tmp[16];
724 723 strcpy(tmp, stor_op_name(op1));
725 724 sprintf(s, "\t%s\t%s, %s%s\n",
726 725 atom->insn, tmp, stor_op_name(op2), comment);
727 726 } else if (atom->op1)
728 727 sprintf(s, "\t%s\t%s%s%s\n",
729 728 atom->insn, stor_op_name(op1),
730 729 comment[0] ? "\t" : "", comment);
731 730 else
732 731 sprintf(s, "\t%s\t%s%s\n",
733 732 atom->insn,
734 733 comment[0] ? "\t\t" : "", comment);
735 734
736 735 if (write(STDOUT_FILENO, s, strlen(s)) < 0)
737 736 die("can't write to stdout");
738 737 }
739 738
740 739 static void emit_atom_list(struct function *f)
741 740 {
742 741 struct atom *atom;
743 742
744 743 FOR_EACH_PTR(f->atom_list, atom) {
745 744 switch (atom->type) {
746 745 case ATOM_TEXT: {
747 746 if (write(STDOUT_FILENO, atom->text, atom->text_len) < 0)
748 747 die("can't write to stdout");
749 748 break;
750 749 }
751 750 case ATOM_INSN:
752 751 emit_insn_atom(f, atom);
753 752 break;
754 753 case ATOM_CSTR:
755 754 assert(0);
756 755 break;
757 756 }
758 757 } END_FOR_EACH_PTR(atom);
759 758 }
760 759
761 760 static void emit_string_list(struct function *f)
762 761 {
763 762 struct atom *atom;
764 763
765 764 emit_section(".section\t.rodata");
766 765
767 766 FOR_EACH_PTR(f->str_list, atom) {
768 767 /* FIXME: escape " in string */
769 768 printf(".L%d:\n", atom->label);
770 769 printf("\t.string\t%s\n", show_string(atom->string));
771 770
772 771 free(atom);
773 772 } END_FOR_EACH_PTR(atom);
774 773 }
775 774
776 775 static void func_cleanup(struct function *f)
777 776 {
778 777 struct storage *stor;
779 778 struct atom *atom;
780 779
781 780 FOR_EACH_PTR(f->atom_list, atom) {
782 781 if ((atom->type == ATOM_TEXT) && (atom->text))
783 782 free(atom->text);
784 783 if (atom->op1 && (atom->op1->flags & STOR_WANTS_FREE))
785 784 free(atom->op1);
786 785 if (atom->op2 && (atom->op2->flags & STOR_WANTS_FREE))
787 786 free(atom->op2);
788 787 free(atom);
789 788 } END_FOR_EACH_PTR(atom);
790 789
791 790 FOR_EACH_PTR(f->pseudo_list, stor) {
792 791 free(stor);
793 792 } END_FOR_EACH_PTR(stor);
794 793
795 794 free_ptr_list(&f->pseudo_list);
796 795 free(f);
797 796 }
798 797
799 798 /* function prologue */
800 799 static void emit_func_pre(struct symbol *sym)
801 800 {
802 801 struct function *f;
803 802 struct symbol *arg;
804 803 unsigned int i, argc = 0, alloc_len;
805 804 unsigned char *mem;
806 805 struct symbol_private *privbase;
807 806 struct storage *storage_base;
808 807 struct symbol *base_type = sym->ctype.base_type;
809 808
810 809 FOR_EACH_PTR(base_type->arguments, arg) {
811 810 argc++;
812 811 } END_FOR_EACH_PTR(arg);
813 812
814 813 alloc_len =
815 814 sizeof(*f) +
816 815 (argc * sizeof(struct symbol *)) +
817 816 (argc * sizeof(struct symbol_private)) +
818 817 (argc * sizeof(struct storage));
819 818 mem = calloc(1, alloc_len);
820 819 if (!mem)
821 820 die("OOM on func info");
822 821
823 822 f = (struct function *) mem;
824 823 mem += sizeof(*f);
825 824 f->argv = (struct symbol **) mem;
826 825 mem += (argc * sizeof(struct symbol *));
827 826 privbase = (struct symbol_private *) mem;
828 827 mem += (argc * sizeof(struct symbol_private));
829 828 storage_base = (struct storage *) mem;
830 829
831 830 f->argc = argc;
832 831 f->ret_target = new_label();
833 832
834 833 i = 0;
835 834 FOR_EACH_PTR(base_type->arguments, arg) {
836 835 f->argv[i] = arg;
837 836 arg->aux = &privbase[i];
838 837 storage_base[i].type = STOR_ARG;
839 838 storage_base[i].idx = i;
840 839 privbase[i].addr = &storage_base[i];
841 840 i++;
842 841 } END_FOR_EACH_PTR(arg);
843 842
844 843 assert(current_func == NULL);
845 844 current_func = f;
846 845 }
847 846
848 847 /* function epilogue */
849 848 static void emit_func_post(struct symbol *sym)
850 849 {
851 850 const char *name = show_ident(sym->ident);
852 851 struct function *f = current_func;
853 852 int stack_size = f->stack_size;
854 853
855 854 if (f->str_list)
856 855 emit_string_list(f);
857 856
858 857 /* function prologue */
859 858 emit_section(".text");
860 859 if ((sym->ctype.modifiers & MOD_STATIC) == 0)
861 860 printf(".globl %s\n", name);
862 861 printf("\t.type\t%s, @function\n", name);
863 862 printf("%s:\n", name);
864 863
865 864 if (stack_size) {
866 865 char pseudo_const[16];
867 866
868 867 sprintf(pseudo_const, "$%d", stack_size);
869 868 printf("\tsubl\t%s, %%esp\n", pseudo_const);
870 869 }
871 870
872 871 /* function epilogue */
873 872
874 873 /* jump target for 'return' statements */
875 874 emit_label(f->ret_target, NULL);
876 875
877 876 if (stack_size) {
878 877 struct storage *val;
879 878
880 879 val = new_storage(STOR_VALUE);
881 880 val->value = (long long) (stack_size);
882 881 val->flags = STOR_WANTS_FREE;
883 882
884 883 insn("addl", val, REG_ESP, NULL);
885 884 }
886 885
887 886 insn("ret", NULL, NULL, NULL);
888 887
889 888 /* output everything to stdout */
890 889 fflush(stdout); /* paranoia; needed? */
891 890 emit_atom_list(f);
892 891
893 892 /* function footer */
894 893 name = show_ident(sym->ident);
895 894 printf("\t.size\t%s, .-%s\n", name, name);
896 895
897 896 func_cleanup(f);
898 897 current_func = NULL;
899 898 }
900 899
901 900 /* emit object (a.k.a. variable, a.k.a. data) prologue */
902 901 static void emit_object_pre(const char *name, unsigned long modifiers,
903 902 unsigned long alignment, unsigned int byte_size)
904 903 {
905 904 if ((modifiers & MOD_STATIC) == 0)
906 905 printf(".globl %s\n", name);
907 906 emit_section(".data");
908 907 if (alignment)
909 908 printf("\t.align %lu\n", alignment);
910 909 printf("\t.type\t%s, @object\n", name);
911 910 printf("\t.size\t%s, %d\n", name, byte_size);
912 911 printf("%s:\n", name);
913 912 }
914 913
915 914 /* emit value (only) for an initializer scalar */
916 915 static void emit_scalar(struct expression *expr, unsigned int bit_size)
917 916 {
918 917 const char *type;
919 918 long long ll;
920 919
921 920 assert(expr->type == EXPR_VALUE);
922 921
923 922 if (expr->value == 0ULL) {
924 923 printf("\t.zero\t%d\n", bit_size / 8);
925 924 return;
926 925 }
927 926
928 927 ll = (long long) expr->value;
929 928
↓ open down ↓ |
464 lines elided |
↑ open up ↑ |
930 929 switch (bit_size) {
931 930 case 8: type = "byte"; ll = (char) ll; break;
932 931 case 16: type = "value"; ll = (short) ll; break;
933 932 case 32: type = "long"; ll = (int) ll; break;
934 933 case 64: type = "quad"; break;
935 934 default: type = NULL; break;
936 935 }
937 936
938 937 assert(type != NULL);
939 938
940 - printf("\t.%s\t%Ld\n", type, ll);
939 + printf("\t.%s\t%lld\n", type, ll);
941 940 }
942 941
943 942 static void emit_global_noinit(const char *name, unsigned long modifiers,
944 943 unsigned long alignment, unsigned int byte_size)
945 944 {
946 945 char s[64];
947 946
948 947 if (modifiers & MOD_STATIC) {
949 948 sprintf(s, "\t.local\t%s\n", name);
950 949 textbuf_push(&unit_post_text, s);
951 950 }
952 951 if (alignment)
953 952 sprintf(s, "\t.comm\t%s,%d,%lu\n", name, byte_size, alignment);
954 953 else
955 954 sprintf(s, "\t.comm\t%s,%d\n", name, byte_size);
956 955 textbuf_push(&unit_post_text, s);
957 956 }
958 957
959 958 static int ea_current, ea_last;
960 959
961 960 static void emit_initializer(struct symbol *sym,
962 961 struct expression *expr)
963 962 {
964 963 int distance = ea_current - ea_last - 1;
965 964
966 965 if (distance > 0)
967 966 printf("\t.zero\t%d\n", (sym->bit_size / 8) * distance);
968 967
969 968 if (expr->type == EXPR_VALUE) {
970 969 struct symbol *base_type = sym->ctype.base_type;
971 970 assert(base_type != NULL);
972 971
973 972 emit_scalar(expr, sym->bit_size / get_expression_value(base_type->array_size));
974 973 return;
975 974 }
976 975 if (expr->type != EXPR_INITIALIZER)
977 976 return;
978 977
979 978 assert(0); /* FIXME */
980 979 }
981 980
982 981 static int sort_array_cmp(const struct expression *a,
983 982 const struct expression *b)
984 983 {
985 984 int a_ofs = 0, b_ofs = 0;
986 985
987 986 if (a->type == EXPR_POS)
988 987 a_ofs = (int) a->init_offset;
989 988 if (b->type == EXPR_POS)
990 989 b_ofs = (int) b->init_offset;
991 990
992 991 return a_ofs - b_ofs;
993 992 }
994 993
995 994 /* move to front-end? */
996 995 static void sort_array(struct expression *expr)
997 996 {
998 997 struct expression *entry, **list;
999 998 unsigned int elem, sorted, i;
1000 999
1001 1000 elem = expression_list_size(expr->expr_list);
1002 1001 if (!elem)
1003 1002 return;
1004 1003
1005 1004 list = malloc(sizeof(entry) * elem);
1006 1005 if (!list)
1007 1006 die("OOM in sort_array");
1008 1007
1009 1008 /* this code is no doubt evil and ignores EXPR_INDEX possibly
1010 1009 * to its detriment and other nasty things. improvements
1011 1010 * welcome.
1012 1011 */
1013 1012 i = 0;
1014 1013 sorted = 0;
1015 1014 FOR_EACH_PTR(expr->expr_list, entry) {
1016 1015 if ((entry->type == EXPR_POS) || (entry->type == EXPR_VALUE)) {
1017 1016 /* add entry to list[], in sorted order */
1018 1017 if (sorted == 0) {
1019 1018 list[0] = entry;
1020 1019 sorted = 1;
1021 1020 } else {
1022 1021 for (i = 0; i < sorted; i++)
1023 1022 if (sort_array_cmp(entry, list[i]) <= 0)
1024 1023 break;
1025 1024
1026 1025 /* If inserting into the middle of list[]
1027 1026 * instead of appending, we memmove.
1028 1027 * This is ugly, but thankfully
1029 1028 * uncommon. Input data with tons of
1030 1029 * entries very rarely have explicit
1031 1030 * offsets. convert to qsort eventually...
1032 1031 */
1033 1032 if (i != sorted)
1034 1033 memmove(&list[i + 1], &list[i],
1035 1034 (sorted - i) * sizeof(entry));
1036 1035 list[i] = entry;
1037 1036 sorted++;
1038 1037 }
1039 1038 }
1040 1039 } END_FOR_EACH_PTR(entry);
1041 1040
1042 1041 i = 0;
1043 1042 FOR_EACH_PTR(expr->expr_list, entry) {
1044 1043 if ((entry->type == EXPR_POS) || (entry->type == EXPR_VALUE))
1045 1044 *THIS_ADDRESS(entry) = list[i++];
1046 1045 } END_FOR_EACH_PTR(entry);
1047 1046
1048 1047 free(list);
1049 1048 }
1050 1049
1051 1050 static void emit_array(struct symbol *sym)
1052 1051 {
1053 1052 struct symbol *base_type = sym->ctype.base_type;
1054 1053 struct expression *expr = sym->initializer;
1055 1054 struct expression *entry;
1056 1055
1057 1056 assert(base_type != NULL);
1058 1057
1059 1058 stor_sym_init(sym);
1060 1059
1061 1060 ea_last = -1;
1062 1061
1063 1062 emit_object_pre(show_ident(sym->ident), sym->ctype.modifiers,
1064 1063 sym->ctype.alignment,
1065 1064 sym->bit_size / 8);
1066 1065
1067 1066 sort_array(expr);
1068 1067
1069 1068 FOR_EACH_PTR(expr->expr_list, entry) {
1070 1069 if (entry->type == EXPR_VALUE) {
1071 1070 ea_current = 0;
1072 1071 emit_initializer(sym, entry);
1073 1072 ea_last = ea_current;
1074 1073 } else if (entry->type == EXPR_POS) {
1075 1074 ea_current =
1076 1075 entry->init_offset / (base_type->bit_size / 8);
1077 1076 emit_initializer(sym, entry->init_expr);
1078 1077 ea_last = ea_current;
1079 1078 }
1080 1079 } END_FOR_EACH_PTR(entry);
1081 1080 }
1082 1081
1083 1082 void emit_one_symbol(struct symbol *sym)
1084 1083 {
1085 1084 x86_symbol(sym);
1086 1085 }
1087 1086
1088 1087 static void emit_copy(struct storage *dest, struct storage *src,
1089 1088 struct symbol *ctype)
1090 1089 {
1091 1090 struct storage *reg = NULL;
1092 1091 unsigned int bit_size;
1093 1092
1094 1093 /* FIXME: Bitfield copy! */
1095 1094
1096 1095 bit_size = src->size * 8;
1097 1096 if (!bit_size)
1098 1097 bit_size = 32;
1099 1098 if ((src->type == STOR_ARG) && (bit_size < 32))
1100 1099 bit_size = 32;
1101 1100
1102 1101 reg = temp_from_bits(bit_size);
1103 1102 emit_move(src, reg, ctype, "begin copy ..");
1104 1103
1105 1104 bit_size = dest->size * 8;
1106 1105 if (!bit_size)
1107 1106 bit_size = 32;
1108 1107 if ((dest->type == STOR_ARG) && (bit_size < 32))
1109 1108 bit_size = 32;
1110 1109
1111 1110 emit_move(reg, dest, ctype, ".... end copy");
1112 1111 put_reg(reg);
1113 1112 }
1114 1113
1115 1114 static void emit_store(struct expression *dest_expr, struct storage *dest,
1116 1115 struct storage *src, int bits)
1117 1116 {
1118 1117 /* FIXME: Bitfield store! */
1119 1118 printf("\tst.%d\t\tv%d,[v%d]\n", bits, src->pseudo, dest->pseudo);
1120 1119 }
1121 1120
1122 1121 static void emit_scalar_noinit(struct symbol *sym)
1123 1122 {
1124 1123 emit_global_noinit(show_ident(sym->ident),
1125 1124 sym->ctype.modifiers, sym->ctype.alignment,
1126 1125 sym->bit_size / 8);
1127 1126 stor_sym_init(sym);
1128 1127 }
1129 1128
1130 1129 static void emit_array_noinit(struct symbol *sym)
1131 1130 {
1132 1131 emit_global_noinit(show_ident(sym->ident),
1133 1132 sym->ctype.modifiers, sym->ctype.alignment,
1134 1133 get_expression_value(sym->array_size) * (sym->bit_size / 8));
1135 1134 stor_sym_init(sym);
1136 1135 }
1137 1136
1138 1137 static const char *opbits(const char *insn, unsigned int bits)
1139 1138 {
1140 1139 static char opbits_str[32];
1141 1140 char c;
1142 1141
1143 1142 switch (bits) {
1144 1143 case 8: c = 'b'; break;
1145 1144 case 16: c = 'w'; break;
1146 1145 case 32: c = 'l'; break;
1147 1146 case 64: c = 'q'; break;
1148 1147 default: abort(); break;
1149 1148 }
1150 1149
1151 1150 sprintf(opbits_str, "%s%c", insn, c);
1152 1151
1153 1152 return opbits_str;
1154 1153 }
1155 1154
↓ open down ↓ |
205 lines elided |
↑ open up ↑ |
1156 1155 static void emit_move(struct storage *src, struct storage *dest,
1157 1156 struct symbol *ctype, const char *comment)
1158 1157 {
1159 1158 unsigned int bits;
1160 1159 unsigned int is_signed;
1161 1160 unsigned int is_dest = (src->type == STOR_REG);
1162 1161 const char *opname;
1163 1162
1164 1163 if (ctype) {
1165 1164 bits = ctype->bit_size;
1166 - is_signed = type_is_signed(ctype);
1165 + is_signed = is_signed_type(ctype);
1167 1166 } else {
1168 1167 bits = 32;
1169 1168 is_signed = 0;
1170 1169 }
1171 1170
1172 1171 /*
1173 1172 * Are we moving from a register to a register?
1174 1173 * Make the new reg to be the "cache".
1175 1174 */
1176 1175 if ((dest->type == STOR_REG) && (src->type == STOR_REG)) {
1177 1176 struct storage *backing;
1178 1177
1179 1178 reg_reg_move:
1180 1179 if (dest == src)
1181 1180 return;
1182 1181
1183 1182 backing = src->reg->contains;
1184 1183 if (backing) {
1185 1184 /* Is it still valid? */
1186 1185 if (backing->reg != src->reg)
1187 1186 backing = NULL;
1188 1187 else
1189 1188 backing->reg = dest->reg;
1190 1189 }
1191 1190 dest->reg->contains = backing;
1192 1191 insn("mov", src, dest, NULL);
1193 1192 return;
1194 1193 }
1195 1194
1196 1195 /*
1197 1196 * Are we moving to a register from a non-reg?
1198 1197 *
1199 1198 * See if we have the non-reg source already cached
1200 1199 * in a register..
1201 1200 */
1202 1201 if (dest->type == STOR_REG) {
1203 1202 if (src->reg) {
1204 1203 struct reg_info *info = src->reg;
1205 1204 if (info->contains == src) {
1206 1205 src = reginfo_reg(info);
1207 1206 goto reg_reg_move;
1208 1207 }
1209 1208 }
1210 1209 dest->reg->contains = src;
1211 1210 src->reg = dest->reg;
1212 1211 }
1213 1212
1214 1213 if (src->type == STOR_REG) {
1215 1214 /* We could just mark the register dirty here and do lazy store.. */
1216 1215 src->reg->contains = dest;
1217 1216 dest->reg = src->reg;
1218 1217 }
1219 1218
1220 1219 if ((bits == 8) || (bits == 16)) {
1221 1220 if (is_dest)
1222 1221 opname = "mov";
1223 1222 else
1224 1223 opname = is_signed ? "movsx" : "movzx";
1225 1224 } else
1226 1225 opname = "mov";
1227 1226
1228 1227 insn(opbits(opname, bits), src, dest, comment);
1229 1228 }
1230 1229
1231 1230 static struct storage *emit_compare(struct expression *expr)
1232 1231 {
1233 1232 struct storage *left = x86_expression(expr->left);
1234 1233 struct storage *right = x86_expression(expr->right);
1235 1234 struct storage *reg1, *reg2;
1236 1235 struct storage *new, *val;
1237 1236 const char *opname = NULL;
1238 1237 unsigned int right_bits = expr->right->ctype->bit_size;
1239 1238
1240 1239 switch(expr->op) {
1241 1240 case '<': opname = "setl"; break;
1242 1241 case '>': opname = "setg"; break;
1243 1242 case SPECIAL_LTE:
1244 1243 opname = "setle"; break;
1245 1244 case SPECIAL_GTE:
1246 1245 opname = "setge"; break;
1247 1246 case SPECIAL_EQUAL: opname = "sete"; break;
1248 1247 case SPECIAL_NOTEQUAL: opname = "setne"; break;
1249 1248 case SPECIAL_UNSIGNED_LT:
1250 1249 opname = "setb"; break;
1251 1250 case SPECIAL_UNSIGNED_GT:
1252 1251 opname = "seta"; break;
1253 1252 case SPECIAL_UNSIGNED_LTE:
1254 1253 opname = "setb"; break;
1255 1254 case SPECIAL_UNSIGNED_GTE:
1256 1255 opname = "setae"; break;
1257 1256 default:
1258 1257 assert(0);
1259 1258 break;
1260 1259 }
1261 1260
1262 1261 /* init EDX to 0 */
1263 1262 val = new_storage(STOR_VALUE);
1264 1263 val->flags = STOR_WANTS_FREE;
1265 1264
1266 1265 reg1 = get_reg(®class_32_8);
1267 1266 emit_move(val, reg1, NULL, NULL);
1268 1267
1269 1268 /* move op1 into EAX */
1270 1269 reg2 = get_reg_value(left, get_regclass(expr->left));
1271 1270
1272 1271 /* perform comparison, RHS (op1, right) and LHS (op2, EAX) */
1273 1272 insn(opbits("cmp", right_bits), right, reg2, NULL);
1274 1273 put_reg(reg2);
1275 1274
1276 1275 /* store result of operation, 0 or 1, in DL using SETcc */
1277 1276 insn(opname, byte_reg(reg1), NULL, NULL);
1278 1277
1279 1278 /* finally, store the result (DL) in a new pseudo / stack slot */
1280 1279 new = stack_alloc(4);
1281 1280 emit_move(reg1, new, NULL, "end EXPR_COMPARE");
1282 1281 put_reg(reg1);
1283 1282
1284 1283 return new;
1285 1284 }
1286 1285
1287 1286 static struct storage *emit_value(struct expression *expr)
1288 1287 {
1289 1288 #if 0 /* old and slow way */
1290 1289 struct storage *new = stack_alloc(4);
1291 1290 struct storage *val;
1292 1291
1293 1292 val = new_storage(STOR_VALUE);
1294 1293 val->value = (long long) expr->value;
1295 1294 val->flags = STOR_WANTS_FREE;
1296 1295 insn("movl", val, new, NULL);
1297 1296
1298 1297 return new;
1299 1298 #else
1300 1299 struct storage *val;
1301 1300
1302 1301 val = new_storage(STOR_VALUE);
1303 1302 val->value = (long long) expr->value;
1304 1303
1305 1304 return val; /* FIXME: memory leak */
1306 1305 #endif
1307 1306 }
1308 1307
1309 1308 static struct storage *emit_divide(struct expression *expr, struct storage *left, struct storage *right)
1310 1309 {
1311 1310 struct storage *eax_edx;
1312 1311 struct storage *reg, *new;
1313 1312 struct storage *val = new_storage(STOR_VALUE);
1314 1313
1315 1314 emit_comment("begin DIVIDE");
1316 1315 eax_edx = get_hardreg(hardreg_storage_table + EAX_EDX, 1);
1317 1316
1318 1317 /* init EDX to 0 */
1319 1318 val->flags = STOR_WANTS_FREE;
1320 1319 emit_move(val, REG_EDX, NULL, NULL);
1321 1320
1322 1321 new = stack_alloc(expr->ctype->bit_size / 8);
1323 1322
1324 1323 /* EAX is dividend */
1325 1324 emit_move(left, REG_EAX, NULL, NULL);
1326 1325
1327 1326 reg = get_reg_value(right, ®class_32);
1328 1327
1329 1328 /* perform binop */
1330 1329 insn("div", reg, REG_EAX, NULL);
1331 1330 put_reg(reg);
1332 1331
1333 1332 reg = REG_EAX;
1334 1333 if (expr->op == '%')
1335 1334 reg = REG_EDX;
1336 1335 emit_move(reg, new, NULL, NULL);
1337 1336
1338 1337 put_reg(eax_edx);
1339 1338 emit_comment("end DIVIDE");
1340 1339 return new;
1341 1340 }
1342 1341
1343 1342 static struct storage *emit_binop(struct expression *expr)
1344 1343 {
1345 1344 struct storage *left = x86_expression(expr->left);
1346 1345 struct storage *right = x86_expression(expr->right);
1347 1346 struct storage *new;
↓ open down ↓ |
171 lines elided |
↑ open up ↑ |
1348 1347 struct storage *dest, *src;
1349 1348 const char *opname = NULL;
1350 1349 const char *suffix = NULL;
1351 1350 char opstr[16];
1352 1351 int is_signed;
1353 1352
1354 1353 /* Divides have special register constraints */
1355 1354 if ((expr->op == '/') || (expr->op == '%'))
1356 1355 return emit_divide(expr, left, right);
1357 1356
1358 - is_signed = type_is_signed(expr->ctype);
1357 + is_signed = is_signed_type(expr->ctype);
1359 1358
1360 1359 switch (expr->op) {
1361 1360 case '+':
1362 1361 opname = "add";
1363 1362 break;
1364 1363 case '-':
1365 1364 opname = "sub";
1366 1365 break;
1367 1366 case '&':
1368 1367 opname = "and";
1369 1368 break;
1370 1369 case '|':
1371 1370 opname = "or";
1372 1371 break;
1373 1372 case '^':
1374 1373 opname = "xor";
1375 1374 break;
1376 1375 case SPECIAL_LEFTSHIFT:
1377 1376 opname = "shl";
1378 1377 break;
1379 1378 case SPECIAL_RIGHTSHIFT:
1380 1379 if (is_signed)
1381 1380 opname = "sar";
1382 1381 else
1383 1382 opname = "shr";
1384 1383 break;
1385 1384 case '*':
1386 1385 if (is_signed)
1387 1386 opname = "imul";
1388 1387 else
1389 1388 opname = "mul";
1390 1389 break;
1391 1390 case SPECIAL_LOGICAL_AND:
1392 1391 warning(expr->pos, "bogus bitwise and for logical op (should use '2*setne + and' or something)");
1393 1392 opname = "and";
1394 1393 break;
1395 1394 case SPECIAL_LOGICAL_OR:
1396 1395 warning(expr->pos, "bogus bitwise or for logical op (should use 'or + setne' or something)");
1397 1396 opname = "or";
1398 1397 break;
1399 1398 default:
1400 1399 error_die(expr->pos, "unhandled binop '%s'\n", show_special(expr->op));
1401 1400 break;
1402 1401 }
1403 1402
1404 1403 dest = get_reg_value(right, ®class_32);
1405 1404 src = get_reg_value(left, ®class_32);
1406 1405 switch (expr->ctype->bit_size) {
1407 1406 case 8:
1408 1407 suffix = "b";
1409 1408 break;
1410 1409 case 16:
1411 1410 suffix = "w";
1412 1411 break;
1413 1412 case 32:
1414 1413 suffix = "l";
1415 1414 break;
1416 1415 case 64:
1417 1416 suffix = "q"; /* FIXME */
1418 1417 break;
1419 1418 default:
1420 1419 assert(0);
1421 1420 break;
1422 1421 }
1423 1422
1424 1423 snprintf(opstr, sizeof(opstr), "%s%s", opname, suffix);
1425 1424
1426 1425 /* perform binop */
1427 1426 insn(opstr, src, dest, NULL);
1428 1427 put_reg(src);
1429 1428
1430 1429 /* store result in new pseudo / stack slot */
1431 1430 new = stack_alloc(expr->ctype->bit_size / 8);
1432 1431 emit_move(dest, new, NULL, "end EXPR_BINOP");
1433 1432
1434 1433 put_reg(dest);
1435 1434
1436 1435 return new;
1437 1436 }
1438 1437
1439 1438 static int emit_conditional_test(struct storage *val)
1440 1439 {
1441 1440 struct storage *reg;
1442 1441 struct storage *target_val;
1443 1442 int target_false;
1444 1443
1445 1444 /* load result into EAX */
1446 1445 emit_comment("begin if/conditional");
1447 1446 reg = get_reg_value(val, ®class_32);
1448 1447
1449 1448 /* compare result with zero */
1450 1449 insn("test", reg, reg, NULL);
1451 1450 put_reg(reg);
1452 1451
1453 1452 /* create conditional-failed label to jump to */
1454 1453 target_false = new_label();
1455 1454 target_val = new_storage(STOR_LABEL);
1456 1455 target_val->label = target_false;
1457 1456 target_val->flags = STOR_WANTS_FREE;
1458 1457 insn("jz", target_val, NULL, NULL);
1459 1458
1460 1459 return target_false;
1461 1460 }
1462 1461
1463 1462 static int emit_conditional_end(int target_false)
1464 1463 {
1465 1464 struct storage *cond_end_st;
1466 1465 int cond_end;
1467 1466
1468 1467 /* finished generating code for if-true statement.
1469 1468 * add a jump-to-end jump to avoid falling through
1470 1469 * to the if-false statement code.
1471 1470 */
1472 1471 cond_end = new_label();
1473 1472 cond_end_st = new_storage(STOR_LABEL);
1474 1473 cond_end_st->label = cond_end;
1475 1474 cond_end_st->flags = STOR_WANTS_FREE;
1476 1475 insn("jmp", cond_end_st, NULL, NULL);
1477 1476
1478 1477 /* if we have both if-true and if-false statements,
1479 1478 * the failed-conditional case will fall through to here
1480 1479 */
1481 1480 emit_label(target_false, NULL);
1482 1481
1483 1482 return cond_end;
1484 1483 }
1485 1484
1486 1485 static void emit_if_conditional(struct statement *stmt)
1487 1486 {
1488 1487 struct storage *val;
1489 1488 int cond_end;
1490 1489
1491 1490 /* emit test portion of conditional */
1492 1491 val = x86_expression(stmt->if_conditional);
1493 1492 cond_end = emit_conditional_test(val);
1494 1493
1495 1494 /* emit if-true statement */
1496 1495 x86_statement(stmt->if_true);
1497 1496
1498 1497 /* emit if-false statement, if present */
1499 1498 if (stmt->if_false) {
1500 1499 cond_end = emit_conditional_end(cond_end);
1501 1500 x86_statement(stmt->if_false);
1502 1501 }
1503 1502
1504 1503 /* end of conditional; jump target for if-true branch */
1505 1504 emit_label(cond_end, "end if");
1506 1505 }
1507 1506
1508 1507 static struct storage *emit_inc_dec(struct expression *expr, int postop)
1509 1508 {
1510 1509 struct storage *addr = x86_address_gen(expr->unop);
1511 1510 struct storage *retval;
1512 1511 char opname[16];
1513 1512
1514 1513 strcpy(opname, opbits(expr->op == SPECIAL_INCREMENT ? "inc" : "dec",
1515 1514 expr->ctype->bit_size));
1516 1515
1517 1516 if (postop) {
1518 1517 struct storage *new = stack_alloc(4);
1519 1518
1520 1519 emit_copy(new, addr, expr->unop->ctype);
1521 1520
1522 1521 retval = new;
1523 1522 } else
1524 1523 retval = addr;
1525 1524
1526 1525 insn(opname, addr, NULL, NULL);
1527 1526
1528 1527 return retval;
1529 1528 }
1530 1529
1531 1530 static struct storage *emit_postop(struct expression *expr)
1532 1531 {
1533 1532 return emit_inc_dec(expr, 1);
1534 1533 }
1535 1534
1536 1535 static struct storage *emit_return_stmt(struct statement *stmt)
1537 1536 {
1538 1537 struct function *f = current_func;
1539 1538 struct expression *expr = stmt->ret_value;
1540 1539 struct storage *val = NULL, *jmplbl;
1541 1540
1542 1541 if (expr && expr->ctype) {
1543 1542 val = x86_expression(expr);
1544 1543 assert(val != NULL);
1545 1544 emit_move(val, REG_EAX, expr->ctype, "return");
1546 1545 }
1547 1546
↓ open down ↓ |
179 lines elided |
↑ open up ↑ |
1548 1547 jmplbl = new_storage(STOR_LABEL);
1549 1548 jmplbl->flags |= STOR_WANTS_FREE;
1550 1549 jmplbl->label = f->ret_target;
1551 1550 insn("jmp", jmplbl, NULL, NULL);
1552 1551
1553 1552 return val;
1554 1553 }
1555 1554
1556 1555 static struct storage *emit_conditional_expr(struct expression *expr)
1557 1556 {
1558 - struct storage *cond, *true = NULL, *false = NULL;
1557 + struct storage *cond, *stot = NULL, *stof = NULL;
1559 1558 struct storage *new = stack_alloc(expr->ctype->bit_size / 8);
1560 1559 int target_false, cond_end;
1561 1560
1562 1561 /* evaluate conditional */
1563 1562 cond = x86_expression(expr->conditional);
1564 1563 target_false = emit_conditional_test(cond);
1565 1564
1566 1565 /* handle if-true part of the expression */
1567 - true = x86_expression(expr->cond_true);
1566 + stot = x86_expression(expr->cond_true);
1568 1567
1569 - emit_copy(new, true, expr->ctype);
1568 + emit_copy(new, stot, expr->ctype);
1570 1569
1571 1570 cond_end = emit_conditional_end(target_false);
1572 1571
1573 1572 /* handle if-false part of the expression */
1574 - false = x86_expression(expr->cond_false);
1573 + stof = x86_expression(expr->cond_false);
1575 1574
1576 - emit_copy(new, false, expr->ctype);
1575 + emit_copy(new, stof, expr->ctype);
1577 1576
1578 1577 /* end of conditional; jump target for if-true branch */
1579 1578 emit_label(cond_end, "end conditional");
1580 1579
1581 1580 return new;
1582 1581 }
1583 1582
1584 1583 static struct storage *emit_select_expr(struct expression *expr)
1585 1584 {
1586 1585 struct storage *cond = x86_expression(expr->conditional);
1587 - struct storage *true = x86_expression(expr->cond_true);
1588 - struct storage *false = x86_expression(expr->cond_false);
1586 + struct storage *stot = x86_expression(expr->cond_true);
1587 + struct storage *stof = x86_expression(expr->cond_false);
1589 1588 struct storage *reg_cond, *reg_true, *reg_false;
1590 1589 struct storage *new = stack_alloc(4);
1591 1590
1592 1591 emit_comment("begin SELECT");
1593 1592 reg_cond = get_reg_value(cond, get_regclass(expr->conditional));
1594 - reg_true = get_reg_value(true, get_regclass(expr));
1595 - reg_false = get_reg_value(false, get_regclass(expr));
1593 + reg_true = get_reg_value(stot, get_regclass(expr));
1594 + reg_false = get_reg_value(stof, get_regclass(expr));
1596 1595
1597 1596 /*
1598 1597 * Do the actual select: check the conditional for zero,
1599 1598 * move false over true if zero
1600 1599 */
1601 1600 insn("test", reg_cond, reg_cond, NULL);
1602 1601 insn("cmovz", reg_false, reg_true, NULL);
1603 1602
1604 1603 /* Store it back */
1605 1604 emit_move(reg_true, new, expr->ctype, NULL);
1606 1605 put_reg(reg_cond);
1607 1606 put_reg(reg_true);
1608 1607 put_reg(reg_false);
1609 1608 emit_comment("end SELECT");
1610 1609 return new;
1611 1610 }
1612 1611
1613 1612 static struct storage *emit_symbol_expr_init(struct symbol *sym)
1614 1613 {
1615 1614 struct expression *expr = sym->initializer;
1616 1615 struct symbol_private *priv = sym->aux;
1617 1616
1618 1617 if (priv == NULL) {
1619 1618 priv = calloc(1, sizeof(*priv));
1620 1619 sym->aux = priv;
1621 1620
1622 1621 if (expr == NULL) {
1623 1622 struct storage *new = stack_alloc(4);
1624 1623 fprintf(stderr, "FIXME! no value for symbol %s. creating pseudo %d (stack offset %d)\n",
1625 1624 show_ident(sym->ident),
1626 1625 new->pseudo, new->pseudo * 4);
1627 1626 priv->addr = new;
1628 1627 } else {
1629 1628 priv->addr = x86_expression(expr);
1630 1629 }
1631 1630 }
1632 1631
1633 1632 return priv->addr;
1634 1633 }
1635 1634
1636 1635 static struct storage *emit_string_expr(struct expression *expr)
1637 1636 {
1638 1637 struct function *f = current_func;
1639 1638 int label = new_label();
1640 1639 struct storage *new;
1641 1640
1642 1641 push_cstring(f, expr->string, label);
1643 1642
1644 1643 new = new_storage(STOR_LABEL);
1645 1644 new->label = label;
1646 1645 new->flags = STOR_LABEL_VAL | STOR_WANTS_FREE;
1647 1646 return new;
1648 1647 }
1649 1648
1650 1649 static struct storage *emit_cast_expr(struct expression *expr)
1651 1650 {
1652 1651 struct symbol *old_type, *new_type;
1653 1652 struct storage *op = x86_expression(expr->cast_expression);
1654 1653 int oldbits, newbits;
1655 1654 struct storage *new;
1656 1655
1657 1656 old_type = expr->cast_expression->ctype;
1658 1657 new_type = expr->cast_type;
1659 1658
1660 1659 oldbits = old_type->bit_size;
1661 1660 newbits = new_type->bit_size;
1662 1661 if (oldbits >= newbits)
1663 1662 return op;
1664 1663
1665 1664 emit_move(op, REG_EAX, old_type, "begin cast ..");
1666 1665
1667 1666 new = stack_alloc(newbits / 8);
1668 1667 emit_move(REG_EAX, new, new_type, ".... end cast");
1669 1668
1670 1669 return new;
1671 1670 }
1672 1671
1673 1672 static struct storage *emit_regular_preop(struct expression *expr)
1674 1673 {
1675 1674 struct storage *target = x86_expression(expr->unop);
1676 1675 struct storage *val, *new = stack_alloc(4);
1677 1676 const char *opname = NULL;
1678 1677
1679 1678 switch (expr->op) {
1680 1679 case '!':
1681 1680 val = new_storage(STOR_VALUE);
1682 1681 val->flags = STOR_WANTS_FREE;
1683 1682 emit_move(val, REG_EDX, NULL, NULL);
1684 1683 emit_move(target, REG_EAX, expr->unop->ctype, NULL);
1685 1684 insn("test", REG_EAX, REG_EAX, NULL);
1686 1685 insn("setz", REG_DL, NULL, NULL);
1687 1686 emit_move(REG_EDX, new, expr->unop->ctype, NULL);
1688 1687
1689 1688 break;
1690 1689 case '~':
1691 1690 opname = "not";
1692 1691 case '-':
1693 1692 if (!opname)
1694 1693 opname = "neg";
1695 1694 emit_move(target, REG_EAX, expr->unop->ctype, NULL);
1696 1695 insn(opname, REG_EAX, NULL, NULL);
1697 1696 emit_move(REG_EAX, new, expr->unop->ctype, NULL);
1698 1697 break;
1699 1698 default:
1700 1699 assert(0);
1701 1700 break;
1702 1701 }
1703 1702
1704 1703 return new;
1705 1704 }
1706 1705
1707 1706 static void emit_case_statement(struct statement *stmt)
1708 1707 {
1709 1708 emit_labelsym(stmt->case_label, NULL);
1710 1709 x86_statement(stmt->case_statement);
1711 1710 }
1712 1711
1713 1712 static void emit_switch_statement(struct statement *stmt)
1714 1713 {
1715 1714 struct storage *val = x86_expression(stmt->switch_expression);
1716 1715 struct symbol *sym, *default_sym = NULL;
1717 1716 struct storage *labelsym, *label;
1718 1717 int switch_end = 0;
1719 1718
1720 1719 emit_move(val, REG_EAX, stmt->switch_expression->ctype, "begin case");
1721 1720
1722 1721 /*
1723 1722 * This is where a _real_ back-end would go through the
1724 1723 * cases to decide whether to use a lookup table or a
1725 1724 * series of comparisons etc
1726 1725 */
1727 1726 FOR_EACH_PTR(stmt->switch_case->symbol_list, sym) {
1728 1727 struct statement *case_stmt = sym->stmt;
1729 1728 struct expression *expr = case_stmt->case_expression;
1730 1729 struct expression *to = case_stmt->case_to;
1731 1730
1732 1731 /* default: */
1733 1732 if (!expr)
1734 1733 default_sym = sym;
1735 1734
1736 1735 /* case NNN: */
1737 1736 else {
1738 1737 struct storage *case_val = new_val(expr->value);
1739 1738
1740 1739 assert (expr->type == EXPR_VALUE);
1741 1740
1742 1741 insn("cmpl", case_val, REG_EAX, NULL);
1743 1742
1744 1743 if (!to) {
1745 1744 labelsym = new_labelsym(sym);
1746 1745 insn("je", labelsym, NULL, NULL);
1747 1746 } else {
1748 1747 int next_test;
1749 1748
1750 1749 label = new_storage(STOR_LABEL);
1751 1750 label->flags |= STOR_WANTS_FREE;
1752 1751 label->label = next_test = new_label();
1753 1752
1754 1753 /* FIXME: signed/unsigned */
1755 1754 insn("jl", label, NULL, NULL);
1756 1755
1757 1756 case_val = new_val(to->value);
1758 1757 insn("cmpl", case_val, REG_EAX, NULL);
1759 1758
1760 1759 /* TODO: implement and use refcounting... */
1761 1760 label = new_storage(STOR_LABEL);
1762 1761 label->flags |= STOR_WANTS_FREE;
1763 1762 label->label = next_test;
1764 1763
1765 1764 /* FIXME: signed/unsigned */
1766 1765 insn("jg", label, NULL, NULL);
1767 1766
1768 1767 labelsym = new_labelsym(sym);
1769 1768 insn("jmp", labelsym, NULL, NULL);
1770 1769
1771 1770 emit_label(next_test, NULL);
1772 1771 }
1773 1772 }
1774 1773 } END_FOR_EACH_PTR(sym);
1775 1774
1776 1775 if (default_sym) {
1777 1776 labelsym = new_labelsym(default_sym);
1778 1777 insn("jmp", labelsym, NULL, "default");
1779 1778 } else {
1780 1779 label = new_storage(STOR_LABEL);
1781 1780 label->flags |= STOR_WANTS_FREE;
1782 1781 label->label = switch_end = new_label();
1783 1782 insn("jmp", label, NULL, "goto end of switch");
1784 1783 }
1785 1784
1786 1785 x86_statement(stmt->switch_statement);
1787 1786
1788 1787 if (stmt->switch_break->used)
1789 1788 emit_labelsym(stmt->switch_break, NULL);
1790 1789
1791 1790 if (switch_end)
1792 1791 emit_label(switch_end, NULL);
1793 1792 }
1794 1793
1795 1794 static void x86_struct_member(struct symbol *sym)
1796 1795 {
1797 1796 printf("\t%s:%d:%ld at offset %ld.%d", show_ident(sym->ident), sym->bit_size, sym->ctype.alignment, sym->offset, sym->bit_offset);
1798 1797 printf("\n");
1799 1798 }
1800 1799
1801 1800 static void x86_symbol(struct symbol *sym)
1802 1801 {
1803 1802 struct symbol *type;
1804 1803
1805 1804 if (!sym)
1806 1805 return;
1807 1806
1808 1807 type = sym->ctype.base_type;
1809 1808 if (!type)
1810 1809 return;
1811 1810
1812 1811 /*
1813 1812 * Show actual implementation information
1814 1813 */
1815 1814 switch (type->type) {
1816 1815
1817 1816 case SYM_ARRAY:
1818 1817 if (sym->initializer)
1819 1818 emit_array(sym);
1820 1819 else
1821 1820 emit_array_noinit(sym);
1822 1821 break;
1823 1822
1824 1823 case SYM_BASETYPE:
1825 1824 if (sym->initializer) {
1826 1825 emit_object_pre(show_ident(sym->ident),
1827 1826 sym->ctype.modifiers,
1828 1827 sym->ctype.alignment,
1829 1828 sym->bit_size / 8);
1830 1829 emit_scalar(sym->initializer, sym->bit_size);
1831 1830 stor_sym_init(sym);
1832 1831 } else
1833 1832 emit_scalar_noinit(sym);
1834 1833 break;
1835 1834
1836 1835 case SYM_STRUCT:
1837 1836 case SYM_UNION: {
1838 1837 struct symbol *member;
1839 1838
1840 1839 printf(" {\n");
1841 1840 FOR_EACH_PTR(type->symbol_list, member) {
1842 1841 x86_struct_member(member);
1843 1842 } END_FOR_EACH_PTR(member);
1844 1843 printf("}\n");
1845 1844 break;
1846 1845 }
1847 1846
1848 1847 case SYM_FN: {
1849 1848 struct statement *stmt = type->stmt;
1850 1849 if (stmt) {
1851 1850 emit_func_pre(sym);
1852 1851 x86_statement(stmt);
1853 1852 emit_func_post(sym);
1854 1853 }
1855 1854 break;
1856 1855 }
1857 1856
1858 1857 default:
1859 1858 break;
1860 1859 }
1861 1860
1862 1861 if (sym->initializer && (type->type != SYM_BASETYPE) &&
1863 1862 (type->type != SYM_ARRAY)) {
1864 1863 printf(" = \n");
1865 1864 x86_expression(sym->initializer);
1866 1865 }
1867 1866 }
1868 1867
1869 1868 static void x86_symbol_init(struct symbol *sym);
1870 1869
1871 1870 static void x86_symbol_decl(struct symbol_list *syms)
1872 1871 {
1873 1872 struct symbol *sym;
1874 1873 FOR_EACH_PTR(syms, sym) {
1875 1874 x86_symbol_init(sym);
1876 1875 } END_FOR_EACH_PTR(sym);
1877 1876 }
1878 1877
1879 1878 static void loopstk_push(int cont_lbl, int loop_bottom_lbl)
1880 1879 {
1881 1880 struct function *f = current_func;
1882 1881 struct loop_stack *ls;
1883 1882
1884 1883 ls = malloc(sizeof(*ls));
1885 1884 ls->continue_lbl = cont_lbl;
1886 1885 ls->loop_bottom_lbl = loop_bottom_lbl;
1887 1886 ls->next = f->loop_stack;
1888 1887 f->loop_stack = ls;
1889 1888 }
1890 1889
1891 1890 static void loopstk_pop(void)
1892 1891 {
1893 1892 struct function *f = current_func;
1894 1893 struct loop_stack *ls;
1895 1894
1896 1895 assert(f->loop_stack != NULL);
1897 1896 ls = f->loop_stack;
1898 1897 f->loop_stack = f->loop_stack->next;
1899 1898 free(ls);
1900 1899 }
1901 1900
1902 1901 static int loopstk_break(void)
1903 1902 {
1904 1903 return current_func->loop_stack->loop_bottom_lbl;
1905 1904 }
1906 1905
1907 1906 static int loopstk_continue(void)
1908 1907 {
1909 1908 return current_func->loop_stack->continue_lbl;
1910 1909 }
1911 1910
1912 1911 static void emit_loop(struct statement *stmt)
1913 1912 {
1914 1913 struct statement *pre_statement = stmt->iterator_pre_statement;
1915 1914 struct expression *pre_condition = stmt->iterator_pre_condition;
1916 1915 struct statement *statement = stmt->iterator_statement;
1917 1916 struct statement *post_statement = stmt->iterator_post_statement;
1918 1917 struct expression *post_condition = stmt->iterator_post_condition;
1919 1918 int loop_top = 0, loop_bottom, loop_continue;
1920 1919 int have_bottom = 0;
1921 1920 struct storage *val;
1922 1921
1923 1922 loop_bottom = new_label();
1924 1923 loop_continue = new_label();
1925 1924 loopstk_push(loop_continue, loop_bottom);
1926 1925
1927 1926 x86_symbol_decl(stmt->iterator_syms);
1928 1927 x86_statement(pre_statement);
1929 1928 if (!post_condition || post_condition->type != EXPR_VALUE || post_condition->value) {
1930 1929 loop_top = new_label();
1931 1930 emit_label(loop_top, "loop top");
1932 1931 }
1933 1932 if (pre_condition) {
1934 1933 if (pre_condition->type == EXPR_VALUE) {
1935 1934 if (!pre_condition->value) {
1936 1935 struct storage *lbv;
1937 1936 lbv = new_storage(STOR_LABEL);
1938 1937 lbv->label = loop_bottom;
1939 1938 lbv->flags = STOR_WANTS_FREE;
1940 1939 insn("jmp", lbv, NULL, "go to loop bottom");
1941 1940 have_bottom = 1;
1942 1941 }
1943 1942 } else {
1944 1943 struct storage *lbv = new_storage(STOR_LABEL);
1945 1944 lbv->label = loop_bottom;
1946 1945 lbv->flags = STOR_WANTS_FREE;
1947 1946 have_bottom = 1;
1948 1947
1949 1948 val = x86_expression(pre_condition);
1950 1949
1951 1950 emit_move(val, REG_EAX, NULL, "loop pre condition");
1952 1951 insn("test", REG_EAX, REG_EAX, NULL);
1953 1952 insn("jz", lbv, NULL, NULL);
1954 1953 }
1955 1954 }
1956 1955 x86_statement(statement);
1957 1956 if (stmt->iterator_continue->used)
1958 1957 emit_label(loop_continue, "'continue' iterator");
1959 1958 x86_statement(post_statement);
1960 1959 if (!post_condition) {
1961 1960 struct storage *lbv = new_storage(STOR_LABEL);
1962 1961 lbv->label = loop_top;
1963 1962 lbv->flags = STOR_WANTS_FREE;
1964 1963 insn("jmp", lbv, NULL, "go to loop top");
1965 1964 } else if (post_condition->type == EXPR_VALUE) {
1966 1965 if (post_condition->value) {
1967 1966 struct storage *lbv = new_storage(STOR_LABEL);
1968 1967 lbv->label = loop_top;
1969 1968 lbv->flags = STOR_WANTS_FREE;
1970 1969 insn("jmp", lbv, NULL, "go to loop top");
1971 1970 }
1972 1971 } else {
1973 1972 struct storage *lbv = new_storage(STOR_LABEL);
1974 1973 lbv->label = loop_top;
1975 1974 lbv->flags = STOR_WANTS_FREE;
1976 1975
1977 1976 val = x86_expression(post_condition);
1978 1977
1979 1978 emit_move(val, REG_EAX, NULL, "loop post condition");
1980 1979 insn("test", REG_EAX, REG_EAX, NULL);
1981 1980 insn("jnz", lbv, NULL, NULL);
1982 1981 }
1983 1982 if (have_bottom || stmt->iterator_break->used)
1984 1983 emit_label(loop_bottom, "loop bottom");
1985 1984
1986 1985 loopstk_pop();
1987 1986 }
1988 1987
1989 1988 /*
1990 1989 * Print out a statement
1991 1990 */
1992 1991 static struct storage *x86_statement(struct statement *stmt)
1993 1992 {
1994 1993 if (!stmt)
1995 1994 return NULL;
1996 1995 switch (stmt->type) {
1997 1996 default:
1998 1997 return NULL;
1999 1998 case STMT_RETURN:
2000 1999 return emit_return_stmt(stmt);
2001 2000 case STMT_DECLARATION:
2002 2001 x86_symbol_decl(stmt->declaration);
2003 2002 break;
2004 2003 case STMT_COMPOUND: {
2005 2004 struct statement *s;
2006 2005 struct storage *last = NULL;
2007 2006
2008 2007 FOR_EACH_PTR(stmt->stmts, s) {
2009 2008 last = x86_statement(s);
2010 2009 } END_FOR_EACH_PTR(s);
2011 2010
2012 2011 return last;
2013 2012 }
2014 2013
2015 2014 case STMT_EXPRESSION:
2016 2015 return x86_expression(stmt->expression);
2017 2016 case STMT_IF:
2018 2017 emit_if_conditional(stmt);
2019 2018 return NULL;
2020 2019
2021 2020 case STMT_CASE:
2022 2021 emit_case_statement(stmt);
2023 2022 break;
2024 2023 case STMT_SWITCH:
2025 2024 emit_switch_statement(stmt);
2026 2025 break;
2027 2026
2028 2027 case STMT_ITERATOR:
2029 2028 emit_loop(stmt);
2030 2029 break;
2031 2030
2032 2031 case STMT_NONE:
2033 2032 break;
2034 2033
2035 2034 case STMT_LABEL:
2036 2035 printf(".L%p:\n", stmt->label_identifier);
2037 2036 x86_statement(stmt->label_statement);
2038 2037 break;
2039 2038
2040 2039 case STMT_GOTO:
2041 2040 if (stmt->goto_expression) {
2042 2041 struct storage *val = x86_expression(stmt->goto_expression);
2043 2042 printf("\tgoto *v%d\n", val->pseudo);
2044 2043 } else if (!strcmp("break", show_ident(stmt->goto_label->ident))) {
2045 2044 struct storage *lbv = new_storage(STOR_LABEL);
2046 2045 lbv->label = loopstk_break();
2047 2046 lbv->flags = STOR_WANTS_FREE;
2048 2047 insn("jmp", lbv, NULL, "'break'; go to loop bottom");
2049 2048 } else if (!strcmp("continue", show_ident(stmt->goto_label->ident))) {
2050 2049 struct storage *lbv = new_storage(STOR_LABEL);
2051 2050 lbv->label = loopstk_continue();
2052 2051 lbv->flags = STOR_WANTS_FREE;
2053 2052 insn("jmp", lbv, NULL, "'continue'; go to loop top");
2054 2053 } else {
2055 2054 struct storage *labelsym = new_labelsym(stmt->goto_label);
2056 2055 insn("jmp", labelsym, NULL, NULL);
2057 2056 }
2058 2057 break;
2059 2058 case STMT_ASM:
2060 2059 printf("\tasm( .... )\n");
2061 2060 break;
2062 2061 }
2063 2062 return NULL;
2064 2063 }
2065 2064
2066 2065 static struct storage *x86_call_expression(struct expression *expr)
2067 2066 {
2068 2067 struct function *f = current_func;
2069 2068 struct symbol *direct;
2070 2069 struct expression *arg, *fn;
2071 2070 struct storage *retval, *fncall;
2072 2071 int framesize;
2073 2072 char s[64];
2074 2073
2075 2074 if (!expr->ctype) {
2076 2075 warning(expr->pos, "\tcall with no type!");
2077 2076 return NULL;
2078 2077 }
2079 2078
2080 2079 framesize = 0;
2081 2080 FOR_EACH_PTR_REVERSE(expr->args, arg) {
2082 2081 struct storage *new = x86_expression(arg);
2083 2082 int size = arg->ctype->bit_size;
2084 2083
2085 2084 /*
2086 2085 * FIXME: i386 SysV ABI dictates that values
2087 2086 * smaller than 32 bits should be placed onto
2088 2087 * the stack as 32-bit objects. We should not
2089 2088 * blindly do a 32-bit push on objects smaller
2090 2089 * than 32 bits.
2091 2090 */
2092 2091 if (size < 32)
2093 2092 size = 32;
2094 2093 insn("pushl", new, NULL,
2095 2094 !framesize ? "begin function call" : NULL);
2096 2095
2097 2096 framesize += bits_to_bytes(size);
2098 2097 } END_FOR_EACH_PTR_REVERSE(arg);
2099 2098
2100 2099 fn = expr->fn;
2101 2100
2102 2101 /* Remove dereference, if any */
2103 2102 direct = NULL;
2104 2103 if (fn->type == EXPR_PREOP) {
2105 2104 if (fn->unop->type == EXPR_SYMBOL) {
2106 2105 struct symbol *sym = fn->unop->symbol;
2107 2106 if (sym->ctype.base_type->type == SYM_FN)
2108 2107 direct = sym;
2109 2108 }
2110 2109 }
2111 2110 if (direct) {
2112 2111 struct storage *direct_stor = new_storage(STOR_SYM);
2113 2112 direct_stor->flags |= STOR_WANTS_FREE;
2114 2113 direct_stor->sym = direct;
2115 2114 insn("call", direct_stor, NULL, NULL);
2116 2115 } else {
2117 2116 fncall = x86_expression(fn);
2118 2117 emit_move(fncall, REG_EAX, fn->ctype, NULL);
2119 2118
2120 2119 strcpy(s, "\tcall\t*%eax\n");
2121 2120 push_text_atom(f, s);
2122 2121 }
2123 2122
2124 2123 /* FIXME: pay attention to BITS_IN_POINTER */
2125 2124 if (framesize) {
2126 2125 struct storage *val = new_storage(STOR_VALUE);
2127 2126 val->value = (long long) framesize;
2128 2127 val->flags = STOR_WANTS_FREE;
2129 2128 insn("addl", val, REG_ESP, NULL);
2130 2129 }
2131 2130
2132 2131 retval = stack_alloc(4);
2133 2132 emit_move(REG_EAX, retval, NULL, "end function call");
2134 2133
2135 2134 return retval;
2136 2135 }
2137 2136
2138 2137 static struct storage *x86_address_gen(struct expression *expr)
2139 2138 {
2140 2139 struct function *f = current_func;
2141 2140 struct storage *addr;
2142 2141 struct storage *new;
2143 2142 char s[32];
2144 2143
2145 2144 addr = x86_expression(expr->unop);
2146 2145 if (expr->unop->type == EXPR_SYMBOL)
2147 2146 return addr;
2148 2147
2149 2148 emit_move(addr, REG_EAX, NULL, "begin deref ..");
2150 2149
2151 2150 /* FIXME: operand size */
2152 2151 strcpy(s, "\tmovl\t(%eax), %ecx\n");
2153 2152 push_text_atom(f, s);
2154 2153
2155 2154 new = stack_alloc(4);
2156 2155 emit_move(REG_ECX, new, NULL, ".... end deref");
2157 2156
2158 2157 return new;
2159 2158 }
2160 2159
2161 2160 static struct storage *x86_assignment(struct expression *expr)
2162 2161 {
2163 2162 struct expression *target = expr->left;
2164 2163 struct storage *val, *addr;
2165 2164
2166 2165 if (!expr->ctype)
2167 2166 return NULL;
2168 2167
2169 2168 val = x86_expression(expr->right);
2170 2169 addr = x86_address_gen(target);
2171 2170
2172 2171 switch (val->type) {
2173 2172 /* copy, where both operands are memory */
2174 2173 case STOR_PSEUDO:
2175 2174 case STOR_ARG:
2176 2175 emit_copy(addr, val, expr->ctype);
2177 2176 break;
2178 2177
2179 2178 /* copy, one or zero operands are memory */
2180 2179 case STOR_REG:
2181 2180 case STOR_SYM:
2182 2181 case STOR_VALUE:
2183 2182 case STOR_LABEL:
2184 2183 emit_move(val, addr, expr->left->ctype, NULL);
2185 2184 break;
2186 2185
2187 2186 case STOR_LABELSYM:
2188 2187 assert(0);
2189 2188 break;
2190 2189 }
2191 2190 return val;
2192 2191 }
2193 2192
2194 2193 static int x86_initialization(struct symbol *sym, struct expression *expr)
2195 2194 {
2196 2195 struct storage *val, *addr;
2197 2196 int bits;
2198 2197
2199 2198 if (!expr->ctype)
2200 2199 return 0;
2201 2200
2202 2201 bits = expr->ctype->bit_size;
2203 2202 val = x86_expression(expr);
2204 2203 addr = x86_symbol_expr(sym);
2205 2204 // FIXME! The "target" expression is for bitfield store information.
2206 2205 // Leave it NULL, which works fine.
2207 2206 emit_store(NULL, addr, val, bits);
2208 2207 return 0;
2209 2208 }
2210 2209
2211 2210 static struct storage *x86_access(struct expression *expr)
2212 2211 {
2213 2212 return x86_address_gen(expr);
2214 2213 }
2215 2214
2216 2215 static struct storage *x86_preop(struct expression *expr)
2217 2216 {
2218 2217 /*
2219 2218 * '*' is an lvalue access, and is fundamentally different
2220 2219 * from an arithmetic operation. Maybe it should have an
2221 2220 * expression type of its own..
2222 2221 */
2223 2222 if (expr->op == '*')
2224 2223 return x86_access(expr);
2225 2224 if (expr->op == SPECIAL_INCREMENT || expr->op == SPECIAL_DECREMENT)
2226 2225 return emit_inc_dec(expr, 0);
2227 2226 return emit_regular_preop(expr);
2228 2227 }
↓ open down ↓ |
623 lines elided |
↑ open up ↑ |
2229 2228
2230 2229 static struct storage *x86_symbol_expr(struct symbol *sym)
2231 2230 {
2232 2231 struct storage *new = stack_alloc(4);
2233 2232
2234 2233 if (sym->ctype.modifiers & (MOD_TOPLEVEL | MOD_EXTERN | MOD_STATIC)) {
2235 2234 printf("\tmovi.%d\t\tv%d,$%s\n", bits_in_pointer, new->pseudo, show_ident(sym->ident));
2236 2235 return new;
2237 2236 }
2238 2237 if (sym->ctype.modifiers & MOD_ADDRESSABLE) {
2239 - printf("\taddi.%d\t\tv%d,vFP,$%lld\n", bits_in_pointer, new->pseudo, sym->value);
2238 + printf("\taddi.%d\t\tv%d,vFP,$%lld\n", bits_in_pointer, new->pseudo, 0LL);
2240 2239 return new;
2241 2240 }
2242 2241 printf("\taddi.%d\t\tv%d,vFP,$offsetof(%s:%p)\n", bits_in_pointer, new->pseudo, show_ident(sym->ident), sym);
2243 2242 return new;
2244 2243 }
2245 2244
2246 2245 static void x86_symbol_init(struct symbol *sym)
2247 2246 {
2248 2247 struct symbol_private *priv = sym->aux;
2249 2248 struct expression *expr = sym->initializer;
2250 2249 struct storage *new;
2251 2250
2252 2251 if (expr)
2253 2252 new = x86_expression(expr);
2254 2253 else
2255 2254 new = stack_alloc(sym->bit_size / 8);
2256 2255
↓ open down ↓ |
7 lines elided |
↑ open up ↑ |
2257 2256 if (!priv) {
2258 2257 priv = calloc(1, sizeof(*priv));
2259 2258 sym->aux = priv;
2260 2259 /* FIXME: leak! we don't free... */
2261 2260 /* (well, we don't free symbols either) */
2262 2261 }
2263 2262
2264 2263 priv->addr = new;
2265 2264 }
2266 2265
2267 -static int type_is_signed(struct symbol *sym)
2268 -{
2269 - if (sym->type == SYM_NODE)
2270 - sym = sym->ctype.base_type;
2271 - if (sym->type == SYM_PTR)
2272 - return 0;
2273 - return !(sym->ctype.modifiers & MOD_UNSIGNED);
2274 -}
2275 -
2276 2266 static struct storage *x86_label_expr(struct expression *expr)
2277 2267 {
2278 2268 struct storage *new = stack_alloc(4);
2279 2269 printf("\tmovi.%d\t\tv%d,.L%p\n", bits_in_pointer, new->pseudo, expr->label_symbol);
2280 2270 return new;
2281 2271 }
2282 2272
2283 2273 static struct storage *x86_statement_expr(struct expression *expr)
2284 2274 {
2285 2275 return x86_statement(expr->statement);
2286 2276 }
2287 2277
2288 2278 static int x86_position_expr(struct expression *expr, struct symbol *base)
2289 2279 {
2290 2280 struct storage *new = x86_expression(expr->init_expr);
2291 2281 struct symbol *ctype = expr->init_expr->ctype;
2292 2282
2293 2283 printf("\tinsert v%d at [%d:%d] of %s\n", new->pseudo,
2294 2284 expr->init_offset, ctype->bit_offset,
2295 2285 show_ident(base->ident));
2296 2286 return 0;
2297 2287 }
2298 2288
2299 2289 static void x86_initializer_expr(struct expression *expr, struct symbol *ctype)
2300 2290 {
2301 2291 struct expression *entry;
2302 2292
2303 2293 FOR_EACH_PTR(expr->expr_list, entry) {
2304 2294 // Nested initializers have their positions already
2305 2295 // recursively calculated - just output them too
2306 2296 if (entry->type == EXPR_INITIALIZER) {
2307 2297 x86_initializer_expr(entry, ctype);
2308 2298 continue;
2309 2299 }
2310 2300
2311 2301 // Ignore initializer indexes and identifiers - the
2312 2302 // evaluator has taken them into account
2313 2303 if (entry->type == EXPR_IDENTIFIER || entry->type == EXPR_INDEX)
2314 2304 continue;
2315 2305 if (entry->type == EXPR_POS) {
2316 2306 x86_position_expr(entry, ctype);
2317 2307 continue;
2318 2308 }
2319 2309 x86_initialization(ctype, entry);
2320 2310 } END_FOR_EACH_PTR(entry);
2321 2311 }
2322 2312
2323 2313 /*
2324 2314 * Print out an expression. Return the pseudo that contains the
2325 2315 * variable.
2326 2316 */
2327 2317 static struct storage *x86_expression(struct expression *expr)
2328 2318 {
2329 2319 if (!expr)
2330 2320 return NULL;
2331 2321
2332 2322 if (!expr->ctype) {
2333 2323 struct position *pos = &expr->pos;
2334 2324 printf("\tno type at %s:%d:%d\n",
2335 2325 stream_name(pos->stream),
2336 2326 pos->line, pos->pos);
2337 2327 return NULL;
2338 2328 }
2339 2329
2340 2330 switch (expr->type) {
2341 2331 default:
2342 2332 return NULL;
2343 2333 case EXPR_CALL:
2344 2334 return x86_call_expression(expr);
2345 2335
2346 2336 case EXPR_ASSIGNMENT:
2347 2337 return x86_assignment(expr);
2348 2338
2349 2339 case EXPR_COMPARE:
2350 2340 return emit_compare(expr);
2351 2341 case EXPR_BINOP:
2352 2342 case EXPR_COMMA:
2353 2343 case EXPR_LOGICAL:
2354 2344 return emit_binop(expr);
2355 2345 case EXPR_PREOP:
2356 2346 return x86_preop(expr);
2357 2347 case EXPR_POSTOP:
2358 2348 return emit_postop(expr);
2359 2349 case EXPR_SYMBOL:
2360 2350 return emit_symbol_expr_init(expr->symbol);
2361 2351 case EXPR_DEREF:
2362 2352 case EXPR_SIZEOF:
2363 2353 case EXPR_ALIGNOF:
2364 2354 warning(expr->pos, "invalid expression after evaluation");
2365 2355 return NULL;
2366 2356 case EXPR_CAST:
2367 2357 case EXPR_FORCE_CAST:
2368 2358 case EXPR_IMPLIED_CAST:
2369 2359 return emit_cast_expr(expr);
2370 2360 case EXPR_VALUE:
2371 2361 return emit_value(expr);
2372 2362 case EXPR_STRING:
2373 2363 return emit_string_expr(expr);
2374 2364 case EXPR_INITIALIZER:
2375 2365 x86_initializer_expr(expr, expr->ctype);
2376 2366 return NULL;
2377 2367 case EXPR_SELECT:
2378 2368 return emit_select_expr(expr);
2379 2369 case EXPR_CONDITIONAL:
2380 2370 return emit_conditional_expr(expr);
2381 2371 case EXPR_STATEMENT:
2382 2372 return x86_statement_expr(expr);
2383 2373 case EXPR_LABEL:
2384 2374 return x86_label_expr(expr);
2385 2375
2386 2376 // None of these should exist as direct expressions: they are only
2387 2377 // valid as sub-expressions of initializers.
2388 2378 case EXPR_POS:
2389 2379 warning(expr->pos, "unable to show plain initializer position expression");
2390 2380 return NULL;
2391 2381 case EXPR_IDENTIFIER:
2392 2382 warning(expr->pos, "unable to show identifier expression");
2393 2383 return NULL;
2394 2384 case EXPR_INDEX:
2395 2385 warning(expr->pos, "unable to show index expression");
2396 2386 return NULL;
2397 2387 case EXPR_TYPE:
2398 2388 warning(expr->pos, "unable to show type expression");
2399 2389 return NULL;
2400 2390 case EXPR_FVALUE:
2401 2391 warning(expr->pos, "floating point support is not implemented");
2402 2392 return NULL;
2403 2393 }
2404 2394 return NULL;
2405 2395 }
↓ open down ↓ |
120 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX