~ubuntu-branches/ubuntu/vivid/golang/vivid

« back to all changes in this revision

Viewing changes to src/cmd/8g/cgen.c

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2013-08-20 14:06:23 UTC
  • mfrom: (14.1.23 saucy-proposed)
  • Revision ID: package-import@ubuntu.com-20130820140623-b414jfxi3m0qkmrq
Tags: 2:1.1.2-2ubuntu1
* Merge from Debian unstable (LP: #1211749, #1202027). Remaining changes:
  - 016-armhf-elf-header.patch: Use correct ELF header for armhf binaries.
  - d/control,control.cross: Update Breaks/Replaces for Ubuntu
    versions to ensure smooth upgrades, regenerate control file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
49
49
void
50
50
cgen(Node *n, Node *res)
51
51
{
52
 
        Node *nl, *nr, *r, n1, n2, nt, f0, f1;
 
52
        Node *nl, *nr, *r, n1, n2, nt;
53
53
        Prog *p1, *p2, *p3;
54
54
        int a;
55
55
 
63
63
        if(res == N || res->type == T)
64
64
                fatal("cgen: res nil");
65
65
 
66
 
        // inline slices
67
 
        if(cgen_inline(n, res))
68
 
                return;
 
66
        switch(n->op) {
 
67
        case OSLICE:
 
68
        case OSLICEARR:
 
69
        case OSLICESTR:
 
70
                if (res->op != ONAME || !res->addable) {
 
71
                        tempname(&n1, n->type);
 
72
                        cgen_slice(n, &n1);
 
73
                        cgen(&n1, res);
 
74
                } else
 
75
                        cgen_slice(n, res);
 
76
                return;
 
77
        case OEFACE:
 
78
                if (res->op != ONAME || !res->addable) {
 
79
                        tempname(&n1, n->type);
 
80
                        cgen_eface(n, &n1);
 
81
                        cgen(&n1, res);
 
82
                } else
 
83
                        cgen_eface(n, res);
 
84
                return;
 
85
        }
69
86
 
70
87
        while(n->op == OCONVNOP)
71
88
                n = n->left;
160
177
                case OADD:
161
178
                case OSUB:
162
179
                case OMUL:
 
180
                case OLROT:
163
181
                case OLSH:
164
182
                case ORSH:
165
183
                case OAND:
170
188
                }
171
189
        }
172
190
 
173
 
        if(nl != N && isfloat[n->type->etype] && isfloat[nl->type->etype])
174
 
                goto flt;
 
191
        if(nl != N && isfloat[n->type->etype] && isfloat[nl->type->etype]) {
 
192
                cgen_float(n, res);
 
193
                return;
 
194
        }
175
195
 
176
196
        switch(n->op) {
177
197
        default:
195
215
        case OGE:
196
216
        case OGT:
197
217
        case ONOT:
198
 
                p1 = gbranch(AJMP, T);
 
218
                p1 = gbranch(AJMP, T, 0);
199
219
                p2 = pc;
200
220
                gmove(nodbool(1), res);
201
 
                p3 = gbranch(AJMP, T);
 
221
                p3 = gbranch(AJMP, T, 0);
202
222
                patch(p1, pc);
203
 
                bgen(n, 1, p2);
 
223
                bgen(n, 1, 0, p2);
204
224
                gmove(nodbool(0), res);
205
225
                patch(p3, pc);
206
226
                return;
232
252
                a = optoas(n->op, nl->type);
233
253
                goto abop;
234
254
 
 
255
        case OHMUL:
 
256
                cgen_hmul(nl, nr, res);
 
257
                break;
 
258
 
235
259
        case OCONV:
236
260
                if(eqtype(n->type, nl->type) || noconv(n->type, nl->type)) {
237
261
                        cgen(nl, res);
274
298
 
275
299
                        nodconst(&n2, types[tptr], 0);
276
300
                        gins(optoas(OCMP, types[tptr]), &n1, &n2);
277
 
                        p1 = gbranch(optoas(OEQ, types[tptr]), T);
 
301
                        p1 = gbranch(optoas(OEQ, types[tptr]), T, -1);
278
302
 
279
303
                        n2 = n1;
280
304
                        n2.op = OINDREG;
308
332
 
309
333
                        nodconst(&n2, types[tptr], 0);
310
334
                        gins(optoas(OCMP, types[tptr]), &n1, &n2);
311
 
                        p1 = gbranch(optoas(OEQ, types[tptr]), T);
 
335
                        p1 = gbranch(optoas(OEQ, types[tptr]), T, -1);
312
336
 
313
337
                        n2 = n1;
314
338
                        n2.op = OINDREG;
324
348
                }
325
349
                if(isslice(nl->type)) {
326
350
                        igen(nl, &n1, res);
327
 
                        n1.op = OINDREG;
328
351
                        n1.type = types[TUINT32];
329
 
                        n1.xoffset = Array_cap;
 
352
                        n1.xoffset += Array_cap;
330
353
                        gmove(&n1, res);
331
354
                        regfree(&n1);
332
355
                        break;
360
383
 
361
384
        case OLSH:
362
385
        case ORSH:
363
 
                cgen_shift(n->op, nl, nr, res);
 
386
        case OLROT:
 
387
                cgen_shift(n->op, n->bounded, nl, nr, res);
364
388
                break;
365
389
        }
366
390
        return;
367
391
 
368
392
sbop:   // symmetric binary
369
 
        if(nl->ullman < nr->ullman) {
 
393
        if(nl->ullman < nr->ullman || nl->op == OLITERAL) {
370
394
                r = nl;
371
395
                nl = nr;
372
396
                nr = r;
373
397
        }
374
398
 
375
399
abop:   // asymmetric binary
376
 
        if(nl->ullman >= nr->ullman) {
 
400
        if(smallintconst(nr)) {
 
401
                mgen(nl, &n1, res);
 
402
                regalloc(&n2, nl->type, &n1);
 
403
                gmove(&n1, &n2);
 
404
                gins(a, nr, &n2);
 
405
                gmove(&n2, res);
 
406
                regfree(&n2);
 
407
                mfree(&n1);
 
408
        } else if(nl->ullman >= nr->ullman) {
377
409
                tempname(&nt, nl->type);
378
410
                cgen(nl, &nt);
379
411
                mgen(nr, &n2, N);
401
433
        gins(a, N, &n1);
402
434
        gmove(&n1, res);
403
435
        return;
404
 
 
405
 
flt:    // floating-point.  387 (not SSE2) to interoperate with 8c
406
 
        nodreg(&f0, nl->type, D_F0);
407
 
        nodreg(&f1, n->type, D_F0+1);
408
 
        if(nr != N)
409
 
                goto flt2;
410
 
 
411
 
        // unary
412
 
        cgen(nl, &f0);
413
 
        if(n->op != OCONV && n->op != OPLUS)
414
 
                gins(foptoas(n->op, n->type, 0), N, N);
415
 
        gmove(&f0, res);
416
 
        return;
417
 
 
418
 
flt2:   // binary
419
 
        if(nl->ullman >= nr->ullman) {
420
 
                cgen(nl, &f0);
421
 
                if(nr->addable)
422
 
                        gins(foptoas(n->op, n->type, 0), nr, &f0);
423
 
                else {
424
 
                        cgen(nr, &f0);
425
 
                        gins(foptoas(n->op, n->type, Fpop), &f0, &f1);
426
 
                }
427
 
        } else {
428
 
                cgen(nr, &f0);
429
 
                if(nl->addable)
430
 
                        gins(foptoas(n->op, n->type, Frev), nl, &f0);
431
 
                else {
432
 
                        cgen(nl, &f0);
433
 
                        gins(foptoas(n->op, n->type, Frev|Fpop), &f0, &f1);
434
 
                }
435
 
        }
436
 
        gmove(&f0, res);
437
 
        return;
438
436
}
439
437
 
440
438
/*
441
 
 * generate array index into res.
442
 
 * n might be any size; res is 32-bit.
 
439
 * generate an addressable node in res, containing the value of n.
 
440
 * n is an array index, and might be any size; res width is <= 32-bit.
443
441
 * returns Prog* to patch to panic call.
444
442
 */
445
 
Prog*
446
 
cgenindex(Node *n, Node *res)
 
443
static Prog*
 
444
igenindex(Node *n, Node *res, int bounded)
447
445
{
448
446
        Node tmp, lo, hi, zero;
449
447
 
450
448
        if(!is64(n->type)) {
451
 
                cgen(n, res);
 
449
                if(n->addable) {
 
450
                        // nothing to do.
 
451
                        *res = *n;
 
452
                } else {
 
453
                        tempname(res, types[TUINT32]);
 
454
                        cgen(n, res);
 
455
                }
452
456
                return nil;
453
457
        }
454
458
 
455
459
        tempname(&tmp, types[TINT64]);
456
460
        cgen(n, &tmp);
457
461
        split64(&tmp, &lo, &hi);
 
462
        tempname(res, types[TUINT32]);
458
463
        gmove(&lo, res);
459
 
        if(debug['B']) {
 
464
        if(bounded) {
460
465
                splitclean();
461
466
                return nil;
462
467
        }
463
468
        nodconst(&zero, types[TINT32], 0);
464
469
        gins(ACMPL, &hi, &zero);
465
470
        splitclean();
466
 
        return gbranch(AJNE, T);
 
471
        return gbranch(AJNE, T, +1);
467
472
}
468
473
                
469
474
/*
474
479
agen(Node *n, Node *res)
475
480
{
476
481
        Node *nl, *nr;
477
 
        Node n1, n2, n3, n4, tmp;
 
482
        Node n1, n2, n3, n4, tmp, nlen;
478
483
        Type *t;
479
484
        uint32 w;
480
485
        uint64 v;
481
486
        Prog *p1, *p2;
 
487
        int bounded;
482
488
 
483
489
        if(debug['g']) {
484
490
                dump("\nagen-res", res);
490
496
        while(n->op == OCONVNOP)
491
497
                n = n->left;
492
498
 
 
499
        if(isconst(n, CTNIL) && n->type->width > widthptr) {
 
500
                // Use of a nil interface or nil slice.
 
501
                // Create a temporary we can take the address of and read.
 
502
                // The generated code is just going to panic, so it need not
 
503
                // be terribly efficient. See issue 3670.
 
504
                tempname(&n1, n->type);
 
505
                clearfat(&n1);
 
506
                regalloc(&n2, types[tptr], res);
 
507
                gins(ALEAL, &n1, &n2);
 
508
                gmove(&n2, res);
 
509
                regfree(&n2);
 
510
                return;
 
511
        }
 
512
                
493
513
        // addressable var is easy
494
514
        if(n->addable) {
495
515
                if(n->op == OREGISTER)
524
544
                cgen_aret(n, res);
525
545
                break;
526
546
 
 
547
        case OSLICE:
 
548
        case OSLICEARR:
 
549
        case OSLICESTR:
 
550
                tempname(&n1, n->type);
 
551
                cgen_slice(n, &n1);
 
552
                agen(&n1, res);
 
553
                break;
 
554
 
 
555
        case OEFACE:
 
556
                tempname(&n1, n->type);
 
557
                cgen_eface(n, &n1);
 
558
                agen(&n1, res);
 
559
                break;
 
560
 
527
561
        case OINDEX:
528
562
                p2 = nil;  // to be patched to panicindex.
529
563
                w = n->type->width;
 
564
                bounded = debug['B'] || n->bounded;
530
565
                if(nr->addable) {
531
 
                        if(!isconst(nr, CTINT))
532
 
                                tempname(&tmp, types[TINT32]);
 
566
                        // Generate &nl first, and move nr into register.
533
567
                        if(!isconst(nl, CTSTR))
534
 
                                agenr(nl, &n3, res);
 
568
                                igen(nl, &n3, res);
535
569
                        if(!isconst(nr, CTINT)) {
536
 
                                p2 = cgenindex(nr, &tmp);
 
570
                                p2 = igenindex(nr, &tmp, bounded);
537
571
                                regalloc(&n1, tmp.type, N);
538
572
                                gmove(&tmp, &n1);
539
573
                        }
540
574
                } else if(nl->addable) {
 
575
                        // Generate nr first, and move &nl into register.
541
576
                        if(!isconst(nr, CTINT)) {
542
 
                                tempname(&tmp, types[TINT32]);
543
 
                                p2 = cgenindex(nr, &tmp);
 
577
                                p2 = igenindex(nr, &tmp, bounded);
544
578
                                regalloc(&n1, tmp.type, N);
545
579
                                gmove(&tmp, &n1);
546
580
                        }
547
 
                        if(!isconst(nl, CTSTR)) {
548
 
                                regalloc(&n3, types[tptr], res);
549
 
                                agen(nl, &n3);
550
 
                        }
 
581
                        if(!isconst(nl, CTSTR))
 
582
                                igen(nl, &n3, res);
551
583
                } else {
552
 
                        tempname(&tmp, types[TINT32]);
553
 
                        p2 = cgenindex(nr, &tmp);
 
584
                        p2 = igenindex(nr, &tmp, bounded);
554
585
                        nr = &tmp;
555
586
                        if(!isconst(nl, CTSTR))
556
 
                                agenr(nl, &n3, res);
 
587
                                igen(nl, &n3, res);
557
588
                        regalloc(&n1, tmp.type, N);
558
589
                        gins(optoas(OAS, tmp.type), &tmp, &n1);
559
590
                }
560
591
 
561
 
                // &a is in &n3 (allocated in res)
562
 
                // i is in &n1 (if not constant)
 
592
                // For fixed array we really want the pointer in n3.
 
593
                if(isfixedarray(nl->type)) {
 
594
                        regalloc(&n2, types[tptr], &n3);
 
595
                        agen(&n3, &n2);
 
596
                        regfree(&n3);
 
597
                        n3 = n2;
 
598
                }
 
599
 
 
600
                // &a[0] is in n3 (allocated in res)
 
601
                // i is in n1 (if not constant)
 
602
                // len(a) is in nlen (if needed)
563
603
                // w is width
564
604
 
565
605
                // explicit check for nil if array is large enough
566
606
                // that we might derive too big a pointer.
567
607
                if(isfixedarray(nl->type) && nl->type->width >= unmappedzero) {
568
 
                        regalloc(&n4, types[tptr], &n3);
569
 
                        gmove(&n3, &n4);
 
608
                        n4 = n3;
570
609
                        n4.op = OINDREG;
571
610
                        n4.type = types[TUINT8];
572
611
                        n4.xoffset = 0;
573
612
                        gins(ATESTB, nodintconst(0), &n4);
574
 
                        regfree(&n4);
575
613
                }
576
614
 
577
615
                // constant index
578
616
                if(isconst(nr, CTINT)) {
579
617
                        if(isconst(nl, CTSTR))
580
 
                                fatal("constant string constant index");
 
618
                                fatal("constant string constant index");  // front end should handle
581
619
                        v = mpgetfix(nr->val.u.xval);
582
620
                        if(isslice(nl->type) || nl->type->etype == TSTRING) {
583
 
                                if(!debug['B'] && !n->etype) {
584
 
                                        n1 = n3;
585
 
                                        n1.op = OINDREG;
586
 
                                        n1.type = types[tptr];
587
 
                                        n1.xoffset = Array_nel;
 
621
                                if(!debug['B'] && !n->bounded) {
 
622
                                        nlen = n3;
 
623
                                        nlen.type = types[TUINT32];
 
624
                                        nlen.xoffset += Array_nel;
588
625
                                        nodconst(&n2, types[TUINT32], v);
589
 
                                        gins(optoas(OCMP, types[TUINT32]), &n1, &n2);
590
 
                                        p1 = gbranch(optoas(OGT, types[TUINT32]), T);
591
 
                                        ginscall(panicindex, 0);
 
626
                                        gins(optoas(OCMP, types[TUINT32]), &nlen, &n2);
 
627
                                        p1 = gbranch(optoas(OGT, types[TUINT32]), T, +1);
 
628
                                        ginscall(panicindex, -1);
592
629
                                        patch(p1, pc);
593
630
                                }
594
 
 
595
 
                                n1 = n3;
596
 
                                n1.op = OINDREG;
597
 
                                n1.type = types[tptr];
598
 
                                n1.xoffset = Array_array;
599
 
                                gmove(&n1, &n3);
600
631
                        }
601
632
 
 
633
                        // Load base pointer in n2 = n3.
 
634
                        regalloc(&n2, types[tptr], &n3);
 
635
                        n3.type = types[tptr];
 
636
                        n3.xoffset += Array_array;
 
637
                        gmove(&n3, &n2);
 
638
                        regfree(&n3);
602
639
                        if (v*w != 0) {
603
 
                                nodconst(&n2, types[tptr], v*w);
604
 
                                gins(optoas(OADD, types[tptr]), &n2, &n3);
 
640
                                nodconst(&n1, types[tptr], v*w);
 
641
                                gins(optoas(OADD, types[tptr]), &n1, &n2);
605
642
                        }
606
 
                        gmove(&n3, res);
607
 
                        regfree(&n3);
 
643
                        gmove(&n2, res);
 
644
                        regfree(&n2);
608
645
                        break;
609
646
                }
610
647
 
611
 
                regalloc(&n2, types[TINT32], &n1);                      // i
 
648
                // i is in register n1, extend to 32 bits.
 
649
                t = types[TUINT32];
 
650
                if(issigned[n1.type->etype])
 
651
                        t = types[TINT32];
 
652
 
 
653
                regalloc(&n2, t, &n1);                  // i
612
654
                gmove(&n1, &n2);
613
655
                regfree(&n1);
614
656
 
615
 
                if(!debug['B'] && !n->etype) {
 
657
                if(!debug['B'] && !n->bounded) {
616
658
                        // check bounds
617
 
                        if(isconst(nl, CTSTR))
618
 
                                nodconst(&n1, types[TUINT32], nl->val.u.sval->len);
619
 
                        else if(isslice(nl->type) || nl->type->etype == TSTRING) {
620
 
                                n1 = n3;
621
 
                                n1.op = OINDREG;
622
 
                                n1.type = types[tptr];
623
 
                                n1.xoffset = Array_nel;
624
 
                        } else
625
 
                                nodconst(&n1, types[TUINT32], nl->type->bound);
626
 
                        gins(optoas(OCMP, types[TUINT32]), &n2, &n1);
627
 
                        p1 = gbranch(optoas(OLT, types[TUINT32]), T);
 
659
                        t = types[TUINT32];
 
660
                        if(isconst(nl, CTSTR)) {
 
661
                                nodconst(&nlen, t, nl->val.u.sval->len);
 
662
                        } else if(isslice(nl->type) || nl->type->etype == TSTRING) {
 
663
                                nlen = n3;
 
664
                                nlen.type = t;
 
665
                                nlen.xoffset += Array_nel;
 
666
                        } else {
 
667
                                nodconst(&nlen, t, nl->type->bound);
 
668
                        }
 
669
                        gins(optoas(OCMP, t), &n2, &nlen);
 
670
                        p1 = gbranch(optoas(OLT, t), T, +1);
628
671
                        if(p2)
629
672
                                patch(p2, pc);
630
 
                        ginscall(panicindex, 0);
 
673
                        ginscall(panicindex, -1);
631
674
                        patch(p1, pc);
632
675
                }
633
 
                
 
676
 
634
677
                if(isconst(nl, CTSTR)) {
635
678
                        regalloc(&n3, types[tptr], res);
636
679
                        p1 = gins(ALEAL, N, &n3);
640
683
                        goto indexdone;
641
684
                }
642
685
 
 
686
                // Load base pointer in n3.
 
687
                regalloc(&tmp, types[tptr], &n3);
643
688
                if(isslice(nl->type) || nl->type->etype == TSTRING) {
644
 
                        n1 = n3;
645
 
                        n1.op = OINDREG;
646
 
                        n1.type = types[tptr];
647
 
                        n1.xoffset = Array_array;
648
 
                        gmove(&n1, &n3);
 
689
                        n3.type = types[tptr];
 
690
                        n3.xoffset += Array_array;
 
691
                        gmove(&n3, &tmp);
649
692
                }
 
693
                regfree(&n3);
 
694
                n3 = tmp;
650
695
 
651
696
                if(w == 0) {
652
697
                        // nothing to do
653
698
                } else if(w == 1 || w == 2 || w == 4 || w == 8) {
 
699
                        // LEAL (n3)(n2*w), n3
654
700
                        p1 = gins(ALEAL, &n2, &n3);
655
701
                        p1->from.scale = w;
656
702
                        p1->from.index = p1->from.type;
657
703
                        p1->from.type = p1->to.type + D_INDIR;
658
704
                } else {
659
 
                        nodconst(&n1, types[TUINT32], w);
660
 
                        gins(optoas(OMUL, types[TUINT32]), &n1, &n2);
 
705
                        nodconst(&tmp, types[TUINT32], w);
 
706
                        gins(optoas(OMUL, types[TUINT32]), &tmp, &n2);
661
707
                        gins(optoas(OADD, types[tptr]), &n2, &n3);
662
708
                }
663
709
 
693
739
 
694
740
        case ODOT:
695
741
                agen(nl, res);
 
742
                // explicit check for nil if struct is large enough
 
743
                // that we might derive too big a pointer.  If the left node
 
744
                // was ODOT we have already done the nil check.
 
745
                if(nl->op != ODOT)
 
746
                if(nl->type->width >= unmappedzero) {
 
747
                        regalloc(&n1, types[tptr], res);
 
748
                        gmove(res, &n1);
 
749
                        n1.op = OINDREG;
 
750
                        n1.type = types[TUINT8];
 
751
                        n1.xoffset = 0;
 
752
                        gins(ATESTB, nodintconst(0), &n1);
 
753
                        regfree(&n1);
 
754
                }
696
755
                if(n->xoffset != 0) {
697
756
                        nodconst(&n1, types[tptr], n->xoffset);
698
757
                        gins(optoas(OADD, types[tptr]), &n1, res);
704
763
                if(!isptr[t->etype])
705
764
                        fatal("agen: not ptr %N", n);
706
765
                cgen(nl, res);
 
766
                // explicit check for nil if struct is large enough
 
767
                // that we might derive too big a pointer.
 
768
                if(nl->type->type->width >= unmappedzero) {
 
769
                        regalloc(&n1, types[tptr], res);
 
770
                        gmove(res, &n1);
 
771
                        n1.op = OINDREG;
 
772
                        n1.type = types[TUINT8];
 
773
                        n1.xoffset = 0;
 
774
                        gins(ATESTB, nodintconst(0), &n1);
 
775
                        regfree(&n1);
 
776
                }
707
777
                if(n->xoffset != 0) {
708
 
                        // explicit check for nil if struct is large enough
709
 
                        // that we might derive too big a pointer.
710
 
                        if(nl->type->type->width >= unmappedzero) {
711
 
                                regalloc(&n1, types[tptr], res);
712
 
                                gmove(res, &n1);
713
 
                                n1.op = OINDREG;
714
 
                                n1.type = types[TUINT8];
715
 
                                n1.xoffset = 0;
716
 
                                gins(ATESTB, nodintconst(0), &n1);
717
 
                                regfree(&n1);
718
 
                        }
719
778
                        nodconst(&n1, types[tptr], n->xoffset);
720
779
                        gins(optoas(OADD, types[tptr]), &n1, res);
721
780
                }
734
793
void
735
794
igen(Node *n, Node *a, Node *res)
736
795
{
737
 
        Node n1;
738
796
        Type *fp;
739
797
        Iter flist;
740
 
  
 
798
        Node n1;
 
799
 
 
800
        if(debug['g']) {
 
801
                dump("\nigen-n", n);
 
802
        }
741
803
        switch(n->op) {
742
804
        case ONAME:
743
805
                if((n->class&PHEAP) || n->class == PPARAMREF)
744
806
                        break;
745
807
                *a = *n;
746
808
                return;
747
 
 
 
809
 
 
810
        case OINDREG:
 
811
                // Increase the refcount of the register so that igen's caller
 
812
                // has to call regfree.
 
813
                if(n->val.u.reg != D_SP)
 
814
                        reg[n->val.u.reg]++;
 
815
                *a = *n;
 
816
                return;
 
817
 
 
818
        case ODOT:
 
819
                igen(n->left, a, res);
 
820
                a->xoffset += n->xoffset;
 
821
                a->type = n->type;
 
822
                return;
 
823
 
 
824
        case ODOTPTR:
 
825
                switch(n->left->op) {
 
826
                case ODOT:
 
827
                case ODOTPTR:
 
828
                case OCALLFUNC:
 
829
                case OCALLMETH:
 
830
                case OCALLINTER:
 
831
                        // igen-able nodes.
 
832
                        igen(n->left, &n1, res);
 
833
                        regalloc(a, types[tptr], &n1);
 
834
                        gmove(&n1, a);
 
835
                        regfree(&n1);
 
836
                        break;
 
837
                default:
 
838
                        regalloc(a, types[tptr], res);
 
839
                        cgen(n->left, a);
 
840
                }
 
841
                // explicit check for nil if struct is large enough
 
842
                // that we might derive too big a pointer.
 
843
                if(n->left->type->type->width >= unmappedzero) {
 
844
                        n1 = *a;
 
845
                        n1.op = OINDREG;
 
846
                        n1.type = types[TUINT8];
 
847
                        n1.xoffset = 0;
 
848
                        gins(ATESTB, nodintconst(0), &n1);
 
849
                }
 
850
                a->op = OINDREG;
 
851
                a->xoffset += n->xoffset;
 
852
                a->type = n->type;
 
853
                return;
 
854
 
748
855
        case OCALLFUNC:
 
856
        case OCALLMETH:
 
857
        case OCALLINTER:
 
858
                switch(n->op) {
 
859
                case OCALLFUNC:
 
860
                        cgen_call(n, 0);
 
861
                        break;
 
862
                case OCALLMETH:
 
863
                        cgen_callmeth(n, 0);
 
864
                        break;
 
865
                case OCALLINTER:
 
866
                        cgen_callinter(n, N, 0);
 
867
                        break;
 
868
                }
749
869
                fp = structfirst(&flist, getoutarg(n->left->type));
750
 
                cgen_call(n, 0);
751
870
                memset(a, 0, sizeof *a);
752
871
                a->op = OINDREG;
753
872
                a->val.u.reg = D_SP;
771
890
}
772
891
 
773
892
/*
774
 
 * generate:
775
 
 *      newreg = &n;
776
 
 *
777
 
 * caller must regfree(a).
778
 
 */
779
 
void
780
 
agenr(Node *n, Node *a, Node *res)
781
 
{
782
 
        Node n1;
783
 
 
784
 
        tempname(&n1, types[tptr]);
785
 
        agen(n, &n1);
786
 
        regalloc(a, types[tptr], res);
787
 
        gmove(&n1, a);
788
 
}
789
 
 
790
 
/*
791
893
 * branch gen
792
894
 *      if(n == true) goto to;
793
895
 */
794
896
void
795
 
bgen(Node *n, int true, Prog *to)
 
897
bgen(Node *n, int true, int likely, Prog *to)
796
898
{
797
899
        int et, a;
798
900
        Node *nl, *nr, *r;
799
 
        Node n1, n2, tmp, t1, t2, ax;
800
 
        NodeList *ll;
 
901
        Node n1, n2, tmp;
801
902
        Prog *p1, *p2;
802
903
 
803
904
        if(debug['g']) {
822
923
                patch(gins(AEND, N, N), to);
823
924
                return;
824
925
        }
 
926
        nl = n->left;
825
927
        nr = N;
826
928
 
 
929
        if(nl != N && isfloat[nl->type->etype]) {
 
930
                bgen_float(n, true, likely, to);
 
931
                return;
 
932
        }
 
933
 
827
934
        switch(n->op) {
828
935
        default:
829
936
        def:
834
941
                a = AJNE;
835
942
                if(!true)
836
943
                        a = AJEQ;
837
 
                patch(gbranch(a, n->type), to);
 
944
                patch(gbranch(a, n->type, likely), to);
838
945
                regfree(&n1);
839
946
                return;
840
947
 
841
948
        case OLITERAL:
842
949
                // need to ask if it is bool?
843
950
                if(!true == !n->val.u.bval)
844
 
                        patch(gbranch(AJMP, T), to);
 
951
                        patch(gbranch(AJMP, T, 0), to);
845
952
                return;
846
953
 
847
954
        case ONAME:
852
959
                a = AJNE;
853
960
                if(!true)
854
961
                        a = AJEQ;
855
 
                patch(gbranch(a, n->type), to);
 
962
                patch(gbranch(a, n->type, likely), to);
856
963
                return;
857
964
 
858
965
        case OANDAND:
860
967
                        goto caseor;
861
968
 
862
969
        caseand:
863
 
                p1 = gbranch(AJMP, T);
864
 
                p2 = gbranch(AJMP, T);
 
970
                p1 = gbranch(AJMP, T, 0);
 
971
                p2 = gbranch(AJMP, T, 0);
865
972
                patch(p1, pc);
866
 
                bgen(n->left, !true, p2);
867
 
                bgen(n->right, !true, p2);
868
 
                p1 = gbranch(AJMP, T);
 
973
                bgen(n->left, !true, -likely, p2);
 
974
                bgen(n->right, !true, -likely, p2);
 
975
                p1 = gbranch(AJMP, T, 0);
869
976
                patch(p1, to);
870
977
                patch(p2, pc);
871
978
                return;
875
982
                        goto caseand;
876
983
 
877
984
        caseor:
878
 
                bgen(n->left, true, to);
879
 
                bgen(n->right, true, to);
 
985
                bgen(n->left, true, likely, to);
 
986
                bgen(n->right, true, likely, to);
880
987
                return;
881
988
 
882
989
        case OEQ:
897
1004
 
898
1005
        switch(n->op) {
899
1006
        case ONOT:
900
 
                bgen(nl, !true, to);
 
1007
                bgen(nl, !true, likely, to);
901
1008
                break;
902
1009
 
903
1010
        case OEQ:
908
1015
        case OGE:
909
1016
                a = n->op;
910
1017
                if(!true) {
911
 
                        if(isfloat[nl->type->etype]) {
912
 
                                // brcom is not valid on floats when NaN is involved.
913
 
                                p1 = gbranch(AJMP, T);
914
 
                                p2 = gbranch(AJMP, T);
915
 
                                patch(p1, pc);
916
 
                                ll = n->ninit;  // avoid re-genning ninit
917
 
                                n->ninit = nil;
918
 
                                bgen(n, 1, p2);
919
 
                                n->ninit = ll;
920
 
                                patch(gbranch(AJMP, T), to);
921
 
                                patch(p2, pc);
922
 
                                break;
923
 
                        }                               
924
1018
                        a = brcom(a);
925
1019
                        true = !true;
926
1020
                }
936
1030
                if(isslice(nl->type)) {
937
1031
                        // front end should only leave cmp to literal nil
938
1032
                        if((a != OEQ && a != ONE) || nr->op != OLITERAL) {
939
 
                                yyerror("illegal array comparison");
 
1033
                                yyerror("illegal slice comparison");
940
1034
                                break;
941
1035
                        }
942
1036
                        a = optoas(a, types[tptr]);
943
 
                        regalloc(&n1, types[tptr], N);
944
 
                        agen(nl, &n1);
945
 
                        n2 = n1;
946
 
                        n2.op = OINDREG;
947
 
                        n2.xoffset = Array_array;
948
 
                        n2.type = types[tptr];
 
1037
                        igen(nl, &n1, N);
 
1038
                        n1.xoffset += Array_array;
 
1039
                        n1.type = types[tptr];
949
1040
                        nodconst(&tmp, types[tptr], 0);
950
 
                        gins(optoas(OCMP, types[tptr]), &n2, &tmp);
951
 
                        patch(gbranch(a, types[tptr]), to);
 
1041
                        gins(optoas(OCMP, types[tptr]), &n1, &tmp);
 
1042
                        patch(gbranch(a, types[tptr], likely), to);
952
1043
                        regfree(&n1);
953
1044
                        break;
954
1045
                }
960
1051
                                break;
961
1052
                        }
962
1053
                        a = optoas(a, types[tptr]);
963
 
                        regalloc(&n1, types[tptr], N);
964
 
                        agen(nl, &n1);
965
 
                        n2 = n1;
966
 
                        n2.op = OINDREG;
967
 
                        n2.xoffset = 0;
 
1054
                        igen(nl, &n1, N);
 
1055
                        n1.type = types[tptr];
968
1056
                        nodconst(&tmp, types[tptr], 0);
969
 
                        gins(optoas(OCMP, types[tptr]), &n2, &tmp);
970
 
                        patch(gbranch(a, types[tptr]), to);
 
1057
                        gins(optoas(OCMP, types[tptr]), &n1, &tmp);
 
1058
                        patch(gbranch(a, types[tptr], likely), to);
971
1059
                        regfree(&n1);
972
1060
                        break;
973
1061
                }
974
1062
 
975
 
                if(isfloat[nr->type->etype]) {
976
 
                        a = brrev(a);   // because the args are stacked
977
 
                        if(a == OGE || a == OGT) {
978
 
                                // only < and <= work right with NaN; reverse if needed
979
 
                                r = nr;
980
 
                                nr = nl;
981
 
                                nl = r;
982
 
                                a = brrev(a);
983
 
                        }
984
 
                        nodreg(&tmp, nr->type, D_F0);
985
 
                        nodreg(&n2, nr->type, D_F0 + 1);
986
 
                        nodreg(&ax, types[TUINT16], D_AX);
987
 
                        et = simsimtype(nr->type);
988
 
                        if(et == TFLOAT64) {
989
 
                                if(nl->ullman > nr->ullman) {
990
 
                                        cgen(nl, &tmp);
991
 
                                        cgen(nr, &tmp);
992
 
                                        gins(AFXCHD, &tmp, &n2);
993
 
                                } else {
994
 
                                        cgen(nr, &tmp);
995
 
                                        cgen(nl, &tmp);
996
 
                                }
997
 
                                gins(AFUCOMIP, &tmp, &n2);
998
 
                                gins(AFMOVDP, &tmp, &tmp);      // annoying pop but still better than STSW+SAHF
999
 
                        } else {
1000
 
                                // TODO(rsc): The moves back and forth to memory
1001
 
                                // here are for truncating the value to 32 bits.
1002
 
                                // This handles 32-bit comparison but presumably
1003
 
                                // all the other ops have the same problem.
1004
 
                                // We need to figure out what the right general
1005
 
                                // solution is, besides telling people to use float64.
1006
 
                                tempname(&t1, types[TFLOAT32]);
1007
 
                                tempname(&t2, types[TFLOAT32]);
1008
 
                                cgen(nr, &t1);
1009
 
                                cgen(nl, &t2);
1010
 
                                gmove(&t2, &tmp);
1011
 
                                gins(AFCOMFP, &t1, &tmp);
1012
 
                                gins(AFSTSW, N, &ax);
1013
 
                                gins(ASAHF, N, N);
1014
 
                        }
1015
 
                        if(a == OEQ) {
1016
 
                                // neither NE nor P
1017
 
                                p1 = gbranch(AJNE, T);
1018
 
                                p2 = gbranch(AJPS, T);
1019
 
                                patch(gbranch(AJMP, T), to);
1020
 
                                patch(p1, pc);
1021
 
                                patch(p2, pc);
1022
 
                        } else if(a == ONE) {
1023
 
                                // either NE or P
1024
 
                                patch(gbranch(AJNE, T), to);
1025
 
                                patch(gbranch(AJPS, T), to);
1026
 
                        } else
1027
 
                                patch(gbranch(optoas(a, nr->type), T), to);
1028
 
                        break;
1029
 
                }
1030
1063
                if(iscomplex[nl->type->etype]) {
1031
 
                        complexbool(a, nl, nr, true, to);
 
1064
                        complexbool(a, nl, nr, true, likely, to);
1032
1065
                        break;
1033
1066
                }
1034
1067
 
1035
1068
                if(is64(nr->type)) {
1036
 
                        if(!nl->addable) {
 
1069
                        if(!nl->addable || isconst(nl, CTINT)) {
1037
1070
                                tempname(&n1, nl->type);
1038
1071
                                cgen(nl, &n1);
1039
1072
                                nl = &n1;
1043
1076
                                cgen(nr, &n2);
1044
1077
                                nr = &n2;
1045
1078
                        }
1046
 
                        cmp64(nl, nr, a, to);
 
1079
                        cmp64(nl, nr, a, likely, to);
1047
1080
                        break;
1048
1081
                }
1049
1082
 
1050
 
                a = optoas(a, nr->type);
1051
 
 
1052
1083
                if(nr->ullman >= UINF) {
 
1084
                        if(!nl->addable) {
 
1085
                                tempname(&n1, nl->type);
 
1086
                                cgen(nl, &n1);
 
1087
                                nl = &n1;
 
1088
                        }
 
1089
                        if(!nr->addable) {
 
1090
                                tempname(&tmp, nr->type);
 
1091
                                cgen(nr, &tmp);
 
1092
                                nr = &tmp;
 
1093
                        }
 
1094
                        regalloc(&n2, nr->type, N);
 
1095
                        cgen(nr, &n2);
 
1096
                        nr = &n2;
 
1097
                        goto cmp;
 
1098
                }
 
1099
 
 
1100
                if(!nl->addable) {
1053
1101
                        tempname(&n1, nl->type);
 
1102
                        cgen(nl, &n1);
 
1103
                        nl = &n1;
 
1104
                }
 
1105
 
 
1106
                if(smallintconst(nr)) {
 
1107
                        gins(optoas(OCMP, nr->type), nl, nr);
 
1108
                        patch(gbranch(optoas(a, nr->type), nr->type, likely), to);
 
1109
                        break;
 
1110
                }
 
1111
 
 
1112
                if(!nr->addable) {
1054
1113
                        tempname(&tmp, nr->type);
1055
 
                        cgen(nl, &n1);
1056
1114
                        cgen(nr, &tmp);
1057
 
                        regalloc(&n2, nr->type, N);
1058
 
                        cgen(&tmp, &n2);
1059
 
                        goto cmp;
1060
 
                }
1061
 
 
1062
 
                tempname(&n1, nl->type);
1063
 
                cgen(nl, &n1);
1064
 
 
1065
 
                if(smallintconst(nr)) {
1066
 
                        gins(optoas(OCMP, nr->type), &n1, nr);
1067
 
                        patch(gbranch(a, nr->type), to);
1068
 
                        break;
1069
 
                }
1070
 
 
1071
 
                tempname(&tmp, nr->type);
1072
 
                cgen(nr, &tmp);
 
1115
                        nr = &tmp;
 
1116
                }
1073
1117
                regalloc(&n2, nr->type, N);
1074
 
                gmove(&tmp, &n2);
 
1118
                gmove(nr, &n2);
 
1119
                nr = &n2;
1075
1120
 
1076
1121
cmp:
1077
 
                gins(optoas(OCMP, nr->type), &n1, &n2);
1078
 
                patch(gbranch(a, nr->type), to);
1079
 
                regfree(&n2);
 
1122
                gins(optoas(OCMP, nr->type), nl, nr);
 
1123
                patch(gbranch(optoas(a, nr->type), nr->type, likely), to);
 
1124
 
 
1125
                if(nl->op == OREGISTER)
 
1126
                        regfree(nl);
 
1127
                regfree(nr);
1080
1128
                break;
1081
1129
        }
1082
1130
}
1164
1212
                return;
1165
1213
        }
1166
1214
 
 
1215
        // Avoid taking the address for simple enough types.
 
1216
        if(componentgen(n, res))
 
1217
                return;
 
1218
 
1167
1219
        // offset on the stack
1168
1220
        osrc = stkof(n);
1169
1221
        odst = stkof(res);
1247
1299
        }
1248
1300
}
1249
1301
 
 
1302
static int
 
1303
cadable(Node *n)
 
1304
{
 
1305
        if(!n->addable) {
 
1306
                // dont know how it happens,
 
1307
                // but it does
 
1308
                return 0;
 
1309
        }
 
1310
 
 
1311
        switch(n->op) {
 
1312
        case ONAME:
 
1313
                return 1;
 
1314
        }
 
1315
        return 0;
 
1316
}
 
1317
 
 
1318
/*
 
1319
 * copy a composite value by moving its individual components.
 
1320
 * Slices, strings and interfaces are supported.
 
1321
 * nr is N when assigning a zero value.
 
1322
 * return 1 if can do, 0 if cant.
 
1323
 */
 
1324
int
 
1325
componentgen(Node *nr, Node *nl)
 
1326
{
 
1327
        Node nodl, nodr;
 
1328
        int freel, freer;
 
1329
 
 
1330
        freel = 0;
 
1331
        freer = 0;
 
1332
 
 
1333
        switch(nl->type->etype) {
 
1334
        default:
 
1335
                goto no;
 
1336
 
 
1337
        case TARRAY:
 
1338
                if(!isslice(nl->type))
 
1339
                        goto no;
 
1340
        case TSTRING:
 
1341
        case TINTER:
 
1342
                break;
 
1343
        }
 
1344
 
 
1345
        nodl = *nl;
 
1346
        if(!cadable(nl)) {
 
1347
                if(nr == N || !cadable(nr))
 
1348
                        goto no;
 
1349
                igen(nl, &nodl, N);
 
1350
                freel = 1;
 
1351
        }
 
1352
 
 
1353
        if(nr != N) {
 
1354
                nodr = *nr;
 
1355
                if(!cadable(nr)) {
 
1356
                        igen(nr, &nodr, N);
 
1357
                        freer = 1;
 
1358
                }
 
1359
        }
 
1360
 
 
1361
        switch(nl->type->etype) {
 
1362
        case TARRAY:
 
1363
                nodl.xoffset += Array_array;
 
1364
                nodl.type = ptrto(nl->type->type);
 
1365
 
 
1366
                if(nr != N) {
 
1367
                        nodr.xoffset += Array_array;
 
1368
                        nodr.type = nodl.type;
 
1369
                } else
 
1370
                        nodconst(&nodr, nodl.type, 0);
 
1371
                gmove(&nodr, &nodl);
 
1372
 
 
1373
                nodl.xoffset += Array_nel-Array_array;
 
1374
                nodl.type = types[TUINT32];
 
1375
 
 
1376
                if(nr != N) {
 
1377
                        nodr.xoffset += Array_nel-Array_array;
 
1378
                        nodr.type = nodl.type;
 
1379
                } else
 
1380
                        nodconst(&nodr, nodl.type, 0);
 
1381
                gmove(&nodr, &nodl);
 
1382
 
 
1383
                nodl.xoffset += Array_cap-Array_nel;
 
1384
                nodl.type = types[TUINT32];
 
1385
 
 
1386
                if(nr != N) {
 
1387
                        nodr.xoffset += Array_cap-Array_nel;
 
1388
                        nodr.type = nodl.type;
 
1389
                } else
 
1390
                        nodconst(&nodr, nodl.type, 0);
 
1391
                gmove(&nodr, &nodl);
 
1392
 
 
1393
                goto yes;
 
1394
 
 
1395
        case TSTRING:
 
1396
                nodl.xoffset += Array_array;
 
1397
                nodl.type = ptrto(types[TUINT8]);
 
1398
 
 
1399
                if(nr != N) {
 
1400
                        nodr.xoffset += Array_array;
 
1401
                        nodr.type = nodl.type;
 
1402
                } else
 
1403
                        nodconst(&nodr, nodl.type, 0);
 
1404
                gmove(&nodr, &nodl);
 
1405
 
 
1406
                nodl.xoffset += Array_nel-Array_array;
 
1407
                nodl.type = types[TUINT32];
 
1408
 
 
1409
                if(nr != N) {
 
1410
                        nodr.xoffset += Array_nel-Array_array;
 
1411
                        nodr.type = nodl.type;
 
1412
                } else
 
1413
                        nodconst(&nodr, nodl.type, 0);
 
1414
                gmove(&nodr, &nodl);
 
1415
 
 
1416
                goto yes;
 
1417
 
 
1418
        case TINTER:
 
1419
                nodl.xoffset += Array_array;
 
1420
                nodl.type = ptrto(types[TUINT8]);
 
1421
 
 
1422
                if(nr != N) {
 
1423
                        nodr.xoffset += Array_array;
 
1424
                        nodr.type = nodl.type;
 
1425
                } else
 
1426
                        nodconst(&nodr, nodl.type, 0);
 
1427
                gmove(&nodr, &nodl);
 
1428
 
 
1429
                nodl.xoffset += Array_nel-Array_array;
 
1430
                nodl.type = ptrto(types[TUINT8]);
 
1431
 
 
1432
                if(nr != N) {
 
1433
                        nodr.xoffset += Array_nel-Array_array;
 
1434
                        nodr.type = nodl.type;
 
1435
                } else
 
1436
                        nodconst(&nodr, nodl.type, 0);
 
1437
                gmove(&nodr, &nodl);
 
1438
 
 
1439
                goto yes;
 
1440
        }
 
1441
 
 
1442
no:
 
1443
        if(freer)
 
1444
                regfree(&nodr);
 
1445
        if(freel)
 
1446
                regfree(&nodl);
 
1447
        return 0;
 
1448
 
 
1449
yes:
 
1450
        if(freer)
 
1451
                regfree(&nodr);
 
1452
        if(freel)
 
1453
                regfree(&nodl);
 
1454
        return 1;
 
1455
}