summaryrefslogtreecommitdiff
path: root/src/cmd
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2014-11-20 11:30:43 -0500
committerRuss Cox <rsc@golang.org>2014-11-20 11:30:43 -0500
commit1ac4b754e58ba42944de03808fb96210b065e4c4 (patch)
tree7e903d8afe4ac7dc3f7a19cce1765d48d44ec5aa /src/cmd
parent76fd55b06c1f4f9d5b5981810d4a723f4bf9952e (diff)
parent4556dad5c76734a7966c6d0c23f9dec4de7196a6 (diff)
downloadgo-1ac4b754e58ba42944de03808fb96210b065e4c4.tar.gz
[dev.cc] all: merge dev.power64 (f57928630b36) into dev.cc
This will be the last dev.power64 merge; we'll finish on dev.cc. TBR=austin CC=golang-codereviews https://codereview.appspot.com/175420043
Diffstat (limited to 'src/cmd')
-rw-r--r--src/cmd/5c/Makefile5
-rw-r--r--src/cmd/5c/cgen.c1213
-rw-r--r--src/cmd/5c/doc.go16
-rw-r--r--src/cmd/5c/gc.h333
-rw-r--r--src/cmd/5c/list.c39
-rw-r--r--src/cmd/5c/mul.c640
-rw-r--r--src/cmd/5c/peep.c1478
-rw-r--r--src/cmd/5c/reg.c1210
-rw-r--r--src/cmd/5c/sgen.c265
-rw-r--r--src/cmd/5c/swt.c461
-rw-r--r--src/cmd/5c/txt.c1361
-rw-r--r--src/cmd/5g/reg.c2
-rw-r--r--src/cmd/6c/Makefile5
-rw-r--r--src/cmd/6c/cgen.c2046
-rw-r--r--src/cmd/6c/div.c236
-rw-r--r--src/cmd/6c/doc.go16
-rw-r--r--src/cmd/6c/gc.h359
-rw-r--r--src/cmd/6c/list.c38
-rw-r--r--src/cmd/6c/machcap.c107
-rw-r--r--src/cmd/6c/mul.c458
-rw-r--r--src/cmd/6c/peep.c902
-rw-r--r--src/cmd/6c/reg.c1523
-rw-r--r--src/cmd/6c/sgen.c483
-rw-r--r--src/cmd/6c/swt.c353
-rw-r--r--src/cmd/6c/txt.c1674
-rw-r--r--src/cmd/8c/Makefile5
-rw-r--r--src/cmd/8c/cgen.c1939
-rw-r--r--src/cmd/8c/cgen64.c2657
-rw-r--r--src/cmd/8c/div.c236
-rw-r--r--src/cmd/8c/doc.go16
-rw-r--r--src/cmd/8c/gc.h364
-rw-r--r--src/cmd/8c/list.c38
-rw-r--r--src/cmd/8c/machcap.c116
-rw-r--r--src/cmd/8c/mul.c458
-rw-r--r--src/cmd/8c/peep.c807
-rw-r--r--src/cmd/8c/reg.c1438
-rw-r--r--src/cmd/8c/sgen.c483
-rw-r--r--src/cmd/8c/swt.c341
-rw-r--r--src/cmd/8c/txt.c1537
-rw-r--r--src/cmd/8g/reg.c10
-rw-r--r--src/cmd/9a/lex.c3
-rw-r--r--src/cmd/9c/Makefile5
-rw-r--r--src/cmd/9c/Notes14
-rw-r--r--src/cmd/9c/cgen.c1147
-rw-r--r--src/cmd/9c/doc.go17
-rw-r--r--src/cmd/9c/gc.h350
-rw-r--r--src/cmd/9c/list.c37
-rw-r--r--src/cmd/9c/machcap.c105
-rw-r--r--src/cmd/9c/mul.c638
-rw-r--r--src/cmd/9c/peep.c1076
-rw-r--r--src/cmd/9c/reg.c1163
-rw-r--r--src/cmd/9c/sgen.c291
-rw-r--r--src/cmd/9c/swt.c407
-rw-r--r--src/cmd/9c/txt.c1537
-rw-r--r--src/cmd/cc/Makefile10
-rw-r--r--src/cmd/cc/acid.c344
-rw-r--r--src/cmd/cc/bits.c120
-rw-r--r--src/cmd/cc/cc.h835
-rw-r--r--src/cmd/cc/cc.y1220
-rw-r--r--src/cmd/cc/com.c1384
-rw-r--r--src/cmd/cc/com64.c644
-rw-r--r--src/cmd/cc/dcl.c1707
-rw-r--r--src/cmd/cc/doc.go13
-rw-r--r--src/cmd/cc/dpchk.c793
-rw-r--r--src/cmd/cc/funct.c431
-rw-r--r--src/cmd/cc/godefs.c367
-rw-r--r--src/cmd/cc/lex.c1593
-rw-r--r--src/cmd/cc/mac.c34
-rw-r--r--src/cmd/cc/omachcap.c40
-rw-r--r--src/cmd/cc/pgen.c622
-rw-r--r--src/cmd/cc/pswt.c140
-rw-r--r--src/cmd/cc/scon.c640
-rw-r--r--src/cmd/cc/sub.c2068
-rw-r--r--src/cmd/cc/y.tab.c3822
-rw-r--r--src/cmd/cc/y.tab.h230
-rw-r--r--src/cmd/cgo/main.go1
-rw-r--r--src/cmd/cgo/out.go154
-rw-r--r--src/cmd/dist/build.c162
-rw-r--r--src/cmd/dist/buildruntime.c366
-rw-r--r--src/cmd/gc/export.c41
-rw-r--r--src/cmd/gc/go.h7
-rw-r--r--src/cmd/gc/lex.c204
-rw-r--r--src/cmd/gc/obj.c12
-rw-r--r--src/cmd/gc/plive.c19
-rw-r--r--src/cmd/gc/reflect.c14
-rw-r--r--src/cmd/gc/subr.c46
-rw-r--r--src/cmd/gc/walk.c1
-rw-r--r--src/cmd/go/build.go46
-rw-r--r--src/cmd/go/doc.go2
-rw-r--r--src/cmd/go/pkg.go24
-rwxr-xr-xsrc/cmd/go/test.bash18
-rw-r--r--src/cmd/go/tool.go2
-rw-r--r--src/cmd/go/vet.go2
-rw-r--r--src/cmd/internal/objfile/disasm.go248
-rw-r--r--src/cmd/internal/objfile/objfile.go14
-rw-r--r--src/cmd/objdump/main.go242
-rw-r--r--src/cmd/objdump/objdump_test.go102
-rw-r--r--src/cmd/pprof/README8
-rw-r--r--src/cmd/pprof/doc.go12
-rw-r--r--src/cmd/pprof/pprof.go41
100 files changed, 806 insertions, 50497 deletions
diff --git a/src/cmd/5c/Makefile b/src/cmd/5c/Makefile
deleted file mode 100644
index 3f528d751..000000000
--- a/src/cmd/5c/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-# Copyright 2012 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../Make.dist
diff --git a/src/cmd/5c/cgen.c b/src/cmd/5c/cgen.c
deleted file mode 100644
index 5a049ae62..000000000
--- a/src/cmd/5c/cgen.c
+++ /dev/null
@@ -1,1213 +0,0 @@
-// Inferno utils/5c/cgen.c
-// http://code.google.com/p/inferno-os/source/browse/utils/5c/cgen.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-#include "../../runtime/funcdata.h"
-
-void
-_cgen(Node *n, Node *nn, int inrel)
-{
- Node *l, *r;
- Prog *p1;
- Node nod, nod1, nod2, nod3, nod4;
- int o, t;
- int32 v, curs;
-
- if(debug['g']) {
- prtree(nn, "cgen lhs");
- prtree(n, "cgen");
- }
- if(n == Z || n->type == T)
- return;
- if(typesuv[n->type->etype] && (n->op != OFUNC || nn != Z)) {
- sugen(n, nn, n->type->width);
- return;
- }
- l = n->left;
- r = n->right;
- o = n->op;
- if(n->addable >= INDEXED) {
- if(nn == Z) {
- switch(o) {
- default:
- nullwarn(Z, Z);
- break;
- case OINDEX:
- nullwarn(l, r);
- break;
- }
- return;
- }
- gmove(n, nn);
- return;
- }
- curs = cursafe;
-
- if(n->complex >= FNX)
- if(l->complex >= FNX)
- if(r != Z && r->complex >= FNX)
- switch(o) {
- default:
- regret(&nod, r, 0, 0);
- cgen(r, &nod);
-
- regsalloc(&nod1, r);
- gopcode(OAS, &nod, Z, &nod1);
-
- regfree(&nod);
- nod = *n;
- nod.right = &nod1;
- cgen(&nod, nn);
- return;
-
- case OFUNC:
- case OCOMMA:
- case OANDAND:
- case OOROR:
- case OCOND:
- case ODOT:
- break;
- }
-
- switch(o) {
- default:
- diag(n, "unknown op in cgen: %O", o);
- break;
-
- case OAS:
- if(l->op == OBIT)
- goto bitas;
- if(l->addable >= INDEXED && l->complex < FNX) {
- if(nn != Z || r->addable < INDEXED) {
- if(r->complex >= FNX && nn == Z)
- regret(&nod, r, 0, 0);
- else
- regalloc(&nod, r, nn);
- cgen(r, &nod);
- gmove(&nod, l);
- if(nn != Z)
- gmove(&nod, nn);
- regfree(&nod);
- } else
- gmove(r, l);
- break;
- }
- if(l->complex >= r->complex) {
- reglcgen(&nod1, l, Z);
- if(r->addable >= INDEXED) {
- gmove(r, &nod1);
- if(nn != Z)
- gmove(r, nn);
- regfree(&nod1);
- break;
- }
- regalloc(&nod, r, nn);
- cgen(r, &nod);
- } else {
- regalloc(&nod, r, nn);
- cgen(r, &nod);
- reglcgen(&nod1, l, Z);
- }
- gmove(&nod, &nod1);
- regfree(&nod);
- regfree(&nod1);
- break;
-
- bitas:
- n = l->left;
- regalloc(&nod, r, nn);
- if(l->complex >= r->complex) {
- reglcgen(&nod1, n, Z);
- cgen(r, &nod);
- } else {
- cgen(r, &nod);
- reglcgen(&nod1, n, Z);
- }
- regalloc(&nod2, n, Z);
- gopcode(OAS, &nod1, Z, &nod2);
- bitstore(l, &nod, &nod1, &nod2, nn);
- break;
-
- case OBIT:
- if(nn == Z) {
- nullwarn(l, Z);
- break;
- }
- bitload(n, &nod, Z, Z, nn);
- gopcode(OAS, &nod, Z, nn);
- regfree(&nod);
- break;
-
- case ODIV:
- case OMOD:
- if(nn != Z)
- if((t = vlog(r)) >= 0) {
- /* signed div/mod by constant power of 2 */
- cgen(l, nn);
- gopcode(OGE, nodconst(0), nn, Z);
- p1 = p;
- if(o == ODIV) {
- gopcode(OADD, nodconst((1<<t)-1), Z, nn);
- patch(p1, pc);
- gopcode(OASHR, nodconst(t), Z, nn);
- } else {
- gopcode(OSUB, nn, nodconst(0), nn);
- gopcode(OAND, nodconst((1<<t)-1), Z, nn);
- gopcode(OSUB, nn, nodconst(0), nn);
- gbranch(OGOTO);
- patch(p1, pc);
- p1 = p;
- gopcode(OAND, nodconst((1<<t)-1), Z, nn);
- patch(p1, pc);
- }
- break;
- }
- goto muldiv;
-
- case OSUB:
- if(nn != Z)
- if(l->op == OCONST)
- if(!typefd[n->type->etype]) {
- cgen(r, nn);
- gopcode(o, Z, l, nn);
- break;
- }
- case OADD:
- case OAND:
- case OOR:
- case OXOR:
- case OLSHR:
- case OASHL:
- case OASHR:
- /*
- * immediate operands
- */
- if(nn != Z)
- if(r->op == OCONST)
- if(!typefd[n->type->etype]) {
- cgen(l, nn);
- if(r->vconst == 0)
- if(o != OAND)
- break;
- if(nn != Z)
- gopcode(o, r, Z, nn);
- break;
- }
-
- case OLMUL:
- case OLDIV:
- case OLMOD:
- case OMUL:
- muldiv:
- if(nn == Z) {
- nullwarn(l, r);
- break;
- }
- if(o == OMUL || o == OLMUL) {
- if(mulcon(n, nn))
- break;
- }
- if(l->complex >= r->complex) {
- regalloc(&nod, l, nn);
- cgen(l, &nod);
- regalloc(&nod1, r, Z);
- cgen(r, &nod1);
- gopcode(o, &nod1, Z, &nod);
- } else {
- regalloc(&nod, r, nn);
- cgen(r, &nod);
- regalloc(&nod1, l, Z);
- cgen(l, &nod1);
- gopcode(o, &nod, &nod1, &nod);
- }
- gopcode(OAS, &nod, Z, nn);
- regfree(&nod);
- regfree(&nod1);
- break;
-
- case OASLSHR:
- case OASASHL:
- case OASASHR:
- case OASAND:
- case OASADD:
- case OASSUB:
- case OASXOR:
- case OASOR:
- if(l->op == OBIT)
- goto asbitop;
- if(r->op == OCONST)
- if(!typefd[r->type->etype])
- if(!typefd[n->type->etype]) {
- if(l->addable < INDEXED)
- reglcgen(&nod2, l, Z);
- else
- nod2 = *l;
- regalloc(&nod, r, nn);
- gopcode(OAS, &nod2, Z, &nod);
- gopcode(o, r, Z, &nod);
- gopcode(OAS, &nod, Z, &nod2);
-
- regfree(&nod);
- if(l->addable < INDEXED)
- regfree(&nod2);
- break;
- }
-
- case OASLMUL:
- case OASLDIV:
- case OASLMOD:
- case OASMUL:
- case OASDIV:
- case OASMOD:
- if(l->op == OBIT)
- goto asbitop;
- if(l->complex >= r->complex) {
- if(l->addable < INDEXED)
- reglcgen(&nod2, l, Z);
- else
- nod2 = *l;
- regalloc(&nod1, r, Z);
- cgen(r, &nod1);
- } else {
- regalloc(&nod1, r, Z);
- cgen(r, &nod1);
- if(l->addable < INDEXED)
- reglcgen(&nod2, l, Z);
- else
- nod2 = *l;
- }
-
- regalloc(&nod, n, nn);
- gmove(&nod2, &nod);
- gopcode(o, &nod1, Z, &nod);
- gmove(&nod, &nod2);
- if(nn != Z)
- gopcode(OAS, &nod, Z, nn);
- regfree(&nod);
- regfree(&nod1);
- if(l->addable < INDEXED)
- regfree(&nod2);
- break;
-
- asbitop:
- regalloc(&nod4, n, nn);
- if(l->complex >= r->complex) {
- bitload(l, &nod, &nod1, &nod2, &nod4);
- regalloc(&nod3, r, Z);
- cgen(r, &nod3);
- } else {
- regalloc(&nod3, r, Z);
- cgen(r, &nod3);
- bitload(l, &nod, &nod1, &nod2, &nod4);
- }
- gmove(&nod, &nod4);
- gopcode(o, &nod3, Z, &nod4);
- regfree(&nod3);
- gmove(&nod4, &nod);
- regfree(&nod4);
- bitstore(l, &nod, &nod1, &nod2, nn);
- break;
-
- case OADDR:
- if(nn == Z) {
- nullwarn(l, Z);
- break;
- }
- lcgen(l, nn);
- break;
-
- case OFUNC:
- if(l->complex >= FNX) {
- if(l->op != OIND)
- diag(n, "bad function call");
-
- regret(&nod, l->left, 0, 0);
- cgen(l->left, &nod);
- regsalloc(&nod1, l->left);
- gopcode(OAS, &nod, Z, &nod1);
- regfree(&nod);
-
- nod = *n;
- nod.left = &nod2;
- nod2 = *l;
- nod2.left = &nod1;
- nod2.complex = 1;
- cgen(&nod, nn);
-
- return;
- }
- if(REGARG >= 0)
- o = reg[REGARG];
- gargs(r, &nod, &nod1);
- if(l->addable < INDEXED) {
- reglcgen(&nod, l, Z);
- gopcode(OFUNC, Z, Z, &nod);
- regfree(&nod);
- } else
- gopcode(OFUNC, Z, Z, l);
- if(REGARG >= 0)
- if(o != reg[REGARG])
- reg[REGARG]--;
- regret(&nod, n, l->type, 1);
- if(nn != Z)
- gmove(&nod, nn);
- if(nod.op == OREGISTER)
- regfree(&nod);
- break;
-
- case OIND:
- if(nn == Z) {
- nullwarn(l, Z);
- break;
- }
- regialloc(&nod, n, nn);
- r = l;
- while(r->op == OADD)
- r = r->right;
- if(sconst(r) && (v = r->vconst+nod.xoffset) > -4096 && v < 4096) {
- v = r->vconst;
- r->vconst = 0;
- cgen(l, &nod);
- nod.xoffset += v;
- r->vconst = v;
- } else
- cgen(l, &nod);
- regind(&nod, n);
- gopcode(OAS, &nod, Z, nn);
- regfree(&nod);
- break;
-
- case OEQ:
- case ONE:
- case OLE:
- case OLT:
- case OGE:
- case OGT:
- case OLO:
- case OLS:
- case OHI:
- case OHS:
- if(nn == Z) {
- nullwarn(l, r);
- break;
- }
- boolgen(n, 1, nn);
- break;
-
- case OANDAND:
- case OOROR:
- boolgen(n, 1, nn);
- if(nn == Z)
- patch(p, pc);
- break;
-
- case ONOT:
- if(nn == Z) {
- nullwarn(l, Z);
- break;
- }
- boolgen(n, 1, nn);
- break;
-
- case OCOMMA:
- cgen(l, Z);
- cgen(r, nn);
- break;
-
- case OCAST:
- if(nn == Z) {
- nullwarn(l, Z);
- break;
- }
- /*
- * convert from types l->n->nn
- */
- if(nocast(l->type, n->type)) {
- if(nocast(n->type, nn->type)) {
- cgen(l, nn);
- break;
- }
- }
- regalloc(&nod, l, nn);
- cgen(l, &nod);
- regalloc(&nod1, n, &nod);
- if(inrel)
- gmover(&nod, &nod1);
- else
- gopcode(OAS, &nod, Z, &nod1);
- gopcode(OAS, &nod1, Z, nn);
- regfree(&nod1);
- regfree(&nod);
- break;
-
- case ODOT:
- sugen(l, nodrat, l->type->width);
- if(nn != Z) {
- warn(n, "non-interruptable temporary");
- nod = *nodrat;
- if(!r || r->op != OCONST) {
- diag(n, "DOT and no offset");
- break;
- }
- nod.xoffset += (int32)r->vconst;
- nod.type = n->type;
- cgen(&nod, nn);
- }
- break;
-
- case OCOND:
- bcgen(l, 1);
- p1 = p;
- cgen(r->left, nn);
- gbranch(OGOTO);
- patch(p1, pc);
- p1 = p;
- cgen(r->right, nn);
- patch(p1, pc);
- break;
-
- case OPOSTINC:
- case OPOSTDEC:
- v = 1;
- if(l->type->etype == TIND)
- v = l->type->link->width;
- if(o == OPOSTDEC)
- v = -v;
- if(l->op == OBIT)
- goto bitinc;
- if(nn == Z)
- goto pre;
-
- if(l->addable < INDEXED)
- reglcgen(&nod2, l, Z);
- else
- nod2 = *l;
-
- regalloc(&nod, l, nn);
- gopcode(OAS, &nod2, Z, &nod);
- regalloc(&nod1, l, Z);
- if(typefd[l->type->etype]) {
- regalloc(&nod3, l, Z);
- if(v < 0) {
- gopcode(OAS, nodfconst(-v), Z, &nod3);
- gopcode(OSUB, &nod3, &nod, &nod1);
- } else {
- gopcode(OAS, nodfconst(v), Z, &nod3);
- gopcode(OADD, &nod3, &nod, &nod1);
- }
- regfree(&nod3);
- } else
- gopcode(OADD, nodconst(v), &nod, &nod1);
- gopcode(OAS, &nod1, Z, &nod2);
-
- regfree(&nod);
- regfree(&nod1);
- if(l->addable < INDEXED)
- regfree(&nod2);
- break;
-
- case OPREINC:
- case OPREDEC:
- v = 1;
- if(l->type->etype == TIND)
- v = l->type->link->width;
- if(o == OPREDEC)
- v = -v;
- if(l->op == OBIT)
- goto bitinc;
-
- pre:
- if(l->addable < INDEXED)
- reglcgen(&nod2, l, Z);
- else
- nod2 = *l;
-
- regalloc(&nod, l, nn);
- gopcode(OAS, &nod2, Z, &nod);
- if(typefd[l->type->etype]) {
- regalloc(&nod3, l, Z);
- if(v < 0) {
- gopcode(OAS, nodfconst(-v), Z, &nod3);
- gopcode(OSUB, &nod3, Z, &nod);
- } else {
- gopcode(OAS, nodfconst(v), Z, &nod3);
- gopcode(OADD, &nod3, Z, &nod);
- }
- regfree(&nod3);
- } else
- gopcode(OADD, nodconst(v), Z, &nod);
- gopcode(OAS, &nod, Z, &nod2);
-
- regfree(&nod);
- if(l->addable < INDEXED)
- regfree(&nod2);
- break;
-
- bitinc:
- if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) {
- bitload(l, &nod, &nod1, &nod2, Z);
- gopcode(OAS, &nod, Z, nn);
- gopcode(OADD, nodconst(v), Z, &nod);
- bitstore(l, &nod, &nod1, &nod2, Z);
- break;
- }
- bitload(l, &nod, &nod1, &nod2, nn);
- gopcode(OADD, nodconst(v), Z, &nod);
- bitstore(l, &nod, &nod1, &nod2, nn);
- break;
- }
- cursafe = curs;
- return;
-}
-
-void
-cgen(Node *n, Node *nn)
-{
- _cgen(n, nn, 0);
-}
-
-void
-cgenrel(Node *n, Node *nn)
-{
- _cgen(n, nn, 1);
-}
-
-void
-reglcgen(Node *t, Node *n, Node *nn)
-{
- Node *r;
- int32 v;
-
- regialloc(t, n, nn);
- if(n->op == OIND) {
- r = n->left;
- while(r->op == OADD)
- r = r->right;
- if(sconst(r) && (v = r->vconst+t->xoffset) > -4096 && v < 4096) {
- v = r->vconst;
- r->vconst = 0;
- lcgen(n, t);
- t->xoffset += v;
- r->vconst = v;
- regind(t, n);
- return;
- }
- } else if(n->op == OINDREG) {
- if((v = n->xoffset) > -4096 && v < 4096) {
- n->op = OREGISTER;
- cgen(n, t);
- t->xoffset += v;
- n->op = OINDREG;
- regind(t, n);
- return;
- }
- }
- lcgen(n, t);
- regind(t, n);
-}
-
-void
-reglpcgen(Node *n, Node *nn, int f)
-{
- Type *t;
-
- t = nn->type;
- nn->type = types[TLONG];
- if(f)
- reglcgen(n, nn, Z);
- else {
- regialloc(n, nn, Z);
- lcgen(nn, n);
- regind(n, nn);
- }
- nn->type = t;
-}
-
-void
-lcgen(Node *n, Node *nn)
-{
- Prog *p1;
- Node nod;
-
- if(debug['g']) {
- prtree(nn, "lcgen lhs");
- prtree(n, "lcgen");
- }
- if(n == Z || n->type == T)
- return;
- if(nn == Z) {
- nn = &nod;
- regalloc(&nod, n, Z);
- }
- switch(n->op) {
- default:
- if(n->addable < INDEXED) {
- diag(n, "unknown op in lcgen: %O", n->op);
- break;
- }
- nod = *n;
- nod.op = OADDR;
- nod.left = n;
- nod.right = Z;
- nod.type = types[TIND];
- gopcode(OAS, &nod, Z, nn);
- break;
-
- case OCOMMA:
- cgen(n->left, n->left);
- lcgen(n->right, nn);
- break;
-
- case OIND:
- cgen(n->left, nn);
- break;
-
- case OCOND:
- bcgen(n->left, 1);
- p1 = p;
- lcgen(n->right->left, nn);
- gbranch(OGOTO);
- patch(p1, pc);
- p1 = p;
- lcgen(n->right->right, nn);
- patch(p1, pc);
- break;
- }
-}
-
-void
-bcgen(Node *n, int true)
-{
-
- if(n->type == T)
- gbranch(OGOTO);
- else
- boolgen(n, true, Z);
-}
-
-void
-boolgen(Node *n, int true, Node *nn)
-{
- int o;
- Prog *p1, *p2;
- Node *l, *r, nod, nod1;
- int32 curs;
-
- if(debug['g']) {
- prtree(nn, "boolgen lhs");
- prtree(n, "boolgen");
- }
- curs = cursafe;
- l = n->left;
- r = n->right;
- switch(n->op) {
-
- default:
- regalloc(&nod, n, nn);
- cgen(n, &nod);
- o = ONE;
- if(true)
- o = comrel[relindex(o)];
- if(typefd[n->type->etype]) {
- gopcode(o, nodfconst(0), &nod, Z);
- } else
- gopcode(o, nodconst(0), &nod, Z);
- regfree(&nod);
- goto com;
-
- case OCONST:
- o = vconst(n);
- if(!true)
- o = !o;
- gbranch(OGOTO);
- if(o) {
- p1 = p;
- gbranch(OGOTO);
- patch(p1, pc);
- }
- goto com;
-
- case OCOMMA:
- cgen(l, Z);
- boolgen(r, true, nn);
- break;
-
- case ONOT:
- boolgen(l, !true, nn);
- break;
-
- case OCOND:
- bcgen(l, 1);
- p1 = p;
- bcgen(r->left, true);
- p2 = p;
- gbranch(OGOTO);
- patch(p1, pc);
- p1 = p;
- bcgen(r->right, !true);
- patch(p2, pc);
- p2 = p;
- gbranch(OGOTO);
- patch(p1, pc);
- patch(p2, pc);
- goto com;
-
- case OANDAND:
- if(!true)
- goto caseor;
-
- caseand:
- bcgen(l, true);
- p1 = p;
- bcgen(r, !true);
- p2 = p;
- patch(p1, pc);
- gbranch(OGOTO);
- patch(p2, pc);
- goto com;
-
- case OOROR:
- if(!true)
- goto caseand;
-
- caseor:
- bcgen(l, !true);
- p1 = p;
- bcgen(r, !true);
- p2 = p;
- gbranch(OGOTO);
- patch(p1, pc);
- patch(p2, pc);
- goto com;
-
- case OEQ:
- case ONE:
- case OLE:
- case OLT:
- case OGE:
- case OGT:
- case OHI:
- case OHS:
- case OLO:
- case OLS:
- o = n->op;
- if(true)
- o = comrel[relindex(o)];
- if(l->complex >= FNX && r->complex >= FNX) {
- regret(&nod, r, 0, 0);
- cgenrel(r, &nod);
- regsalloc(&nod1, r);
- gopcode(OAS, &nod, Z, &nod1);
- regfree(&nod);
- nod = *n;
- nod.right = &nod1;
- boolgen(&nod, true, nn);
- break;
- }
- if(sconst(l)) {
- regalloc(&nod, r, nn);
- cgenrel(r, &nod);
- o = invrel[relindex(o)];
- gopcode(o, l, &nod, Z);
- regfree(&nod);
- goto com;
- }
- if(sconst(r)) {
- regalloc(&nod, l, nn);
- cgenrel(l, &nod);
- gopcode(o, r, &nod, Z);
- regfree(&nod);
- goto com;
- }
- if(l->complex >= r->complex) {
- regalloc(&nod1, l, nn);
- cgenrel(l, &nod1);
- regalloc(&nod, r, Z);
- cgenrel(r, &nod);
- } else {
- regalloc(&nod, r, nn);
- cgenrel(r, &nod);
- regalloc(&nod1, l, Z);
- cgenrel(l, &nod1);
- }
- gopcode(o, &nod, &nod1, Z);
- regfree(&nod);
- regfree(&nod1);
-
- com:
- if(nn != Z) {
- p1 = p;
- gopcode(OAS, nodconst(1), Z, nn);
- gbranch(OGOTO);
- p2 = p;
- patch(p1, pc);
- gopcode(OAS, nodconst(0), Z, nn);
- patch(p2, pc);
- }
- break;
- }
- cursafe = curs;
-}
-
-void
-sugen(Node *n, Node *nn, int32 w)
-{
- Prog *p1;
- Node nod0, nod1, nod2, nod3, nod4, *l, *r;
- Type *t;
- int32 pc1;
- int i, m, c;
-
- if(n == Z || n->type == T)
- return;
- if(debug['g']) {
- prtree(nn, "sugen lhs");
- prtree(n, "sugen");
- }
- if(nn == nodrat)
- if(w > nrathole)
- nrathole = w;
- switch(n->op) {
- case OIND:
- if(nn == Z) {
- nullwarn(n->left, Z);
- break;
- }
-
- default:
- goto copy;
-
- case OCONST:
- if(n->type && typev[n->type->etype]) {
- if(nn == Z) {
- nullwarn(n->left, Z);
- break;
- }
-
- t = nn->type;
- nn->type = types[TLONG];
- reglcgen(&nod1, nn, Z);
- nn->type = t;
-
- if(isbigendian)
- gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1);
- else
- gopcode(OAS, nod32const(n->vconst), Z, &nod1);
- nod1.xoffset += SZ_LONG;
- if(isbigendian)
- gopcode(OAS, nod32const(n->vconst), Z, &nod1);
- else
- gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1);
-
- regfree(&nod1);
- break;
- }
- goto copy;
-
- case ODOT:
- l = n->left;
- sugen(l, nodrat, l->type->width);
- if(nn != Z) {
- warn(n, "non-interruptable temporary");
- nod1 = *nodrat;
- r = n->right;
- if(!r || r->op != OCONST) {
- diag(n, "DOT and no offset");
- break;
- }
- nod1.xoffset += (int32)r->vconst;
- nod1.type = n->type;
- sugen(&nod1, nn, w);
- }
- break;
-
- case OSTRUCT:
- /*
- * rewrite so lhs has no side effect.
- */
- if(nn != Z && side(nn)) {
- nod1 = *n;
- nod1.type = typ(TIND, n->type);
- regret(&nod2, &nod1, 0, 0);
- lcgen(nn, &nod2);
- regsalloc(&nod0, &nod1);
- gopcode(OAS, &nod2, Z, &nod0);
- regfree(&nod2);
-
- nod1 = *n;
- nod1.op = OIND;
- nod1.left = &nod0;
- nod1.right = Z;
- nod1.complex = 1;
-
- sugen(n, &nod1, w);
- return;
- }
-
- r = n->left;
- for(t = n->type->link; t != T; t = t->down) {
- l = r;
- if(r->op == OLIST) {
- l = r->left;
- r = r->right;
- }
- if(nn == Z) {
- cgen(l, nn);
- continue;
- }
- /*
- * hand craft *(&nn + o) = l
- */
- nod0 = znode;
- nod0.op = OAS;
- nod0.type = t;
- nod0.left = &nod1;
- nod0.right = l;
-
- nod1 = znode;
- nod1.op = OIND;
- nod1.type = t;
- nod1.left = &nod2;
-
- nod2 = znode;
- nod2.op = OADD;
- nod2.type = typ(TIND, t);
- nod2.left = &nod3;
- nod2.right = &nod4;
-
- nod3 = znode;
- nod3.op = OADDR;
- nod3.type = nod2.type;
- nod3.left = nn;
-
- nod4 = znode;
- nod4.op = OCONST;
- nod4.type = nod2.type;
- nod4.vconst = t->offset;
-
- ccom(&nod0);
- acom(&nod0);
- xcom(&nod0);
- nod0.addable = 0;
-
- cgen(&nod0, Z);
- }
- break;
-
- case OAS:
- if(nn == Z) {
- if(n->addable < INDEXED)
- sugen(n->right, n->left, w);
- break;
- }
- sugen(n->right, nodrat, w);
- warn(n, "non-interruptable temporary");
- sugen(nodrat, n->left, w);
- sugen(nodrat, nn, w);
- break;
-
- case OFUNC:
- if(!hasdotdotdot(n->left->type)) {
- cgen(n, Z);
- if(nn != Z) {
- curarg -= n->type->width;
- regret(&nod1, n, n->left->type, 1);
- if(nn->complex >= FNX) {
- regsalloc(&nod2, n);
- cgen(&nod1, &nod2);
- nod1 = nod2;
- }
- cgen(&nod1, nn);
- }
- break;
- }
- if(nn == Z) {
- sugen(n, nodrat, w);
- break;
- }
- if(nn->op != OIND) {
- nn = new1(OADDR, nn, Z);
- nn->type = types[TIND];
- nn->addable = 0;
- } else
- nn = nn->left;
- n = new(OFUNC, n->left, new(OLIST, nn, n->right));
- n->type = types[TVOID];
- n->left->type = types[TVOID];
- cgen(n, Z);
- break;
-
- case OCOND:
- bcgen(n->left, 1);
- p1 = p;
- sugen(n->right->left, nn, w);
- gbranch(OGOTO);
- patch(p1, pc);
- p1 = p;
- sugen(n->right->right, nn, w);
- patch(p1, pc);
- break;
-
- case OCOMMA:
- cgen(n->left, Z);
- sugen(n->right, nn, w);
- break;
- }
- return;
-
-copy:
- if(nn == Z)
- return;
- if(n->complex >= FNX && nn->complex >= FNX) {
- t = nn->type;
- nn->type = types[TLONG];
- regialloc(&nod1, nn, Z);
- lcgen(nn, &nod1);
- regsalloc(&nod2, nn);
- nn->type = t;
-
- gopcode(OAS, &nod1, Z, &nod2);
- regfree(&nod1);
-
- nod2.type = typ(TIND, t);
-
- nod1 = nod2;
- nod1.op = OIND;
- nod1.left = &nod2;
- nod1.right = Z;
- nod1.complex = 1;
- nod1.type = t;
-
- sugen(n, &nod1, w);
- return;
- }
-
- w /= SZ_LONG;
- if(w <= 2) {
- if(n->complex > nn->complex) {
- reglpcgen(&nod1, n, 1);
- reglpcgen(&nod2, nn, 1);
- } else {
- reglpcgen(&nod2, nn, 1);
- reglpcgen(&nod1, n, 1);
- }
- regalloc(&nod3, &regnode, Z);
- regalloc(&nod4, &regnode, Z);
- nod0 = *nodconst((1<<nod3.reg)|(1<<nod4.reg));
- if(w == 2 && nod1.xoffset == 0)
- gmovm(&nod1, &nod0, 0);
- else {
- gmove(&nod1, &nod3);
- if(w == 2) {
- nod1.xoffset += SZ_LONG;
- gmove(&nod1, &nod4);
- }
- }
- if(w == 2 && nod2.xoffset == 0)
- gmovm(&nod0, &nod2, 0);
- else {
- gmove(&nod3, &nod2);
- if(w == 2) {
- nod2.xoffset += SZ_LONG;
- gmove(&nod4, &nod2);
- }
- }
- regfree(&nod1);
- regfree(&nod2);
- regfree(&nod3);
- regfree(&nod4);
- return;
- }
-
- if(n->complex > nn->complex) {
- reglpcgen(&nod1, n, 0);
- reglpcgen(&nod2, nn, 0);
- } else {
- reglpcgen(&nod2, nn, 0);
- reglpcgen(&nod1, n, 0);
- }
-
- m = 0;
- for(c = 0; c < w && c < 4; c++) {
- i = tmpreg();
- if (i == 0)
- break;
- reg[i]++;
- m |= 1<<i;
- }
- nod4 = *(nodconst(m));
- if(w < 3*c) {
- for (; w>c; w-=c) {
- gmovm(&nod1, &nod4, 1);
- gmovm(&nod4, &nod2, 1);
- }
- goto out;
- }
-
- regalloc(&nod3, &regnode, Z);
- gopcode(OAS, nodconst(w/c), Z, &nod3);
- w %= c;
-
- pc1 = pc;
- gmovm(&nod1, &nod4, 1);
- gmovm(&nod4, &nod2, 1);
-
- gopcode(OSUB, nodconst(1), Z, &nod3);
- gopcode(OEQ, nodconst(0), &nod3, Z);
- p->as = ABGT;
- patch(p, pc1);
- regfree(&nod3);
-
-out:
- if (w) {
- i = 0;
- while (c>w) {
- while ((m&(1<<i)) == 0)
- i++;
- m &= ~(1<<i);
- reg[i] = 0;
- c--;
- i++;
- }
- nod4.vconst = m;
- gmovm(&nod1, &nod4, 0);
- gmovm(&nod4, &nod2, 0);
- }
- i = 0;
- do {
- while ((m&(1<<i)) == 0)
- i++;
- reg[i] = 0;
- c--;
- i++;
- } while (c>0);
- regfree(&nod1);
- regfree(&nod2);
-}
diff --git a/src/cmd/5c/doc.go b/src/cmd/5c/doc.go
deleted file mode 100644
index 7291d45f4..000000000
--- a/src/cmd/5c/doc.go
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build ignore
-
-/*
-
-5c is a version of the Plan 9 C compiler. The original is documented at
-
- http://plan9.bell-labs.com/magic/man2html/1/8c
-
-Its target architecture is the ARM, referred to by these tools as arm.
-
-*/
-package main
diff --git a/src/cmd/5c/gc.h b/src/cmd/5c/gc.h
deleted file mode 100644
index 7417b7dbe..000000000
--- a/src/cmd/5c/gc.h
+++ /dev/null
@@ -1,333 +0,0 @@
-// Inferno utils/5c/gc.h
-// http://code.google.com/p/inferno-os/source/browse/utils/5c/gc.h
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include <u.h>
-#include "../cc/cc.h"
-#include "../5l/5.out.h"
-
-/*
- * 5c/arm
- * Arm 7500
- */
-#define SZ_CHAR 1
-#define SZ_SHORT 2
-#define SZ_INT 4
-#define SZ_LONG 4
-#define SZ_IND 4
-#define SZ_FLOAT 4
-#define SZ_VLONG 8
-#define SZ_DOUBLE 8
-#define FNX 100
-
-typedef struct Case Case;
-typedef struct C1 C1;
-typedef struct Multab Multab;
-typedef struct Hintab Hintab;
-typedef struct Reg Reg;
-typedef struct Rgn Rgn;
-
-
-#define R0ISZERO 0
-
-#define A ((Addr*)0)
-
-#define INDEXED 9
-#define P ((Prog*)0)
-
-struct Case
-{
- Case* link;
- int32 val;
- int32 label;
- char def;
- char isv;
-};
-#define C ((Case*)0)
-
-struct C1
-{
- int32 val;
- int32 label;
-};
-
-struct Multab
-{
- int32 val;
- char code[20];
-};
-
-struct Hintab
-{
- ushort val;
- char hint[10];
-};
-
-struct Reg
-{
- int32 pc;
- int32 rpo; /* reverse post ordering */
-
- Bits set;
- Bits use1;
- Bits use2;
-
- Bits refbehind;
- Bits refahead;
- Bits calbehind;
- Bits calahead;
- Bits regdiff;
- Bits act;
-
- int32 regu;
- int32 loop; /* could be shorter */
-
-
- Reg* log5;
- int32 active;
-
- Reg* p1;
- Reg* p2;
- Reg* p2link;
- Reg* s1;
- Reg* s2;
- Reg* link;
- Prog* prog;
-};
-#define R ((Reg*)0)
-
-#define NRGN 600
-struct Rgn
-{
- Reg* enter;
- short cost;
- short varno;
- short regno;
-};
-
-EXTERN int32 breakpc;
-EXTERN int32 nbreak;
-EXTERN Case* cases;
-EXTERN Node constnode;
-EXTERN Node fconstnode;
-EXTERN int32 continpc;
-EXTERN int32 curarg;
-EXTERN int32 cursafe;
-EXTERN int32 isbigendian;
-EXTERN Prog* lastp;
-EXTERN int32 maxargsafe;
-EXTERN int mnstring;
-EXTERN Multab multab[20];
-extern int hintabsize;
-EXTERN Node* nodrat;
-EXTERN Node* nodret;
-EXTERN Node* nodsafe;
-EXTERN int32 nrathole;
-EXTERN int32 nstring;
-EXTERN Prog* p;
-EXTERN int32 pc;
-EXTERN Node regnode;
-EXTERN char string[NSNAME];
-EXTERN Sym* symrathole;
-EXTERN Node znode;
-EXTERN Prog zprog;
-EXTERN char reg[NREG+NFREG];
-EXTERN int32 exregoffset;
-EXTERN int32 exfregoffset;
-EXTERN int suppress;
-
-#define BLOAD(r) band(bnot(r->refbehind), r->refahead)
-#define BSTORE(r) band(bnot(r->calbehind), r->calahead)
-#define LOAD(r) (~r->refbehind.b[z] & r->refahead.b[z])
-#define STORE(r) (~r->calbehind.b[z] & r->calahead.b[z])
-
-#define bset(a,n) ((a).b[(n)/32]&(1L<<(n)%32))
-
-#define CLOAD 4
-#define CREF 5
-#define CINF 1000
-#define LOOP 3
-
-EXTERN Rgn region[NRGN];
-EXTERN Rgn* rgp;
-EXTERN int nregion;
-EXTERN int nvar;
-
-EXTERN Bits externs;
-EXTERN Bits params;
-EXTERN Bits consts;
-EXTERN Bits addrs;
-
-EXTERN int32 regbits;
-EXTERN int32 exregbits;
-
-EXTERN int change;
-
-EXTERN Reg* firstr;
-EXTERN Reg* lastr;
-EXTERN Reg zreg;
-EXTERN Reg* freer;
-EXTERN int32* idom;
-EXTERN Reg** rpo2r;
-EXTERN int32 maxnr;
-
-extern char* anames[];
-extern Hintab hintab[];
-
-/*
- * sgen.c
- */
-void codgen(Node*, Node*);
-void gen(Node*);
-void noretval(int);
-void usedset(Node*, int);
-void xcom(Node*);
-int bcomplex(Node*, Node*);
-Prog* gtext(Sym*, int32);
-vlong argsize(int);
-
-/*
- * cgen.c
- */
-void cgen(Node*, Node*);
-void reglcgen(Node*, Node*, Node*);
-void lcgen(Node*, Node*);
-void bcgen(Node*, int);
-void boolgen(Node*, int, Node*);
-void sugen(Node*, Node*, int32);
-void layout(Node*, Node*, int, int, Node*);
-void cgenrel(Node*, Node*);
-
-/*
- * txt.c
- */
-void ginit(void);
-void gclean(void);
-void nextpc(void);
-void gargs(Node*, Node*, Node*);
-void garg1(Node*, Node*, Node*, int, Node**);
-Node* nodconst(int32);
-Node* nod32const(vlong);
-Node* nodfconst(double);
-void nodreg(Node*, Node*, int);
-void regret(Node*, Node*, Type*, int);
-int tmpreg(void);
-void regalloc(Node*, Node*, Node*);
-void regfree(Node*);
-void regialloc(Node*, Node*, Node*);
-void regsalloc(Node*, Node*);
-void regaalloc1(Node*, Node*);
-void regaalloc(Node*, Node*);
-void regind(Node*, Node*);
-void gprep(Node*, Node*);
-void raddr(Node*, Prog*);
-void naddr(Node*, Addr*);
-void gmovm(Node*, Node*, int);
-void gmove(Node*, Node*);
-void gmover(Node*, Node*);
-void gins(int a, Node*, Node*);
-void gopcode(int, Node*, Node*, Node*);
-int samaddr(Node*, Node*);
-void gbranch(int);
-void patch(Prog*, int32);
-int sconst(Node*);
-int sval(int32);
-void gpseudo(int, Sym*, Node*);
-void gprefetch(Node*);
-void gpcdata(int, int);
-
-/*
- * swt.c
- */
-int swcmp(const void*, const void*);
-void doswit(Node*);
-void swit1(C1*, int, int32, Node*);
-void swit2(C1*, int, int32, Node*);
-void newcase(void);
-void bitload(Node*, Node*, Node*, Node*, Node*);
-void bitstore(Node*, Node*, Node*, Node*, Node*);
-int mulcon(Node*, Node*);
-Multab* mulcon0(int32);
-void nullwarn(Node*, Node*);
-void outcode(void);
-
-/*
- * list
- */
-void listinit(void);
-
-/*
- * reg.c
- */
-Reg* rega(void);
-int rcmp(const void*, const void*);
-void regopt(Prog*);
-void addmove(Reg*, int, int, int);
-Bits mkvar(Addr*, int);
-void prop(Reg*, Bits, Bits);
-void loopit(Reg*, int32);
-void synch(Reg*, Bits);
-uint32 allreg(uint32, Rgn*);
-void paint1(Reg*, int);
-uint32 paint2(Reg*, int);
-void paint3(Reg*, int, int32, int);
-void addreg(Addr*, int);
-
-/*
- * peep.c
- */
-void peep(void);
-void excise(Reg*);
-Reg* uniqp(Reg*);
-Reg* uniqs(Reg*);
-int regtyp(Addr*);
-int regzer(Addr*);
-int anyvar(Addr*);
-int subprop(Reg*);
-int copyprop(Reg*);
-int shiftprop(Reg*);
-void constprop(Addr*, Addr*, Reg*);
-int copy1(Addr*, Addr*, Reg*, int);
-int copyu(Prog*, Addr*, Addr*);
-
-int copyas(Addr*, Addr*);
-int copyau(Addr*, Addr*);
-int copyau1(Prog*, Addr*);
-int copysub(Addr*, Addr*, Addr*, int);
-int copysub1(Prog*, Addr*, Addr*, int);
-
-int32 RtoB(int);
-int32 FtoB(int);
-int BtoR(int32);
-int BtoF(int32);
-
-void predicate(void);
-int isbranch(Prog *);
-int predicable(Prog *p);
-int modifiescpsr(Prog *p);
diff --git a/src/cmd/5c/list.c b/src/cmd/5c/list.c
deleted file mode 100644
index 98da424de..000000000
--- a/src/cmd/5c/list.c
+++ /dev/null
@@ -1,39 +0,0 @@
-// Inferno utils/5c/list.c
-// http://code.google.com/p/inferno-os/source/browse/utils/5c/list.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-
-#define EXTERN
-#include "gc.h"
-
-void
-listinit(void)
-{
- listinit5();
-}
diff --git a/src/cmd/5c/mul.c b/src/cmd/5c/mul.c
deleted file mode 100644
index ff50c4845..000000000
--- a/src/cmd/5c/mul.c
+++ /dev/null
@@ -1,640 +0,0 @@
-// Inferno utils/5c/mul.c
-// http://code.google.com/p/inferno-os/source/browse/utils/5c/mul.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-
-#include "gc.h"
-
-/*
- * code sequences for multiply by constant.
- * [a-l][0-3]
- * lsl $(A-'a'),r0,r1
- * [+][0-7]
- * add r0,r1,r2
- * [-][0-7]
- * sub r0,r1,r2
- */
-
-static int maxmulops = 3; /* max # of ops to replace mul with */
-static int multabp;
-static int32 mulval;
-static char* mulcp;
-static int32 valmax;
-static int shmax;
-
-static int docode(char *hp, char *cp, int r0, int r1);
-static int gen1(int len);
-static int gen2(int len, int32 r1);
-static int gen3(int len, int32 r0, int32 r1, int flag);
-enum
-{
- SR1 = 1<<0, /* r1 has been shifted */
- SR0 = 1<<1, /* r0 has been shifted */
- UR1 = 1<<2, /* r1 has not been used */
- UR0 = 1<<3, /* r0 has not been used */
-};
-
-Multab*
-mulcon0(int32 v)
-{
- int a1, a2, g;
- Multab *m, *m1;
- char hint[10];
-
- if(v < 0)
- v = -v;
-
- /*
- * look in cache
- */
- m = multab;
- for(g=0; g<nelem(multab); g++) {
- if(m->val == v) {
- if(m->code[0] == 0)
- return 0;
- return m;
- }
- m++;
- }
-
- /*
- * select a spot in cache to overwrite
- */
- multabp++;
- if(multabp < 0 || multabp >= nelem(multab))
- multabp = 0;
- m = multab+multabp;
- m->val = v;
- mulval = v;
-
- /*
- * look in execption hint table
- */
- a1 = 0;
- a2 = hintabsize;
- for(;;) {
- if(a1 >= a2)
- goto no;
- g = (a2 + a1)/2;
- if(v < hintab[g].val) {
- a2 = g;
- continue;
- }
- if(v > hintab[g].val) {
- a1 = g+1;
- continue;
- }
- break;
- }
-
- if(docode(hintab[g].hint, m->code, 1, 0))
- return m;
- print("multiply table failure %d\n", v);
- m->code[0] = 0;
- return 0;
-
-no:
- /*
- * try to search
- */
- hint[0] = 0;
- for(g=1; g<=maxmulops; g++) {
- if(g >= maxmulops && v >= 65535)
- break;
- mulcp = hint+g;
- *mulcp = 0;
- if(gen1(g)) {
- if(docode(hint, m->code, 1, 0))
- return m;
- print("multiply table failure %d\n", v);
- break;
- }
- }
-
- /*
- * try a recur followed by a shift
- */
- g = 0;
- while(!(v & 1)) {
- g++;
- v >>= 1;
- }
- if(g) {
- m1 = mulcon0(v);
- if(m1) {
- strcpy(m->code, m1->code);
- sprint(strchr(m->code, 0), "%c0", g+'a');
- return m;
- }
- }
- m->code[0] = 0;
- return 0;
-}
-
-static int
-docode(char *hp, char *cp, int r0, int r1)
-{
- int c, i;
-
- c = *hp++;
- *cp = c;
- cp += 2;
- switch(c) {
- default:
- c -= 'a';
- if(c < 1 || c >= 30)
- break;
- for(i=0; i<4; i++) {
- switch(i) {
- case 0:
- if(docode(hp, cp, r0<<c, r1))
- goto out;
- break;
- case 1:
- if(docode(hp, cp, r1<<c, r1))
- goto out;
- break;
- case 2:
- if(docode(hp, cp, r0, r0<<c))
- goto out;
- break;
- case 3:
- if(docode(hp, cp, r0, r1<<c))
- goto out;
- break;
- }
- }
- break;
-
- case '+':
- for(i=0; i<8; i++) {
- cp[-1] = i+'0';
- switch(i) {
- case 1:
- if(docode(hp, cp, r0+r1, r1))
- goto out;
- break;
- case 5:
- if(docode(hp, cp, r0, r0+r1))
- goto out;
- break;
- }
- }
- break;
-
- case '-':
- for(i=0; i<8; i++) {
- cp[-1] = i+'0';
- switch(i) {
- case 1:
- if(docode(hp, cp, r0-r1, r1))
- goto out;
- break;
- case 2:
- if(docode(hp, cp, r1-r0, r1))
- goto out;
- break;
- case 5:
- if(docode(hp, cp, r0, r0-r1))
- goto out;
- break;
- case 6:
- if(docode(hp, cp, r0, r1-r0))
- goto out;
- break;
- }
- }
- break;
-
- case 0:
- if(r0 == mulval)
- return 1;
- }
- return 0;
-
-out:
- cp[-1] = i+'0';
- return 1;
-}
-
-static int
-gen1(int len)
-{
- int i;
-
- for(shmax=1; shmax<30; shmax++) {
- valmax = 1<<shmax;
- if(valmax >= mulval)
- break;
- }
- if(mulval == 1)
- return 1;
-
- len--;
- for(i=1; i<=shmax; i++)
- if(gen2(len, 1<<i)) {
- *--mulcp = 'a'+i;
- return 1;
- }
- return 0;
-}
-
-static int
-gen2(int len, int32 r1)
-{
- int i;
-
- if(len <= 0) {
- if(r1 == mulval)
- return 1;
- return 0;
- }
-
- len--;
- if(len == 0)
- goto calcr0;
-
- if(gen3(len, r1, r1+1, UR1)) {
- i = '+';
- goto out;
- }
- if(gen3(len, r1-1, r1, UR0)) {
- i = '-';
- goto out;
- }
- if(gen3(len, 1, r1+1, UR1)) {
- i = '+';
- goto out;
- }
- if(gen3(len, 1, r1-1, UR1)) {
- i = '-';
- goto out;
- }
-
- return 0;
-
-calcr0:
- if(mulval == r1+1) {
- i = '+';
- goto out;
- }
- if(mulval == r1-1) {
- i = '-';
- goto out;
- }
- return 0;
-
-out:
- *--mulcp = i;
- return 1;
-}
-
-static int
-gen3(int len, int32 r0, int32 r1, int flag)
-{
- int i, f1, f2;
- int32 x;
-
- if(r0 <= 0 ||
- r0 >= r1 ||
- r1 > valmax)
- return 0;
-
- len--;
- if(len == 0)
- goto calcr0;
-
- if(!(flag & UR1)) {
- f1 = UR1|SR1;
- for(i=1; i<=shmax; i++) {
- x = r0<<i;
- if(x > valmax)
- break;
- if(gen3(len, r0, x, f1)) {
- i += 'a';
- goto out;
- }
- }
- }
-
- if(!(flag & UR0)) {
- f1 = UR1|SR1;
- for(i=1; i<=shmax; i++) {
- x = r1<<i;
- if(x > valmax)
- break;
- if(gen3(len, r1, x, f1)) {
- i += 'a';
- goto out;
- }
- }
- }
-
- if(!(flag & SR1)) {
- f1 = UR1|SR1|(flag&UR0);
- for(i=1; i<=shmax; i++) {
- x = r1<<i;
- if(x > valmax)
- break;
- if(gen3(len, r0, x, f1)) {
- i += 'a';
- goto out;
- }
- }
- }
-
- if(!(flag & SR0)) {
- f1 = UR0|SR0|(flag&(SR1|UR1));
-
- f2 = UR1|SR1;
- if(flag & UR1)
- f2 |= UR0;
- if(flag & SR1)
- f2 |= SR0;
-
- for(i=1; i<=shmax; i++) {
- x = r0<<i;
- if(x > valmax)
- break;
- if(x > r1) {
- if(gen3(len, r1, x, f2)) {
- i += 'a';
- goto out;
- }
- } else
- if(gen3(len, x, r1, f1)) {
- i += 'a';
- goto out;
- }
- }
- }
-
- x = r1+r0;
- if(gen3(len, r0, x, UR1)) {
- i = '+';
- goto out;
- }
-
- if(gen3(len, r1, x, UR1)) {
- i = '+';
- goto out;
- }
-
- x = r1-r0;
- if(gen3(len, x, r1, UR0)) {
- i = '-';
- goto out;
- }
-
- if(x > r0) {
- if(gen3(len, r0, x, UR1)) {
- i = '-';
- goto out;
- }
- } else
- if(gen3(len, x, r0, UR0)) {
- i = '-';
- goto out;
- }
-
- return 0;
-
-calcr0:
- f1 = flag & (UR0|UR1);
- if(f1 == UR1) {
- for(i=1; i<=shmax; i++) {
- x = r1<<i;
- if(x >= mulval) {
- if(x == mulval) {
- i += 'a';
- goto out;
- }
- break;
- }
- }
- }
-
- if(mulval == r1+r0) {
- i = '+';
- goto out;
- }
- if(mulval == r1-r0) {
- i = '-';
- goto out;
- }
-
- return 0;
-
-out:
- *--mulcp = i;
- return 1;
-}
-
-/*
- * hint table has numbers that
- * the search algorithm fails on.
- * <1000:
- * all numbers
- * <5000:
- * ÷ by 5
- * <10000:
- * ÷ by 50
- * <65536:
- * ÷ by 250
- */
-Hintab hintab[] =
-{
- 683, "b++d+e+",
- 687, "b+e++e-",
- 691, "b++d+e+",
- 731, "b++d+e+",
- 811, "b++d+i+",
- 821, "b++e+e+",
- 843, "b+d++e+",
- 851, "b+f-+e-",
- 853, "b++e+e+",
- 877, "c++++g-",
- 933, "b+c++g-",
- 981, "c-+e-d+",
- 1375, "b+c+b+h-",
- 1675, "d+b++h+",
- 2425, "c++f-e+",
- 2675, "c+d++f-",
- 2750, "b+d-b+h-",
- 2775, "c-+g-e-",
- 3125, "b++e+g+",
- 3275, "b+c+g+e+",
- 3350, "c++++i+",
- 3475, "c-+e-f-",
- 3525, "c-+d+g-",
- 3625, "c-+e-j+",
- 3675, "b+d+d+e+",
- 3725, "b+d-+h+",
- 3925, "b+d+f-d-",
- 4275, "b+g++e+",
- 4325, "b+h-+d+",
- 4425, "b+b+g-j-",
- 4525, "b+d-d+f+",
- 4675, "c++d-g+",
- 4775, "b+d+b+g-",
- 4825, "c+c-+i-",
- 4850, "c++++i-",
- 4925, "b++e-g-",
- 4975, "c+f++e-",
- 5500, "b+g-c+d+",
- 6700, "d+b++i+",
- 9700, "d++++j-",
- 11000, "b+f-c-h-",
- 11750, "b+d+g+j-",
- 12500, "b+c+e-k+",
- 13250, "b+d+e-f+",
- 13750, "b+h-c-d+",
- 14250, "b+g-c+e-",
- 14500, "c+f+j-d-",
- 14750, "d-g--f+",
- 16750, "b+e-d-n+",
- 17750, "c+h-b+e+",
- 18250, "d+b+h-d+",
- 18750, "b+g-++f+",
- 19250, "b+e+b+h+",
- 19750, "b++h--f-",
- 20250, "b+e-l-c+",
- 20750, "c++bi+e-",
- 21250, "b+i+l+c+",
- 22000, "b+e+d-g-",
- 22250, "b+d-h+k-",
- 22750, "b+d-e-g+",
- 23250, "b+c+h+e-",
- 23500, "b+g-c-g-",
- 23750, "b+g-b+h-",
- 24250, "c++g+m-",
- 24750, "b+e+e+j-",
- 25000, "b++dh+g+",
- 25250, "b+e+d-g-",
- 25750, "b+e+b+j+",
- 26250, "b+h+c+e+",
- 26500, "b+h+c+g+",
- 26750, "b+d+e+g-",
- 27250, "b+e+e+f+",
- 27500, "c-i-c-d+",
- 27750, "b+bd++j+",
- 28250, "d-d-++i-",
- 28500, "c+c-h-e-",
- 29000, "b+g-d-f+",
- 29500, "c+h+++e-",
- 29750, "b+g+f-c+",
- 30250, "b+f-g-c+",
- 33500, "c-f-d-n+",
- 33750, "b+d-b+j-",
- 34250, "c+e+++i+",
- 35250, "e+b+d+k+",
- 35500, "c+e+d-g-",
- 35750, "c+i-++e+",
- 36250, "b+bh-d+e+",
- 36500, "c+c-h-e-",
- 36750, "d+e--i+",
- 37250, "b+g+g+b+",
- 37500, "b+h-b+f+",
- 37750, "c+be++j-",
- 38500, "b+e+b+i+",
- 38750, "d+i-b+d+",
- 39250, "b+g-l-+d+",
- 39500, "b+g-c+g-",
- 39750, "b+bh-c+f-",
- 40250, "b+bf+d+g-",
- 40500, "b+g-c+g+",
- 40750, "c+b+i-e+",
- 41250, "d++bf+h+",
- 41500, "b+j+c+d-",
- 41750, "c+f+b+h-",
- 42500, "c+h++g+",
- 42750, "b+g+d-f-",
- 43250, "b+l-e+d-",
- 43750, "c+bd+h+f-",
- 44000, "b+f+g-d-",
- 44250, "b+d-g--f+",
- 44500, "c+e+c+h+",
- 44750, "b+e+d-h-",
- 45250, "b++g+j-g+",
- 45500, "c+d+e-g+",
- 45750, "b+d-h-e-",
- 46250, "c+bd++j+",
- 46500, "b+d-c-j-",
- 46750, "e-e-b+g-",
- 47000, "b+c+d-j-",
- 47250, "b+e+e-g-",
- 47500, "b+g-c-h-",
- 47750, "b+f-c+h-",
- 48250, "d--h+n-",
- 48500, "b+c-g+m-",
- 48750, "b+e+e-g+",
- 49500, "c-f+e+j-",
- 49750, "c+c+g++f-",
- 50000, "b+e+e+k+",
- 50250, "b++i++g+",
- 50500, "c+g+f-i+",
- 50750, "b+e+d+k-",
- 51500, "b+i+c-f+",
- 51750, "b+bd+g-e-",
- 52250, "b+d+g-j+",
- 52500, "c+c+f+g+",
- 52750, "b+c+e+i+",
- 53000, "b+i+c+g+",
- 53500, "c+g+g-n+",
- 53750, "b+j+d-c+",
- 54250, "b+d-g-j-",
- 54500, "c-f+e+f+",
- 54750, "b+f-+c+g+",
- 55000, "b+g-d-g-",
- 55250, "b+e+e+g+",
- 55500, "b+cd++j+",
- 55750, "b+bh-d-f-",
- 56250, "c+d-b+j-",
- 56500, "c+d+c+i+",
- 56750, "b+e+d++h-",
- 57000, "b+d+g-f+",
- 57250, "b+f-m+d-",
- 57750, "b+i+c+e-",
- 58000, "b+e+d+h+",
- 58250, "c+b+g+g+",
- 58750, "d-e-j--e+",
- 59000, "d-i-+e+",
- 59250, "e--h-m+",
- 59500, "c+c-h+f-",
- 59750, "b+bh-e+i-",
- 60250, "b+bh-e-e-",
- 60500, "c+c-g-g-",
- 60750, "b+e-l-e-",
- 61250, "b+g-g-c+",
- 61750, "b+g-c+g+",
- 62250, "f--+c-i-",
- 62750, "e+f--+g+",
- 64750, "b+f+d+p-",
-};
-int hintabsize = nelem(hintab);
diff --git a/src/cmd/5c/peep.c b/src/cmd/5c/peep.c
deleted file mode 100644
index 1de56b594..000000000
--- a/src/cmd/5c/peep.c
+++ /dev/null
@@ -1,1478 +0,0 @@
-// Inferno utils/5c/peep.c
-// http://code.google.com/p/inferno-os/source/browse/utils/5c/peep.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-
-#include "gc.h"
-
-int xtramodes(Reg*, Addr*);
-
-void
-peep(void)
-{
- Reg *r, *r1, *r2;
- Prog *p, *p1;
- int t;
-/*
- * complete R structure
- */
- t = 0;
- for(r=firstr; r!=R; r=r1) {
- r1 = r->link;
- if(r1 == R)
- break;
- p = r->prog->link;
- while(p != r1->prog)
- switch(p->as) {
- default:
- r2 = rega();
- r->link = r2;
- r2->link = r1;
-
- r2->prog = p;
- r2->p1 = r;
- r->s1 = r2;
- r2->s1 = r1;
- r1->p1 = r2;
-
- r = r2;
- t++;
-
- case ADATA:
- case AGLOBL:
- case ANAME:
- case ASIGNAME:
- p = p->link;
- }
- }
-
-loop1:
- t = 0;
- for(r=firstr; r!=R; r=r->link) {
- p = r->prog;
- if(p->as == ASLL || p->as == ASRL || p->as == ASRA) {
- /*
- * elide shift into D_SHIFT operand of subsequent instruction
- */
- if(shiftprop(r)) {
- excise(r);
- t++;
- }
- }
- if(p->as == AMOVW || p->as == AMOVF || p->as == AMOVD)
- if(regtyp(&p->to)) {
- if(p->from.type == D_CONST)
- constprop(&p->from, &p->to, r->s1);
- else if(regtyp(&p->from))
- if(p->from.type == p->to.type) {
- if(copyprop(r)) {
- excise(r);
- t++;
- } else
- if(subprop(r) && copyprop(r)) {
- excise(r);
- t++;
- }
- }
- }
- }
- if(t)
- goto loop1;
- /*
- * look for MOVB x,R; MOVB R,R
- */
- for(r=firstr; r!=R; r=r->link) {
- p = r->prog;
- switch(p->as) {
- default:
- continue;
- case AEOR:
- /*
- * EOR -1,x,y => MVN x,y
- */
- if(p->from.type == D_CONST && p->from.offset == -1) {
- p->as = AMVN;
- p->from.type = D_REG;
- if(p->reg != NREG)
- p->from.reg = p->reg;
- else
- p->from.reg = p->to.reg;
- p->reg = NREG;
- }
- continue;
- case AMOVH:
- case AMOVHS:
- case AMOVHU:
- case AMOVB:
- case AMOVBS:
- case AMOVBU:
- if(p->to.type != D_REG)
- continue;
- break;
- }
- r1 = r->link;
- if(r1 == R)
- continue;
- p1 = r1->prog;
- if(p1->as != p->as)
- continue;
- if(p1->from.type != D_REG || p1->from.reg != p->to.reg)
- continue;
- if(p1->to.type != D_REG || p1->to.reg != p->to.reg)
- continue;
- excise(r1);
- }
-
- for(r=firstr; r!=R; r=r->link) {
- p = r->prog;
- switch(p->as) {
- case AMOVW:
- case AMOVB:
- case AMOVBS:
- case AMOVBU:
- if(p->from.type == D_OREG && p->from.offset == 0)
- xtramodes(r, &p->from);
- else if(p->to.type == D_OREG && p->to.offset == 0)
- xtramodes(r, &p->to);
- else
- continue;
- break;
- case ACMP:
- /*
- * elide CMP $0,x if calculation of x can set condition codes
- */
- if(p->from.type != D_CONST || p->from.offset != 0)
- continue;
- r2 = r->s1;
- if(r2 == R)
- continue;
- t = r2->prog->as;
- switch(t) {
- default:
- continue;
- case ABEQ:
- case ABNE:
- case ABMI:
- case ABPL:
- break;
- case ABGE:
- t = ABPL;
- break;
- case ABLT:
- t = ABMI;
- break;
- case ABHI:
- t = ABNE;
- break;
- case ABLS:
- t = ABEQ;
- break;
- }
- r1 = r;
- do
- r1 = uniqp(r1);
- while (r1 != R && r1->prog->as == ANOP);
- if(r1 == R)
- continue;
- p1 = r1->prog;
- if(p1->to.type != D_REG)
- continue;
- if(p1->to.reg != p->reg)
- if(!(p1->as == AMOVW && p1->from.type == D_REG && p1->from.reg == p->reg))
- continue;
- switch(p1->as) {
- default:
- continue;
- case AMOVW:
- if(p1->from.type != D_REG)
- continue;
- case AAND:
- case AEOR:
- case AORR:
- case ABIC:
- case AMVN:
- case ASUB:
- case ARSB:
- case AADD:
- case AADC:
- case ASBC:
- case ARSC:
- break;
- }
- p1->scond |= C_SBIT;
- r2->prog->as = t;
- excise(r);
- continue;
- }
- }
-
- predicate();
-}
-
-void
-excise(Reg *r)
-{
- Prog *p;
-
- p = r->prog;
- p->as = ANOP;
- p->scond = zprog.scond;
- p->from = zprog.from;
- p->to = zprog.to;
- p->reg = zprog.reg; /**/
-}
-
-Reg*
-uniqp(Reg *r)
-{
- Reg *r1;
-
- r1 = r->p1;
- if(r1 == R) {
- r1 = r->p2;
- if(r1 == R || r1->p2link != R)
- return R;
- } else
- if(r->p2 != R)
- return R;
- return r1;
-}
-
-Reg*
-uniqs(Reg *r)
-{
- Reg *r1;
-
- r1 = r->s1;
- if(r1 == R) {
- r1 = r->s2;
- if(r1 == R)
- return R;
- } else
- if(r->s2 != R)
- return R;
- return r1;
-}
-
-int
-regtyp(Addr *a)
-{
-
- if(a->type == D_REG)
- return 1;
- if(a->type == D_FREG)
- return 1;
- return 0;
-}
-
-/*
- * the idea is to substitute
- * one register for another
- * from one MOV to another
- * MOV a, R0
- * ADD b, R0 / no use of R1
- * MOV R0, R1
- * would be converted to
- * MOV a, R1
- * ADD b, R1
- * MOV R1, R0
- * hopefully, then the former or latter MOV
- * will be eliminated by copy propagation.
- */
-int
-subprop(Reg *r0)
-{
- Prog *p;
- Addr *v1, *v2;
- Reg *r;
- int t;
-
- p = r0->prog;
- v1 = &p->from;
- if(!regtyp(v1))
- return 0;
- v2 = &p->to;
- if(!regtyp(v2))
- return 0;
- for(r=uniqp(r0); r!=R; r=uniqp(r)) {
- if(uniqs(r) == R)
- break;
- p = r->prog;
- switch(p->as) {
- case ABL:
- return 0;
-
- case ACMP:
- case ACMN:
- case AADD:
- case ASUB:
- case ARSB:
- case ASLL:
- case ASRL:
- case ASRA:
- case AORR:
- case AAND:
- case AEOR:
- case AMUL:
- case ADIV:
- case ADIVU:
-
- case ACMPF:
- case ACMPD:
- case AADDD:
- case AADDF:
- case ASUBD:
- case ASUBF:
- case AMULD:
- case AMULF:
- case ADIVD:
- case ADIVF:
- if(p->to.type == v1->type)
- if(p->to.reg == v1->reg) {
- if(p->reg == NREG)
- p->reg = p->to.reg;
- goto gotit;
- }
- break;
-
- case AMOVF:
- case AMOVD:
- case AMOVW:
- if(p->to.type == v1->type)
- if(p->to.reg == v1->reg)
- goto gotit;
- break;
-
- case AMOVM:
- t = 1<<v2->reg;
- if((p->from.type == D_CONST && (p->from.offset&t)) ||
- (p->to.type == D_CONST && (p->to.offset&t)))
- return 0;
- break;
- }
- if(copyau(&p->from, v2) ||
- copyau1(p, v2) ||
- copyau(&p->to, v2))
- break;
- if(copysub(&p->from, v1, v2, 0) ||
- copysub1(p, v1, v2, 0) ||
- copysub(&p->to, v1, v2, 0))
- break;
- }
- return 0;
-
-gotit:
- copysub(&p->to, v1, v2, 1);
- if(debug['P']) {
- print("gotit: %D->%D\n%P", v1, v2, r->prog);
- if(p->from.type == v2->type)
- print(" excise");
- print("\n");
- }
- for(r=uniqs(r); r!=r0; r=uniqs(r)) {
- p = r->prog;
- copysub(&p->from, v1, v2, 1);
- copysub1(p, v1, v2, 1);
- copysub(&p->to, v1, v2, 1);
- if(debug['P'])
- print("%P\n", r->prog);
- }
- t = v1->reg;
- v1->reg = v2->reg;
- v2->reg = t;
- if(debug['P'])
- print("%P last\n", r->prog);
- return 1;
-}
-
-/*
- * The idea is to remove redundant copies.
- * v1->v2 F=0
- * (use v2 s/v2/v1/)*
- * set v1 F=1
- * use v2 return fail
- * -----------------
- * v1->v2 F=0
- * (use v2 s/v2/v1/)*
- * set v1 F=1
- * set v2 return success
- */
-int
-copyprop(Reg *r0)
-{
- Prog *p;
- Addr *v1, *v2;
- Reg *r;
-
- p = r0->prog;
- v1 = &p->from;
- v2 = &p->to;
- if(copyas(v1, v2))
- return 1;
- for(r=firstr; r!=R; r=r->link)
- r->active = 0;
- return copy1(v1, v2, r0->s1, 0);
-}
-
-int
-copy1(Addr *v1, Addr *v2, Reg *r, int f)
-{
- int t;
- Prog *p;
-
- if(r->active) {
- if(debug['P'])
- print("act set; return 1\n");
- return 1;
- }
- r->active = 1;
- if(debug['P'])
- print("copy %D->%D f=%d\n", v1, v2, f);
- for(; r != R; r = r->s1) {
- p = r->prog;
- if(debug['P'])
- print("%P", p);
- if(!f && uniqp(r) == R) {
- f = 1;
- if(debug['P'])
- print("; merge; f=%d", f);
- }
- t = copyu(p, v2, A);
- switch(t) {
- case 2: /* rar, can't split */
- if(debug['P'])
- print("; %Drar; return 0\n", v2);
- return 0;
-
- case 3: /* set */
- if(debug['P'])
- print("; %Dset; return 1\n", v2);
- return 1;
-
- case 1: /* used, substitute */
- case 4: /* use and set */
- if(f) {
- if(!debug['P'])
- return 0;
- if(t == 4)
- print("; %Dused+set and f=%d; return 0\n", v2, f);
- else
- print("; %Dused and f=%d; return 0\n", v2, f);
- return 0;
- }
- if(copyu(p, v2, v1)) {
- if(debug['P'])
- print("; sub fail; return 0\n");
- return 0;
- }
- if(debug['P'])
- print("; sub%D/%D", v2, v1);
- if(t == 4) {
- if(debug['P'])
- print("; %Dused+set; return 1\n", v2);
- return 1;
- }
- break;
- }
- if(!f) {
- t = copyu(p, v1, A);
- if(!f && (t == 2 || t == 3 || t == 4)) {
- f = 1;
- if(debug['P'])
- print("; %Dset and !f; f=%d", v1, f);
- }
- }
- if(debug['P'])
- print("\n");
- if(r->s2)
- if(!copy1(v1, v2, r->s2, f))
- return 0;
- }
- return 1;
-}
-
-/*
- * The idea is to remove redundant constants.
- * $c1->v1
- * ($c1->v2 s/$c1/v1)*
- * set v1 return
- * The v1->v2 should be eliminated by copy propagation.
- */
-void
-constprop(Addr *c1, Addr *v1, Reg *r)
-{
- Prog *p;
-
- if(debug['C'])
- print("constprop %D->%D\n", c1, v1);
- for(; r != R; r = r->s1) {
- p = r->prog;
- if(debug['C'])
- print("%P", p);
- if(uniqp(r) == R) {
- if(debug['C'])
- print("; merge; return\n");
- return;
- }
- if(p->as == AMOVW && copyas(&p->from, c1)) {
- if(debug['C'])
- print("; sub%D/%D", &p->from, v1);
- p->from = *v1;
- } else if(copyu(p, v1, A) > 1) {
- if(debug['C'])
- print("; %Dset; return\n", v1);
- return;
- }
- if(debug['C'])
- print("\n");
- if(r->s2)
- constprop(c1, v1, r->s2);
- }
-}
-
-/*
- * ASLL x,y,w
- * .. (not use w, not set x y w)
- * AXXX w,a,b (a != w)
- * .. (not use w)
- * (set w)
- * ----------- changed to
- * ..
- * AXXX (x<<y),a,b
- * ..
- */
-#define FAIL(msg) { if(debug['H']) print("\t%s; FAILURE\n", msg); return 0; }
-int
-shiftprop(Reg *r)
-{
- Reg *r1;
- Prog *p, *p1, *p2;
- int n, o;
- Addr a;
-
- p = r->prog;
- if(p->to.type != D_REG)
- FAIL("BOTCH: result not reg");
- n = p->to.reg;
- a = zprog.from;
- if(p->reg != NREG && p->reg != p->to.reg) {
- a.type = D_REG;
- a.reg = p->reg;
- }
- if(debug['H'])
- print("shiftprop\n%P", p);
- r1 = r;
- for(;;) {
- /* find first use of shift result; abort if shift operands or result are changed */
- r1 = uniqs(r1);
- if(r1 == R)
- FAIL("branch");
- if(uniqp(r1) == R)
- FAIL("merge");
- p1 = r1->prog;
- if(debug['H'])
- print("\n%P", p1);
- switch(copyu(p1, &p->to, A)) {
- case 0: /* not used or set */
- if((p->from.type == D_REG && copyu(p1, &p->from, A) > 1) ||
- (a.type == D_REG && copyu(p1, &a, A) > 1))
- FAIL("args modified");
- continue;
- case 3: /* set, not used */
- FAIL("BOTCH: noref");
- }
- break;
- }
- /* check whether substitution can be done */
- switch(p1->as) {
- default:
- FAIL("non-dpi");
- case AAND:
- case AEOR:
- case AADD:
- case AADC:
- case AORR:
- case ASUB:
- case ARSB:
- case ASBC:
- case ARSC:
- if(p1->reg == n || (p1->reg == NREG && p1->to.type == D_REG && p1->to.reg == n)) {
- if(p1->from.type != D_REG)
- FAIL("can't swap");
- p1->reg = p1->from.reg;
- p1->from.reg = n;
- switch(p1->as) {
- case ASUB:
- p1->as = ARSB;
- break;
- case ARSB:
- p1->as = ASUB;
- break;
- case ASBC:
- p1->as = ARSC;
- break;
- case ARSC:
- p1->as = ASBC;
- break;
- }
- if(debug['H'])
- print("\t=>%P", p1);
- }
- case ABIC:
- case ACMP:
- case ACMN:
- if(p1->reg == n)
- FAIL("can't swap");
- if(p1->reg == NREG && p1->to.reg == n)
- FAIL("shift result used twice");
- case AMVN:
- if(p1->from.type == D_SHIFT)
- FAIL("shift result used in shift");
- if(p1->from.type != D_REG || p1->from.reg != n)
- FAIL("BOTCH: where is it used?");
- break;
- }
- /* check whether shift result is used subsequently */
- p2 = p1;
- if(p1->to.reg != n)
- for (;;) {
- r1 = uniqs(r1);
- if(r1 == R)
- FAIL("inconclusive");
- p1 = r1->prog;
- if(debug['H'])
- print("\n%P", p1);
- switch(copyu(p1, &p->to, A)) {
- case 0: /* not used or set */
- continue;
- case 3: /* set, not used */
- break;
- default:/* used */
- FAIL("reused");
- }
- break;
- }
- /* make the substitution */
- p2->from.type = D_SHIFT;
- p2->from.reg = NREG;
- o = p->reg;
- if(o == NREG)
- o = p->to.reg;
- switch(p->from.type){
- case D_CONST:
- o |= (p->from.offset&0x1f)<<7;
- break;
- case D_REG:
- o |= (1<<4) | (p->from.reg<<8);
- break;
- }
- switch(p->as){
- case ASLL:
- o |= 0<<5;
- break;
- case ASRL:
- o |= 1<<5;
- break;
- case ASRA:
- o |= 2<<5;
- break;
- }
- p2->from.offset = o;
- if(debug['H'])
- print("\t=>%P\tSUCCEED\n", p2);
- return 1;
-}
-
-Reg*
-findpre(Reg *r, Addr *v)
-{
- Reg *r1;
-
- for(r1=uniqp(r); r1!=R; r=r1,r1=uniqp(r)) {
- if(uniqs(r1) != r)
- return R;
- switch(copyu(r1->prog, v, A)) {
- case 1: /* used */
- case 2: /* read-alter-rewrite */
- return R;
- case 3: /* set */
- case 4: /* set and used */
- return r1;
- }
- }
- return R;
-}
-
-Reg*
-findinc(Reg *r, Reg *r2, Addr *v)
-{
- Reg *r1;
- Prog *p;
-
-
- for(r1=uniqs(r); r1!=R && r1!=r2; r=r1,r1=uniqs(r)) {
- if(uniqp(r1) != r)
- return R;
- switch(copyu(r1->prog, v, A)) {
- case 0: /* not touched */
- continue;
- case 4: /* set and used */
- p = r1->prog;
- if(p->as == AADD)
- if(p->from.type == D_CONST)
- if(p->from.offset > -4096 && p->from.offset < 4096)
- return r1;
- default:
- return R;
- }
- }
- return R;
-}
-
-int
-nochange(Reg *r, Reg *r2, Prog *p)
-{
- Addr a[3];
- int i, n;
-
- if(r == r2)
- return 1;
- n = 0;
- if(p->reg != NREG && p->reg != p->to.reg) {
- a[n].type = D_REG;
- a[n++].reg = p->reg;
- }
- switch(p->from.type) {
- case D_SHIFT:
- a[n].type = D_REG;
- a[n++].reg = p->from.offset&0xf;
- case D_REG:
- a[n].type = D_REG;
- a[n++].reg = p->from.reg;
- }
- if(n == 0)
- return 1;
- for(; r!=R && r!=r2; r=uniqs(r)) {
- p = r->prog;
- for(i=0; i<n; i++)
- if(copyu(p, &a[i], A) > 1)
- return 0;
- }
- return 1;
-}
-
-int
-findu1(Reg *r, Addr *v)
-{
- for(; r != R; r = r->s1) {
- if(r->active)
- return 0;
- r->active = 1;
- switch(copyu(r->prog, v, A)) {
- case 1: /* used */
- case 2: /* read-alter-rewrite */
- case 4: /* set and used */
- return 1;
- case 3: /* set */
- return 0;
- }
- if(r->s2)
- if (findu1(r->s2, v))
- return 1;
- }
- return 0;
-}
-
-int
-finduse(Reg *r, Addr *v)
-{
- Reg *r1;
-
- for(r1=firstr; r1!=R; r1=r1->link)
- r1->active = 0;
- return findu1(r, v);
-}
-
-int
-xtramodes(Reg *r, Addr *a)
-{
- Reg *r1, *r2, *r3;
- Prog *p, *p1;
- Addr v;
-
- p = r->prog;
- if((p->as == AMOVB || p->as == AMOVBS) && p->from.type == D_OREG) /* byte load */
- return 0;
- v = *a;
- v.type = D_REG;
- r1 = findpre(r, &v);
- if(r1 != R) {
- p1 = r1->prog;
- if(p1->to.type == D_REG && p1->to.reg == v.reg)
- switch(p1->as) {
- case AADD:
- if(p1->from.type == D_REG ||
- (p1->from.type == D_SHIFT && (p1->from.offset&(1<<4)) == 0 &&
- ((p->as != AMOVB && p->as != AMOVBS) || (a == &p->from && (p1->from.offset&~0xf) == 0))) ||
- (p1->from.type == D_CONST &&
- p1->from.offset > -4096 && p1->from.offset < 4096))
- if(nochange(uniqs(r1), r, p1)) {
- if(a != &p->from || v.reg != p->to.reg)
- if (finduse(r->s1, &v)) {
- if(p1->reg == NREG || p1->reg == v.reg)
- /* pre-indexing */
- p->scond |= C_WBIT;
- else return 0;
- }
- switch (p1->from.type) {
- case D_REG:
- /* register offset */
- if(nacl)
- return 0;
- a->type = D_SHIFT;
- a->offset = p1->from.reg;
- break;
- case D_SHIFT:
- /* scaled register offset */
- if(nacl)
- return 0;
- a->type = D_SHIFT;
- case D_CONST:
- /* immediate offset */
- a->offset = p1->from.offset;
- break;
- }
- if(p1->reg != NREG)
- a->reg = p1->reg;
- excise(r1);
- return 1;
- }
- break;
- case AMOVW:
- if(p1->from.type == D_REG)
- if((r2 = findinc(r1, r, &p1->from)) != R) {
- for(r3=uniqs(r2); r3->prog->as==ANOP; r3=uniqs(r3))
- ;
- if(r3 == r) {
- /* post-indexing */
- p1 = r2->prog;
- a->reg = p1->to.reg;
- a->offset = p1->from.offset;
- p->scond |= C_PBIT;
- if(!finduse(r, &r1->prog->to))
- excise(r1);
- excise(r2);
- return 1;
- }
- }
- break;
- }
- }
- if(a != &p->from || a->reg != p->to.reg)
- if((r1 = findinc(r, R, &v)) != R) {
- /* post-indexing */
- p1 = r1->prog;
- a->offset = p1->from.offset;
- p->scond |= C_PBIT;
- excise(r1);
- return 1;
- }
- return 0;
-}
-
-/*
- * return
- * 1 if v only used (and substitute),
- * 2 if read-alter-rewrite
- * 3 if set
- * 4 if set and used
- * 0 otherwise (not touched)
- */
-int
-copyu(Prog *p, Addr *v, Addr *s)
-{
-
- switch(p->as) {
-
- default:
- if(debug['P'])
- print(" (?)");
- return 2;
-
- case AMOVM:
- if(v->type != D_REG)
- return 0;
- if(p->from.type == D_CONST) { /* read reglist, read/rar */
- if(s != A) {
- if(p->from.offset&(1<<v->reg))
- return 1;
- if(copysub(&p->to, v, s, 1))
- return 1;
- return 0;
- }
- if(copyau(&p->to, v)) {
- if(p->scond&C_WBIT)
- return 2;
- return 1;
- }
- if(p->from.offset&(1<<v->reg))
- return 1;
- } else { /* read/rar, write reglist */
- if(s != A) {
- if(p->to.offset&(1<<v->reg))
- return 1;
- if(copysub(&p->from, v, s, 1))
- return 1;
- return 0;
- }
- if(copyau(&p->from, v)) {
- if(p->scond&C_WBIT)
- return 2;
- if(p->to.offset&(1<<v->reg))
- return 4;
- return 1;
- }
- if(p->to.offset&(1<<v->reg))
- return 3;
- }
- return 0;
-
- case ANOP: /* read, write */
- case AMOVW:
- case AMOVF:
- case AMOVD:
- case AMOVH:
- case AMOVHS:
- case AMOVHU:
- case AMOVB:
- case AMOVBS:
- case AMOVBU:
- case AMOVDW:
- case AMOVWD:
- case AMOVFD:
- case AMOVDF:
- if(p->scond&(C_WBIT|C_PBIT))
- if(v->type == D_REG) {
- if(p->from.type == D_OREG || p->from.type == D_SHIFT) {
- if(p->from.reg == v->reg)
- return 2;
- } else {
- if(p->to.reg == v->reg)
- return 2;
- }
- }
- if(s != A) {
- if(copysub(&p->from, v, s, 1))
- return 1;
- if(!copyas(&p->to, v))
- if(copysub(&p->to, v, s, 1))
- return 1;
- return 0;
- }
- if(copyas(&p->to, v)) {
- if(copyau(&p->from, v))
- return 4;
- return 3;
- }
- if(copyau(&p->from, v))
- return 1;
- if(copyau(&p->to, v))
- return 1;
- return 0;
-
-
- case AADD: /* read, read, write */
- case ASUB:
- case ARSB:
- case ASLL:
- case ASRL:
- case ASRA:
- case AORR:
- case AAND:
- case AEOR:
- case AMUL:
- case ADIV:
- case ADIVU:
- case AADDF:
- case AADDD:
- case ASUBF:
- case ASUBD:
- case AMULF:
- case AMULD:
- case ADIVF:
- case ADIVD:
-
- case ACMPF:
- case ACMPD:
- case ACMP:
- case ACMN:
- case ACASE:
- if(s != A) {
- if(copysub(&p->from, v, s, 1))
- return 1;
- if(copysub1(p, v, s, 1))
- return 1;
- if(!copyas(&p->to, v))
- if(copysub(&p->to, v, s, 1))
- return 1;
- return 0;
- }
- if(copyas(&p->to, v)) {
- if(p->reg == NREG)
- p->reg = p->to.reg;
- if(copyau(&p->from, v))
- return 4;
- if(copyau1(p, v))
- return 4;
- return 3;
- }
- if(copyau(&p->from, v))
- return 1;
- if(copyau1(p, v))
- return 1;
- if(copyau(&p->to, v))
- return 1;
- return 0;
-
- case ABEQ: /* read, read */
- case ABNE:
- case ABCS:
- case ABHS:
- case ABCC:
- case ABLO:
- case ABMI:
- case ABPL:
- case ABVS:
- case ABVC:
- case ABHI:
- case ABLS:
- case ABGE:
- case ABLT:
- case ABGT:
- case ABLE:
- case APLD:
- if(s != A) {
- if(copysub(&p->from, v, s, 1))
- return 1;
- return copysub1(p, v, s, 1);
- }
- if(copyau(&p->from, v))
- return 1;
- if(copyau1(p, v))
- return 1;
- return 0;
-
- case AB: /* funny */
- if(s != A) {
- if(copysub(&p->to, v, s, 1))
- return 1;
- return 0;
- }
- if(copyau(&p->to, v))
- return 1;
- return 0;
-
- case ARET: /* funny */
- if(v->type == D_REG)
- if(v->reg == REGRET)
- return 2;
- if(v->type == D_FREG)
- if(v->reg == FREGRET)
- return 2;
-
- case ABL: /* funny */
- if(v->type == D_REG) {
- if(v->reg <= REGEXT && v->reg > exregoffset)
- return 2;
- if(v->reg == REGARG)
- return 2;
- }
- if(v->type == D_FREG)
- if(v->reg <= FREGEXT && v->reg > exfregoffset)
- return 2;
-
- if(s != A) {
- if(copysub(&p->to, v, s, 1))
- return 1;
- return 0;
- }
- if(copyau(&p->to, v))
- return 4;
- return 3;
-
- case ATEXT: /* funny */
- if(v->type == D_REG)
- if(v->reg == REGARG)
- return 3;
- return 0;
- }
-}
-
-int
-a2type(Prog *p)
-{
-
- switch(p->as) {
-
- case ACMP:
- case ACMN:
-
- case AADD:
- case ASUB:
- case ARSB:
- case ASLL:
- case ASRL:
- case ASRA:
- case AORR:
- case AAND:
- case AEOR:
- case AMUL:
- case ADIV:
- case ADIVU:
- return D_REG;
-
- case ACMPF:
- case ACMPD:
-
- case AADDF:
- case AADDD:
- case ASUBF:
- case ASUBD:
- case AMULF:
- case AMULD:
- case ADIVF:
- case ADIVD:
- return D_FREG;
- }
- return D_NONE;
-}
-
-/*
- * direct reference,
- * could be set/use depending on
- * semantics
- */
-int
-copyas(Addr *a, Addr *v)
-{
-
- if(regtyp(v)) {
- if(a->type == v->type)
- if(a->reg == v->reg)
- return 1;
- } else if(v->type == D_CONST) { /* for constprop */
- if(a->type == v->type)
- if(a->name == v->name)
- if(a->sym == v->sym)
- if(a->reg == v->reg)
- if(a->offset == v->offset)
- return 1;
- }
- return 0;
-}
-
-/*
- * either direct or indirect
- */
-int
-copyau(Addr *a, Addr *v)
-{
-
- if(copyas(a, v))
- return 1;
- if(v->type == D_REG) {
- if(a->type == D_OREG) {
- if(v->reg == a->reg)
- return 1;
- } else if(a->type == D_SHIFT) {
- if((a->offset&0xf) == v->reg)
- return 1;
- if((a->offset&(1<<4)) && (a->offset>>8) == v->reg)
- return 1;
- }
- }
- return 0;
-}
-
-int
-copyau1(Prog *p, Addr *v)
-{
-
- if(regtyp(v)) {
- if(a2type(p) == v->type)
- if(p->reg == v->reg) {
- if(a2type(p) != v->type)
- print("botch a2type %P\n", p);
- return 1;
- }
- }
- return 0;
-}
-
-/*
- * substitute s for v in a
- * return failure to substitute
- */
-int
-copysub(Addr *a, Addr *v, Addr *s, int f)
-{
-
- if(f)
- if(copyau(a, v)) {
- if(a->type == D_SHIFT) {
- if((a->offset&0xf) == v->reg)
- a->offset = (a->offset&~0xf)|s->reg;
- if((a->offset&(1<<4)) && (a->offset>>8) == v->reg)
- a->offset = (a->offset&~(0xf<<8))|(s->reg<<8);
- } else
- a->reg = s->reg;
- }
- return 0;
-}
-
-int
-copysub1(Prog *p1, Addr *v, Addr *s, int f)
-{
-
- if(f)
- if(copyau1(p1, v))
- p1->reg = s->reg;
- return 0;
-}
-
-struct {
- int opcode;
- int notopcode;
- int scond;
- int notscond;
-} predinfo[] = {
- { ABEQ, ABNE, 0x0, 0x1, },
- { ABNE, ABEQ, 0x1, 0x0, },
- { ABCS, ABCC, 0x2, 0x3, },
- { ABHS, ABLO, 0x2, 0x3, },
- { ABCC, ABCS, 0x3, 0x2, },
- { ABLO, ABHS, 0x3, 0x2, },
- { ABMI, ABPL, 0x4, 0x5, },
- { ABPL, ABMI, 0x5, 0x4, },
- { ABVS, ABVC, 0x6, 0x7, },
- { ABVC, ABVS, 0x7, 0x6, },
- { ABHI, ABLS, 0x8, 0x9, },
- { ABLS, ABHI, 0x9, 0x8, },
- { ABGE, ABLT, 0xA, 0xB, },
- { ABLT, ABGE, 0xB, 0xA, },
- { ABGT, ABLE, 0xC, 0xD, },
- { ABLE, ABGT, 0xD, 0xC, },
-};
-
-typedef struct {
- Reg *start;
- Reg *last;
- Reg *end;
- int len;
-} Joininfo;
-
-enum {
- Join,
- Split,
- End,
- Branch,
- Setcond,
- Toolong
-};
-
-enum {
- Falsecond,
- Truecond,
- Delbranch,
- Keepbranch
-};
-
-int
-isbranch(Prog *p)
-{
- return (ABEQ <= p->as) && (p->as <= ABLE);
-}
-
-int
-predicable(Prog *p)
-{
- if (isbranch(p)
- || p->as == ANOP
- || p->as == AXXX
- || p->as == ADATA
- || p->as == AGLOBL
- || p->as == AGOK
- || p->as == AHISTORY
- || p->as == ANAME
- || p->as == ASIGNAME
- || p->as == ATEXT
- || p->as == AWORD
- || p->as == ABCASE
- || p->as == ACASE)
- return 0;
- return 1;
-}
-
-/*
- * Depends on an analysis of the encodings performed by 5l.
- * These seem to be all of the opcodes that lead to the "S" bit
- * being set in the instruction encodings.
- *
- * C_SBIT may also have been set explicitly in p->scond.
- */
-int
-modifiescpsr(Prog *p)
-{
- return (p->scond&C_SBIT)
- || p->as == ATST
- || p->as == ATEQ
- || p->as == ACMN
- || p->as == ACMP
- || p->as == AMULU
- || p->as == ADIVU
- || p->as == AMUL
- || p->as == ADIV
- || p->as == AMOD
- || p->as == AMODU
- || p->as == ABL;
-}
-
-/*
- * Find the maximal chain of instructions starting with r which could
- * be executed conditionally
- */
-int
-joinsplit(Reg *r, Joininfo *j)
-{
- j->start = r;
- j->last = r;
- j->len = 0;
- do {
- if (r->p2 && (r->p1 || r->p2->p2link)) {
- j->end = r;
- return Join;
- }
- if (r->s1 && r->s2) {
- j->end = r;
- return Split;
- }
- j->last = r;
- if (r->prog->as != ANOP)
- j->len++;
- if (!r->s1 && !r->s2) {
- j->end = r->link;
- return End;
- }
- if (r->s2) {
- j->end = r->s2;
- return Branch;
- }
- if (modifiescpsr(r->prog)) {
- j->end = r->s1;
- return Setcond;
- }
- r = r->s1;
- } while (j->len < 4);
- j->end = r;
- return Toolong;
-}
-
-Reg *
-successor(Reg *r)
-{
- if (r->s1)
- return r->s1;
- else
- return r->s2;
-}
-
-void
-applypred(Reg *rstart, Joininfo *j, int cond, int branch)
-{
- int pred;
- Reg *r;
-
- if(j->len == 0)
- return;
- if (cond == Truecond)
- pred = predinfo[rstart->prog->as - ABEQ].scond;
- else
- pred = predinfo[rstart->prog->as - ABEQ].notscond;
-
- for (r = j->start; ; r = successor(r)) {
- if (r->prog->as == AB) {
- if (r != j->last || branch == Delbranch)
- excise(r);
- else {
- if (cond == Truecond)
- r->prog->as = predinfo[rstart->prog->as - ABEQ].opcode;
- else
- r->prog->as = predinfo[rstart->prog->as - ABEQ].notopcode;
- }
- }
- else if (predicable(r->prog))
- r->prog->scond = (r->prog->scond&~C_SCOND)|pred;
- if (r->s1 != r->link) {
- r->s1 = r->link;
- r->link->p1 = r;
- }
- if (r == j->last)
- break;
- }
-}
-
-void
-predicate(void)
-{
- Reg *r;
- int t1, t2;
- Joininfo j1, j2;
-
- for(r=firstr; r!=R; r=r->link) {
- if (isbranch(r->prog)) {
- t1 = joinsplit(r->s1, &j1);
- t2 = joinsplit(r->s2, &j2);
- if(j1.last->link != j2.start)
- continue;
- if(j1.end == j2.end)
- if((t1 == Branch && (t2 == Join || t2 == Setcond)) ||
- (t2 == Join && (t1 == Join || t1 == Setcond))) {
- applypred(r, &j1, Falsecond, Delbranch);
- applypred(r, &j2, Truecond, Delbranch);
- excise(r);
- continue;
- }
- if(t1 == End || t1 == Branch) {
- applypred(r, &j1, Falsecond, Keepbranch);
- excise(r);
- continue;
- }
- }
- }
-}
diff --git a/src/cmd/5c/reg.c b/src/cmd/5c/reg.c
deleted file mode 100644
index 9024d5f49..000000000
--- a/src/cmd/5c/reg.c
+++ /dev/null
@@ -1,1210 +0,0 @@
-// Inferno utils/5c/reg.c
-// http://code.google.com/p/inferno-os/source/browse/utils/5c/reg.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-
-#include "gc.h"
-
-void addsplits(void);
-
-Reg*
-rega(void)
-{
- Reg *r;
-
- r = freer;
- if(r == R) {
- r = alloc(sizeof(*r));
- } else
- freer = r->link;
-
- *r = zreg;
- return r;
-}
-
-int
-rcmp(const void *a1, const void *a2)
-{
- Rgn *p1, *p2;
- int c1, c2;
-
- p1 = (Rgn*)a1;
- p2 = (Rgn*)a2;
- c1 = p2->cost;
- c2 = p1->cost;
- if(c1 -= c2)
- return c1;
- return p2->varno - p1->varno;
-}
-
-void
-regopt(Prog *p)
-{
- Reg *r, *r1, *r2;
- Prog *p1;
- int i, z;
- int32 initpc, val, npc;
- uint32 vreg;
- Bits bit;
- struct
- {
- int32 m;
- int32 c;
- Reg* p;
- } log5[6], *lp;
-
- firstr = R;
- lastr = R;
- nvar = 0;
- regbits = 0;
- for(z=0; z<BITS; z++) {
- externs.b[z] = 0;
- params.b[z] = 0;
- consts.b[z] = 0;
- addrs.b[z] = 0;
- }
-
- /*
- * pass 1
- * build aux data structure
- * allocate pcs
- * find use and set of variables
- */
- val = 5L * 5L * 5L * 5L * 5L;
- lp = log5;
- for(i=0; i<5; i++) {
- lp->m = val;
- lp->c = 0;
- lp->p = R;
- val /= 5L;
- lp++;
- }
- val = 0;
- for(; p != P; p = p->link) {
- switch(p->as) {
- case ADATA:
- case AGLOBL:
- case ANAME:
- case ASIGNAME:
- case AFUNCDATA:
- continue;
- }
- r = rega();
- if(firstr == R) {
- firstr = r;
- lastr = r;
- } else {
- lastr->link = r;
- r->p1 = lastr;
- lastr->s1 = r;
- lastr = r;
- }
- r->prog = p;
- r->pc = val;
- val++;
-
- lp = log5;
- for(i=0; i<5; i++) {
- lp->c--;
- if(lp->c <= 0) {
- lp->c = lp->m;
- if(lp->p != R)
- lp->p->log5 = r;
- lp->p = r;
- (lp+1)->c = 0;
- break;
- }
- lp++;
- }
-
- r1 = r->p1;
- if(r1 != R)
- switch(r1->prog->as) {
- case ARET:
- case AB:
- case ARFE:
- r->p1 = R;
- r1->s1 = R;
- }
-
- /*
- * left side always read
- */
- bit = mkvar(&p->from, p->as==AMOVW);
- for(z=0; z<BITS; z++)
- r->use1.b[z] |= bit.b[z];
-
- /*
- * right side depends on opcode
- */
- bit = mkvar(&p->to, 0);
- if(bany(&bit))
- switch(p->as) {
- default:
- diag(Z, "reg: unknown asop: %A", p->as);
- break;
-
- /*
- * right side write
- */
- case ANOP:
- case AMOVB:
- case AMOVBS:
- case AMOVBU:
- case AMOVH:
- case AMOVHS:
- case AMOVHU:
- case AMOVW:
- case AMOVF:
- case AMOVD:
- for(z=0; z<BITS; z++)
- r->set.b[z] |= bit.b[z];
- break;
-
- /*
- * right side read
- */
- case APLD:
- for(z=0; z<BITS; z++)
- r->use2.b[z] |= bit.b[z];
- break;
-
- /*
- * funny
- */
- case ABL:
- for(z=0; z<BITS; z++)
- addrs.b[z] |= bit.b[z];
- break;
- }
-
- /* the mod/div runtime routines smash R12 */
- switch(p->as) {
- case AMOD:
- case AMODU:
- case ADIV:
- case ADIVU:
- regbits |= RtoB(12);
- break;
- }
-
- if(p->as == AMOVM) {
- if(p->from.type == D_CONST)
- z = p->from.offset;
- else
- z = p->to.offset;
- for(i=0; z; i++) {
- if(z&1)
- regbits |= RtoB(i);
- z >>= 1;
- }
- }
- }
- if(firstr == R)
- return;
- initpc = pc - val;
- npc = val;
-
- /*
- * pass 2
- * turn branch references to pointers
- * build back pointers
- */
- for(r = firstr; r != R; r = r->link) {
- p = r->prog;
- if(p->to.type == D_BRANCH) {
- val = p->to.offset - initpc;
- r1 = firstr;
- while(r1 != R) {
- r2 = r1->log5;
- if(r2 != R && val >= r2->pc) {
- r1 = r2;
- continue;
- }
- if(r1->pc == val)
- break;
- r1 = r1->link;
- }
- if(r1 == R) {
- nearln = p->lineno;
- diag(Z, "ref not found\n%P", p);
- continue;
- }
- if(r1 == r) {
- nearln = p->lineno;
- diag(Z, "ref to self\n%P", p);
- continue;
- }
- r->s2 = r1;
- r->p2link = r1->p2;
- r1->p2 = r;
- }
- }
- if(debug['R']) {
- p = firstr->prog;
- print("\n%L %D\n", p->lineno, &p->from);
- }
-
- /*
- * pass 2.5
- * find looping structure
- */
- for(r = firstr; r != R; r = r->link)
- r->active = 0;
- change = 0;
- loopit(firstr, npc);
-
- /*
- * pass 3
- * iterate propagating usage
- * back until flow graph is complete
- */
-loop1:
- change = 0;
- for(r = firstr; r != R; r = r->link)
- r->active = 0;
- for(r = firstr; r != R; r = r->link)
- if(r->prog->as == ARET)
- prop(r, zbits, zbits);
-loop11:
- /* pick up unreachable code */
- i = 0;
- for(r = firstr; r != R; r = r1) {
- r1 = r->link;
- if(r1 && r1->active && !r->active) {
- prop(r, zbits, zbits);
- i = 1;
- }
- }
- if(i)
- goto loop11;
- if(change)
- goto loop1;
-
-
- /*
- * pass 4
- * iterate propagating register/variable synchrony
- * forward until graph is complete
- */
-loop2:
- change = 0;
- for(r = firstr; r != R; r = r->link)
- r->active = 0;
- synch(firstr, zbits);
- if(change)
- goto loop2;
-
- addsplits();
-
- if(debug['R'] && debug['v']) {
- print("\nprop structure:\n");
- for(r = firstr; r != R; r = r->link) {
- print("%d:%P", r->loop, r->prog);
- for(z=0; z<BITS; z++)
- bit.b[z] = r->set.b[z] |
- r->refahead.b[z] | r->calahead.b[z] |
- r->refbehind.b[z] | r->calbehind.b[z] |
- r->use1.b[z] | r->use2.b[z];
- if(bany(&bit)) {
- print("\t");
- if(bany(&r->use1))
- print(" u1=%B", r->use1);
- if(bany(&r->use2))
- print(" u2=%B", r->use2);
- if(bany(&r->set))
- print(" st=%B", r->set);
- if(bany(&r->refahead))
- print(" ra=%B", r->refahead);
- if(bany(&r->calahead))
- print(" ca=%B", r->calahead);
- if(bany(&r->refbehind))
- print(" rb=%B", r->refbehind);
- if(bany(&r->calbehind))
- print(" cb=%B", r->calbehind);
- }
- print("\n");
- }
- }
-
- /*
- * pass 5
- * isolate regions
- * calculate costs (paint1)
- */
- r = firstr;
- if(r) {
- for(z=0; z<BITS; z++)
- bit.b[z] = (r->refahead.b[z] | r->calahead.b[z]) &
- ~(externs.b[z] | params.b[z] | addrs.b[z] | consts.b[z]);
- if(bany(&bit)) {
- nearln = r->prog->lineno;
- warn(Z, "used and not set: %B", bit);
- if(debug['R'] && !debug['w'])
- print("used and not set: %B\n", bit);
- }
- }
-
- for(r = firstr; r != R; r = r->link)
- r->act = zbits;
- rgp = region;
- nregion = 0;
- for(r = firstr; r != R; r = r->link) {
- for(z=0; z<BITS; z++)
- bit.b[z] = r->set.b[z] &
- ~(r->refahead.b[z] | r->calahead.b[z] | addrs.b[z]);
- if(bany(&bit)) {
- nearln = r->prog->lineno;
- warn(Z, "set and not used: %B", bit);
- if(debug['R'])
- print("set and not used: %B\n", bit);
- excise(r);
- }
- for(z=0; z<BITS; z++)
- bit.b[z] = LOAD(r) & ~(r->act.b[z] | addrs.b[z]);
- while(bany(&bit)) {
- i = bnum(bit);
- rgp->enter = r;
- rgp->varno = i;
- change = 0;
- if(debug['R'] && debug['v'])
- print("\n");
- paint1(r, i);
- bit.b[i/32] &= ~(1L<<(i%32));
- if(change <= 0) {
- if(debug['R'])
- print("%L $%d: %B\n",
- r->prog->lineno, change, blsh(i));
- continue;
- }
- rgp->cost = change;
- nregion++;
- if(nregion >= NRGN) {
- fatal(Z, "too many regions");
- goto brk;
- }
- rgp++;
- }
- }
-brk:
- qsort(region, nregion, sizeof(region[0]), rcmp);
-
- /*
- * pass 6
- * determine used registers (paint2)
- * replace code (paint3)
- */
- rgp = region;
- for(i=0; i<nregion; i++) {
- bit = blsh(rgp->varno);
- vreg = paint2(rgp->enter, rgp->varno);
- vreg = allreg(vreg, rgp);
- if(debug['R']) {
- if(rgp->regno >= NREG)
- print("%L $%d F%d: %B\n",
- rgp->enter->prog->lineno,
- rgp->cost,
- rgp->regno-NREG,
- bit);
- else
- print("%L $%d R%d: %B\n",
- rgp->enter->prog->lineno,
- rgp->cost,
- rgp->regno,
- bit);
- }
- if(rgp->regno != 0)
- paint3(rgp->enter, rgp->varno, vreg, rgp->regno);
- rgp++;
- }
- /*
- * pass 7
- * peep-hole on basic block
- */
- if(!debug['R'] || debug['P'])
- peep();
-
- /*
- * pass 8
- * recalculate pc
- */
- val = initpc;
- for(r = firstr; r != R; r = r1) {
- r->pc = val;
- p = r->prog;
- p1 = P;
- r1 = r->link;
- if(r1 != R)
- p1 = r1->prog;
- for(; p != p1; p = p->link) {
- switch(p->as) {
- default:
- val++;
- break;
-
- case ANOP:
- case ADATA:
- case AGLOBL:
- case ANAME:
- case ASIGNAME:
- case AFUNCDATA:
- break;
- }
- }
- }
- pc = val;
-
- /*
- * fix up branches
- */
- if(debug['R'])
- if(bany(&addrs))
- print("addrs: %B\n", addrs);
-
- r1 = 0; /* set */
- for(r = firstr; r != R; r = r->link) {
- p = r->prog;
- if(p->to.type == D_BRANCH) {
- p->to.offset = r->s2->pc;
- p->to.u.branch = r->s2->prog;
- }
- r1 = r;
- }
-
- /*
- * last pass
- * eliminate nops
- * free aux structures
- */
- for(p = firstr->prog; p != P; p = p->link){
- while(p->link && p->link->as == ANOP)
- p->link = p->link->link;
- }
- if(r1 != R) {
- r1->link = freer;
- freer = firstr;
- }
-}
-
-void
-addsplits(void)
-{
- Reg *r, *r1;
- int z, i;
- Bits bit;
-
- for(r = firstr; r != R; r = r->link) {
- if(r->loop > 1)
- continue;
- if(r->prog->as == ABL)
- continue;
- for(r1 = r->p2; r1 != R; r1 = r1->p2link) {
- if(r1->loop <= 1)
- continue;
- for(z=0; z<BITS; z++)
- bit.b[z] = r1->calbehind.b[z] &
- (r->refahead.b[z] | r->use1.b[z] | r->use2.b[z]) &
- ~(r->calahead.b[z] & addrs.b[z]);
- while(bany(&bit)) {
- i = bnum(bit);
- bit.b[i/32] &= ~(1L << (i%32));
- }
- }
- }
-}
-
-/*
- * add mov b,rn
- * just after r
- */
-void
-addmove(Reg *r, int bn, int rn, int f)
-{
- Prog *p, *p1;
- Addr *a;
- Var *v;
-
- p1 = alloc(sizeof(*p1));
- *p1 = zprog;
- p = r->prog;
-
- p1->link = p->link;
- p->link = p1;
- p1->lineno = p->lineno;
-
- v = var + bn;
-
- a = &p1->to;
- a->sym = v->sym;
- a->name = v->name;
- a->offset = v->offset;
- a->etype = v->etype;
- a->type = D_OREG;
- if(a->etype == TARRAY || a->sym == nil)
- a->type = D_CONST;
-
- p1->as = AMOVW;
- if(v->etype == TCHAR || v->etype == TUCHAR)
- p1->as = AMOVBS;
- if(v->etype == TSHORT || v->etype == TUSHORT)
- p1->as = AMOVHS;
- if(v->etype == TFLOAT)
- p1->as = AMOVF;
- if(v->etype == TDOUBLE)
- p1->as = AMOVD;
-
- p1->from.type = D_REG;
- p1->from.reg = rn;
- if(rn >= NREG) {
- p1->from.type = D_FREG;
- p1->from.reg = rn-NREG;
- }
- if(!f) {
- p1->from = *a;
- *a = zprog.from;
- a->type = D_REG;
- a->reg = rn;
- if(rn >= NREG) {
- a->type = D_FREG;
- a->reg = rn-NREG;
- }
- if(v->etype == TUCHAR)
- p1->as = AMOVBU;
- if(v->etype == TUSHORT)
- p1->as = AMOVHU;
- }
- if(debug['R'])
- print("%P\t.a%P\n", p, p1);
-}
-
-Bits
-mkvar(Addr *a, int docon)
-{
- Var *v;
- int i, t, n, et, z;
- int32 o;
- Bits bit;
- LSym *s;
-
- t = a->type;
- if(t == D_REG && a->reg != NREG)
- regbits |= RtoB(a->reg);
- if(t == D_FREG && a->reg != NREG)
- regbits |= FtoB(a->reg);
- s = a->sym;
- o = a->offset;
- et = a->etype;
- if(s == nil) {
- if(t != D_CONST || !docon || a->reg != NREG)
- goto none;
- et = TLONG;
- }
- if(t == D_CONST) {
- if(s == nil && sval(o))
- goto none;
- }
-
- n = a->name;
- v = var;
- for(i=0; i<nvar; i++) {
- if(s == v->sym)
- if(n == v->name)
- if(o == v->offset)
- goto out;
- v++;
- }
- if(s)
- if(s->name[0] == '.')
- goto none;
- if(nvar >= NVAR)
- fatal(Z, "variable not optimized: %s", s->name);
- i = nvar;
- nvar++;
- v = &var[i];
- v->sym = s;
- v->offset = o;
- v->etype = et;
- v->name = n;
- if(debug['R'])
- print("bit=%2d et=%2d %D\n", i, et, a);
-out:
- bit = blsh(i);
- if(n == D_EXTERN || n == D_STATIC)
- for(z=0; z<BITS; z++)
- externs.b[z] |= bit.b[z];
- if(n == D_PARAM)
- for(z=0; z<BITS; z++)
- params.b[z] |= bit.b[z];
- if(v->etype != et || !typechlpfd[et]) /* funny punning */
- for(z=0; z<BITS; z++)
- addrs.b[z] |= bit.b[z];
- if(t == D_CONST) {
- if(s == nil) {
- for(z=0; z<BITS; z++)
- consts.b[z] |= bit.b[z];
- return bit;
- }
- if(et != TARRAY)
- for(z=0; z<BITS; z++)
- addrs.b[z] |= bit.b[z];
- for(z=0; z<BITS; z++)
- params.b[z] |= bit.b[z];
- return bit;
- }
- if(t == D_OREG)
- return bit;
-
-none:
- return zbits;
-}
-
-void
-prop(Reg *r, Bits ref, Bits cal)
-{
- Reg *r1, *r2;
- int z;
-
- for(r1 = r; r1 != R; r1 = r1->p1) {
- for(z=0; z<BITS; z++) {
- ref.b[z] |= r1->refahead.b[z];
- if(ref.b[z] != r1->refahead.b[z]) {
- r1->refahead.b[z] = ref.b[z];
- change++;
- }
- cal.b[z] |= r1->calahead.b[z];
- if(cal.b[z] != r1->calahead.b[z]) {
- r1->calahead.b[z] = cal.b[z];
- change++;
- }
- }
- switch(r1->prog->as) {
- case ABL:
- for(z=0; z<BITS; z++) {
- cal.b[z] |= ref.b[z] | externs.b[z];
- ref.b[z] = 0;
- }
- break;
-
- case ATEXT:
- for(z=0; z<BITS; z++) {
- cal.b[z] = 0;
- ref.b[z] = 0;
- }
- break;
-
- case ARET:
- for(z=0; z<BITS; z++) {
- cal.b[z] = externs.b[z];
- ref.b[z] = 0;
- }
- }
- for(z=0; z<BITS; z++) {
- ref.b[z] = (ref.b[z] & ~r1->set.b[z]) |
- r1->use1.b[z] | r1->use2.b[z];
- cal.b[z] &= ~(r1->set.b[z] | r1->use1.b[z] | r1->use2.b[z]);
- r1->refbehind.b[z] = ref.b[z];
- r1->calbehind.b[z] = cal.b[z];
- }
- if(r1->active)
- break;
- r1->active = 1;
- }
- for(; r != r1; r = r->p1)
- for(r2 = r->p2; r2 != R; r2 = r2->p2link)
- prop(r2, r->refbehind, r->calbehind);
-}
-
-/*
- * find looping structure
- *
- * 1) find reverse postordering
- * 2) find approximate dominators,
- * the actual dominators if the flow graph is reducible
- * otherwise, dominators plus some other non-dominators.
- * See Matthew S. Hecht and Jeffrey D. Ullman,
- * "Analysis of a Simple Algorithm for Global Data Flow Problems",
- * Conf. Record of ACM Symp. on Principles of Prog. Langs, Boston, Massachusetts,
- * Oct. 1-3, 1973, pp. 207-217.
- * 3) find all nodes with a predecessor dominated by the current node.
- * such a node is a loop head.
- * recursively, all preds with a greater rpo number are in the loop
- */
-int32
-postorder(Reg *r, Reg **rpo2r, int32 n)
-{
- Reg *r1;
-
- r->rpo = 1;
- r1 = r->s1;
- if(r1 && !r1->rpo)
- n = postorder(r1, rpo2r, n);
- r1 = r->s2;
- if(r1 && !r1->rpo)
- n = postorder(r1, rpo2r, n);
- rpo2r[n] = r;
- n++;
- return n;
-}
-
-int32
-rpolca(int32 *idom, int32 rpo1, int32 rpo2)
-{
- int32 t;
-
- if(rpo1 == -1)
- return rpo2;
- while(rpo1 != rpo2){
- if(rpo1 > rpo2){
- t = rpo2;
- rpo2 = rpo1;
- rpo1 = t;
- }
- while(rpo1 < rpo2){
- t = idom[rpo2];
- if(t >= rpo2)
- fatal(Z, "bad idom");
- rpo2 = t;
- }
- }
- return rpo1;
-}
-
-int
-doms(int32 *idom, int32 r, int32 s)
-{
- while(s > r)
- s = idom[s];
- return s == r;
-}
-
-int
-loophead(int32 *idom, Reg *r)
-{
- int32 src;
-
- src = r->rpo;
- if(r->p1 != R && doms(idom, src, r->p1->rpo))
- return 1;
- for(r = r->p2; r != R; r = r->p2link)
- if(doms(idom, src, r->rpo))
- return 1;
- return 0;
-}
-
-void
-loopmark(Reg **rpo2r, int32 head, Reg *r)
-{
- if(r->rpo < head || r->active == head)
- return;
- r->active = head;
- r->loop += LOOP;
- if(r->p1 != R)
- loopmark(rpo2r, head, r->p1);
- for(r = r->p2; r != R; r = r->p2link)
- loopmark(rpo2r, head, r);
-}
-
-void
-loopit(Reg *r, int32 nr)
-{
- Reg *r1;
- int32 i, d, me;
-
- if(nr > maxnr) {
- rpo2r = alloc(nr * sizeof(Reg*));
- idom = alloc(nr * sizeof(int32));
- maxnr = nr;
- }
- d = postorder(r, rpo2r, 0);
- if(d > nr)
- fatal(Z, "too many reg nodes");
- nr = d;
- for(i = 0; i < nr / 2; i++){
- r1 = rpo2r[i];
- rpo2r[i] = rpo2r[nr - 1 - i];
- rpo2r[nr - 1 - i] = r1;
- }
- for(i = 0; i < nr; i++)
- rpo2r[i]->rpo = i;
-
- idom[0] = 0;
- for(i = 0; i < nr; i++){
- r1 = rpo2r[i];
- me = r1->rpo;
- d = -1;
- if(r1->p1 != R && r1->p1->rpo < me)
- d = r1->p1->rpo;
- for(r1 = r1->p2; r1 != nil; r1 = r1->p2link)
- if(r1->rpo < me)
- d = rpolca(idom, d, r1->rpo);
- idom[i] = d;
- }
-
- for(i = 0; i < nr; i++){
- r1 = rpo2r[i];
- r1->loop++;
- if(r1->p2 != R && loophead(idom, r1))
- loopmark(rpo2r, i, r1);
- }
-}
-
-void
-synch(Reg *r, Bits dif)
-{
- Reg *r1;
- int z;
-
- for(r1 = r; r1 != R; r1 = r1->s1) {
- for(z=0; z<BITS; z++) {
- dif.b[z] = (dif.b[z] &
- ~(~r1->refbehind.b[z] & r1->refahead.b[z])) |
- r1->set.b[z] | r1->regdiff.b[z];
- if(dif.b[z] != r1->regdiff.b[z]) {
- r1->regdiff.b[z] = dif.b[z];
- change++;
- }
- }
- if(r1->active)
- break;
- r1->active = 1;
- for(z=0; z<BITS; z++)
- dif.b[z] &= ~(~r1->calbehind.b[z] & r1->calahead.b[z]);
- if(r1->s2 != R)
- synch(r1->s2, dif);
- }
-}
-
-uint32
-allreg(uint32 b, Rgn *r)
-{
- Var *v;
- int i;
-
- v = var + r->varno;
- r->regno = 0;
- switch(v->etype) {
-
- default:
- diag(Z, "unknown etype %d/%d", bitno(b), v->etype);
- break;
-
- case TCHAR:
- case TUCHAR:
- case TSHORT:
- case TUSHORT:
- case TINT:
- case TUINT:
- case TLONG:
- case TULONG:
- case TIND:
- case TARRAY:
- i = BtoR(~b);
- if(i && r->cost >= 0) {
- r->regno = i;
- return RtoB(i);
- }
- break;
-
- case TVLONG:
- case TDOUBLE:
- case TFLOAT:
- i = BtoF(~b);
- if(i && r->cost >= 0) {
- r->regno = i+NREG;
- return FtoB(i);
- }
- break;
- }
- return 0;
-}
-
-void
-paint1(Reg *r, int bn)
-{
- Reg *r1;
- Prog *p;
- int z;
- uint32 bb;
-
- z = bn/32;
- bb = 1L<<(bn%32);
- if(r->act.b[z] & bb)
- return;
- for(;;) {
- if(!(r->refbehind.b[z] & bb))
- break;
- r1 = r->p1;
- if(r1 == R)
- break;
- if(!(r1->refahead.b[z] & bb))
- break;
- if(r1->act.b[z] & bb)
- break;
- r = r1;
- }
-
- if(LOAD(r) & ~(r->set.b[z] & ~(r->use1.b[z]|r->use2.b[z])) & bb) {
- change -= CLOAD * r->loop;
- if(debug['R'] && debug['v'])
- print("%d%P\td %B $%d\n", r->loop,
- r->prog, blsh(bn), change);
- }
- for(;;) {
- r->act.b[z] |= bb;
- p = r->prog;
-
- if(r->use1.b[z] & bb) {
- change += CREF * r->loop;
- if(debug['R'] && debug['v'])
- print("%d%P\tu1 %B $%d\n", r->loop,
- p, blsh(bn), change);
- }
-
- if((r->use2.b[z]|r->set.b[z]) & bb) {
- change += CREF * r->loop;
- if(debug['R'] && debug['v'])
- print("%d%P\tu2 %B $%d\n", r->loop,
- p, blsh(bn), change);
- }
-
- if(STORE(r) & r->regdiff.b[z] & bb) {
- change -= CLOAD * r->loop;
- if(debug['R'] && debug['v'])
- print("%d%P\tst %B $%d\n", r->loop,
- p, blsh(bn), change);
- }
-
- if(r->refbehind.b[z] & bb)
- for(r1 = r->p2; r1 != R; r1 = r1->p2link)
- if(r1->refahead.b[z] & bb)
- paint1(r1, bn);
-
- if(!(r->refahead.b[z] & bb))
- break;
- r1 = r->s2;
- if(r1 != R)
- if(r1->refbehind.b[z] & bb)
- paint1(r1, bn);
- r = r->s1;
- if(r == R)
- break;
- if(r->act.b[z] & bb)
- break;
- if(!(r->refbehind.b[z] & bb))
- break;
- }
-}
-
-uint32
-paint2(Reg *r, int bn)
-{
- Reg *r1;
- int z;
- uint32 bb, vreg;
-
- z = bn/32;
- bb = 1L << (bn%32);
- vreg = regbits;
- if(!(r->act.b[z] & bb))
- return vreg;
- for(;;) {
- if(!(r->refbehind.b[z] & bb))
- break;
- r1 = r->p1;
- if(r1 == R)
- break;
- if(!(r1->refahead.b[z] & bb))
- break;
- if(!(r1->act.b[z] & bb))
- break;
- r = r1;
- }
- for(;;) {
- r->act.b[z] &= ~bb;
-
- vreg |= r->regu;
-
- if(r->refbehind.b[z] & bb)
- for(r1 = r->p2; r1 != R; r1 = r1->p2link)
- if(r1->refahead.b[z] & bb)
- vreg |= paint2(r1, bn);
-
- if(!(r->refahead.b[z] & bb))
- break;
- r1 = r->s2;
- if(r1 != R)
- if(r1->refbehind.b[z] & bb)
- vreg |= paint2(r1, bn);
- r = r->s1;
- if(r == R)
- break;
- if(!(r->act.b[z] & bb))
- break;
- if(!(r->refbehind.b[z] & bb))
- break;
- }
- return vreg;
-}
-
-void
-paint3(Reg *r, int bn, int32 rb, int rn)
-{
- Reg *r1;
- Prog *p;
- int z;
- uint32 bb;
-
- z = bn/32;
- bb = 1L << (bn%32);
- if(r->act.b[z] & bb)
- return;
- for(;;) {
- if(!(r->refbehind.b[z] & bb))
- break;
- r1 = r->p1;
- if(r1 == R)
- break;
- if(!(r1->refahead.b[z] & bb))
- break;
- if(r1->act.b[z] & bb)
- break;
- r = r1;
- }
-
- if(LOAD(r) & ~(r->set.b[z] & ~(r->use1.b[z]|r->use2.b[z])) & bb)
- addmove(r, bn, rn, 0);
- for(;;) {
- r->act.b[z] |= bb;
- p = r->prog;
-
- if(r->use1.b[z] & bb) {
- if(debug['R'])
- print("%P", p);
- addreg(&p->from, rn);
- if(debug['R'])
- print("\t.c%P\n", p);
- }
- if((r->use2.b[z]|r->set.b[z]) & bb) {
- if(debug['R'])
- print("%P", p);
- addreg(&p->to, rn);
- if(debug['R'])
- print("\t.c%P\n", p);
- }
-
- if(STORE(r) & r->regdiff.b[z] & bb)
- addmove(r, bn, rn, 1);
- r->regu |= rb;
-
- if(r->refbehind.b[z] & bb)
- for(r1 = r->p2; r1 != R; r1 = r1->p2link)
- if(r1->refahead.b[z] & bb)
- paint3(r1, bn, rb, rn);
-
- if(!(r->refahead.b[z] & bb))
- break;
- r1 = r->s2;
- if(r1 != R)
- if(r1->refbehind.b[z] & bb)
- paint3(r1, bn, rb, rn);
- r = r->s1;
- if(r == R)
- break;
- if(r->act.b[z] & bb)
- break;
- if(!(r->refbehind.b[z] & bb))
- break;
- }
-}
-
-void
-addreg(Addr *a, int rn)
-{
-
- a->sym = 0;
- a->name = D_NONE;
- a->type = D_REG;
- a->reg = rn;
- if(rn >= NREG) {
- a->type = D_FREG;
- a->reg = rn-NREG;
- }
-}
-
-/*
- * bit reg
- * 0 R0
- * 1 R1
- * ... ...
- * 10 R10
- * 12 R12
- */
-int32
-RtoB(int r)
-{
-
- if(r < 2 || (r >= REGTMP-2 && r != 12)) // excluded R9 and R10 for m and g, but not R12
- return 0;
- return 1L << r;
-}
-
-int
-BtoR(int32 b)
-{
- b &= 0x11fcL; // excluded R9 and R10 for m and g, but not R12
- if(b == 0)
- return 0;
- return bitno(b);
-}
-
-/*
- * bit reg
- * 18 F2
- * 19 F3
- * ... ...
- * 31 F15
- */
-int32
-FtoB(int f)
-{
-
- if(f < 2 || f > NFREG-1)
- return 0;
- return 1L << (f + 16);
-}
-
-int
-BtoF(int32 b)
-{
-
- b &= 0xfffc0000L;
- if(b == 0)
- return 0;
- return bitno(b) - 16;
-}
diff --git a/src/cmd/5c/sgen.c b/src/cmd/5c/sgen.c
deleted file mode 100644
index a36612caa..000000000
--- a/src/cmd/5c/sgen.c
+++ /dev/null
@@ -1,265 +0,0 @@
-// Inferno utils/5c/sgen.c
-// http://code.google.com/p/inferno-os/source/browse/utils/5c/sgen.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-
-#include "gc.h"
-
-Prog*
-gtext(Sym *s, int32 stkoff)
-{
- int32 a;
-
- a = argsize(1);
- if((textflag & NOSPLIT) != 0 && stkoff >= 128)
- yyerror("stack frame too large for NOSPLIT function");
-
- gpseudo(ATEXT, s, nodconst(stkoff));
- p->to.type = D_CONST2;
- p->to.offset2 = a;
- return p;
-}
-
-void
-noretval(int n)
-{
-
- if(n & 1) {
- gins(ANOP, Z, Z);
- p->to.type = D_REG;
- p->to.reg = REGRET;
- }
- if(n & 2) {
- gins(ANOP, Z, Z);
- p->to.type = D_FREG;
- p->to.reg = FREGRET;
- }
-}
-
-/*
- * calculate addressability as follows
- * CONST ==> 20 $value
- * NAME ==> 10 name
- * REGISTER ==> 11 register
- * INDREG ==> 12 *[(reg)+offset]
- * &10 ==> 2 $name
- * ADD(2, 20) ==> 2 $name+offset
- * ADD(3, 20) ==> 3 $(reg)+offset
- * &12 ==> 3 $(reg)+offset
- * *11 ==> 11 ??
- * *2 ==> 10 name
- * *3 ==> 12 *(reg)+offset
- * calculate complexity (number of registers)
- */
-void
-xcom(Node *n)
-{
- Node *l, *r;
- int t;
-
- if(n == Z)
- return;
- l = n->left;
- r = n->right;
- n->addable = 0;
- n->complex = 0;
- switch(n->op) {
- case OCONST:
- n->addable = 20;
- return;
-
- case OREGISTER:
- n->addable = 11;
- return;
-
- case OINDREG:
- n->addable = 12;
- return;
-
- case ONAME:
- n->addable = 10;
- return;
-
- case OADDR:
- xcom(l);
- if(l->addable == 10)
- n->addable = 2;
- if(l->addable == 12)
- n->addable = 3;
- break;
-
- case OIND:
- xcom(l);
- if(l->addable == 11)
- n->addable = 12;
- if(l->addable == 3)
- n->addable = 12;
- if(l->addable == 2)
- n->addable = 10;
- break;
-
- case OADD:
- xcom(l);
- xcom(r);
- if(l->addable == 20) {
- if(r->addable == 2)
- n->addable = 2;
- if(r->addable == 3)
- n->addable = 3;
- }
- if(r->addable == 20) {
- if(l->addable == 2)
- n->addable = 2;
- if(l->addable == 3)
- n->addable = 3;
- }
- break;
-
- case OASLMUL:
- case OASMUL:
- xcom(l);
- xcom(r);
- t = vlog(r);
- if(t >= 0) {
- n->op = OASASHL;
- r->vconst = t;
- r->type = types[TINT];
- }
- break;
-
- case OMUL:
- case OLMUL:
- xcom(l);
- xcom(r);
- t = vlog(r);
- if(t >= 0) {
- n->op = OASHL;
- r->vconst = t;
- r->type = types[TINT];
- }
- t = vlog(l);
- if(t >= 0) {
- n->op = OASHL;
- n->left = r;
- n->right = l;
- r = l;
- l = n->left;
- r->vconst = t;
- r->type = types[TINT];
- }
- break;
-
- case OASLDIV:
- xcom(l);
- xcom(r);
- t = vlog(r);
- if(t >= 0) {
- n->op = OASLSHR;
- r->vconst = t;
- r->type = types[TINT];
- }
- break;
-
- case OLDIV:
- xcom(l);
- xcom(r);
- t = vlog(r);
- if(t >= 0) {
- n->op = OLSHR;
- r->vconst = t;
- r->type = types[TINT];
- }
- break;
-
- case OASLMOD:
- xcom(l);
- xcom(r);
- t = vlog(r);
- if(t >= 0) {
- n->op = OASAND;
- r->vconst--;
- }
- break;
-
- case OLMOD:
- xcom(l);
- xcom(r);
- t = vlog(r);
- if(t >= 0) {
- n->op = OAND;
- r->vconst--;
- }
- break;
-
- default:
- if(l != Z)
- xcom(l);
- if(r != Z)
- xcom(r);
- break;
- }
- if(n->addable >= 10)
- return;
-
- if(l != Z)
- n->complex = l->complex;
- if(r != Z) {
- if(r->complex == n->complex)
- n->complex = r->complex+1;
- else
- if(r->complex > n->complex)
- n->complex = r->complex;
- }
- if(n->complex == 0)
- n->complex++;
-
- if(com64(n))
- return;
-
- switch(n->op) {
- case OFUNC:
- n->complex = FNX;
- break;
-
- case OADD:
- case OXOR:
- case OAND:
- case OOR:
- case OEQ:
- case ONE:
- /*
- * immediate operators, make const on right
- */
- if(l->op == OCONST) {
- n->left = r;
- n->right = l;
- }
- break;
- }
-}
diff --git a/src/cmd/5c/swt.c b/src/cmd/5c/swt.c
deleted file mode 100644
index f39963b8f..000000000
--- a/src/cmd/5c/swt.c
+++ /dev/null
@@ -1,461 +0,0 @@
-// Inferno utils/5c/swt.c
-// http://code.google.com/p/inferno-os/source/browse/utils/5c/swt.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-
-void
-swit1(C1 *q, int nc, int32 def, Node *n)
-{
- Node nreg;
-
- if(typev[n->type->etype]) {
- regsalloc(&nreg, n);
- nreg.type = types[TVLONG];
- cgen(n, &nreg);
- swit2(q, nc, def, &nreg);
- return;
- }
-
- regalloc(&nreg, n, Z);
- nreg.type = types[TLONG];
- cgen(n, &nreg);
- swit2(q, nc, def, &nreg);
- regfree(&nreg);
-}
-
-void
-swit2(C1 *q, int nc, int32 def, Node *n)
-{
- C1 *r;
- int i;
- int32 v;
- Prog *sp;
-
- if(nc >= 3) {
- i = (q+nc-1)->val - (q+0)->val;
- if(!nacl && i > 0 && i < nc*2)
- goto direct;
- }
- if(nc < 5) {
- for(i=0; i<nc; i++) {
- if(debug['W'])
- print("case = %.8ux\n", q->val);
- gopcode(OEQ, nodconst(q->val), n, Z);
- patch(p, q->label);
- q++;
- }
- gbranch(OGOTO);
- patch(p, def);
- return;
- }
-
- i = nc / 2;
- r = q+i;
- if(debug['W'])
- print("case > %.8ux\n", r->val);
- gopcode(OGT, nodconst(r->val), n, Z);
- sp = p;
- gopcode(OEQ, nodconst(r->val), n, Z); /* just gen the B.EQ */
- patch(p, r->label);
- swit2(q, i, def, n);
-
- if(debug['W'])
- print("case < %.8ux\n", r->val);
- patch(sp, pc);
- swit2(r+1, nc-i-1, def, n);
- return;
-
-direct:
- v = q->val;
- if(v != 0)
- gopcode(OSUB, nodconst(v), Z, n);
- gopcode(OCASE, nodconst((q+nc-1)->val - v), n, Z);
- patch(p, def);
- for(i=0; i<nc; i++) {
- if(debug['W'])
- print("case = %.8ux\n", q->val);
- while(q->val != v) {
- nextpc();
- p->as = ABCASE;
- patch(p, def);
- v++;
- }
- nextpc();
- p->as = ABCASE;
- patch(p, q->label);
- q++;
- v++;
- }
- gbranch(OGOTO); /* so that regopt() won't be confused */
- patch(p, def);
-}
-
-void
-bitload(Node *b, Node *n1, Node *n2, Node *n3, Node *nn)
-{
- int sh;
- int32 v;
- Node *l;
-
- /*
- * n1 gets adjusted/masked value
- * n2 gets address of cell
- * n3 gets contents of cell
- */
- l = b->left;
- if(n2 != Z) {
- regalloc(n1, l, nn);
- reglcgen(n2, l, Z);
- regalloc(n3, l, Z);
- gopcode(OAS, n2, Z, n3);
- gopcode(OAS, n3, Z, n1);
- } else {
- regalloc(n1, l, nn);
- cgen(l, n1);
- }
- if(b->type->shift == 0 && typeu[b->type->etype]) {
- v = ~0 + (1L << b->type->nbits);
- gopcode(OAND, nodconst(v), Z, n1);
- } else {
- sh = 32 - b->type->shift - b->type->nbits;
- if(sh > 0)
- gopcode(OASHL, nodconst(sh), Z, n1);
- sh += b->type->shift;
- if(sh > 0)
- if(typeu[b->type->etype])
- gopcode(OLSHR, nodconst(sh), Z, n1);
- else
- gopcode(OASHR, nodconst(sh), Z, n1);
- }
-}
-
-void
-bitstore(Node *b, Node *n1, Node *n2, Node *n3, Node *nn)
-{
- int32 v;
- Node nod, *l;
- int sh;
-
- /*
- * n1 has adjusted/masked value
- * n2 has address of cell
- * n3 has contents of cell
- */
- l = b->left;
- regalloc(&nod, l, Z);
- v = ~0 + (1L << b->type->nbits);
- gopcode(OAND, nodconst(v), Z, n1);
- gopcode(OAS, n1, Z, &nod);
- if(nn != Z)
- gopcode(OAS, n1, Z, nn);
- sh = b->type->shift;
- if(sh > 0)
- gopcode(OASHL, nodconst(sh), Z, &nod);
- v <<= sh;
- gopcode(OAND, nodconst(~v), Z, n3);
- gopcode(OOR, n3, Z, &nod);
- gopcode(OAS, &nod, Z, n2);
-
- regfree(&nod);
- regfree(n1);
- regfree(n2);
- regfree(n3);
-}
-
-int32
-outstring(char *s, int32 n)
-{
- int32 r;
-
- if(suppress)
- return nstring;
- r = nstring;
- while(n) {
- string[mnstring] = *s++;
- mnstring++;
- nstring++;
- if(mnstring >= NSNAME) {
- gpseudo(ADATA, symstring, nodconst(0L));
- p->from.offset += nstring - NSNAME;
- p->reg = NSNAME;
- p->to.type = D_SCONST;
- memmove(p->to.u.sval, string, NSNAME);
- mnstring = 0;
- }
- n--;
- }
- return r;
-}
-
-int
-mulcon(Node *n, Node *nn)
-{
- Node *l, *r, nod1, nod2;
- Multab *m;
- int32 v, vs;
- int o;
- char code[sizeof(m->code)+2], *p;
-
- if(typefd[n->type->etype])
- return 0;
- l = n->left;
- r = n->right;
- if(l->op == OCONST) {
- l = r;
- r = n->left;
- }
- if(r->op != OCONST)
- return 0;
- v = convvtox(r->vconst, n->type->etype);
- if(v != r->vconst) {
- if(debug['M'])
- print("%L multiply conv: %lld\n", n->lineno, r->vconst);
- return 0;
- }
- m = mulcon0(v);
- if(!m) {
- if(debug['M'])
- print("%L multiply table: %lld\n", n->lineno, r->vconst);
- return 0;
- }
- if(debug['M'] && debug['v'])
- print("%L multiply: %d\n", n->lineno, v);
-
- memmove(code, m->code, sizeof(m->code));
- code[sizeof(m->code)] = 0;
-
- p = code;
- if(p[1] == 'i')
- p += 2;
- regalloc(&nod1, n, nn);
- cgen(l, &nod1);
- vs = v;
- regalloc(&nod2, n, Z);
-
-loop:
- switch(*p) {
- case 0:
- regfree(&nod2);
- if(vs < 0) {
- gopcode(OAS, &nod1, Z, &nod1);
- gopcode(OSUB, &nod1, nodconst(0), nn);
- } else
- gopcode(OAS, &nod1, Z, nn);
- regfree(&nod1);
- return 1;
- case '+':
- o = OADD;
- goto addsub;
- case '-':
- o = OSUB;
- addsub: /* number is r,n,l */
- v = p[1] - '0';
- r = &nod1;
- if(v&4)
- r = &nod2;
- n = &nod1;
- if(v&2)
- n = &nod2;
- l = &nod1;
- if(v&1)
- l = &nod2;
- gopcode(o, l, n, r);
- break;
- default: /* op is shiftcount, number is r,l */
- v = p[1] - '0';
- r = &nod1;
- if(v&2)
- r = &nod2;
- l = &nod1;
- if(v&1)
- l = &nod2;
- v = *p - 'a';
- if(v < 0 || v >= 32) {
- diag(n, "mulcon unknown op: %c%c", p[0], p[1]);
- break;
- }
- gopcode(OASHL, nodconst(v), l, r);
- break;
- }
- p += 2;
- goto loop;
-}
-
-void
-sextern(Sym *s, Node *a, int32 o, int32 w)
-{
- int32 e, lw;
-
- for(e=0; e<w; e+=NSNAME) {
- lw = NSNAME;
- if(w-e < lw)
- lw = w-e;
- gpseudo(ADATA, s, nodconst(0));
- p->from.offset += o+e;
- p->reg = lw;
- p->to.type = D_SCONST;
- memmove(p->to.u.sval, a->cstring+e, lw);
- }
-}
-
-void
-gextern(Sym *s, Node *a, int32 o, int32 w)
-{
-
- if(a->op == OCONST && typev[a->type->etype]) {
- if(isbigendian)
- gpseudo(ADATA, s, nod32const(a->vconst>>32));
- else
- gpseudo(ADATA, s, nod32const(a->vconst));
- p->from.offset += o;
- p->reg = 4;
- if(isbigendian)
- gpseudo(ADATA, s, nod32const(a->vconst));
- else
- gpseudo(ADATA, s, nod32const(a->vconst>>32));
- p->from.offset += o + 4;
- p->reg = 4;
- return;
- }
- gpseudo(ADATA, s, a);
- p->from.offset += o;
- p->reg = w;
- if(p->to.type == D_OREG)
- p->to.type = D_CONST;
-}
-
-void
-outcode(void)
-{
- Bprint(&outbuf, "go object %s %s %s\n", getgoos(), getgoarch(), getgoversion());
- if(pragcgobuf.to > pragcgobuf.start) {
- Bprint(&outbuf, "\n");
- Bprint(&outbuf, "$$ // exports\n\n");
- Bprint(&outbuf, "$$ // local types\n\n");
- Bprint(&outbuf, "$$ // cgo\n");
- Bprint(&outbuf, "%s", fmtstrflush(&pragcgobuf));
- Bprint(&outbuf, "\n$$\n\n");
- }
- Bprint(&outbuf, "!\n");
-
- writeobj(ctxt, &outbuf);
- lastp = P;
-}
-
-int32
-align(int32 i, Type *t, int op, int32 *maxalign)
-{
- int32 o;
- Type *v;
- int w, packw;
-
- o = i;
- w = 1;
- packw = 0;
- switch(op) {
- default:
- diag(Z, "unknown align opcode %d", op);
- break;
-
- case Asu2: /* padding at end of a struct */
- w = *maxalign;
- if(w < 1)
- w = 1;
- if(packflg)
- packw = packflg;
- break;
-
- case Ael1: /* initial align of struct element */
- for(v=t; v->etype==TARRAY; v=v->link)
- ;
- if(v->etype == TSTRUCT || v->etype == TUNION)
- w = v->align;
- else {
- w = ewidth[v->etype];
- if(w == 8)
- w = 4;
- }
- if(w < 1 || w > SZ_LONG)
- fatal(Z, "align");
- if(packflg)
- packw = packflg;
- break;
-
- case Ael2: /* width of a struct element */
- o += t->width;
- break;
-
- case Aarg0: /* initial passbyptr argument in arg list */
- if(typesuv[t->etype]) {
- o = align(o, types[TIND], Aarg1, nil);
- o = align(o, types[TIND], Aarg2, nil);
- }
- break;
-
- case Aarg1: /* initial align of parameter */
- w = ewidth[t->etype];
- if(w <= 0 || w >= SZ_LONG) {
- w = SZ_LONG;
- break;
- }
- w = 1; /* little endian no adjustment */
- break;
-
- case Aarg2: /* width of a parameter */
- o += t->width;
- w = t->width;
- if(w > SZ_LONG)
- w = SZ_LONG;
- break;
-
- case Aaut3: /* total align of automatic */
- o = align(o, t, Ael2, nil);
- o = align(o, t, Ael1, nil);
- w = SZ_LONG; /* because of a pun in cc/dcl.c:contig() */
- break;
- }
- if(packw != 0 && xround(o, w) != xround(o, packw))
- diag(Z, "#pragma pack changes offset of %T", t);
- o = xround(o, w);
- if(maxalign != nil && *maxalign < w)
- *maxalign = w;
- if(debug['A'])
- print("align %s %d %T = %d\n", bnames[op], i, t, o);
- return o;
-}
-
-int32
-maxround(int32 max, int32 v)
-{
- v = xround(v, SZ_LONG);
- if(v > max)
- return v;
- return max;
-}
diff --git a/src/cmd/5c/txt.c b/src/cmd/5c/txt.c
deleted file mode 100644
index af40220cc..000000000
--- a/src/cmd/5c/txt.c
+++ /dev/null
@@ -1,1361 +0,0 @@
-// Inferno utils/5c/txt.c
-// http://code.google.com/p/inferno-os/source/browse/utils/5c/txt.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-
-#include "gc.h"
-
-
-int thechar = '5';
-char *thestring = "arm";
-
-LinkArch *thelinkarch = &linkarm;
-
-void
-linkarchinit(void)
-{
-}
-
-void
-ginit(void)
-{
- Type *t;
-
- exregoffset = REGEXT;
- exfregoffset = FREGEXT;
- listinit();
- nstring = 0;
- mnstring = 0;
- nrathole = 0;
- pc = 0;
- breakpc = -1;
- continpc = -1;
- cases = C;
- lastp = P;
- tfield = types[TLONG];
-
- zprog.link = P;
- zprog.as = AGOK;
- zprog.reg = NREG;
- zprog.from.type = D_NONE;
- zprog.from.name = D_NONE;
- zprog.from.reg = NREG;
- zprog.to = zprog.from;
- zprog.scond = 0xE;
-
- regnode.op = OREGISTER;
- regnode.class = CEXREG;
- regnode.reg = REGTMP;
- regnode.complex = 0;
- regnode.addable = 11;
- regnode.type = types[TLONG];
-
- constnode.op = OCONST;
- constnode.class = CXXX;
- constnode.complex = 0;
- constnode.addable = 20;
- constnode.type = types[TLONG];
-
- fconstnode.op = OCONST;
- fconstnode.class = CXXX;
- fconstnode.complex = 0;
- fconstnode.addable = 20;
- fconstnode.type = types[TDOUBLE];
-
- nodsafe = new(ONAME, Z, Z);
- nodsafe->sym = slookup(".safe");
- nodsafe->type = types[TINT];
- nodsafe->etype = types[TINT]->etype;
- nodsafe->class = CAUTO;
- complex(nodsafe);
-
- t = typ(TARRAY, types[TCHAR]);
- symrathole = slookup(".rathole");
- symrathole->class = CGLOBL;
- symrathole->type = t;
-
- nodrat = new(ONAME, Z, Z);
- nodrat->sym = symrathole;
- nodrat->type = types[TIND];
- nodrat->etype = TVOID;
- nodrat->class = CGLOBL;
- complex(nodrat);
- nodrat->type = t;
-
- nodret = new(ONAME, Z, Z);
- nodret->sym = slookup(".ret");
- nodret->type = types[TIND];
- nodret->etype = TIND;
- nodret->class = CPARAM;
- nodret = new(OIND, nodret, Z);
- complex(nodret);
-
- com64init();
-
- memset(reg, 0, sizeof(reg));
-}
-
-void
-gclean(void)
-{
- int i;
- Sym *s;
-
- for(i=0; i<NREG; i++)
- if(reg[i])
- diag(Z, "reg %d left allocated", i);
- for(i=NREG; i<NREG+NFREG; i++)
- if(reg[i])
- diag(Z, "freg %d left allocated", i-NREG);
- while(mnstring)
- outstring("", 1L);
- symstring->type->width = nstring;
- symrathole->type->width = nrathole;
- for(i=0; i<NHASH; i++)
- for(s = hash[i]; s != S; s = s->link) {
- if(s->type == T)
- continue;
- if(s->type->width == 0)
- continue;
- if(s->class != CGLOBL && s->class != CSTATIC)
- continue;
- if(s->type == types[TENUM])
- continue;
- gpseudo(AGLOBL, s, nodconst(s->type->width));
- }
- nextpc();
- p->as = AEND;
- outcode();
-}
-
-void
-nextpc(void)
-{
- Plist *pl;
-
- p = alloc(sizeof(*p));
- *p = zprog;
- p->lineno = nearln;
- pc++;
- if(lastp == nil) {
- pl = linknewplist(ctxt);
- pl->firstpc = p;
- } else
- lastp->link = p;
- lastp = p;
-}
-
-void
-gargs(Node *n, Node *tn1, Node *tn2)
-{
- int32 regs;
- Node fnxargs[20], *fnxp;
-
- regs = cursafe;
-
- fnxp = fnxargs;
- garg1(n, tn1, tn2, 0, &fnxp); /* compile fns to temps */
-
- curarg = 0;
- fnxp = fnxargs;
- garg1(n, tn1, tn2, 1, &fnxp); /* compile normal args and temps */
-
- cursafe = regs;
-}
-
-void
-garg1(Node *n, Node *tn1, Node *tn2, int f, Node **fnxp)
-{
- Node nod;
-
- if(n == Z)
- return;
- if(n->op == OLIST) {
- garg1(n->left, tn1, tn2, f, fnxp);
- garg1(n->right, tn1, tn2, f, fnxp);
- return;
- }
- if(f == 0) {
- if(n->complex >= FNX) {
- regsalloc(*fnxp, n);
- nod = znode;
- nod.op = OAS;
- nod.left = *fnxp;
- nod.right = n;
- nod.type = n->type;
- cgen(&nod, Z);
- (*fnxp)++;
- }
- return;
- }
- if(typesuv[n->type->etype]) {
- regaalloc(tn2, n);
- if(n->complex >= FNX) {
- sugen(*fnxp, tn2, n->type->width);
- (*fnxp)++;
- } else
- sugen(n, tn2, n->type->width);
- return;
- }
- if(REGARG >= 0 && curarg == 0 && typechlp[n->type->etype]) {
- regaalloc1(tn1, n);
- if(n->complex >= FNX) {
- cgen(*fnxp, tn1);
- (*fnxp)++;
- } else
- cgen(n, tn1);
- return;
- }
- regalloc(tn1, n, Z);
- if(n->complex >= FNX) {
- cgen(*fnxp, tn1);
- (*fnxp)++;
- } else
- cgen(n, tn1);
- regaalloc(tn2, n);
- gopcode(OAS, tn1, Z, tn2);
- regfree(tn1);
-}
-
-Node*
-nodconst(int32 v)
-{
- constnode.vconst = v;
- return &constnode;
-}
-
-Node*
-nod32const(vlong v)
-{
- constnode.vconst = v & MASK(32);
- return &constnode;
-}
-
-Node*
-nodfconst(double d)
-{
- fconstnode.fconst = d;
- return &fconstnode;
-}
-
-void
-nodreg(Node *n, Node *nn, int reg)
-{
- *n = regnode;
- n->reg = reg;
- n->type = nn->type;
- n->lineno = nn->lineno;
-}
-
-void
-regret(Node *n, Node *nn, Type *t, int mode)
-{
- int r;
-
- if(mode == 0 || hasdotdotdot(t) || nn->type->width == 0) {
- r = REGRET;
- if(typefd[nn->type->etype])
- r = FREGRET+NREG;
- nodreg(n, nn, r);
- reg[r]++;
- return;
- }
-
- if(mode == 1) {
- // fetch returned value after call.
- // already called gargs, so curarg is set.
- curarg = (curarg+3) & ~3;
- regaalloc(n, nn);
- return;
- }
-
- if(mode == 2) {
- // store value to be returned.
- // must compute arg offset.
- if(t->etype != TFUNC)
- fatal(Z, "bad regret func %T", t);
- *n = *nn;
- n->op = ONAME;
- n->class = CPARAM;
- n->sym = slookup(".ret");
- n->complex = nodret->complex;
- n->xoffset = argsize(0);
- n->addable = 20;
- return;
- }
-
- fatal(Z, "bad regret");
-}
-
-int
-tmpreg(void)
-{
- int i;
-
- for(i=REGRET+1; i<NREG; i++)
- if(reg[i] == 0)
- return i;
- diag(Z, "out of fixed registers");
- return 0;
-}
-
-void
-regalloc(Node *n, Node *tn, Node *o)
-{
- int i;
-
- switch(tn->type->etype) {
- case TCHAR:
- case TUCHAR:
- case TSHORT:
- case TUSHORT:
- case TINT:
- case TUINT:
- case TLONG:
- case TULONG:
- case TIND:
- if(o != Z && o->op == OREGISTER) {
- i = o->reg;
- if(i >= 0 && i < NREG)
- goto out;
- }
- for(i=REGRET+1; i<=REGEXT-2; i++)
- if(reg[i] == 0)
- goto out;
- diag(tn, "out of fixed registers");
- goto err;
-
- case TFLOAT:
- case TDOUBLE:
- case TVLONG:
- if(o != Z && o->op == OREGISTER) {
- i = o->reg;
- if(i >= NREG && i < NREG+NFREG)
- goto out;
- }
- for(i=NREG; i<NREG+NFREG; i++)
- if(reg[i] == 0)
- goto out;
- diag(tn, "out of float registers");
- goto err;
- }
- diag(tn, "unknown type in regalloc: %T", tn->type);
-err:
- nodreg(n, tn, 0);
- return;
-out:
- reg[i]++;
- nodreg(n, tn, i);
-}
-
-void
-regialloc(Node *n, Node *tn, Node *o)
-{
- Node nod;
-
- nod = *tn;
- nod.type = types[TIND];
- regalloc(n, &nod, o);
-}
-
-void
-regfree(Node *n)
-{
- int i;
-
- i = 0;
- if(n->op != OREGISTER && n->op != OINDREG)
- goto err;
- i = n->reg;
- if(i < 0 || i >= nelem(reg))
- goto err;
- if(reg[i] <= 0)
- goto err;
- reg[i]--;
- return;
-err:
- diag(n, "error in regfree: %d", i);
-}
-
-void
-regsalloc(Node *n, Node *nn)
-{
- cursafe = align(cursafe, nn->type, Aaut3, nil);
- maxargsafe = maxround(maxargsafe, cursafe+curarg);
- *n = *nodsafe;
- n->xoffset = -(stkoff + cursafe);
- n->type = nn->type;
- n->etype = nn->type->etype;
- n->lineno = nn->lineno;
-}
-
-void
-regaalloc1(Node *n, Node *nn)
-{
- if(REGARG < 0) {
- fatal(n, "regaalloc1 and REGARG<0");
- return;
- }
- nodreg(n, nn, REGARG);
- reg[REGARG]++;
- curarg = align(curarg, nn->type, Aarg1, nil);
- curarg = align(curarg, nn->type, Aarg2, nil);
- maxargsafe = maxround(maxargsafe, cursafe+curarg);
-}
-
-void
-regaalloc(Node *n, Node *nn)
-{
- curarg = align(curarg, nn->type, Aarg1, nil);
- *n = *nn;
- n->op = OINDREG;
- n->reg = REGSP;
- n->xoffset = curarg + SZ_LONG;
- n->complex = 0;
- n->addable = 20;
- curarg = align(curarg, nn->type, Aarg2, nil);
- maxargsafe = maxround(maxargsafe, cursafe+curarg);
-}
-
-void
-regind(Node *n, Node *nn)
-{
-
- if(n->op != OREGISTER) {
- diag(n, "regind not OREGISTER");
- return;
- }
- n->op = OINDREG;
- n->type = nn->type;
-}
-
-void
-raddr(Node *n, Prog *p)
-{
- Addr a;
-
- naddr(n, &a);
- if(R0ISZERO && a.type == D_CONST && a.offset == 0) {
- a.type = D_REG;
- a.reg = 0;
- }
- if(a.type != D_REG && a.type != D_FREG) {
- if(n)
- diag(n, "bad in raddr: %O", n->op);
- else
- diag(n, "bad in raddr: <null>");
- p->reg = NREG;
- } else
- p->reg = a.reg;
-}
-
-void
-naddr(Node *n, Addr *a)
-{
- int32 v;
-
- a->type = D_NONE;
- if(n == Z)
- return;
- switch(n->op) {
- default:
- bad:
- diag(n, "bad in naddr: %O", n->op);
- break;
-
- case OREGISTER:
- a->type = D_REG;
- a->sym = nil;
- a->reg = n->reg;
- if(a->reg >= NREG) {
- a->type = D_FREG;
- a->reg -= NREG;
- }
- break;
-
- case OIND:
- naddr(n->left, a);
- if(a->type == D_REG) {
- a->type = D_OREG;
- break;
- }
- if(a->type == D_CONST) {
- a->type = D_OREG;
- break;
- }
- goto bad;
-
- case OINDREG:
- a->type = D_OREG;
- a->sym = nil;
- a->offset = n->xoffset;
- a->reg = n->reg;
- break;
-
- case ONAME:
- a->etype = n->etype;
- a->type = D_OREG;
- a->name = D_STATIC;
- a->sym = linksym(n->sym);
- a->offset = n->xoffset;
- if(n->class == CSTATIC)
- break;
- if(n->class == CEXTERN || n->class == CGLOBL) {
- a->name = D_EXTERN;
- break;
- }
- if(n->class == CAUTO) {
- a->name = D_AUTO;
- break;
- }
- if(n->class == CPARAM) {
- a->name = D_PARAM;
- break;
- }
- goto bad;
-
- case OCONST:
- a->sym = nil;
- a->reg = NREG;
- if(typefd[n->type->etype]) {
- a->type = D_FCONST;
- a->u.dval = n->fconst;
- } else {
- a->type = D_CONST;
- a->offset = n->vconst;
- }
- break;
-
- case OADDR:
- naddr(n->left, a);
- if(a->type == D_OREG) {
- a->type = D_CONST;
- break;
- }
- goto bad;
-
- case OADD:
- if(n->left->op == OCONST) {
- naddr(n->left, a);
- v = a->offset;
- naddr(n->right, a);
- } else {
- naddr(n->right, a);
- v = a->offset;
- naddr(n->left, a);
- }
- a->offset += v;
- break;
-
- }
-}
-
-void
-fop(int as, int f1, int f2, Node *t)
-{
- Node nod1, nod2, nod3;
-
- nodreg(&nod1, t, NREG+f1);
- nodreg(&nod2, t, NREG+f2);
- regalloc(&nod3, t, t);
- gopcode(as, &nod1, &nod2, &nod3);
- gmove(&nod3, t);
- regfree(&nod3);
-}
-
-void
-gmovm(Node *f, Node *t, int w)
-{
- gins(AMOVM, f, t);
- p->scond |= C_UBIT;
- if(w)
- p->scond |= C_WBIT;
-}
-
-void
-gmove(Node *f, Node *t)
-{
- int ft, tt, a;
- Node nod, nod1;
- Prog *p1;
-
- ft = f->type->etype;
- tt = t->type->etype;
-
- if(ft == TDOUBLE && f->op == OCONST) {
- }
- if(ft == TFLOAT && f->op == OCONST) {
- }
-
- /*
- * a load --
- * put it into a register then
- * worry what to do with it.
- */
- if(f->op == ONAME || f->op == OINDREG || f->op == OIND) {
- switch(ft) {
- default:
- a = AMOVW;
- break;
- case TFLOAT:
- a = AMOVF;
- break;
- case TDOUBLE:
- a = AMOVD;
- break;
- case TCHAR:
- a = AMOVBS;
- break;
- case TUCHAR:
- a = AMOVBU;
- break;
- case TSHORT:
- a = AMOVHS;
- break;
- case TUSHORT:
- a = AMOVHU;
- break;
- }
- if(typechlp[ft] && typeilp[tt])
- regalloc(&nod, t, t);
- else
- regalloc(&nod, f, t);
- gins(a, f, &nod);
- gmove(&nod, t);
- regfree(&nod);
- return;
- }
-
- /*
- * a store --
- * put it into a register then
- * store it.
- */
- if(t->op == ONAME || t->op == OINDREG || t->op == OIND) {
- switch(tt) {
- default:
- a = AMOVW;
- break;
- case TUCHAR:
- a = AMOVBU;
- break;
- case TCHAR:
- a = AMOVBS;
- break;
- case TUSHORT:
- a = AMOVHU;
- break;
- case TSHORT:
- a = AMOVHS;
- break;
- case TFLOAT:
- a = AMOVF;
- break;
- case TVLONG:
- case TDOUBLE:
- a = AMOVD;
- break;
- }
- if(ft == tt)
- regalloc(&nod, t, f);
- else
- regalloc(&nod, t, Z);
- gmove(f, &nod);
- gins(a, &nod, t);
- regfree(&nod);
- return;
- }
-
- /*
- * type x type cross table
- */
- a = AGOK;
- switch(ft) {
- case TDOUBLE:
- case TVLONG:
- case TFLOAT:
- switch(tt) {
- case TDOUBLE:
- case TVLONG:
- a = AMOVD;
- if(ft == TFLOAT)
- a = AMOVFD;
- break;
- case TFLOAT:
- a = AMOVDF;
- if(ft == TFLOAT)
- a = AMOVF;
- break;
- case TINT:
- case TUINT:
- case TLONG:
- case TULONG:
- case TIND:
- a = AMOVDW;
- if(ft == TFLOAT)
- a = AMOVFW;
- break;
- case TSHORT:
- case TUSHORT:
- case TCHAR:
- case TUCHAR:
- a = AMOVDW;
- if(ft == TFLOAT)
- a = AMOVFW;
- break;
- }
- break;
- case TUINT:
- case TULONG:
- if(tt == TFLOAT || tt == TDOUBLE) {
- // ugly and probably longer than necessary,
- // but vfp has a single instruction for this,
- // so hopefully it won't last long.
- //
- // tmp = f
- // tmp1 = tmp & 0x80000000
- // tmp ^= tmp1
- // t = float(int32(tmp))
- // if(tmp1)
- // t += 2147483648.
- //
- regalloc(&nod, f, Z);
- regalloc(&nod1, f, Z);
- gins(AMOVW, f, &nod);
- gins(AMOVW, &nod, &nod1);
- gins(AAND, nodconst(0x80000000), &nod1);
- gins(AEOR, &nod1, &nod);
- if(tt == TFLOAT)
- gins(AMOVWF, &nod, t);
- else
- gins(AMOVWD, &nod, t);
- gins(ACMP, nodconst(0), Z);
- raddr(&nod1, p);
- gins(ABEQ, Z, Z);
- regfree(&nod);
- regfree(&nod1);
- p1 = p;
- regalloc(&nod, t, Z);
- gins(AMOVF, nodfconst(2147483648.), &nod);
- gins(AADDF, &nod, t);
- regfree(&nod);
- patch(p1, pc);
- return;
- }
- // fall through
-
- case TINT:
- case TLONG:
- case TIND:
- switch(tt) {
- case TDOUBLE:
- gins(AMOVWD, f, t);
- return;
- case TFLOAT:
- gins(AMOVWF, f, t);
- return;
- case TINT:
- case TUINT:
- case TLONG:
- case TULONG:
- case TIND:
- case TSHORT:
- case TUSHORT:
- case TCHAR:
- case TUCHAR:
- a = AMOVW;
- break;
- }
- break;
- case TSHORT:
- switch(tt) {
- case TDOUBLE:
- regalloc(&nod, f, Z);
- gins(AMOVHS, f, &nod);
- gins(AMOVWD, &nod, t);
- regfree(&nod);
- return;
- case TFLOAT:
- regalloc(&nod, f, Z);
- gins(AMOVHS, f, &nod);
- gins(AMOVWF, &nod, t);
- regfree(&nod);
- return;
- case TUINT:
- case TINT:
- case TULONG:
- case TLONG:
- case TIND:
- a = AMOVHS;
- break;
- case TSHORT:
- case TUSHORT:
- case TCHAR:
- case TUCHAR:
- a = AMOVW;
- break;
- }
- break;
- case TUSHORT:
- switch(tt) {
- case TDOUBLE:
- regalloc(&nod, f, Z);
- gins(AMOVHU, f, &nod);
- gins(AMOVWD, &nod, t);
- regfree(&nod);
- return;
- case TFLOAT:
- regalloc(&nod, f, Z);
- gins(AMOVHU, f, &nod);
- gins(AMOVWF, &nod, t);
- regfree(&nod);
- return;
- case TINT:
- case TUINT:
- case TLONG:
- case TULONG:
- case TIND:
- a = AMOVHU;
- break;
- case TSHORT:
- case TUSHORT:
- case TCHAR:
- case TUCHAR:
- a = AMOVW;
- break;
- }
- break;
- case TCHAR:
- switch(tt) {
- case TDOUBLE:
- regalloc(&nod, f, Z);
- gins(AMOVBS, f, &nod);
- gins(AMOVWD, &nod, t);
- regfree(&nod);
- return;
- case TFLOAT:
- regalloc(&nod, f, Z);
- gins(AMOVBS, f, &nod);
- gins(AMOVWF, &nod, t);
- regfree(&nod);
- return;
- case TINT:
- case TUINT:
- case TLONG:
- case TULONG:
- case TIND:
- case TSHORT:
- case TUSHORT:
- a = AMOVBS;
- break;
- case TCHAR:
- case TUCHAR:
- a = AMOVW;
- break;
- }
- break;
- case TUCHAR:
- switch(tt) {
- case TDOUBLE:
- regalloc(&nod, f, Z);
- gins(AMOVBU, f, &nod);
- gins(AMOVWD, &nod, t);
- regfree(&nod);
- return;
- case TFLOAT:
- regalloc(&nod, f, Z);
- gins(AMOVBU, f, &nod);
- gins(AMOVWF, &nod, t);
- regfree(&nod);
- return;
- case TINT:
- case TUINT:
- case TLONG:
- case TULONG:
- case TIND:
- case TSHORT:
- case TUSHORT:
- a = AMOVBU;
- break;
- case TCHAR:
- case TUCHAR:
- a = AMOVW;
- break;
- }
- break;
- }
- if(a == AGOK)
- diag(Z, "bad opcode in gmove %T -> %T", f->type, t->type);
- if(a == AMOVW || a == AMOVF || a == AMOVD)
- if(samaddr(f, t))
- return;
- gins(a, f, t);
-}
-
-void
-gmover(Node *f, Node *t)
-{
- int ft, tt, a;
-
- ft = f->type->etype;
- tt = t->type->etype;
- a = AGOK;
- if(typechlp[ft] && typechlp[tt] && ewidth[ft] >= ewidth[tt]){
- switch(tt){
- case TSHORT:
- a = AMOVHS;
- break;
- case TUSHORT:
- a = AMOVHU;
- break;
- case TCHAR:
- a = AMOVBS;
- break;
- case TUCHAR:
- a = AMOVBU;
- break;
- }
- }
- if(a == AGOK)
- gmove(f, t);
- else
- gins(a, f, t);
-}
-
-void
-gins(int a, Node *f, Node *t)
-{
-
- nextpc();
- p->as = a;
- if(f != Z)
- naddr(f, &p->from);
- if(t != Z)
- naddr(t, &p->to);
- if(debug['g'])
- print("%P\n", p);
-}
-
-void
-gopcode(int o, Node *f1, Node *f2, Node *t)
-{
- int a, et;
- Addr ta;
-
- et = TLONG;
- if(f1 != Z && f1->type != T)
- et = f1->type->etype;
- a = AGOK;
- switch(o) {
- case OAS:
- gmove(f1, t);
- return;
-
- case OASADD:
- case OADD:
- a = AADD;
- if(et == TFLOAT)
- a = AADDF;
- else
- if(et == TDOUBLE || et == TVLONG)
- a = AADDD;
- break;
-
- case OASSUB:
- case OSUB:
- if(f2 && f2->op == OCONST) {
- Node *t = f1;
- f1 = f2;
- f2 = t;
- a = ARSB;
- } else
- a = ASUB;
- if(et == TFLOAT)
- a = ASUBF;
- else
- if(et == TDOUBLE || et == TVLONG)
- a = ASUBD;
- break;
-
- case OASOR:
- case OOR:
- a = AORR;
- break;
-
- case OASAND:
- case OAND:
- a = AAND;
- break;
-
- case OASXOR:
- case OXOR:
- a = AEOR;
- break;
-
- case OASLSHR:
- case OLSHR:
- a = ASRL;
- break;
-
- case OASASHR:
- case OASHR:
- a = ASRA;
- break;
-
- case OASASHL:
- case OASHL:
- a = ASLL;
- break;
-
- case OFUNC:
- a = ABL;
- break;
-
- case OASMUL:
- case OMUL:
- a = AMUL;
- if(et == TFLOAT)
- a = AMULF;
- else
- if(et == TDOUBLE || et == TVLONG)
- a = AMULD;
- break;
-
- case OASDIV:
- case ODIV:
- a = ADIV;
- if(et == TFLOAT)
- a = ADIVF;
- else
- if(et == TDOUBLE || et == TVLONG)
- a = ADIVD;
- break;
-
- case OASMOD:
- case OMOD:
- a = AMOD;
- break;
-
- case OASLMUL:
- case OLMUL:
- a = AMULU;
- break;
-
- case OASLMOD:
- case OLMOD:
- a = AMODU;
- break;
-
- case OASLDIV:
- case OLDIV:
- a = ADIVU;
- break;
-
- case OCASE:
- case OEQ:
- case ONE:
- case OLT:
- case OLE:
- case OGE:
- case OGT:
- case OLO:
- case OLS:
- case OHS:
- case OHI:
- a = ACMP;
- if(et == TFLOAT)
- a = ACMPF;
- else
- if(et == TDOUBLE || et == TVLONG)
- a = ACMPD;
- nextpc();
- p->as = a;
- naddr(f1, &p->from);
- if(a == ACMP && f1->op == OCONST && p->from.offset < 0) {
- p->as = ACMN;
- p->from.offset = -p->from.offset;
- }
- raddr(f2, p);
- switch(o) {
- case OEQ:
- a = ABEQ;
- break;
- case ONE:
- a = ABNE;
- break;
- case OLT:
- a = ABLT;
- break;
- case OLE:
- a = ABLE;
- break;
- case OGE:
- a = ABGE;
- break;
- case OGT:
- a = ABGT;
- break;
- case OLO:
- a = ABLO;
- break;
- case OLS:
- a = ABLS;
- break;
- case OHS:
- a = ABHS;
- break;
- case OHI:
- a = ABHI;
- break;
- case OCASE:
- nextpc();
- p->as = ACASE;
- p->scond = 0x9;
- naddr(f2, &p->from);
- a = ABHI;
- break;
- }
- f1 = Z;
- f2 = Z;
- break;
- }
- if(a == AGOK)
- diag(Z, "bad in gopcode %O", o);
- nextpc();
- p->as = a;
- if(f1 != Z)
- naddr(f1, &p->from);
- if(f2 != Z) {
- naddr(f2, &ta);
- p->reg = ta.reg;
- }
- if(t != Z)
- naddr(t, &p->to);
- if(debug['g'])
- print("%P\n", p);
-}
-
-int
-samaddr(Node *f, Node *t)
-{
-
- if(f->op != t->op)
- return 0;
- switch(f->op) {
-
- case OREGISTER:
- if(f->reg != t->reg)
- break;
- return 1;
- }
- return 0;
-}
-
-void
-gbranch(int o)
-{
- int a;
-
- a = AGOK;
- switch(o) {
- case ORETURN:
- a = ARET;
- break;
- case OGOTO:
- a = AB;
- break;
- }
- nextpc();
- if(a == AGOK) {
- diag(Z, "bad in gbranch %O", o);
- nextpc();
- }
- p->as = a;
-}
-
-void
-patch(Prog *op, int32 pc)
-{
-
- op->to.offset = pc;
- op->to.type = D_BRANCH;
-}
-
-void
-gpseudo(int a, Sym *s, Node *n)
-{
- nextpc();
- p->as = a;
- p->from.type = D_OREG;
- p->from.sym = linksym(s);
- p->from.name = D_EXTERN;
-
- switch(a) {
- case ATEXT:
- p->reg = textflag;
- textflag = 0;
- break;
- case AGLOBL:
- p->reg = s->dataflag;
- break;
- }
-
- if(s->class == CSTATIC)
- p->from.name = D_STATIC;
- naddr(n, &p->to);
- if(a == ADATA || a == AGLOBL)
- pc--;
-}
-
-void
-gpcdata(int index, int value)
-{
- Node n1;
-
- n1 = *nodconst(index);
- gins(APCDATA, &n1, nodconst(value));
-}
-
-void
-gprefetch(Node *n)
-{
- Node n1;
-
- regalloc(&n1, n, Z);
- gmove(n, &n1);
- n1.op = OINDREG;
- gins(APLD, &n1, Z);
- regfree(&n1);
-}
-
-int
-sconst(Node *n)
-{
- vlong vv;
-
- if(n->op == OCONST) {
- if(!typefd[n->type->etype]) {
- vv = n->vconst;
- if(vv >= (vlong)(-32766) && vv < (vlong)32766)
- return 1;
- /*
- * should be specialised for constant values which will
- * fit in different instructionsl; for now, let 5l
- * sort it out
- */
- return 1;
- }
- }
- return 0;
-}
-
-int
-sval(int32 v)
-{
- int i;
-
- for(i=0; i<16; i++) {
- if((v & ~0xff) == 0)
- return 1;
- if((~v & ~0xff) == 0)
- return 1;
- v = (v<<2) | ((uint32)v>>30);
- }
- return 0;
-}
-
-int32
-exreg(Type *t)
-{
- int32 o;
-
- if(typechlp[t->etype]) {
- if(exregoffset <= REGEXT-4)
- return 0;
- o = exregoffset;
- exregoffset--;
- return o;
- }
- if(typefd[t->etype]) {
- if(exfregoffset <= NFREG-1)
- return 0;
- o = exfregoffset + NREG;
- exfregoffset--;
- return o;
- }
- return 0;
-}
-
-schar ewidth[NTYPE] =
-{
- -1, /* [TXXX] */
- SZ_CHAR, /* [TCHAR] */
- SZ_CHAR, /* [TUCHAR] */
- SZ_SHORT, /* [TSHORT] */
- SZ_SHORT, /* [TUSHORT] */
- SZ_INT, /* [TINT] */
- SZ_INT, /* [TUINT] */
- SZ_LONG, /* [TLONG] */
- SZ_LONG, /* [TULONG] */
- SZ_VLONG, /* [TVLONG] */
- SZ_VLONG, /* [TUVLONG] */
- SZ_FLOAT, /* [TFLOAT] */
- SZ_DOUBLE, /* [TDOUBLE] */
- SZ_IND, /* [TIND] */
- 0, /* [TFUNC] */
- -1, /* [TARRAY] */
- 0, /* [TVOID] */
- -1, /* [TSTRUCT] */
- -1, /* [TUNION] */
- SZ_INT, /* [TENUM] */
-};
-
-int32 ncast[NTYPE] =
-{
- 0, /* [TXXX] */
- BCHAR|BUCHAR, /* [TCHAR] */
- BCHAR|BUCHAR, /* [TUCHAR] */
- BSHORT|BUSHORT, /* [TSHORT] */
- BSHORT|BUSHORT, /* [TUSHORT] */
- BINT|BUINT|BLONG|BULONG|BIND, /* [TINT] */
- BINT|BUINT|BLONG|BULONG|BIND, /* [TUINT] */
- BINT|BUINT|BLONG|BULONG|BIND, /* [TLONG] */
- BINT|BUINT|BLONG|BULONG|BIND, /* [TULONG] */
- BVLONG|BUVLONG, /* [TVLONG] */
- BVLONG|BUVLONG, /* [TUVLONG] */
- BFLOAT, /* [TFLOAT] */
- BDOUBLE, /* [TDOUBLE] */
- BLONG|BULONG|BIND, /* [TIND] */
- 0, /* [TFUNC] */
- 0, /* [TARRAY] */
- 0, /* [TVOID] */
- BSTRUCT, /* [TSTRUCT] */
- BUNION, /* [TUNION] */
- 0, /* [TENUM] */
-};
diff --git a/src/cmd/5g/reg.c b/src/cmd/5g/reg.c
index 86a1f7efb..56ea7826e 100644
--- a/src/cmd/5g/reg.c
+++ b/src/cmd/5g/reg.c
@@ -199,7 +199,7 @@ regopt(Prog *firstp)
proginfo(&info, p);
// Avoid making variables for direct-called functions.
- if(p->as == ABL && p->to.type == D_EXTERN)
+ if(p->as == ABL && p->to.name == D_EXTERN)
continue;
bit = mkvar(r, &p->from);
diff --git a/src/cmd/6c/Makefile b/src/cmd/6c/Makefile
deleted file mode 100644
index 3f528d751..000000000
--- a/src/cmd/6c/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-# Copyright 2012 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../Make.dist
diff --git a/src/cmd/6c/cgen.c b/src/cmd/6c/cgen.c
deleted file mode 100644
index 68dd7bb5f..000000000
--- a/src/cmd/6c/cgen.c
+++ /dev/null
@@ -1,2046 +0,0 @@
-// Inferno utils/6c/cgen.c
-// http://code.google.com/p/inferno-os/source/browse/utils/6c/cgen.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-#include "../../runtime/funcdata.h"
-
-/* ,x/^(print|prtree)\(/i/\/\/ */
-int castup(Type*, Type*);
-int vaddr(Node *n, int a);
-
-void
-cgen(Node *n, Node *nn)
-{
- Node *l, *r, *t;
- Prog *p1;
- Node nod, nod1, nod2, nod3, nod4;
- int o, hardleft;
- int32 v, curs;
- vlong c;
-
- if(debug['g']) {
- prtree(nn, "cgen lhs");
- prtree(n, "cgen");
- }
- if(n == Z || n->type == T)
- return;
- if(typesu[n->type->etype] && (n->op != OFUNC || nn != Z)) {
- sugen(n, nn, n->type->width);
- return;
- }
- l = n->left;
- r = n->right;
- o = n->op;
-
- if(n->op == OEXREG || (nn != Z && nn->op == OEXREG)) {
- gmove(n, nn);
- return;
- }
-
- if(n->addable >= INDEXED) {
- if(nn == Z) {
- switch(o) {
- default:
- nullwarn(Z, Z);
- break;
- case OINDEX:
- nullwarn(l, r);
- break;
- }
- return;
- }
- gmove(n, nn);
- return;
- }
- curs = cursafe;
-
- if(l->complex >= FNX)
- if(r != Z && r->complex >= FNX)
- switch(o) {
- default:
- if(cond(o) && typesu[l->type->etype])
- break;
-
- regret(&nod, r, 0, 0);
- cgen(r, &nod);
-
- regsalloc(&nod1, r);
- gmove(&nod, &nod1);
-
- regfree(&nod);
- nod = *n;
- nod.right = &nod1;
-
- cgen(&nod, nn);
- return;
-
- case OFUNC:
- case OCOMMA:
- case OANDAND:
- case OOROR:
- case OCOND:
- case ODOT:
- break;
- }
-
- hardleft = l->addable < INDEXED || l->complex >= FNX;
- switch(o) {
- default:
- diag(n, "unknown op in cgen: %O", o);
- break;
-
- case ONEG:
- case OCOM:
- if(nn == Z) {
- nullwarn(l, Z);
- break;
- }
- regalloc(&nod, l, nn);
- cgen(l, &nod);
- gopcode(o, n->type, Z, &nod);
- gmove(&nod, nn);
- regfree(&nod);
- break;
-
- case OAS:
- if(l->op == OBIT)
- goto bitas;
- if(!hardleft) {
- if(nn != Z || r->addable < INDEXED || hardconst(r)) {
- if(r->complex >= FNX && nn == Z)
- regret(&nod, r, 0, 0);
- else
- regalloc(&nod, r, nn);
- cgen(r, &nod);
- gmove(&nod, l);
- if(nn != Z)
- gmove(&nod, nn);
- regfree(&nod);
- } else
- gmove(r, l);
- break;
- }
- if(l->complex >= r->complex) {
- if(l->op == OINDEX && immconst(r)) {
- gmove(r, l);
- break;
- }
- reglcgen(&nod1, l, Z);
- if(r->addable >= INDEXED && !hardconst(r)) {
- gmove(r, &nod1);
- if(nn != Z)
- gmove(r, nn);
- regfree(&nod1);
- break;
- }
- regalloc(&nod, r, nn);
- cgen(r, &nod);
- } else {
- regalloc(&nod, r, nn);
- cgen(r, &nod);
- reglcgen(&nod1, l, Z);
- }
- gmove(&nod, &nod1);
- regfree(&nod);
- regfree(&nod1);
- break;
-
- bitas:
- n = l->left;
- regalloc(&nod, r, nn);
- if(l->complex >= r->complex) {
- reglcgen(&nod1, n, Z);
- cgen(r, &nod);
- } else {
- cgen(r, &nod);
- reglcgen(&nod1, n, Z);
- }
- regalloc(&nod2, n, Z);
- gmove(&nod1, &nod2);
- bitstore(l, &nod, &nod1, &nod2, nn);
- break;
-
- case OBIT:
- if(nn == Z) {
- nullwarn(l, Z);
- break;
- }
- bitload(n, &nod, Z, Z, nn);
- gmove(&nod, nn);
- regfree(&nod);
- break;
-
- case OLSHR:
- case OASHL:
- case OASHR:
- if(nn == Z) {
- nullwarn(l, r);
- break;
- }
- if(r->op == OCONST) {
- if(r->vconst == 0) {
- cgen(l, nn);
- break;
- }
- regalloc(&nod, l, nn);
- cgen(l, &nod);
- if(o == OASHL && r->vconst == 1)
- gopcode(OADD, n->type, &nod, &nod);
- else
- gopcode(o, n->type, r, &nod);
- gmove(&nod, nn);
- regfree(&nod);
- break;
- }
-
- /*
- * get nod to be D_CX
- */
- if(nodreg(&nod, nn, D_CX)) {
- regsalloc(&nod1, n);
- gmove(&nod, &nod1);
- cgen(n, &nod); /* probably a bug */
- gmove(&nod, nn);
- gmove(&nod1, &nod);
- break;
- }
- reg[D_CX]++;
- if(nn->op == OREGISTER && nn->reg == D_CX)
- regalloc(&nod1, l, Z);
- else
- regalloc(&nod1, l, nn);
- if(r->complex >= l->complex) {
- cgen(r, &nod);
- cgen(l, &nod1);
- } else {
- cgen(l, &nod1);
- cgen(r, &nod);
- }
- gopcode(o, n->type, &nod, &nod1);
- gmove(&nod1, nn);
- regfree(&nod);
- regfree(&nod1);
- break;
-
- case OADD:
- case OSUB:
- case OOR:
- case OXOR:
- case OAND:
- if(nn == Z) {
- nullwarn(l, r);
- break;
- }
- if(typefd[n->type->etype])
- goto fop;
- if(r->op == OCONST) {
- if(r->vconst == 0 && o != OAND) {
- cgen(l, nn);
- break;
- }
- }
- if(n->op == OOR && l->op == OASHL && r->op == OLSHR
- && l->right->op == OCONST && r->right->op == OCONST
- && l->left->op == ONAME && r->left->op == ONAME
- && l->left->sym == r->left->sym
- && l->right->vconst + r->right->vconst == 8 * l->left->type->width) {
- regalloc(&nod, l->left, nn);
- cgen(l->left, &nod);
- gopcode(OROTL, n->type, l->right, &nod);
- gmove(&nod, nn);
- regfree(&nod);
- break;
- }
- if(n->op == OADD && l->op == OASHL && l->right->op == OCONST
- && (r->op != OCONST || r->vconst < -128 || r->vconst > 127)) {
- c = l->right->vconst;
- if(c > 0 && c <= 3) {
- if(l->left->complex >= r->complex) {
- regalloc(&nod, l->left, nn);
- cgen(l->left, &nod);
- if(r->addable < INDEXED) {
- regalloc(&nod1, r, Z);
- cgen(r, &nod1);
- genmuladd(&nod, &nod, 1 << c, &nod1);
- regfree(&nod1);
- }
- else
- genmuladd(&nod, &nod, 1 << c, r);
- }
- else {
- regalloc(&nod, r, nn);
- cgen(r, &nod);
- regalloc(&nod1, l->left, Z);
- cgen(l->left, &nod1);
- genmuladd(&nod, &nod1, 1 << c, &nod);
- regfree(&nod1);
- }
- gmove(&nod, nn);
- regfree(&nod);
- break;
- }
- }
- if(r->addable >= INDEXED && !hardconst(r)) {
- regalloc(&nod, l, nn);
- cgen(l, &nod);
- gopcode(o, n->type, r, &nod);
- gmove(&nod, nn);
- regfree(&nod);
- break;
- }
- if(l->complex >= r->complex) {
- regalloc(&nod, l, nn);
- cgen(l, &nod);
- regalloc(&nod1, r, Z);
- cgen(r, &nod1);
- gopcode(o, n->type, &nod1, &nod);
- } else {
- regalloc(&nod1, r, nn);
- cgen(r, &nod1);
- regalloc(&nod, l, Z);
- cgen(l, &nod);
- gopcode(o, n->type, &nod1, &nod);
- }
- gmove(&nod, nn);
- regfree(&nod);
- regfree(&nod1);
- break;
-
- case OLMOD:
- case OMOD:
- case OLMUL:
- case OLDIV:
- case OMUL:
- case ODIV:
- if(nn == Z) {
- nullwarn(l, r);
- break;
- }
- if(typefd[n->type->etype])
- goto fop;
- if(r->op == OCONST && typechl[n->type->etype]) { /* TO DO */
- SET(v);
- switch(o) {
- case ODIV:
- case OMOD:
- c = r->vconst;
- if(c < 0)
- c = -c;
- v = xlog2(c);
- if(v < 0)
- break;
- /* fall thru */
- case OMUL:
- case OLMUL:
- regalloc(&nod, l, nn);
- cgen(l, &nod);
- switch(o) {
- case OMUL:
- case OLMUL:
- mulgen(n->type, r, &nod);
- break;
- case ODIV:
- sdiv2(r->vconst, v, l, &nod);
- break;
- case OMOD:
- smod2(r->vconst, v, l, &nod);
- break;
- }
- gmove(&nod, nn);
- regfree(&nod);
- goto done;
- case OLDIV:
- c = r->vconst;
- if((c & 0x80000000) == 0)
- break;
- regalloc(&nod1, l, Z);
- cgen(l, &nod1);
- regalloc(&nod, l, nn);
- zeroregm(&nod);
- gins(ACMPL, &nod1, nodconst(c));
- gins(ASBBL, nodconst(-1), &nod);
- regfree(&nod1);
- gmove(&nod, nn);
- regfree(&nod);
- goto done;
- }
- }
-
- if(o == OMUL || o == OLMUL) {
- if(l->addable >= INDEXED) {
- t = l;
- l = r;
- r = t;
- }
- reg[D_DX]++; // for gopcode case OMUL
- regalloc(&nod, l, nn);
- cgen(l, &nod);
- if(r->addable < INDEXED || hardconst(r)) {
- regalloc(&nod1, r, Z);
- cgen(r, &nod1);
- gopcode(OMUL, n->type, &nod1, &nod);
- regfree(&nod1);
- }else
- gopcode(OMUL, n->type, r, &nod); /* addressible */
- gmove(&nod, nn);
- regfree(&nod);
- reg[D_DX]--;
- break;
- }
-
- /*
- * get nod to be D_AX
- * get nod1 to be D_DX
- */
- if(nodreg(&nod, nn, D_AX)) {
- regsalloc(&nod2, n);
- gmove(&nod, &nod2);
- v = reg[D_AX];
- reg[D_AX] = 0;
-
- if(isreg(l, D_AX)) {
- nod3 = *n;
- nod3.left = &nod2;
- cgen(&nod3, nn);
- } else
- if(isreg(r, D_AX)) {
- nod3 = *n;
- nod3.right = &nod2;
- cgen(&nod3, nn);
- } else
- cgen(n, nn);
-
- gmove(&nod2, &nod);
- reg[D_AX] = v;
- break;
- }
- if(nodreg(&nod1, nn, D_DX)) {
- regsalloc(&nod2, n);
- gmove(&nod1, &nod2);
- v = reg[D_DX];
- reg[D_DX] = 0;
-
- if(isreg(l, D_DX)) {
- nod3 = *n;
- nod3.left = &nod2;
- cgen(&nod3, nn);
- } else
- if(isreg(r, D_DX)) {
- nod3 = *n;
- nod3.right = &nod2;
- cgen(&nod3, nn);
- } else
- cgen(n, nn);
-
- gmove(&nod2, &nod1);
- reg[D_DX] = v;
- break;
- }
- reg[D_AX]++;
-
- if(r->op == OCONST && (o == ODIV || o == OLDIV) && immconst(r) && typechl[r->type->etype]) {
- reg[D_DX]++;
- if(l->addable < INDEXED) {
- regalloc(&nod2, l, Z);
- cgen(l, &nod2);
- l = &nod2;
- }
- if(o == ODIV)
- sdivgen(l, r, &nod, &nod1);
- else
- udivgen(l, r, &nod, &nod1);
- gmove(&nod1, nn);
- if(l == &nod2)
- regfree(l);
- goto freeaxdx;
- }
-
- if(l->complex >= r->complex) {
- cgen(l, &nod);
- reg[D_DX]++;
- if(o == ODIV || o == OMOD)
- gins(typechl[l->type->etype]? ACDQ: ACQO, Z, Z);
- if(o == OLDIV || o == OLMOD)
- zeroregm(&nod1);
- if(r->addable < INDEXED || r->op == OCONST) {
- regsalloc(&nod3, r);
- cgen(r, &nod3);
- gopcode(o, n->type, &nod3, Z);
- } else
- gopcode(o, n->type, r, Z);
- } else {
- regsalloc(&nod3, r);
- cgen(r, &nod3);
- cgen(l, &nod);
- reg[D_DX]++;
- if(o == ODIV || o == OMOD)
- gins(typechl[l->type->etype]? ACDQ: ACQO, Z, Z);
- if(o == OLDIV || o == OLMOD)
- zeroregm(&nod1);
- gopcode(o, n->type, &nod3, Z);
- }
- if(o == OMOD || o == OLMOD)
- gmove(&nod1, nn);
- else
- gmove(&nod, nn);
- freeaxdx:
- regfree(&nod);
- regfree(&nod1);
- break;
-
- case OASLSHR:
- case OASASHL:
- case OASASHR:
- if(r->op == OCONST)
- goto asand;
- if(l->op == OBIT)
- goto asbitop;
- if(typefd[n->type->etype])
- goto asand; /* can this happen? */
-
- /*
- * get nod to be D_CX
- */
- if(nodreg(&nod, nn, D_CX)) {
- regsalloc(&nod1, n);
- gmove(&nod, &nod1);
- cgen(n, &nod);
- if(nn != Z)
- gmove(&nod, nn);
- gmove(&nod1, &nod);
- break;
- }
- reg[D_CX]++;
-
- if(r->complex >= l->complex) {
- cgen(r, &nod);
- if(hardleft)
- reglcgen(&nod1, l, Z);
- else
- nod1 = *l;
- } else {
- if(hardleft)
- reglcgen(&nod1, l, Z);
- else
- nod1 = *l;
- cgen(r, &nod);
- }
-
- gopcode(o, l->type, &nod, &nod1);
- regfree(&nod);
- if(nn != Z)
- gmove(&nod1, nn);
- if(hardleft)
- regfree(&nod1);
- break;
-
- case OASAND:
- case OASADD:
- case OASSUB:
- case OASXOR:
- case OASOR:
- asand:
- if(l->op == OBIT)
- goto asbitop;
- if(typefd[l->type->etype] || typefd[r->type->etype])
- goto asfop;
- if(l->complex >= r->complex) {
- if(hardleft)
- reglcgen(&nod, l, Z);
- else
- nod = *l;
- if(!immconst(r)) {
- regalloc(&nod1, r, nn);
- cgen(r, &nod1);
- gopcode(o, l->type, &nod1, &nod);
- regfree(&nod1);
- } else
- gopcode(o, l->type, r, &nod);
- } else {
- regalloc(&nod1, r, nn);
- cgen(r, &nod1);
- if(hardleft)
- reglcgen(&nod, l, Z);
- else
- nod = *l;
- gopcode(o, l->type, &nod1, &nod);
- regfree(&nod1);
- }
- if(nn != Z)
- gmove(&nod, nn);
- if(hardleft)
- regfree(&nod);
- break;
-
- asfop:
- if(l->complex >= r->complex) {
- if(hardleft)
- reglcgen(&nod, l, Z);
- else
- nod = *l;
- if(r->addable < INDEXED){
- regalloc(&nod1, r, nn);
- cgen(r, &nod1);
- }else
- nod1 = *r;
- regalloc(&nod2, r, Z);
- gmove(&nod, &nod2);
- gopcode(o, r->type, &nod1, &nod2);
- gmove(&nod2, &nod);
- regfree(&nod2);
- if(r->addable < INDEXED)
- regfree(&nod1);
- } else {
- regalloc(&nod1, r, nn);
- cgen(r, &nod1);
- if(hardleft)
- reglcgen(&nod, l, Z);
- else
- nod = *l;
- if(o != OASMUL && o != OASADD) {
- regalloc(&nod2, r, Z);
- gmove(&nod, &nod2);
- gopcode(o, r->type, &nod1, &nod2);
- regfree(&nod1);
- gmove(&nod2, &nod);
- regfree(&nod2);
- } else {
- gopcode(o, r->type, &nod, &nod1);
- gmove(&nod1, &nod);
- regfree(&nod1);
- }
- }
- if(nn != Z)
- gmove(&nod, nn);
- if(hardleft)
- regfree(&nod);
- break;
-
- case OASLMUL:
- case OASLDIV:
- case OASLMOD:
- case OASMUL:
- case OASDIV:
- case OASMOD:
- if(l->op == OBIT)
- goto asbitop;
- if(typefd[n->type->etype] || typefd[r->type->etype])
- goto asfop;
- if(r->op == OCONST && typechl[n->type->etype]) {
- SET(v);
- switch(o) {
- case OASDIV:
- case OASMOD:
- c = r->vconst;
- if(c < 0)
- c = -c;
- v = xlog2(c);
- if(v < 0)
- break;
- /* fall thru */
- case OASMUL:
- case OASLMUL:
- if(hardleft)
- reglcgen(&nod2, l, Z);
- else
- nod2 = *l;
- regalloc(&nod, l, nn);
- cgen(&nod2, &nod);
- switch(o) {
- case OASMUL:
- case OASLMUL:
- mulgen(n->type, r, &nod);
- break;
- case OASDIV:
- sdiv2(r->vconst, v, l, &nod);
- break;
- case OASMOD:
- smod2(r->vconst, v, l, &nod);
- break;
- }
- havev:
- gmove(&nod, &nod2);
- if(nn != Z)
- gmove(&nod, nn);
- if(hardleft)
- regfree(&nod2);
- regfree(&nod);
- goto done;
- case OASLDIV:
- c = r->vconst;
- if((c & 0x80000000) == 0)
- break;
- if(hardleft)
- reglcgen(&nod2, l, Z);
- else
- nod2 = *l;
- regalloc(&nod1, l, nn);
- cgen(&nod2, &nod1);
- regalloc(&nod, l, nn);
- zeroregm(&nod);
- gins(ACMPL, &nod1, nodconst(c));
- gins(ASBBL, nodconst(-1), &nod);
- regfree(&nod1);
- goto havev;
- }
- }
-
- if(o == OASMUL) {
- /* should favour AX */
- regalloc(&nod, l, nn);
- if(r->complex >= FNX) {
- regalloc(&nod1, r, Z);
- cgen(r, &nod1);
- r = &nod1;
- }
- if(hardleft)
- reglcgen(&nod2, l, Z);
- else
- nod2 = *l;
- cgen(&nod2, &nod);
- if(r->addable < INDEXED || hardconst(r)) {
- if(r->complex < FNX) {
- regalloc(&nod1, r, Z);
- cgen(r, &nod1);
- }
- gopcode(OASMUL, n->type, &nod1, &nod);
- regfree(&nod1);
- }
- else
- gopcode(OASMUL, n->type, r, &nod);
- if(r == &nod1)
- regfree(r);
- gmove(&nod, &nod2);
- if(nn != Z)
- gmove(&nod, nn);
- regfree(&nod);
- if(hardleft)
- regfree(&nod2);
- break;
- }
-
- /*
- * get nod to be D_AX
- * get nod1 to be D_DX
- */
- if(nodreg(&nod, nn, D_AX)) {
- regsalloc(&nod2, n);
- gmove(&nod, &nod2);
- v = reg[D_AX];
- reg[D_AX] = 0;
-
- if(isreg(l, D_AX)) {
- nod3 = *n;
- nod3.left = &nod2;
- cgen(&nod3, nn);
- } else
- if(isreg(r, D_AX)) {
- nod3 = *n;
- nod3.right = &nod2;
- cgen(&nod3, nn);
- } else
- cgen(n, nn);
-
- gmove(&nod2, &nod);
- reg[D_AX] = v;
- break;
- }
- if(nodreg(&nod1, nn, D_DX)) {
- regsalloc(&nod2, n);
- gmove(&nod1, &nod2);
- v = reg[D_DX];
- reg[D_DX] = 0;
-
- if(isreg(l, D_DX)) {
- nod3 = *n;
- nod3.left = &nod2;
- cgen(&nod3, nn);
- } else
- if(isreg(r, D_DX)) {
- nod3 = *n;
- nod3.right = &nod2;
- cgen(&nod3, nn);
- } else
- cgen(n, nn);
-
- gmove(&nod2, &nod1);
- reg[D_DX] = v;
- break;
- }
- reg[D_AX]++;
- reg[D_DX]++;
-
- if(l->complex >= r->complex) {
- if(hardleft)
- reglcgen(&nod2, l, Z);
- else
- nod2 = *l;
- cgen(&nod2, &nod);
- if(r->op == OCONST && typechl[r->type->etype]) {
- switch(o) {
- case OASDIV:
- sdivgen(&nod2, r, &nod, &nod1);
- goto divdone;
- case OASLDIV:
- udivgen(&nod2, r, &nod, &nod1);
- divdone:
- gmove(&nod1, &nod2);
- if(nn != Z)
- gmove(&nod1, nn);
- goto freelxaxdx;
- }
- }
- if(o == OASDIV || o == OASMOD)
- gins(typechl[l->type->etype]? ACDQ: ACQO, Z, Z);
- if(o == OASLDIV || o == OASLMOD)
- zeroregm(&nod1);
- if(r->addable < INDEXED || r->op == OCONST ||
- !typeil[r->type->etype]) {
- regalloc(&nod3, r, Z);
- cgen(r, &nod3);
- gopcode(o, l->type, &nod3, Z);
- regfree(&nod3);
- } else
- gopcode(o, n->type, r, Z);
- } else {
- regalloc(&nod3, r, Z);
- cgen(r, &nod3);
- if(hardleft)
- reglcgen(&nod2, l, Z);
- else
- nod2 = *l;
- cgen(&nod2, &nod);
- if(o == OASDIV || o == OASMOD)
- gins(typechl[l->type->etype]? ACDQ: ACQO, Z, Z);
- if(o == OASLDIV || o == OASLMOD)
- zeroregm(&nod1);
- gopcode(o, l->type, &nod3, Z);
- regfree(&nod3);
- }
- if(o == OASMOD || o == OASLMOD) {
- gmove(&nod1, &nod2);
- if(nn != Z)
- gmove(&nod1, nn);
- } else {
- gmove(&nod, &nod2);
- if(nn != Z)
- gmove(&nod, nn);
- }
- freelxaxdx:
- if(hardleft)
- regfree(&nod2);
- regfree(&nod);
- regfree(&nod1);
- break;
-
- fop:
- if(l->complex >= r->complex) {
- regalloc(&nod, l, nn);
- cgen(l, &nod);
- if(r->addable < INDEXED) {
- regalloc(&nod1, r, Z);
- cgen(r, &nod1);
- gopcode(o, n->type, &nod1, &nod);
- regfree(&nod1);
- } else
- gopcode(o, n->type, r, &nod);
- } else {
- /* TO DO: could do better with r->addable >= INDEXED */
- regalloc(&nod1, r, Z);
- cgen(r, &nod1);
- regalloc(&nod, l, nn);
- cgen(l, &nod);
- gopcode(o, n->type, &nod1, &nod);
- regfree(&nod1);
- }
- gmove(&nod, nn);
- regfree(&nod);
- break;
-
- asbitop:
- regalloc(&nod4, n, nn);
- if(l->complex >= r->complex) {
- bitload(l, &nod, &nod1, &nod2, &nod4);
- regalloc(&nod3, r, Z);
- cgen(r, &nod3);
- } else {
- regalloc(&nod3, r, Z);
- cgen(r, &nod3);
- bitload(l, &nod, &nod1, &nod2, &nod4);
- }
- gmove(&nod, &nod4);
-
- { /* TO DO: check floating point source */
- Node onod;
-
- /* incredible grot ... */
- onod = nod3;
- onod.op = o;
- onod.complex = 2;
- onod.addable = 0;
- onod.type = tfield;
- onod.left = &nod4;
- onod.right = &nod3;
- cgen(&onod, Z);
- }
- regfree(&nod3);
- gmove(&nod4, &nod);
- regfree(&nod4);
- bitstore(l, &nod, &nod1, &nod2, nn);
- break;
-
- case OADDR:
- if(nn == Z) {
- nullwarn(l, Z);
- break;
- }
- lcgen(l, nn);
- break;
-
- case OFUNC:
- if(l->complex >= FNX) {
- if(l->op != OIND)
- diag(n, "bad function call");
-
- regret(&nod, l->left, 0, 0);
- cgen(l->left, &nod);
- regsalloc(&nod1, l->left);
- gmove(&nod, &nod1);
- regfree(&nod);
-
- nod = *n;
- nod.left = &nod2;
- nod2 = *l;
- nod2.left = &nod1;
- nod2.complex = 1;
- cgen(&nod, nn);
-
- return;
- }
- gargs(r, &nod, &nod1);
- if(l->addable < INDEXED) {
- reglcgen(&nod, l, nn);
- nod.op = OREGISTER;
- gopcode(OFUNC, n->type, Z, &nod);
- regfree(&nod);
- } else
- gopcode(OFUNC, n->type, Z, l);
- if(REGARG >= 0 && reg[REGARG])
- reg[REGARG]--;
- regret(&nod, n, l->type, 1); // update maxarg if nothing else
- if(nn != Z)
- gmove(&nod, nn);
- if(nod.op == OREGISTER)
- regfree(&nod);
- break;
-
- case OIND:
- if(nn == Z) {
- nullwarn(l, Z);
- break;
- }
- regialloc(&nod, n, nn);
- r = l;
- while(r->op == OADD)
- r = r->right;
- if(sconst(r)) {
- v = r->vconst;
- r->vconst = 0;
- cgen(l, &nod);
- nod.xoffset += v;
- r->vconst = v;
- } else
- cgen(l, &nod);
- regind(&nod, n);
- gmove(&nod, nn);
- regfree(&nod);
- break;
-
- case OEQ:
- case ONE:
- case OLE:
- case OLT:
- case OGE:
- case OGT:
- case OLO:
- case OLS:
- case OHI:
- case OHS:
- if(nn == Z) {
- nullwarn(l, r);
- break;
- }
- boolgen(n, 1, nn);
- break;
-
- case OANDAND:
- case OOROR:
- boolgen(n, 1, nn);
- if(nn == Z)
- patch(p, pc);
- break;
-
- case ONOT:
- if(nn == Z) {
- nullwarn(l, Z);
- break;
- }
- boolgen(n, 1, nn);
- break;
-
- case OCOMMA:
- cgen(l, Z);
- cgen(r, nn);
- break;
-
- case OCAST:
- if(nn == Z) {
- nullwarn(l, Z);
- break;
- }
- /*
- * convert from types l->n->nn
- */
- if(nocast(l->type, n->type) && nocast(n->type, nn->type)) {
- /* both null, gen l->nn */
- cgen(l, nn);
- break;
- }
- if(ewidth[n->type->etype] < ewidth[l->type->etype]){
- if(l->type->etype == TIND && typechlp[n->type->etype])
- warn(n, "conversion of pointer to shorter integer");
- }else if(0){
- if(nocast(n->type, nn->type) || castup(n->type, nn->type)){
- if(typefd[l->type->etype] != typefd[nn->type->etype])
- regalloc(&nod, l, nn);
- else
- regalloc(&nod, nn, nn);
- cgen(l, &nod);
- gmove(&nod, nn);
- regfree(&nod);
- break;
- }
- }
- regalloc(&nod, l, nn);
- cgen(l, &nod);
- regalloc(&nod1, n, &nod);
- gmove(&nod, &nod1);
- gmove(&nod1, nn);
- regfree(&nod1);
- regfree(&nod);
- break;
-
- case ODOT:
- sugen(l, nodrat, l->type->width);
- if(nn == Z)
- break;
- warn(n, "non-interruptable temporary");
- nod = *nodrat;
- if(!r || r->op != OCONST) {
- diag(n, "DOT and no offset");
- break;
- }
- nod.xoffset += (int32)r->vconst;
- nod.type = n->type;
- cgen(&nod, nn);
- break;
-
- case OCOND:
- bcgen(l, 1);
- p1 = p;
- cgen(r->left, nn);
- gbranch(OGOTO);
- patch(p1, pc);
- p1 = p;
- cgen(r->right, nn);
- patch(p1, pc);
- break;
-
- case OPOSTINC:
- case OPOSTDEC:
- v = 1;
- if(l->type->etype == TIND)
- v = l->type->link->width;
- if(o == OPOSTDEC)
- v = -v;
- if(l->op == OBIT)
- goto bitinc;
- if(nn == Z)
- goto pre;
-
- if(hardleft)
- reglcgen(&nod, l, Z);
- else
- nod = *l;
-
- gmove(&nod, nn);
- if(typefd[n->type->etype]) {
- regalloc(&nod1, l, Z);
- gmove(&nod, &nod1);
- if(v < 0)
- gopcode(OSUB, n->type, nodfconst(-v), &nod1);
- else
- gopcode(OADD, n->type, nodfconst(v), &nod1);
- gmove(&nod1, &nod);
- regfree(&nod1);
- } else
- gopcode(OADD, n->type, nodconst(v), &nod);
- if(hardleft)
- regfree(&nod);
- break;
-
- case OPREINC:
- case OPREDEC:
- v = 1;
- if(l->type->etype == TIND)
- v = l->type->link->width;
- if(o == OPREDEC)
- v = -v;
- if(l->op == OBIT)
- goto bitinc;
-
- pre:
- if(hardleft)
- reglcgen(&nod, l, Z);
- else
- nod = *l;
- if(typefd[n->type->etype]) {
- regalloc(&nod1, l, Z);
- gmove(&nod, &nod1);
- if(v < 0)
- gopcode(OSUB, n->type, nodfconst(-v), &nod1);
- else
- gopcode(OADD, n->type, nodfconst(v), &nod1);
- gmove(&nod1, &nod);
- regfree(&nod1);
- } else
- gopcode(OADD, n->type, nodconst(v), &nod);
- if(nn != Z)
- gmove(&nod, nn);
- if(hardleft)
- regfree(&nod);
- break;
-
- bitinc:
- if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) {
- bitload(l, &nod, &nod1, &nod2, Z);
- gmove(&nod, nn);
- gopcode(OADD, tfield, nodconst(v), &nod);
- bitstore(l, &nod, &nod1, &nod2, Z);
- break;
- }
- bitload(l, &nod, &nod1, &nod2, nn);
- gopcode(OADD, tfield, nodconst(v), &nod);
- bitstore(l, &nod, &nod1, &nod2, nn);
- break;
- }
-done:
- cursafe = curs;
-}
-
-void
-reglcgen(Node *t, Node *n, Node *nn)
-{
- Node *r;
- int32 v;
-
- regialloc(t, n, nn);
- if(n->op == OIND) {
- r = n->left;
- while(r->op == OADD)
- r = r->right;
- if(sconst(r)) {
- v = r->vconst;
- r->vconst = 0;
- lcgen(n, t);
- t->xoffset += v;
- r->vconst = v;
- regind(t, n);
- return;
- }
- }
- lcgen(n, t);
- regind(t, n);
-}
-
-void
-lcgen(Node *n, Node *nn)
-{
- Prog *p1;
- Node nod;
-
- if(debug['g']) {
- prtree(nn, "lcgen lhs");
- prtree(n, "lcgen");
- }
- if(n == Z || n->type == T)
- return;
- if(nn == Z) {
- nn = &nod;
- regalloc(&nod, n, Z);
- }
- switch(n->op) {
- default:
- if(n->addable < INDEXED) {
- diag(n, "unknown op in lcgen: %O", n->op);
- break;
- }
- gopcode(OADDR, n->type, n, nn);
- break;
-
- case OCOMMA:
- cgen(n->left, n->left);
- lcgen(n->right, nn);
- break;
-
- case OIND:
- cgen(n->left, nn);
- break;
-
- case OCOND:
- bcgen(n->left, 1);
- p1 = p;
- lcgen(n->right->left, nn);
- gbranch(OGOTO);
- patch(p1, pc);
- p1 = p;
- lcgen(n->right->right, nn);
- patch(p1, pc);
- break;
- }
-}
-
-void
-bcgen(Node *n, int true)
-{
-
- if(n->type == T)
- gbranch(OGOTO);
- else
- boolgen(n, true, Z);
-}
-
-void
-boolgen(Node *n, int true, Node *nn)
-{
- int o;
- Prog *p1, *p2, *p3;
- Node *l, *r, nod, nod1;
- int32 curs;
-
- if(debug['g']) {
- print("boolgen %d\n", true);
- prtree(nn, "boolgen lhs");
- prtree(n, "boolgen");
- }
- curs = cursafe;
- l = n->left;
- r = n->right;
- switch(n->op) {
-
- default:
- o = ONE;
- if(true)
- o = OEQ;
- /* bad, 13 is address of external that becomes constant */
- if(n->addable >= INDEXED && n->addable != 13) {
- if(typefd[n->type->etype]) {
- regalloc(&nod1, n, Z);
- gmove(nodfconst(0.0), &nod1); /* TO DO: FREGZERO */
- gopcode(o, n->type, n, &nod1);
- regfree(&nod1);
- } else
- gopcode(o, n->type, n, nodconst(0));
- goto com;
- }
- regalloc(&nod, n, nn);
- cgen(n, &nod);
- if(typefd[n->type->etype]) {
- regalloc(&nod1, n, Z);
- gmove(nodfconst(0.0), &nod1); /* TO DO: FREGZERO */
- gopcode(o, n->type, &nod, &nod1);
- regfree(&nod1);
- } else
- gopcode(o, n->type, &nod, nodconst(0));
- regfree(&nod);
- goto com;
-
- case OCONST:
- o = vconst(n);
- if(!true)
- o = !o;
- gbranch(OGOTO);
- if(o) {
- p1 = p;
- gbranch(OGOTO);
- patch(p1, pc);
- }
- goto com;
-
- case OCOMMA:
- cgen(l, Z);
- boolgen(r, true, nn);
- break;
-
- case ONOT:
- boolgen(l, !true, nn);
- break;
-
- case OCOND:
- bcgen(l, 1);
- p1 = p;
- bcgen(r->left, true);
- p2 = p;
- gbranch(OGOTO);
- patch(p1, pc);
- p1 = p;
- bcgen(r->right, !true);
- patch(p2, pc);
- p2 = p;
- gbranch(OGOTO);
- patch(p1, pc);
- patch(p2, pc);
- goto com;
-
- case OANDAND:
- if(!true)
- goto caseor;
-
- caseand:
- bcgen(l, true);
- p1 = p;
- bcgen(r, !true);
- p2 = p;
- patch(p1, pc);
- gbranch(OGOTO);
- patch(p2, pc);
- goto com;
-
- case OOROR:
- if(!true)
- goto caseand;
-
- caseor:
- bcgen(l, !true);
- p1 = p;
- bcgen(r, !true);
- p2 = p;
- gbranch(OGOTO);
- patch(p1, pc);
- patch(p2, pc);
- goto com;
-
- case OEQ:
- case ONE:
- case OLE:
- case OLT:
- case OGE:
- case OGT:
- case OHI:
- case OHS:
- case OLO:
- case OLS:
- o = n->op;
- if(true && typefd[l->type->etype] && (o == OEQ || o == ONE)) {
- // Cannot rewrite !(l == r) into l != r with float64; it breaks NaNs.
- // Jump around instead.
- boolgen(n, 0, Z);
- p1 = p;
- gbranch(OGOTO);
- patch(p1, pc);
- goto com;
- }
- if(true)
- o = comrel[relindex(o)];
- if(l->complex >= FNX && r->complex >= FNX) {
- regret(&nod, r, 0, 0);
- cgen(r, &nod);
- regsalloc(&nod1, r);
- gmove(&nod, &nod1);
- regfree(&nod);
- nod = *n;
- nod.right = &nod1;
- boolgen(&nod, true, nn);
- break;
- }
- if(immconst(l)) {
- // NOTE: Reversing the comparison here is wrong
- // for floating point ordering comparisons involving NaN,
- // but we don't have any of those yet so we don't
- // bother worrying about it.
- o = invrel[relindex(o)];
- /* bad, 13 is address of external that becomes constant */
- if(r->addable < INDEXED || r->addable == 13) {
- regalloc(&nod, r, nn);
- cgen(r, &nod);
- gopcode(o, l->type, &nod, l);
- regfree(&nod);
- } else
- gopcode(o, l->type, r, l);
- goto com;
- }
- if(typefd[l->type->etype])
- o = invrel[relindex(logrel[relindex(o)])];
- if(l->complex >= r->complex) {
- regalloc(&nod, l, nn);
- cgen(l, &nod);
- if(r->addable < INDEXED || hardconst(r) || typefd[l->type->etype]) {
- regalloc(&nod1, r, Z);
- cgen(r, &nod1);
- gopcode(o, l->type, &nod, &nod1);
- regfree(&nod1);
- } else {
- gopcode(o, l->type, &nod, r);
- }
- regfree(&nod);
- goto fixfloat;
- }
- regalloc(&nod, r, nn);
- cgen(r, &nod);
- if(l->addable < INDEXED || l->addable == 13 || hardconst(l)) {
- regalloc(&nod1, l, Z);
- cgen(l, &nod1);
- if(typechl[l->type->etype] && ewidth[l->type->etype] <= ewidth[TINT])
- gopcode(o, types[TINT], &nod1, &nod);
- else
- gopcode(o, l->type, &nod1, &nod);
- regfree(&nod1);
- } else
- gopcode(o, l->type, l, &nod);
- regfree(&nod);
- fixfloat:
- if(typefd[l->type->etype]) {
- switch(o) {
- case OEQ:
- // Already emitted AJEQ; want AJEQ and AJPC.
- p1 = p;
- gbranch(OGOTO);
- p2 = p;
- patch(p1, pc);
- gins(AJPC, Z, Z);
- patch(p2, pc);
- break;
-
- case ONE:
- // Already emitted AJNE; want AJNE or AJPS.
- p1 = p;
- gins(AJPS, Z, Z);
- p2 = p;
- gbranch(OGOTO);
- p3 = p;
- patch(p1, pc);
- patch(p2, pc);
- gbranch(OGOTO);
- patch(p3, pc);
- break;
- }
- }
-
- com:
- if(nn != Z) {
- p1 = p;
- gmove(nodconst(1L), nn);
- gbranch(OGOTO);
- p2 = p;
- patch(p1, pc);
- gmove(nodconst(0L), nn);
- patch(p2, pc);
- }
- break;
- }
- cursafe = curs;
-}
-
-void
-sugen(Node *n, Node *nn, int32 w)
-{
- Prog *p1;
- Node nod0, nod1, nod2, nod3, nod4, *l, *r;
- Type *t;
- int c, mt, mo;
- vlong o0, o1;
-
- if(n == Z || n->type == T)
- return;
- if(debug['g']) {
- prtree(nn, "sugen lhs");
- prtree(n, "sugen");
- }
- if(nn == nodrat)
- if(w > nrathole)
- nrathole = w;
- switch(n->op) {
- case OIND:
- if(nn == Z) {
- nullwarn(n->left, Z);
- break;
- }
-
- default:
- goto copy;
-
- case OCONST:
- goto copy;
-
- case ODOT:
- l = n->left;
- sugen(l, nodrat, l->type->width);
- if(nn == Z)
- break;
- warn(n, "non-interruptable temporary");
- nod1 = *nodrat;
- r = n->right;
- if(!r || r->op != OCONST) {
- diag(n, "DOT and no offset");
- break;
- }
- nod1.xoffset += (int32)r->vconst;
- nod1.type = n->type;
- sugen(&nod1, nn, w);
- break;
-
- case OSTRUCT:
- /*
- * rewrite so lhs has no fn call
- */
- if(nn != Z && side(nn)) {
- nod1 = *n;
- nod1.type = typ(TIND, n->type);
- regret(&nod2, &nod1, 0, 0);
- lcgen(nn, &nod2);
- regsalloc(&nod0, &nod1);
- cgen(&nod2, &nod0);
- regfree(&nod2);
-
- nod1 = *n;
- nod1.op = OIND;
- nod1.left = &nod0;
- nod1.right = Z;
- nod1.complex = 1;
-
- sugen(n, &nod1, w);
- return;
- }
-
- r = n->left;
- for(t = n->type->link; t != T; t = t->down) {
- l = r;
- if(r->op == OLIST) {
- l = r->left;
- r = r->right;
- }
- if(nn == Z) {
- cgen(l, nn);
- continue;
- }
- /*
- * hand craft *(&nn + o) = l
- */
- nod0 = znode;
- nod0.op = OAS;
- nod0.type = t;
- nod0.left = &nod1;
- nod0.right = nil;
-
- nod1 = znode;
- nod1.op = OIND;
- nod1.type = t;
- nod1.left = &nod2;
-
- nod2 = znode;
- nod2.op = OADD;
- nod2.type = typ(TIND, t);
- nod2.left = &nod3;
- nod2.right = &nod4;
-
- nod3 = znode;
- nod3.op = OADDR;
- nod3.type = nod2.type;
- nod3.left = nn;
-
- nod4 = znode;
- nod4.op = OCONST;
- nod4.type = nod2.type;
- nod4.vconst = t->offset;
-
- ccom(&nod0);
- acom(&nod0);
- xcom(&nod0);
- nod0.addable = 0;
- nod0.right = l;
-
- // prtree(&nod0, "hand craft");
- cgen(&nod0, Z);
- }
- break;
-
- case OAS:
- if(nn == Z) {
- if(n->addable < INDEXED)
- sugen(n->right, n->left, w);
- break;
- }
-
- sugen(n->right, nodrat, w);
- warn(n, "non-interruptable temporary");
- sugen(nodrat, n->left, w);
- sugen(nodrat, nn, w);
- break;
-
- case OFUNC:
- if(!hasdotdotdot(n->left->type)) {
- cgen(n, Z);
- if(nn != Z) {
- curarg -= n->type->width;
- regret(&nod1, n, n->left->type, 1);
- if(nn->complex >= FNX) {
- regsalloc(&nod2, n);
- cgen(&nod1, &nod2);
- nod1 = nod2;
- }
- cgen(&nod1, nn);
- }
- break;
- }
- if(nn == Z) {
- sugen(n, nodrat, w);
- break;
- }
- if(nn->op != OIND) {
- nn = new1(OADDR, nn, Z);
- nn->type = types[TIND];
- nn->addable = 0;
- } else
- nn = nn->left;
- n = new(OFUNC, n->left, new(OLIST, nn, n->right));
- n->type = types[TVOID];
- n->left->type = types[TVOID];
- cgen(n, Z);
- break;
-
- case OCOND:
- bcgen(n->left, 1);
- p1 = p;
- sugen(n->right->left, nn, w);
- gbranch(OGOTO);
- patch(p1, pc);
- p1 = p;
- sugen(n->right->right, nn, w);
- patch(p1, pc);
- break;
-
- case OCOMMA:
- cgen(n->left, Z);
- sugen(n->right, nn, w);
- break;
- }
- return;
-
-copy:
- if(nn == Z) {
- switch(n->op) {
- case OASADD:
- case OASSUB:
- case OASAND:
- case OASOR:
- case OASXOR:
-
- case OASMUL:
- case OASLMUL:
-
-
- case OASASHL:
- case OASASHR:
- case OASLSHR:
- break;
-
- case OPOSTINC:
- case OPOSTDEC:
- case OPREINC:
- case OPREDEC:
- break;
-
- default:
- return;
- }
- }
-
- if(n->complex >= FNX && nn != nil && nn->complex >= FNX) {
- t = nn->type;
- nn->type = types[TIND];
- regialloc(&nod1, nn, Z);
- lcgen(nn, &nod1);
- regsalloc(&nod2, nn);
- nn->type = t;
-
- gins(AMOVQ, &nod1, &nod2);
- regfree(&nod1);
-
- nod2.type = typ(TIND, t);
-
- nod1 = nod2;
- nod1.op = OIND;
- nod1.left = &nod2;
- nod1.right = Z;
- nod1.complex = 1;
- nod1.type = t;
-
- sugen(n, &nod1, w);
- return;
- }
-
- if(w <= 32) {
- c = cursafe;
- if(n->left != Z && n->left->complex >= FNX
- && n->right != Z && n->right->complex >= FNX) {
- regsalloc(&nod1, n->right);
- cgen(n->right, &nod1);
- nod2 = *n;
- nod2.right = &nod1;
- cgen(&nod2, nn);
- cursafe = c;
- return;
- }
- if(w & 7) {
- mt = TLONG;
- mo = AMOVL;
- } else {
- mt = TVLONG;
- mo = AMOVQ;
- }
- if(n->complex > nn->complex) {
- t = n->type;
- n->type = types[mt];
- regalloc(&nod0, n, Z);
- if(!vaddr(n, 0)) {
- reglcgen(&nod1, n, Z);
- n->type = t;
- n = &nod1;
- }
- else
- n->type = t;
-
- t = nn->type;
- nn->type = types[mt];
- if(!vaddr(nn, 0)) {
- reglcgen(&nod2, nn, Z);
- nn->type = t;
- nn = &nod2;
- }
- else
- nn->type = t;
- } else {
- t = nn->type;
- nn->type = types[mt];
- regalloc(&nod0, nn, Z);
- if(!vaddr(nn, 0)) {
- reglcgen(&nod2, nn, Z);
- nn->type = t;
- nn = &nod2;
- }
- else
- nn->type = t;
-
- t = n->type;
- n->type = types[mt];
- if(!vaddr(n, 0)) {
- reglcgen(&nod1, n, Z);
- n->type = t;
- n = &nod1;
- }
- else
- n->type = t;
- }
- o0 = n->xoffset;
- o1 = nn->xoffset;
- w /= ewidth[mt];
- while(--w >= 0) {
- gins(mo, n, &nod0);
- gins(mo, &nod0, nn);
- n->xoffset += ewidth[mt];
- nn->xoffset += ewidth[mt];
- }
- n->xoffset = o0;
- nn->xoffset = o1;
- if(nn == &nod2)
- regfree(&nod2);
- if(n == &nod1)
- regfree(&nod1);
- regfree(&nod0);
- return;
- }
-
- /* botch, need to save in .safe */
- c = 0;
- if(n->complex > nn->complex) {
- t = n->type;
- n->type = types[TIND];
- nodreg(&nod1, n, D_SI);
- if(reg[D_SI]) {
- gins(APUSHQ, &nod1, Z);
- c |= 1;
- reg[D_SI]++;
- }
- lcgen(n, &nod1);
- n->type = t;
-
- t = nn->type;
- nn->type = types[TIND];
- nodreg(&nod2, nn, D_DI);
- if(reg[D_DI]) {
-warn(Z, "DI botch");
- gins(APUSHQ, &nod2, Z);
- c |= 2;
- reg[D_DI]++;
- }
- lcgen(nn, &nod2);
- nn->type = t;
- } else {
- t = nn->type;
- nn->type = types[TIND];
- nodreg(&nod2, nn, D_DI);
- if(reg[D_DI]) {
-warn(Z, "DI botch");
- gins(APUSHQ, &nod2, Z);
- c |= 2;
- reg[D_DI]++;
- }
- lcgen(nn, &nod2);
- nn->type = t;
-
- t = n->type;
- n->type = types[TIND];
- nodreg(&nod1, n, D_SI);
- if(reg[D_SI]) {
- gins(APUSHQ, &nod1, Z);
- c |= 1;
- reg[D_SI]++;
- }
- lcgen(n, &nod1);
- n->type = t;
- }
- nodreg(&nod3, n, D_CX);
- if(reg[D_CX]) {
- gins(APUSHQ, &nod3, Z);
- c |= 4;
- reg[D_CX]++;
- }
- gins(AMOVL, nodconst(w/SZ_INT), &nod3);
- gins(ACLD, Z, Z);
- gins(AREP, Z, Z);
- gins(AMOVSL, Z, Z);
- if(c & 4) {
- gins(APOPQ, Z, &nod3);
- reg[D_CX]--;
- }
- if(c & 2) {
- gins(APOPQ, Z, &nod2);
- reg[nod2.reg]--;
- }
- if(c & 1) {
- gins(APOPQ, Z, &nod1);
- reg[nod1.reg]--;
- }
-}
-
-/*
- * TO DO
- */
-void
-layout(Node *f, Node *t, int c, int cv, Node *cn)
-{
- Node t1, t2;
-
- while(c > 3) {
- layout(f, t, 2, 0, Z);
- c -= 2;
- }
-
- regalloc(&t1, &lregnode, Z);
- regalloc(&t2, &lregnode, Z);
- if(c > 0) {
- gmove(f, &t1);
- f->xoffset += SZ_INT;
- }
- if(cn != Z)
- gmove(nodconst(cv), cn);
- if(c > 1) {
- gmove(f, &t2);
- f->xoffset += SZ_INT;
- }
- if(c > 0) {
- gmove(&t1, t);
- t->xoffset += SZ_INT;
- }
- if(c > 2) {
- gmove(f, &t1);
- f->xoffset += SZ_INT;
- }
- if(c > 1) {
- gmove(&t2, t);
- t->xoffset += SZ_INT;
- }
- if(c > 2) {
- gmove(&t1, t);
- t->xoffset += SZ_INT;
- }
- regfree(&t1);
- regfree(&t2);
-}
-
-/*
- * constant is not vlong or fits as 32-bit signed immediate
- */
-int
-immconst(Node *n)
-{
- int32 v;
-
- if(n->op != OCONST || !typechlpv[n->type->etype])
- return 0;
- if(typechl[n->type->etype])
- return 1;
- v = n->vconst;
- return n->vconst == (vlong)v;
-}
-
-/*
- * if a constant and vlong, doesn't fit as 32-bit signed immediate
- */
-int
-hardconst(Node *n)
-{
- return n->op == OCONST && !immconst(n);
-}
-
-/*
- * casting up to t2 covers an intermediate cast to t1
- */
-int
-castup(Type *t1, Type *t2)
-{
- int ft;
-
- if(!nilcast(t1, t2))
- return 0;
- /* known to be small to large */
- ft = t1->etype;
- switch(t2->etype){
- case TINT:
- case TLONG:
- return ft == TLONG || ft == TINT || ft == TSHORT || ft == TCHAR;
- case TUINT:
- case TULONG:
- return ft == TULONG || ft == TUINT || ft == TUSHORT || ft == TUCHAR;
- case TVLONG:
- return ft == TLONG || ft == TINT || ft == TSHORT;
- case TUVLONG:
- return ft == TULONG || ft == TUINT || ft == TUSHORT;
- }
- return 0;
-}
-
-void
-zeroregm(Node *n)
-{
- gins(AMOVL, nodconst(0), n);
-}
-
-/* do we need to load the address of a vlong? */
-int
-vaddr(Node *n, int a)
-{
- switch(n->op) {
- case ONAME:
- if(a)
- return 1;
- return !(n->class == CEXTERN || n->class == CGLOBL || n->class == CSTATIC);
-
- case OCONST:
- case OREGISTER:
- case OINDREG:
- return 1;
- }
- return 0;
-}
-
-int32
-hi64v(Node *n)
-{
- if(align(0, types[TCHAR], Aarg1, nil)) /* isbigendian */
- return (int32)(n->vconst) & ~0L;
- else
- return (int32)((uvlong)n->vconst>>32) & ~0L;
-}
-
-int32
-lo64v(Node *n)
-{
- if(align(0, types[TCHAR], Aarg1, nil)) /* isbigendian */
- return (int32)((uvlong)n->vconst>>32) & ~0L;
- else
- return (int32)(n->vconst) & ~0L;
-}
-
-Node *
-hi64(Node *n)
-{
- return nodconst(hi64v(n));
-}
-
-Node *
-lo64(Node *n)
-{
- return nodconst(lo64v(n));
-}
-
-int
-cond(int op)
-{
- switch(op) {
- case OANDAND:
- case OOROR:
- case ONOT:
- return 1;
-
- case OEQ:
- case ONE:
- case OLE:
- case OLT:
- case OGE:
- case OGT:
- case OHI:
- case OHS:
- case OLO:
- case OLS:
- return 1;
- }
- return 0;
-}
diff --git a/src/cmd/6c/div.c b/src/cmd/6c/div.c
deleted file mode 100644
index bad6c5e27..000000000
--- a/src/cmd/6c/div.c
+++ /dev/null
@@ -1,236 +0,0 @@
-// Inferno utils/6c/div.c
-// http://code.google.com/p/inferno-os/source/browse/utils/6c/div.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-
-/*
- * Based on: Granlund, T.; Montgomery, P.L.
- * "Division by Invariant Integers using Multiplication".
- * SIGPLAN Notices, Vol. 29, June 1994, page 61.
- */
-
-#define TN(n) ((uvlong)1 << (n))
-#define T31 TN(31)
-#define T32 TN(32)
-
-int
-multiplier(uint32 d, int p, uvlong *mp)
-{
- int l;
- uvlong mlo, mhi, tlo, thi;
-
- l = topbit(d - 1) + 1;
- mlo = (((TN(l) - d) << 32) / d) + T32;
- if(l + p == 64)
- mhi = (((TN(l) + 1 - d) << 32) / d) + T32;
- else
- mhi = (TN(32 + l) + TN(32 + l - p)) / d;
- /*assert(mlo < mhi);*/
- while(l > 0) {
- tlo = mlo >> 1;
- thi = mhi >> 1;
- if(tlo == thi)
- break;
- mlo = tlo;
- mhi = thi;
- l--;
- }
- *mp = mhi;
- return l;
-}
-
-int
-sdiv(uint32 d, uint32 *mp, int *sp)
-{
- int s;
- uvlong m;
-
- s = multiplier(d, 32 - 1, &m);
- *mp = m;
- *sp = s;
- if(m >= T31)
- return 1;
- else
- return 0;
-}
-
-int
-udiv(uint32 d, uint32 *mp, int *sp, int *pp)
-{
- int p, s;
- uvlong m;
-
- s = multiplier(d, 32, &m);
- p = 0;
- if(m >= T32) {
- while((d & 1) == 0) {
- d >>= 1;
- p++;
- }
- s = multiplier(d, 32 - p, &m);
- }
- *mp = m;
- *pp = p;
- if(m >= T32) {
- /*assert(p == 0);*/
- *sp = s - 1;
- return 1;
- }
- else {
- *sp = s;
- return 0;
- }
-}
-
-void
-sdivgen(Node *l, Node *r, Node *ax, Node *dx)
-{
- int a, s;
- uint32 m;
- vlong c;
-
- c = r->vconst;
- if(c < 0)
- c = -c;
- a = sdiv(c, &m, &s);
-//print("a=%d i=%d s=%d m=%ux\n", a, (long)r->vconst, s, m);
- gins(AMOVL, nodconst(m), ax);
- gins(AIMULL, l, Z);
- gins(AMOVL, l, ax);
- if(a)
- gins(AADDL, ax, dx);
- gins(ASHRL, nodconst(31), ax);
- gins(ASARL, nodconst(s), dx);
- gins(AADDL, ax, dx);
- if(r->vconst < 0)
- gins(ANEGL, Z, dx);
-}
-
-void
-udivgen(Node *l, Node *r, Node *ax, Node *dx)
-{
- int a, s, t;
- uint32 m;
- Node nod;
-
- a = udiv(r->vconst, &m, &s, &t);
-//print("a=%ud i=%d p=%d s=%d m=%ux\n", a, (long)r->vconst, t, s, m);
- if(t != 0) {
- gins(AMOVL, l, ax);
- gins(ASHRL, nodconst(t), ax);
- gins(AMOVL, nodconst(m), dx);
- gins(AMULL, dx, Z);
- }
- else if(a) {
- if(l->op != OREGISTER) {
- regalloc(&nod, l, Z);
- gins(AMOVL, l, &nod);
- l = &nod;
- }
- gins(AMOVL, nodconst(m), ax);
- gins(AMULL, l, Z);
- gins(AADDL, l, dx);
- gins(ARCRL, nodconst(1), dx);
- if(l == &nod)
- regfree(l);
- }
- else {
- gins(AMOVL, nodconst(m), ax);
- gins(AMULL, l, Z);
- }
- if(s != 0)
- gins(ASHRL, nodconst(s), dx);
-}
-
-void
-sext(Node *d, Node *s, Node *l)
-{
- if(s->reg == D_AX && !nodreg(d, Z, D_DX)) {
- reg[D_DX]++;
- gins(ACDQ, Z, Z);
- }
- else {
- regalloc(d, l, Z);
- gins(AMOVL, s, d);
- gins(ASARL, nodconst(31), d);
- }
-}
-
-void
-sdiv2(int32 c, int v, Node *l, Node *n)
-{
- Node nod;
-
- if(v > 0) {
- if(v > 1) {
- sext(&nod, n, l);
- gins(AANDL, nodconst((1 << v) - 1), &nod);
- gins(AADDL, &nod, n);
- regfree(&nod);
- }
- else {
- gins(ACMPL, n, nodconst(0x80000000));
- gins(ASBBL, nodconst(-1), n);
- }
- gins(ASARL, nodconst(v), n);
- }
- if(c < 0)
- gins(ANEGL, Z, n);
-}
-
-void
-smod2(int32 c, int v, Node *l, Node *n)
-{
- Node nod;
-
- if(c == 1) {
- zeroregm(n);
- return;
- }
-
- sext(&nod, n, l);
- if(v == 0) {
- zeroregm(n);
- gins(AXORL, &nod, n);
- gins(ASUBL, &nod, n);
- }
- else if(v > 1) {
- gins(AANDL, nodconst((1 << v) - 1), &nod);
- gins(AADDL, &nod, n);
- gins(AANDL, nodconst((1 << v) - 1), n);
- gins(ASUBL, &nod, n);
- }
- else {
- gins(AANDL, nodconst(1), n);
- gins(AXORL, &nod, n);
- gins(ASUBL, &nod, n);
- }
- regfree(&nod);
-}
diff --git a/src/cmd/6c/doc.go b/src/cmd/6c/doc.go
deleted file mode 100644
index e0a22e78b..000000000
--- a/src/cmd/6c/doc.go
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build ignore
-
-/*
-
-6c is a version of the Plan 9 C compiler. The original is documented at
-
- http://plan9.bell-labs.com/magic/man2html/1/8c
-
-Its target architecture is the x86-64, referred to by these tools as amd64.
-
-*/
-package main
diff --git a/src/cmd/6c/gc.h b/src/cmd/6c/gc.h
deleted file mode 100644
index aa9d95d21..000000000
--- a/src/cmd/6c/gc.h
+++ /dev/null
@@ -1,359 +0,0 @@
-// Inferno utils/6c/gc.h
-// http://code.google.com/p/inferno-os/source/browse/utils/6c/gc.h
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include <u.h>
-#include "../cc/cc.h"
-#include "../6l/6.out.h"
-
-/*
- * 6c/amd64
- * Intel 386 with AMD64 extensions
- */
-#define SZ_CHAR 1
-#define SZ_SHORT 2
-#define SZ_INT 4
-#define SZ_LONG 4
-#define SZ_IND 8
-#define SZ_FLOAT 4
-#define SZ_VLONG 8
-#define SZ_DOUBLE 8
-#define FNX 100
-
-typedef struct Case Case;
-typedef struct C1 C1;
-typedef struct Reg Reg;
-typedef struct Rgn Rgn;
-typedef struct Renv Renv;
-
-EXTERN struct
-{
- Node* regtree;
- Node* basetree;
- short scale;
- short reg;
- short ptr;
-} idx;
-
-#define INDEXED 9
-
-#define A ((Addr*)0)
-#define P ((Prog*)0)
-
-struct Case
-{
- Case* link;
- vlong val;
- int32 label;
- char def;
- char isv;
-};
-#define C ((Case*)0)
-
-struct C1
-{
- vlong val;
- int32 label;
-};
-
-struct Reg
-{
- int32 pc;
- int32 rpo; /* reverse post ordering */
-
- Bits set;
- Bits use1;
- Bits use2;
-
- Bits refbehind;
- Bits refahead;
- Bits calbehind;
- Bits calahead;
- Bits regdiff;
- Bits act;
-
- int32 regu;
- int32 loop; /* could be shorter */
-
- Reg* log5;
- int32 active;
-
- Reg* p1;
- Reg* p2;
- Reg* p2link;
- Reg* s1;
- Reg* s2;
- Reg* link;
- Prog* prog;
-};
-#define R ((Reg*)0)
-
-struct Renv
-{
- int safe;
- Node base;
- Node* saved;
- Node* scope;
-};
-
-#define NRGN 600
-struct Rgn
-{
- Reg* enter;
- short cost;
- short varno;
- short regno;
-};
-
-EXTERN int32 breakpc;
-EXTERN int32 nbreak;
-EXTERN Case* cases;
-EXTERN Node constnode;
-EXTERN Node fconstnode;
-EXTERN Node vconstnode;
-EXTERN int32 continpc;
-EXTERN int32 curarg;
-EXTERN int32 cursafe;
-EXTERN Prog* lastp;
-EXTERN int32 maxargsafe;
-EXTERN int mnstring;
-EXTERN Node* nodrat;
-EXTERN Node* nodret;
-EXTERN Node* nodsafe;
-EXTERN int32 nrathole;
-EXTERN int32 nstring;
-EXTERN Prog* p;
-EXTERN int32 pc;
-EXTERN Node lregnode;
-EXTERN Node qregnode;
-EXTERN char string[NSNAME];
-EXTERN Sym* symrathole;
-EXTERN Node znode;
-EXTERN Prog zprog;
-EXTERN int reg[D_NONE];
-EXTERN int32 exregoffset;
-EXTERN int32 exfregoffset;
-EXTERN uchar typechlpv[NTYPE];
-
-#define BLOAD(r) band(bnot(r->refbehind), r->refahead)
-#define BSTORE(r) band(bnot(r->calbehind), r->calahead)
-#define LOAD(r) (~r->refbehind.b[z] & r->refahead.b[z])
-#define STORE(r) (~r->calbehind.b[z] & r->calahead.b[z])
-
-#define bset(a,n) ((a).b[(n)/32]&(1L<<(n)%32))
-
-#define CLOAD 5
-#define CREF 5
-#define CINF 1000
-#define LOOP 3
-
-EXTERN Rgn region[NRGN];
-EXTERN Rgn* rgp;
-EXTERN int nregion;
-EXTERN int nvar;
-
-EXTERN Bits externs;
-EXTERN Bits params;
-EXTERN Bits consts;
-EXTERN Bits addrs;
-
-EXTERN int32 regbits;
-EXTERN int32 exregbits;
-
-EXTERN int change;
-EXTERN int suppress;
-
-EXTERN Reg* firstr;
-EXTERN Reg* lastr;
-EXTERN Reg zreg;
-EXTERN Reg* freer;
-EXTERN int32* idom;
-EXTERN Reg** rpo2r;
-EXTERN int32 maxnr;
-
-extern char* anames[];
-
-/*
- * sgen.c
- */
-void codgen(Node*, Node*);
-void gen(Node*);
-void noretval(int);
-void usedset(Node*, int);
-void xcom(Node*);
-void indx(Node*);
-int bcomplex(Node*, Node*);
-Prog* gtext(Sym*, int32);
-vlong argsize(int);
-
-/*
- * cgen.c
- */
-void zeroregm(Node*);
-void cgen(Node*, Node*);
-void reglcgen(Node*, Node*, Node*);
-void lcgen(Node*, Node*);
-void bcgen(Node*, int);
-void boolgen(Node*, int, Node*);
-void sugen(Node*, Node*, int32);
-int needreg(Node*, int);
-int hardconst(Node*);
-int immconst(Node*);
-
-/*
- * txt.c
- */
-void ginit(void);
-void gclean(void);
-void nextpc(void);
-void gargs(Node*, Node*, Node*);
-void garg1(Node*, Node*, Node*, int, Node**);
-Node* nodconst(int32);
-Node* nodfconst(double);
-Node* nodgconst(vlong, Type*);
-int nodreg(Node*, Node*, int);
-int isreg(Node*, int);
-void regret(Node*, Node*, Type*, int);
-void regalloc(Node*, Node*, Node*);
-void regfree(Node*);
-void regialloc(Node*, Node*, Node*);
-void regsalloc(Node*, Node*);
-void regaalloc1(Node*, Node*);
-void regaalloc(Node*, Node*);
-void regind(Node*, Node*);
-void gprep(Node*, Node*);
-void naddr(Node*, Addr*);
-void gcmp(int, Node*, vlong);
-void gmove(Node*, Node*);
-void gins(int a, Node*, Node*);
-void gopcode(int, Type*, Node*, Node*);
-int samaddr(Node*, Node*);
-void gbranch(int);
-void patch(Prog*, int32);
-int sconst(Node*);
-void gpseudo(int, Sym*, Node*);
-void gprefetch(Node*);
-void gpcdata(int, int);
-
-/*
- * swt.c
- */
-int swcmp(const void*, const void*);
-void doswit(Node*);
-void swit1(C1*, int, int32, Node*);
-void swit2(C1*, int, int32, Node*);
-void newcase(void);
-void bitload(Node*, Node*, Node*, Node*, Node*);
-void bitstore(Node*, Node*, Node*, Node*, Node*);
-int32 outstring(char*, int32);
-void nullwarn(Node*, Node*);
-void sextern(Sym*, Node*, int32, int32);
-void gextern(Sym*, Node*, int32, int32);
-void outcode(void);
-
-/*
- * list
- */
-void listinit(void);
-
-/*
- * reg.c
- */
-Reg* rega(void);
-int rcmp(const void*, const void*);
-void regopt(Prog*);
-void addmove(Reg*, int, int, int);
-Bits mkvar(Reg*, Addr*);
-void prop(Reg*, Bits, Bits);
-void loopit(Reg*, int32);
-void synch(Reg*, Bits);
-uint32 allreg(uint32, Rgn*);
-void paint1(Reg*, int);
-uint32 paint2(Reg*, int);
-void paint3(Reg*, int, int32, int);
-void addreg(Addr*, int);
-
-/*
- * peep.c
- */
-void peep(void);
-void excise(Reg*);
-Reg* uniqp(Reg*);
-Reg* uniqs(Reg*);
-int regtyp(Addr*);
-int anyvar(Addr*);
-int subprop(Reg*);
-int copyprop(Reg*);
-int copy1(Addr*, Addr*, Reg*, int);
-int copyu(Prog*, Addr*, Addr*);
-
-int copyas(Addr*, Addr*);
-int copyau(Addr*, Addr*);
-int copysub(Addr*, Addr*, Addr*, int);
-int copysub1(Prog*, Addr*, Addr*, int);
-
-int32 RtoB(int);
-int32 FtoB(int);
-int BtoR(int32);
-int BtoF(int32);
-
-#define D_HI D_NONE
-#define D_LO D_NONE
-
-/*
- * bound
- */
-void comtarg(void);
-
-/*
- * com64
- */
-int cond(int);
-int com64(Node*);
-void com64init(void);
-void bool64(Node*);
-int32 lo64v(Node*);
-int32 hi64v(Node*);
-Node* lo64(Node*);
-Node* hi64(Node*);
-
-/*
- * div/mul
- */
-void sdivgen(Node*, Node*, Node*, Node*);
-void udivgen(Node*, Node*, Node*, Node*);
-void sdiv2(int32, int, Node*, Node*);
-void smod2(int32, int, Node*, Node*);
-void mulgen(Type*, Node*, Node*);
-void genmuladd(Node*, Node*, int, Node*);
-void shiftit(Type*, Node*, Node*);
-
-#define D_X7 (D_X0+7)
-
-void fgopcode(int, Node*, Node*, int, int);
diff --git a/src/cmd/6c/list.c b/src/cmd/6c/list.c
deleted file mode 100644
index 28f5b8df7..000000000
--- a/src/cmd/6c/list.c
+++ /dev/null
@@ -1,38 +0,0 @@
-// Inferno utils/6c/list.c
-// http://code.google.com/p/inferno-os/source/browse/utils/6c/list.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#define EXTERN
-#include "gc.h"
-
-void
-listinit(void)
-{
- listinit6();
-}
diff --git a/src/cmd/6c/machcap.c b/src/cmd/6c/machcap.c
deleted file mode 100644
index 820d9a0aa..000000000
--- a/src/cmd/6c/machcap.c
+++ /dev/null
@@ -1,107 +0,0 @@
-// Inferno utils/6c/machcap.c
-// http://code.google.com/p/inferno-os/source/browse/utils/6c/machcap.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-
-int
-machcap(Node *n)
-{
-
- if(n == Z)
- return 1; /* test */
-
- switch(n->op) {
- case OMUL:
- case OLMUL:
- case OASMUL:
- case OASLMUL:
- if(typechl[n->type->etype])
- return 1;
- if(typev[n->type->etype])
- return 1;
- break;
-
- case OCOM:
- case ONEG:
- case OADD:
- case OAND:
- case OOR:
- case OSUB:
- case OXOR:
- case OASHL:
- case OLSHR:
- case OASHR:
- if(typechlv[n->left->type->etype])
- return 1;
- break;
-
- case OCAST:
- return 1;
-
- case OCOND:
- case OCOMMA:
- case OLIST:
- case OANDAND:
- case OOROR:
- case ONOT:
- return 1;
-
- case OASADD:
- case OASSUB:
- case OASAND:
- case OASOR:
- case OASXOR:
- return 1;
-
- case OASASHL:
- case OASASHR:
- case OASLSHR:
- return 1;
-
- case OPOSTINC:
- case OPOSTDEC:
- case OPREINC:
- case OPREDEC:
- return 1;
-
- case OEQ:
- case ONE:
- case OLE:
- case OGT:
- case OLT:
- case OGE:
- case OHI:
- case OHS:
- case OLO:
- case OLS:
- return 1;
- }
- return 0;
-}
diff --git a/src/cmd/6c/mul.c b/src/cmd/6c/mul.c
deleted file mode 100644
index 510edc05c..000000000
--- a/src/cmd/6c/mul.c
+++ /dev/null
@@ -1,458 +0,0 @@
-// Inferno utils/6c/mul.c
-// http://code.google.com/p/inferno-os/source/browse/utils/6c/mul.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-
-typedef struct Malg Malg;
-typedef struct Mparam Mparam;
-
-struct Malg
-{
- schar vals[10];
-};
-
-struct Mparam
-{
- uint32 value;
- schar alg;
- char neg;
- char shift;
- char arg;
- schar off;
-};
-
-static Mparam multab[32];
-static int mulptr;
-
-static Malg malgs[] =
-{
- {0, 100},
- {-1, 1, 100},
- {-9, -5, -3, 3, 5, 9, 100},
- {6, 10, 12, 18, 20, 24, 36, 40, 72, 100},
- {-8, -4, -2, 2, 4, 8, 100},
-};
-
-/*
- * return position of lowest 1
- */
-int
-lowbit(uint32 v)
-{
- int s, i;
- uint32 m;
-
- s = 0;
- m = 0xFFFFFFFFUL;
- for(i = 16; i > 0; i >>= 1) {
- m >>= i;
- if((v & m) == 0) {
- v >>= i;
- s += i;
- }
- }
- return s;
-}
-
-void
-genmuladd(Node *d, Node *s, int m, Node *a)
-{
- Node nod;
-
- nod.op = OINDEX;
- nod.left = a;
- nod.right = s;
- nod.scale = m;
- nod.type = types[TIND];
- nod.xoffset = 0;
- xcom(&nod);
- gopcode(OADDR, d->type, &nod, d);
-}
-
-void
-mulparam(uint32 m, Mparam *mp)
-{
- int c, i, j, n, o, q, s;
- int bc, bi, bn, bo, bq, bs, bt;
- schar *p;
- int32 u;
- uint32 t;
-
- bc = bq = 10;
- bi = bn = bo = bs = bt = 0;
- for(i = 0; i < nelem(malgs); i++) {
- for(p = malgs[i].vals, j = 0; (o = p[j]) < 100; j++)
- for(s = 0; s < 2; s++) {
- c = 10;
- q = 10;
- u = m - o;
- if(u == 0)
- continue;
- if(s) {
- o = -o;
- if(o > 0)
- continue;
- u = -u;
- }
- n = lowbit(u);
- t = (uint32)u >> n;
- switch(i) {
- case 0:
- if(t == 1) {
- c = s + 1;
- q = 0;
- break;
- }
- switch(t) {
- case 3:
- case 5:
- case 9:
- c = s + 1;
- if(n)
- c++;
- q = 0;
- break;
- }
- if(s)
- break;
- switch(t) {
- case 15:
- case 25:
- case 27:
- case 45:
- case 81:
- c = 2;
- if(n)
- c++;
- q = 1;
- break;
- }
- break;
- case 1:
- if(t == 1) {
- c = 3;
- q = 3;
- break;
- }
- switch(t) {
- case 3:
- case 5:
- case 9:
- c = 3;
- q = 2;
- break;
- }
- break;
- case 2:
- if(t == 1) {
- c = 3;
- q = 2;
- break;
- }
- break;
- case 3:
- if(s)
- break;
- if(t == 1) {
- c = 3;
- q = 1;
- break;
- }
- break;
- case 4:
- if(t == 1) {
- c = 3;
- q = 0;
- break;
- }
- break;
- }
- if(c < bc || (c == bc && q > bq)) {
- bc = c;
- bi = i;
- bn = n;
- bo = o;
- bq = q;
- bs = s;
- bt = t;
- }
- }
- }
- mp->value = m;
- if(bc <= 3) {
- mp->alg = bi;
- mp->shift = bn;
- mp->off = bo;
- mp->neg = bs;
- mp->arg = bt;
- }
- else
- mp->alg = -1;
-}
-
-int
-m0(int a)
-{
- switch(a) {
- case -2:
- case 2:
- return 2;
- case -3:
- case 3:
- return 2;
- case -4:
- case 4:
- return 4;
- case -5:
- case 5:
- return 4;
- case 6:
- return 2;
- case -8:
- case 8:
- return 8;
- case -9:
- case 9:
- return 8;
- case 10:
- return 4;
- case 12:
- return 2;
- case 15:
- return 2;
- case 18:
- return 8;
- case 20:
- return 4;
- case 24:
- return 2;
- case 25:
- return 4;
- case 27:
- return 2;
- case 36:
- return 8;
- case 40:
- return 4;
- case 45:
- return 4;
- case 72:
- return 8;
- case 81:
- return 8;
- }
- diag(Z, "bad m0");
- return 0;
-}
-
-int
-m1(int a)
-{
- switch(a) {
- case 15:
- return 4;
- case 25:
- return 4;
- case 27:
- return 8;
- case 45:
- return 8;
- case 81:
- return 8;
- }
- diag(Z, "bad m1");
- return 0;
-}
-
-int
-m2(int a)
-{
- switch(a) {
- case 6:
- return 2;
- case 10:
- return 2;
- case 12:
- return 4;
- case 18:
- return 2;
- case 20:
- return 4;
- case 24:
- return 8;
- case 36:
- return 4;
- case 40:
- return 8;
- case 72:
- return 8;
- }
- diag(Z, "bad m2");
- return 0;
-}
-
-void
-shiftit(Type *t, Node *s, Node *d)
-{
- int32 c;
-
- c = (int32)s->vconst & 31;
- switch(c) {
- case 0:
- break;
- case 1:
- gopcode(OADD, t, d, d);
- break;
- default:
- gopcode(OASHL, t, s, d);
- }
-}
-
-static int
-mulgen1(uint32 v, Node *n)
-{
- int i, o;
- Mparam *p;
- Node nod, nods;
-
- for(i = 0; i < nelem(multab); i++) {
- p = &multab[i];
- if(p->value == v)
- goto found;
- }
-
- p = &multab[mulptr];
- if(++mulptr == nelem(multab))
- mulptr = 0;
-
- mulparam(v, p);
-
-found:
-// print("v=%.x a=%d n=%d s=%d g=%d o=%d \n", p->value, p->alg, p->neg, p->shift, p->arg, p->off);
- if(p->alg < 0)
- return 0;
-
- nods = *nodconst(p->shift);
-
- o = OADD;
- if(p->alg > 0) {
- regalloc(&nod, n, Z);
- if(p->off < 0)
- o = OSUB;
- }
-
- switch(p->alg) {
- case 0:
- switch(p->arg) {
- case 1:
- shiftit(n->type, &nods, n);
- break;
- case 15:
- case 25:
- case 27:
- case 45:
- case 81:
- genmuladd(n, n, m1(p->arg), n);
- /* fall thru */
- case 3:
- case 5:
- case 9:
- genmuladd(n, n, m0(p->arg), n);
- shiftit(n->type, &nods, n);
- break;
- default:
- goto bad;
- }
- if(p->neg == 1)
- gins(ANEGL, Z, n);
- break;
- case 1:
- switch(p->arg) {
- case 1:
- gmove(n, &nod);
- shiftit(n->type, &nods, &nod);
- break;
- case 3:
- case 5:
- case 9:
- genmuladd(&nod, n, m0(p->arg), n);
- shiftit(n->type, &nods, &nod);
- break;
- default:
- goto bad;
- }
- if(p->neg)
- gopcode(o, n->type, &nod, n);
- else {
- gopcode(o, n->type, n, &nod);
- gmove(&nod, n);
- }
- break;
- case 2:
- genmuladd(&nod, n, m0(p->off), n);
- shiftit(n->type, &nods, n);
- goto comop;
- case 3:
- genmuladd(&nod, n, m0(p->off), n);
- shiftit(n->type, &nods, n);
- genmuladd(n, &nod, m2(p->off), n);
- break;
- case 4:
- genmuladd(&nod, n, m0(p->off), nodconst(0));
- shiftit(n->type, &nods, n);
- goto comop;
- default:
- diag(Z, "bad mul alg");
- break;
- comop:
- if(p->neg) {
- gopcode(o, n->type, n, &nod);
- gmove(&nod, n);
- }
- else
- gopcode(o, n->type, &nod, n);
- }
-
- if(p->alg > 0)
- regfree(&nod);
-
- return 1;
-
-bad:
- diag(Z, "mulgen botch");
- return 1;
-}
-
-void
-mulgen(Type *t, Node *r, Node *n)
-{
- if(!mulgen1(r->vconst, n))
- gopcode(OMUL, t, r, n);
-}
diff --git a/src/cmd/6c/peep.c b/src/cmd/6c/peep.c
deleted file mode 100644
index a11067c84..000000000
--- a/src/cmd/6c/peep.c
+++ /dev/null
@@ -1,902 +0,0 @@
-// Inferno utils/6c/peep.c
-// http://code.google.com/p/inferno-os/source/browse/utils/6c/peep.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-
-static int
-needc(Prog *p)
-{
- while(p != P) {
- switch(p->as) {
- case AADCL:
- case AADCQ:
- case ASBBL:
- case ASBBQ:
- case ARCRL:
- case ARCRQ:
- return 1;
- case AADDL:
- case AADDQ:
- case ASUBL:
- case ASUBQ:
- case AJMP:
- case ARET:
- case ACALL:
- return 0;
- default:
- if(p->to.type == D_BRANCH)
- return 0;
- }
- p = p->link;
- }
- return 0;
-}
-
-static Reg*
-rnops(Reg *r)
-{
- Prog *p;
- Reg *r1;
-
- if(r != R)
- for(;;){
- p = r->prog;
- if(p->as != ANOP || p->from.type != D_NONE || p->to.type != D_NONE)
- break;
- r1 = uniqs(r);
- if(r1 == R)
- break;
- r = r1;
- }
- return r;
-}
-
-void
-peep(void)
-{
- Reg *r, *r1, *r2;
- Prog *p, *p1;
- int t;
-
- /*
- * complete R structure
- */
- t = 0;
- for(r=firstr; r!=R; r=r1) {
- r1 = r->link;
- if(r1 == R)
- break;
- p = r->prog->link;
- while(p != r1->prog)
- switch(p->as) {
- default:
- r2 = rega();
- r->link = r2;
- r2->link = r1;
-
- r2->prog = p;
- r2->p1 = r;
- r->s1 = r2;
- r2->s1 = r1;
- r1->p1 = r2;
-
- r = r2;
- t++;
-
- case ADATA:
- case AGLOBL:
- case ANAME:
- case ASIGNAME:
- p = p->link;
- }
- }
-
- pc = 0; /* speculating it won't kill */
-
-loop1:
-
- t = 0;
- for(r=firstr; r!=R; r=r->link) {
- p = r->prog;
- switch(p->as) {
- case AMOVL:
- case AMOVQ:
- case AMOVSS:
- case AMOVSD:
- if(regtyp(&p->to))
- if(regtyp(&p->from)) {
- if(copyprop(r)) {
- excise(r);
- t++;
- } else
- if(subprop(r) && copyprop(r)) {
- excise(r);
- t++;
- }
- }
- break;
-
- case AMOVBLZX:
- case AMOVWLZX:
- case AMOVBLSX:
- case AMOVWLSX:
- if(regtyp(&p->to)) {
- r1 = rnops(uniqs(r));
- if(r1 != R) {
- p1 = r1->prog;
- if(p->as == p1->as && p->to.type == p1->from.type){
- p1->as = AMOVL;
- t++;
- }
- }
- }
- break;
-
- case AMOVBQSX:
- case AMOVBQZX:
- case AMOVWQSX:
- case AMOVWQZX:
- case AMOVLQSX:
- case AMOVLQZX:
- if(regtyp(&p->to)) {
- r1 = rnops(uniqs(r));
- if(r1 != R) {
- p1 = r1->prog;
- if(p->as == p1->as && p->to.type == p1->from.type){
- p1->as = AMOVQ;
- t++;
- }
- }
- }
- break;
-
- case AADDL:
- case AADDQ:
- case AADDW:
- if(p->from.type != D_CONST || needc(p->link))
- break;
- if(p->from.offset == -1){
- if(p->as == AADDQ)
- p->as = ADECQ;
- else if(p->as == AADDL)
- p->as = ADECL;
- else
- p->as = ADECW;
- p->from = zprog.from;
- }
- else if(p->from.offset == 1){
- if(p->as == AADDQ)
- p->as = AINCQ;
- else if(p->as == AADDL)
- p->as = AINCL;
- else
- p->as = AINCW;
- p->from = zprog.from;
- }
- break;
-
- case ASUBL:
- case ASUBQ:
- case ASUBW:
- if(p->from.type != D_CONST || needc(p->link))
- break;
- if(p->from.offset == -1) {
- if(p->as == ASUBQ)
- p->as = AINCQ;
- else if(p->as == ASUBL)
- p->as = AINCL;
- else
- p->as = AINCW;
- p->from = zprog.from;
- }
- else if(p->from.offset == 1){
- if(p->as == ASUBQ)
- p->as = ADECQ;
- else if(p->as == ASUBL)
- p->as = ADECL;
- else
- p->as = ADECW;
- p->from = zprog.from;
- }
- break;
- }
- }
- if(t)
- goto loop1;
-}
-
-void
-excise(Reg *r)
-{
- Prog *p;
-
- p = r->prog;
- p->as = ANOP;
- p->from = zprog.from;
- p->to = zprog.to;
-}
-
-Reg*
-uniqp(Reg *r)
-{
- Reg *r1;
-
- r1 = r->p1;
- if(r1 == R) {
- r1 = r->p2;
- if(r1 == R || r1->p2link != R)
- return R;
- } else
- if(r->p2 != R)
- return R;
- return r1;
-}
-
-Reg*
-uniqs(Reg *r)
-{
- Reg *r1;
-
- r1 = r->s1;
- if(r1 == R) {
- r1 = r->s2;
- if(r1 == R)
- return R;
- } else
- if(r->s2 != R)
- return R;
- return r1;
-}
-
-int
-regtyp(Addr *a)
-{
- int t;
-
- t = a->type;
- if(t >= D_AX && t <= D_R15)
- return 1;
- if(t >= D_X0 && t <= D_X0+15)
- return 1;
- return 0;
-}
-
-/*
- * the idea is to substitute
- * one register for another
- * from one MOV to another
- * MOV a, R0
- * ADD b, R0 / no use of R1
- * MOV R0, R1
- * would be converted to
- * MOV a, R1
- * ADD b, R1
- * MOV R1, R0
- * hopefully, then the former or latter MOV
- * will be eliminated by copy propagation.
- */
-int
-subprop(Reg *r0)
-{
- Prog *p;
- Addr *v1, *v2;
- Reg *r;
- int t;
-
- p = r0->prog;
- v1 = &p->from;
- if(!regtyp(v1))
- return 0;
- v2 = &p->to;
- if(!regtyp(v2))
- return 0;
- for(r=uniqp(r0); r!=R; r=uniqp(r)) {
- if(uniqs(r) == R)
- break;
- p = r->prog;
- switch(p->as) {
- case ACALL:
- return 0;
-
- case AIMULL:
- case AIMULQ:
- case AIMULW:
- if(p->to.type != D_NONE)
- break;
- goto giveup;
-
- case AROLB:
- case AROLL:
- case AROLQ:
- case AROLW:
- case ARORB:
- case ARORL:
- case ARORQ:
- case ARORW:
- case ASALB:
- case ASALL:
- case ASALQ:
- case ASALW:
- case ASARB:
- case ASARL:
- case ASARQ:
- case ASARW:
- case ASHLB:
- case ASHLL:
- case ASHLQ:
- case ASHLW:
- case ASHRB:
- case ASHRL:
- case ASHRQ:
- case ASHRW:
- if(p->from.type == D_CONST)
- break;
- goto giveup;
-
- case ADIVB:
- case ADIVL:
- case ADIVQ:
- case ADIVW:
- case AIDIVB:
- case AIDIVL:
- case AIDIVQ:
- case AIDIVW:
- case AIMULB:
- case AMULB:
- case AMULL:
- case AMULQ:
- case AMULW:
-
- case AREP:
- case AREPN:
-
- case ACWD:
- case ACDQ:
- case ACQO:
-
- case ASTOSB:
- case ASTOSL:
- case ASTOSQ:
- case AMOVSB:
- case AMOVSL:
- case AMOVSQ:
- case AMOVQL:
- giveup:
- return 0;
-
- case AMOVL:
- case AMOVQ:
- if(p->to.type == v1->type)
- goto gotit;
- break;
- }
- if(copyau(&p->from, v2) ||
- copyau(&p->to, v2))
- break;
- if(copysub(&p->from, v1, v2, 0) ||
- copysub(&p->to, v1, v2, 0))
- break;
- }
- return 0;
-
-gotit:
- copysub(&p->to, v1, v2, 1);
- if(debug['P']) {
- print("gotit: %D->%D\n%P", v1, v2, r->prog);
- if(p->from.type == v2->type)
- print(" excise");
- print("\n");
- }
- for(r=uniqs(r); r!=r0; r=uniqs(r)) {
- p = r->prog;
- copysub(&p->from, v1, v2, 1);
- copysub(&p->to, v1, v2, 1);
- if(debug['P'])
- print("%P\n", r->prog);
- }
- t = v1->type;
- v1->type = v2->type;
- v2->type = t;
- if(debug['P'])
- print("%P last\n", r->prog);
- return 1;
-}
-
-/*
- * The idea is to remove redundant copies.
- * v1->v2 F=0
- * (use v2 s/v2/v1/)*
- * set v1 F=1
- * use v2 return fail
- * -----------------
- * v1->v2 F=0
- * (use v2 s/v2/v1/)*
- * set v1 F=1
- * set v2 return success
- */
-int
-copyprop(Reg *r0)
-{
- Prog *p;
- Addr *v1, *v2;
- Reg *r;
-
- p = r0->prog;
- v1 = &p->from;
- v2 = &p->to;
- if(copyas(v1, v2))
- return 1;
- for(r=firstr; r!=R; r=r->link)
- r->active = 0;
- return copy1(v1, v2, r0->s1, 0);
-}
-
-int
-copy1(Addr *v1, Addr *v2, Reg *r, int f)
-{
- int t;
- Prog *p;
-
- if(r->active) {
- if(debug['P'])
- print("act set; return 1\n");
- return 1;
- }
- r->active = 1;
- if(debug['P'])
- print("copy %D->%D f=%d\n", v1, v2, f);
- for(; r != R; r = r->s1) {
- p = r->prog;
- if(debug['P'])
- print("%P", p);
- if(!f && uniqp(r) == R) {
- f = 1;
- if(debug['P'])
- print("; merge; f=%d", f);
- }
- t = copyu(p, v2, A);
- switch(t) {
- case 2: /* rar, can't split */
- if(debug['P'])
- print("; %D rar; return 0\n", v2);
- return 0;
-
- case 3: /* set */
- if(debug['P'])
- print("; %D set; return 1\n", v2);
- return 1;
-
- case 1: /* used, substitute */
- case 4: /* use and set */
- if(f) {
- if(!debug['P'])
- return 0;
- if(t == 4)
- print("; %D used+set and f=%d; return 0\n", v2, f);
- else
- print("; %D used and f=%d; return 0\n", v2, f);
- return 0;
- }
- if(copyu(p, v2, v1)) {
- if(debug['P'])
- print("; sub fail; return 0\n");
- return 0;
- }
- if(debug['P'])
- print("; sub %D/%D", v2, v1);
- if(t == 4) {
- if(debug['P'])
- print("; %D used+set; return 1\n", v2);
- return 1;
- }
- break;
- }
- if(!f) {
- t = copyu(p, v1, A);
- if(!f && (t == 2 || t == 3 || t == 4)) {
- f = 1;
- if(debug['P'])
- print("; %D set and !f; f=%d", v1, f);
- }
- }
- if(debug['P'])
- print("\n");
- if(r->s2)
- if(!copy1(v1, v2, r->s2, f))
- return 0;
- }
- return 1;
-}
-
-/*
- * return
- * 1 if v only used (and substitute),
- * 2 if read-alter-rewrite
- * 3 if set
- * 4 if set and used
- * 0 otherwise (not touched)
- */
-int
-copyu(Prog *p, Addr *v, Addr *s)
-{
-
- switch(p->as) {
-
- default:
- if(debug['P'])
- print("unknown op %A\n", p->as);
- /* SBBL; ADCL; FLD1; SAHF */
- return 2;
-
-
- case ANEGB:
- case ANEGW:
- case ANEGL:
- case ANEGQ:
- case ANOTB:
- case ANOTW:
- case ANOTL:
- case ANOTQ:
- if(copyas(&p->to, v))
- return 2;
- break;
-
- case ALEAL: /* lhs addr, rhs store */
- case ALEAQ:
- if(copyas(&p->from, v))
- return 2;
-
-
- case ANOP: /* rhs store */
- case AMOVL:
- case AMOVQ:
- case AMOVBLSX:
- case AMOVBLZX:
- case AMOVBQSX:
- case AMOVBQZX:
- case AMOVLQSX:
- case AMOVLQZX:
- case AMOVWLSX:
- case AMOVWLZX:
- case AMOVWQSX:
- case AMOVWQZX:
- case AMOVQL:
-
- case AMOVSS:
- case AMOVSD:
- case ACVTSD2SL:
- case ACVTSD2SQ:
- case ACVTSD2SS:
- case ACVTSL2SD:
- case ACVTSL2SS:
- case ACVTSQ2SD:
- case ACVTSQ2SS:
- case ACVTSS2SD:
- case ACVTSS2SL:
- case ACVTSS2SQ:
- case ACVTTSD2SL:
- case ACVTTSD2SQ:
- case ACVTTSS2SL:
- case ACVTTSS2SQ:
- if(copyas(&p->to, v)) {
- if(s != A)
- return copysub(&p->from, v, s, 1);
- if(copyau(&p->from, v))
- return 4;
- return 3;
- }
- goto caseread;
-
- case AROLB:
- case AROLL:
- case AROLQ:
- case AROLW:
- case ARORB:
- case ARORL:
- case ARORQ:
- case ARORW:
- case ASALB:
- case ASALL:
- case ASALQ:
- case ASALW:
- case ASARB:
- case ASARL:
- case ASARQ:
- case ASARW:
- case ASHLB:
- case ASHLL:
- case ASHLQ:
- case ASHLW:
- case ASHRB:
- case ASHRL:
- case ASHRQ:
- case ASHRW:
- if(copyas(&p->to, v))
- return 2;
- if(copyas(&p->from, v))
- if(p->from.type == D_CX)
- return 2;
- goto caseread;
-
- case AADDB: /* rhs rar */
- case AADDL:
- case AADDQ:
- case AADDW:
- case AANDB:
- case AANDL:
- case AANDQ:
- case AANDW:
- case ADECL:
- case ADECQ:
- case ADECW:
- case AINCL:
- case AINCQ:
- case AINCW:
- case ASUBB:
- case ASUBL:
- case ASUBQ:
- case ASUBW:
- case AORB:
- case AORL:
- case AORQ:
- case AORW:
- case AXORB:
- case AXORL:
- case AXORQ:
- case AXORW:
- case AMOVB:
- case AMOVW:
-
- case AADDSD:
- case AADDSS:
- case ACMPSD:
- case ACMPSS:
- case ADIVSD:
- case ADIVSS:
- case AMAXSD:
- case AMAXSS:
- case AMINSD:
- case AMINSS:
- case AMULSD:
- case AMULSS:
- case ARCPSS:
- case ARSQRTSS:
- case ASQRTSD:
- case ASQRTSS:
- case ASUBSD:
- case ASUBSS:
- case AXORPD:
- if(copyas(&p->to, v))
- return 2;
- goto caseread;
-
- case ACMPL: /* read only */
- case ACMPW:
- case ACMPB:
- case ACMPQ:
-
- case APREFETCHT0:
- case APREFETCHT1:
- case APREFETCHT2:
- case APREFETCHNTA:
-
- case ACOMISD:
- case ACOMISS:
- case AUCOMISD:
- case AUCOMISS:
- caseread:
- if(s != A) {
- if(copysub(&p->from, v, s, 1))
- return 1;
- return copysub(&p->to, v, s, 1);
- }
- if(copyau(&p->from, v))
- return 1;
- if(copyau(&p->to, v))
- return 1;
- break;
-
- case AJGE: /* no reference */
- case AJNE:
- case AJLE:
- case AJEQ:
- case AJHI:
- case AJLS:
- case AJMI:
- case AJPL:
- case AJGT:
- case AJLT:
- case AJCC:
- case AJCS:
-
- case AADJSP:
- case AWAIT:
- case ACLD:
- break;
-
- case AIMULL:
- case AIMULQ:
- case AIMULW:
- if(p->to.type != D_NONE) {
- if(copyas(&p->to, v))
- return 2;
- goto caseread;
- }
-
- case ADIVB:
- case ADIVL:
- case ADIVQ:
- case ADIVW:
- case AIDIVB:
- case AIDIVL:
- case AIDIVQ:
- case AIDIVW:
- case AIMULB:
- case AMULB:
- case AMULL:
- case AMULQ:
- case AMULW:
-
- case ACWD:
- case ACDQ:
- case ACQO:
- if(v->type == D_AX || v->type == D_DX)
- return 2;
- goto caseread;
-
- case AREP:
- case AREPN:
- if(v->type == D_CX)
- return 2;
- goto caseread;
-
- case AMOVSB:
- case AMOVSL:
- case AMOVSQ:
- if(v->type == D_DI || v->type == D_SI)
- return 2;
- goto caseread;
-
- case ASTOSB:
- case ASTOSL:
- case ASTOSQ:
- if(v->type == D_AX || v->type == D_DI)
- return 2;
- goto caseread;
-
- case AJMP: /* funny */
- if(s != A) {
- if(copysub(&p->to, v, s, 1))
- return 1;
- return 0;
- }
- if(copyau(&p->to, v))
- return 1;
- return 0;
-
- case ARET: /* funny */
- if(v->type == REGRET || v->type == FREGRET)
- return 2;
- if(s != A)
- return 1;
- return 3;
-
- case ACALL: /* funny */
- if(REGARG >= 0 && v->type == (uchar)REGARG)
- return 2;
-
- if(s != A) {
- if(copysub(&p->to, v, s, 1))
- return 1;
- return 0;
- }
- if(copyau(&p->to, v))
- return 4;
- return 3;
-
- case ATEXT: /* funny */
- if(REGARG >= 0 && v->type == (uchar)REGARG)
- return 3;
- return 0;
- }
- return 0;
-}
-
-/*
- * direct reference,
- * could be set/use depending on
- * semantics
- */
-int
-copyas(Addr *a, Addr *v)
-{
- if(a->type != v->type)
- return 0;
- if(regtyp(v))
- return 1;
- if(v->type == D_AUTO || v->type == D_PARAM)
- if(v->offset == a->offset)
- return 1;
- return 0;
-}
-
-/*
- * either direct or indirect
- */
-int
-copyau(Addr *a, Addr *v)
-{
-
- if(copyas(a, v))
- return 1;
- if(regtyp(v)) {
- if(a->type-D_INDIR == v->type)
- return 1;
- if(a->index == v->type)
- return 1;
- }
- return 0;
-}
-
-/*
- * substitute s for v in a
- * return failure to substitute
- */
-int
-copysub(Addr *a, Addr *v, Addr *s, int f)
-{
- int t;
-
- if(copyas(a, v)) {
- t = s->type;
- if(t >= D_AX && t <= D_R15 || t >= D_X0 && t <= D_X0+15) {
- if(f)
- a->type = t;
- }
- return 0;
- }
- if(regtyp(v)) {
- t = v->type;
- if(a->type == t+D_INDIR) {
- if((s->type == D_BP || s->type == D_R13) && a->index != D_NONE)
- return 1; /* can't use BP-base with index */
- if(f)
- a->type = s->type+D_INDIR;
-// return 0;
- }
- if(a->index == t) {
- if(f)
- a->index = s->type;
- return 0;
- }
- return 0;
- }
- return 0;
-}
diff --git a/src/cmd/6c/reg.c b/src/cmd/6c/reg.c
deleted file mode 100644
index 6f8d3ce14..000000000
--- a/src/cmd/6c/reg.c
+++ /dev/null
@@ -1,1523 +0,0 @@
-// Inferno utils/6c/reg.c
-// http://code.google.com/p/inferno-os/source/browse/utils/6c/reg.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-
-static void fixjmp(Reg*);
-
-Reg*
-rega(void)
-{
- Reg *r;
-
- r = freer;
- if(r == R) {
- r = alloc(sizeof(*r));
- } else
- freer = r->link;
-
- *r = zreg;
- return r;
-}
-
-int
-rcmp(const void *a1, const void *a2)
-{
- Rgn *p1, *p2;
- int c1, c2;
-
- p1 = (Rgn*)a1;
- p2 = (Rgn*)a2;
- c1 = p2->cost;
- c2 = p1->cost;
- if(c1 -= c2)
- return c1;
- return p2->varno - p1->varno;
-}
-
-void
-regopt(Prog *p)
-{
- Reg *r, *r1, *r2;
- Prog *p1;
- int i, z;
- int32 initpc, val, npc;
- uint32 vreg;
- Bits bit;
- struct
- {
- int32 m;
- int32 c;
- Reg* p;
- } log5[6], *lp;
-
- firstr = R;
- lastr = R;
- nvar = 0;
- regbits = RtoB(D_SP) | RtoB(D_AX) | RtoB(D_X0);
- for(z=0; z<BITS; z++) {
- externs.b[z] = 0;
- params.b[z] = 0;
- consts.b[z] = 0;
- addrs.b[z] = 0;
- }
-
- /*
- * pass 1
- * build aux data structure
- * allocate pcs
- * find use and set of variables
- */
- val = 5L * 5L * 5L * 5L * 5L;
- lp = log5;
- for(i=0; i<5; i++) {
- lp->m = val;
- lp->c = 0;
- lp->p = R;
- val /= 5L;
- lp++;
- }
- val = 0;
- for(; p != P; p = p->link) {
- switch(p->as) {
- case ADATA:
- case AGLOBL:
- case ANAME:
- case ASIGNAME:
- case AFUNCDATA:
- continue;
- }
- r = rega();
- if(firstr == R) {
- firstr = r;
- lastr = r;
- } else {
- lastr->link = r;
- r->p1 = lastr;
- lastr->s1 = r;
- lastr = r;
- }
- r->prog = p;
- r->pc = val;
- val++;
-
- lp = log5;
- for(i=0; i<5; i++) {
- lp->c--;
- if(lp->c <= 0) {
- lp->c = lp->m;
- if(lp->p != R)
- lp->p->log5 = r;
- lp->p = r;
- (lp+1)->c = 0;
- break;
- }
- lp++;
- }
-
- r1 = r->p1;
- if(r1 != R)
- switch(r1->prog->as) {
- case ARET:
- case AJMP:
- case AIRETL:
- case AIRETQ:
- r->p1 = R;
- r1->s1 = R;
- }
-
- bit = mkvar(r, &p->from);
- if(bany(&bit))
- switch(p->as) {
- /*
- * funny
- */
- case ALEAL:
- case ALEAQ:
- for(z=0; z<BITS; z++)
- addrs.b[z] |= bit.b[z];
- break;
-
- /*
- * left side read
- */
- default:
- for(z=0; z<BITS; z++)
- r->use1.b[z] |= bit.b[z];
- break;
- }
-
- bit = mkvar(r, &p->to);
- if(bany(&bit))
- switch(p->as) {
- default:
- diag(Z, "reg: unknown op: %A", p->as);
- break;
-
- /*
- * right side read
- */
- case ACMPB:
- case ACMPL:
- case ACMPQ:
- case ACMPW:
- case APREFETCHT0:
- case APREFETCHT1:
- case APREFETCHT2:
- case APREFETCHNTA:
- case ACOMISS:
- case ACOMISD:
- case AUCOMISS:
- case AUCOMISD:
- for(z=0; z<BITS; z++)
- r->use2.b[z] |= bit.b[z];
- break;
-
- /*
- * right side write
- */
- case ANOP:
- case AMOVL:
- case AMOVQ:
- case AMOVB:
- case AMOVW:
- case AMOVBLSX:
- case AMOVBLZX:
- case AMOVBQSX:
- case AMOVBQZX:
- case AMOVLQSX:
- case AMOVLQZX:
- case AMOVWLSX:
- case AMOVWLZX:
- case AMOVWQSX:
- case AMOVWQZX:
- case AMOVQL:
-
- case AMOVSS:
- case AMOVSD:
- case ACVTSD2SL:
- case ACVTSD2SQ:
- case ACVTSD2SS:
- case ACVTSL2SD:
- case ACVTSL2SS:
- case ACVTSQ2SD:
- case ACVTSQ2SS:
- case ACVTSS2SD:
- case ACVTSS2SL:
- case ACVTSS2SQ:
- case ACVTTSD2SL:
- case ACVTTSD2SQ:
- case ACVTTSS2SL:
- case ACVTTSS2SQ:
- for(z=0; z<BITS; z++)
- r->set.b[z] |= bit.b[z];
- break;
-
- /*
- * right side read+write
- */
- case AADDB:
- case AADDL:
- case AADDQ:
- case AADDW:
- case AANDB:
- case AANDL:
- case AANDQ:
- case AANDW:
- case ASUBB:
- case ASUBL:
- case ASUBQ:
- case ASUBW:
- case AORB:
- case AORL:
- case AORQ:
- case AORW:
- case AXORB:
- case AXORL:
- case AXORQ:
- case AXORW:
- case ASALB:
- case ASALL:
- case ASALQ:
- case ASALW:
- case ASARB:
- case ASARL:
- case ASARQ:
- case ASARW:
- case AROLB:
- case AROLL:
- case AROLQ:
- case AROLW:
- case ARORB:
- case ARORL:
- case ARORQ:
- case ARORW:
- case ASHLB:
- case ASHLL:
- case ASHLQ:
- case ASHLW:
- case ASHRB:
- case ASHRL:
- case ASHRQ:
- case ASHRW:
- case AIMULL:
- case AIMULQ:
- case AIMULW:
- case ANEGL:
- case ANEGQ:
- case ANOTL:
- case ANOTQ:
- case AADCL:
- case AADCQ:
- case ASBBL:
- case ASBBQ:
-
- case AADDSD:
- case AADDSS:
- case ACMPSD:
- case ACMPSS:
- case ADIVSD:
- case ADIVSS:
- case AMAXSD:
- case AMAXSS:
- case AMINSD:
- case AMINSS:
- case AMULSD:
- case AMULSS:
- case ARCPSS:
- case ARSQRTSS:
- case ASQRTSD:
- case ASQRTSS:
- case ASUBSD:
- case ASUBSS:
- case AXORPD:
- for(z=0; z<BITS; z++) {
- r->set.b[z] |= bit.b[z];
- r->use2.b[z] |= bit.b[z];
- }
- break;
-
- /*
- * funny
- */
- case ACALL:
- for(z=0; z<BITS; z++)
- addrs.b[z] |= bit.b[z];
- break;
- }
-
- switch(p->as) {
- case AIMULL:
- case AIMULQ:
- case AIMULW:
- if(p->to.type != D_NONE)
- break;
-
- case AIDIVB:
- case AIDIVL:
- case AIDIVQ:
- case AIDIVW:
- case AIMULB:
- case ADIVB:
- case ADIVL:
- case ADIVQ:
- case ADIVW:
- case AMULB:
- case AMULL:
- case AMULQ:
- case AMULW:
-
- case ACWD:
- case ACDQ:
- case ACQO:
- r->regu |= RtoB(D_AX) | RtoB(D_DX);
- break;
-
- case AREP:
- case AREPN:
- case ALOOP:
- case ALOOPEQ:
- case ALOOPNE:
- r->regu |= RtoB(D_CX);
- break;
-
- case AMOVSB:
- case AMOVSL:
- case AMOVSQ:
- case AMOVSW:
- case ACMPSB:
- case ACMPSL:
- case ACMPSQ:
- case ACMPSW:
- r->regu |= RtoB(D_SI) | RtoB(D_DI);
- break;
-
- case ASTOSB:
- case ASTOSL:
- case ASTOSQ:
- case ASTOSW:
- case ASCASB:
- case ASCASL:
- case ASCASQ:
- case ASCASW:
- r->regu |= RtoB(D_AX) | RtoB(D_DI);
- break;
-
- case AINSB:
- case AINSL:
- case AINSW:
- case AOUTSB:
- case AOUTSL:
- case AOUTSW:
- r->regu |= RtoB(D_DI) | RtoB(D_DX);
- break;
- }
- }
- if(firstr == R)
- return;
- initpc = pc - val;
- npc = val;
-
- /*
- * pass 2
- * turn branch references to pointers
- * build back pointers
- */
- for(r = firstr; r != R; r = r->link) {
- p = r->prog;
- if(p->to.type == D_BRANCH) {
- val = p->to.offset - initpc;
- r1 = firstr;
- while(r1 != R) {
- r2 = r1->log5;
- if(r2 != R && val >= r2->pc) {
- r1 = r2;
- continue;
- }
- if(r1->pc == val)
- break;
- r1 = r1->link;
- }
- if(r1 == R) {
- nearln = p->lineno;
- diag(Z, "ref not found\n%P", p);
- continue;
- }
- if(r1 == r) {
- nearln = p->lineno;
- diag(Z, "ref to self\n%P", p);
- continue;
- }
- r->s2 = r1;
- r->p2link = r1->p2;
- r1->p2 = r;
- }
- }
- if(debug['R']) {
- p = firstr->prog;
- print("\n%L %D\n", p->lineno, &p->from);
- }
-
- /*
- * pass 2.1
- * fix jumps
- */
- fixjmp(firstr);
-
- /*
- * pass 2.5
- * find looping structure
- */
- for(r = firstr; r != R; r = r->link)
- r->active = 0;
- change = 0;
- loopit(firstr, npc);
- if(debug['R'] && debug['v']) {
- print("\nlooping structure:\n");
- for(r = firstr; r != R; r = r->link) {
- print("%d:%P", r->loop, r->prog);
- for(z=0; z<BITS; z++)
- bit.b[z] = r->use1.b[z] |
- r->use2.b[z] |
- r->set.b[z];
- if(bany(&bit)) {
- print("\t");
- if(bany(&r->use1))
- print(" u1=%B", r->use1);
- if(bany(&r->use2))
- print(" u2=%B", r->use2);
- if(bany(&r->set))
- print(" st=%B", r->set);
- }
- print("\n");
- }
- }
-
- /*
- * pass 3
- * iterate propagating usage
- * back until flow graph is complete
- */
-loop1:
- change = 0;
- for(r = firstr; r != R; r = r->link)
- r->active = 0;
- for(r = firstr; r != R; r = r->link)
- if(r->prog->as == ARET)
- prop(r, zbits, zbits);
-loop11:
- /* pick up unreachable code */
- i = 0;
- for(r = firstr; r != R; r = r1) {
- r1 = r->link;
- if(r1 && r1->active && !r->active) {
- prop(r, zbits, zbits);
- i = 1;
- }
- }
- if(i)
- goto loop11;
- if(change)
- goto loop1;
-
-
- /*
- * pass 4
- * iterate propagating register/variable synchrony
- * forward until graph is complete
- */
-loop2:
- change = 0;
- for(r = firstr; r != R; r = r->link)
- r->active = 0;
- synch(firstr, zbits);
- if(change)
- goto loop2;
-
-
- /*
- * pass 5
- * isolate regions
- * calculate costs (paint1)
- */
- r = firstr;
- if(r) {
- for(z=0; z<BITS; z++)
- bit.b[z] = (r->refahead.b[z] | r->calahead.b[z]) &
- ~(externs.b[z] | params.b[z] | addrs.b[z] | consts.b[z]);
- if(bany(&bit)) {
- nearln = r->prog->lineno;
- warn(Z, "used and not set: %B", bit);
- if(debug['R'] && !debug['w'])
- print("used and not set: %B\n", bit);
- }
- }
- if(debug['R'] && debug['v'])
- print("\nprop structure:\n");
- for(r = firstr; r != R; r = r->link)
- r->act = zbits;
- rgp = region;
- nregion = 0;
- for(r = firstr; r != R; r = r->link) {
- if(debug['R'] && debug['v']) {
- print("%P\t", r->prog);
- if(bany(&r->set))
- print("s:%B ", r->set);
- if(bany(&r->refahead))
- print("ra:%B ", r->refahead);
- if(bany(&r->calahead))
- print("ca:%B ", r->calahead);
- print("\n");
- }
- for(z=0; z<BITS; z++)
- bit.b[z] = r->set.b[z] &
- ~(r->refahead.b[z] | r->calahead.b[z] | addrs.b[z]);
- if(bany(&bit)) {
- nearln = r->prog->lineno;
- warn(Z, "set and not used: %B", bit);
- if(debug['R'])
- print("set and not used: %B\n", bit);
- excise(r);
- }
- for(z=0; z<BITS; z++)
- bit.b[z] = LOAD(r) & ~(r->act.b[z] | addrs.b[z]);
- while(bany(&bit)) {
- i = bnum(bit);
- rgp->enter = r;
- rgp->varno = i;
- change = 0;
- if(debug['R'] && debug['v'])
- print("\n");
- paint1(r, i);
- bit.b[i/32] &= ~(1L<<(i%32));
- if(change <= 0) {
- if(debug['R'])
- print("%L$%d: %B\n",
- r->prog->lineno, change, blsh(i));
- continue;
- }
- rgp->cost = change;
- nregion++;
- if(nregion >= NRGN)
- fatal(Z, "too many regions");
- rgp++;
- }
- }
- qsort(region, nregion, sizeof(region[0]), rcmp);
-
- /*
- * pass 6
- * determine used registers (paint2)
- * replace code (paint3)
- */
- rgp = region;
- for(i=0; i<nregion; i++) {
- bit = blsh(rgp->varno);
- vreg = paint2(rgp->enter, rgp->varno);
- vreg = allreg(vreg, rgp);
- if(debug['R']) {
- print("%L$%d %R: %B\n",
- rgp->enter->prog->lineno,
- rgp->cost,
- rgp->regno,
- bit);
- }
- if(rgp->regno != 0)
- paint3(rgp->enter, rgp->varno, vreg, rgp->regno);
- rgp++;
- }
- /*
- * pass 7
- * peep-hole on basic block
- */
- if(!debug['R'] || debug['P'])
- peep();
-
- /*
- * pass 8
- * recalculate pc
- */
- val = initpc;
- for(r = firstr; r != R; r = r1) {
- r->pc = val;
- p = r->prog;
- p1 = P;
- r1 = r->link;
- if(r1 != R)
- p1 = r1->prog;
- for(; p != p1; p = p->link) {
- switch(p->as) {
- default:
- val++;
- break;
-
- case ANOP:
- case ADATA:
- case AGLOBL:
- case ANAME:
- case ASIGNAME:
- case AFUNCDATA:
- break;
- }
- }
- }
- pc = val;
-
- /*
- * fix up branches
- */
- if(debug['R'])
- if(bany(&addrs))
- print("addrs: %B\n", addrs);
-
- r1 = 0; /* set */
- for(r = firstr; r != R; r = r->link) {
- p = r->prog;
- if(p->to.type == D_BRANCH) {
- p->to.offset = r->s2->pc;
- p->to.u.branch = r->s2->prog;
- }
- r1 = r;
- }
-
- /*
- * last pass
- * eliminate nops
- * free aux structures
- */
- for(p = firstr->prog; p != P; p = p->link){
- while(p->link && p->link->as == ANOP)
- p->link = p->link->link;
- }
- if(r1 != R) {
- r1->link = freer;
- freer = firstr;
- }
-}
-
-/*
- * add mov b,rn
- * just after r
- */
-void
-addmove(Reg *r, int bn, int rn, int f)
-{
- Prog *p, *p1;
- Addr *a;
- Var *v;
-
- p1 = alloc(sizeof(*p1));
- *p1 = zprog;
- p = r->prog;
-
- p1->link = p->link;
- p->link = p1;
- p1->lineno = p->lineno;
-
- v = var + bn;
-
- a = &p1->to;
- a->sym = v->sym;
- a->offset = v->offset;
- a->etype = v->etype;
- a->type = v->name;
-
- p1->as = AMOVL;
- if(v->etype == TCHAR || v->etype == TUCHAR)
- p1->as = AMOVB;
- if(v->etype == TSHORT || v->etype == TUSHORT)
- p1->as = AMOVW;
- if(v->etype == TVLONG || v->etype == TUVLONG || (v->etype == TIND && ewidth[TIND] == 8))
- p1->as = AMOVQ;
- if(v->etype == TFLOAT)
- p1->as = AMOVSS;
- if(v->etype == TDOUBLE)
- p1->as = AMOVSD;
-
- p1->from.type = rn;
- if(!f) {
- p1->from = *a;
- *a = zprog.from;
- a->type = rn;
- if(v->etype == TUCHAR)
- p1->as = AMOVB;
- if(v->etype == TUSHORT)
- p1->as = AMOVW;
- }
- if(debug['R'])
- print("%P\t.a%P\n", p, p1);
-}
-
-uint32
-doregbits(int r)
-{
- uint32 b;
-
- b = 0;
- if(r >= D_INDIR)
- r -= D_INDIR;
- if(r >= D_AX && r <= D_R15)
- b |= RtoB(r);
- else
- if(r >= D_AL && r <= D_R15B)
- b |= RtoB(r-D_AL+D_AX);
- else
- if(r >= D_AH && r <= D_BH)
- b |= RtoB(r-D_AH+D_AX);
- else
- if(r >= D_X0 && r <= D_X0+15)
- b |= FtoB(r);
- return b;
-}
-
-Bits
-mkvar(Reg *r, Addr *a)
-{
- Var *v;
- int i, t, n, et, z;
- int32 o;
- Bits bit;
- LSym *s;
-
- /*
- * mark registers used
- */
- t = a->type;
- r->regu |= doregbits(t);
- r->regu |= doregbits(a->index);
-
- switch(t) {
- default:
- goto none;
- case D_ADDR:
- a->type = a->index;
- bit = mkvar(r, a);
- for(z=0; z<BITS; z++)
- addrs.b[z] |= bit.b[z];
- a->type = t;
- goto none;
- case D_EXTERN:
- case D_STATIC:
- case D_PARAM:
- case D_AUTO:
- n = t;
- break;
- }
- s = a->sym;
- if(s == nil)
- goto none;
- if(s->name[0] == '.')
- goto none;
- et = a->etype;
- o = a->offset;
- v = var;
- for(i=0; i<nvar; i++) {
- if(s == v->sym)
- if(n == v->name)
- if(o == v->offset)
- goto out;
- v++;
- }
- if(nvar >= NVAR)
- fatal(Z, "variable not optimized: %s", s->name);
- i = nvar;
- nvar++;
- v = &var[i];
- v->sym = s;
- v->offset = o;
- v->name = n;
- v->etype = et;
- if(debug['R'])
- print("bit=%2d et=%2d %D\n", i, et, a);
-
-out:
- bit = blsh(i);
- if(n == D_EXTERN || n == D_STATIC)
- for(z=0; z<BITS; z++)
- externs.b[z] |= bit.b[z];
- if(n == D_PARAM)
- for(z=0; z<BITS; z++)
- params.b[z] |= bit.b[z];
- if(v->etype != et || !(typechlpfd[et] || typev[et])) /* funny punning */
- for(z=0; z<BITS; z++)
- addrs.b[z] |= bit.b[z];
- return bit;
-
-none:
- return zbits;
-}
-
-void
-prop(Reg *r, Bits ref, Bits cal)
-{
- Reg *r1, *r2;
- int z;
-
- for(r1 = r; r1 != R; r1 = r1->p1) {
- for(z=0; z<BITS; z++) {
- ref.b[z] |= r1->refahead.b[z];
- if(ref.b[z] != r1->refahead.b[z]) {
- r1->refahead.b[z] = ref.b[z];
- change++;
- }
- cal.b[z] |= r1->calahead.b[z];
- if(cal.b[z] != r1->calahead.b[z]) {
- r1->calahead.b[z] = cal.b[z];
- change++;
- }
- }
- switch(r1->prog->as) {
- case ACALL:
- for(z=0; z<BITS; z++) {
- cal.b[z] |= ref.b[z] | externs.b[z];
- ref.b[z] = 0;
- }
- break;
-
- case ATEXT:
- for(z=0; z<BITS; z++) {
- cal.b[z] = 0;
- ref.b[z] = 0;
- }
- break;
-
- case ARET:
- for(z=0; z<BITS; z++) {
- cal.b[z] = externs.b[z];
- ref.b[z] = 0;
- }
- }
- for(z=0; z<BITS; z++) {
- ref.b[z] = (ref.b[z] & ~r1->set.b[z]) |
- r1->use1.b[z] | r1->use2.b[z];
- cal.b[z] &= ~(r1->set.b[z] | r1->use1.b[z] | r1->use2.b[z]);
- r1->refbehind.b[z] = ref.b[z];
- r1->calbehind.b[z] = cal.b[z];
- }
- if(r1->active)
- break;
- r1->active = 1;
- }
- for(; r != r1; r = r->p1)
- for(r2 = r->p2; r2 != R; r2 = r2->p2link)
- prop(r2, r->refbehind, r->calbehind);
-}
-
-/*
- * find looping structure
- *
- * 1) find reverse postordering
- * 2) find approximate dominators,
- * the actual dominators if the flow graph is reducible
- * otherwise, dominators plus some other non-dominators.
- * See Matthew S. Hecht and Jeffrey D. Ullman,
- * "Analysis of a Simple Algorithm for Global Data Flow Problems",
- * Conf. Record of ACM Symp. on Principles of Prog. Langs, Boston, Massachusetts,
- * Oct. 1-3, 1973, pp. 207-217.
- * 3) find all nodes with a predecessor dominated by the current node.
- * such a node is a loop head.
- * recursively, all preds with a greater rpo number are in the loop
- */
-int32
-postorder(Reg *r, Reg **rpo2r, int32 n)
-{
- Reg *r1;
-
- r->rpo = 1;
- r1 = r->s1;
- if(r1 && !r1->rpo)
- n = postorder(r1, rpo2r, n);
- r1 = r->s2;
- if(r1 && !r1->rpo)
- n = postorder(r1, rpo2r, n);
- rpo2r[n] = r;
- n++;
- return n;
-}
-
-int32
-rpolca(int32 *idom, int32 rpo1, int32 rpo2)
-{
- int32 t;
-
- if(rpo1 == -1)
- return rpo2;
- while(rpo1 != rpo2){
- if(rpo1 > rpo2){
- t = rpo2;
- rpo2 = rpo1;
- rpo1 = t;
- }
- while(rpo1 < rpo2){
- t = idom[rpo2];
- if(t >= rpo2)
- fatal(Z, "bad idom");
- rpo2 = t;
- }
- }
- return rpo1;
-}
-
-int
-doms(int32 *idom, int32 r, int32 s)
-{
- while(s > r)
- s = idom[s];
- return s == r;
-}
-
-int
-loophead(int32 *idom, Reg *r)
-{
- int32 src;
-
- src = r->rpo;
- if(r->p1 != R && doms(idom, src, r->p1->rpo))
- return 1;
- for(r = r->p2; r != R; r = r->p2link)
- if(doms(idom, src, r->rpo))
- return 1;
- return 0;
-}
-
-void
-loopmark(Reg **rpo2r, int32 head, Reg *r)
-{
- if(r->rpo < head || r->active == head)
- return;
- r->active = head;
- r->loop += LOOP;
- if(r->p1 != R)
- loopmark(rpo2r, head, r->p1);
- for(r = r->p2; r != R; r = r->p2link)
- loopmark(rpo2r, head, r);
-}
-
-void
-loopit(Reg *r, int32 nr)
-{
- Reg *r1;
- int32 i, d, me;
-
- if(nr > maxnr) {
- rpo2r = alloc(nr * sizeof(Reg*));
- idom = alloc(nr * sizeof(int32));
- maxnr = nr;
- }
-
- d = postorder(r, rpo2r, 0);
- if(d > nr)
- fatal(Z, "too many reg nodes");
- nr = d;
- for(i = 0; i < nr / 2; i++){
- r1 = rpo2r[i];
- rpo2r[i] = rpo2r[nr - 1 - i];
- rpo2r[nr - 1 - i] = r1;
- }
- for(i = 0; i < nr; i++)
- rpo2r[i]->rpo = i;
-
- idom[0] = 0;
- for(i = 0; i < nr; i++){
- r1 = rpo2r[i];
- me = r1->rpo;
- d = -1;
- if(r1->p1 != R && r1->p1->rpo < me)
- d = r1->p1->rpo;
- for(r1 = r1->p2; r1 != nil; r1 = r1->p2link)
- if(r1->rpo < me)
- d = rpolca(idom, d, r1->rpo);
- idom[i] = d;
- }
-
- for(i = 0; i < nr; i++){
- r1 = rpo2r[i];
- r1->loop++;
- if(r1->p2 != R && loophead(idom, r1))
- loopmark(rpo2r, i, r1);
- }
-}
-
-void
-synch(Reg *r, Bits dif)
-{
- Reg *r1;
- int z;
-
- for(r1 = r; r1 != R; r1 = r1->s1) {
- for(z=0; z<BITS; z++) {
- dif.b[z] = (dif.b[z] &
- ~(~r1->refbehind.b[z] & r1->refahead.b[z])) |
- r1->set.b[z] | r1->regdiff.b[z];
- if(dif.b[z] != r1->regdiff.b[z]) {
- r1->regdiff.b[z] = dif.b[z];
- change++;
- }
- }
- if(r1->active)
- break;
- r1->active = 1;
- for(z=0; z<BITS; z++)
- dif.b[z] &= ~(~r1->calbehind.b[z] & r1->calahead.b[z]);
- if(r1->s2 != R)
- synch(r1->s2, dif);
- }
-}
-
-uint32
-allreg(uint32 b, Rgn *r)
-{
- Var *v;
- int i;
-
- v = var + r->varno;
- r->regno = 0;
- switch(v->etype) {
-
- default:
- diag(Z, "unknown etype %d/%d", bitno(b), v->etype);
- break;
-
- case TCHAR:
- case TUCHAR:
- case TSHORT:
- case TUSHORT:
- case TINT:
- case TUINT:
- case TLONG:
- case TULONG:
- case TVLONG:
- case TUVLONG:
- case TIND:
- case TARRAY:
- i = BtoR(~b);
- if(i && r->cost > 0) {
- r->regno = i;
- return RtoB(i);
- }
- break;
-
- case TDOUBLE:
- case TFLOAT:
- i = BtoF(~b);
- if(i && r->cost > 0) {
- r->regno = i;
- return FtoB(i);
- }
- break;
- }
- return 0;
-}
-
-void
-paint1(Reg *r, int bn)
-{
- Reg *r1;
- Prog *p;
- int z;
- uint32 bb;
-
- z = bn/32;
- bb = 1L<<(bn%32);
- if(r->act.b[z] & bb)
- return;
- for(;;) {
- if(!(r->refbehind.b[z] & bb))
- break;
- r1 = r->p1;
- if(r1 == R)
- break;
- if(!(r1->refahead.b[z] & bb))
- break;
- if(r1->act.b[z] & bb)
- break;
- r = r1;
- }
-
- if(LOAD(r) & ~(r->set.b[z]&~(r->use1.b[z]|r->use2.b[z])) & bb) {
- change -= CLOAD * r->loop;
- if(debug['R'] && debug['v'])
- print("%d%P\td %B $%d\n", r->loop,
- r->prog, blsh(bn), change);
- }
- for(;;) {
- r->act.b[z] |= bb;
- p = r->prog;
-
- if(r->use1.b[z] & bb) {
- change += CREF * r->loop;
- if(debug['R'] && debug['v'])
- print("%d%P\tu1 %B $%d\n", r->loop,
- p, blsh(bn), change);
- }
-
- if((r->use2.b[z]|r->set.b[z]) & bb) {
- change += CREF * r->loop;
- if(debug['R'] && debug['v'])
- print("%d%P\tu2 %B $%d\n", r->loop,
- p, blsh(bn), change);
- }
-
- if(STORE(r) & r->regdiff.b[z] & bb) {
- change -= CLOAD * r->loop;
- if(debug['R'] && debug['v'])
- print("%d%P\tst %B $%d\n", r->loop,
- p, blsh(bn), change);
- }
-
- if(r->refbehind.b[z] & bb)
- for(r1 = r->p2; r1 != R; r1 = r1->p2link)
- if(r1->refahead.b[z] & bb)
- paint1(r1, bn);
-
- if(!(r->refahead.b[z] & bb))
- break;
- r1 = r->s2;
- if(r1 != R)
- if(r1->refbehind.b[z] & bb)
- paint1(r1, bn);
- r = r->s1;
- if(r == R)
- break;
- if(r->act.b[z] & bb)
- break;
- if(!(r->refbehind.b[z] & bb))
- break;
- }
-}
-
-uint32
-regset(Reg *r, uint32 bb)
-{
- uint32 b, set;
- Addr v;
- int c;
-
- set = 0;
- v = zprog.from;
- while(b = bb & ~(bb-1)) {
- v.type = b & 0xFFFF? BtoR(b): BtoF(b);
- if(v.type == 0)
- diag(Z, "zero v.type for %#ux", b);
- c = copyu(r->prog, &v, A);
- if(c == 3)
- set |= b;
- bb &= ~b;
- }
- return set;
-}
-
-uint32
-reguse(Reg *r, uint32 bb)
-{
- uint32 b, set;
- Addr v;
- int c;
-
- set = 0;
- v = zprog.from;
- while(b = bb & ~(bb-1)) {
- v.type = b & 0xFFFF? BtoR(b): BtoF(b);
- c = copyu(r->prog, &v, A);
- if(c == 1 || c == 2 || c == 4)
- set |= b;
- bb &= ~b;
- }
- return set;
-}
-
-uint32
-paint2(Reg *r, int bn)
-{
- Reg *r1;
- int z;
- uint32 bb, vreg, x;
-
- z = bn/32;
- bb = 1L << (bn%32);
- vreg = regbits;
- if(!(r->act.b[z] & bb))
- return vreg;
- for(;;) {
- if(!(r->refbehind.b[z] & bb))
- break;
- r1 = r->p1;
- if(r1 == R)
- break;
- if(!(r1->refahead.b[z] & bb))
- break;
- if(!(r1->act.b[z] & bb))
- break;
- r = r1;
- }
- for(;;) {
- r->act.b[z] &= ~bb;
-
- vreg |= r->regu;
-
- if(r->refbehind.b[z] & bb)
- for(r1 = r->p2; r1 != R; r1 = r1->p2link)
- if(r1->refahead.b[z] & bb)
- vreg |= paint2(r1, bn);
-
- if(!(r->refahead.b[z] & bb))
- break;
- r1 = r->s2;
- if(r1 != R)
- if(r1->refbehind.b[z] & bb)
- vreg |= paint2(r1, bn);
- r = r->s1;
- if(r == R)
- break;
- if(!(r->act.b[z] & bb))
- break;
- if(!(r->refbehind.b[z] & bb))
- break;
- }
-
- bb = vreg;
- for(; r; r=r->s1) {
- x = r->regu & ~bb;
- if(x) {
- vreg |= reguse(r, x);
- bb |= regset(r, x);
- }
- }
- return vreg;
-}
-
-void
-paint3(Reg *r, int bn, int32 rb, int rn)
-{
- Reg *r1;
- Prog *p;
- int z;
- uint32 bb;
-
- z = bn/32;
- bb = 1L << (bn%32);
- if(r->act.b[z] & bb)
- return;
- for(;;) {
- if(!(r->refbehind.b[z] & bb))
- break;
- r1 = r->p1;
- if(r1 == R)
- break;
- if(!(r1->refahead.b[z] & bb))
- break;
- if(r1->act.b[z] & bb)
- break;
- r = r1;
- }
-
- if(LOAD(r) & ~(r->set.b[z] & ~(r->use1.b[z]|r->use2.b[z])) & bb)
- addmove(r, bn, rn, 0);
- for(;;) {
- r->act.b[z] |= bb;
- p = r->prog;
-
- if(r->use1.b[z] & bb) {
- if(debug['R'])
- print("%P", p);
- addreg(&p->from, rn);
- if(debug['R'])
- print("\t.c%P\n", p);
- }
- if((r->use2.b[z]|r->set.b[z]) & bb) {
- if(debug['R'])
- print("%P", p);
- addreg(&p->to, rn);
- if(debug['R'])
- print("\t.c%P\n", p);
- }
-
- if(STORE(r) & r->regdiff.b[z] & bb)
- addmove(r, bn, rn, 1);
- r->regu |= rb;
-
- if(r->refbehind.b[z] & bb)
- for(r1 = r->p2; r1 != R; r1 = r1->p2link)
- if(r1->refahead.b[z] & bb)
- paint3(r1, bn, rb, rn);
-
- if(!(r->refahead.b[z] & bb))
- break;
- r1 = r->s2;
- if(r1 != R)
- if(r1->refbehind.b[z] & bb)
- paint3(r1, bn, rb, rn);
- r = r->s1;
- if(r == R)
- break;
- if(r->act.b[z] & bb)
- break;
- if(!(r->refbehind.b[z] & bb))
- break;
- }
-}
-
-void
-addreg(Addr *a, int rn)
-{
-
- a->sym = 0;
- a->offset = 0;
- a->type = rn;
-}
-
-int32
-RtoB(int r)
-{
-
- if(r < D_AX || r > D_R15)
- return 0;
- return 1L << (r-D_AX);
-}
-
-int
-BtoR(int32 b)
-{
-
- b &= 0xffffL;
- if(nacl)
- b &= ~((1<<(D_BP-D_AX)) | (1<<(D_R15-D_AX)));
- if(b == 0)
- return 0;
- return bitno(b) + D_AX;
-}
-
-/*
- * bit reg
- * 16 X5
- * 17 X6
- * 18 X7
- */
-int32
-FtoB(int f)
-{
- if(f < FREGMIN || f > FREGEXT)
- return 0;
- return 1L << (f - FREGMIN + 16);
-}
-
-int
-BtoF(int32 b)
-{
-
- b &= 0x70000L;
- if(b == 0)
- return 0;
- return bitno(b) - 16 + FREGMIN;
-}
-
-/* what instruction does a JMP to p eventually land on? */
-static Reg*
-chasejmp(Reg *r, int *jmploop)
-{
- int n;
-
- n = 0;
- for(; r; r=r->s2) {
- if(r->prog->as != AJMP || r->prog->to.type != D_BRANCH)
- break;
- if(++n > 10) {
- *jmploop = 1;
- break;
- }
- }
- return r;
-}
-
-/* mark all code reachable from firstp as alive */
-static void
-mark(Reg *firstr)
-{
- Reg *r;
- Prog *p;
-
- for(r=firstr; r; r=r->link) {
- if(r->active)
- break;
- r->active = 1;
- p = r->prog;
- if(p->as != ACALL && p->to.type == D_BRANCH)
- mark(r->s2);
- if(p->as == AJMP || p->as == ARET || p->as == AUNDEF)
- break;
- }
-}
-
-/*
- * the code generator depends on being able to write out JMP
- * instructions that it can jump to now but fill in later.
- * the linker will resolve them nicely, but they make the code
- * longer and more difficult to follow during debugging.
- * remove them.
- */
-static void
-fixjmp(Reg *firstr)
-{
- int jmploop;
- Reg *r;
- Prog *p;
-
- if(debug['R'] && debug['v'])
- print("\nfixjmp\n");
-
- // pass 1: resolve jump to AJMP, mark all code as dead.
- jmploop = 0;
- for(r=firstr; r; r=r->link) {
- p = r->prog;
- if(debug['R'] && debug['v'])
- print("%04d %P\n", (int)r->pc, p);
- if(p->as != ACALL && p->to.type == D_BRANCH && r->s2 && r->s2->prog->as == AJMP) {
- r->s2 = chasejmp(r->s2, &jmploop);
- p->to.offset = r->s2->pc;
- p->to.u.branch = r->s2->prog;
- if(debug['R'] && debug['v'])
- print("->%P\n", p);
- }
- r->active = 0;
- }
- if(debug['R'] && debug['v'])
- print("\n");
-
- // pass 2: mark all reachable code alive
- mark(firstr);
-
- // pass 3: delete dead code (mostly JMPs).
- for(r=firstr; r; r=r->link) {
- if(!r->active) {
- p = r->prog;
- if(p->link == P && p->as == ARET && r->p1 && r->p1->prog->as != ARET) {
- // This is the final ARET, and the code so far doesn't have one.
- // Let it stay.
- } else {
- if(debug['R'] && debug['v'])
- print("del %04d %P\n", (int)r->pc, p);
- p->as = ANOP;
- }
- }
- }
-
- // pass 4: elide JMP to next instruction.
- // only safe if there are no jumps to JMPs anymore.
- if(!jmploop) {
- for(r=firstr; r; r=r->link) {
- p = r->prog;
- if(p->as == AJMP && p->to.type == D_BRANCH && r->s2 == r->link) {
- if(debug['R'] && debug['v'])
- print("del %04d %P\n", (int)r->pc, p);
- p->as = ANOP;
- }
- }
- }
-
- // fix back pointers.
- for(r=firstr; r; r=r->link) {
- r->p2 = R;
- r->p2link = R;
- }
- for(r=firstr; r; r=r->link) {
- if(r->s2) {
- r->p2link = r->s2->p2;
- r->s2->p2 = r;
- }
- }
-
- if(debug['R'] && debug['v']) {
- print("\n");
- for(r=firstr; r; r=r->link)
- print("%04d %P\n", (int)r->pc, r->prog);
- print("\n");
- }
-}
-
diff --git a/src/cmd/6c/sgen.c b/src/cmd/6c/sgen.c
deleted file mode 100644
index fceb332b2..000000000
--- a/src/cmd/6c/sgen.c
+++ /dev/null
@@ -1,483 +0,0 @@
-// Inferno utils/6c/sgen.c
-// http://code.google.com/p/inferno-os/source/browse/utils/6c/sgen.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-#include "../../runtime/funcdata.h"
-
-Prog*
-gtext(Sym *s, int32 stkoff)
-{
- vlong v;
-
- v = ((uvlong)argsize(1) << 32) | (stkoff & 0xffffffff);
- if((textflag & NOSPLIT) && stkoff >= 128)
- yyerror("stack frame too large for NOSPLIT function");
-
- gpseudo(ATEXT, s, nodgconst(v, types[TVLONG]));
- return p;
-}
-
-void
-noretval(int n)
-{
-
- if(n & 1) {
- gins(ANOP, Z, Z);
- p->to.type = REGRET;
- }
- if(n & 2) {
- gins(ANOP, Z, Z);
- p->to.type = FREGRET;
- }
-}
-
-/* welcome to commute */
-static void
-commute(Node *n)
-{
- Node *l, *r;
-
- l = n->left;
- r = n->right;
- if(r->complex > l->complex) {
- n->left = r;
- n->right = l;
- }
-}
-
-void
-indexshift(Node *n)
-{
- int g;
-
- if(!typechlpv[n->type->etype])
- return;
- simplifyshift(n);
- if(n->op == OASHL && n->right->op == OCONST){
- g = vconst(n->right);
- if(g >= 0 && g <= 3)
- n->addable = 7;
- }
-}
-
-/*
- * calculate addressability as follows
- * NAME ==> 10/11 name+value(SB/SP)
- * REGISTER ==> 12 register
- * CONST ==> 20 $value
- * *(20) ==> 21 value
- * &(10) ==> 13 $name+value(SB)
- * &(11) ==> 1 $name+value(SP)
- * (13) + (20) ==> 13 fold constants
- * (1) + (20) ==> 1 fold constants
- * *(13) ==> 10 back to name
- * *(1) ==> 11 back to name
- *
- * (20) * (X) ==> 7 multiplier in indexing
- * (X,7) + (13,1) ==> 8 adder in indexing (addresses)
- * (8) ==> &9(OINDEX) index, almost addressable
- *
- * calculate complexity (number of registers)
- */
-void
-xcom(Node *n)
-{
- Node *l, *r;
- int g;
-
- if(n == Z)
- return;
- l = n->left;
- r = n->right;
- n->complex = 0;
- n->addable = 0;
- switch(n->op) {
- case OCONST:
- n->addable = 20;
- break;
-
- case ONAME:
- n->addable = 9;
- if(n->class == CPARAM || n->class == CAUTO)
- n->addable = 11;
- break;
-
- case OEXREG:
- n->addable = 0;
- break;
-
- case OREGISTER:
- n->addable = 12;
- break;
-
- case OINDREG:
- n->addable = 12;
- break;
-
- case OADDR:
- xcom(l);
- if(l->addable == 10)
- n->addable = 13;
- else
- if(l->addable == 11)
- n->addable = 1;
- break;
-
- case OADD:
- xcom(l);
- xcom(r);
- if(n->type->etype != TIND)
- break;
-
- switch(r->addable) {
- case 20:
- switch(l->addable) {
- case 1:
- case 13:
- commadd:
- l->type = n->type;
- *n = *l;
- l = new(0, Z, Z);
- *l = *(n->left);
- l->xoffset += r->vconst;
- n->left = l;
- r = n->right;
- goto brk;
- }
- break;
-
- case 1:
- case 13:
- case 10:
- case 11:
- /* l is the base, r is the index */
- if(l->addable != 20)
- n->addable = 8;
- break;
- }
- switch(l->addable) {
- case 20:
- switch(r->addable) {
- case 13:
- case 1:
- r = n->left;
- l = n->right;
- n->left = l;
- n->right = r;
- goto commadd;
- }
- break;
-
- case 13:
- case 1:
- case 10:
- case 11:
- /* r is the base, l is the index */
- if(r->addable != 20)
- n->addable = 8;
- break;
- }
- if(n->addable == 8 && !side(n) && !nacl) {
- indx(n);
- l = new1(OINDEX, idx.basetree, idx.regtree);
- l->scale = idx.scale;
- l->addable = 9;
- l->complex = l->right->complex;
- l->type = l->left->type;
- n->op = OADDR;
- n->left = l;
- n->right = Z;
- n->addable = 8;
- break;
- }
- break;
-
- case OINDEX:
- xcom(l);
- xcom(r);
- n->addable = 9;
- break;
-
- case OIND:
- xcom(l);
- if(l->op == OADDR) {
- l = l->left;
- l->type = n->type;
- *n = *l;
- return;
- }
- switch(l->addable) {
- case 20:
- n->addable = 21;
- break;
- case 1:
- n->addable = 11;
- break;
- case 13:
- n->addable = 10;
- break;
- }
- break;
-
- case OASHL:
- xcom(l);
- xcom(r);
- indexshift(n);
- break;
-
- case OMUL:
- case OLMUL:
- xcom(l);
- xcom(r);
- g = vlog(l);
- if(g >= 0) {
- n->left = r;
- n->right = l;
- l = r;
- r = n->right;
- }
- g = vlog(r);
- if(g >= 0) {
- n->op = OASHL;
- r->vconst = g;
- r->type = types[TINT];
- indexshift(n);
- break;
- }
- commute(n);
- break;
-
- case OASLDIV:
- xcom(l);
- xcom(r);
- g = vlog(r);
- if(g >= 0) {
- n->op = OASLSHR;
- r->vconst = g;
- r->type = types[TINT];
- }
- break;
-
- case OLDIV:
- xcom(l);
- xcom(r);
- g = vlog(r);
- if(g >= 0) {
- n->op = OLSHR;
- r->vconst = g;
- r->type = types[TINT];
- indexshift(n);
- break;
- }
- break;
-
- case OASLMOD:
- xcom(l);
- xcom(r);
- g = vlog(r);
- if(g >= 0) {
- n->op = OASAND;
- r->vconst--;
- }
- break;
-
- case OLMOD:
- xcom(l);
- xcom(r);
- g = vlog(r);
- if(g >= 0) {
- n->op = OAND;
- r->vconst--;
- }
- break;
-
- case OASMUL:
- case OASLMUL:
- xcom(l);
- xcom(r);
- g = vlog(r);
- if(g >= 0) {
- n->op = OASASHL;
- r->vconst = g;
- }
- break;
-
- case OLSHR:
- case OASHR:
- xcom(l);
- xcom(r);
- indexshift(n);
- break;
-
- default:
- if(l != Z)
- xcom(l);
- if(r != Z)
- xcom(r);
- break;
- }
-brk:
- if(n->addable >= 10)
- return;
- if(l != Z)
- n->complex = l->complex;
- if(r != Z) {
- if(r->complex == n->complex)
- n->complex = r->complex+1;
- else
- if(r->complex > n->complex)
- n->complex = r->complex;
- }
- if(n->complex == 0)
- n->complex++;
-
- switch(n->op) {
-
- case OFUNC:
- n->complex = FNX;
- break;
-
- case OCAST:
- if(l->type->etype == TUVLONG && typefd[n->type->etype])
- n->complex += 2;
- break;
-
- case OLMOD:
- case OMOD:
- case OLMUL:
- case OLDIV:
- case OMUL:
- case ODIV:
- case OASLMUL:
- case OASLDIV:
- case OASLMOD:
- case OASMUL:
- case OASDIV:
- case OASMOD:
- if(r->complex >= l->complex) {
- n->complex = l->complex + 3;
- if(r->complex > n->complex)
- n->complex = r->complex;
- } else {
- n->complex = r->complex + 3;
- if(l->complex > n->complex)
- n->complex = l->complex;
- }
- break;
-
- case OLSHR:
- case OASHL:
- case OASHR:
- case OASLSHR:
- case OASASHL:
- case OASASHR:
- if(r->complex >= l->complex) {
- n->complex = l->complex + 2;
- if(r->complex > n->complex)
- n->complex = r->complex;
- } else {
- n->complex = r->complex + 2;
- if(l->complex > n->complex)
- n->complex = l->complex;
- }
- break;
-
- case OADD:
- case OXOR:
- case OAND:
- case OOR:
- /*
- * immediate operators, make const on right
- */
- if(l->op == OCONST) {
- n->left = r;
- n->right = l;
- }
- break;
-
- case OEQ:
- case ONE:
- case OLE:
- case OLT:
- case OGE:
- case OGT:
- case OHI:
- case OHS:
- case OLO:
- case OLS:
- /*
- * compare operators, make const on left
- */
- if(r->op == OCONST) {
- n->left = r;
- n->right = l;
- n->op = invrel[relindex(n->op)];
- }
- break;
- }
-}
-
-void
-indx(Node *n)
-{
- Node *l, *r;
-
- if(debug['x'])
- prtree(n, "indx");
-
- l = n->left;
- r = n->right;
- if(l->addable == 1 || l->addable == 13 || r->complex > l->complex) {
- n->right = l;
- n->left = r;
- l = r;
- r = n->right;
- }
- if(l->addable != 7) {
- idx.regtree = l;
- idx.scale = 1;
- } else
- if(l->right->addable == 20) {
- idx.regtree = l->left;
- idx.scale = 1 << l->right->vconst;
- } else
- if(l->left->addable == 20) {
- idx.regtree = l->right;
- idx.scale = 1 << l->left->vconst;
- } else
- diag(n, "bad index");
-
- idx.basetree = r;
- if(debug['x']) {
- print("scale = %d\n", idx.scale);
- prtree(idx.regtree, "index");
- prtree(idx.basetree, "base");
- }
-}
diff --git a/src/cmd/6c/swt.c b/src/cmd/6c/swt.c
deleted file mode 100644
index 6e918eb10..000000000
--- a/src/cmd/6c/swt.c
+++ /dev/null
@@ -1,353 +0,0 @@
-// Inferno utils/6c/swt.c
-// http://code.google.com/p/inferno-os/source/browse/utils/6c/swt.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-
-void
-swit1(C1 *q, int nc, int32 def, Node *n)
-{
- Node nreg;
-
- regalloc(&nreg, n, Z);
- if(typev[n->type->etype])
- nreg.type = types[TVLONG];
- else
- nreg.type = types[TLONG];
- cgen(n, &nreg);
- swit2(q, nc, def, &nreg);
- regfree(&nreg);
-}
-
-void
-swit2(C1 *q, int nc, int32 def, Node *n)
-{
- C1 *r;
- int i;
- Prog *sp;
-
- if(nc < 5) {
- for(i=0; i<nc; i++) {
- if(debug['W'])
- print("case = %.8llux\n", q->val);
- gcmp(OEQ, n, q->val);
- patch(p, q->label);
- q++;
- }
- gbranch(OGOTO);
- patch(p, def);
- return;
- }
- i = nc / 2;
- r = q+i;
- if(debug['W'])
- print("case > %.8llux\n", r->val);
- gcmp(OGT, n, r->val);
- sp = p;
- gbranch(OGOTO);
- p->as = AJEQ;
- patch(p, r->label);
- swit2(q, i, def, n);
-
- if(debug['W'])
- print("case < %.8llux\n", r->val);
- patch(sp, pc);
- swit2(r+1, nc-i-1, def, n);
-}
-
-void
-bitload(Node *b, Node *n1, Node *n2, Node *n3, Node *nn)
-{
- int sh;
- int32 v;
- Node *l;
-
- /*
- * n1 gets adjusted/masked value
- * n2 gets address of cell
- * n3 gets contents of cell
- */
- l = b->left;
- if(n2 != Z) {
- regalloc(n1, l, nn);
- reglcgen(n2, l, Z);
- regalloc(n3, l, Z);
- gmove(n2, n3);
- gmove(n3, n1);
- } else {
- regalloc(n1, l, nn);
- cgen(l, n1);
- }
- if(b->type->shift == 0 && typeu[b->type->etype]) {
- v = ~0 + (1L << b->type->nbits);
- gopcode(OAND, tfield, nodconst(v), n1);
- } else {
- sh = 32 - b->type->shift - b->type->nbits;
- if(sh > 0)
- gopcode(OASHL, tfield, nodconst(sh), n1);
- sh += b->type->shift;
- if(sh > 0)
- if(typeu[b->type->etype])
- gopcode(OLSHR, tfield, nodconst(sh), n1);
- else
- gopcode(OASHR, tfield, nodconst(sh), n1);
- }
-}
-
-void
-bitstore(Node *b, Node *n1, Node *n2, Node *n3, Node *nn)
-{
- int32 v;
- Node nod;
- int sh;
-
- regalloc(&nod, b->left, Z);
- v = ~0 + (1L << b->type->nbits);
- gopcode(OAND, types[TLONG], nodconst(v), n1);
- gmove(n1, &nod);
- if(nn != Z)
- gmove(n1, nn);
- sh = b->type->shift;
- if(sh > 0)
- gopcode(OASHL, types[TLONG], nodconst(sh), &nod);
- v <<= sh;
- gopcode(OAND, types[TLONG], nodconst(~v), n3);
- gopcode(OOR, types[TLONG], n3, &nod);
- gmove(&nod, n2);
-
- regfree(&nod);
- regfree(n1);
- regfree(n2);
- regfree(n3);
-}
-
-int32
-outstring(char *s, int32 n)
-{
- int32 r;
-
- if(suppress)
- return nstring;
- r = nstring;
- while(n) {
- string[mnstring] = *s++;
- mnstring++;
- nstring++;
- if(mnstring >= NSNAME) {
- gpseudo(ADATA, symstring, nodconst(0L));
- p->from.offset += nstring - NSNAME;
- p->from.scale = NSNAME;
- p->to.type = D_SCONST;
- memmove(p->to.u.sval, string, NSNAME);
- mnstring = 0;
- }
- n--;
- }
- return r;
-}
-
-void
-sextern(Sym *s, Node *a, int32 o, int32 w)
-{
- int32 e, lw;
-
- for(e=0; e<w; e+=NSNAME) {
- lw = NSNAME;
- if(w-e < lw)
- lw = w-e;
- gpseudo(ADATA, s, nodconst(0L));
- p->from.offset += o+e;
- p->from.scale = lw;
- p->to.type = D_SCONST;
- memmove(p->to.u.sval, a->cstring+e, lw);
- }
-}
-
-void
-gextern(Sym *s, Node *a, int32 o, int32 w)
-{
- if(0 && a->op == OCONST && typev[a->type->etype]) {
- gpseudo(ADATA, s, lo64(a));
- p->from.offset += o;
- p->from.scale = 4;
- gpseudo(ADATA, s, hi64(a));
- p->from.offset += o + 4;
- p->from.scale = 4;
- return;
- }
- gpseudo(ADATA, s, a);
- p->from.offset += o;
- p->from.scale = w;
- switch(p->to.type) {
- default:
- p->to.index = p->to.type;
- p->to.type = D_ADDR;
- case D_CONST:
- case D_FCONST:
- case D_ADDR:
- break;
- }
-}
-
-void
-outcode(void)
-{
- int f;
- Biobuf b;
-
- f = open(outfile, OWRITE);
- if(f < 0) {
- diag(Z, "cannot open %s", outfile);
- return;
- }
- Binit(&b, f, OWRITE);
-
- Bprint(&b, "go object %s %s %s\n", getgoos(), getgoarch(), getgoversion());
- if(pragcgobuf.to > pragcgobuf.start) {
- Bprint(&b, "\n");
- Bprint(&b, "$$ // exports\n\n");
- Bprint(&b, "$$ // local types\n\n");
- Bprint(&b, "$$ // cgo\n");
- Bprint(&b, "%s", fmtstrflush(&pragcgobuf));
- Bprint(&b, "\n$$\n\n");
- }
- Bprint(&b, "!\n");
-
- writeobj(ctxt, &b);
- Bterm(&b);
- close(f);
- lastp = P;
-}
-
-int32
-align(int32 i, Type *t, int op, int32 *maxalign)
-{
- int32 o;
- Type *v;
- int w, packw;
-
- o = i;
- w = 1;
- packw = 0;
- switch(op) {
- default:
- diag(Z, "unknown align opcode %d", op);
- break;
-
- case Asu2: /* padding at end of a struct */
- w = *maxalign;
- if(w < 1)
- w = 1;
- if(packflg)
- packw = packflg;
- break;
-
- case Ael1: /* initial align of struct element */
- for(v=t; v->etype==TARRAY; v=v->link)
- ;
- if(v->etype == TSTRUCT || v->etype == TUNION)
- w = v->align;
- else
- w = ewidth[v->etype];
- if(w < 1 || w > SZ_VLONG)
- fatal(Z, "align");
- if(packflg)
- packw = packflg;
- break;
-
- case Ael2: /* width of a struct element */
- o += t->width;
- break;
-
- case Aarg0: /* initial passbyptr argument in arg list */
- if(typesu[t->etype]) {
- o = align(o, types[TIND], Aarg1, nil);
- o = align(o, types[TIND], Aarg2, nil);
- }
- break;
-
- case Aarg1: /* initial align of parameter */
- if(ewidth[TIND] == 4) {
- if(typesu[t->etype]) {
- for(v = t->link; v != T; v = v->down)
- o = align(o, v, Aarg1, maxalign);
- goto out;
- }
- w = ewidth[t->etype];
- if(typev[t->etype] || t->etype == TDOUBLE)
- w = 8;
- else if(w <= 0 || w >= 4)
- w = 4;
- else
- w = 1;
- break;
- }
- w = ewidth[t->etype];
- if(w <= 0 || w >= SZ_VLONG) {
- w = SZ_VLONG;
- break;
- }
- w = 1; /* little endian no adjustment */
- break;
-
- case Aarg2: /* width of a parameter */
- o += t->width;
- if(ewidth[TIND] == 4) {
- o = align(o, t, Aarg1, maxalign);
- goto out;
- }
- w = t->width;
- if(w > SZ_VLONG)
- w = SZ_VLONG;
- break;
-
- case Aaut3: /* total align of automatic */
- o = align(o, t, Ael1, nil);
- o = align(o, t, Ael2, nil);
- break;
- }
- if(packw != 0 && xround(o, w) != xround(o, packw))
- diag(Z, "#pragma pack changes offset of %T", t);
- o = xround(o, w);
- if(maxalign && *maxalign < w)
- *maxalign = w;
-out:
- if(debug['A'])
- print("align %s %d %T = %d\n", bnames[op], i, t, o);
- return o;
-}
-
-int32
-maxround(int32 max, int32 v)
-{
- v = xround(v, SZ_VLONG);
- if(v > max)
- return v;
- return max;
-}
diff --git a/src/cmd/6c/txt.c b/src/cmd/6c/txt.c
deleted file mode 100644
index 3bdbf410e..000000000
--- a/src/cmd/6c/txt.c
+++ /dev/null
@@ -1,1674 +0,0 @@
-// Inferno utils/6c/txt.c
-// http://code.google.com/p/inferno-os/source/browse/utils/6c/txt.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-
-int thechar = '6';
-char *thestring = "amd64";
-
-LinkArch *thelinkarch = &linkamd64;
-
-void
-linkarchinit(void)
-{
- if(strcmp(getgoarch(), "amd64p32") == 0)
- thelinkarch = &linkamd64p32;
-}
-
-void
-ginit(void)
-{
- int i;
- Type *t;
-
- dodefine("_64BITREG");
- if(ewidth[TIND] == 8)
- dodefine("_64BIT");
- listinit();
- nstring = 0;
- mnstring = 0;
- nrathole = 0;
- pc = 0;
- breakpc = -1;
- continpc = -1;
- cases = C;
- lastp = P;
- tfield = types[TINT];
-
- typeword = typechlvp;
- typecmplx = typesu;
-
- /* TO DO */
- memmove(typechlpv, typechlp, sizeof(typechlpv));
- typechlpv[TVLONG] = 1;
- typechlpv[TUVLONG] = 1;
-
- zprog.link = P;
- zprog.as = AGOK;
- zprog.from.type = D_NONE;
- zprog.from.index = D_NONE;
- zprog.from.scale = 0;
- zprog.to = zprog.from;
-
- lregnode.op = OREGISTER;
- lregnode.class = CEXREG;
- lregnode.reg = REGTMP;
- lregnode.complex = 0;
- lregnode.addable = 11;
- lregnode.type = types[TLONG];
-
- qregnode = lregnode;
- qregnode.type = types[TVLONG];
-
- constnode.op = OCONST;
- constnode.class = CXXX;
- constnode.complex = 0;
- constnode.addable = 20;
- constnode.type = types[TLONG];
-
- vconstnode = constnode;
- vconstnode.type = types[TVLONG];
-
- fconstnode.op = OCONST;
- fconstnode.class = CXXX;
- fconstnode.complex = 0;
- fconstnode.addable = 20;
- fconstnode.type = types[TDOUBLE];
-
- nodsafe = new(ONAME, Z, Z);
- nodsafe->sym = slookup(".safe");
- nodsafe->type = types[TINT];
- nodsafe->etype = types[TINT]->etype;
- nodsafe->class = CAUTO;
- complex(nodsafe);
-
- t = typ(TARRAY, types[TCHAR]);
- symrathole = slookup(".rathole");
- symrathole->class = CGLOBL;
- symrathole->type = t;
-
- nodrat = new(ONAME, Z, Z);
- nodrat->sym = symrathole;
- nodrat->type = types[TIND];
- nodrat->etype = TVOID;
- nodrat->class = CGLOBL;
- complex(nodrat);
- nodrat->type = t;
-
- nodret = new(ONAME, Z, Z);
- nodret->sym = slookup(".ret");
- nodret->type = types[TIND];
- nodret->etype = TIND;
- nodret->class = CPARAM;
- nodret = new(OIND, nodret, Z);
- complex(nodret);
-
- if(0)
- com64init();
-
- for(i=0; i<nelem(reg); i++) {
- reg[i] = 1;
- if(i >= D_AX && i <= D_R15 && i != D_SP)
- reg[i] = 0;
- if(i >= D_X0 && i <= D_X7)
- reg[i] = 0;
- }
- if(nacl) {
- reg[D_BP] = 1;
- reg[D_R15] = 1;
- }
-}
-
-void
-gclean(void)
-{
- int i;
- Sym *s;
-
- reg[D_SP]--;
- if(nacl) {
- reg[D_BP]--;
- reg[D_R15]--;
- }
- for(i=D_AX; i<=D_R15; i++)
- if(reg[i])
- diag(Z, "reg %R left allocated", i);
- for(i=D_X0; i<=D_X7; i++)
- if(reg[i])
- diag(Z, "reg %R left allocated", i);
- while(mnstring)
- outstring("", 1L);
- symstring->type->width = nstring;
- symrathole->type->width = nrathole;
- for(i=0; i<NHASH; i++)
- for(s = hash[i]; s != S; s = s->link) {
- if(s->type == T)
- continue;
- if(s->type->width == 0)
- continue;
- if(s->class != CGLOBL && s->class != CSTATIC)
- continue;
- if(s->type == types[TENUM])
- continue;
- gpseudo(AGLOBL, s, nodconst(s->type->width));
- }
- nextpc();
- p->as = AEND;
- outcode();
-}
-
-void
-nextpc(void)
-{
- Plist *pl;
-
- p = alloc(sizeof(*p));
- *p = zprog;
- p->lineno = nearln;
- p->pc = pc;
- pc++;
- if(lastp == nil) {
- pl = linknewplist(ctxt);
- pl->firstpc = p;
- } else
- lastp->link = p;
- lastp = p;
-}
-
-void
-gargs(Node *n, Node *tn1, Node *tn2)
-{
- int32 regs;
- Node fnxargs[20], *fnxp;
-
- regs = cursafe;
-
- fnxp = fnxargs;
- garg1(n, tn1, tn2, 0, &fnxp); /* compile fns to temps */
-
- curarg = 0;
- fnxp = fnxargs;
- garg1(n, tn1, tn2, 1, &fnxp); /* compile normal args and temps */
-
- cursafe = regs;
-}
-
-int
-nareg(void)
-{
- int i, n;
-
- n = 0;
- for(i=D_AX; i<=D_R15; i++)
- if(reg[i] == 0)
- n++;
- return n;
-}
-
-void
-garg1(Node *n, Node *tn1, Node *tn2, int f, Node **fnxp)
-{
- Node nod;
-
- if(n == Z)
- return;
- if(n->op == OLIST) {
- garg1(n->left, tn1, tn2, f, fnxp);
- garg1(n->right, tn1, tn2, f, fnxp);
- return;
- }
- if(f == 0) {
- if(n->complex >= FNX) {
- regsalloc(*fnxp, n);
- nod = znode;
- nod.op = OAS;
- nod.left = *fnxp;
- nod.right = n;
- nod.type = n->type;
- cgen(&nod, Z);
- (*fnxp)++;
- }
- return;
- }
- if(typesu[n->type->etype]) {
- regaalloc(tn2, n);
- if(n->complex >= FNX) {
- sugen(*fnxp, tn2, n->type->width);
- (*fnxp)++;
- } else
- sugen(n, tn2, n->type->width);
- return;
- }
- if(REGARG >= 0 && curarg == 0 && typechlpv[n->type->etype]) {
- regaalloc1(tn1, n);
- if(n->complex >= FNX) {
- cgen(*fnxp, tn1);
- (*fnxp)++;
- } else
- cgen(n, tn1);
- return;
- }
- if(vconst(n) == 0) {
- regaalloc(tn2, n);
- gmove(n, tn2);
- return;
- }
- regalloc(tn1, n, Z);
- if(n->complex >= FNX) {
- cgen(*fnxp, tn1);
- (*fnxp)++;
- } else
- cgen(n, tn1);
- regaalloc(tn2, n);
- gmove(tn1, tn2);
- regfree(tn1);
-}
-
-Node*
-nodgconst(vlong v, Type *t)
-{
- if(!typev[t->etype])
- return nodconst((int32)v);
- vconstnode.vconst = v;
- return &vconstnode;
-}
-
-Node*
-nodconst(int32 v)
-{
- constnode.vconst = v;
- return &constnode;
-}
-
-Node*
-nodfconst(double d)
-{
- fconstnode.fconst = d;
- return &fconstnode;
-}
-
-int
-isreg(Node *n, int r)
-{
-
- if(n->op == OREGISTER)
- if(n->reg == r)
- return 1;
- return 0;
-}
-
-int
-nodreg(Node *n, Node *nn, int r)
-{
- int et;
-
- *n = qregnode;
- n->reg = r;
- if(nn != Z){
- et = nn->type->etype;
- if(!typefd[et] && nn->type->width <= SZ_LONG && 0)
- n->type = typeu[et]? types[TUINT]: types[TINT];
- else
- n->type = nn->type;
-//print("nodreg %s [%s]\n", tnames[et], tnames[n->type->etype]);
- n->lineno = nn->lineno;
- }
- if(reg[r] == 0)
- return 0;
- if(nn != Z) {
- if(nn->op == OREGISTER)
- if(nn->reg == r)
- return 0;
- }
- return 1;
-}
-
-void
-regret(Node *n, Node *nn, Type *t, int mode)
-{
- int r;
-
- if(mode == 0 || hasdotdotdot(t) || nn->type->width == 0) {
- r = REGRET;
- if(typefd[nn->type->etype])
- r = FREGRET;
- nodreg(n, nn, r);
- reg[r]++;
- return;
- }
-
- if(mode == 1) {
- // fetch returned value after call.
- // already called gargs, so curarg is set.
- curarg = (curarg+7) & ~7;
- regaalloc(n, nn);
- return;
- }
-
- if(mode == 2) {
- // store value to be returned.
- // must compute arg offset.
- if(t->etype != TFUNC)
- fatal(Z, "bad regret func %T", t);
- *n = *nn;
- n->op = ONAME;
- n->class = CPARAM;
- n->sym = slookup(".ret");
- n->complex = nodret->complex;
- n->addable = 20;
- n->xoffset = argsize(0);
- return;
- }
-
- fatal(Z, "bad regret");
-}
-
-void
-regalloc(Node *n, Node *tn, Node *o)
-{
- int i;
-
- switch(tn->type->etype) {
- case TCHAR:
- case TUCHAR:
- case TSHORT:
- case TUSHORT:
- case TINT:
- case TUINT:
- case TLONG:
- case TULONG:
- case TVLONG:
- case TUVLONG:
- case TIND:
- if(o != Z && o->op == OREGISTER) {
- i = o->reg;
- if(i >= D_AX && i <= D_R15)
- goto out;
- }
- for(i=D_AX; i<=D_R15; i++)
- if(reg[i] == 0)
- goto out;
- diag(tn, "out of fixed registers");
- goto err;
-
- case TFLOAT:
- case TDOUBLE:
- if(o != Z && o->op == OREGISTER) {
- i = o->reg;
- if(i >= D_X0 && i <= D_X7)
- goto out;
- }
- for(i=D_X0; i<=D_X7; i++)
- if(reg[i] == 0)
- goto out;
- diag(tn, "out of float registers");
- goto out;
- }
- diag(tn, "unknown type in regalloc: %T", tn->type);
-err:
- i = 0;
-out:
- if(i)
- reg[i]++;
- nodreg(n, tn, i);
-}
-
-void
-regialloc(Node *n, Node *tn, Node *o)
-{
- Node nod;
-
- nod = *tn;
- nod.type = types[TIND];
- regalloc(n, &nod, o);
-}
-
-void
-regfree(Node *n)
-{
- int i;
-
- i = 0;
- if(n->op != OREGISTER && n->op != OINDREG)
- goto err;
- i = n->reg;
- if(i < 0 || i >= nelem(reg))
- goto err;
- if(reg[i] <= 0)
- goto err;
- reg[i]--;
- return;
-err:
- diag(n, "error in regfree: %R", i);
-}
-
-void
-regsalloc(Node *n, Node *nn)
-{
- cursafe = align(cursafe, nn->type, Aaut3, nil);
- maxargsafe = maxround(maxargsafe, cursafe+curarg);
- *n = *nodsafe;
- n->xoffset = -(stkoff + cursafe);
- n->type = nn->type;
- n->etype = nn->type->etype;
- n->lineno = nn->lineno;
-}
-
-void
-regaalloc1(Node *n, Node *nn)
-{
- if(REGARG < 0) {
- fatal(n, "regaalloc1 and REGARG<0");
- return;
- }
- nodreg(n, nn, REGARG);
- reg[(uchar)REGARG]++;
- curarg = align(curarg, nn->type, Aarg1, nil);
- curarg = align(curarg, nn->type, Aarg2, nil);
- maxargsafe = maxround(maxargsafe, cursafe+curarg);
-}
-
-void
-regaalloc(Node *n, Node *nn)
-{
- curarg = align(curarg, nn->type, Aarg1, nil);
- *n = *nn;
- n->op = OINDREG;
- n->reg = REGSP;
- n->xoffset = curarg;
- n->complex = 0;
- n->addable = 20;
- curarg = align(curarg, nn->type, Aarg2, nil);
- maxargsafe = maxround(maxargsafe, cursafe+curarg);
-}
-
-void
-regind(Node *n, Node *nn)
-{
-
- if(n->op != OREGISTER) {
- diag(n, "regind not OREGISTER");
- return;
- }
- n->op = OINDREG;
- n->type = nn->type;
-}
-
-void
-naddr(Node *n, Addr *a)
-{
- int32 v;
-
- a->type = D_NONE;
- if(n == Z)
- return;
- switch(n->op) {
- default:
- bad:
- diag(n, "bad in naddr: %O %D", n->op, a);
- break;
-
- case OREGISTER:
- a->type = n->reg;
- a->sym = nil;
- break;
-
- case OEXREG:
- a->type = D_INDIR + D_TLS;
- a->offset = n->reg - 1;
- break;
-
- case OIND:
- naddr(n->left, a);
- if(a->type >= D_AX && a->type <= D_R15)
- a->type += D_INDIR;
- else
- if(a->type == D_CONST)
- a->type = D_NONE+D_INDIR;
- else
- if(a->type == D_ADDR) {
- a->type = a->index;
- a->index = D_NONE;
- } else
- goto bad;
- break;
-
- case OINDEX:
- a->type = idx.ptr;
- if(n->left->op == OADDR || n->left->op == OCONST)
- naddr(n->left, a);
- if(a->type >= D_AX && a->type <= D_R15)
- a->type += D_INDIR;
- else
- if(a->type == D_CONST)
- a->type = D_NONE+D_INDIR;
- else
- if(a->type == D_ADDR) {
- a->type = a->index;
- a->index = D_NONE;
- } else
- goto bad;
- a->index = idx.reg;
- a->scale = n->scale;
- a->offset += n->xoffset;
- break;
-
- case OINDREG:
- a->type = n->reg+D_INDIR;
- a->sym = nil;
- a->offset = n->xoffset;
- break;
-
- case ONAME:
- a->etype = n->etype;
- a->type = D_STATIC;
- a->sym = linksym(n->sym);
- a->offset = n->xoffset;
- if(n->class == CSTATIC)
- break;
- if(n->class == CEXTERN || n->class == CGLOBL) {
- a->type = D_EXTERN;
- break;
- }
- if(n->class == CAUTO) {
- a->type = D_AUTO;
- break;
- }
- if(n->class == CPARAM) {
- a->type = D_PARAM;
- break;
- }
- goto bad;
-
- case OCONST:
- if(typefd[n->type->etype]) {
- a->type = D_FCONST;
- a->u.dval = n->fconst;
- break;
- }
- a->sym = nil;
- a->type = D_CONST;
- if(typev[n->type->etype] || (n->type->etype == TIND && ewidth[TIND] == 8))
- a->offset = n->vconst;
- else
- a->offset = convvtox(n->vconst, typeu[n->type->etype]? TULONG: TLONG);
- break;
-
- case OADDR:
- naddr(n->left, a);
- if(a->type >= D_INDIR) {
- a->type -= D_INDIR;
- break;
- }
- if(a->type == D_EXTERN || a->type == D_STATIC ||
- a->type == D_AUTO || a->type == D_PARAM)
- if(a->index == D_NONE) {
- a->index = a->type;
- a->type = D_ADDR;
- break;
- }
- goto bad;
-
- case OADD:
- if(n->right->op == OCONST) {
- v = n->right->vconst;
- naddr(n->left, a);
- } else
- if(n->left->op == OCONST) {
- v = n->left->vconst;
- naddr(n->right, a);
- } else
- goto bad;
- a->offset += v;
- break;
-
- }
-}
-
-void
-gcmp(int op, Node *n, vlong val)
-{
- Node *cn, nod;
-
- cn = nodgconst(val, n->type);
- if(!immconst(cn)){
- regalloc(&nod, n, Z);
- gmove(cn, &nod);
- gopcode(op, n->type, n, &nod);
- regfree(&nod);
- }else
- gopcode(op, n->type, n, cn);
-}
-
-#define CASE(a,b) ((a<<8)|(b<<0))
-
-void
-gmove(Node *f, Node *t)
-{
- int ft, tt, t64, a;
- Node nod, nod1, nod2, nod3;
- Prog *p1, *p2;
-
- ft = f->type->etype;
- tt = t->type->etype;
- if(ewidth[TIND] == 4) {
- if(ft == TIND)
- ft = TUINT;
- if(tt == TIND)
- tt = TUINT;
- }
- t64 = tt == TVLONG || tt == TUVLONG || tt == TIND;
- if(debug['M'])
- print("gop: %O %O[%s],%O[%s]\n", OAS,
- f->op, tnames[ft], t->op, tnames[tt]);
- if(typefd[ft] && f->op == OCONST) {
- /* TO DO: pick up special constants, possibly preloaded */
- if(f->fconst == 0.0){
- regalloc(&nod, t, t);
- gins(AXORPD, &nod, &nod);
- gmove(&nod, t);
- regfree(&nod);
- return;
- }
- }
-/*
- * load
- */
- if(ft == TVLONG || ft == TUVLONG)
- if(f->op == OCONST)
- if(f->vconst > 0x7fffffffLL || f->vconst < -0x7fffffffLL)
- if(t->op != OREGISTER) {
- regalloc(&nod, f, Z);
- gmove(f, &nod);
- gmove(&nod, t);
- regfree(&nod);
- return;
- }
-
- if(f->op == ONAME || f->op == OINDREG ||
- f->op == OIND || f->op == OINDEX)
- switch(ft) {
- case TCHAR:
- a = AMOVBLSX;
- if(t64)
- a = AMOVBQSX;
- goto ld;
- case TUCHAR:
- a = AMOVBLZX;
- if(t64)
- a = AMOVBQZX;
- goto ld;
- case TSHORT:
- a = AMOVWLSX;
- if(t64)
- a = AMOVWQSX;
- goto ld;
- case TUSHORT:
- a = AMOVWLZX;
- if(t64)
- a = AMOVWQZX;
- goto ld;
- case TINT:
- case TLONG:
- if(typefd[tt]) {
- regalloc(&nod, t, t);
- if(tt == TDOUBLE)
- a = ACVTSL2SD;
- else
- a = ACVTSL2SS;
- gins(a, f, &nod);
- gmove(&nod, t);
- regfree(&nod);
- return;
- }
- a = AMOVL;
- if(t64)
- a = AMOVLQSX;
- goto ld;
- case TUINT:
- case TULONG:
- a = AMOVL;
- if(t64)
- a = AMOVLQZX; /* could probably use plain MOVL */
- goto ld;
- case TVLONG:
- if(typefd[tt]) {
- regalloc(&nod, t, t);
- if(tt == TDOUBLE)
- a = ACVTSQ2SD;
- else
- a = ACVTSQ2SS;
- gins(a, f, &nod);
- gmove(&nod, t);
- regfree(&nod);
- return;
- }
- case TUVLONG:
- a = AMOVQ;
- goto ld;
- case TIND:
- a = AMOVQ;
- if(ewidth[TIND] == 4)
- a = AMOVL;
-
- ld:
- regalloc(&nod, f, t);
- nod.type = t64? types[TVLONG]: types[TINT];
- gins(a, f, &nod);
- gmove(&nod, t);
- regfree(&nod);
- return;
-
- case TFLOAT:
- a = AMOVSS;
- goto fld;
- case TDOUBLE:
- a = AMOVSD;
- fld:
- regalloc(&nod, f, t);
- if(tt != TDOUBLE && tt != TFLOAT){ /* TO DO: why is this here */
- prtree(f, "odd tree");
- nod.type = t64? types[TVLONG]: types[TINT];
- }
- gins(a, f, &nod);
- gmove(&nod, t);
- regfree(&nod);
- return;
- }
-
-/*
- * store
- */
- if(t->op == ONAME || t->op == OINDREG ||
- t->op == OIND || t->op == OINDEX)
- switch(tt) {
- case TCHAR:
- case TUCHAR:
- a = AMOVB; goto st;
- case TSHORT:
- case TUSHORT:
- a = AMOVW; goto st;
- case TINT:
- case TUINT:
- case TLONG:
- case TULONG:
- a = AMOVL; goto st;
- case TVLONG:
- case TUVLONG:
- case TIND:
- a = AMOVQ; goto st;
-
- st:
- if(f->op == OCONST) {
- gins(a, f, t);
- return;
- }
- fst:
- regalloc(&nod, t, f);
- gmove(f, &nod);
- gins(a, &nod, t);
- regfree(&nod);
- return;
-
- case TFLOAT:
- a = AMOVSS;
- goto fst;
- case TDOUBLE:
- a = AMOVSD;
- goto fst;
- }
-
-/*
- * convert
- */
- switch(CASE(ft,tt)) {
- default:
-/*
- * integer to integer
- ********
- a = AGOK; break;
-
- case CASE( TCHAR, TCHAR):
- case CASE( TUCHAR, TCHAR):
- case CASE( TSHORT, TCHAR):
- case CASE( TUSHORT,TCHAR):
- case CASE( TINT, TCHAR):
- case CASE( TUINT, TCHAR):
- case CASE( TLONG, TCHAR):
- case CASE( TULONG, TCHAR):
-
- case CASE( TCHAR, TUCHAR):
- case CASE( TUCHAR, TUCHAR):
- case CASE( TSHORT, TUCHAR):
- case CASE( TUSHORT,TUCHAR):
- case CASE( TINT, TUCHAR):
- case CASE( TUINT, TUCHAR):
- case CASE( TLONG, TUCHAR):
- case CASE( TULONG, TUCHAR):
-
- case CASE( TSHORT, TSHORT):
- case CASE( TUSHORT,TSHORT):
- case CASE( TINT, TSHORT):
- case CASE( TUINT, TSHORT):
- case CASE( TLONG, TSHORT):
- case CASE( TULONG, TSHORT):
-
- case CASE( TSHORT, TUSHORT):
- case CASE( TUSHORT,TUSHORT):
- case CASE( TINT, TUSHORT):
- case CASE( TUINT, TUSHORT):
- case CASE( TLONG, TUSHORT):
- case CASE( TULONG, TUSHORT):
-
- case CASE( TINT, TINT):
- case CASE( TUINT, TINT):
- case CASE( TLONG, TINT):
- case CASE( TULONG, TINT):
-
- case CASE( TINT, TUINT):
- case CASE( TUINT, TUINT):
- case CASE( TLONG, TUINT):
- case CASE( TULONG, TUINT):
- *****/
- a = AMOVL;
- break;
-
- case CASE( TINT, TIND):
- case CASE( TINT, TVLONG):
- case CASE( TINT, TUVLONG):
- case CASE( TLONG, TIND):
- case CASE( TLONG, TVLONG):
- case CASE( TLONG, TUVLONG):
- a = AMOVLQSX;
- if(f->op == OCONST) {
- f->vconst &= (uvlong)0xffffffffU;
- if(f->vconst & 0x80000000)
- f->vconst |= (vlong)0xffffffff << 32;
- a = AMOVQ;
- }
- break;
-
- case CASE( TUINT, TIND):
- case CASE( TUINT, TVLONG):
- case CASE( TUINT, TUVLONG):
- case CASE( TULONG, TVLONG):
- case CASE( TULONG, TUVLONG):
- case CASE( TULONG, TIND):
- a = AMOVLQZX;
- if(f->op == OCONST) {
- f->vconst &= (uvlong)0xffffffffU;
- a = AMOVQ;
- }
- break;
-
- case CASE( TIND, TCHAR):
- case CASE( TIND, TUCHAR):
- case CASE( TIND, TSHORT):
- case CASE( TIND, TUSHORT):
- case CASE( TIND, TINT):
- case CASE( TIND, TUINT):
- case CASE( TIND, TLONG):
- case CASE( TIND, TULONG):
- case CASE( TVLONG, TCHAR):
- case CASE( TVLONG, TUCHAR):
- case CASE( TVLONG, TSHORT):
- case CASE( TVLONG, TUSHORT):
- case CASE( TVLONG, TINT):
- case CASE( TVLONG, TUINT):
- case CASE( TVLONG, TLONG):
- case CASE( TVLONG, TULONG):
- case CASE( TUVLONG, TCHAR):
- case CASE( TUVLONG, TUCHAR):
- case CASE( TUVLONG, TSHORT):
- case CASE( TUVLONG, TUSHORT):
- case CASE( TUVLONG, TINT):
- case CASE( TUVLONG, TUINT):
- case CASE( TUVLONG, TLONG):
- case CASE( TUVLONG, TULONG):
- a = AMOVQL;
- if(f->op == OCONST) {
- f->vconst &= (int)0xffffffffU;
- a = AMOVL;
- }
- break;
-
- case CASE( TIND, TIND):
- case CASE( TIND, TVLONG):
- case CASE( TIND, TUVLONG):
- case CASE( TVLONG, TIND):
- case CASE( TVLONG, TVLONG):
- case CASE( TVLONG, TUVLONG):
- case CASE( TUVLONG, TIND):
- case CASE( TUVLONG, TVLONG):
- case CASE( TUVLONG, TUVLONG):
- a = AMOVQ;
- break;
-
- case CASE( TSHORT, TINT):
- case CASE( TSHORT, TUINT):
- case CASE( TSHORT, TLONG):
- case CASE( TSHORT, TULONG):
- a = AMOVWLSX;
- if(f->op == OCONST) {
- f->vconst &= 0xffff;
- if(f->vconst & 0x8000)
- f->vconst |= 0xffff0000;
- a = AMOVL;
- }
- break;
-
- case CASE( TSHORT, TVLONG):
- case CASE( TSHORT, TUVLONG):
- case CASE( TSHORT, TIND):
- a = AMOVWQSX;
- if(f->op == OCONST) {
- f->vconst &= 0xffff;
- if(f->vconst & 0x8000){
- f->vconst |= 0xffff0000;
- f->vconst |= (vlong)~0 << 32;
- }
- a = AMOVL;
- }
- break;
-
- case CASE( TUSHORT,TINT):
- case CASE( TUSHORT,TUINT):
- case CASE( TUSHORT,TLONG):
- case CASE( TUSHORT,TULONG):
- a = AMOVWLZX;
- if(f->op == OCONST) {
- f->vconst &= 0xffff;
- a = AMOVL;
- }
- break;
-
- case CASE( TUSHORT,TVLONG):
- case CASE( TUSHORT,TUVLONG):
- case CASE( TUSHORT,TIND):
- a = AMOVWQZX;
- if(f->op == OCONST) {
- f->vconst &= 0xffff;
- a = AMOVL; /* MOVL also zero-extends to 64 bits */
- }
- break;
-
- case CASE( TCHAR, TSHORT):
- case CASE( TCHAR, TUSHORT):
- case CASE( TCHAR, TINT):
- case CASE( TCHAR, TUINT):
- case CASE( TCHAR, TLONG):
- case CASE( TCHAR, TULONG):
- a = AMOVBLSX;
- if(f->op == OCONST) {
- f->vconst &= 0xff;
- if(f->vconst & 0x80)
- f->vconst |= 0xffffff00;
- a = AMOVL;
- }
- break;
-
- case CASE( TCHAR, TVLONG):
- case CASE( TCHAR, TUVLONG):
- case CASE( TCHAR, TIND):
- a = AMOVBQSX;
- if(f->op == OCONST) {
- f->vconst &= 0xff;
- if(f->vconst & 0x80){
- f->vconst |= 0xffffff00;
- f->vconst |= (vlong)~0 << 32;
- }
- a = AMOVQ;
- }
- break;
-
- case CASE( TUCHAR, TSHORT):
- case CASE( TUCHAR, TUSHORT):
- case CASE( TUCHAR, TINT):
- case CASE( TUCHAR, TUINT):
- case CASE( TUCHAR, TLONG):
- case CASE( TUCHAR, TULONG):
- a = AMOVBLZX;
- if(f->op == OCONST) {
- f->vconst &= 0xff;
- a = AMOVL;
- }
- break;
-
- case CASE( TUCHAR, TVLONG):
- case CASE( TUCHAR, TUVLONG):
- case CASE( TUCHAR, TIND):
- a = AMOVBQZX;
- if(f->op == OCONST) {
- f->vconst &= 0xff;
- a = AMOVL; /* zero-extends to 64-bits */
- }
- break;
-
-/*
- * float to fix
- */
- case CASE( TFLOAT, TCHAR):
- case CASE( TFLOAT, TUCHAR):
- case CASE( TFLOAT, TSHORT):
- case CASE( TFLOAT, TUSHORT):
- case CASE( TFLOAT, TINT):
- case CASE( TFLOAT, TUINT):
- case CASE( TFLOAT, TLONG):
- case CASE( TFLOAT, TULONG):
- case CASE( TFLOAT, TVLONG):
- case CASE( TFLOAT, TUVLONG):
- case CASE( TFLOAT, TIND):
-
- case CASE( TDOUBLE,TCHAR):
- case CASE( TDOUBLE,TUCHAR):
- case CASE( TDOUBLE,TSHORT):
- case CASE( TDOUBLE,TUSHORT):
- case CASE( TDOUBLE,TINT):
- case CASE( TDOUBLE,TUINT):
- case CASE( TDOUBLE,TLONG):
- case CASE( TDOUBLE,TULONG):
- case CASE( TDOUBLE,TVLONG):
- case CASE( TDOUBLE,TUVLONG):
- case CASE( TDOUBLE,TIND):
- regalloc(&nod, t, Z);
- if(ewidth[tt] == SZ_VLONG || typeu[tt] && ewidth[tt] == SZ_INT){
- if(ft == TFLOAT)
- a = ACVTTSS2SQ;
- else
- a = ACVTTSD2SQ;
- }else{
- if(ft == TFLOAT)
- a = ACVTTSS2SL;
- else
- a = ACVTTSD2SL;
- }
- gins(a, f, &nod);
- gmove(&nod, t);
- regfree(&nod);
- return;
-
-/*
- * uvlong to float
- */
- case CASE( TUVLONG, TDOUBLE):
- case CASE( TUVLONG, TFLOAT):
- a = ACVTSQ2SS;
- if(tt == TDOUBLE)
- a = ACVTSQ2SD;
- regalloc(&nod, f, f);
- gmove(f, &nod);
- regalloc(&nod1, t, t);
- gins(ACMPQ, &nod, nodconst(0));
- gins(AJLT, Z, Z);
- p1 = p;
- gins(a, &nod, &nod1);
- gins(AJMP, Z, Z);
- p2 = p;
- patch(p1, pc);
- regalloc(&nod2, f, Z);
- regalloc(&nod3, f, Z);
- gmove(&nod, &nod2);
- gins(ASHRQ, nodconst(1), &nod2);
- gmove(&nod, &nod3);
- gins(AANDL, nodconst(1), &nod3);
- gins(AORQ, &nod3, &nod2);
- gins(a, &nod2, &nod1);
- gins(tt == TDOUBLE? AADDSD: AADDSS, &nod1, &nod1);
- regfree(&nod2);
- regfree(&nod3);
- patch(p2, pc);
- regfree(&nod);
- regfree(&nod1);
- return;
-
- case CASE( TULONG, TDOUBLE):
- case CASE( TUINT, TDOUBLE):
- case CASE( TULONG, TFLOAT):
- case CASE( TUINT, TFLOAT):
- a = ACVTSQ2SS;
- if(tt == TDOUBLE)
- a = ACVTSQ2SD;
- regalloc(&nod, f, f);
- gins(AMOVLQZX, f, &nod);
- regalloc(&nod1, t, t);
- gins(a, &nod, &nod1);
- gmove(&nod1, t);
- regfree(&nod);
- regfree(&nod1);
- return;
-
-/*
- * fix to float
- */
- case CASE( TCHAR, TFLOAT):
- case CASE( TUCHAR, TFLOAT):
- case CASE( TSHORT, TFLOAT):
- case CASE( TUSHORT,TFLOAT):
- case CASE( TINT, TFLOAT):
- case CASE( TLONG, TFLOAT):
- case CASE( TVLONG, TFLOAT):
- case CASE( TIND, TFLOAT):
-
- case CASE( TCHAR, TDOUBLE):
- case CASE( TUCHAR, TDOUBLE):
- case CASE( TSHORT, TDOUBLE):
- case CASE( TUSHORT,TDOUBLE):
- case CASE( TINT, TDOUBLE):
- case CASE( TLONG, TDOUBLE):
- case CASE( TVLONG, TDOUBLE):
- case CASE( TIND, TDOUBLE):
- regalloc(&nod, t, t);
- if(ewidth[ft] == SZ_VLONG){
- if(tt == TFLOAT)
- a = ACVTSQ2SS;
- else
- a = ACVTSQ2SD;
- }else{
- if(tt == TFLOAT)
- a = ACVTSL2SS;
- else
- a = ACVTSL2SD;
- }
- gins(a, f, &nod);
- gmove(&nod, t);
- regfree(&nod);
- return;
-
-/*
- * float to float
- */
- case CASE( TFLOAT, TFLOAT):
- a = AMOVSS;
- break;
- case CASE( TDOUBLE,TFLOAT):
- a = ACVTSD2SS;
- break;
- case CASE( TFLOAT, TDOUBLE):
- a = ACVTSS2SD;
- break;
- case CASE( TDOUBLE,TDOUBLE):
- a = AMOVSD;
- break;
- }
- if(a == AMOVQ || a == AMOVSD || a == AMOVSS || a == AMOVL && ewidth[ft] == ewidth[tt]) /* TO DO: check AMOVL */
- if(samaddr(f, t))
- return;
- gins(a, f, t);
-}
-
-void
-doindex(Node *n)
-{
- Node nod, nod1;
- int32 v;
-
-if(debug['Y'])
-prtree(n, "index");
-
-if(n->left->complex >= FNX)
-print("botch in doindex\n");
-
- regalloc(&nod, &qregnode, Z);
- v = constnode.vconst;
- cgen(n->right, &nod);
- idx.ptr = D_NONE;
- if(n->left->op == OCONST)
- idx.ptr = D_CONST;
- else if(n->left->op == OREGISTER)
- idx.ptr = n->left->reg;
- else if(n->left->op != OADDR) {
- reg[D_BP]++; // can't be used as a base
- regalloc(&nod1, &qregnode, Z);
- cgen(n->left, &nod1);
- idx.ptr = nod1.reg;
- regfree(&nod1);
- reg[D_BP]--;
- }
- idx.reg = nod.reg;
- regfree(&nod);
- constnode.vconst = v;
-}
-
-void
-gins(int a, Node *f, Node *t)
-{
-
- if(f != Z && f->op == OINDEX)
- doindex(f);
- if(t != Z && t->op == OINDEX)
- doindex(t);
- nextpc();
- p->as = a;
- if(f != Z)
- naddr(f, &p->from);
- if(t != Z)
- naddr(t, &p->to);
- if(debug['g'])
- print("%P\n", p);
-}
-
-void
-gopcode(int o, Type *ty, Node *f, Node *t)
-{
- int a, et;
-
- et = TLONG;
- if(ty != T)
- et = ty->etype;
- if(et == TIND && ewidth[TIND] == 4)
- et = TUINT;
- if(debug['M']) {
- if(f != Z && f->type != T)
- print("gop: %O %O[%s],", o, f->op, tnames[et]);
- else
- print("gop: %O Z,", o);
- if(t != Z && t->type != T)
- print("%O[%s]\n", t->op, tnames[t->type->etype]);
- else
- print("Z\n");
- }
- a = AGOK;
- switch(o) {
- case OCOM:
- a = ANOTL;
- if(et == TCHAR || et == TUCHAR)
- a = ANOTB;
- if(et == TSHORT || et == TUSHORT)
- a = ANOTW;
- if(et == TVLONG || et == TUVLONG || et == TIND)
- a = ANOTQ;
- break;
-
- case ONEG:
- a = ANEGL;
- if(et == TCHAR || et == TUCHAR)
- a = ANEGB;
- if(et == TSHORT || et == TUSHORT)
- a = ANEGW;
- if(et == TVLONG || et == TUVLONG || et == TIND)
- a = ANEGQ;
- break;
-
- case OADDR:
- a = ALEAQ;
- break;
-
- case OASADD:
- case OADD:
- a = AADDL;
- if(et == TCHAR || et == TUCHAR)
- a = AADDB;
- if(et == TSHORT || et == TUSHORT)
- a = AADDW;
- if(et == TVLONG || et == TUVLONG || et == TIND)
- a = AADDQ;
- if(et == TFLOAT)
- a = AADDSS;
- if(et == TDOUBLE)
- a = AADDSD;
- break;
-
- case OASSUB:
- case OSUB:
- a = ASUBL;
- if(et == TCHAR || et == TUCHAR)
- a = ASUBB;
- if(et == TSHORT || et == TUSHORT)
- a = ASUBW;
- if(et == TVLONG || et == TUVLONG || et == TIND)
- a = ASUBQ;
- if(et == TFLOAT)
- a = ASUBSS;
- if(et == TDOUBLE)
- a = ASUBSD;
- break;
-
- case OASOR:
- case OOR:
- a = AORL;
- if(et == TCHAR || et == TUCHAR)
- a = AORB;
- if(et == TSHORT || et == TUSHORT)
- a = AORW;
- if(et == TVLONG || et == TUVLONG || et == TIND)
- a = AORQ;
- break;
-
- case OASAND:
- case OAND:
- a = AANDL;
- if(et == TCHAR || et == TUCHAR)
- a = AANDB;
- if(et == TSHORT || et == TUSHORT)
- a = AANDW;
- if(et == TVLONG || et == TUVLONG || et == TIND)
- a = AANDQ;
- break;
-
- case OASXOR:
- case OXOR:
- a = AXORL;
- if(et == TCHAR || et == TUCHAR)
- a = AXORB;
- if(et == TSHORT || et == TUSHORT)
- a = AXORW;
- if(et == TVLONG || et == TUVLONG || et == TIND)
- a = AXORQ;
- break;
-
- case OASLSHR:
- case OLSHR:
- a = ASHRL;
- if(et == TCHAR || et == TUCHAR)
- a = ASHRB;
- if(et == TSHORT || et == TUSHORT)
- a = ASHRW;
- if(et == TVLONG || et == TUVLONG || et == TIND)
- a = ASHRQ;
- break;
-
- case OASASHR:
- case OASHR:
- a = ASARL;
- if(et == TCHAR || et == TUCHAR)
- a = ASARB;
- if(et == TSHORT || et == TUSHORT)
- a = ASARW;
- if(et == TVLONG || et == TUVLONG || et == TIND)
- a = ASARQ;
- break;
-
- case OASASHL:
- case OASHL:
- a = ASALL;
- if(et == TCHAR || et == TUCHAR)
- a = ASALB;
- if(et == TSHORT || et == TUSHORT)
- a = ASALW;
- if(et == TVLONG || et == TUVLONG || et == TIND)
- a = ASALQ;
- break;
-
- case OROTL:
- a = AROLL;
- if(et == TCHAR || et == TUCHAR)
- a = AROLB;
- if(et == TSHORT || et == TUSHORT)
- a = AROLW;
- if(et == TVLONG || et == TUVLONG || et == TIND)
- a = AROLQ;
- break;
-
- case OFUNC:
- a = ACALL;
- break;
-
- case OASMUL:
- case OMUL:
- if(f->op == OREGISTER && t != Z && isreg(t, D_AX) && reg[D_DX] == 0)
- t = Z;
- a = AIMULL;
- if(et == TVLONG || et == TUVLONG || et == TIND)
- a = AIMULQ;
- if(et == TFLOAT)
- a = AMULSS;
- if(et == TDOUBLE)
- a = AMULSD;
- break;
-
- case OASMOD:
- case OMOD:
- case OASDIV:
- case ODIV:
- a = AIDIVL;
- if(et == TVLONG || et == TUVLONG || et == TIND)
- a = AIDIVQ;
- if(et == TFLOAT)
- a = ADIVSS;
- if(et == TDOUBLE)
- a = ADIVSD;
- break;
-
- case OASLMUL:
- case OLMUL:
- a = AMULL;
- if(et == TVLONG || et == TUVLONG || et == TIND)
- a = AMULQ;
- break;
-
- case OASLMOD:
- case OLMOD:
- case OASLDIV:
- case OLDIV:
- a = ADIVL;
- if(et == TVLONG || et == TUVLONG || et == TIND)
- a = ADIVQ;
- break;
-
- case OEQ:
- case ONE:
- case OLT:
- case OLE:
- case OGE:
- case OGT:
- case OLO:
- case OLS:
- case OHS:
- case OHI:
- a = ACMPL;
- if(et == TCHAR || et == TUCHAR)
- a = ACMPB;
- if(et == TSHORT || et == TUSHORT)
- a = ACMPW;
- if(et == TVLONG || et == TUVLONG || et == TIND)
- a = ACMPQ;
- if(et == TFLOAT)
- a = AUCOMISS;
- if(et == TDOUBLE)
- a = AUCOMISD;
- gins(a, f, t);
- switch(o) {
- case OEQ: a = AJEQ; break;
- case ONE: a = AJNE; break;
- case OLT: a = AJLT; break;
- case OLE: a = AJLE; break;
- case OGE: a = AJGE; break;
- case OGT: a = AJGT; break;
- case OLO: a = AJCS; break;
- case OLS: a = AJLS; break;
- case OHS: a = AJCC; break;
- case OHI: a = AJHI; break;
- }
- gins(a, Z, Z);
- return;
- }
- if(a == AGOK)
- diag(Z, "bad in gopcode %O", o);
- gins(a, f, t);
-}
-
-int
-samaddr(Node *f, Node *t)
-{
- return f->op == OREGISTER && t->op == OREGISTER && f->reg == t->reg;
-}
-
-void
-gbranch(int o)
-{
- int a;
-
- a = AGOK;
- switch(o) {
- case ORETURN:
- a = ARET;
- break;
- case OGOTO:
- a = AJMP;
- break;
- }
- nextpc();
- if(a == AGOK) {
- diag(Z, "bad in gbranch %O", o);
- nextpc();
- }
- p->as = a;
-}
-
-void
-patch(Prog *op, int32 pc)
-{
- op->to.offset = pc;
- op->to.type = D_BRANCH;
- op->to.u.branch = nil;
- op->pcond = nil;
-}
-
-void
-gpseudo(int a, Sym *s, Node *n)
-{
-
- nextpc();
- p->as = a;
- p->from.type = D_EXTERN;
- p->from.sym = linksym(s);
-
- switch(a) {
- case ATEXT:
- p->from.scale = textflag;
- textflag = 0;
- break;
- case AGLOBL:
- p->from.scale = s->dataflag;
- break;
- }
-
- if(s->class == CSTATIC)
- p->from.type = D_STATIC;
- naddr(n, &p->to);
- if(a == ADATA || a == AGLOBL)
- pc--;
-}
-
-void
-gpcdata(int index, int value)
-{
- Node n1;
-
- n1 = *nodconst(index);
- gins(APCDATA, &n1, nodconst(value));
-}
-
-void
-gprefetch(Node *n)
-{
- Node n1;
-
- regalloc(&n1, n, Z);
- gmove(n, &n1);
- n1.op = OINDREG;
- gins(APREFETCHNTA, &n1, Z);
- regfree(&n1);
-}
-
-int
-sconst(Node *n)
-{
- int32 v;
-
- if(n->op == OCONST && !typefd[n->type->etype]) {
- v = n->vconst;
- if(v >= -32766L && v < 32766L)
- return 1;
- }
- return 0;
-}
-
-int32
-exreg(Type *t)
-{
- int32 o;
-
- if(typechlpv[t->etype]) {
- if(exregoffset >= 64)
- return 0;
- o = exregoffset;
- exregoffset += ewidth[TIND];
- return o+1; // +1 to avoid 0 == failure; naddr's case OEXREG will subtract 1.
- }
- return 0;
-}
-
-schar ewidth[NTYPE] =
-{
- -1, /*[TXXX]*/
- SZ_CHAR, /*[TCHAR]*/
- SZ_CHAR, /*[TUCHAR]*/
- SZ_SHORT, /*[TSHORT]*/
- SZ_SHORT, /*[TUSHORT]*/
- SZ_INT, /*[TINT]*/
- SZ_INT, /*[TUINT]*/
- SZ_LONG, /*[TLONG]*/
- SZ_LONG, /*[TULONG]*/
- SZ_VLONG, /*[TVLONG]*/
- SZ_VLONG, /*[TUVLONG]*/
- SZ_FLOAT, /*[TFLOAT]*/
- SZ_DOUBLE, /*[TDOUBLE]*/
- SZ_IND, /*[TIND]*/
- 0, /*[TFUNC]*/
- -1, /*[TARRAY]*/
- 0, /*[TVOID]*/
- -1, /*[TSTRUCT]*/
- -1, /*[TUNION]*/
- SZ_INT, /*[TENUM]*/
-};
-int32 ncast[NTYPE] =
-{
- 0, /*[TXXX]*/
- BCHAR|BUCHAR, /*[TCHAR]*/
- BCHAR|BUCHAR, /*[TUCHAR]*/
- BSHORT|BUSHORT, /*[TSHORT]*/
- BSHORT|BUSHORT, /*[TUSHORT]*/
- BINT|BUINT|BLONG|BULONG, /*[TINT]*/
- BINT|BUINT|BLONG|BULONG, /*[TUINT]*/
- BINT|BUINT|BLONG|BULONG, /*[TLONG]*/
- BINT|BUINT|BLONG|BULONG, /*[TULONG]*/
- BVLONG|BUVLONG|BIND, /*[TVLONG]*/
- BVLONG|BUVLONG|BIND, /*[TUVLONG]*/
- BFLOAT, /*[TFLOAT]*/
- BDOUBLE, /*[TDOUBLE]*/
- BVLONG|BUVLONG|BIND, /*[TIND]*/
- 0, /*[TFUNC]*/
- 0, /*[TARRAY]*/
- 0, /*[TVOID]*/
- BSTRUCT, /*[TSTRUCT]*/
- BUNION, /*[TUNION]*/
- 0, /*[TENUM]*/
-};
diff --git a/src/cmd/8c/Makefile b/src/cmd/8c/Makefile
deleted file mode 100644
index 3f528d751..000000000
--- a/src/cmd/8c/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-# Copyright 2012 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../Make.dist
diff --git a/src/cmd/8c/cgen.c b/src/cmd/8c/cgen.c
deleted file mode 100644
index 87e8fdad8..000000000
--- a/src/cmd/8c/cgen.c
+++ /dev/null
@@ -1,1939 +0,0 @@
-// Inferno utils/8c/cgen.c
-// http://code.google.com/p/inferno-os/source/browse/utils/8c/cgen.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-#include "../../runtime/funcdata.h"
-
-/* ,x/^(print|prtree)\(/i/\/\/ */
-
-void
-cgen(Node *n, Node *nn)
-{
- Node *l, *r, *t;
- Prog *p1;
- Node nod, nod1, nod2, nod3, nod4;
- int o, hardleft;
- int32 v, curs;
- vlong c;
-
- if(debug['g']) {
- prtree(nn, "cgen lhs");
- prtree(n, "cgen");
- }
- if(n == Z || n->type == T)
- return;
- if(typesuv[n->type->etype] && (n->op != OFUNC || nn != Z)) {
- sugen(n, nn, n->type->width);
- return;
- }
- l = n->left;
- r = n->right;
- o = n->op;
-
- if(n->op == OEXREG || (nn != Z && nn->op == OEXREG)) {
- gmove(n, nn);
- return;
- }
-
- if(n->addable >= INDEXED) {
- if(nn == Z) {
- switch(o) {
- default:
- nullwarn(Z, Z);
- break;
- case OINDEX:
- nullwarn(l, r);
- break;
- }
- return;
- }
- gmove(n, nn);
- return;
- }
- curs = cursafe;
-
- if(l->complex >= FNX)
- if(r != Z && r->complex >= FNX)
- switch(o) {
- default:
- if(cond(o) && typesuv[l->type->etype])
- break;
-
- regret(&nod, r, 0, 0);
- cgen(r, &nod);
-
- regsalloc(&nod1, r);
- gmove(&nod, &nod1);
-
- regfree(&nod);
- nod = *n;
- nod.right = &nod1;
-
- cgen(&nod, nn);
- return;
-
- case OFUNC:
- case OCOMMA:
- case OANDAND:
- case OOROR:
- case OCOND:
- case ODOT:
- break;
- }
-
- hardleft = l->addable < INDEXED || l->complex >= FNX;
- switch(o) {
- default:
- diag(n, "unknown op in cgen: %O", o);
- break;
-
- case ONEG:
- case OCOM:
- if(nn == Z) {
- nullwarn(l, Z);
- break;
- }
- regalloc(&nod, l, nn);
- cgen(l, &nod);
- gopcode(o, n->type, Z, &nod);
- gmove(&nod, nn);
- regfree(&nod);
- break;
-
- case OAS:
- if(typefd[n->type->etype]) {
- cgen(r, &fregnode0);
- if(nn != Z)
- gins(AFMOVD, &fregnode0, &fregnode0);
- if(l->addable < INDEXED) {
- reglcgen(&nod, l, Z);
- gmove(&fregnode0, &nod);
- regfree(&nod);
- } else
- gmove(&fregnode0, l);
- if(nn != Z)
- gmove(&fregnode0, nn);
- return;
- }
- if(l->op == OBIT)
- goto bitas;
- if(!hardleft) {
- if(nn != Z || r->addable < INDEXED) {
- if(r->complex >= FNX && nn == Z)
- regret(&nod, r, 0, 0);
- else
- regalloc(&nod, r, nn);
- cgen(r, &nod);
- gmove(&nod, l);
- if(nn != Z)
- gmove(&nod, nn);
- regfree(&nod);
- } else
- gmove(r, l);
- break;
- }
- if(l->complex >= r->complex) {
- if(l->op == OINDEX && r->op == OCONST) {
- gmove(r, l);
- break;
- }
- reglcgen(&nod1, l, Z);
- if(r->addable >= INDEXED) {
- gmove(r, &nod1);
- if(nn != Z)
- gmove(r, nn);
- regfree(&nod1);
- break;
- }
- regalloc(&nod, r, nn);
- cgen(r, &nod);
- } else {
- regalloc(&nod, r, nn);
- cgen(r, &nod);
- reglcgen(&nod1, l, Z);
- }
- gmove(&nod, &nod1);
- regfree(&nod);
- regfree(&nod1);
- break;
-
- bitas:
- n = l->left;
- regalloc(&nod, r, nn);
- if(l->complex >= r->complex) {
- reglcgen(&nod1, n, Z);
- cgen(r, &nod);
- } else {
- cgen(r, &nod);
- reglcgen(&nod1, n, Z);
- }
- regalloc(&nod2, n, Z);
- gmove(&nod1, &nod2);
- bitstore(l, &nod, &nod1, &nod2, nn);
- break;
-
- case OBIT:
- if(nn == Z) {
- nullwarn(l, Z);
- break;
- }
- bitload(n, &nod, Z, Z, nn);
- gmove(&nod, nn);
- regfree(&nod);
- break;
-
- case OLSHR:
- case OASHL:
- case OASHR:
- if(nn == Z) {
- nullwarn(l, r);
- break;
- }
- if(r->op == OCONST) {
- if(r->vconst == 0) {
- cgen(l, nn);
- break;
- }
- regalloc(&nod, l, nn);
- cgen(l, &nod);
- if(o == OASHL && r->vconst == 1)
- gopcode(OADD, n->type, &nod, &nod);
- else
- gopcode(o, n->type, r, &nod);
- gmove(&nod, nn);
- regfree(&nod);
- break;
- }
-
- /*
- * get nod to be D_CX
- */
- if(nodreg(&nod, nn, D_CX)) {
- regsalloc(&nod1, n);
- gmove(&nod, &nod1);
- cgen(n, &nod); /* probably a bug */
- gmove(&nod, nn);
- gmove(&nod1, &nod);
- break;
- }
- reg[D_CX]++;
- if(nn->op == OREGISTER && nn->reg == D_CX)
- regalloc(&nod1, l, Z);
- else
- regalloc(&nod1, l, nn);
- if(r->complex >= l->complex) {
- cgen(r, &nod);
- cgen(l, &nod1);
- } else {
- cgen(l, &nod1);
- cgen(r, &nod);
- }
- gopcode(o, n->type, &nod, &nod1);
- gmove(&nod1, nn);
- regfree(&nod);
- regfree(&nod1);
- break;
-
- case OADD:
- case OSUB:
- case OOR:
- case OXOR:
- case OAND:
- if(nn == Z) {
- nullwarn(l, r);
- break;
- }
- if(typefd[n->type->etype])
- goto fop;
- if(r->op == OCONST) {
- if(r->vconst == 0 && o != OAND) {
- cgen(l, nn);
- break;
- }
- }
- if(n->op == OOR && l->op == OASHL && r->op == OLSHR
- && l->right->op == OCONST && r->right->op == OCONST
- && l->left->op == ONAME && r->left->op == ONAME
- && l->left->sym == r->left->sym
- && l->right->vconst + r->right->vconst == 8 * l->left->type->width) {
- regalloc(&nod, l->left, nn);
- cgen(l->left, &nod);
- gopcode(OROTL, n->type, l->right, &nod);
- gmove(&nod, nn);
- regfree(&nod);
- break;
- }
- if(n->op == OADD && l->op == OASHL && l->right->op == OCONST
- && (r->op != OCONST || r->vconst < -128 || r->vconst > 127)) {
- c = l->right->vconst;
- if(c > 0 && c <= 3) {
- if(l->left->complex >= r->complex) {
- regalloc(&nod, l->left, nn);
- cgen(l->left, &nod);
- if(r->addable < INDEXED) {
- regalloc(&nod1, r, Z);
- cgen(r, &nod1);
- genmuladd(&nod, &nod, 1 << c, &nod1);
- regfree(&nod1);
- }
- else
- genmuladd(&nod, &nod, 1 << c, r);
- }
- else {
- regalloc(&nod, r, nn);
- cgen(r, &nod);
- regalloc(&nod1, l->left, Z);
- cgen(l->left, &nod1);
- genmuladd(&nod, &nod1, 1 << c, &nod);
- regfree(&nod1);
- }
- gmove(&nod, nn);
- regfree(&nod);
- break;
- }
- }
- if(r->addable >= INDEXED) {
- regalloc(&nod, l, nn);
- cgen(l, &nod);
- gopcode(o, n->type, r, &nod);
- gmove(&nod, nn);
- regfree(&nod);
- break;
- }
- if(l->complex >= r->complex) {
- regalloc(&nod, l, nn);
- cgen(l, &nod);
- regalloc(&nod1, r, Z);
- cgen(r, &nod1);
- gopcode(o, n->type, &nod1, &nod);
- } else {
- regalloc(&nod1, r, nn);
- cgen(r, &nod1);
- regalloc(&nod, l, Z);
- cgen(l, &nod);
- gopcode(o, n->type, &nod1, &nod);
- }
- gmove(&nod, nn);
- regfree(&nod);
- regfree(&nod1);
- break;
-
- case OLMOD:
- case OMOD:
- case OLMUL:
- case OLDIV:
- case OMUL:
- case ODIV:
- if(nn == Z) {
- nullwarn(l, r);
- break;
- }
- if(typefd[n->type->etype])
- goto fop;
- if(r->op == OCONST) {
- SET(v);
- switch(o) {
- case ODIV:
- case OMOD:
- c = r->vconst;
- if(c < 0)
- c = -c;
- v = xlog2(c);
- if(v < 0)
- break;
- /* fall thru */
- case OMUL:
- case OLMUL:
- regalloc(&nod, l, nn);
- cgen(l, &nod);
- switch(o) {
- case OMUL:
- case OLMUL:
- mulgen(n->type, r, &nod);
- break;
- case ODIV:
- sdiv2(r->vconst, v, l, &nod);
- break;
- case OMOD:
- smod2(r->vconst, v, l, &nod);
- break;
- }
- gmove(&nod, nn);
- regfree(&nod);
- goto done;
- case OLDIV:
- c = r->vconst;
- if((c & 0x80000000) == 0)
- break;
- regalloc(&nod1, l, Z);
- cgen(l, &nod1);
- regalloc(&nod, l, nn);
- zeroregm(&nod);
- gins(ACMPL, &nod1, nodconst(c));
- gins(ASBBL, nodconst(-1), &nod);
- regfree(&nod1);
- gmove(&nod, nn);
- regfree(&nod);
- goto done;
- }
- }
-
- if(o == OMUL || o == OLMUL) {
- if(l->addable >= INDEXED) {
- t = l;
- l = r;
- r = t;
- }
- reg[D_DX]++; // for gopcode case OMUL
- regalloc(&nod, l, nn);
- cgen(l, &nod);
- if(r->addable < INDEXED) {
- regalloc(&nod1, r, Z);
- cgen(r, &nod1);
- gopcode(OMUL, n->type, &nod1, &nod);
- regfree(&nod1);
- }else
- gopcode(OMUL, n->type, r, &nod); /* addressible */
- gmove(&nod, nn);
- regfree(&nod);
- reg[D_DX]--;
- break;
- }
-
- /*
- * get nod to be D_AX
- * get nod1 to be D_DX
- */
- if(nodreg(&nod, nn, D_AX)) {
- regsalloc(&nod2, n);
- gmove(&nod, &nod2);
- v = reg[D_AX];
- reg[D_AX] = 0;
-
- if(isreg(l, D_AX)) {
- nod3 = *n;
- nod3.left = &nod2;
- cgen(&nod3, nn);
- } else
- if(isreg(r, D_AX)) {
- nod3 = *n;
- nod3.right = &nod2;
- cgen(&nod3, nn);
- } else
- cgen(n, nn);
-
- gmove(&nod2, &nod);
- reg[D_AX] = v;
- break;
- }
- if(nodreg(&nod1, nn, D_DX)) {
- regsalloc(&nod2, n);
- gmove(&nod1, &nod2);
- v = reg[D_DX];
- reg[D_DX] = 0;
-
- if(isreg(l, D_DX)) {
- nod3 = *n;
- nod3.left = &nod2;
- cgen(&nod3, nn);
- } else
- if(isreg(r, D_DX)) {
- nod3 = *n;
- nod3.right = &nod2;
- cgen(&nod3, nn);
- } else
- cgen(n, nn);
-
- gmove(&nod2, &nod1);
- reg[D_DX] = v;
- break;
- }
- reg[D_AX]++;
-
- if(r->op == OCONST && (o == ODIV || o == OLDIV)) {
- reg[D_DX]++;
- if(l->addable < INDEXED) {
- regalloc(&nod2, l, Z);
- cgen(l, &nod2);
- l = &nod2;
- }
- if(o == ODIV)
- sdivgen(l, r, &nod, &nod1);
- else
- udivgen(l, r, &nod, &nod1);
- gmove(&nod1, nn);
- if(l == &nod2)
- regfree(l);
- goto freeaxdx;
- }
-
- if(l->complex >= r->complex) {
- cgen(l, &nod);
- reg[D_DX]++;
- if(o == ODIV || o == OMOD)
- gins(ACDQ, Z, Z);
- if(o == OLDIV || o == OLMOD)
- zeroregm(&nod1);
- if(r->addable < INDEXED || r->op == OCONST) {
- regsalloc(&nod3, r);
- cgen(r, &nod3);
- gopcode(o, n->type, &nod3, Z);
- } else
- gopcode(o, n->type, r, Z);
- } else {
- regsalloc(&nod3, r);
- cgen(r, &nod3);
- cgen(l, &nod);
- reg[D_DX]++;
- if(o == ODIV || o == OMOD)
- gins(ACDQ, Z, Z);
- if(o == OLDIV || o == OLMOD)
- zeroregm(&nod1);
- gopcode(o, n->type, &nod3, Z);
- }
- if(o == OMOD || o == OLMOD)
- gmove(&nod1, nn);
- else
- gmove(&nod, nn);
- freeaxdx:
- regfree(&nod);
- regfree(&nod1);
- break;
-
- case OASLSHR:
- case OASASHL:
- case OASASHR:
- if(r->op == OCONST)
- goto asand;
- if(l->op == OBIT)
- goto asbitop;
- if(typefd[n->type->etype])
- goto asfop;
-
- /*
- * get nod to be D_CX
- */
- if(nodreg(&nod, nn, D_CX)) {
- regsalloc(&nod1, n);
- gmove(&nod, &nod1);
- cgen(n, &nod);
- if(nn != Z)
- gmove(&nod, nn);
- gmove(&nod1, &nod);
- break;
- }
- reg[D_CX]++;
-
- if(r->complex >= l->complex) {
- cgen(r, &nod);
- if(hardleft)
- reglcgen(&nod1, l, Z);
- else
- nod1 = *l;
- } else {
- if(hardleft)
- reglcgen(&nod1, l, Z);
- else
- nod1 = *l;
- cgen(r, &nod);
- }
-
- gopcode(o, l->type, &nod, &nod1);
- regfree(&nod);
- if(nn != Z)
- gmove(&nod1, nn);
- if(hardleft)
- regfree(&nod1);
- break;
-
- case OASAND:
- case OASADD:
- case OASSUB:
- case OASXOR:
- case OASOR:
- asand:
- if(l->op == OBIT)
- goto asbitop;
- if(typefd[n->type->etype]||typefd[r->type->etype])
- goto asfop;
- if(l->complex >= r->complex) {
- if(hardleft)
- reglcgen(&nod, l, Z);
- else
- nod = *l;
- if(r->op != OCONST) {
- regalloc(&nod1, r, nn);
- cgen(r, &nod1);
- gopcode(o, l->type, &nod1, &nod);
- regfree(&nod1);
- } else
- gopcode(o, l->type, r, &nod);
- } else {
- regalloc(&nod1, r, nn);
- cgen(r, &nod1);
- if(hardleft)
- reglcgen(&nod, l, Z);
- else
- nod = *l;
- gopcode(o, l->type, &nod1, &nod);
- regfree(&nod1);
- }
- if(nn != Z)
- gmove(&nod, nn);
- if(hardleft)
- regfree(&nod);
- break;
-
- case OASLMUL:
- case OASLDIV:
- case OASLMOD:
- case OASMUL:
- case OASDIV:
- case OASMOD:
- if(l->op == OBIT)
- goto asbitop;
- if(typefd[n->type->etype]||typefd[r->type->etype])
- goto asfop;
- if(r->op == OCONST) {
- SET(v);
- switch(o) {
- case OASDIV:
- case OASMOD:
- c = r->vconst;
- if(c < 0)
- c = -c;
- v = xlog2(c);
- if(v < 0)
- break;
- /* fall thru */
- case OASMUL:
- case OASLMUL:
- if(hardleft)
- reglcgen(&nod2, l, Z);
- else
- nod2 = *l;
- regalloc(&nod, l, nn);
- cgen(&nod2, &nod);
- switch(o) {
- case OASMUL:
- case OASLMUL:
- mulgen(n->type, r, &nod);
- break;
- case OASDIV:
- sdiv2(r->vconst, v, l, &nod);
- break;
- case OASMOD:
- smod2(r->vconst, v, l, &nod);
- break;
- }
- havev:
- gmove(&nod, &nod2);
- if(nn != Z)
- gmove(&nod, nn);
- if(hardleft)
- regfree(&nod2);
- regfree(&nod);
- goto done;
- case OASLDIV:
- c = r->vconst;
- if((c & 0x80000000) == 0)
- break;
- if(hardleft)
- reglcgen(&nod2, l, Z);
- else
- nod2 = *l;
- regalloc(&nod1, l, nn);
- cgen(&nod2, &nod1);
- regalloc(&nod, l, nn);
- zeroregm(&nod);
- gins(ACMPL, &nod1, nodconst(c));
- gins(ASBBL, nodconst(-1), &nod);
- regfree(&nod1);
- goto havev;
- }
- }
-
- if(o == OASMUL) {
- /* should favour AX */
- regalloc(&nod, l, nn);
- if(r->complex >= FNX) {
- regalloc(&nod1, r, Z);
- cgen(r, &nod1);
- r = &nod1;
- }
- if(hardleft)
- reglcgen(&nod2, l, Z);
- else
- nod2 = *l;
- cgen(&nod2, &nod);
- if(r->addable < INDEXED) {
- if(r->complex < FNX) {
- regalloc(&nod1, r, Z);
- cgen(r, &nod1);
- }
- gopcode(OASMUL, n->type, &nod1, &nod);
- regfree(&nod1);
- }
- else
- gopcode(OASMUL, n->type, r, &nod);
- if(r == &nod1)
- regfree(r);
- gmove(&nod, &nod2);
- if(nn != Z)
- gmove(&nod, nn);
- regfree(&nod);
- if(hardleft)
- regfree(&nod2);
- break;
- }
-
- /*
- * get nod to be D_AX
- * get nod1 to be D_DX
- */
- if(nodreg(&nod, nn, D_AX)) {
- regsalloc(&nod2, n);
- gmove(&nod, &nod2);
- v = reg[D_AX];
- reg[D_AX] = 0;
-
- if(isreg(l, D_AX)) {
- nod3 = *n;
- nod3.left = &nod2;
- cgen(&nod3, nn);
- } else
- if(isreg(r, D_AX)) {
- nod3 = *n;
- nod3.right = &nod2;
- cgen(&nod3, nn);
- } else
- cgen(n, nn);
-
- gmove(&nod2, &nod);
- reg[D_AX] = v;
- break;
- }
- if(nodreg(&nod1, nn, D_DX)) {
- regsalloc(&nod2, n);
- gmove(&nod1, &nod2);
- v = reg[D_DX];
- reg[D_DX] = 0;
-
- if(isreg(l, D_DX)) {
- nod3 = *n;
- nod3.left = &nod2;
- cgen(&nod3, nn);
- } else
- if(isreg(r, D_DX)) {
- nod3 = *n;
- nod3.right = &nod2;
- cgen(&nod3, nn);
- } else
- cgen(n, nn);
-
- gmove(&nod2, &nod1);
- reg[D_DX] = v;
- break;
- }
- reg[D_AX]++;
- reg[D_DX]++;
-
- if(l->complex >= r->complex) {
- if(hardleft)
- reglcgen(&nod2, l, Z);
- else
- nod2 = *l;
- cgen(&nod2, &nod);
- if(r->op == OCONST) {
- switch(o) {
- case OASDIV:
- sdivgen(&nod2, r, &nod, &nod1);
- goto divdone;
- case OASLDIV:
- udivgen(&nod2, r, &nod, &nod1);
- divdone:
- gmove(&nod1, &nod2);
- if(nn != Z)
- gmove(&nod1, nn);
- goto freelxaxdx;
- }
- }
- if(o == OASDIV || o == OASMOD)
- gins(ACDQ, Z, Z);
- if(o == OASLDIV || o == OASLMOD)
- zeroregm(&nod1);
- if(r->addable < INDEXED || r->op == OCONST ||
- !typeil[r->type->etype]) {
- regalloc(&nod3, r, Z);
- cgen(r, &nod3);
- gopcode(o, l->type, &nod3, Z);
- regfree(&nod3);
- } else
- gopcode(o, n->type, r, Z);
- } else {
- regalloc(&nod3, r, Z);
- cgen(r, &nod3);
- if(hardleft)
- reglcgen(&nod2, l, Z);
- else
- nod2 = *l;
- cgen(&nod2, &nod);
- if(o == OASDIV || o == OASMOD)
- gins(ACDQ, Z, Z);
- if(o == OASLDIV || o == OASLMOD)
- zeroregm(&nod1);
- gopcode(o, l->type, &nod3, Z);
- regfree(&nod3);
- }
- if(o == OASMOD || o == OASLMOD) {
- gmove(&nod1, &nod2);
- if(nn != Z)
- gmove(&nod1, nn);
- } else {
- gmove(&nod, &nod2);
- if(nn != Z)
- gmove(&nod, nn);
- }
- freelxaxdx:
- if(hardleft)
- regfree(&nod2);
- regfree(&nod);
- regfree(&nod1);
- break;
-
- fop:
- if(l->complex >= r->complex) {
- cgen(l, &fregnode0);
- if(r->addable < INDEXED) {
- cgen(r, &fregnode0);
- fgopcode(o, &fregnode0, &fregnode1, 1, 0);
- } else
- fgopcode(o, r, &fregnode0, 0, 0);
- } else {
- cgen(r, &fregnode0);
- if(l->addable < INDEXED) {
- cgen(l, &fregnode0);
- fgopcode(o, &fregnode0, &fregnode1, 1, 1);
- } else
- fgopcode(o, l, &fregnode0, 0, 1);
- }
- gmove(&fregnode0, nn);
- break;
-
- asfop:
- if(l->complex >= r->complex) {
- if(hardleft)
- reglcgen(&nod, l, Z);
- else
- nod = *l;
- cgen(r, &fregnode0);
- } else {
- cgen(r, &fregnode0);
- if(hardleft)
- reglcgen(&nod, l, Z);
- else
- nod = *l;
- }
- if(!typefd[l->type->etype]) {
- gmove(&nod, &fregnode0);
- fgopcode(o, &fregnode0, &fregnode1, 1, 1);
- } else
- fgopcode(o, &nod, &fregnode0, 0, 1);
- if(nn != Z)
- gins(AFMOVD, &fregnode0, &fregnode0);
- gmove(&fregnode0, &nod);
- if(nn != Z)
- gmove(&fregnode0, nn);
- if(hardleft)
- regfree(&nod);
- break;
-
- asbitop:
- regalloc(&nod4, n, nn);
- if(l->complex >= r->complex) {
- bitload(l, &nod, &nod1, &nod2, &nod4);
- regalloc(&nod3, r, Z);
- cgen(r, &nod3);
- } else {
- regalloc(&nod3, r, Z);
- cgen(r, &nod3);
- bitload(l, &nod, &nod1, &nod2, &nod4);
- }
- gmove(&nod, &nod4);
-
- if(typefd[nod3.type->etype])
- fgopcode(o, &fregnode0, &fregnode1, 1, 1);
- else {
- Node onod;
-
- /* incredible grot ... */
- onod = nod3;
- onod.op = o;
- onod.complex = 2;
- onod.addable = 0;
- onod.type = tfield;
- onod.left = &nod4;
- onod.right = &nod3;
- cgen(&onod, Z);
- }
- regfree(&nod3);
- gmove(&nod4, &nod);
- regfree(&nod4);
- bitstore(l, &nod, &nod1, &nod2, nn);
- break;
-
- case OADDR:
- if(nn == Z) {
- nullwarn(l, Z);
- break;
- }
- lcgen(l, nn);
- break;
-
- case OFUNC:
- if(l->complex >= FNX) {
- if(l->op != OIND)
- diag(n, "bad function call");
-
- regret(&nod, l->left, 0, 0);
- cgen(l->left, &nod);
- regsalloc(&nod1, l->left);
- gmove(&nod, &nod1);
- regfree(&nod);
-
- nod = *n;
- nod.left = &nod2;
- nod2 = *l;
- nod2.left = &nod1;
- nod2.complex = 1;
- cgen(&nod, nn);
-
- return;
- }
- gargs(r, &nod, &nod1);
- if(l->addable < INDEXED) {
- reglcgen(&nod, l, nn);
- nod.op = OREGISTER;
- gopcode(OFUNC, n->type, Z, &nod);
- regfree(&nod);
- } else
- gopcode(OFUNC, n->type, Z, l);
- if(REGARG >= 0 && reg[REGARG])
- reg[REGARG]--;
- regret(&nod, n, l->type, 1); // update maxarg if nothing else
- if(nn != Z)
- gmove(&nod, nn);
- if(nod.op == OREGISTER)
- regfree(&nod);
- if(nn == Z && hasdotdotdot(l->type) && typefd[n->type->etype])
- gins(AFMOVDP, &fregnode0, &fregnode0);
- break;
-
- case OIND:
- if(nn == Z) {
- nullwarn(l, Z);
- break;
- }
- regialloc(&nod, n, nn);
- r = l;
- while(r->op == OADD)
- r = r->right;
- if(sconst(r)) {
- v = r->vconst;
- r->vconst = 0;
- cgen(l, &nod);
- nod.xoffset += v;
- r->vconst = v;
- } else
- cgen(l, &nod);
- regind(&nod, n);
- gmove(&nod, nn);
- regfree(&nod);
- break;
-
- case OEQ:
- case ONE:
- case OLE:
- case OLT:
- case OGE:
- case OGT:
- case OLO:
- case OLS:
- case OHI:
- case OHS:
- if(nn == Z) {
- nullwarn(l, r);
- break;
- }
- boolgen(n, 1, nn);
- break;
-
- case OANDAND:
- case OOROR:
- boolgen(n, 1, nn);
- if(nn == Z)
- patch(p, pc);
- break;
-
- case ONOT:
- if(nn == Z) {
- nullwarn(l, Z);
- break;
- }
- boolgen(n, 1, nn);
- break;
-
- case OCOMMA:
- cgen(l, Z);
- cgen(r, nn);
- break;
-
- case OCAST:
- if(nn == Z) {
- nullwarn(l, Z);
- break;
- }
- /*
- * convert from types l->n->nn
- */
- if(nocast(l->type, n->type) && nocast(n->type, nn->type)) {
- /* both null, gen l->nn */
- cgen(l, nn);
- break;
- }
- if(typev[l->type->etype]) {
- cgen64(n, nn);
- break;
- }
- regalloc(&nod, l, nn);
- cgen(l, &nod);
- regalloc(&nod1, n, &nod);
- gmove(&nod, &nod1);
- gmove(&nod1, nn);
- regfree(&nod1);
- regfree(&nod);
- break;
-
- case ODOT:
- sugen(l, nodrat, l->type->width);
- if(nn == Z)
- break;
- warn(n, "non-interruptable temporary");
- nod = *nodrat;
- if(!r || r->op != OCONST) {
- diag(n, "DOT and no offset");
- break;
- }
- nod.xoffset += (int32)r->vconst;
- nod.type = n->type;
- cgen(&nod, nn);
- break;
-
- case OCOND:
- bcgen(l, 1);
- p1 = p;
- cgen(r->left, nn);
- gbranch(OGOTO);
- patch(p1, pc);
- p1 = p;
- cgen(r->right, nn);
- patch(p1, pc);
- break;
-
- case OPOSTINC:
- case OPOSTDEC:
- v = 1;
- if(l->type->etype == TIND)
- v = l->type->link->width;
- if(o == OPOSTDEC)
- v = -v;
- if(l->op == OBIT)
- goto bitinc;
- if(nn == Z)
- goto pre;
-
- if(hardleft)
- reglcgen(&nod, l, Z);
- else
- nod = *l;
-
- if(typefd[n->type->etype])
- goto fltinc;
- gmove(&nod, nn);
- gopcode(OADD, n->type, nodconst(v), &nod);
- if(hardleft)
- regfree(&nod);
- break;
-
- case OPREINC:
- case OPREDEC:
- v = 1;
- if(l->type->etype == TIND)
- v = l->type->link->width;
- if(o == OPREDEC)
- v = -v;
- if(l->op == OBIT)
- goto bitinc;
-
- pre:
- if(hardleft)
- reglcgen(&nod, l, Z);
- else
- nod = *l;
- if(typefd[n->type->etype])
- goto fltinc;
- gopcode(OADD, n->type, nodconst(v), &nod);
- if(nn != Z)
- gmove(&nod, nn);
- if(hardleft)
- regfree(&nod);
- break;
-
- fltinc:
- gmove(&nod, &fregnode0);
- if(nn != Z && (o == OPOSTINC || o == OPOSTDEC))
- gins(AFMOVD, &fregnode0, &fregnode0);
- gins(AFLD1, Z, Z);
- if(v < 0)
- fgopcode(OSUB, &fregnode0, &fregnode1, 1, 0);
- else
- fgopcode(OADD, &fregnode0, &fregnode1, 1, 0);
- if(nn != Z && (o == OPREINC || o == OPREDEC))
- gins(AFMOVD, &fregnode0, &fregnode0);
- gmove(&fregnode0, &nod);
- if(hardleft)
- regfree(&nod);
- break;
-
- bitinc:
- if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) {
- bitload(l, &nod, &nod1, &nod2, Z);
- gmove(&nod, nn);
- gopcode(OADD, tfield, nodconst(v), &nod);
- bitstore(l, &nod, &nod1, &nod2, Z);
- break;
- }
- bitload(l, &nod, &nod1, &nod2, nn);
- gopcode(OADD, tfield, nodconst(v), &nod);
- bitstore(l, &nod, &nod1, &nod2, nn);
- break;
- }
-done:
- cursafe = curs;
-}
-
-void
-reglcgen(Node *t, Node *n, Node *nn)
-{
- Node *r;
- int32 v;
-
- regialloc(t, n, nn);
- if(n->op == OIND) {
- r = n->left;
- while(r->op == OADD)
- r = r->right;
- if(sconst(r)) {
- v = r->vconst;
- r->vconst = 0;
- lcgen(n, t);
- t->xoffset += v;
- r->vconst = v;
- regind(t, n);
- return;
- }
- }
- lcgen(n, t);
- regind(t, n);
-}
-
-void
-lcgen(Node *n, Node *nn)
-{
- Prog *p1;
- Node nod;
-
- if(debug['g']) {
- prtree(nn, "lcgen lhs");
- prtree(n, "lcgen");
- }
- if(n == Z || n->type == T)
- return;
- if(nn == Z) {
- nn = &nod;
- regalloc(&nod, n, Z);
- }
- switch(n->op) {
- default:
- if(n->addable < INDEXED) {
- diag(n, "unknown op in lcgen: %O", n->op);
- break;
- }
- gopcode(OADDR, n->type, n, nn);
- break;
-
- case OCOMMA:
- cgen(n->left, n->left);
- lcgen(n->right, nn);
- break;
-
- case OIND:
- cgen(n->left, nn);
- break;
-
- case OCOND:
- bcgen(n->left, 1);
- p1 = p;
- lcgen(n->right->left, nn);
- gbranch(OGOTO);
- patch(p1, pc);
- p1 = p;
- lcgen(n->right->right, nn);
- patch(p1, pc);
- break;
- }
-}
-
-void
-bcgen(Node *n, int true)
-{
-
- if(n->type == T)
- gbranch(OGOTO);
- else
- boolgen(n, true, Z);
-}
-
-void
-boolgen(Node *n, int true, Node *nn)
-{
- int o;
- Prog *p1, *p2, *p3;
- Node *l, *r, nod, nod1;
- int32 curs;
-
- if(debug['g']) {
- prtree(nn, "boolgen lhs");
- prtree(n, "boolgen");
- }
- curs = cursafe;
- l = n->left;
- r = n->right;
- switch(n->op) {
-
- default:
- if(typev[n->type->etype]) {
- testv(n, true);
- goto com;
- }
- o = ONE;
- if(true)
- o = OEQ;
- if(typefd[n->type->etype]) {
- if(n->addable < INDEXED) {
- cgen(n, &fregnode0);
- gins(AFLDZ, Z, Z);
- fgopcode(o, &fregnode0, &fregnode1, 1, 1);
- } else {
- gins(AFLDZ, Z, Z);
- fgopcode(o, n, &fregnode0, 0, 1);
- }
- goto com;
- }
- /* bad, 13 is address of external that becomes constant */
- if(n->addable >= INDEXED && n->addable != 13) {
- gopcode(o, n->type, n, nodconst(0));
- goto com;
- }
- regalloc(&nod, n, nn);
- cgen(n, &nod);
- gopcode(o, n->type, &nod, nodconst(0));
- regfree(&nod);
- goto com;
-
- case OCONST:
- o = vconst(n);
- if(!true)
- o = !o;
- gbranch(OGOTO);
- if(o) {
- p1 = p;
- gbranch(OGOTO);
- patch(p1, pc);
- }
- goto com;
-
- case OCOMMA:
- cgen(l, Z);
- boolgen(r, true, nn);
- break;
-
- case ONOT:
- boolgen(l, !true, nn);
- break;
-
- case OCOND:
- bcgen(l, 1);
- p1 = p;
- bcgen(r->left, true);
- p2 = p;
- gbranch(OGOTO);
- patch(p1, pc);
- p1 = p;
- bcgen(r->right, !true);
- patch(p2, pc);
- p2 = p;
- gbranch(OGOTO);
- patch(p1, pc);
- patch(p2, pc);
- goto com;
-
- case OANDAND:
- if(!true)
- goto caseor;
-
- caseand:
- bcgen(l, true);
- p1 = p;
- bcgen(r, !true);
- p2 = p;
- patch(p1, pc);
- gbranch(OGOTO);
- patch(p2, pc);
- goto com;
-
- case OOROR:
- if(!true)
- goto caseand;
-
- caseor:
- bcgen(l, !true);
- p1 = p;
- bcgen(r, !true);
- p2 = p;
- gbranch(OGOTO);
- patch(p1, pc);
- patch(p2, pc);
- goto com;
-
- case OEQ:
- case ONE:
- case OLE:
- case OLT:
- case OGE:
- case OGT:
- case OHI:
- case OHS:
- case OLO:
- case OLS:
- o = n->op;
- if(typev[l->type->etype]) {
- if(!true)
- n->op = comrel[relindex(o)];
- cgen64(n, Z);
- goto com;
- }
- if(true && typefd[l->type->etype] && (o == OEQ || o == ONE)) {
- // Cannot rewrite !(l == r) into l != r with float64; it breaks NaNs.
- // Jump around instead.
- boolgen(n, 0, Z);
- p1 = p;
- gbranch(OGOTO);
- patch(p1, pc);
- goto com;
- }
- if(true)
- o = comrel[relindex(o)];
- if(l->complex >= FNX && r->complex >= FNX) {
- regret(&nod, r, 0, 0);
- cgen(r, &nod);
- regsalloc(&nod1, r);
- gmove(&nod, &nod1);
- regfree(&nod);
- nod = *n;
- nod.right = &nod1;
- boolgen(&nod, true, nn);
- break;
- }
- if(typefd[l->type->etype]) {
- if(l->complex >= r->complex) {
- cgen(l, &fregnode0);
- if(r->addable < INDEXED) {
- cgen(r, &fregnode0);
- o = invrel[relindex(o)];
- fgopcode(o, &fregnode0, &fregnode1, 1, 1);
- } else
- fgopcode(o, r, &fregnode0, 0, 1);
- } else {
- o = invrel[relindex(o)];
- cgen(r, &fregnode0);
- if(l->addable < INDEXED) {
- cgen(l, &fregnode0);
- o = invrel[relindex(o)];
- fgopcode(o, &fregnode0, &fregnode1, 1, 1);
- } else
- fgopcode(o, l, &fregnode0, 0, 1);
- }
- switch(o) {
- case OEQ:
- // Already emitted AJEQ; want AJEQ and AJPC.
- p1 = p;
- gbranch(OGOTO);
- p2 = p;
- patch(p1, pc);
- gins(AJPC, Z, Z);
- patch(p2, pc);
- break;
-
- case ONE:
- // Already emitted AJNE; want AJNE or AJPS.
- p1 = p;
- gins(AJPS, Z, Z);
- p2 = p;
- gbranch(OGOTO);
- p3 = p;
- patch(p1, pc);
- patch(p2, pc);
- gbranch(OGOTO);
- patch(p3, pc);
- break;
- }
- goto com;
- }
- if(l->op == OCONST) {
- o = invrel[relindex(o)];
- /* bad, 13 is address of external that becomes constant */
- if(r->addable < INDEXED || r->addable == 13) {
- regalloc(&nod, r, nn);
- cgen(r, &nod);
- gopcode(o, l->type, &nod, l);
- regfree(&nod);
- } else
- gopcode(o, l->type, r, l);
- goto com;
- }
- if(l->complex >= r->complex) {
- regalloc(&nod, l, nn);
- cgen(l, &nod);
- if(r->addable < INDEXED) {
- regalloc(&nod1, r, Z);
- cgen(r, &nod1);
- gopcode(o, l->type, &nod, &nod1);
- regfree(&nod1);
- } else
- gopcode(o, l->type, &nod, r);
- regfree(&nod);
- goto com;
- }
- regalloc(&nod, r, nn);
- cgen(r, &nod);
- if(l->addable < INDEXED || l->addable == 13) {
- regalloc(&nod1, l, Z);
- cgen(l, &nod1);
- if(typechlp[l->type->etype])
- gopcode(o, types[TINT], &nod1, &nod);
- else
- gopcode(o, l->type, &nod1, &nod);
- regfree(&nod1);
- } else
- gopcode(o, l->type, l, &nod);
- regfree(&nod);
-
- com:
- if(nn != Z) {
- p1 = p;
- gmove(nodconst(1L), nn);
- gbranch(OGOTO);
- p2 = p;
- patch(p1, pc);
- gmove(nodconst(0L), nn);
- patch(p2, pc);
- }
- break;
- }
- cursafe = curs;
-}
-
-void
-sugen(Node *n, Node *nn, int32 w)
-{
- Prog *p1;
- Node nod0, nod1, nod2, nod3, nod4, *h, *l, *r;
- Type *t;
- int c, v, x;
-
- if(n == Z || n->type == T)
- return;
- if(debug['g']) {
- prtree(nn, "sugen lhs");
- prtree(n, "sugen");
- }
- if(nn == nodrat)
- if(w > nrathole)
- nrathole = w;
- switch(n->op) {
- case OIND:
- if(nn == Z) {
- nullwarn(n->left, Z);
- break;
- }
-
- default:
- goto copy;
-
- case OCONST:
- if(n->type && typev[n->type->etype]) {
- if(nn == Z) {
- nullwarn(n->left, Z);
- break;
- }
-
- if(nn->op == OREGPAIR) {
- loadpair(n, nn);
- break;
- }
- else if(!vaddr(nn, 0)) {
- t = nn->type;
- nn->type = types[TLONG];
- reglcgen(&nod1, nn, Z);
- nn->type = t;
-
- gmove(lo64(n), &nod1);
- nod1.xoffset += SZ_LONG;
- gmove(hi64(n), &nod1);
- regfree(&nod1);
- }
- else {
- gins(AMOVL, lo64(n), nn);
- nn->xoffset += SZ_LONG;
- gins(AMOVL, hi64(n), nn);
- nn->xoffset -= SZ_LONG;
- break;
- }
- break;
- }
- goto copy;
-
- case ODOT:
- l = n->left;
- sugen(l, nodrat, l->type->width);
- if(nn == Z)
- break;
- warn(n, "non-interruptable temporary");
- nod1 = *nodrat;
- r = n->right;
- if(!r || r->op != OCONST) {
- diag(n, "DOT and no offset");
- break;
- }
- nod1.xoffset += (int32)r->vconst;
- nod1.type = n->type;
- sugen(&nod1, nn, w);
- break;
-
- case OSTRUCT:
- /*
- * rewrite so lhs has no fn call
- */
- if(nn != Z && side(nn)) {
- nod1 = *n;
- nod1.type = typ(TIND, n->type);
- regret(&nod2, &nod1, 0, 0);
- lcgen(nn, &nod2);
- regsalloc(&nod0, &nod1);
- cgen(&nod2, &nod0);
- regfree(&nod2);
-
- nod1 = *n;
- nod1.op = OIND;
- nod1.left = &nod0;
- nod1.right = Z;
- nod1.complex = 1;
-
- sugen(n, &nod1, w);
- return;
- }
-
- r = n->left;
- for(t = n->type->link; t != T; t = t->down) {
- l = r;
- if(r->op == OLIST) {
- l = r->left;
- r = r->right;
- }
- if(nn == Z) {
- cgen(l, nn);
- continue;
- }
- /*
- * hand craft *(&nn + o) = l
- */
- nod0 = znode;
- nod0.op = OAS;
- nod0.type = t;
- nod0.left = &nod1;
- nod0.right = nil;
-
- nod1 = znode;
- nod1.op = OIND;
- nod1.type = t;
- nod1.left = &nod2;
-
- nod2 = znode;
- nod2.op = OADD;
- nod2.type = typ(TIND, t);
- nod2.left = &nod3;
- nod2.right = &nod4;
-
- nod3 = znode;
- nod3.op = OADDR;
- nod3.type = nod2.type;
- nod3.left = nn;
-
- nod4 = znode;
- nod4.op = OCONST;
- nod4.type = nod2.type;
- nod4.vconst = t->offset;
-
- ccom(&nod0);
- acom(&nod0);
- xcom(&nod0);
- nod0.addable = 0;
- nod0.right = l;
-
- // prtree(&nod0, "hand craft");
- cgen(&nod0, Z);
- }
- break;
-
- case OAS:
- if(nn == Z) {
- if(n->addable < INDEXED)
- sugen(n->right, n->left, w);
- break;
- }
-
- sugen(n->right, nodrat, w);
- warn(n, "non-interruptable temporary");
- sugen(nodrat, n->left, w);
- sugen(nodrat, nn, w);
- break;
-
- case OFUNC:
- if(!hasdotdotdot(n->left->type)) {
- cgen(n, Z);
- if(nn != Z) {
- curarg -= n->type->width;
- regret(&nod1, n, n->left->type, 1);
- if(nn->complex >= FNX) {
- regsalloc(&nod2, n);
- cgen(&nod1, &nod2);
- nod1 = nod2;
- }
- cgen(&nod1, nn);
- }
- break;
- }
- if(nn == Z) {
- sugen(n, nodrat, w);
- break;
- }
- h = nn;
- if(nn->op == OREGPAIR) {
- regsalloc(&nod1, nn);
- nn = &nod1;
- }
- if(nn->op != OIND) {
- nn = new1(OADDR, nn, Z);
- nn->type = types[TIND];
- nn->addable = 0;
- } else
- nn = nn->left;
- n = new(OFUNC, n->left, new(OLIST, nn, n->right));
- n->type = types[TVOID];
- n->left->type = types[TVOID];
- cgen(n, Z);
- if(h->op == OREGPAIR)
- loadpair(nn->left, h);
- break;
-
- case OCOND:
- bcgen(n->left, 1);
- p1 = p;
- sugen(n->right->left, nn, w);
- gbranch(OGOTO);
- patch(p1, pc);
- p1 = p;
- sugen(n->right->right, nn, w);
- patch(p1, pc);
- break;
-
- case OCOMMA:
- cgen(n->left, Z);
- sugen(n->right, nn, w);
- break;
- }
- return;
-
-copy:
- if(nn == Z) {
- switch(n->op) {
- case OASADD:
- case OASSUB:
- case OASAND:
- case OASOR:
- case OASXOR:
-
- case OASMUL:
- case OASLMUL:
-
-
- case OASASHL:
- case OASASHR:
- case OASLSHR:
- break;
-
- case OPOSTINC:
- case OPOSTDEC:
- case OPREINC:
- case OPREDEC:
- break;
-
- default:
- return;
- }
- }
-
- v = w == 8;
- if(n->complex >= FNX && nn != nil && nn->complex >= FNX) {
- t = nn->type;
- nn->type = types[TLONG];
- regialloc(&nod1, nn, Z);
- lcgen(nn, &nod1);
- regsalloc(&nod2, nn);
- nn->type = t;
-
- gins(AMOVL, &nod1, &nod2);
- regfree(&nod1);
-
- nod2.type = typ(TIND, t);
-
- nod1 = nod2;
- nod1.op = OIND;
- nod1.left = &nod2;
- nod1.right = Z;
- nod1.complex = 1;
- nod1.type = t;
-
- sugen(n, &nod1, w);
- return;
- }
-
- x = 0;
- if(v) {
- if(nn != nil && nn->complex >= FNX) {
- t = nn->type;
- nn->type = types[TLONG];
- regialloc(&nod2, nn, Z);
- lcgen(nn, &nod2);
- nn->type = t;
-
- nod2.type = typ(TIND, t);
-
- nod1 = nod2;
- nod1.op = OIND;
- nod1.left = &nod2;
- nod1.right = Z;
- nod1.complex = 1;
- nod1.type = t;
-
- sugen(n, &nod1, w);
- regfree(&nod2);
- return;
- }
-
- c = cursafe;
- if(n->left != Z && n->left->complex >= FNX
- && n->right != Z && n->right->complex >= FNX) {
-// warn(n, "toughie");
- regsalloc(&nod1, n->right);
- cgen(n->right, &nod1);
- nod2 = *n;
- nod2.right = &nod1;
- cgen(&nod2, nn);
- cursafe = c;
- return;
- }
- if(cgen64(n, nn)) {
- cursafe = c;
- return;
- }
- if(n->op == OCOM) {
- n = n->left;
- x = 1;
- }
- }
-
- /* botch, need to save in .safe */
- c = 0;
- if(n->complex > nn->complex) {
- t = n->type;
- n->type = types[TLONG];
- if(v) {
- regalloc(&nod0, n, Z);
- if(!vaddr(n, 0)) {
- reglcgen(&nod1, n, Z);
- n->type = t;
- n = &nod1;
- }
- else
- n->type = t;
- }
- else {
- nodreg(&nod1, n, D_SI);
- if(reg[D_SI]) {
- gins(APUSHL, &nod1, Z);
- c |= 1;
- reg[D_SI]++;
- }
- lcgen(n, &nod1);
- n->type = t;
- }
-
- t = nn->type;
- nn->type = types[TLONG];
- if(v) {
- if(!vaddr(nn, 0)) {
- reglcgen(&nod2, nn, Z);
- nn->type = t;
- nn = &nod2;
- }
- else
- nn->type = t;
- }
- else {
- nodreg(&nod2, nn, D_DI);
- if(reg[D_DI]) {
- gins(APUSHL, &nod2, Z);
- c |= 2;
- reg[D_DI]++;
- }
- lcgen(nn, &nod2);
- nn->type = t;
- }
- } else {
- t = nn->type;
- nn->type = types[TLONG];
- if(v) {
- regalloc(&nod0, nn, Z);
- if(!vaddr(nn, 0)) {
- reglcgen(&nod2, nn, Z);
- nn->type = t;
- nn = &nod2;
- }
- else
- nn->type = t;
- }
- else {
- nodreg(&nod2, nn, D_DI);
- if(reg[D_DI]) {
- gins(APUSHL, &nod2, Z);
- c |= 2;
- reg[D_DI]++;
- }
- lcgen(nn, &nod2);
- nn->type = t;
- }
-
- t = n->type;
- n->type = types[TLONG];
- if(v) {
- if(!vaddr(n, 0)) {
- reglcgen(&nod1, n, Z);
- n->type = t;
- n = &nod1;
- }
- else
- n->type = t;
- }
- else {
- nodreg(&nod1, n, D_SI);
- if(reg[D_SI]) {
- gins(APUSHL, &nod1, Z);
- c |= 1;
- reg[D_SI]++;
- }
- lcgen(n, &nod1);
- n->type = t;
- }
- }
- if(v) {
- gins(AMOVL, n, &nod0);
- if(x)
- gins(ANOTL, Z, &nod0);
- gins(AMOVL, &nod0, nn);
- n->xoffset += SZ_LONG;
- nn->xoffset += SZ_LONG;
- gins(AMOVL, n, &nod0);
- if(x)
- gins(ANOTL, Z, &nod0);
- gins(AMOVL, &nod0, nn);
- n->xoffset -= SZ_LONG;
- nn->xoffset -= SZ_LONG;
- if(nn == &nod2)
- regfree(&nod2);
- if(n == &nod1)
- regfree(&nod1);
- regfree(&nod0);
- return;
- }
- nodreg(&nod3, n, D_CX);
- if(reg[D_CX]) {
- gins(APUSHL, &nod3, Z);
- c |= 4;
- reg[D_CX]++;
- }
- gins(AMOVL, nodconst(w/SZ_LONG), &nod3);
- gins(ACLD, Z, Z);
- gins(AREP, Z, Z);
- gins(AMOVSL, Z, Z);
- if(c & 4) {
- gins(APOPL, Z, &nod3);
- reg[D_CX]--;
- }
- if(c & 2) {
- gins(APOPL, Z, &nod2);
- reg[nod2.reg]--;
- }
- if(c & 1) {
- gins(APOPL, Z, &nod1);
- reg[nod1.reg]--;
- }
-}
diff --git a/src/cmd/8c/cgen64.c b/src/cmd/8c/cgen64.c
deleted file mode 100644
index 3424f762c..000000000
--- a/src/cmd/8c/cgen64.c
+++ /dev/null
@@ -1,2657 +0,0 @@
-// Inferno utils/8c/cgen64.c
-// http://code.google.com/p/inferno-os/source/browse/utils/8c/cgen64.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-
-void
-zeroregm(Node *n)
-{
- gins(AMOVL, nodconst(0), n);
-}
-
-/* do we need to load the address of a vlong? */
-int
-vaddr(Node *n, int a)
-{
- switch(n->op) {
- case ONAME:
- if(a)
- return 1;
- return !(n->class == CEXTERN || n->class == CGLOBL || n->class == CSTATIC);
-
- case OCONST:
- case OREGISTER:
- case OINDREG:
- return 1;
- }
- return 0;
-}
-
-int32
-hi64v(Node *n)
-{
- if(align(0, types[TCHAR], Aarg1, nil)) /* isbigendian */
- return (int32)(n->vconst) & ~0L;
- else
- return (int32)((uvlong)n->vconst>>32) & ~0L;
-}
-
-int32
-lo64v(Node *n)
-{
- if(align(0, types[TCHAR], Aarg1, nil)) /* isbigendian */
- return (int32)((uvlong)n->vconst>>32) & ~0L;
- else
- return (int32)(n->vconst) & ~0L;
-}
-
-Node *
-hi64(Node *n)
-{
- return nodconst(hi64v(n));
-}
-
-Node *
-lo64(Node *n)
-{
- return nodconst(lo64v(n));
-}
-
-static Node *
-anonreg(void)
-{
- Node *n;
-
- n = new(OREGISTER, Z, Z);
- n->reg = D_NONE;
- n->type = types[TLONG];
- return n;
-}
-
-static Node *
-regpair(Node *n, Node *t)
-{
- Node *r;
-
- if(n != Z && n->op == OREGPAIR)
- return n;
- r = new(OREGPAIR, anonreg(), anonreg());
- if(n != Z)
- r->type = n->type;
- else
- r->type = t->type;
- return r;
-}
-
-static void
-evacaxdx(Node *r)
-{
- Node nod1, nod2;
-
- if(r->reg == D_AX || r->reg == D_DX) {
- reg[D_AX]++;
- reg[D_DX]++;
- /*
- * this is just an optim that should
- * check for spill
- */
- r->type = types[TULONG];
- regalloc(&nod1, r, Z);
- nodreg(&nod2, Z, r->reg);
- gins(AMOVL, &nod2, &nod1);
- regfree(r);
- r->reg = nod1.reg;
- reg[D_AX]--;
- reg[D_DX]--;
- }
-}
-
-/* lazy instantiation of register pair */
-static int
-instpair(Node *n, Node *l)
-{
- int r;
-
- r = 0;
- if(n->left->reg == D_NONE) {
- if(l != Z) {
- n->left->reg = l->reg;
- r = 1;
- }
- else
- regalloc(n->left, n->left, Z);
- }
- if(n->right->reg == D_NONE)
- regalloc(n->right, n->right, Z);
- return r;
-}
-
-static void
-zapreg(Node *n)
-{
- if(n->reg != D_NONE) {
- regfree(n);
- n->reg = D_NONE;
- }
-}
-
-static void
-freepair(Node *n)
-{
- regfree(n->left);
- regfree(n->right);
-}
-
-/* n is not OREGPAIR, nn is */
-void
-loadpair(Node *n, Node *nn)
-{
- Node nod;
-
- instpair(nn, Z);
- if(n->op == OCONST) {
- gins(AMOVL, lo64(n), nn->left);
- n->xoffset += SZ_LONG;
- gins(AMOVL, hi64(n), nn->right);
- n->xoffset -= SZ_LONG;
- return;
- }
- if(!vaddr(n, 0)) {
- /* steal the right register for the laddr */
- nod = regnode;
- nod.reg = nn->right->reg;
- lcgen(n, &nod);
- n = &nod;
- regind(n, n);
- n->xoffset = 0;
- }
- gins(AMOVL, n, nn->left);
- n->xoffset += SZ_LONG;
- gins(AMOVL, n, nn->right);
- n->xoffset -= SZ_LONG;
-}
-
-/* n is OREGPAIR, nn is not */
-static void
-storepair(Node *n, Node *nn, int f)
-{
- Node nod;
-
- if(!vaddr(nn, 0)) {
- reglcgen(&nod, nn, Z);
- nn = &nod;
- }
- gins(AMOVL, n->left, nn);
- nn->xoffset += SZ_LONG;
- gins(AMOVL, n->right, nn);
- nn->xoffset -= SZ_LONG;
- if(nn == &nod)
- regfree(&nod);
- if(f)
- freepair(n);
-}
-
-enum
-{
-/* 4 only, see WW */
- WNONE = 0,
- WCONST,
- WADDR,
- WHARD,
-};
-
-static int
-whatof(Node *n, int a)
-{
- if(n->op == OCONST)
- return WCONST;
- return !vaddr(n, a) ? WHARD : WADDR;
-}
-
-/* can upgrade an extern to addr for AND */
-static int
-reduxv(Node *n)
-{
- return lo64v(n) == 0 || hi64v(n) == 0;
-}
-
-int
-cond(int op)
-{
- switch(op) {
- case OANDAND:
- case OOROR:
- case ONOT:
- return 1;
-
- case OEQ:
- case ONE:
- case OLE:
- case OLT:
- case OGE:
- case OGT:
- case OHI:
- case OHS:
- case OLO:
- case OLS:
- return 1;
- }
- return 0;
-}
-
-/*
- * for a func operand call it and then return
- * the safe node
- */
-static Node *
-vfunc(Node *n, Node *nn)
-{
- Node *t;
-
- if(n->op != OFUNC)
- return n;
- t = new(0, Z, Z);
- if(nn == Z || nn == nodret)
- nn = n;
- regsalloc(t, nn);
- sugen(n, t, 8);
- return t;
-}
-
-/* try to steal a reg */
-static int
-getreg(Node **np, Node *t, int r)
-{
- Node *n, *p;
-
- n = *np;
- if(n->reg == r) {
- p = new(0, Z, Z);
- regalloc(p, n, Z);
- gins(AMOVL, n, p);
- *t = *n;
- *np = p;
- return 1;
- }
- return 0;
-}
-
-static Node *
-snarfreg(Node *n, Node *t, int r, Node *d, Node *c)
-{
- if(n == Z || n->op != OREGPAIR || (!getreg(&n->left, t, r) && !getreg(&n->right, t, r))) {
- if(nodreg(t, Z, r)) {
- regalloc(c, d, Z);
- gins(AMOVL, t, c);
- reg[r]++;
- return c;
- }
- reg[r]++;
- }
- return Z;
-}
-
-enum
-{
- Vstart = OEND,
-
- Vgo,
- Vamv,
- Vmv,
- Vzero,
- Vop,
- Vopx,
- Vins,
- Vins0,
- Vinsl,
- Vinsr,
- Vinsla,
- Vinsra,
- Vinsx,
- Vmul,
- Vshll,
- VT,
- VF,
- V_l_lo_f,
- V_l_hi_f,
- V_l_lo_t,
- V_l_hi_t,
- V_l_lo_u,
- V_l_hi_u,
- V_r_lo_f,
- V_r_hi_f,
- V_r_lo_t,
- V_r_hi_t,
- V_r_lo_u,
- V_r_hi_u,
- Vspazz,
- Vend,
-
- V_T0,
- V_T1,
- V_F0,
- V_F1,
-
- V_a0,
- V_a1,
- V_f0,
- V_f1,
-
- V_p0,
- V_p1,
- V_p2,
- V_p3,
- V_p4,
-
- V_s0,
- V_s1,
- V_s2,
- V_s3,
- V_s4,
-
- C00,
- C01,
- C31,
- C32,
-
- O_l_lo,
- O_l_hi,
- O_r_lo,
- O_r_hi,
- O_t_lo,
- O_t_hi,
- O_l,
- O_r,
- O_l_rp,
- O_r_rp,
- O_t_rp,
- O_r0,
- O_r1,
- O_Zop,
-
- O_a0,
- O_a1,
-
- V_C0,
- V_C1,
-
- V_S0,
- V_S1,
-
- VOPS = 5,
- VLEN = 5,
- VARGS = 2,
-
- S00 = 0,
- Sc0,
- Sc1,
- Sc2,
- Sac3,
- Sac4,
- S10,
-
- SAgen = 0,
- SAclo,
- SAc32,
- SAchi,
- SAdgen,
- SAdclo,
- SAdc32,
- SAdchi,
-
- B0c = 0,
- Bca,
- Bac,
-
- T0i = 0,
- Tii,
-
- Bop0 = 0,
- Bop1,
-};
-
-/*
- * _testv:
- * CMPL lo,$0
- * JNE true
- * CMPL hi,$0
- * JNE true
- * GOTO false
- * false:
- * GOTO code
- * true:
- * GOTO patchme
- * code:
- */
-
-static uchar testi[][VLEN] =
-{
- {Vop, ONE, O_l_lo, C00},
- {V_s0, Vop, ONE, O_l_hi, C00},
- {V_s1, Vgo, V_s2, Vgo, V_s3},
- {VF, V_p0, V_p1, VT, V_p2},
- {Vgo, V_p3},
- {VT, V_p0, V_p1, VF, V_p2},
- {Vend},
-};
-
-/* shift left general case */
-static uchar shll00[][VLEN] =
-{
- {Vop, OGE, O_r, C32},
- {V_s0, Vinsl, ASHLL, O_r, O_l_rp},
- {Vins, ASHLL, O_r, O_l_lo, Vgo},
- {V_p0, V_s0},
- {Vins, ASHLL, O_r, O_l_lo},
- {Vins, AMOVL, O_l_lo, O_l_hi},
- {Vzero, O_l_lo, V_p0, Vend},
-};
-
-/* shift left rp, const < 32 */
-static uchar shllc0[][VLEN] =
-{
- {Vinsl, ASHLL, O_r, O_l_rp},
- {Vshll, O_r, O_l_lo, Vend},
-};
-
-/* shift left rp, const == 32 */
-static uchar shllc1[][VLEN] =
-{
- {Vins, AMOVL, O_l_lo, O_l_hi},
- {Vzero, O_l_lo, Vend},
-};
-
-/* shift left rp, const > 32 */
-static uchar shllc2[][VLEN] =
-{
- {Vshll, O_r, O_l_lo},
- {Vins, AMOVL, O_l_lo, O_l_hi},
- {Vzero, O_l_lo, Vend},
-};
-
-/* shift left addr, const == 32 */
-static uchar shllac3[][VLEN] =
-{
- {Vins, AMOVL, O_l_lo, O_t_hi},
- {Vzero, O_t_lo, Vend},
-};
-
-/* shift left addr, const > 32 */
-static uchar shllac4[][VLEN] =
-{
- {Vins, AMOVL, O_l_lo, O_t_hi},
- {Vshll, O_r, O_t_hi},
- {Vzero, O_t_lo, Vend},
-};
-
-/* shift left of constant */
-static uchar shll10[][VLEN] =
-{
- {Vop, OGE, O_r, C32},
- {V_s0, Vins, AMOVL, O_l_lo, O_t_lo},
- {Vins, AMOVL, O_l_hi, O_t_hi},
- {Vinsl, ASHLL, O_r, O_t_rp},
- {Vins, ASHLL, O_r, O_t_lo, Vgo},
- {V_p0, V_s0},
- {Vins, AMOVL, O_l_lo, O_t_hi},
- {V_l_lo_t, Vins, ASHLL, O_r, O_t_hi},
- {Vzero, O_t_lo, V_p0, Vend},
-};
-
-static uchar (*shlltab[])[VLEN] =
-{
- shll00,
- shllc0,
- shllc1,
- shllc2,
- shllac3,
- shllac4,
- shll10,
-};
-
-/* shift right general case */
-static uchar shrl00[][VLEN] =
-{
- {Vop, OGE, O_r, C32},
- {V_s0, Vinsr, ASHRL, O_r, O_l_rp},
- {Vins, O_a0, O_r, O_l_hi, Vgo},
- {V_p0, V_s0},
- {Vins, O_a0, O_r, O_l_hi},
- {Vins, AMOVL, O_l_hi, O_l_lo},
- {V_T1, Vzero, O_l_hi},
- {V_F1, Vins, ASARL, C31, O_l_hi},
- {V_p0, Vend},
-};
-
-/* shift right rp, const < 32 */
-static uchar shrlc0[][VLEN] =
-{
- {Vinsr, ASHRL, O_r, O_l_rp},
- {Vins, O_a0, O_r, O_l_hi, Vend},
-};
-
-/* shift right rp, const == 32 */
-static uchar shrlc1[][VLEN] =
-{
- {Vins, AMOVL, O_l_hi, O_l_lo},
- {V_T1, Vzero, O_l_hi},
- {V_F1, Vins, ASARL, C31, O_l_hi},
- {Vend},
-};
-
-/* shift right rp, const > 32 */
-static uchar shrlc2[][VLEN] =
-{
- {Vins, O_a0, O_r, O_l_hi},
- {Vins, AMOVL, O_l_hi, O_l_lo},
- {V_T1, Vzero, O_l_hi},
- {V_F1, Vins, ASARL, C31, O_l_hi},
- {Vend},
-};
-
-/* shift right addr, const == 32 */
-static uchar shrlac3[][VLEN] =
-{
- {Vins, AMOVL, O_l_hi, O_t_lo},
- {V_T1, Vzero, O_t_hi},
- {V_F1, Vins, AMOVL, O_t_lo, O_t_hi},
- {V_F1, Vins, ASARL, C31, O_t_hi},
- {Vend},
-};
-
-/* shift right addr, const > 32 */
-static uchar shrlac4[][VLEN] =
-{
- {Vins, AMOVL, O_l_hi, O_t_lo},
- {Vins, O_a0, O_r, O_t_lo},
- {V_T1, Vzero, O_t_hi},
- {V_F1, Vins, AMOVL, O_t_lo, O_t_hi},
- {V_F1, Vins, ASARL, C31, O_t_hi},
- {Vend},
-};
-
-/* shift right of constant */
-static uchar shrl10[][VLEN] =
-{
- {Vop, OGE, O_r, C32},
- {V_s0, Vins, AMOVL, O_l_lo, O_t_lo},
- {Vins, AMOVL, O_l_hi, O_t_hi},
- {Vinsr, ASHRL, O_r, O_t_rp},
- {Vins, O_a0, O_r, O_t_hi, Vgo},
- {V_p0, V_s0},
- {Vins, AMOVL, O_l_hi, O_t_lo},
- {V_l_hi_t, Vins, O_a0, O_r, O_t_lo},
- {V_l_hi_u, V_S1},
- {V_T1, Vzero, O_t_hi, V_p0},
- {V_F1, Vins, AMOVL, O_t_lo, O_t_hi},
- {V_F1, Vins, ASARL, C31, O_t_hi},
- {Vend},
-};
-
-static uchar (*shrltab[])[VLEN] =
-{
- shrl00,
- shrlc0,
- shrlc1,
- shrlc2,
- shrlac3,
- shrlac4,
- shrl10,
-};
-
-/* shift asop left general case */
-static uchar asshllgen[][VLEN] =
-{
- {V_a0, V_a1},
- {Vop, OGE, O_r, C32},
- {V_s0, Vins, AMOVL, O_l_lo, O_r0},
- {Vins, AMOVL, O_l_hi, O_r1},
- {Vinsla, ASHLL, O_r, O_r0},
- {Vins, ASHLL, O_r, O_r0},
- {Vins, AMOVL, O_r1, O_l_hi},
- {Vins, AMOVL, O_r0, O_l_lo, Vgo},
- {V_p0, V_s0},
- {Vins, AMOVL, O_l_lo, O_r0},
- {Vzero, O_l_lo},
- {Vins, ASHLL, O_r, O_r0},
- {Vins, AMOVL, O_r0, O_l_hi, V_p0},
- {V_f0, V_f1, Vend},
-};
-
-/* shift asop left, const < 32 */
-static uchar asshllclo[][VLEN] =
-{
- {V_a0, V_a1},
- {Vins, AMOVL, O_l_lo, O_r0},
- {Vins, AMOVL, O_l_hi, O_r1},
- {Vinsla, ASHLL, O_r, O_r0},
- {Vshll, O_r, O_r0},
- {Vins, AMOVL, O_r1, O_l_hi},
- {Vins, AMOVL, O_r0, O_l_lo},
- {V_f0, V_f1, Vend},
-};
-
-/* shift asop left, const == 32 */
-static uchar asshllc32[][VLEN] =
-{
- {V_a0},
- {Vins, AMOVL, O_l_lo, O_r0},
- {Vzero, O_l_lo},
- {Vins, AMOVL, O_r0, O_l_hi},
- {V_f0, Vend},
-};
-
-/* shift asop left, const > 32 */
-static uchar asshllchi[][VLEN] =
-{
- {V_a0},
- {Vins, AMOVL, O_l_lo, O_r0},
- {Vzero, O_l_lo},
- {Vshll, O_r, O_r0},
- {Vins, AMOVL, O_r0, O_l_hi},
- {V_f0, Vend},
-};
-
-/* shift asop dest left general case */
-static uchar asdshllgen[][VLEN] =
-{
- {Vop, OGE, O_r, C32},
- {V_s0, Vins, AMOVL, O_l_lo, O_t_lo},
- {Vins, AMOVL, O_l_hi, O_t_hi},
- {Vinsl, ASHLL, O_r, O_t_rp},
- {Vins, ASHLL, O_r, O_t_lo},
- {Vins, AMOVL, O_t_hi, O_l_hi},
- {Vins, AMOVL, O_t_lo, O_l_lo, Vgo},
- {V_p0, V_s0},
- {Vins, AMOVL, O_l_lo, O_t_hi},
- {Vzero, O_l_lo},
- {Vins, ASHLL, O_r, O_t_hi},
- {Vzero, O_t_lo},
- {Vins, AMOVL, O_t_hi, O_l_hi, V_p0},
- {Vend},
-};
-
-/* shift asop dest left, const < 32 */
-static uchar asdshllclo[][VLEN] =
-{
- {Vins, AMOVL, O_l_lo, O_t_lo},
- {Vins, AMOVL, O_l_hi, O_t_hi},
- {Vinsl, ASHLL, O_r, O_t_rp},
- {Vshll, O_r, O_t_lo},
- {Vins, AMOVL, O_t_hi, O_l_hi},
- {Vins, AMOVL, O_t_lo, O_l_lo},
- {Vend},
-};
-
-/* shift asop dest left, const == 32 */
-static uchar asdshllc32[][VLEN] =
-{
- {Vins, AMOVL, O_l_lo, O_t_hi},
- {Vzero, O_t_lo},
- {Vins, AMOVL, O_t_hi, O_l_hi},
- {Vins, AMOVL, O_t_lo, O_l_lo},
- {Vend},
-};
-
-/* shift asop dest, const > 32 */
-static uchar asdshllchi[][VLEN] =
-{
- {Vins, AMOVL, O_l_lo, O_t_hi},
- {Vzero, O_t_lo},
- {Vshll, O_r, O_t_hi},
- {Vins, AMOVL, O_t_lo, O_l_lo},
- {Vins, AMOVL, O_t_hi, O_l_hi},
- {Vend},
-};
-
-static uchar (*asshlltab[])[VLEN] =
-{
- asshllgen,
- asshllclo,
- asshllc32,
- asshllchi,
- asdshllgen,
- asdshllclo,
- asdshllc32,
- asdshllchi,
-};
-
-/* shift asop right general case */
-static uchar asshrlgen[][VLEN] =
-{
- {V_a0, V_a1},
- {Vop, OGE, O_r, C32},
- {V_s0, Vins, AMOVL, O_l_lo, O_r0},
- {Vins, AMOVL, O_l_hi, O_r1},
- {Vinsra, ASHRL, O_r, O_r0},
- {Vinsx, Bop0, O_r, O_r1},
- {Vins, AMOVL, O_r0, O_l_lo},
- {Vins, AMOVL, O_r1, O_l_hi, Vgo},
- {V_p0, V_s0},
- {Vins, AMOVL, O_l_hi, O_r0},
- {Vinsx, Bop0, O_r, O_r0},
- {V_T1, Vzero, O_l_hi},
- {Vins, AMOVL, O_r0, O_l_lo},
- {V_F1, Vins, ASARL, C31, O_r0},
- {V_F1, Vins, AMOVL, O_r0, O_l_hi},
- {V_p0, V_f0, V_f1, Vend},
-};
-
-/* shift asop right, const < 32 */
-static uchar asshrlclo[][VLEN] =
-{
- {V_a0, V_a1},
- {Vins, AMOVL, O_l_lo, O_r0},
- {Vins, AMOVL, O_l_hi, O_r1},
- {Vinsra, ASHRL, O_r, O_r0},
- {Vinsx, Bop0, O_r, O_r1},
- {Vins, AMOVL, O_r0, O_l_lo},
- {Vins, AMOVL, O_r1, O_l_hi},
- {V_f0, V_f1, Vend},
-};
-
-/* shift asop right, const == 32 */
-static uchar asshrlc32[][VLEN] =
-{
- {V_a0},
- {Vins, AMOVL, O_l_hi, O_r0},
- {V_T1, Vzero, O_l_hi},
- {Vins, AMOVL, O_r0, O_l_lo},
- {V_F1, Vins, ASARL, C31, O_r0},
- {V_F1, Vins, AMOVL, O_r0, O_l_hi},
- {V_f0, Vend},
-};
-
-/* shift asop right, const > 32 */
-static uchar asshrlchi[][VLEN] =
-{
- {V_a0},
- {Vins, AMOVL, O_l_hi, O_r0},
- {V_T1, Vzero, O_l_hi},
- {Vinsx, Bop0, O_r, O_r0},
- {Vins, AMOVL, O_r0, O_l_lo},
- {V_F1, Vins, ASARL, C31, O_r0},
- {V_F1, Vins, AMOVL, O_r0, O_l_hi},
- {V_f0, Vend},
-};
-
-/* shift asop dest right general case */
-static uchar asdshrlgen[][VLEN] =
-{
- {Vop, OGE, O_r, C32},
- {V_s0, Vins, AMOVL, O_l_lo, O_t_lo},
- {Vins, AMOVL, O_l_hi, O_t_hi},
- {Vinsr, ASHRL, O_r, O_t_rp},
- {Vinsx, Bop0, O_r, O_t_hi},
- {Vins, AMOVL, O_t_lo, O_l_lo},
- {Vins, AMOVL, O_t_hi, O_l_hi, Vgo},
- {V_p0, V_s0},
- {Vins, AMOVL, O_l_hi, O_t_lo},
- {V_T1, Vzero, O_t_hi},
- {Vinsx, Bop0, O_r, O_t_lo},
- {V_F1, Vins, AMOVL, O_t_lo, O_t_hi},
- {V_F1, Vins, ASARL, C31, O_t_hi},
- {Vins, AMOVL, O_t_hi, O_l_hi, V_p0},
- {Vend},
-};
-
-/* shift asop dest right, const < 32 */
-static uchar asdshrlclo[][VLEN] =
-{
- {Vins, AMOVL, O_l_lo, O_t_lo},
- {Vins, AMOVL, O_l_hi, O_t_hi},
- {Vinsr, ASHRL, O_r, O_t_rp},
- {Vinsx, Bop0, O_r, O_t_hi},
- {Vins, AMOVL, O_t_lo, O_l_lo},
- {Vins, AMOVL, O_t_hi, O_l_hi},
- {Vend},
-};
-
-/* shift asop dest right, const == 32 */
-static uchar asdshrlc32[][VLEN] =
-{
- {Vins, AMOVL, O_l_hi, O_t_lo},
- {V_T1, Vzero, O_t_hi},
- {V_F1, Vins, AMOVL, O_t_lo, O_t_hi},
- {V_F1, Vins, ASARL, C31, O_t_hi},
- {Vins, AMOVL, O_t_lo, O_l_lo},
- {Vins, AMOVL, O_t_hi, O_l_hi},
- {Vend},
-};
-
-/* shift asop dest, const > 32 */
-static uchar asdshrlchi[][VLEN] =
-{
- {Vins, AMOVL, O_l_hi, O_t_lo},
- {V_T1, Vzero, O_t_hi},
- {Vinsx, Bop0, O_r, O_t_lo},
- {V_T1, Vins, AMOVL, O_t_hi, O_l_hi},
- {V_T1, Vins, AMOVL, O_t_lo, O_l_lo},
- {V_F1, Vins, AMOVL, O_t_lo, O_t_hi},
- {V_F1, Vins, ASARL, C31, O_t_hi},
- {V_F1, Vins, AMOVL, O_t_lo, O_l_lo},
- {V_F1, Vins, AMOVL, O_t_hi, O_l_hi},
- {Vend},
-};
-
-static uchar (*asshrltab[])[VLEN] =
-{
- asshrlgen,
- asshrlclo,
- asshrlc32,
- asshrlchi,
- asdshrlgen,
- asdshrlclo,
- asdshrlc32,
- asdshrlchi,
-};
-
-static uchar shrlargs[] = { ASHRL, 1 };
-static uchar sarlargs[] = { ASARL, 0 };
-
-/* ++ -- */
-static uchar incdec[][VLEN] =
-{
- {Vinsx, Bop0, C01, O_l_lo},
- {Vinsx, Bop1, C00, O_l_hi, Vend},
-};
-
-/* ++ -- *p */
-static uchar incdecpre[][VLEN] =
-{
- {Vins, AMOVL, O_l_lo, O_t_lo},
- {Vins, AMOVL, O_l_hi, O_t_hi},
- {Vinsx, Bop0, C01, O_t_lo},
- {Vinsx, Bop1, C00, O_t_hi},
- {Vins, AMOVL, O_t_lo, O_l_lo},
- {Vins, AMOVL, O_t_hi, O_l_hi, Vend},
-};
-
-/* *p ++ -- */
-static uchar incdecpost[][VLEN] =
-{
- {Vins, AMOVL, O_l_lo, O_t_lo},
- {Vins, AMOVL, O_l_hi, O_t_hi},
- {Vinsx, Bop0, C01, O_l_lo},
- {Vinsx, Bop1, C00, O_l_hi, Vend},
-};
-
-/* binop rp, rp */
-static uchar binop00[][VLEN] =
-{
- {Vinsx, Bop0, O_r_lo, O_l_lo},
- {Vinsx, Bop1, O_r_hi, O_l_hi, Vend},
- {Vend},
-};
-
-/* binop rp, addr */
-static uchar binoptmp[][VLEN] =
-{
- {V_a0, Vins, AMOVL, O_r_lo, O_r0},
- {Vinsx, Bop0, O_r0, O_l_lo},
- {Vins, AMOVL, O_r_hi, O_r0},
- {Vinsx, Bop1, O_r0, O_l_hi},
- {V_f0, Vend},
-};
-
-/* binop t = *a op *b */
-static uchar binop11[][VLEN] =
-{
- {Vins, AMOVL, O_l_lo, O_t_lo},
- {Vinsx, Bop0, O_r_lo, O_t_lo},
- {Vins, AMOVL, O_l_hi, O_t_hi},
- {Vinsx, Bop1, O_r_hi, O_t_hi, Vend},
-};
-
-/* binop t = rp +- c */
-static uchar add0c[][VLEN] =
-{
- {V_r_lo_t, Vinsx, Bop0, O_r_lo, O_l_lo},
- {V_r_lo_f, Vamv, Bop0, Bop1},
- {Vinsx, Bop1, O_r_hi, O_l_hi},
- {Vend},
-};
-
-/* binop t = rp & c */
-static uchar and0c[][VLEN] =
-{
- {V_r_lo_t, Vinsx, Bop0, O_r_lo, O_l_lo},
- {V_r_lo_f, Vins, AMOVL, C00, O_l_lo},
- {V_r_hi_t, Vinsx, Bop1, O_r_hi, O_l_hi},
- {V_r_hi_f, Vins, AMOVL, C00, O_l_hi},
- {Vend},
-};
-
-/* binop t = rp | c */
-static uchar or0c[][VLEN] =
-{
- {V_r_lo_t, Vinsx, Bop0, O_r_lo, O_l_lo},
- {V_r_hi_t, Vinsx, Bop1, O_r_hi, O_l_hi},
- {Vend},
-};
-
-/* binop t = c - rp */
-static uchar sub10[][VLEN] =
-{
- {V_a0, Vins, AMOVL, O_l_lo, O_r0},
- {Vinsx, Bop0, O_r_lo, O_r0},
- {Vins, AMOVL, O_l_hi, O_r_lo},
- {Vinsx, Bop1, O_r_hi, O_r_lo},
- {Vspazz, V_f0, Vend},
-};
-
-/* binop t = c + *b */
-static uchar addca[][VLEN] =
-{
- {Vins, AMOVL, O_r_lo, O_t_lo},
- {V_l_lo_t, Vinsx, Bop0, O_l_lo, O_t_lo},
- {V_l_lo_f, Vamv, Bop0, Bop1},
- {Vins, AMOVL, O_r_hi, O_t_hi},
- {Vinsx, Bop1, O_l_hi, O_t_hi},
- {Vend},
-};
-
-/* binop t = c & *b */
-static uchar andca[][VLEN] =
-{
- {V_l_lo_t, Vins, AMOVL, O_r_lo, O_t_lo},
- {V_l_lo_t, Vinsx, Bop0, O_l_lo, O_t_lo},
- {V_l_lo_f, Vzero, O_t_lo},
- {V_l_hi_t, Vins, AMOVL, O_r_hi, O_t_hi},
- {V_l_hi_t, Vinsx, Bop1, O_l_hi, O_t_hi},
- {V_l_hi_f, Vzero, O_t_hi},
- {Vend},
-};
-
-/* binop t = c | *b */
-static uchar orca[][VLEN] =
-{
- {Vins, AMOVL, O_r_lo, O_t_lo},
- {V_l_lo_t, Vinsx, Bop0, O_l_lo, O_t_lo},
- {Vins, AMOVL, O_r_hi, O_t_hi},
- {V_l_hi_t, Vinsx, Bop1, O_l_hi, O_t_hi},
- {Vend},
-};
-
-/* binop t = c - *b */
-static uchar subca[][VLEN] =
-{
- {Vins, AMOVL, O_l_lo, O_t_lo},
- {Vins, AMOVL, O_l_hi, O_t_hi},
- {Vinsx, Bop0, O_r_lo, O_t_lo},
- {Vinsx, Bop1, O_r_hi, O_t_hi},
- {Vend},
-};
-
-/* binop t = *a +- c */
-static uchar addac[][VLEN] =
-{
- {Vins, AMOVL, O_l_lo, O_t_lo},
- {V_r_lo_t, Vinsx, Bop0, O_r_lo, O_t_lo},
- {V_r_lo_f, Vamv, Bop0, Bop1},
- {Vins, AMOVL, O_l_hi, O_t_hi},
- {Vinsx, Bop1, O_r_hi, O_t_hi},
- {Vend},
-};
-
-/* binop t = *a | c */
-static uchar orac[][VLEN] =
-{
- {Vins, AMOVL, O_l_lo, O_t_lo},
- {V_r_lo_t, Vinsx, Bop0, O_r_lo, O_t_lo},
- {Vins, AMOVL, O_l_hi, O_t_hi},
- {V_r_hi_t, Vinsx, Bop1, O_r_hi, O_t_hi},
- {Vend},
-};
-
-/* binop t = *a & c */
-static uchar andac[][VLEN] =
-{
- {V_r_lo_t, Vins, AMOVL, O_l_lo, O_t_lo},
- {V_r_lo_t, Vinsx, Bop0, O_r_lo, O_t_lo},
- {V_r_lo_f, Vzero, O_t_lo},
- {V_r_hi_t, Vins, AMOVL, O_l_hi, O_t_hi},
- {V_r_hi_t, Vinsx, Bop0, O_r_hi, O_t_hi},
- {V_r_hi_f, Vzero, O_t_hi},
- {Vend},
-};
-
-static uchar ADDargs[] = { AADDL, AADCL };
-static uchar ANDargs[] = { AANDL, AANDL };
-static uchar ORargs[] = { AORL, AORL };
-static uchar SUBargs[] = { ASUBL, ASBBL };
-static uchar XORargs[] = { AXORL, AXORL };
-
-static uchar (*ADDtab[])[VLEN] =
-{
- add0c, addca, addac,
-};
-
-static uchar (*ANDtab[])[VLEN] =
-{
- and0c, andca, andac,
-};
-
-static uchar (*ORtab[])[VLEN] =
-{
- or0c, orca, orac,
-};
-
-static uchar (*SUBtab[])[VLEN] =
-{
- add0c, subca, addac,
-};
-
-/* mul of const32 */
-static uchar mulc32[][VLEN] =
-{
- {V_a0, Vop, ONE, O_l_hi, C00},
- {V_s0, Vins, AMOVL, O_r_lo, O_r0},
- {Vins, AMULL, O_r0, O_Zop},
- {Vgo, V_p0, V_s0},
- {Vins, AMOVL, O_l_hi, O_r0},
- {Vmul, O_r_lo, O_r0},
- {Vins, AMOVL, O_r_lo, O_l_hi},
- {Vins, AMULL, O_l_hi, O_Zop},
- {Vins, AADDL, O_r0, O_l_hi},
- {V_f0, V_p0, Vend},
-};
-
-/* mul of const64 */
-static uchar mulc64[][VLEN] =
-{
- {V_a0, Vins, AMOVL, O_r_hi, O_r0},
- {Vop, OOR, O_l_hi, O_r0},
- {Vop, ONE, O_r0, C00},
- {V_s0, Vins, AMOVL, O_r_lo, O_r0},
- {Vins, AMULL, O_r0, O_Zop},
- {Vgo, V_p0, V_s0},
- {Vmul, O_r_lo, O_l_hi},
- {Vins, AMOVL, O_l_lo, O_r0},
- {Vmul, O_r_hi, O_r0},
- {Vins, AADDL, O_l_hi, O_r0},
- {Vins, AMOVL, O_r_lo, O_l_hi},
- {Vins, AMULL, O_l_hi, O_Zop},
- {Vins, AADDL, O_r0, O_l_hi},
- {V_f0, V_p0, Vend},
-};
-
-/* mul general */
-static uchar mull[][VLEN] =
-{
- {V_a0, Vins, AMOVL, O_r_hi, O_r0},
- {Vop, OOR, O_l_hi, O_r0},
- {Vop, ONE, O_r0, C00},
- {V_s0, Vins, AMOVL, O_r_lo, O_r0},
- {Vins, AMULL, O_r0, O_Zop},
- {Vgo, V_p0, V_s0},
- {Vins, AIMULL, O_r_lo, O_l_hi},
- {Vins, AMOVL, O_l_lo, O_r0},
- {Vins, AIMULL, O_r_hi, O_r0},
- {Vins, AADDL, O_l_hi, O_r0},
- {Vins, AMOVL, O_r_lo, O_l_hi},
- {Vins, AMULL, O_l_hi, O_Zop},
- {Vins, AADDL, O_r0, O_l_hi},
- {V_f0, V_p0, Vend},
-};
-
-/* cast rp l to rp t */
-static uchar castrp[][VLEN] =
-{
- {Vmv, O_l, O_t_lo},
- {VT, Vins, AMOVL, O_t_lo, O_t_hi},
- {VT, Vins, ASARL, C31, O_t_hi},
- {VF, Vzero, O_t_hi},
- {Vend},
-};
-
-/* cast rp l to addr t */
-static uchar castrpa[][VLEN] =
-{
- {VT, V_a0, Vmv, O_l, O_r0},
- {VT, Vins, AMOVL, O_r0, O_t_lo},
- {VT, Vins, ASARL, C31, O_r0},
- {VT, Vins, AMOVL, O_r0, O_t_hi},
- {VT, V_f0},
- {VF, Vmv, O_l, O_t_lo},
- {VF, Vzero, O_t_hi},
- {Vend},
-};
-
-static uchar netab0i[][VLEN] =
-{
- {Vop, ONE, O_l_lo, O_r_lo},
- {V_s0, Vop, ONE, O_l_hi, O_r_hi},
- {V_s1, Vgo, V_s2, Vgo, V_s3},
- {VF, V_p0, V_p1, VT, V_p2},
- {Vgo, V_p3},
- {VT, V_p0, V_p1, VF, V_p2},
- {Vend},
-};
-
-static uchar netabii[][VLEN] =
-{
- {V_a0, Vins, AMOVL, O_l_lo, O_r0},
- {Vop, ONE, O_r0, O_r_lo},
- {V_s0, Vins, AMOVL, O_l_hi, O_r0},
- {Vop, ONE, O_r0, O_r_hi},
- {V_s1, Vgo, V_s2, Vgo, V_s3},
- {VF, V_p0, V_p1, VT, V_p2},
- {Vgo, V_p3},
- {VT, V_p0, V_p1, VF, V_p2},
- {V_f0, Vend},
-};
-
-static uchar cmptab0i[][VLEN] =
-{
- {Vopx, Bop0, O_l_hi, O_r_hi},
- {V_s0, Vins0, AJNE},
- {V_s1, Vopx, Bop1, O_l_lo, O_r_lo},
- {V_s2, Vgo, V_s3, Vgo, V_s4},
- {VT, V_p1, V_p3},
- {VF, V_p0, V_p2},
- {Vgo, V_p4},
- {VT, V_p0, V_p2},
- {VF, V_p1, V_p3},
- {Vend},
-};
-
-static uchar cmptabii[][VLEN] =
-{
- {V_a0, Vins, AMOVL, O_l_hi, O_r0},
- {Vopx, Bop0, O_r0, O_r_hi},
- {V_s0, Vins0, AJNE},
- {V_s1, Vins, AMOVL, O_l_lo, O_r0},
- {Vopx, Bop1, O_r0, O_r_lo},
- {V_s2, Vgo, V_s3, Vgo, V_s4},
- {VT, V_p1, V_p3},
- {VF, V_p0, V_p2},
- {Vgo, V_p4},
- {VT, V_p0, V_p2},
- {VF, V_p1, V_p3},
- {V_f0, Vend},
-};
-
-static uchar (*NEtab[])[VLEN] =
-{
- netab0i, netabii,
-};
-
-static uchar (*cmptab[])[VLEN] =
-{
- cmptab0i, cmptabii,
-};
-
-static uchar GEargs[] = { OGT, OHS };
-static uchar GTargs[] = { OGT, OHI };
-static uchar HIargs[] = { OHI, OHI };
-static uchar HSargs[] = { OHI, OHS };
-
-/* Big Generator */
-static void
-biggen(Node *l, Node *r, Node *t, int true, uchar code[][VLEN], uchar *a)
-{
- int i, j, g, oc, op, lo, ro, to, xo, *xp;
- Type *lt;
- Prog *pr[VOPS];
- Node *ot, *tl, *tr, tmps[2];
- uchar *c, (*cp)[VLEN], args[VARGS];
-
- if(a != nil)
- memmove(args, a, VARGS);
-//print("biggen %d %d %d\n", args[0], args[1], args[2]);
-//if(l) prtree(l, "l");
-//if(r) prtree(r, "r");
-//if(t) prtree(t, "t");
- lo = ro = to = 0;
- cp = code;
-
- for (;;) {
- c = *cp++;
- g = 1;
- i = 0;
-//print("code %d %d %d %d %d\n", c[0], c[1], c[2], c[3], c[4]);
- for(;;) {
- switch(op = c[i]) {
- case Vgo:
- if(g)
- gbranch(OGOTO);
- i++;
- break;
-
- case Vamv:
- i += 3;
- if(i > VLEN) {
- diag(l, "bad Vop");
- return;
- }
- if(g)
- args[c[i - 1]] = args[c[i - 2]];
- break;
-
- case Vzero:
- i += 2;
- if(i > VLEN) {
- diag(l, "bad Vop");
- return;
- }
- j = i - 1;
- goto op;
-
- case Vspazz: // nasty hack to save a reg in SUB
-//print("spazz\n");
- if(g) {
-//print("hi %R lo %R t %R\n", r->right->reg, r->left->reg, tmps[0].reg);
- ot = r->right;
- r->right = r->left;
- tl = new(0, Z, Z);
- *tl = tmps[0];
- r->left = tl;
- tmps[0] = *ot;
-//print("hi %R lo %R t %R\n", r->right->reg, r->left->reg, tmps[0].reg);
- }
- i++;
- break;
-
- case Vmv:
- case Vmul:
- case Vshll:
- i += 3;
- if(i > VLEN) {
- diag(l, "bad Vop");
- return;
- }
- j = i - 2;
- goto op;
-
- case Vins0:
- i += 2;
- if(i > VLEN) {
- diag(l, "bad Vop");
- return;
- }
- gins(c[i - 1], Z, Z);
- break;
-
- case Vop:
- case Vopx:
- case Vins:
- case Vinsl:
- case Vinsr:
- case Vinsla:
- case Vinsra:
- case Vinsx:
- i += 4;
- if(i > VLEN) {
- diag(l, "bad Vop");
- return;
- }
- j = i - 2;
- goto op;
-
- op:
- if(!g)
- break;
- tl = Z;
- tr = Z;
- for(; j < i; j++) {
- switch(c[j]) {
- case C00:
- ot = nodconst(0);
- break;
- case C01:
- ot = nodconst(1);
- break;
- case C31:
- ot = nodconst(31);
- break;
- case C32:
- ot = nodconst(32);
- break;
-
- case O_l:
- case O_l_lo:
- ot = l; xp = &lo; xo = 0;
- goto op0;
- case O_l_hi:
- ot = l; xp = &lo; xo = SZ_LONG;
- goto op0;
- case O_r:
- case O_r_lo:
- ot = r; xp = &ro; xo = 0;
- goto op0;
- case O_r_hi:
- ot = r; xp = &ro; xo = SZ_LONG;
- goto op0;
- case O_t_lo:
- ot = t; xp = &to; xo = 0;
- goto op0;
- case O_t_hi:
- ot = t; xp = &to; xo = SZ_LONG;
- goto op0;
- case O_l_rp:
- ot = l;
- break;
- case O_r_rp:
- ot = r;
- break;
- case O_t_rp:
- ot = t;
- break;
- case O_r0:
- case O_r1:
- ot = &tmps[c[j] - O_r0];
- break;
- case O_Zop:
- ot = Z;
- break;
-
- op0:
- switch(ot->op) {
- case OCONST:
- if(xo)
- ot = hi64(ot);
- else
- ot = lo64(ot);
- break;
- case OREGPAIR:
- if(xo)
- ot = ot->right;
- else
- ot = ot->left;
- break;
- case OREGISTER:
- break;
- default:
- if(xo != *xp) {
- ot->xoffset += xo - *xp;
- *xp = xo;
- }
- }
- break;
-
- default:
- diag(l, "bad V_lop");
- return;
- }
- if(tl == nil)
- tl = ot;
- else
- tr = ot;
- }
- if(op == Vzero) {
- zeroregm(tl);
- break;
- }
- oc = c[i - 3];
- if(op == Vinsx || op == Vopx) {
-//print("%d -> %d\n", oc, args[oc]);
- oc = args[oc];
- }
- else {
- switch(oc) {
- case O_a0:
- case O_a1:
- oc = args[oc - O_a0];
- break;
- }
- }
- switch(op) {
- case Vmul:
- mulgen(tr->type, tl, tr);
- break;
- case Vmv:
- gmove(tl, tr);
- break;
- case Vshll:
- shiftit(tr->type, tl, tr);
- break;
- case Vop:
- case Vopx:
- gopcode(oc, types[TULONG], tl, tr);
- break;
- case Vins:
- case Vinsx:
- gins(oc, tl, tr);
- break;
- case Vinsl:
- gins(oc, tl, tr->right);
- p->from.index = tr->left->reg;
- break;
- case Vinsr:
- gins(oc, tl, tr->left);
- p->from.index = tr->right->reg;
- break;
- case Vinsla:
- gins(oc, tl, tr + 1);
- p->from.index = tr->reg;
- break;
- case Vinsra:
- gins(oc, tl, tr);
- p->from.index = (tr + 1)->reg;
- break;
- }
- break;
-
- case VT:
- g = true;
- i++;
- break;
- case VF:
- g = !true;
- i++;
- break;
-
- case V_T0: case V_T1:
- g = args[op - V_T0];
- i++;
- break;
-
- case V_F0: case V_F1:
- g = !args[op - V_F0];
- i++;
- break;
-
- case V_C0: case V_C1:
- if(g)
- args[op - V_C0] = 0;
- i++;
- break;
-
- case V_S0: case V_S1:
- if(g)
- args[op - V_S0] = 1;
- i++;
- break;
-
- case V_l_lo_f:
- g = lo64v(l) == 0;
- i++;
- break;
- case V_l_hi_f:
- g = hi64v(l) == 0;
- i++;
- break;
- case V_l_lo_t:
- g = lo64v(l) != 0;
- i++;
- break;
- case V_l_hi_t:
- g = hi64v(l) != 0;
- i++;
- break;
- case V_l_lo_u:
- g = lo64v(l) >= 0;
- i++;
- break;
- case V_l_hi_u:
- g = hi64v(l) >= 0;
- i++;
- break;
- case V_r_lo_f:
- g = lo64v(r) == 0;
- i++;
- break;
- case V_r_hi_f:
- g = hi64v(r) == 0;
- i++;
- break;
- case V_r_lo_t:
- g = lo64v(r) != 0;
- i++;
- break;
- case V_r_hi_t:
- g = hi64v(r) != 0;
- i++;
- break;
- case V_r_lo_u:
- g = lo64v(r) >= 0;
- i++;
- break;
- case V_r_hi_u:
- g = hi64v(r) >= 0;
- i++;
- break;
-
- case Vend:
- goto out;
-
- case V_a0: case V_a1:
- if(g) {
- lt = l->type;
- l->type = types[TULONG];
- regalloc(&tmps[op - V_a0], l, Z);
- l->type = lt;
- }
- i++;
- break;
-
- case V_f0: case V_f1:
- if(g)
- regfree(&tmps[op - V_f0]);
- i++;
- break;
-
- case V_p0: case V_p1: case V_p2: case V_p3: case V_p4:
- if(g)
- patch(pr[op - V_p0], pc);
- i++;
- break;
-
- case V_s0: case V_s1: case V_s2: case V_s3: case V_s4:
- if(g)
- pr[op - V_s0] = p;
- i++;
- break;
-
- default:
- diag(l, "bad biggen: %d", op);
- return;
- }
- if(i == VLEN || c[i] == 0)
- break;
- }
- }
-out:
- if(lo)
- l->xoffset -= lo;
- if(ro)
- r->xoffset -= ro;
- if(to)
- t->xoffset -= to;
-}
-
-int
-cgen64(Node *n, Node *nn)
-{
- Type *dt;
- uchar *args, (*cp)[VLEN], (**optab)[VLEN];
- int li, ri, lri, dr, si, m, op, sh, cmp, true;
- Node *c, *d, *l, *r, *t, *s, nod1, nod2, nod3, nod4, nod5;
-
- if(debug['g']) {
- prtree(nn, "cgen64 lhs");
- prtree(n, "cgen64");
- print("AX = %d\n", reg[D_AX]);
- }
- cmp = 0;
- sh = 0;
-
- switch(n->op) {
- case ONEG:
- d = regpair(nn, n);
- sugen(n->left, d, 8);
- gins(ANOTL, Z, d->right);
- gins(ANEGL, Z, d->left);
- gins(ASBBL, nodconst(-1), d->right);
- break;
-
- case OCOM:
- if(!vaddr(n->left, 0) || !vaddr(nn, 0))
- d = regpair(nn, n);
- else
- return 0;
- sugen(n->left, d, 8);
- gins(ANOTL, Z, d->left);
- gins(ANOTL, Z, d->right);
- break;
-
- case OADD:
- optab = ADDtab;
- args = ADDargs;
- goto twoop;
- case OAND:
- optab = ANDtab;
- args = ANDargs;
- goto twoop;
- case OOR:
- optab = ORtab;
- args = ORargs;
- goto twoop;
- case OSUB:
- optab = SUBtab;
- args = SUBargs;
- goto twoop;
- case OXOR:
- optab = ORtab;
- args = XORargs;
- goto twoop;
- case OASHL:
- sh = 1;
- args = nil;
- optab = shlltab;
- goto twoop;
- case OLSHR:
- sh = 1;
- args = shrlargs;
- optab = shrltab;
- goto twoop;
- case OASHR:
- sh = 1;
- args = sarlargs;
- optab = shrltab;
- goto twoop;
- case OEQ:
- cmp = 1;
- args = nil;
- optab = nil;
- goto twoop;
- case ONE:
- cmp = 1;
- args = nil;
- optab = nil;
- goto twoop;
- case OLE:
- cmp = 1;
- args = nil;
- optab = nil;
- goto twoop;
- case OLT:
- cmp = 1;
- args = nil;
- optab = nil;
- goto twoop;
- case OGE:
- cmp = 1;
- args = nil;
- optab = nil;
- goto twoop;
- case OGT:
- cmp = 1;
- args = nil;
- optab = nil;
- goto twoop;
- case OHI:
- cmp = 1;
- args = nil;
- optab = nil;
- goto twoop;
- case OHS:
- cmp = 1;
- args = nil;
- optab = nil;
- goto twoop;
- case OLO:
- cmp = 1;
- args = nil;
- optab = nil;
- goto twoop;
- case OLS:
- cmp = 1;
- args = nil;
- optab = nil;
- goto twoop;
-
-twoop:
- dr = nn != Z && nn->op == OREGPAIR;
- l = vfunc(n->left, nn);
- if(sh)
- r = n->right;
- else
- r = vfunc(n->right, nn);
-
- li = l->op == ONAME || l->op == OINDREG || l->op == OCONST;
- ri = r->op == ONAME || r->op == OINDREG || r->op == OCONST;
-
-#define IMM(l, r) ((l) | ((r) << 1))
-
- lri = IMM(li, ri);
-
- /* find out what is so easy about some operands */
- if(li)
- li = whatof(l, sh | cmp);
- if(ri)
- ri = whatof(r, cmp);
-
- if(sh)
- goto shift;
-
- if(cmp)
- goto cmp;
-
- /* evaluate hard subexps, stealing nn if possible. */
- switch(lri) {
- case IMM(0, 0):
- bin00:
- if(l->complex > r->complex) {
- if(dr)
- t = nn;
- else
- t = regpair(Z, n);
- sugen(l, t, 8);
- l = t;
- t = regpair(Z, n);
- sugen(r, t, 8);
- r = t;
- }
- else {
- t = regpair(Z, n);
- sugen(r, t, 8);
- r = t;
- if(dr)
- t = nn;
- else
- t = regpair(Z, n);
- sugen(l, t, 8);
- l = t;
- }
- break;
- case IMM(0, 1):
- if(dr)
- t = nn;
- else
- t = regpair(Z, n);
- sugen(l, t, 8);
- l = t;
- break;
- case IMM(1, 0):
- if(n->op == OSUB && l->op == OCONST && hi64v(l) == 0) {
- lri = IMM(0, 0);
- goto bin00;
- }
- if(dr)
- t = nn;
- else
- t = regpair(Z, n);
- sugen(r, t, 8);
- r = t;
- break;
- case IMM(1, 1):
- break;
- }
-
-#define WW(l, r) ((l) | ((r) << 2))
- d = Z;
- dt = nn->type;
- nn->type = types[TLONG];
-
- switch(lri) {
- case IMM(0, 0):
- biggen(l, r, Z, 0, binop00, args);
- break;
- case IMM(0, 1):
- switch(ri) {
- case WNONE:
- diag(r, "bad whatof\n");
- break;
- case WCONST:
- biggen(l, r, Z, 0, optab[B0c], args);
- break;
- case WHARD:
- reglcgen(&nod2, r, Z);
- r = &nod2;
- /* fall thru */
- case WADDR:
- biggen(l, r, Z, 0, binoptmp, args);
- if(ri == WHARD)
- regfree(r);
- break;
- }
- break;
- case IMM(1, 0):
- if(n->op == OSUB) {
- switch(li) {
- case WNONE:
- diag(l, "bad whatof\n");
- break;
- case WHARD:
- reglcgen(&nod2, l, Z);
- l = &nod2;
- /* fall thru */
- case WADDR:
- case WCONST:
- biggen(l, r, Z, 0, sub10, args);
- break;
- }
- if(li == WHARD)
- regfree(l);
- }
- else {
- switch(li) {
- case WNONE:
- diag(l, "bad whatof\n");
- break;
- case WCONST:
- biggen(r, l, Z, 0, optab[B0c], args);
- break;
- case WHARD:
- reglcgen(&nod2, l, Z);
- l = &nod2;
- /* fall thru */
- case WADDR:
- biggen(r, l, Z, 0, binoptmp, args);
- if(li == WHARD)
- regfree(l);
- break;
- }
- }
- break;
- case IMM(1, 1):
- switch(WW(li, ri)) {
- case WW(WCONST, WHARD):
- if(r->op == ONAME && n->op == OAND && reduxv(l))
- ri = WADDR;
- break;
- case WW(WHARD, WCONST):
- if(l->op == ONAME && n->op == OAND && reduxv(r))
- li = WADDR;
- break;
- }
- if(li == WHARD) {
- reglcgen(&nod3, l, Z);
- l = &nod3;
- }
- if(ri == WHARD) {
- reglcgen(&nod2, r, Z);
- r = &nod2;
- }
- d = regpair(nn, n);
- instpair(d, Z);
- switch(WW(li, ri)) {
- case WW(WCONST, WADDR):
- case WW(WCONST, WHARD):
- biggen(l, r, d, 0, optab[Bca], args);
- break;
-
- case WW(WADDR, WCONST):
- case WW(WHARD, WCONST):
- biggen(l, r, d, 0, optab[Bac], args);
- break;
-
- case WW(WADDR, WADDR):
- case WW(WADDR, WHARD):
- case WW(WHARD, WADDR):
- case WW(WHARD, WHARD):
- biggen(l, r, d, 0, binop11, args);
- break;
-
- default:
- diag(r, "bad whatof pair %d %d\n", li, ri);
- break;
- }
- if(li == WHARD)
- regfree(l);
- if(ri == WHARD)
- regfree(r);
- break;
- }
-
- nn->type = dt;
-
- if(d != Z)
- goto finished;
-
- switch(lri) {
- case IMM(0, 0):
- freepair(r);
- /* fall thru */;
- case IMM(0, 1):
- if(!dr)
- storepair(l, nn, 1);
- break;
- case IMM(1, 0):
- if(!dr)
- storepair(r, nn, 1);
- break;
- case IMM(1, 1):
- break;
- }
- return 1;
-
- shift:
- c = Z;
-
- /* evaluate hard subexps, stealing nn if possible. */
- /* must also secure CX. not as many optims as binop. */
- switch(lri) {
- case IMM(0, 0):
- imm00:
- if(l->complex + 1 > r->complex) {
- if(dr)
- t = nn;
- else
- t = regpair(Z, l);
- sugen(l, t, 8);
- l = t;
- t = &nod1;
- c = snarfreg(l, t, D_CX, r, &nod2);
- cgen(r, t);
- r = t;
- }
- else {
- t = &nod1;
- c = snarfreg(nn, t, D_CX, r, &nod2);
- cgen(r, t);
- r = t;
- if(dr)
- t = nn;
- else
- t = regpair(Z, l);
- sugen(l, t, 8);
- l = t;
- }
- break;
- case IMM(0, 1):
- imm01:
- if(ri != WCONST) {
- lri = IMM(0, 0);
- goto imm00;
- }
- if(dr)
- t = nn;
- else
- t = regpair(Z, n);
- sugen(l, t, 8);
- l = t;
- break;
- case IMM(1, 0):
- imm10:
- if(li != WCONST) {
- lri = IMM(0, 0);
- goto imm00;
- }
- t = &nod1;
- c = snarfreg(nn, t, D_CX, r, &nod2);
- cgen(r, t);
- r = t;
- break;
- case IMM(1, 1):
- if(ri != WCONST) {
- lri = IMM(1, 0);
- goto imm10;
- }
- if(li == WHARD) {
- lri = IMM(0, 1);
- goto imm01;
- }
- break;
- }
-
- d = Z;
-
- switch(lri) {
- case IMM(0, 0):
- biggen(l, r, Z, 0, optab[S00], args);
- break;
- case IMM(0, 1):
- switch(ri) {
- case WNONE:
- case WADDR:
- case WHARD:
- diag(r, "bad whatof\n");
- break;
- case WCONST:
- m = r->vconst & 63;
- s = nodconst(m);
- if(m < 32)
- cp = optab[Sc0];
- else if(m == 32)
- cp = optab[Sc1];
- else
- cp = optab[Sc2];
- biggen(l, s, Z, 0, cp, args);
- break;
- }
- break;
- case IMM(1, 0):
- /* left is const */
- d = regpair(nn, n);
- instpair(d, Z);
- biggen(l, r, d, 0, optab[S10], args);
- regfree(r);
- break;
- case IMM(1, 1):
- d = regpair(nn, n);
- instpair(d, Z);
- switch(WW(li, ri)) {
- case WW(WADDR, WCONST):
- m = r->vconst & 63;
- s = nodconst(m);
- if(m < 32) {
- loadpair(l, d);
- l = d;
- cp = optab[Sc0];
- }
- else if(m == 32)
- cp = optab[Sac3];
- else
- cp = optab[Sac4];
- biggen(l, s, d, 0, cp, args);
- break;
-
- default:
- diag(r, "bad whatof pair %d %d\n", li, ri);
- break;
- }
- break;
- }
-
- if(c != Z) {
- gins(AMOVL, c, r);
- regfree(c);
- }
-
- if(d != Z)
- goto finished;
-
- switch(lri) {
- case IMM(0, 0):
- regfree(r);
- /* fall thru */
- case IMM(0, 1):
- if(!dr)
- storepair(l, nn, 1);
- break;
- case IMM(1, 0):
- regfree(r);
- break;
- case IMM(1, 1):
- break;
- }
- return 1;
-
- cmp:
- op = n->op;
- /* evaluate hard subexps */
- switch(lri) {
- case IMM(0, 0):
- if(l->complex > r->complex) {
- t = regpair(Z, l);
- sugen(l, t, 8);
- l = t;
- t = regpair(Z, r);
- sugen(r, t, 8);
- r = t;
- }
- else {
- t = regpair(Z, r);
- sugen(r, t, 8);
- r = t;
- t = regpair(Z, l);
- sugen(l, t, 8);
- l = t;
- }
- break;
- case IMM(1, 0):
- t = r;
- r = l;
- l = t;
- ri = li;
- op = invrel[relindex(op)];
- /* fall thru */
- case IMM(0, 1):
- t = regpair(Z, l);
- sugen(l, t, 8);
- l = t;
- break;
- case IMM(1, 1):
- break;
- }
-
- true = 1;
- optab = cmptab;
- switch(op) {
- case OEQ:
- optab = NEtab;
- true = 0;
- break;
- case ONE:
- optab = NEtab;
- break;
- case OLE:
- args = GTargs;
- true = 0;
- break;
- case OGT:
- args = GTargs;
- break;
- case OLS:
- args = HIargs;
- true = 0;
- break;
- case OHI:
- args = HIargs;
- break;
- case OLT:
- args = GEargs;
- true = 0;
- break;
- case OGE:
- args = GEargs;
- break;
- case OLO:
- args = HSargs;
- true = 0;
- break;
- case OHS:
- args = HSargs;
- break;
- default:
- diag(n, "bad cmp\n");
- SET(optab);
- }
-
- switch(lri) {
- case IMM(0, 0):
- biggen(l, r, Z, true, optab[T0i], args);
- break;
- case IMM(0, 1):
- case IMM(1, 0):
- switch(ri) {
- case WNONE:
- diag(l, "bad whatof\n");
- break;
- case WCONST:
- biggen(l, r, Z, true, optab[T0i], args);
- break;
- case WHARD:
- reglcgen(&nod2, r, Z);
- r = &nod2;
- /* fall thru */
- case WADDR:
- biggen(l, r, Z, true, optab[T0i], args);
- if(ri == WHARD)
- regfree(r);
- break;
- }
- break;
- case IMM(1, 1):
- if(li == WHARD) {
- reglcgen(&nod3, l, Z);
- l = &nod3;
- }
- if(ri == WHARD) {
- reglcgen(&nod2, r, Z);
- r = &nod2;
- }
- biggen(l, r, Z, true, optab[Tii], args);
- if(li == WHARD)
- regfree(l);
- if(ri == WHARD)
- regfree(r);
- break;
- }
-
- switch(lri) {
- case IMM(0, 0):
- freepair(r);
- /* fall thru */;
- case IMM(0, 1):
- case IMM(1, 0):
- freepair(l);
- break;
- case IMM(1, 1):
- break;
- }
- return 1;
-
- case OASMUL:
- case OASLMUL:
- m = 0;
- goto mulop;
-
- case OMUL:
- case OLMUL:
- m = 1;
- goto mulop;
-
- mulop:
- dr = nn != Z && nn->op == OREGPAIR;
- l = vfunc(n->left, nn);
- r = vfunc(n->right, nn);
- if(r->op != OCONST) {
- if(l->complex > r->complex) {
- if(m) {
- t = l;
- l = r;
- r = t;
- }
- else if(!vaddr(l, 1)) {
- reglcgen(&nod5, l, Z);
- l = &nod5;
- evacaxdx(l);
- }
- }
- t = regpair(Z, n);
- sugen(r, t, 8);
- r = t;
- evacaxdx(r->left);
- evacaxdx(r->right);
- if(l->complex <= r->complex && !m && !vaddr(l, 1)) {
- reglcgen(&nod5, l, Z);
- l = &nod5;
- evacaxdx(l);
- }
- }
- if(dr)
- t = nn;
- else
- t = regpair(Z, n);
- c = Z;
- d = Z;
- if(!nodreg(&nod1, t->left, D_AX)) {
- if(t->left->reg != D_AX){
- t->left->reg = D_AX;
- reg[D_AX]++;
- }else if(reg[D_AX] == 0)
- fatal(Z, "vlong mul AX botch");
- }
- if(!nodreg(&nod2, t->right, D_DX)) {
- if(t->right->reg != D_DX){
- t->right->reg = D_DX;
- reg[D_DX]++;
- }else if(reg[D_DX] == 0)
- fatal(Z, "vlong mul DX botch");
- }
- if(m)
- sugen(l, t, 8);
- else
- loadpair(l, t);
- if(t->left->reg != D_AX) {
- c = &nod3;
- regsalloc(c, t->left);
- gmove(&nod1, c);
- gmove(t->left, &nod1);
- zapreg(t->left);
- }
- if(t->right->reg != D_DX) {
- d = &nod4;
- regsalloc(d, t->right);
- gmove(&nod2, d);
- gmove(t->right, &nod2);
- zapreg(t->right);
- }
- if(c != Z || d != Z) {
- s = regpair(Z, n);
- s->left = &nod1;
- s->right = &nod2;
- }
- else
- s = t;
- if(r->op == OCONST) {
- if(hi64v(r) == 0)
- biggen(s, r, Z, 0, mulc32, nil);
- else
- biggen(s, r, Z, 0, mulc64, nil);
- }
- else
- biggen(s, r, Z, 0, mull, nil);
- instpair(t, Z);
- if(c != Z) {
- gmove(&nod1, t->left);
- gmove(&nod3, &nod1);
- }
- if(d != Z) {
- gmove(&nod2, t->right);
- gmove(&nod4, &nod2);
- }
- if(r->op == OREGPAIR)
- freepair(r);
- if(!m)
- storepair(t, l, 0);
- if(l == &nod5)
- regfree(l);
- if(!dr) {
- if(nn != Z)
- storepair(t, nn, 1);
- else
- freepair(t);
- }
- return 1;
-
- case OASADD:
- args = ADDargs;
- goto vasop;
- case OASAND:
- args = ANDargs;
- goto vasop;
- case OASOR:
- args = ORargs;
- goto vasop;
- case OASSUB:
- args = SUBargs;
- goto vasop;
- case OASXOR:
- args = XORargs;
- goto vasop;
-
- vasop:
- l = n->left;
- r = n->right;
- dr = nn != Z && nn->op == OREGPAIR;
- m = 0;
- if(l->complex > r->complex) {
- if(!vaddr(l, 1)) {
- reglcgen(&nod1, l, Z);
- l = &nod1;
- }
- if(!vaddr(r, 1) || nn != Z || r->op == OCONST) {
- if(dr)
- t = nn;
- else
- t = regpair(Z, r);
- sugen(r, t, 8);
- r = t;
- m = 1;
- }
- }
- else {
- if(!vaddr(r, 1) || nn != Z || r->op == OCONST) {
- if(dr)
- t = nn;
- else
- t = regpair(Z, r);
- sugen(r, t, 8);
- r = t;
- m = 1;
- }
- if(!vaddr(l, 1)) {
- reglcgen(&nod1, l, Z);
- l = &nod1;
- }
- }
- if(nn != Z) {
- if(n->op == OASSUB)
- biggen(l, r, Z, 0, sub10, args);
- else
- biggen(r, l, Z, 0, binoptmp, args);
- storepair(r, l, 0);
- }
- else {
- if(m)
- biggen(l, r, Z, 0, binop00, args);
- else
- biggen(l, r, Z, 0, binoptmp, args);
- }
- if(l == &nod1)
- regfree(&nod1);
- if(m) {
- if(nn == Z)
- freepair(r);
- else if(!dr)
- storepair(r, nn, 1);
- }
- return 1;
-
- case OASASHL:
- args = nil;
- optab = asshlltab;
- goto assh;
- case OASLSHR:
- args = shrlargs;
- optab = asshrltab;
- goto assh;
- case OASASHR:
- args = sarlargs;
- optab = asshrltab;
- goto assh;
-
- assh:
- c = Z;
- l = n->left;
- r = n->right;
- if(r->op == OCONST) {
- m = r->vconst & 63;
- if(m < 32)
- m = SAclo;
- else if(m == 32)
- m = SAc32;
- else
- m = SAchi;
- }
- else
- m = SAgen;
- if(l->complex > r->complex) {
- if(!vaddr(l, 0)) {
- reglcgen(&nod1, l, Z);
- l = &nod1;
- }
- if(m == SAgen) {
- t = &nod2;
- if(l->reg == D_CX) {
- regalloc(t, r, Z);
- gmove(l, t);
- l->reg = t->reg;
- t->reg = D_CX;
- }
- else
- c = snarfreg(nn, t, D_CX, r, &nod3);
- cgen(r, t);
- r = t;
- }
- }
- else {
- if(m == SAgen) {
- t = &nod2;
- c = snarfreg(nn, t, D_CX, r, &nod3);
- cgen(r, t);
- r = t;
- }
- if(!vaddr(l, 0)) {
- reglcgen(&nod1, l, Z);
- l = &nod1;
- }
- }
-
- if(nn != Z) {
- m += SAdgen - SAgen;
- d = regpair(nn, n);
- instpair(d, Z);
- biggen(l, r, d, 0, optab[m], args);
- if(l == &nod1) {
- regfree(&nod1);
- l = Z;
- }
- if(r == &nod2 && c == Z) {
- regfree(&nod2);
- r = Z;
- }
- if(d != nn)
- storepair(d, nn, 1);
- }
- else
- biggen(l, r, Z, 0, optab[m], args);
-
- if(c != Z) {
- gins(AMOVL, c, r);
- regfree(c);
- }
- if(l == &nod1)
- regfree(&nod1);
- if(r == &nod2)
- regfree(&nod2);
- return 1;
-
- case OPOSTINC:
- args = ADDargs;
- cp = incdecpost;
- goto vinc;
- case OPOSTDEC:
- args = SUBargs;
- cp = incdecpost;
- goto vinc;
- case OPREINC:
- args = ADDargs;
- cp = incdecpre;
- goto vinc;
- case OPREDEC:
- args = SUBargs;
- cp = incdecpre;
- goto vinc;
-
- vinc:
- l = n->left;
- if(!vaddr(l, 1)) {
- reglcgen(&nod1, l, Z);
- l = &nod1;
- }
-
- if(nn != Z) {
- d = regpair(nn, n);
- instpair(d, Z);
- biggen(l, Z, d, 0, cp, args);
- if(l == &nod1) {
- regfree(&nod1);
- l = Z;
- }
- if(d != nn)
- storepair(d, nn, 1);
- }
- else
- biggen(l, Z, Z, 0, incdec, args);
-
- if(l == &nod1)
- regfree(&nod1);
- return 1;
-
- case OCAST:
- l = n->left;
- if(typev[l->type->etype]) {
- if(!vaddr(l, 1)) {
- if(l->complex + 1 > nn->complex) {
- d = regpair(Z, l);
- sugen(l, d, 8);
- if(!vaddr(nn, 1)) {
- reglcgen(&nod1, nn, Z);
- r = &nod1;
- }
- else
- r = nn;
- }
- else {
- if(!vaddr(nn, 1)) {
- reglcgen(&nod1, nn, Z);
- r = &nod1;
- }
- else
- r = nn;
- d = regpair(Z, l);
- sugen(l, d, 8);
- }
-// d->left->type = r->type;
- d->left->type = types[TLONG];
- gmove(d->left, r);
- freepair(d);
- }
- else {
- if(nn->op != OREGISTER && !vaddr(nn, 1)) {
- reglcgen(&nod1, nn, Z);
- r = &nod1;
- }
- else
- r = nn;
-// l->type = r->type;
- l->type = types[TLONG];
- gmove(l, r);
- }
- if(r != nn)
- regfree(r);
- }
- else {
- if(typeu[l->type->etype] || cond(l->op))
- si = TUNSIGNED;
- else
- si = TSIGNED;
- regalloc(&nod1, l, Z);
- cgen(l, &nod1);
- if(nn->op == OREGPAIR) {
- m = instpair(nn, &nod1);
- biggen(&nod1, Z, nn, si == TSIGNED, castrp, nil);
- }
- else {
- m = 0;
- if(!vaddr(nn, si != TSIGNED)) {
- dt = nn->type;
- nn->type = types[TLONG];
- reglcgen(&nod2, nn, Z);
- nn->type = dt;
- nn = &nod2;
- }
- dt = nn->type;
- nn->type = types[TLONG];
- biggen(&nod1, Z, nn, si == TSIGNED, castrpa, nil);
- nn->type = dt;
- if(nn == &nod2)
- regfree(&nod2);
- }
- if(!m)
- regfree(&nod1);
- }
- return 1;
-
- default:
- if(n->op == OREGPAIR) {
- storepair(n, nn, 1);
- return 1;
- }
- if(nn->op == OREGPAIR) {
- loadpair(n, nn);
- return 1;
- }
- return 0;
- }
-finished:
- if(d != nn)
- storepair(d, nn, 1);
- return 1;
-}
-
-void
-testv(Node *n, int true)
-{
- Type *t;
- Node *nn, nod;
-
- switch(n->op) {
- case OINDREG:
- case ONAME:
- biggen(n, Z, Z, true, testi, nil);
- break;
-
- default:
- n = vfunc(n, n);
- if(n->addable >= INDEXED) {
- t = n->type;
- n->type = types[TLONG];
- reglcgen(&nod, n, Z);
- n->type = t;
- n = &nod;
- biggen(n, Z, Z, true, testi, nil);
- if(n == &nod)
- regfree(n);
- }
- else {
- nn = regpair(Z, n);
- sugen(n, nn, 8);
- biggen(nn, Z, Z, true, testi, nil);
- freepair(nn);
- }
- }
-}
diff --git a/src/cmd/8c/div.c b/src/cmd/8c/div.c
deleted file mode 100644
index 14945052e..000000000
--- a/src/cmd/8c/div.c
+++ /dev/null
@@ -1,236 +0,0 @@
-// Inferno utils/8c/div.c
-// http://code.google.com/p/inferno-os/source/browse/utils/8c/div.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-
-/*
- * Based on: Granlund, T.; Montgomery, P.L.
- * "Division by Invariant Integers using Multiplication".
- * SIGPLAN Notices, Vol. 29, June 1994, page 61.
- */
-
-#define TN(n) ((uvlong)1 << (n))
-#define T31 TN(31)
-#define T32 TN(32)
-
-int
-multiplier(uint32 d, int p, uvlong *mp)
-{
- int l;
- uvlong mlo, mhi, tlo, thi;
-
- l = topbit(d - 1) + 1;
- mlo = (((TN(l) - d) << 32) / d) + T32;
- if(l + p == 64)
- mhi = (((TN(l) + 1 - d) << 32) / d) + T32;
- else
- mhi = (TN(32 + l) + TN(32 + l - p)) / d;
- /*assert(mlo < mhi);*/
- while(l > 0) {
- tlo = mlo >> 1;
- thi = mhi >> 1;
- if(tlo == thi)
- break;
- mlo = tlo;
- mhi = thi;
- l--;
- }
- *mp = mhi;
- return l;
-}
-
-int
-sdiv(uint32 d, uint32 *mp, int *sp)
-{
- int s;
- uvlong m;
-
- s = multiplier(d, 32 - 1, &m);
- *mp = m;
- *sp = s;
- if(m >= T31)
- return 1;
- else
- return 0;
-}
-
-int
-udiv(uint32 d, uint32 *mp, int *sp, int *pp)
-{
- int p, s;
- uvlong m;
-
- s = multiplier(d, 32, &m);
- p = 0;
- if(m >= T32) {
- while((d & 1) == 0) {
- d >>= 1;
- p++;
- }
- s = multiplier(d, 32 - p, &m);
- }
- *mp = m;
- *pp = p;
- if(m >= T32) {
- /*assert(p == 0);*/
- *sp = s - 1;
- return 1;
- }
- else {
- *sp = s;
- return 0;
- }
-}
-
-void
-sdivgen(Node *l, Node *r, Node *ax, Node *dx)
-{
- int a, s;
- uint32 m;
- vlong c;
-
- c = r->vconst;
- if(c < 0)
- c = -c;
- a = sdiv(c, &m, &s);
-//print("a=%d i=%d s=%d m=%ux\n", a, (int32)r->vconst, s, m);
- gins(AMOVL, nodconst(m), ax);
- gins(AIMULL, l, Z);
- gins(AMOVL, l, ax);
- if(a)
- gins(AADDL, ax, dx);
- gins(ASHRL, nodconst(31), ax);
- gins(ASARL, nodconst(s), dx);
- gins(AADDL, ax, dx);
- if(r->vconst < 0)
- gins(ANEGL, Z, dx);
-}
-
-void
-udivgen(Node *l, Node *r, Node *ax, Node *dx)
-{
- int a, s, t;
- uint32 m;
- Node nod;
-
- a = udiv(r->vconst, &m, &s, &t);
-//print("a=%ud i=%d p=%d s=%d m=%ux\n", a, (int32)r->vconst, t, s, m);
- if(t != 0) {
- gins(AMOVL, l, ax);
- gins(ASHRL, nodconst(t), ax);
- gins(AMOVL, nodconst(m), dx);
- gins(AMULL, dx, Z);
- }
- else if(a) {
- if(l->op != OREGISTER) {
- regalloc(&nod, l, Z);
- gins(AMOVL, l, &nod);
- l = &nod;
- }
- gins(AMOVL, nodconst(m), ax);
- gins(AMULL, l, Z);
- gins(AADDL, l, dx);
- gins(ARCRL, nodconst(1), dx);
- if(l == &nod)
- regfree(l);
- }
- else {
- gins(AMOVL, nodconst(m), ax);
- gins(AMULL, l, Z);
- }
- if(s != 0)
- gins(ASHRL, nodconst(s), dx);
-}
-
-void
-sext(Node *d, Node *s, Node *l)
-{
- if(s->reg == D_AX && !nodreg(d, Z, D_DX)) {
- reg[D_DX]++;
- gins(ACDQ, Z, Z);
- }
- else {
- regalloc(d, l, Z);
- gins(AMOVL, s, d);
- gins(ASARL, nodconst(31), d);
- }
-}
-
-void
-sdiv2(int32 c, int v, Node *l, Node *n)
-{
- Node nod;
-
- if(v > 0) {
- if(v > 1) {
- sext(&nod, n, l);
- gins(AANDL, nodconst((1 << v) - 1), &nod);
- gins(AADDL, &nod, n);
- regfree(&nod);
- }
- else {
- gins(ACMPL, n, nodconst(0x80000000));
- gins(ASBBL, nodconst(-1), n);
- }
- gins(ASARL, nodconst(v), n);
- }
- if(c < 0)
- gins(ANEGL, Z, n);
-}
-
-void
-smod2(int32 c, int v, Node *l, Node *n)
-{
- Node nod;
-
- if(c == 1) {
- zeroregm(n);
- return;
- }
-
- sext(&nod, n, l);
- if(v == 0) {
- zeroregm(n);
- gins(AXORL, &nod, n);
- gins(ASUBL, &nod, n);
- }
- else if(v > 1) {
- gins(AANDL, nodconst((1 << v) - 1), &nod);
- gins(AADDL, &nod, n);
- gins(AANDL, nodconst((1 << v) - 1), n);
- gins(ASUBL, &nod, n);
- }
- else {
- gins(AANDL, nodconst(1), n);
- gins(AXORL, &nod, n);
- gins(ASUBL, &nod, n);
- }
- regfree(&nod);
-}
diff --git a/src/cmd/8c/doc.go b/src/cmd/8c/doc.go
deleted file mode 100644
index 0d07db14d..000000000
--- a/src/cmd/8c/doc.go
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build ignore
-
-/*
-
-8c is a version of the Plan 9 C compiler. The original is documented at
-
- http://plan9.bell-labs.com/magic/man2html/1/8c
-
-Its target architecture is the x86, referred to by these tools for historical reasons as 386.
-
-*/
-package main
diff --git a/src/cmd/8c/gc.h b/src/cmd/8c/gc.h
deleted file mode 100644
index aa3888d73..000000000
--- a/src/cmd/8c/gc.h
+++ /dev/null
@@ -1,364 +0,0 @@
-// Inferno utils/8c/gc.h
-// http://code.google.com/p/inferno-os/source/browse/utils/8c/gc.h
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include <u.h>
-#include "../cc/cc.h"
-#include "../8l/8.out.h"
-
-/*
- * 8c/386
- * Intel 386
- */
-#define SZ_CHAR 1
-#define SZ_SHORT 2
-#define SZ_INT 4
-#define SZ_LONG 4
-#define SZ_IND 4
-#define SZ_FLOAT 4
-#define SZ_VLONG 8
-#define SZ_DOUBLE 8
-#define FNX 100
-
-typedef struct Case Case;
-typedef struct C1 C1;
-typedef struct Reg Reg;
-typedef struct Rgn Rgn;
-typedef struct Renv Renv;
-
-EXTERN struct
-{
- Node* regtree;
- Node* basetree;
- short scale;
- short reg;
- short ptr;
-} idx;
-
-#define A ((Addr*)0)
-
-#define INDEXED 9
-
-#define P ((Prog*)0)
-
-struct Case
-{
- Case* link;
- int32 val;
- int32 label;
- char def;
- char isv;
-};
-#define C ((Case*)0)
-
-struct C1
-{
- int32 val;
- int32 label;
-};
-
-struct Reg
-{
- int32 pc;
- int32 rpo; /* reverse post ordering */
-
- Bits set;
- Bits use1;
- Bits use2;
-
- Bits refbehind;
- Bits refahead;
- Bits calbehind;
- Bits calahead;
- Bits regdiff;
- Bits act;
-
- int32 regu;
- int32 loop; /* could be shorter */
-
- Reg* log5;
- int32 active;
-
- Reg* p1;
- Reg* p2;
- Reg* p2link;
- Reg* s1;
- Reg* s2;
- Reg* link;
- Prog* prog;
-};
-#define R ((Reg*)0)
-
-struct Renv
-{
- int safe;
- Node base;
- Node* saved;
- Node* scope;
-};
-
-#define NRGN 600
-struct Rgn
-{
- Reg* enter;
- short cost;
- short varno;
- short regno;
-};
-
-EXTERN int32 breakpc;
-EXTERN int32 nbreak;
-EXTERN Case* cases;
-EXTERN Node constnode;
-EXTERN Node fconstnode;
-EXTERN int32 continpc;
-EXTERN int32 curarg;
-EXTERN int32 cursafe;
-EXTERN Prog* lastp;
-EXTERN int32 maxargsafe;
-EXTERN int mnstring;
-EXTERN Node* nodrat;
-EXTERN Node* nodret;
-EXTERN Node* nodsafe;
-EXTERN int32 nrathole;
-EXTERN int32 nstring;
-EXTERN Prog* p;
-EXTERN int32 pc;
-EXTERN Node regnode;
-EXTERN Node fregnode0;
-EXTERN Node fregnode1;
-EXTERN char string[NSNAME];
-EXTERN Sym* symrathole;
-EXTERN Node znode;
-EXTERN Prog zprog;
-EXTERN int reg[D_NONE];
-EXTERN int32 exregoffset;
-EXTERN int32 exfregoffset;
-
-#define BLOAD(r) band(bnot(r->refbehind), r->refahead)
-#define BSTORE(r) band(bnot(r->calbehind), r->calahead)
-#define LOAD(r) (~r->refbehind.b[z] & r->refahead.b[z])
-#define STORE(r) (~r->calbehind.b[z] & r->calahead.b[z])
-
-#define bset(a,n) ((a).b[(n)/32]&(1L<<(n)%32))
-
-#define CLOAD 5
-#define CREF 5
-#define CINF 1000
-#define LOOP 3
-
-EXTERN Rgn region[NRGN];
-EXTERN Rgn* rgp;
-EXTERN int nregion;
-EXTERN int nvar;
-
-EXTERN Bits externs;
-EXTERN Bits params;
-EXTERN Bits consts;
-EXTERN Bits addrs;
-
-EXTERN int32 regbits;
-EXTERN int32 exregbits;
-
-EXTERN int change;
-EXTERN int suppress;
-
-EXTERN Reg* firstr;
-EXTERN Reg* lastr;
-EXTERN Reg zreg;
-EXTERN Reg* freer;
-EXTERN int32* idom;
-EXTERN Reg** rpo2r;
-EXTERN int32 maxnr;
-
-extern char* anames[];
-
-/*
- * sgen.c
- */
-void codgen(Node*, Node*);
-void gen(Node*);
-void noretval(int);
-void usedset(Node*, int);
-void xcom(Node*);
-void indx(Node*);
-int bcomplex(Node*, Node*);
-Prog* gtext(Sym*, int32);
-vlong argsize(int);
-
-/*
- * cgen.c
- */
-void zeroregm(Node*);
-void cgen(Node*, Node*);
-void reglcgen(Node*, Node*, Node*);
-void lcgen(Node*, Node*);
-void bcgen(Node*, int);
-void boolgen(Node*, int, Node*);
-void sugen(Node*, Node*, int32);
-int needreg(Node*, int);
-
-/*
- * cgen64.c
- */
-int vaddr(Node*, int);
-void loadpair(Node*, Node*);
-int cgen64(Node*, Node*);
-void testv(Node*, int);
-
-/*
- * txt.c
- */
-void ginit(void);
-void gclean(void);
-void nextpc(void);
-void gargs(Node*, Node*, Node*);
-void garg1(Node*, Node*, Node*, int, Node**);
-Node* nodconst(int32);
-Node* nodfconst(double);
-int nodreg(Node*, Node*, int);
-int isreg(Node*, int);
-void regret(Node*, Node*, Type*, int);
-void regalloc(Node*, Node*, Node*);
-void regfree(Node*);
-void regialloc(Node*, Node*, Node*);
-void regsalloc(Node*, Node*);
-void regaalloc1(Node*, Node*);
-void regaalloc(Node*, Node*);
-void regind(Node*, Node*);
-void gprep(Node*, Node*);
-void naddr(Node*, Addr*);
-void gmove(Node*, Node*);
-void gins(int a, Node*, Node*);
-void fgopcode(int, Node*, Node*, int, int);
-void gopcode(int, Type*, Node*, Node*);
-int samaddr(Node*, Node*);
-void gbranch(int);
-void patch(Prog*, int32);
-int sconst(Node*);
-void gpseudo(int, Sym*, Node*);
-void gprefetch(Node*);
-void gpcdata(int, int);
-
-/*
- * swt.c
- */
-int swcmp(const void*, const void*);
-void doswit(Node*);
-void swit1(C1*, int, int32, Node*);
-void swit2(C1*, int, int32, Node*);
-void newcase(void);
-void bitload(Node*, Node*, Node*, Node*, Node*);
-void bitstore(Node*, Node*, Node*, Node*, Node*);
-int32 outstring(char*, int32);
-void nullwarn(Node*, Node*);
-void sextern(Sym*, Node*, int32, int32);
-void gextern(Sym*, Node*, int32, int32);
-void outcode(void);
-
-/*
- * list
- */
-void listinit(void);
-
-/*
- * reg.c
- */
-Reg* rega(void);
-int rcmp(const void*, const void*);
-void regopt(Prog*);
-void addmove(Reg*, int, int, int);
-Bits mkvar(Reg*, Addr*);
-void prop(Reg*, Bits, Bits);
-void loopit(Reg*, int32);
-void synch(Reg*, Bits);
-uint32 allreg(uint32, Rgn*);
-void paint1(Reg*, int);
-uint32 paint2(Reg*, int);
-void paint3(Reg*, int, int32, int);
-void addreg(Addr*, int);
-
-/*
- * peep.c
- */
-void peep(void);
-void excise(Reg*);
-Reg* uniqp(Reg*);
-Reg* uniqs(Reg*);
-int regtyp(Addr*);
-int anyvar(Addr*);
-int subprop(Reg*);
-int copyprop(Reg*);
-int copy1(Addr*, Addr*, Reg*, int);
-int copyu(Prog*, Addr*, Addr*);
-
-int copyas(Addr*, Addr*);
-int copyau(Addr*, Addr*);
-int copysub(Addr*, Addr*, Addr*, int);
-int copysub1(Prog*, Addr*, Addr*, int);
-
-int32 RtoB(int);
-int32 FtoB(int);
-int BtoR(int32);
-int BtoF(int32);
-
-#define D_HI D_NONE
-#define D_LO D_NONE
-
-/*
- * bound
- */
-void comtarg(void);
-
-/*
- * com64
- */
-int cond(int);
-int com64(Node*);
-void com64init(void);
-void bool64(Node*);
-int32 lo64v(Node*);
-int32 hi64v(Node*);
-Node* lo64(Node*);
-Node* hi64(Node*);
-
-/*
- * div/mul
- */
-void sdivgen(Node*, Node*, Node*, Node*);
-void udivgen(Node*, Node*, Node*, Node*);
-void sdiv2(int32, int, Node*, Node*);
-void smod2(int32, int, Node*, Node*);
-void mulgen(Type*, Node*, Node*);
-void genmuladd(Node*, Node*, int, Node*);
-void shiftit(Type*, Node*, Node*);
-
-/* wrecklessly steal a field */
-
-#define rplink label
diff --git a/src/cmd/8c/list.c b/src/cmd/8c/list.c
deleted file mode 100644
index 1730eccd0..000000000
--- a/src/cmd/8c/list.c
+++ /dev/null
@@ -1,38 +0,0 @@
-// Inferno utils/8c/list.c
-// http://code.google.com/p/inferno-os/source/browse/utils/8c/list.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#define EXTERN
-#include "gc.h"
-
-void
-listinit(void)
-{
- listinit8();
-}
diff --git a/src/cmd/8c/machcap.c b/src/cmd/8c/machcap.c
deleted file mode 100644
index 61e5aad16..000000000
--- a/src/cmd/8c/machcap.c
+++ /dev/null
@@ -1,116 +0,0 @@
-// Inferno utils/8c/machcap.c
-// http://code.google.com/p/inferno-os/source/browse/utils/8c/machcap.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-
-int
-machcap(Node *n)
-{
-
- if(n == Z)
- return 1; /* test */
-
- switch(n->op) {
- case OMUL:
- case OLMUL:
- case OASMUL:
- case OASLMUL:
- if(typechl[n->type->etype])
- return 1;
- if(typev[n->type->etype]) {
- return 1;
- }
- break;
-
- case OCOM:
- case ONEG:
- case OADD:
- case OAND:
- case OOR:
- case OSUB:
- case OXOR:
- case OASHL:
- case OLSHR:
- case OASHR:
- if(typechlv[n->left->type->etype])
- return 1;
- break;
-
- case OCAST:
- if(typev[n->type->etype]) {
- if(typechlp[n->left->type->etype])
- return 1;
- }
- else if(!typefd[n->type->etype]) {
- if(typev[n->left->type->etype])
- return 1;
- }
- break;
-
- case OCOND:
- case OCOMMA:
- case OLIST:
- case OANDAND:
- case OOROR:
- case ONOT:
- return 1;
-
- case OASADD:
- case OASSUB:
- case OASAND:
- case OASOR:
- case OASXOR:
- return 1;
-
- case OASASHL:
- case OASASHR:
- case OASLSHR:
- return 1;
-
- case OPOSTINC:
- case OPOSTDEC:
- case OPREINC:
- case OPREDEC:
- return 1;
-
- case OEQ:
- case ONE:
- case OLE:
- case OGT:
- case OLT:
- case OGE:
- case OHI:
- case OHS:
- case OLO:
- case OLS:
- return 1;
- }
- return 0;
-}
diff --git a/src/cmd/8c/mul.c b/src/cmd/8c/mul.c
deleted file mode 100644
index 9955e762f..000000000
--- a/src/cmd/8c/mul.c
+++ /dev/null
@@ -1,458 +0,0 @@
-// Inferno utils/8c/mul.c
-// http://code.google.com/p/inferno-os/source/browse/utils/8c/mul.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-
-typedef struct Malg Malg;
-typedef struct Mparam Mparam;
-
-struct Malg
-{
- schar vals[10];
-};
-
-struct Mparam
-{
- uint32 value;
- schar alg;
- char neg;
- char shift;
- char arg;
- schar off;
-};
-
-static Mparam multab[32];
-static int mulptr;
-
-static Malg malgs[] =
-{
- {0, 100},
- {-1, 1, 100},
- {-9, -5, -3, 3, 5, 9, 100},
- {6, 10, 12, 18, 20, 24, 36, 40, 72, 100},
- {-8, -4, -2, 2, 4, 8, 100},
-};
-
-/*
- * return position of lowest 1
- */
-int
-lowbit(uint32 v)
-{
- int s, i;
- uint32 m;
-
- s = 0;
- m = 0xFFFFFFFFUL;
- for(i = 16; i > 0; i >>= 1) {
- m >>= i;
- if((v & m) == 0) {
- v >>= i;
- s += i;
- }
- }
- return s;
-}
-
-void
-genmuladd(Node *d, Node *s, int m, Node *a)
-{
- Node nod;
-
- nod.op = OINDEX;
- nod.left = a;
- nod.right = s;
- nod.scale = m;
- nod.type = types[TIND];
- nod.xoffset = 0;
- xcom(&nod);
- gopcode(OADDR, d->type, &nod, d);
-}
-
-void
-mulparam(uint32 m, Mparam *mp)
-{
- int c, i, j, n, o, q, s;
- int bc, bi, bn, bo, bq, bs, bt;
- schar *p;
- int32 u;
- uint32 t;
-
- bc = bq = 10;
- bi = bn = bo = bs = bt = 0;
- for(i = 0; i < nelem(malgs); i++) {
- for(p = malgs[i].vals, j = 0; (o = p[j]) < 100; j++)
- for(s = 0; s < 2; s++) {
- c = 10;
- q = 10;
- u = m - o;
- if(u == 0)
- continue;
- if(s) {
- o = -o;
- if(o > 0)
- continue;
- u = -u;
- }
- n = lowbit(u);
- t = (uint32)u >> n;
- switch(i) {
- case 0:
- if(t == 1) {
- c = s + 1;
- q = 0;
- break;
- }
- switch(t) {
- case 3:
- case 5:
- case 9:
- c = s + 1;
- if(n)
- c++;
- q = 0;
- break;
- }
- if(s)
- break;
- switch(t) {
- case 15:
- case 25:
- case 27:
- case 45:
- case 81:
- c = 2;
- if(n)
- c++;
- q = 1;
- break;
- }
- break;
- case 1:
- if(t == 1) {
- c = 3;
- q = 3;
- break;
- }
- switch(t) {
- case 3:
- case 5:
- case 9:
- c = 3;
- q = 2;
- break;
- }
- break;
- case 2:
- if(t == 1) {
- c = 3;
- q = 2;
- break;
- }
- break;
- case 3:
- if(s)
- break;
- if(t == 1) {
- c = 3;
- q = 1;
- break;
- }
- break;
- case 4:
- if(t == 1) {
- c = 3;
- q = 0;
- break;
- }
- break;
- }
- if(c < bc || (c == bc && q > bq)) {
- bc = c;
- bi = i;
- bn = n;
- bo = o;
- bq = q;
- bs = s;
- bt = t;
- }
- }
- }
- mp->value = m;
- if(bc <= 3) {
- mp->alg = bi;
- mp->shift = bn;
- mp->off = bo;
- mp->neg = bs;
- mp->arg = bt;
- }
- else
- mp->alg = -1;
-}
-
-int
-m0(int a)
-{
- switch(a) {
- case -2:
- case 2:
- return 2;
- case -3:
- case 3:
- return 2;
- case -4:
- case 4:
- return 4;
- case -5:
- case 5:
- return 4;
- case 6:
- return 2;
- case -8:
- case 8:
- return 8;
- case -9:
- case 9:
- return 8;
- case 10:
- return 4;
- case 12:
- return 2;
- case 15:
- return 2;
- case 18:
- return 8;
- case 20:
- return 4;
- case 24:
- return 2;
- case 25:
- return 4;
- case 27:
- return 2;
- case 36:
- return 8;
- case 40:
- return 4;
- case 45:
- return 4;
- case 72:
- return 8;
- case 81:
- return 8;
- }
- diag(Z, "bad m0");
- return 0;
-}
-
-int
-m1(int a)
-{
- switch(a) {
- case 15:
- return 4;
- case 25:
- return 4;
- case 27:
- return 8;
- case 45:
- return 8;
- case 81:
- return 8;
- }
- diag(Z, "bad m1");
- return 0;
-}
-
-int
-m2(int a)
-{
- switch(a) {
- case 6:
- return 2;
- case 10:
- return 2;
- case 12:
- return 4;
- case 18:
- return 2;
- case 20:
- return 4;
- case 24:
- return 8;
- case 36:
- return 4;
- case 40:
- return 8;
- case 72:
- return 8;
- }
- diag(Z, "bad m2");
- return 0;
-}
-
-void
-shiftit(Type *t, Node *s, Node *d)
-{
- int32 c;
-
- c = (int32)s->vconst & 31;
- switch(c) {
- case 0:
- break;
- case 1:
- gopcode(OADD, t, d, d);
- break;
- default:
- gopcode(OASHL, t, s, d);
- }
-}
-
-static int
-mulgen1(uint32 v, Node *n)
-{
- int i, o;
- Mparam *p;
- Node nod, nods;
-
- for(i = 0; i < nelem(multab); i++) {
- p = &multab[i];
- if(p->value == v)
- goto found;
- }
-
- p = &multab[mulptr];
- if(++mulptr == nelem(multab))
- mulptr = 0;
-
- mulparam(v, p);
-
-found:
-// print("v=%.x a=%d n=%d s=%d g=%d o=%d \n", p->value, p->alg, p->neg, p->shift, p->arg, p->off);
- if(p->alg < 0)
- return 0;
-
- nods = *nodconst(p->shift);
-
- o = OADD;
- if(p->alg > 0) {
- regalloc(&nod, n, Z);
- if(p->off < 0)
- o = OSUB;
- }
-
- switch(p->alg) {
- case 0:
- switch(p->arg) {
- case 1:
- shiftit(n->type, &nods, n);
- break;
- case 15:
- case 25:
- case 27:
- case 45:
- case 81:
- genmuladd(n, n, m1(p->arg), n);
- /* fall thru */
- case 3:
- case 5:
- case 9:
- genmuladd(n, n, m0(p->arg), n);
- shiftit(n->type, &nods, n);
- break;
- default:
- goto bad;
- }
- if(p->neg == 1)
- gins(ANEGL, Z, n);
- break;
- case 1:
- switch(p->arg) {
- case 1:
- gmove(n, &nod);
- shiftit(n->type, &nods, &nod);
- break;
- case 3:
- case 5:
- case 9:
- genmuladd(&nod, n, m0(p->arg), n);
- shiftit(n->type, &nods, &nod);
- break;
- default:
- goto bad;
- }
- if(p->neg)
- gopcode(o, n->type, &nod, n);
- else {
- gopcode(o, n->type, n, &nod);
- gmove(&nod, n);
- }
- break;
- case 2:
- genmuladd(&nod, n, m0(p->off), n);
- shiftit(n->type, &nods, n);
- goto comop;
- case 3:
- genmuladd(&nod, n, m0(p->off), n);
- shiftit(n->type, &nods, n);
- genmuladd(n, &nod, m2(p->off), n);
- break;
- case 4:
- genmuladd(&nod, n, m0(p->off), nodconst(0));
- shiftit(n->type, &nods, n);
- goto comop;
- default:
- diag(Z, "bad mul alg");
- break;
- comop:
- if(p->neg) {
- gopcode(o, n->type, n, &nod);
- gmove(&nod, n);
- }
- else
- gopcode(o, n->type, &nod, n);
- }
-
- if(p->alg > 0)
- regfree(&nod);
-
- return 1;
-
-bad:
- diag(Z, "mulgen botch");
- return 1;
-}
-
-void
-mulgen(Type *t, Node *r, Node *n)
-{
- if(!mulgen1(r->vconst, n))
- gopcode(OMUL, t, r, n);
-}
diff --git a/src/cmd/8c/peep.c b/src/cmd/8c/peep.c
deleted file mode 100644
index 4f58fc05c..000000000
--- a/src/cmd/8c/peep.c
+++ /dev/null
@@ -1,807 +0,0 @@
-// Inferno utils/8c/peep.c
-// http://code.google.com/p/inferno-os/source/browse/utils/8c/peep.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-
-static int
-needc(Prog *p)
-{
- while(p != P) {
- switch(p->as) {
- case AADCL:
- case ASBBL:
- case ARCRL:
- return 1;
- case AADDL:
- case ASUBL:
- case AJMP:
- case ARET:
- case ACALL:
- return 0;
- default:
- if(p->to.type == D_BRANCH)
- return 0;
- }
- p = p->link;
- }
- return 0;
-}
-
-void
-peep(void)
-{
- Reg *r, *r1, *r2;
- Prog *p, *p1;
- int t;
-
- /*
- * complete R structure
- */
- t = 0;
- for(r=firstr; r!=R; r=r1) {
- r1 = r->link;
- if(r1 == R)
- break;
- p = r->prog->link;
- while(p != r1->prog)
- switch(p->as) {
- default:
- r2 = rega();
- r->link = r2;
- r2->link = r1;
-
- r2->prog = p;
- r2->p1 = r;
- r->s1 = r2;
- r2->s1 = r1;
- r1->p1 = r2;
-
- r = r2;
- t++;
-
- case ADATA:
- case AGLOBL:
- case ANAME:
- case ASIGNAME:
- p = p->link;
- }
- }
-
- pc = 0; /* speculating it won't kill */
-
-loop1:
-
- t = 0;
- for(r=firstr; r!=R; r=r->link) {
- p = r->prog;
- switch(p->as) {
- case AMOVL:
- if(regtyp(&p->to))
- if(regtyp(&p->from)) {
- if(copyprop(r)) {
- excise(r);
- t++;
- }
- if(subprop(r) && copyprop(r)) {
- excise(r);
- t++;
- }
- }
- break;
-
- case AMOVBLSX:
- case AMOVBLZX:
- case AMOVWLSX:
- case AMOVWLZX:
- if(regtyp(&p->to)) {
- r1 = uniqs(r);
- if(r1 != R) {
- p1 = r1->prog;
- if(p->as == p1->as && p->to.type == p1->from.type)
- p1->as = AMOVL;
- }
- }
- break;
- case AADDL:
- case AADDW:
- if(p->from.type != D_CONST || needc(p->link))
- break;
- if(p->from.offset == -1){
- if(p->as == AADDL)
- p->as = ADECL;
- else
- p->as = ADECW;
- p->from = zprog.from;
- }
- else if(p->from.offset == 1){
- if(p->as == AADDL)
- p->as = AINCL;
- else
- p->as = AINCW;
- p->from = zprog.from;
- }
- break;
- case ASUBL:
- case ASUBW:
- if(p->from.type != D_CONST || needc(p->link))
- break;
- if(p->from.offset == -1) {
- if(p->as == ASUBL)
- p->as = AINCL;
- else
- p->as = AINCW;
- p->from = zprog.from;
- }
- else if(p->from.offset == 1){
- if(p->as == ASUBL)
- p->as = ADECL;
- else
- p->as = ADECW;
- p->from = zprog.from;
- }
- break;
- }
- }
- if(t)
- goto loop1;
-}
-
-void
-excise(Reg *r)
-{
- Prog *p;
-
- p = r->prog;
- p->as = ANOP;
- p->from = zprog.from;
- p->to = zprog.to;
-}
-
-Reg*
-uniqp(Reg *r)
-{
- Reg *r1;
-
- r1 = r->p1;
- if(r1 == R) {
- r1 = r->p2;
- if(r1 == R || r1->p2link != R)
- return R;
- } else
- if(r->p2 != R)
- return R;
- return r1;
-}
-
-Reg*
-uniqs(Reg *r)
-{
- Reg *r1;
-
- r1 = r->s1;
- if(r1 == R) {
- r1 = r->s2;
- if(r1 == R)
- return R;
- } else
- if(r->s2 != R)
- return R;
- return r1;
-}
-
-int
-regtyp(Addr *a)
-{
- int t;
-
- t = a->type;
- if(t >= D_AX && t <= D_DI)
- return 1;
- return 0;
-}
-
-/*
- * the idea is to substitute
- * one register for another
- * from one MOV to another
- * MOV a, R0
- * ADD b, R0 / no use of R1
- * MOV R0, R1
- * would be converted to
- * MOV a, R1
- * ADD b, R1
- * MOV R1, R0
- * hopefully, then the former or latter MOV
- * will be eliminated by copy propagation.
- */
-int
-subprop(Reg *r0)
-{
- Prog *p;
- Addr *v1, *v2;
- Reg *r;
- int t;
-
- p = r0->prog;
- v1 = &p->from;
- if(!regtyp(v1))
- return 0;
- v2 = &p->to;
- if(!regtyp(v2))
- return 0;
- for(r=uniqp(r0); r!=R; r=uniqp(r)) {
- if(uniqs(r) == R)
- break;
- p = r->prog;
- switch(p->as) {
- case ACALL:
- return 0;
-
- case AIMULL:
- case AIMULW:
- if(p->to.type != D_NONE)
- break;
-
- case ADIVB:
- case ADIVL:
- case ADIVW:
- case AIDIVB:
- case AIDIVL:
- case AIDIVW:
- case AIMULB:
- case AMULB:
- case AMULL:
- case AMULW:
-
- case AROLB:
- case AROLL:
- case AROLW:
- case ARORB:
- case ARORL:
- case ARORW:
- case ASALB:
- case ASALL:
- case ASALW:
- case ASARB:
- case ASARL:
- case ASARW:
- case ASHLB:
- case ASHLL:
- case ASHLW:
- case ASHRB:
- case ASHRL:
- case ASHRW:
-
- case AREP:
- case AREPN:
-
- case ACWD:
- case ACDQ:
-
- case ASTOSB:
- case ASTOSL:
- case AMOVSB:
- case AMOVSL:
- case AFSTSW:
- return 0;
-
- case AMOVL:
- if(p->to.type == v1->type)
- goto gotit;
- break;
- }
- if(copyau(&p->from, v2) ||
- copyau(&p->to, v2))
- break;
- if(copysub(&p->from, v1, v2, 0) ||
- copysub(&p->to, v1, v2, 0))
- break;
- }
- return 0;
-
-gotit:
- copysub(&p->to, v1, v2, 1);
- if(debug['P']) {
- print("gotit: %D->%D\n%P", v1, v2, r->prog);
- if(p->from.type == v2->type)
- print(" excise");
- print("\n");
- }
- for(r=uniqs(r); r!=r0; r=uniqs(r)) {
- p = r->prog;
- copysub(&p->from, v1, v2, 1);
- copysub(&p->to, v1, v2, 1);
- if(debug['P'])
- print("%P\n", r->prog);
- }
- t = v1->type;
- v1->type = v2->type;
- v2->type = t;
- if(debug['P'])
- print("%P last\n", r->prog);
- return 1;
-}
-
-/*
- * The idea is to remove redundant copies.
- * v1->v2 F=0
- * (use v2 s/v2/v1/)*
- * set v1 F=1
- * use v2 return fail
- * -----------------
- * v1->v2 F=0
- * (use v2 s/v2/v1/)*
- * set v1 F=1
- * set v2 return success
- */
-int
-copyprop(Reg *r0)
-{
- Prog *p;
- Addr *v1, *v2;
- Reg *r;
-
- p = r0->prog;
- v1 = &p->from;
- v2 = &p->to;
- if(copyas(v1, v2))
- return 1;
- for(r=firstr; r!=R; r=r->link)
- r->active = 0;
- return copy1(v1, v2, r0->s1, 0);
-}
-
-int
-copy1(Addr *v1, Addr *v2, Reg *r, int f)
-{
- int t;
- Prog *p;
-
- if(r->active) {
- if(debug['P'])
- print("act set; return 1\n");
- return 1;
- }
- r->active = 1;
- if(debug['P'])
- print("copy %D->%D f=%d\n", v1, v2, f);
- for(; r != R; r = r->s1) {
- p = r->prog;
- if(debug['P'])
- print("%P", p);
- if(!f && uniqp(r) == R) {
- f = 1;
- if(debug['P'])
- print("; merge; f=%d", f);
- }
- t = copyu(p, v2, A);
- switch(t) {
- case 2: /* rar, can't split */
- if(debug['P'])
- print("; %D rar; return 0\n", v2);
- return 0;
-
- case 3: /* set */
- if(debug['P'])
- print("; %D set; return 1\n", v2);
- return 1;
-
- case 1: /* used, substitute */
- case 4: /* use and set */
- if(f) {
- if(!debug['P'])
- return 0;
- if(t == 4)
- print("; %D used+set and f=%d; return 0\n", v2, f);
- else
- print("; %D used and f=%d; return 0\n", v2, f);
- return 0;
- }
- if(copyu(p, v2, v1)) {
- if(debug['P'])
- print("; sub fail; return 0\n");
- return 0;
- }
- if(debug['P'])
- print("; sub %D/%D", v2, v1);
- if(t == 4) {
- if(debug['P'])
- print("; %D used+set; return 1\n", v2);
- return 1;
- }
- break;
- }
- if(!f) {
- t = copyu(p, v1, A);
- if(!f && (t == 2 || t == 3 || t == 4)) {
- f = 1;
- if(debug['P'])
- print("; %D set and !f; f=%d", v1, f);
- }
- }
- if(debug['P'])
- print("\n");
- if(r->s2)
- if(!copy1(v1, v2, r->s2, f))
- return 0;
- }
- return 1;
-}
-
-/*
- * return
- * 1 if v only used (and substitute),
- * 2 if read-alter-rewrite
- * 3 if set
- * 4 if set and used
- * 0 otherwise (not touched)
- */
-int
-copyu(Prog *p, Addr *v, Addr *s)
-{
-
- switch(p->as) {
-
- default:
- if(debug['P'])
- print("unknown op %A\n", p->as);
- return 2;
-
- case ANEGB:
- case ANEGW:
- case ANEGL:
- case ANOTB:
- case ANOTW:
- case ANOTL:
- if(copyas(&p->to, v))
- return 2;
- break;
-
- case ALEAL: /* lhs addr, rhs store */
- if(copyas(&p->from, v))
- return 2;
-
-
- case ANOP: /* rhs store */
- case AMOVL:
- case AMOVBLSX:
- case AMOVBLZX:
- case AMOVWLSX:
- case AMOVWLZX:
- if(copyas(&p->to, v)) {
- if(s != A)
- return copysub(&p->from, v, s, 1);
- if(copyau(&p->from, v))
- return 4;
- return 3;
- }
- goto caseread;
-
- case AROLB:
- case AROLL:
- case AROLW:
- case ARORB:
- case ARORL:
- case ARORW:
- case ASALB:
- case ASALL:
- case ASALW:
- case ASARB:
- case ASARL:
- case ASARW:
- case ASHLB:
- case ASHLL:
- case ASHLW:
- case ASHRB:
- case ASHRL:
- case ASHRW:
- if(copyas(&p->to, v))
- return 2;
- if(copyas(&p->from, v))
- if(p->from.type == D_CX)
- return 2;
- goto caseread;
-
- case AADDB: /* rhs rar */
- case AADDL:
- case AADDW:
- case AANDB:
- case AANDL:
- case AANDW:
- case ADECL:
- case ADECW:
- case AINCL:
- case AINCW:
- case ASUBB:
- case ASUBL:
- case ASUBW:
- case AORB:
- case AORL:
- case AORW:
- case AXORB:
- case AXORL:
- case AXORW:
- case AMOVB:
- case AMOVW:
-
- case AFMOVB:
- case AFMOVBP:
- case AFMOVD:
- case AFMOVDP:
- case AFMOVF:
- case AFMOVFP:
- case AFMOVL:
- case AFMOVLP:
- case AFMOVV:
- case AFMOVVP:
- case AFMOVW:
- case AFMOVWP:
- case AFMOVX:
- case AFMOVXP:
- case AFADDDP:
- case AFADDW:
- case AFADDL:
- case AFADDF:
- case AFADDD:
- case AFMULDP:
- case AFMULW:
- case AFMULL:
- case AFMULF:
- case AFMULD:
- case AFSUBDP:
- case AFSUBW:
- case AFSUBL:
- case AFSUBF:
- case AFSUBD:
- case AFSUBRDP:
- case AFSUBRW:
- case AFSUBRL:
- case AFSUBRF:
- case AFSUBRD:
- case AFDIVDP:
- case AFDIVW:
- case AFDIVL:
- case AFDIVF:
- case AFDIVD:
- case AFDIVRDP:
- case AFDIVRW:
- case AFDIVRL:
- case AFDIVRF:
- case AFDIVRD:
- if(copyas(&p->to, v))
- return 2;
- goto caseread;
-
- case ACMPL: /* read only */
- case ACMPW:
- case ACMPB:
-
- case APREFETCHT0:
- case APREFETCHT1:
- case APREFETCHT2:
- case APREFETCHNTA:
-
-
- case AFCOMB:
- case AFCOMBP:
- case AFCOMD:
- case AFCOMDP:
- case AFCOMDPP:
- case AFCOMF:
- case AFCOMFP:
- case AFCOML:
- case AFCOMLP:
- case AFCOMW:
- case AFCOMWP:
- case AFUCOM:
- case AFUCOMP:
- case AFUCOMPP:
- caseread:
- if(s != A) {
- if(copysub(&p->from, v, s, 1))
- return 1;
- return copysub(&p->to, v, s, 1);
- }
- if(copyau(&p->from, v))
- return 1;
- if(copyau(&p->to, v))
- return 1;
- break;
-
- case AJGE: /* no reference */
- case AJNE:
- case AJLE:
- case AJEQ:
- case AJHI:
- case AJLS:
- case AJMI:
- case AJPL:
- case AJGT:
- case AJLT:
- case AJCC:
- case AJCS:
-
- case AADJSP:
- case AFLDZ:
- case AWAIT:
- break;
-
- case AIMULL:
- case AIMULW:
- if(p->to.type != D_NONE) {
- if(copyas(&p->to, v))
- return 2;
- goto caseread;
- }
-
- case ADIVB:
- case ADIVL:
- case ADIVW:
- case AIDIVB:
- case AIDIVL:
- case AIDIVW:
- case AIMULB:
- case AMULB:
- case AMULL:
- case AMULW:
-
- case ACWD:
- case ACDQ:
- if(v->type == D_AX || v->type == D_DX)
- return 2;
- goto caseread;
-
- case AREP:
- case AREPN:
- if(v->type == D_CX)
- return 2;
- goto caseread;
-
- case AMOVSB:
- case AMOVSL:
- if(v->type == D_DI || v->type == D_SI)
- return 2;
- goto caseread;
-
- case ASTOSB:
- case ASTOSL:
- if(v->type == D_AX || v->type == D_DI)
- return 2;
- goto caseread;
-
- case AFSTSW:
- if(v->type == D_AX)
- return 2;
- goto caseread;
-
- case AJMP: /* funny */
- if(s != A) {
- if(copysub(&p->to, v, s, 1))
- return 1;
- return 0;
- }
- if(copyau(&p->to, v))
- return 1;
- return 0;
-
- case ARET: /* funny */
- if(v->type == REGRET)
- return 2;
- if(s != A)
- return 1;
- return 3;
-
- case ACALL: /* funny */
- if(REGARG >= 0 && v->type == (uchar)REGARG)
- return 2;
-
- if(s != A) {
- if(copysub(&p->to, v, s, 1))
- return 1;
- return 0;
- }
- if(copyau(&p->to, v))
- return 4;
- return 3;
- }
- return 0;
-}
-
-/*
- * direct reference,
- * could be set/use depending on
- * semantics
- */
-int
-copyas(Addr *a, Addr *v)
-{
- if(a->type != v->type)
- return 0;
- if(regtyp(v))
- return 1;
- if(v->type == D_AUTO || v->type == D_PARAM)
- if(v->offset == a->offset)
- return 1;
- return 0;
-}
-
-/*
- * either direct or indirect
- */
-int
-copyau(Addr *a, Addr *v)
-{
-
- if(copyas(a, v))
- return 1;
- if(regtyp(v)) {
- if(a->type-D_INDIR == v->type)
- return 1;
- if(a->index == v->type)
- return 1;
- }
- return 0;
-}
-
-/*
- * substitute s for v in a
- * return failure to substitute
- */
-int
-copysub(Addr *a, Addr *v, Addr *s, int f)
-{
- int t;
-
- if(copyas(a, v)) {
- t = s->type;
- if(t >= D_AX && t <= D_DI) {
- if(f)
- a->type = t;
- }
- return 0;
- }
- if(regtyp(v)) {
- t = v->type;
- if(a->type == t+D_INDIR) {
- if(s->type == D_BP && a->index != D_NONE)
- return 1; /* can't use BP-base with index */
- if(f)
- a->type = s->type+D_INDIR;
-// return 0;
- }
- if(a->index == t) {
- if(f)
- a->index = s->type;
- return 0;
- }
- return 0;
- }
- return 0;
-}
diff --git a/src/cmd/8c/reg.c b/src/cmd/8c/reg.c
deleted file mode 100644
index ea862f388..000000000
--- a/src/cmd/8c/reg.c
+++ /dev/null
@@ -1,1438 +0,0 @@
-// Inferno utils/8c/reg.c
-// http://code.google.com/p/inferno-os/source/browse/utils/8c/reg.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-
-static void fixjmp(Reg*);
-
-Reg*
-rega(void)
-{
- Reg *r;
-
- r = freer;
- if(r == R) {
- r = alloc(sizeof(*r));
- } else
- freer = r->link;
-
- *r = zreg;
- return r;
-}
-
-int
-rcmp(const void *a1, const void *a2)
-{
- Rgn *p1, *p2;
- int c1, c2;
-
- p1 = (Rgn*)a1;
- p2 = (Rgn*)a2;
- c1 = p2->cost;
- c2 = p1->cost;
- if(c1 -= c2)
- return c1;
- return p2->varno - p1->varno;
-}
-
-void
-regopt(Prog *p)
-{
- Reg *r, *r1, *r2;
- Prog *p1;
- int i, z;
- int32 initpc, val, npc;
- uint32 vreg;
- Bits bit;
- struct
- {
- int32 m;
- int32 c;
- Reg* p;
- } log5[6], *lp;
-
- firstr = R;
- lastr = R;
- nvar = 0;
- regbits = RtoB(D_SP) | RtoB(D_AX);
- for(z=0; z<BITS; z++) {
- externs.b[z] = 0;
- params.b[z] = 0;
- consts.b[z] = 0;
- addrs.b[z] = 0;
- }
-
- /*
- * pass 1
- * build aux data structure
- * allocate pcs
- * find use and set of variables
- */
- val = 5L * 5L * 5L * 5L * 5L;
- lp = log5;
- for(i=0; i<5; i++) {
- lp->m = val;
- lp->c = 0;
- lp->p = R;
- val /= 5L;
- lp++;
- }
- val = 0;
- for(; p != P; p = p->link) {
- switch(p->as) {
- case ADATA:
- case AGLOBL:
- case ANAME:
- case ASIGNAME:
- case AFUNCDATA:
- continue;
- }
- r = rega();
- if(firstr == R) {
- firstr = r;
- lastr = r;
- } else {
- lastr->link = r;
- r->p1 = lastr;
- lastr->s1 = r;
- lastr = r;
- }
- r->prog = p;
- r->pc = val;
- val++;
-
- lp = log5;
- for(i=0; i<5; i++) {
- lp->c--;
- if(lp->c <= 0) {
- lp->c = lp->m;
- if(lp->p != R)
- lp->p->log5 = r;
- lp->p = r;
- (lp+1)->c = 0;
- break;
- }
- lp++;
- }
-
- r1 = r->p1;
- if(r1 != R)
- switch(r1->prog->as) {
- case ARET:
- case AJMP:
- case AIRETL:
- r->p1 = R;
- r1->s1 = R;
- }
- bit = mkvar(r, &p->from);
- if(bany(&bit))
- switch(p->as) {
- /*
- * funny
- */
- case ALEAL:
- for(z=0; z<BITS; z++)
- addrs.b[z] |= bit.b[z];
- break;
-
- /*
- * left side read
- */
- default:
- for(z=0; z<BITS; z++)
- r->use1.b[z] |= bit.b[z];
- break;
- }
-
- bit = mkvar(r, &p->to);
- if(bany(&bit))
- switch(p->as) {
- default:
- diag(Z, "reg: unknown op: %A", p->as);
- break;
-
- /*
- * right side read
- */
- case ACMPB:
- case ACMPL:
- case ACMPW:
- case APREFETCHT0:
- case APREFETCHT1:
- case APREFETCHT2:
- case APREFETCHNTA:
- for(z=0; z<BITS; z++)
- r->use2.b[z] |= bit.b[z];
- break;
-
- /*
- * right side write
- */
- case ANOP:
- case AMOVL:
- case AMOVB:
- case AMOVW:
- case AMOVBLSX:
- case AMOVBLZX:
- case AMOVWLSX:
- case AMOVWLZX:
- for(z=0; z<BITS; z++)
- r->set.b[z] |= bit.b[z];
- break;
-
- /*
- * right side read+write
- */
- case AADDB:
- case AADDL:
- case AADDW:
- case AANDB:
- case AANDL:
- case AANDW:
- case ASUBB:
- case ASUBL:
- case ASUBW:
- case AORB:
- case AORL:
- case AORW:
- case AXORB:
- case AXORL:
- case AXORW:
- case ASALB:
- case ASALL:
- case ASALW:
- case ASARB:
- case ASARL:
- case ASARW:
- case AROLB:
- case AROLL:
- case AROLW:
- case ARORB:
- case ARORL:
- case ARORW:
- case ASHLB:
- case ASHLL:
- case ASHLW:
- case ASHRB:
- case ASHRL:
- case ASHRW:
- case AIMULL:
- case AIMULW:
- case ANEGL:
- case ANOTL:
- case AADCL:
- case ASBBL:
- for(z=0; z<BITS; z++) {
- r->set.b[z] |= bit.b[z];
- r->use2.b[z] |= bit.b[z];
- }
- break;
-
- /*
- * funny
- */
- case AFMOVDP:
- case AFMOVFP:
- case AFMOVLP:
- case AFMOVVP:
- case AFMOVWP:
- case ACALL:
- for(z=0; z<BITS; z++)
- addrs.b[z] |= bit.b[z];
- break;
- }
-
- switch(p->as) {
- case AIMULL:
- case AIMULW:
- if(p->to.type != D_NONE)
- break;
-
- case AIDIVB:
- case AIDIVL:
- case AIDIVW:
- case AIMULB:
- case ADIVB:
- case ADIVL:
- case ADIVW:
- case AMULB:
- case AMULL:
- case AMULW:
-
- case ACWD:
- case ACDQ:
- r->regu |= RtoB(D_AX) | RtoB(D_DX);
- break;
-
- case AREP:
- case AREPN:
- case ALOOP:
- case ALOOPEQ:
- case ALOOPNE:
- r->regu |= RtoB(D_CX);
- break;
-
- case AMOVSB:
- case AMOVSL:
- case AMOVSW:
- case ACMPSB:
- case ACMPSL:
- case ACMPSW:
- r->regu |= RtoB(D_SI) | RtoB(D_DI);
- break;
-
- case ASTOSB:
- case ASTOSL:
- case ASTOSW:
- case ASCASB:
- case ASCASL:
- case ASCASW:
- r->regu |= RtoB(D_AX) | RtoB(D_DI);
- break;
-
- case AINSB:
- case AINSL:
- case AINSW:
- case AOUTSB:
- case AOUTSL:
- case AOUTSW:
- r->regu |= RtoB(D_DI) | RtoB(D_DX);
- break;
-
- case AFSTSW:
- case ASAHF:
- r->regu |= RtoB(D_AX);
- break;
- }
- }
- if(firstr == R)
- return;
- initpc = pc - val;
- npc = val;
-
- /*
- * pass 2
- * turn branch references to pointers
- * build back pointers
- */
- for(r = firstr; r != R; r = r->link) {
- p = r->prog;
- if(p->to.type == D_BRANCH) {
- val = p->to.offset - initpc;
- r1 = firstr;
- while(r1 != R) {
- r2 = r1->log5;
- if(r2 != R && val >= r2->pc) {
- r1 = r2;
- continue;
- }
- if(r1->pc == val)
- break;
- r1 = r1->link;
- }
- if(r1 == R) {
- nearln = p->lineno;
- diag(Z, "ref not found\n%P", p);
- continue;
- }
- if(r1 == r) {
- nearln = p->lineno;
- diag(Z, "ref to self\n%P", p);
- continue;
- }
- r->s2 = r1;
- r->p2link = r1->p2;
- r1->p2 = r;
- }
- }
- if(debug['R']) {
- p = firstr->prog;
- print("\n%L %D\n", p->lineno, &p->from);
- }
-
- /*
- * pass 2.1
- * fix jumps
- */
- fixjmp(firstr);
-
- /*
- * pass 2.5
- * find looping structure
- */
- for(r = firstr; r != R; r = r->link)
- r->active = 0;
- change = 0;
- loopit(firstr, npc);
- if(debug['R'] && debug['v']) {
- print("\nlooping structure:\n");
- for(r = firstr; r != R; r = r->link) {
- print("%d:%P", r->loop, r->prog);
- for(z=0; z<BITS; z++)
- bit.b[z] = r->use1.b[z] |
- r->use2.b[z] |
- r->set.b[z];
- if(bany(&bit)) {
- print("\t");
- if(bany(&r->use1))
- print(" u1=%B", r->use1);
- if(bany(&r->use2))
- print(" u2=%B", r->use2);
- if(bany(&r->set))
- print(" st=%B", r->set);
- }
- print("\n");
- }
- }
-
- /*
- * pass 3
- * iterate propagating usage
- * back until flow graph is complete
- */
-loop1:
- change = 0;
- for(r = firstr; r != R; r = r->link)
- r->active = 0;
- for(r = firstr; r != R; r = r->link)
- if(r->prog->as == ARET)
- prop(r, zbits, zbits);
-loop11:
- /* pick up unreachable code */
- i = 0;
- for(r = firstr; r != R; r = r1) {
- r1 = r->link;
- if(r1 && r1->active && !r->active) {
- prop(r, zbits, zbits);
- i = 1;
- }
- }
- if(i)
- goto loop11;
- if(change)
- goto loop1;
-
-
- /*
- * pass 4
- * iterate propagating register/variable synchrony
- * forward until graph is complete
- */
-loop2:
- change = 0;
- for(r = firstr; r != R; r = r->link)
- r->active = 0;
- synch(firstr, zbits);
- if(change)
- goto loop2;
-
-
- /*
- * pass 5
- * isolate regions
- * calculate costs (paint1)
- */
- r = firstr;
- if(r) {
- for(z=0; z<BITS; z++)
- bit.b[z] = (r->refahead.b[z] | r->calahead.b[z]) &
- ~(externs.b[z] | params.b[z] | addrs.b[z] | consts.b[z]);
- if(bany(&bit)) {
- nearln = r->prog->lineno;
- warn(Z, "used and not set: %B", bit);
- if(debug['R'] && !debug['w'])
- print("used and not set: %B\n", bit);
- }
- }
- if(debug['R'] && debug['v'])
- print("\nprop structure:\n");
- for(r = firstr; r != R; r = r->link)
- r->act = zbits;
- rgp = region;
- nregion = 0;
- for(r = firstr; r != R; r = r->link) {
- if(debug['R'] && debug['v']) {
- print("%P\t", r->prog);
- if(bany(&r->set))
- print("s:%B ", r->set);
- if(bany(&r->refahead))
- print("ra:%B ", r->refahead);
- if(bany(&r->calahead))
- print("ca:%B ", r->calahead);
- print("\n");
- }
- for(z=0; z<BITS; z++)
- bit.b[z] = r->set.b[z] &
- ~(r->refahead.b[z] | r->calahead.b[z] | addrs.b[z]);
- if(bany(&bit)) {
- nearln = r->prog->lineno;
- warn(Z, "set and not used: %B", bit);
- if(debug['R'])
- print("set and not used: %B\n", bit);
- excise(r);
- }
- for(z=0; z<BITS; z++)
- bit.b[z] = LOAD(r) & ~(r->act.b[z] | addrs.b[z]);
- while(bany(&bit)) {
- i = bnum(bit);
- rgp->enter = r;
- rgp->varno = i;
- change = 0;
- if(debug['R'] && debug['v'])
- print("\n");
- paint1(r, i);
- bit.b[i/32] &= ~(1L<<(i%32));
- if(change <= 0) {
- if(debug['R'])
- print("%L$%d: %B\n",
- r->prog->lineno, change, blsh(i));
- continue;
- }
- rgp->cost = change;
- nregion++;
- if(nregion >= NRGN) {
- fatal(Z, "too many regions");
- goto brk;
- }
- rgp++;
- }
- }
-brk:
- qsort(region, nregion, sizeof(region[0]), rcmp);
-
- /*
- * pass 6
- * determine used registers (paint2)
- * replace code (paint3)
- */
- rgp = region;
- for(i=0; i<nregion; i++) {
- bit = blsh(rgp->varno);
- vreg = paint2(rgp->enter, rgp->varno);
- vreg = allreg(vreg, rgp);
- if(debug['R']) {
- print("%L$%d %R: %B\n",
- rgp->enter->prog->lineno,
- rgp->cost,
- rgp->regno,
- bit);
- }
- if(rgp->regno != 0)
- paint3(rgp->enter, rgp->varno, vreg, rgp->regno);
- rgp++;
- }
- /*
- * pass 7
- * peep-hole on basic block
- */
- if(!debug['R'] || debug['P'])
- peep();
-
- if(debug['R'] && debug['v']) {
- print("after pass 7 (peep)\n");
- for(r=firstr; r; r=r->link)
- print("%04d %P\n", (int)r->pc, r->prog);
- print("\n");
- }
-
- /*
- * pass 8
- * recalculate pc
- */
- val = initpc;
- for(r = firstr; r != R; r = r1) {
- r->pc = val;
- p = r->prog;
- p1 = P;
- r1 = r->link;
- if(r1 != R)
- p1 = r1->prog;
- for(; p != p1; p = p->link) {
- switch(p->as) {
- default:
- val++;
- break;
-
- case ANOP:
- case ADATA:
- case AGLOBL:
- case ANAME:
- case ASIGNAME:
- case AFUNCDATA:
- break;
- }
- }
- }
- pc = val;
-
- /*
- * fix up branches
- */
- if(debug['R'])
- if(bany(&addrs))
- print("addrs: %B\n", addrs);
-
- r1 = 0; /* set */
- for(r = firstr; r != R; r = r->link) {
- p = r->prog;
- if(p->to.type == D_BRANCH) {
- p->to.offset = r->s2->pc;
- p->to.u.branch = r->s2->prog;
- }
- r1 = r;
- }
-
- /*
- * last pass
- * eliminate nops
- * free aux structures
- */
- for(p = firstr->prog; p != P; p = p->link){
- while(p->link && p->link->as == ANOP)
- p->link = p->link->link;
- }
-
- if(debug['R'] && debug['v']) {
- print("after pass 8 (fixup pc)\n");
- for(p1=firstr->prog; p1!=P; p1=p1->link)
- print("%P\n", p1);
- print("\n");
- }
-
- if(r1 != R) {
- r1->link = freer;
- freer = firstr;
- }
-}
-
-/*
- * add mov b,rn
- * just after r
- */
-void
-addmove(Reg *r, int bn, int rn, int f)
-{
- Prog *p, *p1;
- Addr *a;
- Var *v;
-
- p1 = alloc(sizeof(*p1));
- *p1 = zprog;
- p = r->prog;
-
- p1->link = p->link;
- p->link = p1;
- p1->lineno = p->lineno;
-
- v = var + bn;
-
- a = &p1->to;
- a->sym = v->sym;
- a->offset = v->offset;
- a->etype = v->etype;
- a->type = v->name;
-
- p1->as = AMOVL;
- if(v->etype == TCHAR || v->etype == TUCHAR)
- p1->as = AMOVB;
- if(v->etype == TSHORT || v->etype == TUSHORT)
- p1->as = AMOVW;
-
- p1->from.type = rn;
- if(!f) {
- p1->from = *a;
- *a = zprog.from;
- a->type = rn;
- if(v->etype == TUCHAR)
- p1->as = AMOVB;
- if(v->etype == TUSHORT)
- p1->as = AMOVW;
- }
- if(debug['R'])
- print("%P\t.a%P\n", p, p1);
-}
-
-uint32
-doregbits(int r)
-{
- uint32 b;
-
- b = 0;
- if(r >= D_INDIR)
- r -= D_INDIR;
- if(r >= D_AX && r <= D_DI)
- b |= RtoB(r);
- else
- if(r >= D_AL && r <= D_BL)
- b |= RtoB(r-D_AL+D_AX);
- else
- if(r >= D_AH && r <= D_BH)
- b |= RtoB(r-D_AH+D_AX);
- return b;
-}
-
-Bits
-mkvar(Reg *r, Addr *a)
-{
- Var *v;
- int i, t, n, et, z;
- int32 o;
- Bits bit;
- LSym *s;
-
- /*
- * mark registers used
- */
- t = a->type;
- r->regu |= doregbits(t);
- r->regu |= doregbits(a->index);
-
- switch(t) {
- default:
- goto none;
- case D_ADDR:
- a->type = a->index;
- bit = mkvar(r, a);
- for(z=0; z<BITS; z++)
- addrs.b[z] |= bit.b[z];
- a->type = t;
- goto none;
- case D_EXTERN:
- case D_STATIC:
- case D_PARAM:
- case D_AUTO:
- n = t;
- break;
- }
- s = a->sym;
- if(s == nil)
- goto none;
- if(s->name[0] == '.')
- goto none;
- et = a->etype;
- o = a->offset;
- v = var;
- for(i=0; i<nvar; i++) {
- if(s == v->sym)
- if(n == v->name)
- if(o == v->offset)
- goto out;
- v++;
- }
- if(nvar >= NVAR)
- fatal(Z, "variable not optimized: %s", s->name);
- i = nvar;
- nvar++;
- v = &var[i];
- v->sym = s;
- v->offset = o;
- v->name = n;
- v->etype = et;
- if(debug['R'])
- print("bit=%2d et=%2d %D\n", i, et, a);
-
-out:
- bit = blsh(i);
- if(n == D_EXTERN || n == D_STATIC)
- for(z=0; z<BITS; z++)
- externs.b[z] |= bit.b[z];
- if(n == D_PARAM)
- for(z=0; z<BITS; z++)
- params.b[z] |= bit.b[z];
- if(v->etype != et || !typechlpfd[et]) /* funny punning */
- for(z=0; z<BITS; z++)
- addrs.b[z] |= bit.b[z];
- return bit;
-
-none:
- return zbits;
-}
-
-void
-prop(Reg *r, Bits ref, Bits cal)
-{
- Reg *r1, *r2;
- int z;
-
- for(r1 = r; r1 != R; r1 = r1->p1) {
- for(z=0; z<BITS; z++) {
- ref.b[z] |= r1->refahead.b[z];
- if(ref.b[z] != r1->refahead.b[z]) {
- r1->refahead.b[z] = ref.b[z];
- change++;
- }
- cal.b[z] |= r1->calahead.b[z];
- if(cal.b[z] != r1->calahead.b[z]) {
- r1->calahead.b[z] = cal.b[z];
- change++;
- }
- }
- switch(r1->prog->as) {
- case ACALL:
- for(z=0; z<BITS; z++) {
- cal.b[z] |= ref.b[z] | externs.b[z];
- ref.b[z] = 0;
- }
- break;
-
- case ATEXT:
- for(z=0; z<BITS; z++) {
- cal.b[z] = 0;
- ref.b[z] = 0;
- }
- break;
-
- case ARET:
- for(z=0; z<BITS; z++) {
- cal.b[z] = externs.b[z];
- ref.b[z] = 0;
- }
- }
- for(z=0; z<BITS; z++) {
- ref.b[z] = (ref.b[z] & ~r1->set.b[z]) |
- r1->use1.b[z] | r1->use2.b[z];
- cal.b[z] &= ~(r1->set.b[z] | r1->use1.b[z] | r1->use2.b[z]);
- r1->refbehind.b[z] = ref.b[z];
- r1->calbehind.b[z] = cal.b[z];
- }
- if(r1->active)
- break;
- r1->active = 1;
- }
- for(; r != r1; r = r->p1)
- for(r2 = r->p2; r2 != R; r2 = r2->p2link)
- prop(r2, r->refbehind, r->calbehind);
-}
-
-/*
- * find looping structure
- *
- * 1) find reverse postordering
- * 2) find approximate dominators,
- * the actual dominators if the flow graph is reducible
- * otherwise, dominators plus some other non-dominators.
- * See Matthew S. Hecht and Jeffrey D. Ullman,
- * "Analysis of a Simple Algorithm for Global Data Flow Problems",
- * Conf. Record of ACM Symp. on Principles of Prog. Langs, Boston, Massachusetts,
- * Oct. 1-3, 1973, pp. 207-217.
- * 3) find all nodes with a predecessor dominated by the current node.
- * such a node is a loop head.
- * recursively, all preds with a greater rpo number are in the loop
- */
-int32
-postorder(Reg *r, Reg **rpo2r, int32 n)
-{
- Reg *r1;
-
- r->rpo = 1;
- r1 = r->s1;
- if(r1 && !r1->rpo)
- n = postorder(r1, rpo2r, n);
- r1 = r->s2;
- if(r1 && !r1->rpo)
- n = postorder(r1, rpo2r, n);
- rpo2r[n] = r;
- n++;
- return n;
-}
-
-int32
-rpolca(int32 *idom, int32 rpo1, int32 rpo2)
-{
- int32 t;
-
- if(rpo1 == -1)
- return rpo2;
- while(rpo1 != rpo2){
- if(rpo1 > rpo2){
- t = rpo2;
- rpo2 = rpo1;
- rpo1 = t;
- }
- while(rpo1 < rpo2){
- t = idom[rpo2];
- if(t >= rpo2)
- fatal(Z, "bad idom");
- rpo2 = t;
- }
- }
- return rpo1;
-}
-
-int
-doms(int32 *idom, int32 r, int32 s)
-{
- while(s > r)
- s = idom[s];
- return s == r;
-}
-
-int
-loophead(int32 *idom, Reg *r)
-{
- int32 src;
-
- src = r->rpo;
- if(r->p1 != R && doms(idom, src, r->p1->rpo))
- return 1;
- for(r = r->p2; r != R; r = r->p2link)
- if(doms(idom, src, r->rpo))
- return 1;
- return 0;
-}
-
-void
-loopmark(Reg **rpo2r, int32 head, Reg *r)
-{
- if(r->rpo < head || r->active == head)
- return;
- r->active = head;
- r->loop += LOOP;
- if(r->p1 != R)
- loopmark(rpo2r, head, r->p1);
- for(r = r->p2; r != R; r = r->p2link)
- loopmark(rpo2r, head, r);
-}
-
-void
-loopit(Reg *r, int32 nr)
-{
- Reg *r1;
- int32 i, d, me;
-
- if(nr > maxnr) {
- rpo2r = alloc(nr * sizeof(Reg*));
- idom = alloc(nr * sizeof(int32));
- maxnr = nr;
- }
-
- d = postorder(r, rpo2r, 0);
- if(d > nr)
- fatal(Z, "too many reg nodes");
- nr = d;
- for(i = 0; i < nr / 2; i++){
- r1 = rpo2r[i];
- rpo2r[i] = rpo2r[nr - 1 - i];
- rpo2r[nr - 1 - i] = r1;
- }
- for(i = 0; i < nr; i++)
- rpo2r[i]->rpo = i;
-
- idom[0] = 0;
- for(i = 0; i < nr; i++){
- r1 = rpo2r[i];
- me = r1->rpo;
- d = -1;
- if(r1->p1 != R && r1->p1->rpo < me)
- d = r1->p1->rpo;
- for(r1 = r1->p2; r1 != nil; r1 = r1->p2link)
- if(r1->rpo < me)
- d = rpolca(idom, d, r1->rpo);
- idom[i] = d;
- }
-
- for(i = 0; i < nr; i++){
- r1 = rpo2r[i];
- r1->loop++;
- if(r1->p2 != R && loophead(idom, r1))
- loopmark(rpo2r, i, r1);
- }
-}
-
-void
-synch(Reg *r, Bits dif)
-{
- Reg *r1;
- int z;
-
- for(r1 = r; r1 != R; r1 = r1->s1) {
- for(z=0; z<BITS; z++) {
- dif.b[z] = (dif.b[z] &
- ~(~r1->refbehind.b[z] & r1->refahead.b[z])) |
- r1->set.b[z] | r1->regdiff.b[z];
- if(dif.b[z] != r1->regdiff.b[z]) {
- r1->regdiff.b[z] = dif.b[z];
- change++;
- }
- }
- if(r1->active)
- break;
- r1->active = 1;
- for(z=0; z<BITS; z++)
- dif.b[z] &= ~(~r1->calbehind.b[z] & r1->calahead.b[z]);
- if(r1->s2 != R)
- synch(r1->s2, dif);
- }
-}
-
-uint32
-allreg(uint32 b, Rgn *r)
-{
- Var *v;
- int i;
-
- v = var + r->varno;
- r->regno = 0;
- switch(v->etype) {
-
- default:
- diag(Z, "unknown etype %d/%d", bitno(b), v->etype);
- break;
-
- case TCHAR:
- case TUCHAR:
- case TSHORT:
- case TUSHORT:
- case TINT:
- case TUINT:
- case TLONG:
- case TULONG:
- case TIND:
- case TARRAY:
- i = BtoR(~b);
- if(i && r->cost > 0) {
- r->regno = i;
- return RtoB(i);
- }
- break;
-
- case TDOUBLE:
- case TFLOAT:
- break;
- }
- return 0;
-}
-
-void
-paint1(Reg *r, int bn)
-{
- Reg *r1;
- Prog *p;
- int z;
- uint32 bb;
-
- z = bn/32;
- bb = 1L<<(bn%32);
- if(r->act.b[z] & bb)
- return;
- for(;;) {
- if(!(r->refbehind.b[z] & bb))
- break;
- r1 = r->p1;
- if(r1 == R)
- break;
- if(!(r1->refahead.b[z] & bb))
- break;
- if(r1->act.b[z] & bb)
- break;
- r = r1;
- }
-
- if(LOAD(r) & ~(r->set.b[z]&~(r->use1.b[z]|r->use2.b[z])) & bb) {
- change -= CLOAD * r->loop;
- if(debug['R'] && debug['v'])
- print("%d%P\td %B $%d\n", r->loop,
- r->prog, blsh(bn), change);
- }
- for(;;) {
- r->act.b[z] |= bb;
- p = r->prog;
-
- if(r->use1.b[z] & bb) {
- change += CREF * r->loop;
- if(p->as == AFMOVL)
- if(BtoR(bb) != D_F0)
- change = -CINF;
- if(debug['R'] && debug['v'])
- print("%d%P\tu1 %B $%d\n", r->loop,
- p, blsh(bn), change);
- }
-
- if((r->use2.b[z]|r->set.b[z]) & bb) {
- change += CREF * r->loop;
- if(p->as == AFMOVL)
- if(BtoR(bb) != D_F0)
- change = -CINF;
- if(debug['R'] && debug['v'])
- print("%d%P\tu2 %B $%d\n", r->loop,
- p, blsh(bn), change);
- }
-
- if(STORE(r) & r->regdiff.b[z] & bb) {
- change -= CLOAD * r->loop;
- if(p->as == AFMOVL)
- if(BtoR(bb) != D_F0)
- change = -CINF;
- if(debug['R'] && debug['v'])
- print("%d%P\tst %B $%d\n", r->loop,
- p, blsh(bn), change);
- }
-
- if(r->refbehind.b[z] & bb)
- for(r1 = r->p2; r1 != R; r1 = r1->p2link)
- if(r1->refahead.b[z] & bb)
- paint1(r1, bn);
-
- if(!(r->refahead.b[z] & bb))
- break;
- r1 = r->s2;
- if(r1 != R)
- if(r1->refbehind.b[z] & bb)
- paint1(r1, bn);
- r = r->s1;
- if(r == R)
- break;
- if(r->act.b[z] & bb)
- break;
- if(!(r->refbehind.b[z] & bb))
- break;
- }
-}
-
-uint32
-regset(Reg *r, uint32 bb)
-{
- uint32 b, set;
- Addr v;
- int c;
-
- set = 0;
- v = zprog.from;
- while(b = bb & ~(bb-1)) {
- v.type = BtoR(b);
- c = copyu(r->prog, &v, A);
- if(c == 3)
- set |= b;
- bb &= ~b;
- }
- return set;
-}
-
-uint32
-reguse(Reg *r, uint32 bb)
-{
- uint32 b, set;
- Addr v;
- int c;
-
- set = 0;
- v = zprog.from;
- while(b = bb & ~(bb-1)) {
- v.type = BtoR(b);
- c = copyu(r->prog, &v, A);
- if(c == 1 || c == 2 || c == 4)
- set |= b;
- bb &= ~b;
- }
- return set;
-}
-
-uint32
-paint2(Reg *r, int bn)
-{
- Reg *r1;
- int z;
- uint32 bb, vreg, x;
-
- z = bn/32;
- bb = 1L << (bn%32);
- vreg = regbits;
- if(!(r->act.b[z] & bb))
- return vreg;
- for(;;) {
- if(!(r->refbehind.b[z] & bb))
- break;
- r1 = r->p1;
- if(r1 == R)
- break;
- if(!(r1->refahead.b[z] & bb))
- break;
- if(!(r1->act.b[z] & bb))
- break;
- r = r1;
- }
- for(;;) {
- r->act.b[z] &= ~bb;
-
- vreg |= r->regu;
-
- if(r->refbehind.b[z] & bb)
- for(r1 = r->p2; r1 != R; r1 = r1->p2link)
- if(r1->refahead.b[z] & bb)
- vreg |= paint2(r1, bn);
-
- if(!(r->refahead.b[z] & bb))
- break;
- r1 = r->s2;
- if(r1 != R)
- if(r1->refbehind.b[z] & bb)
- vreg |= paint2(r1, bn);
- r = r->s1;
- if(r == R)
- break;
- if(!(r->act.b[z] & bb))
- break;
- if(!(r->refbehind.b[z] & bb))
- break;
- }
-
- bb = vreg;
- for(; r; r=r->s1) {
- x = r->regu & ~bb;
- if(x) {
- vreg |= reguse(r, x);
- bb |= regset(r, x);
- }
- }
- return vreg;
-}
-
-void
-paint3(Reg *r, int bn, int32 rb, int rn)
-{
- Reg *r1;
- Prog *p;
- int z;
- uint32 bb;
-
- z = bn/32;
- bb = 1L << (bn%32);
- if(r->act.b[z] & bb)
- return;
- for(;;) {
- if(!(r->refbehind.b[z] & bb))
- break;
- r1 = r->p1;
- if(r1 == R)
- break;
- if(!(r1->refahead.b[z] & bb))
- break;
- if(r1->act.b[z] & bb)
- break;
- r = r1;
- }
-
- if(LOAD(r) & ~(r->set.b[z] & ~(r->use1.b[z]|r->use2.b[z])) & bb)
- addmove(r, bn, rn, 0);
- for(;;) {
- r->act.b[z] |= bb;
- p = r->prog;
-
- if(r->use1.b[z] & bb) {
- if(debug['R'])
- print("%P", p);
- addreg(&p->from, rn);
- if(debug['R'])
- print("\t.c%P\n", p);
- }
- if((r->use2.b[z]|r->set.b[z]) & bb) {
- if(debug['R'])
- print("%P", p);
- addreg(&p->to, rn);
- if(debug['R'])
- print("\t.c%P\n", p);
- }
-
- if(STORE(r) & r->regdiff.b[z] & bb)
- addmove(r, bn, rn, 1);
- r->regu |= rb;
-
- if(r->refbehind.b[z] & bb)
- for(r1 = r->p2; r1 != R; r1 = r1->p2link)
- if(r1->refahead.b[z] & bb)
- paint3(r1, bn, rb, rn);
-
- if(!(r->refahead.b[z] & bb))
- break;
- r1 = r->s2;
- if(r1 != R)
- if(r1->refbehind.b[z] & bb)
- paint3(r1, bn, rb, rn);
- r = r->s1;
- if(r == R)
- break;
- if(r->act.b[z] & bb)
- break;
- if(!(r->refbehind.b[z] & bb))
- break;
- }
-}
-
-void
-addreg(Addr *a, int rn)
-{
-
- a->sym = 0;
- a->offset = 0;
- a->type = rn;
-}
-
-int32
-RtoB(int r)
-{
-
- if(r < D_AX || r > D_DI)
- return 0;
- return 1L << (r-D_AX);
-}
-
-int
-BtoR(int32 b)
-{
-
- b &= 0xffL;
- if(b == 0)
- return 0;
- return bitno(b) + D_AX;
-}
-
-/* what instruction does a JMP to p eventually land on? */
-static Reg*
-chasejmp(Reg *r, int *jmploop)
-{
- int n;
-
- n = 0;
- for(; r; r=r->s2) {
- if(r->prog->as != AJMP || r->prog->to.type != D_BRANCH)
- break;
- if(++n > 10) {
- *jmploop = 1;
- break;
- }
- }
- return r;
-}
-
-/* mark all code reachable from firstp as alive */
-static void
-mark(Reg *firstr)
-{
- Reg *r;
- Prog *p;
-
- for(r=firstr; r; r=r->link) {
- if(r->active)
- break;
- r->active = 1;
- p = r->prog;
- if(p->as != ACALL && p->to.type == D_BRANCH)
- mark(r->s2);
- if(p->as == AJMP || p->as == ARET || p->as == AUNDEF)
- break;
- }
-}
-
-/*
- * the code generator depends on being able to write out JMP
- * instructions that it can jump to now but fill in later.
- * the linker will resolve them nicely, but they make the code
- * longer and more difficult to follow during debugging.
- * remove them.
- */
-static void
-fixjmp(Reg *firstr)
-{
- int jmploop;
- Reg *r;
- Prog *p;
-
- if(debug['R'] && debug['v'])
- print("\nfixjmp\n");
-
- // pass 1: resolve jump to AJMP, mark all code as dead.
- jmploop = 0;
- for(r=firstr; r; r=r->link) {
- p = r->prog;
- if(debug['R'] && debug['v'])
- print("%04d %P\n", (int)r->pc, p);
- if(p->as != ACALL && p->to.type == D_BRANCH && r->s2 && r->s2->prog->as == AJMP) {
- r->s2 = chasejmp(r->s2, &jmploop);
- p->to.offset = r->s2->pc;
- p->to.u.branch = r->s2->prog;
- if(debug['R'] && debug['v'])
- print("->%P\n", p);
- }
- r->active = 0;
- }
- if(debug['R'] && debug['v'])
- print("\n");
-
- // pass 2: mark all reachable code alive
- mark(firstr);
-
- // pass 3: delete dead code (mostly JMPs).
- for(r=firstr; r; r=r->link) {
- if(!r->active) {
- p = r->prog;
- if(p->link == P && p->as == ARET && r->p1 && r->p1->prog->as != ARET) {
- // This is the final ARET, and the code so far doesn't have one.
- // Let it stay.
- } else {
- if(debug['R'] && debug['v'])
- print("del %04d %P\n", (int)r->pc, p);
- p->as = ANOP;
- }
- }
- }
-
- // pass 4: elide JMP to next instruction.
- // only safe if there are no jumps to JMPs anymore.
- if(!jmploop) {
- for(r=firstr; r; r=r->link) {
- p = r->prog;
- if(p->as == AJMP && p->to.type == D_BRANCH && r->s2 == r->link) {
- if(debug['R'] && debug['v'])
- print("del %04d %P\n", (int)r->pc, p);
- p->as = ANOP;
- }
- }
- }
-
- // fix back pointers.
- for(r=firstr; r; r=r->link) {
- r->p2 = R;
- r->p2link = R;
- }
- for(r=firstr; r; r=r->link) {
- if(r->s2) {
- r->p2link = r->s2->p2;
- r->s2->p2 = r;
- }
- }
-
- if(debug['R'] && debug['v']) {
- print("\n");
- for(r=firstr; r; r=r->link)
- print("%04d %P\n", (int)r->pc, r->prog);
- print("\n");
- }
-}
-
diff --git a/src/cmd/8c/sgen.c b/src/cmd/8c/sgen.c
deleted file mode 100644
index d647010ef..000000000
--- a/src/cmd/8c/sgen.c
+++ /dev/null
@@ -1,483 +0,0 @@
-// Inferno utils/8c/sgen.c
-// http://code.google.com/p/inferno-os/source/browse/utils/8c/sgen.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-
-Prog*
-gtext(Sym *s, int32 stkoff)
-{
- int32 a;
-
- a = argsize(1);
- if((textflag & NOSPLIT) != 0 && stkoff >= 128)
- yyerror("stack frame too large for NOSPLIT function");
-
- gpseudo(ATEXT, s, nodconst(stkoff));
- p->to.type = D_CONST2;
- p->to.offset2 = a;
- return p;
-}
-
-void
-noretval(int n)
-{
-
- if(n & 1) {
- gins(ANOP, Z, Z);
- p->to.type = REGRET;
- }
- if(n & 2) {
- gins(ANOP, Z, Z);
- p->to.type = FREGRET;
- }
-}
-
-/* welcome to commute */
-static void
-commute(Node *n)
-{
- Node *l, *r;
-
- l = n->left;
- r = n->right;
- if(r->complex > l->complex) {
- n->left = r;
- n->right = l;
- }
-}
-
-void
-indexshift(Node *n)
-{
- int g;
-
- if(!typechlp[n->type->etype])
- return;
- simplifyshift(n);
- if(n->op == OASHL && n->right->op == OCONST){
- g = vconst(n->right);
- if(g >= 0 && g < 4)
- n->addable = 7;
- }
-}
-
-/*
- * calculate addressability as follows
- * NAME ==> 10/11 name+value(SB/SP)
- * REGISTER ==> 12 register
- * CONST ==> 20 $value
- * *(20) ==> 21 value
- * &(10) ==> 13 $name+value(SB)
- * &(11) ==> 1 $name+value(SP)
- * (13) + (20) ==> 13 fold constants
- * (1) + (20) ==> 1 fold constants
- * *(13) ==> 10 back to name
- * *(1) ==> 11 back to name
- *
- * (20) * (X) ==> 7 multiplier in indexing
- * (X,7) + (13,1) ==> 8 adder in indexing (addresses)
- * (8) ==> &9(OINDEX) index, almost addressable
- * 100 extern register
- *
- * calculate complexity (number of registers)
- */
-void
-xcom(Node *n)
-{
- Node *l, *r;
- int g;
-
- if(n == Z)
- return;
- l = n->left;
- r = n->right;
- n->complex = 0;
- n->addable = 0;
- switch(n->op) {
- case OCONST:
- n->addable = 20;
- break;
-
- case ONAME:
- n->addable = 10;
- if(n->class == CPARAM || n->class == CAUTO)
- n->addable = 11;
- break;
-
- case OEXREG:
- n->addable = 0;
- break;
-
- case OREGISTER:
- n->addable = 12;
- break;
-
- case OINDREG:
- n->addable = 12;
- break;
-
- case OADDR:
- xcom(l);
- if(l->addable == 10)
- n->addable = 13;
- else
- if(l->addable == 11)
- n->addable = 1;
- break;
-
- case OADD:
- xcom(l);
- xcom(r);
- if(n->type->etype != TIND)
- break;
-
- switch(r->addable) {
- case 20:
- switch(l->addable) {
- case 1:
- case 13:
- commadd:
- l->type = n->type;
- *n = *l;
- l = new(0, Z, Z);
- *l = *(n->left);
- l->xoffset += r->vconst;
- n->left = l;
- r = n->right;
- goto brk;
- }
- break;
-
- case 1:
- case 13:
- case 10:
- case 11:
- /* l is the base, r is the index */
- if(l->addable != 20)
- n->addable = 8;
- break;
- }
- switch(l->addable) {
- case 20:
- switch(r->addable) {
- case 13:
- case 1:
- r = n->left;
- l = n->right;
- n->left = l;
- n->right = r;
- goto commadd;
- }
- break;
-
- case 13:
- case 1:
- case 10:
- case 11:
- /* r is the base, l is the index */
- if(r->addable != 20)
- n->addable = 8;
- break;
- }
- if(n->addable == 8 && !side(n)) {
- indx(n);
- l = new1(OINDEX, idx.basetree, idx.regtree);
- l->scale = idx.scale;
- l->addable = 9;
- l->complex = l->right->complex;
- l->type = l->left->type;
- n->op = OADDR;
- n->left = l;
- n->right = Z;
- n->addable = 8;
- break;
- }
- break;
-
- case OINDEX:
- xcom(l);
- xcom(r);
- n->addable = 9;
- break;
-
- case OIND:
- xcom(l);
- if(l->op == OADDR) {
- l = l->left;
- l->type = n->type;
- *n = *l;
- return;
- }
- switch(l->addable) {
- case 20:
- n->addable = 21;
- break;
- case 1:
- n->addable = 11;
- break;
- case 13:
- n->addable = 10;
- break;
- }
- break;
-
- case OASHL:
- xcom(l);
- xcom(r);
- indexshift(n);
- break;
-
- case OMUL:
- case OLMUL:
- xcom(l);
- xcom(r);
- g = vlog(l);
- if(g >= 0) {
- n->left = r;
- n->right = l;
- l = r;
- r = n->right;
- }
- g = vlog(r);
- if(g >= 0) {
- n->op = OASHL;
- r->vconst = g;
- r->type = types[TINT];
- indexshift(n);
- break;
- }
-commute(n);
- break;
-
- case OASLDIV:
- xcom(l);
- xcom(r);
- g = vlog(r);
- if(g >= 0) {
- n->op = OASLSHR;
- r->vconst = g;
- r->type = types[TINT];
- }
- break;
-
- case OLDIV:
- xcom(l);
- xcom(r);
- g = vlog(r);
- if(g >= 0) {
- n->op = OLSHR;
- r->vconst = g;
- r->type = types[TINT];
- indexshift(n);
- break;
- }
- break;
-
- case OASLMOD:
- xcom(l);
- xcom(r);
- g = vlog(r);
- if(g >= 0) {
- n->op = OASAND;
- r->vconst--;
- }
- break;
-
- case OLMOD:
- xcom(l);
- xcom(r);
- g = vlog(r);
- if(g >= 0) {
- n->op = OAND;
- r->vconst--;
- }
- break;
-
- case OASMUL:
- case OASLMUL:
- xcom(l);
- xcom(r);
- g = vlog(r);
- if(g >= 0) {
- n->op = OASASHL;
- r->vconst = g;
- }
- break;
-
- case OLSHR:
- case OASHR:
- xcom(l);
- xcom(r);
- indexshift(n);
- break;
-
- default:
- if(l != Z)
- xcom(l);
- if(r != Z)
- xcom(r);
- break;
- }
-brk:
- if(n->addable >= 10)
- return;
- if(l != Z)
- n->complex = l->complex;
- if(r != Z) {
- if(r->complex == n->complex)
- n->complex = r->complex+1;
- else
- if(r->complex > n->complex)
- n->complex = r->complex;
- }
- if(n->complex == 0)
- n->complex++;
-
- if(com64(n))
- return;
-
- switch(n->op) {
-
- case OFUNC:
- n->complex = FNX;
- break;
-
- case OLMOD:
- case OMOD:
- case OLMUL:
- case OLDIV:
- case OMUL:
- case ODIV:
- case OASLMUL:
- case OASLDIV:
- case OASLMOD:
- case OASMUL:
- case OASDIV:
- case OASMOD:
- if(r->complex >= l->complex) {
- n->complex = l->complex + 3;
- if(r->complex > n->complex)
- n->complex = r->complex;
- } else {
- n->complex = r->complex + 3;
- if(l->complex > n->complex)
- n->complex = l->complex;
- }
- break;
-
- case OLSHR:
- case OASHL:
- case OASHR:
- case OASLSHR:
- case OASASHL:
- case OASASHR:
- if(r->complex >= l->complex) {
- n->complex = l->complex + 2;
- if(r->complex > n->complex)
- n->complex = r->complex;
- } else {
- n->complex = r->complex + 2;
- if(l->complex > n->complex)
- n->complex = l->complex;
- }
- break;
-
- case OADD:
- case OXOR:
- case OAND:
- case OOR:
- /*
- * immediate operators, make const on right
- */
- if(l->op == OCONST) {
- n->left = r;
- n->right = l;
- }
- break;
-
- case OEQ:
- case ONE:
- case OLE:
- case OLT:
- case OGE:
- case OGT:
- case OHI:
- case OHS:
- case OLO:
- case OLS:
- /*
- * compare operators, make const on left
- */
- if(r->op == OCONST) {
- n->left = r;
- n->right = l;
- n->op = invrel[relindex(n->op)];
- }
- break;
- }
-}
-
-void
-indx(Node *n)
-{
- Node *l, *r;
-
- if(debug['x'])
- prtree(n, "indx");
-
- l = n->left;
- r = n->right;
- if(l->addable == 1 || l->addable == 13 || r->complex > l->complex) {
- n->right = l;
- n->left = r;
- l = r;
- r = n->right;
- }
- if(l->addable != 7) {
- idx.regtree = l;
- idx.scale = 1;
- } else
- if(l->right->addable == 20) {
- idx.regtree = l->left;
- idx.scale = 1 << l->right->vconst;
- } else
- if(l->left->addable == 20) {
- idx.regtree = l->right;
- idx.scale = 1 << l->left->vconst;
- } else
- diag(n, "bad index");
-
- idx.basetree = r;
- if(debug['x']) {
- print("scale = %d\n", idx.scale);
- prtree(idx.regtree, "index");
- prtree(idx.basetree, "base");
- }
-}
diff --git a/src/cmd/8c/swt.c b/src/cmd/8c/swt.c
deleted file mode 100644
index d960519e3..000000000
--- a/src/cmd/8c/swt.c
+++ /dev/null
@@ -1,341 +0,0 @@
-// Inferno utils/8c/swt.c
-// http://code.google.com/p/inferno-os/source/browse/utils/8c/swt.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-
-void
-swit1(C1 *q, int nc, int32 def, Node *n)
-{
- Node nreg;
-
- if(typev[n->type->etype]) {
- regsalloc(&nreg, n);
- nreg.type = types[TVLONG];
- cgen(n, &nreg);
- swit2(q, nc, def, &nreg);
- return;
- }
-
- regalloc(&nreg, n, Z);
- nreg.type = types[TLONG];
- cgen(n, &nreg);
- swit2(q, nc, def, &nreg);
- regfree(&nreg);
-}
-
-void
-swit2(C1 *q, int nc, int32 def, Node *n)
-{
- C1 *r;
- int i;
- Prog *sp;
-
- if(nc < 5) {
- for(i=0; i<nc; i++) {
- if(debug['W'])
- print("case = %.8ux\n", q->val);
- gopcode(OEQ, n->type, n, nodconst(q->val));
- patch(p, q->label);
- q++;
- }
- gbranch(OGOTO);
- patch(p, def);
- return;
- }
- i = nc / 2;
- r = q+i;
- if(debug['W'])
- print("case > %.8ux\n", r->val);
- gopcode(OGT, n->type, n, nodconst(r->val));
- sp = p;
- gbranch(OGOTO);
- p->as = AJEQ;
- patch(p, r->label);
- swit2(q, i, def, n);
-
- if(debug['W'])
- print("case < %.8ux\n", r->val);
- patch(sp, pc);
- swit2(r+1, nc-i-1, def, n);
-}
-
-void
-bitload(Node *b, Node *n1, Node *n2, Node *n3, Node *nn)
-{
- int sh;
- int32 v;
- Node *l;
-
- /*
- * n1 gets adjusted/masked value
- * n2 gets address of cell
- * n3 gets contents of cell
- */
- l = b->left;
- if(n2 != Z) {
- regalloc(n1, l, nn);
- reglcgen(n2, l, Z);
- regalloc(n3, l, Z);
- gmove(n2, n3);
- gmove(n3, n1);
- } else {
- regalloc(n1, l, nn);
- cgen(l, n1);
- }
- if(b->type->shift == 0 && typeu[b->type->etype]) {
- v = ~0 + (1L << b->type->nbits);
- gopcode(OAND, types[TLONG], nodconst(v), n1);
- } else {
- sh = 32 - b->type->shift - b->type->nbits;
- if(sh > 0)
- gopcode(OASHL, types[TLONG], nodconst(sh), n1);
- sh += b->type->shift;
- if(sh > 0)
- if(typeu[b->type->etype])
- gopcode(OLSHR, types[TLONG], nodconst(sh), n1);
- else
- gopcode(OASHR, types[TLONG], nodconst(sh), n1);
- }
-}
-
-void
-bitstore(Node *b, Node *n1, Node *n2, Node *n3, Node *nn)
-{
- int32 v;
- Node nod;
- int sh;
-
- regalloc(&nod, b->left, Z);
- v = ~0 + (1L << b->type->nbits);
- gopcode(OAND, types[TLONG], nodconst(v), n1);
- gmove(n1, &nod);
- if(nn != Z)
- gmove(n1, nn);
- sh = b->type->shift;
- if(sh > 0)
- gopcode(OASHL, types[TLONG], nodconst(sh), &nod);
- v <<= sh;
- gopcode(OAND, types[TLONG], nodconst(~v), n3);
- gopcode(OOR, types[TLONG], n3, &nod);
- gmove(&nod, n2);
-
- regfree(&nod);
- regfree(n1);
- regfree(n2);
- regfree(n3);
-}
-
-int32
-outstring(char *s, int32 n)
-{
- int32 r;
-
- if(suppress)
- return nstring;
- r = nstring;
- while(n) {
- string[mnstring] = *s++;
- mnstring++;
- nstring++;
- if(mnstring >= NSNAME) {
- gpseudo(ADATA, symstring, nodconst(0L));
- p->from.offset += nstring - NSNAME;
- p->from.scale = NSNAME;
- p->to.type = D_SCONST;
- memmove(p->to.u.sval, string, NSNAME);
- mnstring = 0;
- }
- n--;
- }
- return r;
-}
-
-void
-sextern(Sym *s, Node *a, int32 o, int32 w)
-{
- int32 e, lw;
-
- for(e=0; e<w; e+=NSNAME) {
- lw = NSNAME;
- if(w-e < lw)
- lw = w-e;
- gpseudo(ADATA, s, nodconst(0L));
- p->from.offset += o+e;
- p->from.scale = lw;
- p->to.type = D_SCONST;
- memmove(p->to.u.sval, a->cstring+e, lw);
- }
-}
-
-void
-gextern(Sym *s, Node *a, int32 o, int32 w)
-{
- if(a->op == OCONST && typev[a->type->etype]) {
- gpseudo(ADATA, s, lo64(a));
- p->from.offset += o;
- p->from.scale = 4;
- gpseudo(ADATA, s, hi64(a));
- p->from.offset += o + 4;
- p->from.scale = 4;
- return;
- }
- gpseudo(ADATA, s, a);
- p->from.offset += o;
- p->from.scale = w;
- switch(p->to.type) {
- default:
- p->to.index = p->to.type;
- p->to.type = D_ADDR;
- case D_CONST:
- case D_FCONST:
- case D_ADDR:
- break;
- }
-}
-
-void
-outcode(void)
-{
- int f;
- Biobuf b;
-
- f = open(outfile, OWRITE);
- if(f < 0) {
- diag(Z, "cannot open %s", outfile);
- return;
- }
- Binit(&b, f, OWRITE);
-
- Bprint(&b, "go object %s %s %s\n", getgoos(), getgoarch(), getgoversion());
- if(pragcgobuf.to > pragcgobuf.start) {
- Bprint(&b, "\n");
- Bprint(&b, "$$ // exports\n\n");
- Bprint(&b, "$$ // local types\n\n");
- Bprint(&b, "$$ // cgo\n");
- Bprint(&b, "%s", fmtstrflush(&pragcgobuf));
- Bprint(&b, "\n$$\n\n");
- }
- Bprint(&b, "!\n");
-
- writeobj(ctxt, &b);
- Bterm(&b);
- close(f);
- lastp = P;
-}
-
-int32
-align(int32 i, Type *t, int op, int32 *maxalign)
-{
- int32 o;
- Type *v;
- int w, packw;
-
- o = i;
- w = 1;
- packw = 0;
- switch(op) {
- default:
- diag(Z, "unknown align opcode %d", op);
- break;
-
- case Asu2: /* padding at end of a struct */
- w = *maxalign;
- if(w < 1)
- w = 1;
- if(packflg)
- packw = packflg;
- break;
-
- case Ael1: /* initial align of struct element */
- for(v=t; v->etype==TARRAY; v=v->link)
- ;
- if(v->etype == TSTRUCT || v->etype == TUNION)
- w = v->align;
- else {
- w = ewidth[v->etype];
- if(w == 8)
- w = 4;
- }
- if(w < 1 || w > SZ_LONG)
- fatal(Z, "align");
- if(packflg)
- packw = packflg;
- break;
-
- case Ael2: /* width of a struct element */
- o += t->width;
- break;
-
- case Aarg0: /* initial passbyptr argument in arg list */
- if(typesuv[t->etype]) {
- o = align(o, types[TIND], Aarg1, nil);
- o = align(o, types[TIND], Aarg2, nil);
- }
- break;
-
- case Aarg1: /* initial align of parameter */
- w = ewidth[t->etype];
- if(w <= 0 || w >= SZ_LONG) {
- w = SZ_LONG;
- break;
- }
- w = 1; /* little endian no adjustment */
- break;
-
- case Aarg2: /* width of a parameter */
- o += t->width;
- w = t->width;
- if(w > SZ_LONG)
- w = SZ_LONG;
- break;
-
- case Aaut3: /* total align of automatic */
- o = align(o, t, Ael1, nil);
- o = align(o, t, Ael2, nil);
- break;
- }
- if(packw != 0 && xround(o, w) != xround(o, packw))
- diag(Z, "#pragma pack changes offset of %T", t);
- o = xround(o, w);
- if(maxalign && *maxalign < w)
- *maxalign = w;
- if(debug['A'])
- print("align %s %d %T = %d\n", bnames[op], i, t, o);
- return o;
-}
-
-int32
-maxround(int32 max, int32 v)
-{
- v = xround(v, SZ_LONG);
- if(v > max)
- return v;
- return max;
-}
diff --git a/src/cmd/8c/txt.c b/src/cmd/8c/txt.c
deleted file mode 100644
index 7f87a0a0d..000000000
--- a/src/cmd/8c/txt.c
+++ /dev/null
@@ -1,1537 +0,0 @@
-// Inferno utils/8c/txt.c
-// http://code.google.com/p/inferno-os/source/browse/utils/8c/txt.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-
-
-int thechar = '8';
-char *thestring = "386";
-
-LinkArch *thelinkarch = &link386;
-
-void
-linkarchinit(void)
-{
-}
-
-void
-ginit(void)
-{
- int i;
- Type *t;
-
- exregoffset = 0;
- exfregoffset = 0;
- listinit();
- nstring = 0;
- mnstring = 0;
- nrathole = 0;
- pc = 0;
- breakpc = -1;
- continpc = -1;
- cases = C;
- lastp = P;
- tfield = types[TLONG];
-
- zprog.link = P;
- zprog.as = AGOK;
- zprog.from.type = D_NONE;
- zprog.from.index = D_NONE;
- zprog.from.scale = 0;
- zprog.to = zprog.from;
-
- regnode.op = OREGISTER;
- regnode.class = CEXREG;
- regnode.reg = REGTMP;
- regnode.complex = 0;
- regnode.addable = 11;
- regnode.type = types[TLONG];
-
- fregnode0 = regnode;
- fregnode0.reg = D_F0;
- fregnode0.type = types[TDOUBLE];
-
- fregnode1 = fregnode0;
- fregnode1.reg = D_F0+1;
-
- constnode.op = OCONST;
- constnode.class = CXXX;
- constnode.complex = 0;
- constnode.addable = 20;
- constnode.type = types[TLONG];
-
- fconstnode.op = OCONST;
- fconstnode.class = CXXX;
- fconstnode.complex = 0;
- fconstnode.addable = 20;
- fconstnode.type = types[TDOUBLE];
-
- nodsafe = new(ONAME, Z, Z);
- nodsafe->sym = slookup(".safe");
- nodsafe->type = types[TINT];
- nodsafe->etype = types[TINT]->etype;
- nodsafe->class = CAUTO;
- complex(nodsafe);
-
- t = typ(TARRAY, types[TCHAR]);
- symrathole = slookup(".rathole");
- symrathole->class = CGLOBL;
- symrathole->type = t;
-
- nodrat = new(ONAME, Z, Z);
- nodrat->sym = symrathole;
- nodrat->type = types[TIND];
- nodrat->etype = TVOID;
- nodrat->class = CGLOBL;
- complex(nodrat);
- nodrat->type = t;
-
- nodret = new(ONAME, Z, Z);
- nodret->sym = slookup(".ret");
- nodret->type = types[TIND];
- nodret->etype = TIND;
- nodret->class = CPARAM;
- nodret = new(OIND, nodret, Z);
- complex(nodret);
-
- com64init();
-
- for(i=0; i<nelem(reg); i++) {
- reg[i] = 1;
- if(i >= D_AX && i <= D_DI && i != D_SP)
- reg[i] = 0;
- }
-}
-
-void
-gclean(void)
-{
- int i;
- Sym *s;
-
- reg[D_SP]--;
- for(i=D_AX; i<=D_DI; i++)
- if(reg[i])
- diag(Z, "reg %R left allocated", i);
- while(mnstring)
- outstring("", 1L);
- symstring->type->width = nstring;
- symrathole->type->width = nrathole;
- for(i=0; i<NHASH; i++)
- for(s = hash[i]; s != S; s = s->link) {
- if(s->type == T)
- continue;
- if(s->type->width == 0)
- continue;
- if(s->class != CGLOBL && s->class != CSTATIC)
- continue;
- if(s->type == types[TENUM])
- continue;
- gpseudo(AGLOBL, s, nodconst(s->type->width));
- }
- nextpc();
- p->as = AEND;
- outcode();
-}
-
-void
-nextpc(void)
-{
- Plist *pl;
-
- p = alloc(sizeof(*p));
- *p = zprog;
- p->lineno = nearln;
- p->pc = pc;
- pc++;
- if(lastp == nil) {
- pl = linknewplist(ctxt);
- pl->firstpc = p;
- } else
- lastp->link = p;
- lastp = p;
-}
-
-void
-gargs(Node *n, Node *tn1, Node *tn2)
-{
- int32 regs;
- Node fnxargs[20], *fnxp;
-
- regs = cursafe;
-
- fnxp = fnxargs;
- garg1(n, tn1, tn2, 0, &fnxp); /* compile fns to temps */
-
- curarg = 0;
- fnxp = fnxargs;
- garg1(n, tn1, tn2, 1, &fnxp); /* compile normal args and temps */
-
- cursafe = regs;
-}
-
-int
-nareg(void)
-{
- int i, n;
-
- n = 0;
- for(i=D_AX; i<=D_DI; i++)
- if(reg[i] == 0)
- n++;
- return n;
-}
-
-void
-garg1(Node *n, Node *tn1, Node *tn2, int f, Node **fnxp)
-{
- Node nod;
-
- if(n == Z)
- return;
- if(n->op == OLIST) {
- garg1(n->left, tn1, tn2, f, fnxp);
- garg1(n->right, tn1, tn2, f, fnxp);
- return;
- }
- if(f == 0) {
- if(n->complex >= FNX) {
- regsalloc(*fnxp, n);
- nod = znode;
- nod.op = OAS;
- nod.left = *fnxp;
- nod.right = n;
- nod.type = n->type;
- cgen(&nod, Z);
- (*fnxp)++;
- }
- return;
- }
- if(typesu[n->type->etype] || typev[n->type->etype]) {
- regaalloc(tn2, n);
- if(n->complex >= FNX) {
- sugen(*fnxp, tn2, n->type->width);
- (*fnxp)++;
- } else
- sugen(n, tn2, n->type->width);
- return;
- }
- if(REGARG >= 0 && curarg == 0 && typeilp[n->type->etype]) {
- regaalloc1(tn1, n);
- if(n->complex >= FNX) {
- cgen(*fnxp, tn1);
- (*fnxp)++;
- } else
- cgen(n, tn1);
- return;
- }
- if(vconst(n) == 0) {
- regaalloc(tn2, n);
- gmove(n, tn2);
- return;
- }
- regalloc(tn1, n, Z);
- if(n->complex >= FNX) {
- cgen(*fnxp, tn1);
- (*fnxp)++;
- } else
- cgen(n, tn1);
- regaalloc(tn2, n);
- gmove(tn1, tn2);
- regfree(tn1);
-}
-
-Node*
-nodconst(int32 v)
-{
- constnode.vconst = v;
- return &constnode;
-}
-
-Node*
-nodfconst(double d)
-{
- fconstnode.fconst = d;
- return &fconstnode;
-}
-
-int
-isreg(Node *n, int r)
-{
-
- if(n->op == OREGISTER)
- if(n->reg == r)
- return 1;
- return 0;
-}
-
-int
-nodreg(Node *n, Node *nn, int r)
-{
-
- *n = regnode;
- n->reg = r;
- if(reg[r] == 0)
- return 0;
- if(nn != Z) {
- n->type = nn->type;
- n->lineno = nn->lineno;
- if(nn->op == OREGISTER)
- if(nn->reg == r)
- return 0;
- }
- return 1;
-}
-
-void
-regret(Node *n, Node *nn, Type *t, int mode)
-{
- int r;
-
- if(mode == 0 || hasdotdotdot(t) || nn->type->width == 0) {
- r = REGRET;
- if(typefd[nn->type->etype])
- r = FREGRET;
- nodreg(n, nn, r);
- reg[r]++;
- return;
- }
-
- if(mode == 1) {
- // fetch returned value after call.
- // already called gargs, so curarg is set.
- curarg = (curarg+3) & ~3;
- regaalloc(n, nn);
- return;
- }
-
- if(mode == 2) {
- // store value to be returned.
- // must compute arg offset.
- if(t->etype != TFUNC)
- fatal(Z, "bad regret func %T", t);
- *n = *nn;
- n->op = ONAME;
- n->class = CPARAM;
- n->sym = slookup(".retx");
- n->complex = 0;
- n->addable = 20;
- n->xoffset = argsize(0);
- return;
- }
-
- fatal(Z, "bad regret");
-}
-
-void
-regalloc(Node *n, Node *tn, Node *o)
-{
- int i;
-
- switch(tn->type->etype) {
- case TCHAR:
- case TUCHAR:
- case TSHORT:
- case TUSHORT:
- case TINT:
- case TUINT:
- case TLONG:
- case TULONG:
- case TIND:
- if(o != Z && o->op == OREGISTER) {
- i = o->reg;
- if(i >= D_AX && i <= D_DI)
- goto out;
- }
- for(i=D_AX; i<=D_DI; i++)
- if(reg[i] == 0)
- goto out;
- diag(tn, "out of fixed registers");
- goto err;
-
- case TFLOAT:
- case TDOUBLE:
- case TVLONG:
- i = D_F0;
- goto out;
- }
- diag(tn, "unknown type in regalloc: %T", tn->type);
-err:
- i = 0;
-out:
- if(i)
- reg[i]++;
- nodreg(n, tn, i);
-}
-
-void
-regialloc(Node *n, Node *tn, Node *o)
-{
- Node nod;
-
- nod = *tn;
- nod.type = types[TIND];
- regalloc(n, &nod, o);
-}
-
-void
-regfree(Node *n)
-{
- int i;
-
- i = 0;
- if(n->op != OREGISTER && n->op != OINDREG)
- goto err;
- i = n->reg;
- if(i < 0 || i >= nelem(reg))
- goto err;
- if(reg[i] <= 0)
- goto err;
- reg[i]--;
- return;
-err:
- diag(n, "error in regfree: %R", i);
-}
-
-void
-regsalloc(Node *n, Node *nn)
-{
- cursafe = align(cursafe, nn->type, Aaut3, nil);
- maxargsafe = maxround(maxargsafe, cursafe+curarg);
- *n = *nodsafe;
- n->xoffset = -(stkoff + cursafe);
- n->type = nn->type;
- n->etype = nn->type->etype;
- n->lineno = nn->lineno;
-}
-
-void
-regaalloc1(Node *n, Node *nn)
-{
- if(REGARG < 0) {
- fatal(n, "regaalloc1 and REGARG<0");
- return;
- }
- nodreg(n, nn, REGARG);
- reg[REGARG]++;
- curarg = align(curarg, nn->type, Aarg1, nil);
- curarg = align(curarg, nn->type, Aarg2, nil);
- maxargsafe = maxround(maxargsafe, cursafe+curarg);
-}
-
-void
-regaalloc(Node *n, Node *nn)
-{
- curarg = align(curarg, nn->type, Aarg1, nil);
- *n = *nn;
- n->op = OINDREG;
- n->reg = REGSP;
- n->xoffset = curarg;
- n->complex = 0;
- n->addable = 20;
- curarg = align(curarg, nn->type, Aarg2, nil);
- maxargsafe = maxround(maxargsafe, cursafe+curarg);
-}
-
-void
-regind(Node *n, Node *nn)
-{
-
- if(n->op != OREGISTER) {
- diag(n, "regind not OREGISTER");
- return;
- }
- n->op = OINDREG;
- n->type = nn->type;
-}
-
-void
-naddr(Node *n, Addr *a)
-{
- int32 v;
-
- a->type = D_NONE;
- if(n == Z)
- return;
- switch(n->op) {
- default:
- bad:
- diag(n, "bad in naddr: %O %D", n->op, a);
- break;
-
- case OREGISTER:
- a->type = n->reg;
- a->sym = nil;
- break;
-
- case OEXREG:
- a->type = D_INDIR + D_TLS;
- a->offset = n->reg - 1;
- break;
-
- case OIND:
- naddr(n->left, a);
- if(a->type >= D_AX && a->type <= D_DI)
- a->type += D_INDIR;
- else
- if(a->type == D_CONST)
- a->type = D_NONE+D_INDIR;
- else
- if(a->type == D_ADDR) {
- a->type = a->index;
- a->index = D_NONE;
- } else
- goto bad;
- break;
-
- case OINDEX:
- a->type = idx.ptr;
- if(n->left->op == OADDR || n->left->op == OCONST)
- naddr(n->left, a);
- if(a->type >= D_AX && a->type <= D_DI)
- a->type += D_INDIR;
- else
- if(a->type == D_CONST)
- a->type = D_NONE+D_INDIR;
- else
- if(a->type == D_ADDR) {
- a->type = a->index;
- a->index = D_NONE;
- } else
- goto bad;
- a->index = idx.reg;
- a->scale = n->scale;
- a->offset += n->xoffset;
- break;
-
- case OINDREG:
- a->type = n->reg+D_INDIR;
- a->sym = nil;
- a->offset = n->xoffset;
- break;
-
- case ONAME:
- a->etype = n->etype;
- a->type = D_STATIC;
- a->sym = linksym(n->sym);
- a->offset = n->xoffset;
- if(n->class == CSTATIC)
- break;
- if(n->class == CEXTERN || n->class == CGLOBL) {
- a->type = D_EXTERN;
- break;
- }
- if(n->class == CAUTO) {
- a->type = D_AUTO;
- break;
- }
- if(n->class == CPARAM) {
- a->type = D_PARAM;
- break;
- }
- goto bad;
-
- case OCONST:
- if(typefd[n->type->etype]) {
- a->type = D_FCONST;
- a->u.dval = n->fconst;
- break;
- }
- a->sym = nil;
- a->type = D_CONST;
- a->offset = n->vconst;
- break;
-
- case OADDR:
- naddr(n->left, a);
- if(a->type >= D_INDIR) {
- a->type -= D_INDIR;
- break;
- }
- if(a->type == D_EXTERN || a->type == D_STATIC ||
- a->type == D_AUTO || a->type == D_PARAM)
- if(a->index == D_NONE) {
- a->index = a->type;
- a->type = D_ADDR;
- break;
- }
- goto bad;
-
- case OADD:
- if(n->right->op == OCONST) {
- v = n->right->vconst;
- naddr(n->left, a);
- } else
- if(n->left->op == OCONST) {
- v = n->left->vconst;
- naddr(n->right, a);
- } else
- goto bad;
- a->offset += v;
- break;
-
- }
-}
-
-#define CASE(a,b) ((a<<8)|(b<<0))
-
-void
-gmove(Node *f, Node *t)
-{
- int ft, tt, a;
- Node nod, nod1;
- Prog *p1;
-
- ft = f->type->etype;
- tt = t->type->etype;
- if(debug['M'])
- print("gop: %O %O[%s],%O[%s]\n", OAS,
- f->op, tnames[ft], t->op, tnames[tt]);
- if(typefd[ft] && f->op == OCONST) {
- if(f->fconst == 0)
- gins(AFLDZ, Z, Z);
- else
- if(f->fconst == 1)
- gins(AFLD1, Z, Z);
- else
- gins(AFMOVD, f, &fregnode0);
- gmove(&fregnode0, t);
- return;
- }
-/*
- * load
- */
- if(f->op == ONAME || f->op == OINDREG ||
- f->op == OIND || f->op == OINDEX)
- switch(ft) {
- case TCHAR:
- a = AMOVBLSX;
- goto ld;
- case TUCHAR:
- a = AMOVBLZX;
- goto ld;
- case TSHORT:
- if(typefd[tt]) {
- gins(AFMOVW, f, &fregnode0);
- gmove(&fregnode0, t);
- return;
- }
- a = AMOVWLSX;
- goto ld;
- case TUSHORT:
- a = AMOVWLZX;
- goto ld;
- case TINT:
- case TUINT:
- case TLONG:
- case TULONG:
- case TIND:
- if(typefd[tt]) {
- gins(AFMOVL, f, &fregnode0);
- gmove(&fregnode0, t);
- return;
- }
- a = AMOVL;
-
- ld:
- regalloc(&nod, f, t);
- nod.type = types[TLONG];
- gins(a, f, &nod);
- gmove(&nod, t);
- regfree(&nod);
- return;
-
- case TFLOAT:
- gins(AFMOVF, f, t);
- return;
- case TDOUBLE:
- gins(AFMOVD, f, t);
- return;
- case TVLONG:
- gins(AFMOVV, f, t);
- return;
- }
-
-/*
- * store
- */
- if(t->op == ONAME || t->op == OINDREG ||
- t->op == OIND || t->op == OINDEX)
- switch(tt) {
- case TCHAR:
- case TUCHAR:
- a = AMOVB; goto st;
- case TSHORT:
- case TUSHORT:
- a = AMOVW; goto st;
- case TINT:
- case TUINT:
- case TLONG:
- case TULONG:
- case TIND:
- a = AMOVL; goto st;
-
- st:
- if(f->op == OCONST) {
- gins(a, f, t);
- return;
- }
- regalloc(&nod, t, f);
- gmove(f, &nod);
- gins(a, &nod, t);
- regfree(&nod);
- return;
-
- case TFLOAT:
- gins(AFMOVFP, f, t);
- return;
- case TDOUBLE:
- gins(AFMOVDP, f, t);
- return;
- case TVLONG:
- gins(AFMOVVP, f, t);
- return;
- }
-
-/*
- * convert
- */
- switch(CASE(ft,tt)) {
- default:
-/*
- * integer to integer
- ********
- a = AGOK; break;
-
- case CASE( TCHAR, TCHAR):
- case CASE( TUCHAR, TCHAR):
- case CASE( TSHORT, TCHAR):
- case CASE( TUSHORT,TCHAR):
- case CASE( TINT, TCHAR):
- case CASE( TUINT, TCHAR):
- case CASE( TLONG, TCHAR):
- case CASE( TULONG, TCHAR):
- case CASE( TIND, TCHAR):
-
- case CASE( TCHAR, TUCHAR):
- case CASE( TUCHAR, TUCHAR):
- case CASE( TSHORT, TUCHAR):
- case CASE( TUSHORT,TUCHAR):
- case CASE( TINT, TUCHAR):
- case CASE( TUINT, TUCHAR):
- case CASE( TLONG, TUCHAR):
- case CASE( TULONG, TUCHAR):
- case CASE( TIND, TUCHAR):
-
- case CASE( TSHORT, TSHORT):
- case CASE( TUSHORT,TSHORT):
- case CASE( TINT, TSHORT):
- case CASE( TUINT, TSHORT):
- case CASE( TLONG, TSHORT):
- case CASE( TULONG, TSHORT):
- case CASE( TIND, TSHORT):
-
- case CASE( TSHORT, TUSHORT):
- case CASE( TUSHORT,TUSHORT):
- case CASE( TINT, TUSHORT):
- case CASE( TUINT, TUSHORT):
- case CASE( TLONG, TUSHORT):
- case CASE( TULONG, TUSHORT):
- case CASE( TIND, TUSHORT):
-
- case CASE( TINT, TINT):
- case CASE( TUINT, TINT):
- case CASE( TLONG, TINT):
- case CASE( TULONG, TINT):
- case CASE( TIND, TINT):
-
- case CASE( TINT, TUINT):
- case CASE( TUINT, TUINT):
- case CASE( TLONG, TUINT):
- case CASE( TULONG, TUINT):
- case CASE( TIND, TUINT):
-
- case CASE( TINT, TLONG):
- case CASE( TUINT, TLONG):
- case CASE( TLONG, TLONG):
- case CASE( TULONG, TLONG):
- case CASE( TIND, TLONG):
-
- case CASE( TINT, TULONG):
- case CASE( TUINT, TULONG):
- case CASE( TLONG, TULONG):
- case CASE( TULONG, TULONG):
- case CASE( TIND, TULONG):
-
- case CASE( TINT, TIND):
- case CASE( TUINT, TIND):
- case CASE( TLONG, TIND):
- case CASE( TULONG, TIND):
- case CASE( TIND, TIND):
- *****/
- a = AMOVL;
- break;
-
- case CASE( TSHORT, TINT):
- case CASE( TSHORT, TUINT):
- case CASE( TSHORT, TLONG):
- case CASE( TSHORT, TULONG):
- case CASE( TSHORT, TIND):
- a = AMOVWLSX;
- if(f->op == OCONST) {
- f->vconst &= 0xffff;
- if(f->vconst & 0x8000)
- f->vconst |= 0xffff0000;
- a = AMOVL;
- }
- break;
-
- case CASE( TUSHORT,TINT):
- case CASE( TUSHORT,TUINT):
- case CASE( TUSHORT,TLONG):
- case CASE( TUSHORT,TULONG):
- case CASE( TUSHORT,TIND):
- a = AMOVWLZX;
- if(f->op == OCONST) {
- f->vconst &= 0xffff;
- a = AMOVL;
- }
- break;
-
- case CASE( TCHAR, TSHORT):
- case CASE( TCHAR, TUSHORT):
- case CASE( TCHAR, TINT):
- case CASE( TCHAR, TUINT):
- case CASE( TCHAR, TLONG):
- case CASE( TCHAR, TULONG):
- case CASE( TCHAR, TIND):
- a = AMOVBLSX;
- if(f->op == OCONST) {
- f->vconst &= 0xff;
- if(f->vconst & 0x80)
- f->vconst |= 0xffffff00;
- a = AMOVL;
- }
- break;
-
- case CASE( TUCHAR, TSHORT):
- case CASE( TUCHAR, TUSHORT):
- case CASE( TUCHAR, TINT):
- case CASE( TUCHAR, TUINT):
- case CASE( TUCHAR, TLONG):
- case CASE( TUCHAR, TULONG):
- case CASE( TUCHAR, TIND):
- a = AMOVBLZX;
- if(f->op == OCONST) {
- f->vconst &= 0xff;
- a = AMOVL;
- }
- break;
-
-/*
- * float to fix
- */
- case CASE( TFLOAT, TCHAR):
- case CASE( TFLOAT, TUCHAR):
- case CASE( TFLOAT, TSHORT):
- case CASE( TFLOAT, TUSHORT):
- case CASE( TFLOAT, TINT):
- case CASE( TFLOAT, TUINT):
- case CASE( TFLOAT, TLONG):
- case CASE( TFLOAT, TULONG):
- case CASE( TFLOAT, TIND):
-
- case CASE( TDOUBLE,TCHAR):
- case CASE( TDOUBLE,TUCHAR):
- case CASE( TDOUBLE,TSHORT):
- case CASE( TDOUBLE,TUSHORT):
- case CASE( TDOUBLE,TINT):
- case CASE( TDOUBLE,TUINT):
- case CASE( TDOUBLE,TLONG):
- case CASE( TDOUBLE,TULONG):
- case CASE( TDOUBLE,TIND):
-
- case CASE( TVLONG, TCHAR):
- case CASE( TVLONG, TUCHAR):
- case CASE( TVLONG, TSHORT):
- case CASE( TVLONG, TUSHORT):
- case CASE( TVLONG, TINT):
- case CASE( TVLONG, TUINT):
- case CASE( TVLONG, TLONG):
- case CASE( TVLONG, TULONG):
- case CASE( TVLONG, TIND):
- if(fproundflg) {
- regsalloc(&nod, &regnode);
- gins(AFMOVLP, f, &nod);
- gmove(&nod, t);
- return;
- }
- regsalloc(&nod, &regnode);
- regsalloc(&nod1, &regnode);
- gins(AFSTCW, Z, &nod1);
- nod1.xoffset += 2;
- gins(AMOVW, nodconst(0xf7f), &nod1);
- gins(AFLDCW, &nod1, Z);
- gins(AFMOVLP, f, &nod);
- nod1.xoffset -= 2;
- gins(AFLDCW, &nod1, Z);
- gmove(&nod, t);
- return;
-
-/*
- * ulong to float
- */
- case CASE( TULONG, TDOUBLE):
- case CASE( TULONG, TVLONG):
- case CASE( TULONG, TFLOAT):
- case CASE( TUINT, TDOUBLE):
- case CASE( TUINT, TVLONG):
- case CASE( TUINT, TFLOAT):
- regalloc(&nod, f, f);
- gmove(f, &nod);
- regsalloc(&nod1, &regnode);
- gmove(&nod, &nod1);
- gins(AFMOVL, &nod1, &fregnode0);
- gins(ACMPL, &nod, nodconst(0));
- gins(AJGE, Z, Z);
- p1 = p;
- gins(AFADDD, nodfconst(4294967296.), &fregnode0);
- patch(p1, pc);
- regfree(&nod);
- return;
-
-/*
- * fix to float
- */
- case CASE( TCHAR, TFLOAT):
- case CASE( TUCHAR, TFLOAT):
- case CASE( TSHORT, TFLOAT):
- case CASE( TUSHORT,TFLOAT):
- case CASE( TINT, TFLOAT):
- case CASE( TLONG, TFLOAT):
- case CASE( TIND, TFLOAT):
-
- case CASE( TCHAR, TDOUBLE):
- case CASE( TUCHAR, TDOUBLE):
- case CASE( TSHORT, TDOUBLE):
- case CASE( TUSHORT,TDOUBLE):
- case CASE( TINT, TDOUBLE):
- case CASE( TLONG, TDOUBLE):
- case CASE( TIND, TDOUBLE):
-
- case CASE( TCHAR, TVLONG):
- case CASE( TUCHAR, TVLONG):
- case CASE( TSHORT, TVLONG):
- case CASE( TUSHORT,TVLONG):
- case CASE( TINT, TVLONG):
- case CASE( TLONG, TVLONG):
- case CASE( TIND, TVLONG):
- regsalloc(&nod, &regnode);
- gmove(f, &nod);
- gins(AFMOVL, &nod, &fregnode0);
- return;
-
-/*
- * float to float
- */
- case CASE( TFLOAT, TFLOAT):
- case CASE( TDOUBLE,TFLOAT):
- case CASE( TVLONG, TFLOAT):
-
- case CASE( TFLOAT, TDOUBLE):
- case CASE( TDOUBLE,TDOUBLE):
- case CASE( TVLONG, TDOUBLE):
-
- case CASE( TFLOAT, TVLONG):
- case CASE( TDOUBLE,TVLONG):
- case CASE( TVLONG, TVLONG):
- a = AFMOVD; break;
- }
- if(a == AMOVL || a == AFMOVD)
- if(samaddr(f, t))
- return;
- gins(a, f, t);
-}
-
-void
-doindex(Node *n)
-{
- Node nod, nod1;
- int32 v;
-
-if(debug['Y'])
-prtree(n, "index");
-
-if(n->left->complex >= FNX)
-print("botch in doindex\n");
-
- regalloc(&nod, &regnode, Z);
- v = constnode.vconst;
- cgen(n->right, &nod);
- idx.ptr = D_NONE;
- if(n->left->op == OCONST)
- idx.ptr = D_CONST;
- else if(n->left->op == OREGISTER)
- idx.ptr = n->left->reg;
- else if(n->left->op != OADDR) {
- reg[D_BP]++; // can't be used as a base
- regalloc(&nod1, &regnode, Z);
- cgen(n->left, &nod1);
- idx.ptr = nod1.reg;
- regfree(&nod1);
- reg[D_BP]--;
- }
- idx.reg = nod.reg;
- regfree(&nod);
- constnode.vconst = v;
-}
-
-void
-gins(int a, Node *f, Node *t)
-{
-
- if(f != Z && f->op == OINDEX)
- doindex(f);
- if(t != Z && t->op == OINDEX)
- doindex(t);
- nextpc();
- p->as = a;
- if(f != Z)
- naddr(f, &p->from);
- if(t != Z)
- naddr(t, &p->to);
- if(debug['g'])
- print("%P\n", p);
-}
-
-void
-fgopcode(int o, Node *f, Node *t, int pop, int rev)
-{
- int a, et;
- Node nod;
-
- et = TLONG;
- if(f != Z && f->type != T)
- et = f->type->etype;
- if(!typefd[et]) {
- diag(f, "fop: integer %O", o);
- return;
- }
- if(debug['M']) {
- if(t != Z && t->type != T)
- print("gop: %O %O-%s Z\n", o, f->op, tnames[et]);
- else
- print("gop: %O %O-%s %O-%s\n", o,
- f->op, tnames[et], t->op, tnames[t->type->etype]);
- }
- a = AGOK;
- switch(o) {
-
- case OASADD:
- case OADD:
- if(et == TFLOAT)
- a = AFADDF;
- else
- if(et == TDOUBLE || et == TVLONG) {
- a = AFADDD;
- if(pop)
- a = AFADDDP;
- }
- break;
-
- case OASSUB:
- case OSUB:
- if(et == TFLOAT) {
- a = AFSUBF;
- if(rev)
- a = AFSUBRF;
- } else
- if(et == TDOUBLE || et == TVLONG) {
- a = AFSUBD;
- if(pop)
- a = AFSUBDP;
- if(rev) {
- a = AFSUBRD;
- if(pop)
- a = AFSUBRDP;
- }
- }
- break;
-
- case OASMUL:
- case OMUL:
- if(et == TFLOAT)
- a = AFMULF;
- else
- if(et == TDOUBLE || et == TVLONG) {
- a = AFMULD;
- if(pop)
- a = AFMULDP;
- }
- break;
-
- case OASMOD:
- case OMOD:
- case OASDIV:
- case ODIV:
- if(et == TFLOAT) {
- a = AFDIVF;
- if(rev)
- a = AFDIVRF;
- } else
- if(et == TDOUBLE || et == TVLONG) {
- a = AFDIVD;
- if(pop)
- a = AFDIVDP;
- if(rev) {
- a = AFDIVRD;
- if(pop)
- a = AFDIVRDP;
- }
- }
- break;
-
- case OEQ:
- case ONE:
- case OLT:
- case OLE:
- case OGE:
- case OGT:
- pop += rev;
- if(et == TFLOAT) {
- a = AFCOMF;
- if(pop) {
- a = AFCOMFP;
- if(pop > 1)
- a = AGOK;
- }
- } else
- if(et == TDOUBLE || et == TVLONG) {
- a = AFCOMF;
- if(pop) {
- a = AFCOMDP;
- if(pop > 1)
- a = AFCOMDPP;
- }
- }
- gins(a, f, t);
- regalloc(&nod, &regnode, Z);
- if(nod.reg != D_AX) {
- regfree(&nod);
- nod.reg = D_AX;
- gins(APUSHL, &nod, Z);
- gins(AWAIT, Z, Z);
- gins(AFSTSW, Z, &nod);
- gins(ASAHF, Z, Z);
- gins(APOPL, Z, &nod);
- } else {
- gins(AWAIT, Z, Z);
- gins(AFSTSW, Z, &nod);
- gins(ASAHF, Z, Z);
- regfree(&nod);
- }
- switch(o) {
- case OEQ: a = AJEQ; break;
- case ONE: a = AJNE; break;
- case OLT: a = AJCS; break;
- case OLE: a = AJLS; break;
- case OGE: a = AJCC; break;
- case OGT: a = AJHI; break;
- }
- gins(a, Z, Z);
- return;
- }
- if(a == AGOK)
- diag(Z, "bad in gopcode %O", o);
- gins(a, f, t);
-}
-
-void
-gopcode(int o, Type *ty, Node *f, Node *t)
-{
- int a, et;
-
- et = TLONG;
- if(ty != T)
- et = ty->etype;
- if(typefd[et] && o != OADDR && o != OFUNC) {
- diag(f, "gop: float %O", o);
- return;
- }
- if(debug['M']) {
- if(f != Z && f->type != T)
- print("gop: %O %O[%s],", o, f->op, tnames[et]);
- else
- print("gop: %O Z,", o);
- if(t != Z && t->type != T)
- print("%O[%s]\n", t->op, tnames[t->type->etype]);
- else
- print("Z\n");
- }
- a = AGOK;
- switch(o) {
- case OCOM:
- a = ANOTL;
- if(et == TCHAR || et == TUCHAR)
- a = ANOTB;
- if(et == TSHORT || et == TUSHORT)
- a = ANOTW;
- break;
-
- case ONEG:
- a = ANEGL;
- if(et == TCHAR || et == TUCHAR)
- a = ANEGB;
- if(et == TSHORT || et == TUSHORT)
- a = ANEGW;
- break;
-
- case OADDR:
- a = ALEAL;
- break;
-
- case OASADD:
- case OADD:
- a = AADDL;
- if(et == TCHAR || et == TUCHAR)
- a = AADDB;
- if(et == TSHORT || et == TUSHORT)
- a = AADDW;
- break;
-
- case OASSUB:
- case OSUB:
- a = ASUBL;
- if(et == TCHAR || et == TUCHAR)
- a = ASUBB;
- if(et == TSHORT || et == TUSHORT)
- a = ASUBW;
- break;
-
- case OASOR:
- case OOR:
- a = AORL;
- if(et == TCHAR || et == TUCHAR)
- a = AORB;
- if(et == TSHORT || et == TUSHORT)
- a = AORW;
- break;
-
- case OASAND:
- case OAND:
- a = AANDL;
- if(et == TCHAR || et == TUCHAR)
- a = AANDB;
- if(et == TSHORT || et == TUSHORT)
- a = AANDW;
- break;
-
- case OASXOR:
- case OXOR:
- a = AXORL;
- if(et == TCHAR || et == TUCHAR)
- a = AXORB;
- if(et == TSHORT || et == TUSHORT)
- a = AXORW;
- break;
-
- case OASLSHR:
- case OLSHR:
- a = ASHRL;
- if(et == TCHAR || et == TUCHAR)
- a = ASHRB;
- if(et == TSHORT || et == TUSHORT)
- a = ASHRW;
- break;
-
- case OASASHR:
- case OASHR:
- a = ASARL;
- if(et == TCHAR || et == TUCHAR)
- a = ASARB;
- if(et == TSHORT || et == TUSHORT)
- a = ASARW;
- break;
-
- case OASASHL:
- case OASHL:
- a = ASALL;
- if(et == TCHAR || et == TUCHAR)
- a = ASALB;
- if(et == TSHORT || et == TUSHORT)
- a = ASALW;
- break;
-
- case OROTL:
- a = AROLL;
- if(et == TCHAR || et == TUCHAR)
- a = AROLB;
- if(et == TSHORT || et == TUSHORT)
- a = AROLW;
- break;
-
- case OFUNC:
- a = ACALL;
- break;
-
- case OASMUL:
- case OMUL:
- if(f->op == OREGISTER && t != Z && isreg(t, D_AX) && reg[D_DX] == 0)
- t = Z;
- a = AIMULL;
- break;
-
- case OASMOD:
- case OMOD:
- case OASDIV:
- case ODIV:
- a = AIDIVL;
- break;
-
- case OASLMUL:
- case OLMUL:
- a = AMULL;
- break;
-
- case OASLMOD:
- case OLMOD:
- case OASLDIV:
- case OLDIV:
- a = ADIVL;
- break;
-
- case OEQ:
- case ONE:
- case OLT:
- case OLE:
- case OGE:
- case OGT:
- case OLO:
- case OLS:
- case OHS:
- case OHI:
- a = ACMPL;
- if(et == TCHAR || et == TUCHAR)
- a = ACMPB;
- if(et == TSHORT || et == TUSHORT)
- a = ACMPW;
- gins(a, f, t);
- switch(o) {
- case OEQ: a = AJEQ; break;
- case ONE: a = AJNE; break;
- case OLT: a = AJLT; break;
- case OLE: a = AJLE; break;
- case OGE: a = AJGE; break;
- case OGT: a = AJGT; break;
- case OLO: a = AJCS; break;
- case OLS: a = AJLS; break;
- case OHS: a = AJCC; break;
- case OHI: a = AJHI; break;
- }
- gins(a, Z, Z);
- return;
- }
- if(a == AGOK)
- diag(Z, "bad in gopcode %O", o);
- gins(a, f, t);
-}
-
-int
-samaddr(Node *f, Node *t)
-{
-
- if(f->op != t->op)
- return 0;
- switch(f->op) {
-
- case OREGISTER:
- if(f->reg != t->reg)
- break;
- return 1;
- }
- return 0;
-}
-
-void
-gbranch(int o)
-{
- int a;
-
- a = AGOK;
- switch(o) {
- case ORETURN:
- a = ARET;
- break;
- case OGOTO:
- a = AJMP;
- break;
- }
- nextpc();
- if(a == AGOK) {
- diag(Z, "bad in gbranch %O", o);
- nextpc();
- }
- p->as = a;
-}
-
-void
-patch(Prog *op, int32 pc)
-{
- op->to.offset = pc;
- op->to.type = D_BRANCH;
- op->to.u.branch = nil;
- op->pcond = nil;
-}
-
-void
-gpseudo(int a, Sym *s, Node *n)
-{
-
- nextpc();
- p->as = a;
- p->from.type = D_EXTERN;
- p->from.sym = linksym(s);
-
- switch(a) {
- case ATEXT:
- p->from.scale = textflag;
- textflag = 0;
- break;
- case AGLOBL:
- p->from.scale = s->dataflag;
- break;
- }
-
- if(s->class == CSTATIC)
- p->from.type = D_STATIC;
- naddr(n, &p->to);
- if(a == ADATA || a == AGLOBL)
- pc--;
-}
-
-void
-gpcdata(int index, int value)
-{
- Node n1;
-
- n1 = *nodconst(index);
- gins(APCDATA, &n1, nodconst(value));
-}
-
-void
-gprefetch(Node *n)
-{
- Node n1;
-
- if(strcmp(getgo386(), "sse2") != 0) // assume no prefetch on old machines
- return;
-
- regalloc(&n1, n, Z);
- gmove(n, &n1);
- n1.op = OINDREG;
- gins(APREFETCHNTA, &n1, Z);
- regfree(&n1);
-}
-
-int
-sconst(Node *n)
-{
- int32 v;
-
- if(n->op == OCONST && !typefd[n->type->etype]) {
- v = n->vconst;
- if(v >= -32766L && v < 32766L)
- return 1;
- }
- return 0;
-}
-
-int32
-exreg(Type *t)
-{
- int32 o;
-
- if(typechlp[t->etype]){
- if(exregoffset >= 32)
- return 0;
- o = exregoffset;
- exregoffset += 4;
- return o+1; // +1 to avoid 0 == failure; naddr case OEXREG will -1.
- }
-
- return 0;
-}
-
-schar ewidth[NTYPE] =
-{
- -1, /*[TXXX]*/
- SZ_CHAR, /*[TCHAR]*/
- SZ_CHAR, /*[TUCHAR]*/
- SZ_SHORT, /*[TSHORT]*/
- SZ_SHORT, /*[TUSHORT]*/
- SZ_INT, /*[TINT]*/
- SZ_INT, /*[TUINT]*/
- SZ_LONG, /*[TLONG]*/
- SZ_LONG, /*[TULONG]*/
- SZ_VLONG, /*[TVLONG]*/
- SZ_VLONG, /*[TUVLONG]*/
- SZ_FLOAT, /*[TFLOAT]*/
- SZ_DOUBLE, /*[TDOUBLE]*/
- SZ_IND, /*[TIND]*/
- 0, /*[TFUNC]*/
- -1, /*[TARRAY]*/
- 0, /*[TVOID]*/
- -1, /*[TSTRUCT]*/
- -1, /*[TUNION]*/
- SZ_INT, /*[TENUM]*/
-};
-int32 ncast[NTYPE] =
-{
- 0, /*[TXXX]*/
- BCHAR|BUCHAR, /*[TCHAR]*/
- BCHAR|BUCHAR, /*[TUCHAR]*/
- BSHORT|BUSHORT, /*[TSHORT]*/
- BSHORT|BUSHORT, /*[TUSHORT]*/
- BINT|BUINT|BLONG|BULONG|BIND, /*[TINT]*/
- BINT|BUINT|BLONG|BULONG|BIND, /*[TUINT]*/
- BINT|BUINT|BLONG|BULONG|BIND, /*[TLONG]*/
- BINT|BUINT|BLONG|BULONG|BIND, /*[TULONG]*/
- BVLONG|BUVLONG, /*[TVLONG]*/
- BVLONG|BUVLONG, /*[TUVLONG]*/
- BFLOAT, /*[TFLOAT]*/
- BDOUBLE, /*[TDOUBLE]*/
- BLONG|BULONG|BIND, /*[TIND]*/
- 0, /*[TFUNC]*/
- 0, /*[TARRAY]*/
- 0, /*[TVOID]*/
- BSTRUCT, /*[TSTRUCT]*/
- BUNION, /*[TUNION]*/
- 0, /*[TENUM]*/
-};
diff --git a/src/cmd/8g/reg.c b/src/cmd/8g/reg.c
index 45aea2c33..13beaf941 100644
--- a/src/cmd/8g/reg.c
+++ b/src/cmd/8g/reg.c
@@ -936,7 +936,7 @@ paint1(Reg *r, int bn)
Reg *r1;
Prog *p;
int z;
- uint64 bb;
+ uint64 bb, rbz;
z = bn/64;
bb = 1LL<<(bn%64);
@@ -955,7 +955,8 @@ paint1(Reg *r, int bn)
r = r1;
}
- if(LOAD(r) & ~(r->set.b[z]&~(r->use1.b[z]|r->use2.b[z])) & bb) {
+ rbz = ~(r->set.b[z]&~(r->use1.b[z]|r->use2.b[z]));
+ if(LOAD(r) & rbz & bb) {
change -= CLOAD * r->f.loop;
}
for(;;) {
@@ -1066,7 +1067,7 @@ paint3(Reg *r, int bn, uint32 rb, int rn)
Reg *r1;
Prog *p;
int z;
- uint64 bb;
+ uint64 bb, rbz;
z = bn/64;
bb = 1LL << (bn%64);
@@ -1085,7 +1086,8 @@ paint3(Reg *r, int bn, uint32 rb, int rn)
r = r1;
}
- if(LOAD(r) & ~(r->set.b[z] & ~(r->use1.b[z]|r->use2.b[z])) & bb)
+ rbz = ~(r->set.b[z] & ~(r->use1.b[z]|r->use2.b[z]));
+ if(LOAD(r) & rbz & bb)
addmove(r, bn, rn, 0);
for(;;) {
r->act.b[z] |= bb;
diff --git a/src/cmd/9a/lex.c b/src/cmd/9a/lex.c
index 26f21f743..e2945ef89 100644
--- a/src/cmd/9a/lex.c
+++ b/src/cmd/9a/lex.c
@@ -250,7 +250,7 @@ struct
"R27", LREG, 27,
"R28", LREG, 28,
"R29", LREG, 29,
- "R30", LREG, 30,
+ "g", LREG, 30, // avoid unintentionally clobbering g using R30
"R31", LREG, 31,
"F", LF, 0,
@@ -488,6 +488,7 @@ struct
"SYSCALL", LNOP, ASYSCALL,
"UNDEF", LNOP, AUNDEF,
+ "RET", LRETRN, ARETURN,
"RETURN", LRETRN, ARETURN,
"RFI", LRETRN, ARFI,
"RFCI", LRETRN, ARFCI,
diff --git a/src/cmd/9c/Makefile b/src/cmd/9c/Makefile
deleted file mode 100644
index 3f528d751..000000000
--- a/src/cmd/9c/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-# Copyright 2012 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../Make.dist
diff --git a/src/cmd/9c/Notes b/src/cmd/9c/Notes
deleted file mode 100644
index 92dd9deb3..000000000
--- a/src/cmd/9c/Notes
+++ /dev/null
@@ -1,14 +0,0 @@
-- effect of register expansion on 32-bit shifts and masks etc
-9c
-- multab
-- floating-point conversions
-- conversions of constants
-- nodtype for loads
-- sign-extension instruction (32-64) when in register?
-- double indexing
-- SLW (eg, in cat)
-- scheduling
-
-9l
-- D_QCONST, DWORD
-- maskgen
diff --git a/src/cmd/9c/cgen.c b/src/cmd/9c/cgen.c
deleted file mode 100644
index bd1f7b28f..000000000
--- a/src/cmd/9c/cgen.c
+++ /dev/null
@@ -1,1147 +0,0 @@
-// cmd/9c/cgen.c from Vita Nuova.
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-#include "../../runtime/funcdata.h"
-
-void
-cgen(Node *n, Node *nn)
-{
- Node *l, *r;
- Prog *p1;
- Node nod, nod1, nod2, nod3, nod4;
- int o;
- int32 v, curs;
-
- if(debug['g']) {
- prtree(nn, "cgen lhs");
- prtree(n, "cgen");
- }
- if(n == Z || n->type == T)
- return;
- if(typesu[n->type->etype] && (n->op != OFUNC || nn != Z)) {
- sugen(n, nn, n->type->width);
- return;
- }
- l = n->left;
- r = n->right;
- o = n->op;
- if(n->addable >= INDEXED) {
- if(nn == Z) {
- switch(o) {
- default:
- nullwarn(Z, Z);
- break;
- case OINDEX:
- nullwarn(l, r);
- break;
- }
- return;
- }
- gmove(n, nn);
- return;
- }
- curs = cursafe;
-
- if(n->complex >= FNX)
- if(l->complex >= FNX)
- if(r != Z && r->complex >= FNX)
- switch(o) {
- default:
- regret(&nod, r, 0, 0);
- cgen(r, &nod);
-
- regsalloc(&nod1, r);
- gopcode(OAS, &nod, Z, &nod1);
-
- regfree(&nod);
- nod = *n;
- nod.right = &nod1;
- cgen(&nod, nn);
- return;
-
- case OFUNC:
- case OCOMMA:
- case OANDAND:
- case OOROR:
- case OCOND:
- case ODOT:
- break;
- }
-
- switch(o) {
- default:
- diag(n, "unknown op in cgen: %O", o);
- break;
-
- case OAS:
- if(l->op == OBIT)
- goto bitas;
- if(l->addable >= INDEXED) {
- if(nn != Z || r->addable < INDEXED) {
- regalloc(&nod, r, nn);
- cgen(r, &nod);
- gmove(&nod, l);
- regfree(&nod);
- } else
- gmove(r, l);
- break;
- }
- if(l->complex >= r->complex) {
- reglcgen(&nod1, l, Z);
- if(r->addable >= INDEXED) {
- gmove(r, &nod1);
- if(nn != Z)
- gmove(r, nn);
- regfree(&nod1);
- break;
- }
- regalloc(&nod, r, nn);
- cgen(r, &nod);
- } else {
- regalloc(&nod, r, nn);
- cgen(r, &nod);
- reglcgen(&nod1, l, Z);
- }
- gmove(&nod, &nod1);
- regfree(&nod);
- regfree(&nod1);
- break;
-
- bitas:
- n = l->left;
- regalloc(&nod, r, nn);
- if(l->complex >= r->complex) {
- reglcgen(&nod1, n, Z);
- cgen(r, &nod);
- } else {
- cgen(r, &nod);
- reglcgen(&nod1, n, Z);
- }
- regalloc(&nod2, n, Z);
- gopcode(OAS, &nod1, Z, &nod2);
- bitstore(l, &nod, &nod1, &nod2, nn);
- break;
-
- case OBIT:
- if(nn == Z) {
- nullwarn(l, Z);
- break;
- }
- bitload(n, &nod, Z, Z, nn);
- gopcode(OAS, &nod, Z, nn);
- regfree(&nod);
- break;
-
- case OXOR:
- if(nn != Z)
- if(r->op == OCONST && r->vconst == -1){
- cgen(l, nn);
- gopcode(OCOM, nn, Z, nn);
- break;
- }
-
- case OADD:
- case OSUB:
- case OAND:
- case OOR:
- case OLSHR:
- case OASHL:
- case OASHR:
- /*
- * immediate operands
- */
- if(nn != Z &&
- r->op == OCONST &&
- !typefd[n->type->etype] &&
- immconst(r)) {
- cgen(l, nn);
- if(r->vconst == 0)
- if(o != OAND)
- break;
- if(nn != Z)
- gopcode(o, r, Z, nn);
- break;
- }
-
- case OMUL:
- case OLMUL:
- case OLDIV:
- case OLMOD:
- case ODIV:
- case OMOD:
- if(nn == Z) {
- nullwarn(l, r);
- break;
- }
- if(o == OMUL || o == OLMUL) {
- if(mulcon(n, nn))
- break;
- if(debug['M'])
- print("%L multiply\n", n->lineno);
- }
- if(l->complex >= r->complex) {
- regalloc(&nod, l, nn);
- cgen(l, &nod);
- regalloc(&nod1, l, Z); /* note: l used for type, so shifts work! */
- cgen(r, &nod1);
- gopcode(o, &nod1, Z, &nod);
- } else {
- regalloc(&nod, l, nn); /* note: l used for type, so shifts work! */
- cgen(r, &nod);
- regalloc(&nod1, l, Z);
- cgen(l, &nod1);
- gopcode(o, &nod, &nod1, &nod);
- }
- gopcode(OAS, &nod, Z, nn);
- regfree(&nod);
- regfree(&nod1);
- break;
-
- case OASLSHR:
- case OASASHL:
- case OASASHR:
- case OASAND:
- case OASADD:
- case OASSUB:
- case OASXOR:
- case OASOR:
- if(l->op == OBIT)
- goto asbitop;
- if(r->op == OCONST &&
- !typefd[n->type->etype] &&
- immconst(r)) {
- if(l->addable < INDEXED)
- reglcgen(&nod2, l, Z);
- else
- nod2 = *l;
- regalloc(&nod, l, nn); /* note: l used for type, so shifts work! */
- gopcode(OAS, &nod2, Z, &nod);
- gopcode(o, r, Z, &nod);
- gopcode(OAS, &nod, Z, &nod2);
-
- regfree(&nod);
- if(l->addable < INDEXED)
- regfree(&nod2);
- break;
- }
-
- case OASLMUL:
- case OASLDIV:
- case OASLMOD:
- case OASMUL:
- case OASDIV:
- case OASMOD:
- if(l->op == OBIT)
- goto asbitop;
- if(l->complex >= r->complex) {
- if(l->addable < INDEXED)
- reglcgen(&nod2, l, Z);
- else
- nod2 = *l;
- regalloc(&nod, n, nn);
- cgen(r, &nod);
- } else {
- regalloc(&nod, n, nn);
- cgen(r, &nod);
- if(l->addable < INDEXED)
- reglcgen(&nod2, l, Z);
- else
- nod2 = *l;
- }
- regalloc(&nod1, n, Z);
- gopcode(OAS, &nod2, Z, &nod1);
- if(nod1.type->etype != nod.type->etype){
- regalloc(&nod3, &nod, Z);
- gmove(&nod1, &nod3);
- regfree(&nod1);
- nod1 = nod3;
- }
- gopcode(o, &nod, &nod1, &nod);
- gmove(&nod, &nod2);
- if(nn != Z)
- gmove(&nod, nn);
- regfree(&nod);
- regfree(&nod1);
- if(l->addable < INDEXED)
- regfree(&nod2);
- break;
-
- asbitop:
- regalloc(&nod4, n, nn);
- regalloc(&nod3, r, Z);
- if(l->complex >= r->complex) {
- bitload(l, &nod, &nod1, &nod2, &nod4);
- cgen(r, &nod3);
- } else {
- cgen(r, &nod3);
- bitload(l, &nod, &nod1, &nod2, &nod4);
- }
- gmove(&nod, &nod4);
- gopcode(n->op, &nod3, Z, &nod4);
- regfree(&nod3);
- gmove(&nod4, &nod);
- regfree(&nod4);
- bitstore(l, &nod, &nod1, &nod2, nn);
- break;
-
- case OADDR:
- if(nn == Z) {
- nullwarn(l, Z);
- break;
- }
- lcgen(l, nn);
- break;
-
- case OFUNC:
- if(l->complex >= FNX) {
- if(l->op != OIND)
- diag(n, "bad function call");
-
- regret(&nod, l->left, 0, 0);
- cgen(l->left, &nod);
- regsalloc(&nod1, l->left);
- gopcode(OAS, &nod, Z, &nod1);
- regfree(&nod);
-
- nod = *n;
- nod.left = &nod2;
- nod2 = *l;
- nod2.left = &nod1;
- nod2.complex = 1;
- cgen(&nod, nn);
-
- return;
- }
- if(REGARG >= 0)
- o = reg[REGARG];
- gargs(r, &nod, &nod1);
- if(l->addable < INDEXED) {
- reglcgen(&nod, l, Z);
- gopcode(OFUNC, Z, Z, &nod);
- regfree(&nod);
- } else
- gopcode(OFUNC, Z, Z, l);
- if(REGARG>=0)
- if(o != reg[REGARG])
- reg[REGARG]--;
- regret(&nod, n, l->type, 1); // update maxarg if nothing else
- if(nn != Z)
- gopcode(OAS, &nod, Z, nn);
- if(nod.op == OREGISTER)
- regfree(&nod);
- break;
-
- case OIND:
- if(nn == Z) {
- cgen(l, nn);
- break;
- }
- regialloc(&nod, n, nn);
- r = l;
- while(r->op == OADD)
- r = r->right;
- if(sconst(r)) {
- v = r->vconst;
- r->vconst = 0;
- cgen(l, &nod);
- nod.xoffset += v;
- r->vconst = v;
- } else
- cgen(l, &nod);
- regind(&nod, n);
- gopcode(OAS, &nod, Z, nn);
- regfree(&nod);
- break;
-
- case OEQ:
- case ONE:
- case OLE:
- case OLT:
- case OGE:
- case OGT:
- case OLO:
- case OLS:
- case OHI:
- case OHS:
- if(nn == Z) {
- nullwarn(l, r);
- break;
- }
- boolgen(n, 1, nn);
- break;
-
- case OANDAND:
- case OOROR:
- boolgen(n, 1, nn);
- if(nn == Z)
- patch(p, pc);
- break;
-
- case ONOT:
- if(nn == Z) {
- nullwarn(l, Z);
- break;
- }
- boolgen(n, 1, nn);
- break;
-
- case OCOMMA:
- cgen(l, Z);
- cgen(r, nn);
- break;
-
- case OCAST:
- if(nn == Z) {
- nullwarn(l, Z);
- break;
- }
- /*
- * convert from types l->n->nn
- */
- if(nocast(l->type, n->type) && nocast(n->type, nn->type)) {
- /* both null, gen l->nn */
- cgen(l, nn);
- break;
- }
- regalloc(&nod, l, nn);
- cgen(l, &nod);
- regalloc(&nod1, n, &nod);
- gopcode(OAS, &nod, Z, &nod1);
- gopcode(OAS, &nod1, Z, nn);
- regfree(&nod1);
- regfree(&nod);
- break;
-
- case ODOT:
- sugen(l, nodrat, l->type->width);
- if(nn != Z) {
- warn(n, "non-interruptable temporary");
- nod = *nodrat;
- if(!r || r->op != OCONST) {
- diag(n, "DOT and no offset");
- break;
- }
- nod.xoffset += (int32)r->vconst;
- nod.type = n->type;
- cgen(&nod, nn);
- }
- break;
-
- case OCOND:
- bcgen(l, 1);
- p1 = p;
- cgen(r->left, nn);
- gbranch(OGOTO);
- patch(p1, pc);
- p1 = p;
- cgen(r->right, nn);
- patch(p1, pc);
- break;
-
- case OPOSTINC:
- case OPOSTDEC:
- v = 1;
- if(l->type->etype == TIND)
- v = l->type->link->width;
- if(o == OPOSTDEC)
- v = -v;
- if(l->op == OBIT)
- goto bitinc;
- if(nn == Z)
- goto pre;
-
- if(l->addable < INDEXED)
- reglcgen(&nod2, l, Z);
- else
- nod2 = *l;
-
- regalloc(&nod, l, nn);
- gopcode(OAS, &nod2, Z, &nod);
- regalloc(&nod1, l, Z);
- if(typefd[l->type->etype]) {
- regalloc(&nod3, l, Z);
- if(v < 0) {
- gopcode(OAS, nodfconst(-v), Z, &nod3);
- gopcode(OSUB, &nod3, &nod, &nod1);
- } else {
- gopcode(OAS, nodfconst(v), Z, &nod3);
- gopcode(OADD, &nod3, &nod, &nod1);
- }
- regfree(&nod3);
- } else
- gopcode(OADD, nodconst(v), &nod, &nod1);
- gopcode(OAS, &nod1, Z, &nod2);
-
- regfree(&nod);
- regfree(&nod1);
- if(l->addable < INDEXED)
- regfree(&nod2);
- break;
-
- case OPREINC:
- case OPREDEC:
- v = 1;
- if(l->type->etype == TIND)
- v = l->type->link->width;
- if(o == OPREDEC)
- v = -v;
- if(l->op == OBIT)
- goto bitinc;
-
- pre:
- if(l->addable < INDEXED)
- reglcgen(&nod2, l, Z);
- else
- nod2 = *l;
-
- regalloc(&nod, l, nn);
- gopcode(OAS, &nod2, Z, &nod);
- if(typefd[l->type->etype]) {
- regalloc(&nod3, l, Z);
- if(v < 0) {
- gopcode(OAS, nodfconst(-v), Z, &nod3);
- gopcode(OSUB, &nod3, Z, &nod);
- } else {
- gopcode(OAS, nodfconst(v), Z, &nod3);
- gopcode(OADD, &nod3, Z, &nod);
- }
- regfree(&nod3);
- } else
- gopcode(OADD, nodconst(v), Z, &nod);
- gopcode(OAS, &nod, Z, &nod2);
- if(nn && l->op == ONAME) /* in x=++i, emit USED(i) */
- gins(ANOP, l, Z);
-
- regfree(&nod);
- if(l->addable < INDEXED)
- regfree(&nod2);
- break;
-
- bitinc:
- if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) {
- bitload(l, &nod, &nod1, &nod2, Z);
- gopcode(OAS, &nod, Z, nn);
- gopcode(OADD, nodconst(v), Z, &nod);
- bitstore(l, &nod, &nod1, &nod2, Z);
- break;
- }
- bitload(l, &nod, &nod1, &nod2, nn);
- gopcode(OADD, nodconst(v), Z, &nod);
- bitstore(l, &nod, &nod1, &nod2, nn);
- break;
- }
- cursafe = curs;
-}
-
-void
-reglcgen(Node *t, Node *n, Node *nn)
-{
- Node *r;
- int32 v;
-
- regialloc(t, n, nn);
- if(n->op == OIND) {
- r = n->left;
- while(r->op == OADD)
- r = r->right;
- if(sconst(r)) {
- v = r->vconst;
- r->vconst = 0;
- lcgen(n, t);
- t->xoffset += v;
- r->vconst = v;
- regind(t, n);
- return;
- }
- }
- lcgen(n, t);
- regind(t, n);
-}
-
-void
-lcgen(Node *n, Node *nn)
-{
- Prog *p1;
- Node nod;
-
- if(debug['g']) {
- prtree(nn, "lcgen lhs");
- prtree(n, "lcgen");
- }
- if(n == Z || n->type == T)
- return;
- if(nn == Z) {
- nn = &nod;
- regalloc(&nod, n, Z);
- }
- switch(n->op) {
- default:
- if(n->addable < INDEXED) {
- diag(n, "unknown op in lcgen: %O", n->op);
- break;
- }
- nod = *n;
- nod.op = OADDR;
- nod.left = n;
- nod.right = Z;
- nod.type = types[TIND];
- gopcode(OAS, &nod, Z, nn);
- break;
-
- case OCOMMA:
- cgen(n->left, n->left);
- lcgen(n->right, nn);
- break;
-
- case OIND:
- cgen(n->left, nn);
- break;
-
- case OCOND:
- bcgen(n->left, 1);
- p1 = p;
- lcgen(n->right->left, nn);
- gbranch(OGOTO);
- patch(p1, pc);
- p1 = p;
- lcgen(n->right->right, nn);
- patch(p1, pc);
- break;
- }
-}
-
-void
-bcgen(Node *n, int true)
-{
-
- if(n->type == T)
- gbranch(OGOTO);
- else
- boolgen(n, true, Z);
-}
-
-void
-boolgen(Node *n, int true, Node *nn)
-{
- int o;
- Prog *p1, *p2;
- Node *l, *r, nod, nod1;
- int32 curs;
-
- if(debug['g']) {
- prtree(nn, "boolgen lhs");
- prtree(n, "boolgen");
- }
- curs = cursafe;
- l = n->left;
- r = n->right;
- switch(n->op) {
-
- default:
- if(n->op == OCONST) {
- o = vconst(n);
- if(!true)
- o = !o;
- gbranch(OGOTO);
- if(o) {
- p1 = p;
- gbranch(OGOTO);
- patch(p1, pc);
- }
- goto com;
- }
- regalloc(&nod, n, nn);
- cgen(n, &nod);
- o = ONE;
- if(true)
- o = comrel[relindex(o)];
- if(typefd[n->type->etype]) {
- nodreg(&nod1, n, NREG+FREGZERO);
- gopcode(o, &nod, Z, &nod1);
- } else
- gopcode(o, &nod, Z, nodconst(0));
- regfree(&nod);
- goto com;
-
- case OCOMMA:
- cgen(l, Z);
- boolgen(r, true, nn);
- break;
-
- case ONOT:
- boolgen(l, !true, nn);
- break;
-
- case OCOND:
- bcgen(l, 1);
- p1 = p;
- bcgen(r->left, true);
- p2 = p;
- gbranch(OGOTO);
- patch(p1, pc);
- p1 = p;
- bcgen(r->right, !true);
- patch(p2, pc);
- p2 = p;
- gbranch(OGOTO);
- patch(p1, pc);
- patch(p2, pc);
- goto com;
-
- case OANDAND:
- if(!true)
- goto caseor;
-
- caseand:
- bcgen(l, true);
- p1 = p;
- bcgen(r, !true);
- p2 = p;
- patch(p1, pc);
- gbranch(OGOTO);
- patch(p2, pc);
- goto com;
-
- case OOROR:
- if(!true)
- goto caseand;
-
- caseor:
- bcgen(l, !true);
- p1 = p;
- bcgen(r, !true);
- p2 = p;
- gbranch(OGOTO);
- patch(p1, pc);
- patch(p2, pc);
- goto com;
-
- case OEQ:
- case ONE:
- case OLE:
- case OLT:
- case OGE:
- case OGT:
- case OHI:
- case OHS:
- case OLO:
- case OLS:
- o = n->op;
- if(true)
- o = comrel[relindex(o)];
- if(l->complex >= FNX && r->complex >= FNX) {
- regret(&nod, r, 0, 0);
- cgen(r, &nod);
- regsalloc(&nod1, r);
- gopcode(OAS, &nod, Z, &nod1);
- regfree(&nod);
- nod = *n;
- nod.right = &nod1;
- boolgen(&nod, true, nn);
- break;
- }
- if(sconst(r)) {
- regalloc(&nod, l, nn);
- cgen(l, &nod);
- gopcode(o, &nod, Z, r);
- regfree(&nod);
- goto com;
- }
- if(l->complex >= r->complex) {
- regalloc(&nod1, l, nn);
- cgen(l, &nod1);
- regalloc(&nod, r, Z);
- cgen(r, &nod);
- } else {
- regalloc(&nod, r, nn);
- cgen(r, &nod);
- regalloc(&nod1, l, Z);
- cgen(l, &nod1);
- }
- gopcode(o, &nod1, Z, &nod);
- regfree(&nod);
- regfree(&nod1);
-
- com:
- if(nn != Z) {
- p1 = p;
- gopcode(OAS, nodconst(1L), Z, nn);
- gbranch(OGOTO);
- p2 = p;
- patch(p1, pc);
- gopcode(OAS, nodconst(0L), Z, nn);
- patch(p2, pc);
- }
- break;
- }
- cursafe = curs;
-}
-
-void
-sugen(Node *n, Node *nn, int32 w)
-{
- Prog *p1;
- Node nod0, nod1, nod2, nod3, nod4, *l, *r;
- Type *t;
- int32 pc1;
- int i, m, c;
-
- if(n == Z || n->type == T)
- return;
- if(debug['g']) {
- prtree(nn, "sugen lhs");
- prtree(n, "sugen");
- }
- if(nn == nodrat)
- if(w > nrathole)
- nrathole = w;
- switch(n->op) {
- case OIND:
- if(nn == Z) {
- nullwarn(n->left, Z);
- break;
- }
-
- default:
- goto copy;
-
- case OCONST:
- if(n->type && typev[n->type->etype]) {
- if(nn == Z) {
- nullwarn(n->left, Z);
- break;
- }
-
- t = nn->type;
- nn->type = types[TLONG];
- reglcgen(&nod1, nn, Z);
- nn->type = t;
-
- if(align(0, types[TCHAR], Aarg1, nil)) /* isbigendian */
- gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1);
- else
- gopcode(OAS, nod32const(n->vconst), Z, &nod1);
- nod1.xoffset += SZ_LONG;
- if(align(0, types[TCHAR], Aarg1, nil)) /* isbigendian */
- gopcode(OAS, nod32const(n->vconst), Z, &nod1);
- else
- gopcode(OAS, nod32const(n->vconst>>32), Z, &nod1);
-
- regfree(&nod1);
- break;
- }
- goto copy;
-
- case ODOT:
- l = n->left;
- sugen(l, nodrat, l->type->width);
- if(nn != Z) {
- warn(n, "non-interruptable temporary");
- nod1 = *nodrat;
- r = n->right;
- if(!r || r->op != OCONST) {
- diag(n, "DOT and no offset");
- break;
- }
- nod1.xoffset += (int32)r->vconst;
- nod1.type = n->type;
- sugen(&nod1, nn, w);
- }
- break;
-
- case OSTRUCT:
- /*
- * rewrite so lhs has no side effects
- */
- if(nn != Z && side(nn)) {
- nod1 = *n;
- nod1.type = typ(TIND, n->type);
- regalloc(&nod2, &nod1, Z);
- lcgen(nn, &nod2);
- regsalloc(&nod0, &nod1);
- gopcode(OAS, &nod2, Z, &nod0);
- regfree(&nod2);
-
- nod1 = *n;
- nod1.op = OIND;
- nod1.left = &nod0;
- nod1.right = Z;
- nod1.complex = 1;
-
- sugen(n, &nod1, w);
- return;
- }
-
- r = n->left;
- for(t = n->type->link; t != T; t = t->down) {
- l = r;
- if(r->op == OLIST) {
- l = r->left;
- r = r->right;
- }
- if(nn == Z) {
- cgen(l, nn);
- continue;
- }
- /*
- * hand craft *(&nn + o) = l
- */
- nod0 = znode;
- nod0.op = OAS;
- nod0.type = t;
- nod0.left = &nod1;
- nod0.right = l;
-
- nod1 = znode;
- nod1.op = OIND;
- nod1.type = t;
- nod1.left = &nod2;
-
- nod2 = znode;
- nod2.op = OADD;
- nod2.type = typ(TIND, t);
- nod2.left = &nod3;
- nod2.right = &nod4;
-
- nod3 = znode;
- nod3.op = OADDR;
- nod3.type = nod2.type;
- nod3.left = nn;
-
- nod4 = znode;
- nod4.op = OCONST;
- nod4.type = nod2.type;
- nod4.vconst = t->offset;
-
- ccom(&nod0);
- acom(&nod0);
- xcom(&nod0);
- nod0.addable = 0;
-
- /* prtree(&nod0, "hand craft"); /* */
- cgen(&nod0, Z);
- }
- break;
-
- case OAS:
- if(nn == Z) {
- if(n->addable < INDEXED)
- sugen(n->right, n->left, w);
- break;
- }
- /* BOTCH -- functions can clobber rathole */
- sugen(n->right, nodrat, w);
- warn(n, "non-interruptable temporary");
- sugen(nodrat, n->left, w);
- sugen(nodrat, nn, w);
- break;
-
- case OFUNC:
- if(!hasdotdotdot(n->left->type)) {
- cgen(n, Z);
- if(nn != Z) {
- curarg -= n->type->width;
- regret(&nod1, n, n->left->type, 1);
- if(nn->complex >= FNX) {
- regsalloc(&nod2, n);
- cgen(&nod1, &nod2);
- nod1 = nod2;
- }
- cgen(&nod1, nn);
- }
- break;
- }
- if(nn == Z) {
- sugen(n, nodrat, w);
- break;
- }
- if(nn->op != OIND) {
- nn = new1(OADDR, nn, Z);
- nn->type = types[TIND];
- nn->addable = 0;
- } else
- nn = nn->left;
- n = new(OFUNC, n->left, new(OLIST, nn, n->right));
- n->type = types[TVOID];
- n->left->type = types[TVOID];
- cgen(n, Z);
- break;
-
- case OCOND:
- bcgen(n->left, 1);
- p1 = p;
- sugen(n->right->left, nn, w);
- gbranch(OGOTO);
- patch(p1, pc);
- p1 = p;
- sugen(n->right->right, nn, w);
- patch(p1, pc);
- break;
-
- case OCOMMA:
- cgen(n->left, Z);
- sugen(n->right, nn, w);
- break;
- }
- return;
-
-copy:
- if(nn == Z)
- return;
- if(n->complex >= FNX && nn->complex >= FNX) {
- t = nn->type;
- nn->type = types[TLONG];
- regialloc(&nod1, nn, Z);
- lcgen(nn, &nod1);
- regsalloc(&nod2, nn);
- nn->type = t;
-
- gopcode(OAS, &nod1, Z, &nod2);
- regfree(&nod1);
-
- nod2.type = typ(TIND, t);
-
- nod1 = nod2;
- nod1.op = OIND;
- nod1.left = &nod2;
- nod1.right = Z;
- nod1.complex = 1;
- nod1.type = t;
-
- sugen(n, &nod1, w);
- return;
- }
-
- if(n->complex > nn->complex) {
- t = n->type;
- n->type = types[TLONG];
- reglcgen(&nod1, n, Z);
- n->type = t;
-
- t = nn->type;
- nn->type = types[TLONG];
- reglcgen(&nod2, nn, Z);
- nn->type = t;
- } else {
- t = nn->type;
- nn->type = types[TLONG];
- reglcgen(&nod2, nn, Z);
- nn->type = t;
-
- t = n->type;
- n->type = types[TLONG];
- reglcgen(&nod1, n, Z);
- n->type = t;
- }
-
- w /= SZ_LONG;
- if(w <= 5) {
- layout(&nod1, &nod2, w, 0, Z);
- goto out;
- }
-
- /*
- * minimize space for unrolling loop
- * 3,4,5 times. (6 or more is never minimum)
- * if small structure, try 2 also.
- */
- c = 0; /* set */
- m = 100;
- i = 3;
- if(w <= 15)
- i = 2;
- for(; i<=5; i++)
- if(i + w%i <= m) {
- c = i;
- m = c + w%c;
- }
-
- regalloc(&nod3, &regnode, Z);
- layout(&nod1, &nod2, w%c, w/c, &nod3);
-
- pc1 = pc;
- layout(&nod1, &nod2, c, 0, Z);
-
- gopcode(OSUB, nodconst(1L), Z, &nod3);
- nod1.op = OREGISTER;
- gopcode(OADD, nodconst(c*SZ_LONG), Z, &nod1);
- nod2.op = OREGISTER;
- gopcode(OADD, nodconst(c*SZ_LONG), Z, &nod2);
-
- gopcode(OGT, &nod3, Z, nodconst(0));
- patch(p, pc1);
-
- regfree(&nod3);
-out:
- regfree(&nod1);
- regfree(&nod2);
-}
-
-void
-layout(Node *f, Node *t, int c, int cv, Node *cn)
-{
- Node t1, t2;
-
- while(c > 3) {
- layout(f, t, 2, 0, Z);
- c -= 2;
- }
-
- regalloc(&t1, &regnode, Z);
- regalloc(&t2, &regnode, Z);
- if(c > 0) {
- gopcode(OAS, f, Z, &t1);
- f->xoffset += SZ_LONG;
- }
- if(cn != Z)
- gopcode(OAS, nodconst(cv), Z, cn);
- if(c > 1) {
- gopcode(OAS, f, Z, &t2);
- f->xoffset += SZ_LONG;
- }
- if(c > 0) {
- gopcode(OAS, &t1, Z, t);
- t->xoffset += SZ_LONG;
- }
- if(c > 2) {
- gopcode(OAS, f, Z, &t1);
- f->xoffset += SZ_LONG;
- }
- if(c > 1) {
- gopcode(OAS, &t2, Z, t);
- t->xoffset += SZ_LONG;
- }
- if(c > 2) {
- gopcode(OAS, &t1, Z, t);
- t->xoffset += SZ_LONG;
- }
- regfree(&t1);
- regfree(&t2);
-}
diff --git a/src/cmd/9c/doc.go b/src/cmd/9c/doc.go
deleted file mode 100644
index 6c9b4762d..000000000
--- a/src/cmd/9c/doc.go
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build ignore
-
-/*
-
-9c is a version of the Plan 9 C compiler. The original is documented at
-
- http://plan9.bell-labs.com/magic/man2html/1/8c
-
-Its target architecture is the Power64, referred to by these tools as
-power64 (big endian) or power64le (little endian).
-
-*/
-package main
diff --git a/src/cmd/9c/gc.h b/src/cmd/9c/gc.h
deleted file mode 100644
index fbe5099fe..000000000
--- a/src/cmd/9c/gc.h
+++ /dev/null
@@ -1,350 +0,0 @@
-// cmd/9c/gc.h from Vita Nuova.
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include <u.h>
-#include "../cc/cc.h"
-#include "../9l/9.out.h"
-
-/*
- * 9c/powerpc64
- */
-#define SZ_CHAR 1
-#define SZ_SHORT 2
-#define SZ_INT 4
-#define SZ_LONG 4
-#define SZ_IND 8
-#define SZ_FLOAT 4
-#define SZ_VLONG 8
-#define SZ_DOUBLE 8
-#define FNX 100
-
-typedef struct Case Case;
-typedef struct C1 C1;
-typedef struct Multab Multab;
-typedef struct Hintab Hintab;
-typedef struct Reg Reg;
-typedef struct Rgn Rgn;
-
-#define A ((Adr*)0)
-
-#define INDEXED 9
-#define P ((Prog*)0)
-
-struct Case
-{
- Case* link;
- vlong val;
- int32 label;
- char def;
- char isv;
-};
-#define C ((Case*)0)
-
-struct C1
-{
- vlong val;
- int32 label;
-};
-
-struct Multab
-{
- int32 val;
- char code[20];
-};
-
-struct Hintab
-{
- ushort val;
- char hint[10];
-};
-
-struct Reg
-{
- int32 pc;
- int32 rpo; /* reverse post ordering */
-
- Bits set;
- Bits use1;
- Bits use2;
-
- Bits refbehind;
- Bits refahead;
- Bits calbehind;
- Bits calahead;
- Bits regdiff;
- Bits act;
-
- int32 regu;
- int32 loop; /* could be shorter */
-
- union
- {
- Reg* log5;
- int32 active;
- };
- Reg* p1;
- Reg* p2;
- Reg* p2link;
- Reg* s1;
- Reg* s2;
- Reg* link;
- Prog* prog;
-};
-#define R ((Reg*)0)
-
-#define NRGN 600
-struct Rgn
-{
- Reg* enter;
- short cost;
- short varno;
- short regno;
-};
-
-EXTERN int32 breakpc;
-EXTERN int32 nbreak;
-EXTERN Case* cases;
-EXTERN Node constnode;
-EXTERN Node fconstnode;
-EXTERN Node vconstnode;
-EXTERN int32 continpc;
-EXTERN int32 curarg;
-EXTERN int32 cursafe;
-EXTERN Prog* lastp;
-extern int hintabsize;
-EXTERN int32 maxargsafe;
-EXTERN Multab multab[20];
-EXTERN int mnstring;
-EXTERN Node* nodrat;
-EXTERN Node* nodret;
-EXTERN Node* nodsafe;
-EXTERN int32 nrathole;
-EXTERN int32 nstring;
-EXTERN Prog* p;
-EXTERN int32 pc;
-EXTERN Node regnode;
-EXTERN Node qregnode;
-EXTERN char string[NSNAME];
-EXTERN Sym* symrathole;
-EXTERN Node znode;
-EXTERN Prog zprog;
-EXTERN int reg[NREG+NREG];
-EXTERN int32 exregoffset;
-EXTERN int32 exfregoffset;
-EXTERN uchar typechlpv[NTYPE];
-
-#define BLOAD(r) band(bnot(r->refbehind), r->refahead)
-#define BSTORE(r) band(bnot(r->calbehind), r->calahead)
-#define LOAD(r) (~r->refbehind.b[z] & r->refahead.b[z])
-#define STORE(r) (~r->calbehind.b[z] & r->calahead.b[z])
-
-#define bset(a,n) ((a).b[(n)/32]&(1L<<(n)%32))
-
-#define CLOAD 5
-#define CREF 5
-#define CINF 1000
-#define LOOP 3
-
-EXTERN Rgn region[NRGN];
-EXTERN Rgn* rgp;
-EXTERN int nregion;
-EXTERN int nvar;
-
-EXTERN Bits externs;
-EXTERN Bits params;
-EXTERN Bits consts;
-EXTERN Bits addrs;
-
-EXTERN int32 regbits;
-EXTERN int32 exregbits;
-
-EXTERN int change;
-EXTERN int suppress;
-
-EXTERN Reg* firstr;
-EXTERN Reg* lastr;
-EXTERN Reg zreg;
-EXTERN Reg* freer;
-EXTERN Var var[NVAR];
-EXTERN int32* idom;
-EXTERN Reg** rpo2r;
-EXTERN int32 maxnr;
-
-#define R0ISZERO (debug['0']==0)
-
-extern char* anames[];
-extern Hintab hintab[];
-
-/*
- * sgen.c
- */
-void codgen(Node*, Node*);
-void gen(Node*);
-void usedset(Node*, int);
-void noretval(int);
-void xcom(Node*);
-int bcomplex(Node*, Node*);
-Prog* gtext(Sym*, int32);
-vlong argsize(int);
-
-/*
- * cgen.c
- */
-void cgen(Node*, Node*);
-void reglcgen(Node*, Node*, Node*);
-void lcgen(Node*, Node*);
-void bcgen(Node*, int);
-void boolgen(Node*, int, Node*);
-void sugen(Node*, Node*, int32);
-void layout(Node*, Node*, int, int, Node*);
-
-/*
- * txt.c
- */
-void ginit(void);
-void gclean(void);
-void nextpc(void);
-void gargs(Node*, Node*, Node*);
-void garg1(Node*, Node*, Node*, int, Node**);
-Node* nodconst(int32);
-Node* nod32const(vlong);
-Node* nodfconst(double);
-Node* nodgconst(vlong v, Type *t);
-void nodreg(Node*, Node*, int);
-void regret(Node*, Node*, Type*, int);
-void regalloc(Node*, Node*, Node*);
-void regfree(Node*);
-void regialloc(Node*, Node*, Node*);
-void regsalloc(Node*, Node*);
-void regaalloc1(Node*, Node*);
-void regaalloc(Node*, Node*);
-void regind(Node*, Node*);
-void gprep(Node*, Node*);
-void raddr(Node*, Prog*);
-void naddr(Node*, Addr*);
-void gmove(Node*, Node*);
-void gins(int a, Node*, Node*);
-void gopcode(int, Node*, Node*, Node*);
-int samaddr(Node*, Node*);
-void gbranch(int);
-int immconst(Node*);
-void patch(Prog*, int32);
-int sconst(Node*);
-int sval(int32);
-int uconst(Node*);
-void gpseudo(int, Sym*, Node*);
-void gprefetch(Node*);
-void gpcdata(int, int);
-
-/*
- * swt.c
- */
-int swcmp(const void*, const void*);
-void doswit(Node*);
-void swit1(C1*, int, int32, Node*);
-void swit2(C1*, int, int32, Node*, Node*);
-void newcase(void);
-void bitload(Node*, Node*, Node*, Node*, Node*);
-void bitstore(Node*, Node*, Node*, Node*, Node*);
-int32 outstring(char*, int32);
-int mulcon(Node*, Node*);
-Multab* mulcon0(Node*, int32);
-int mulcon1(Node*, int32, Node*);
-void nullwarn(Node*, Node*);
-void sextern(Sym*, Node*, int32, int32);
-void gextern(Sym*, Node*, int32, int32);
-void outcode(void);
-
-/*
- * list
- */
-void listinit(void);
-int Pconv(Fmt*);
-int Aconv(Fmt*);
-int Dconv(Fmt*);
-int Sconv(Fmt*);
-int Nconv(Fmt*);
-int Bconv(Fmt*);
-
-/*
- * reg.c
- */
-Reg* rega(void);
-int rcmp(const void*, const void*);
-void regopt(Prog*);
-void addmove(Reg*, int, int, int);
-Bits mkvar(Addr*, int);
-void prop(Reg*, Bits, Bits);
-void loopit(Reg*, int32);
-void synch(Reg*, Bits);
-uint32 allreg(uint32, Rgn*);
-void paint1(Reg*, int);
-uint32 paint2(Reg*, int);
-void paint3(Reg*, int, int32, int);
-void addreg(Addr*, int);
-
-/*
- * peep.c
- */
-void peep(void);
-void excise(Reg*);
-Reg* uniqp(Reg*);
-Reg* uniqs(Reg*);
-int regtyp(Addr*);
-int regzer(Addr*);
-int anyvar(Addr*);
-int subprop(Reg*);
-int copyprop(Reg*);
-int copy1(Addr*, Addr*, Reg*, int);
-int copyu(Prog*, Addr*, Addr*);
-
-int copyas(Addr*, Addr*);
-int copyau(Addr*, Addr*);
-int copyau1(Prog*, Addr*);
-int copysub(Addr*, Addr*, Addr*, int);
-int copysub1(Prog*, Addr*, Addr*, int);
-
-int32 RtoB(int);
-int32 FtoB(int);
-int BtoR(int32);
-int BtoF(int32);
-
-/*
- * com64.c
- */
-int com64(Node*);
-void com64init(void);
-void bool64(Node*);
-
-#pragma varargck type "A" int
-#pragma varargck type "B" Bits
-#pragma varargck type "D" Addr*
-#pragma varargck type "N" Addr*
-#pragma varargck type "P" Prog*
-#pragma varargck type "S" char*
diff --git a/src/cmd/9c/list.c b/src/cmd/9c/list.c
deleted file mode 100644
index 5cfc442cb..000000000
--- a/src/cmd/9c/list.c
+++ /dev/null
@@ -1,37 +0,0 @@
-// cmd/9c/list.c from Vita Nuova.
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#define EXTERN
-#include "gc.h"
-
-void
-listinit(void)
-{
- listinit9();
-}
diff --git a/src/cmd/9c/machcap.c b/src/cmd/9c/machcap.c
deleted file mode 100644
index af44bc820..000000000
--- a/src/cmd/9c/machcap.c
+++ /dev/null
@@ -1,105 +0,0 @@
-// cmd/9c/machcap.c from Vita Nuova.
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-
-int
-machcap(Node *n)
-{
-
- if(n == Z)
- return 1; /* test */
-
- switch(n->op) {
- case OMUL:
- case OLMUL:
- case OASMUL:
- case OASLMUL:
- if(typechlv[n->type->etype])
- return 1;
- break;
-
- case OADD:
- case OAND:
- case OOR:
- case OSUB:
- case OXOR:
- case OASHL:
- case OLSHR:
- case OASHR:
- if(typechlv[n->left->type->etype])
- return 1;
- break;
-
- case OCAST:
- return 1;
-
- case OCOND:
- case OCOMMA:
- case OLIST:
- case OANDAND:
- case OOROR:
- case ONOT:
- return 1;
-
- case OASADD:
- case OASSUB:
- case OASAND:
- case OASOR:
- case OASXOR:
- return 1;
-
- case OASASHL:
- case OASASHR:
- case OASLSHR:
- return 1;
-
- case OPOSTINC:
- case OPOSTDEC:
- case OPREINC:
- case OPREDEC:
- return 1;
-
- case OEQ:
- case ONE:
- case OLE:
- case OGT:
- case OLT:
- case OGE:
- case OHI:
- case OHS:
- case OLO:
- case OLS:
- return 1;
- case ONEG:
- case OCOM:
- break;
- }
- return 0;
-}
diff --git a/src/cmd/9c/mul.c b/src/cmd/9c/mul.c
deleted file mode 100644
index 353376f15..000000000
--- a/src/cmd/9c/mul.c
+++ /dev/null
@@ -1,638 +0,0 @@
-// cmd/9c/mul.c from Vita Nuova.
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-
-/*
- * code sequences for multiply by constant.
- * [a-l][0-3]
- * lsl $(A-'a'),r0,r1
- * [+][0-7]
- * add r0,r1,r2
- * [-][0-7]
- * sub r0,r1,r2
- */
-
-static int multabp;
-static int32 mulval;
-static char* mulcp;
-static int32 valmax;
-static int shmax;
-
-static int docode(char *hp, char *cp, int r0, int r1);
-static int gen1(int len);
-static int gen2(int len, int32 r1);
-static int gen3(int len, int32 r0, int32 r1, int flag);
-enum
-{
- SR1 = 1<<0, /* r1 has been shifted */
- SR0 = 1<<1, /* r0 has been shifted */
- UR1 = 1<<2, /* r1 has not been used */
- UR0 = 1<<3, /* r0 has not been used */
-};
-
-Multab*
-mulcon0(Node *n, int32 v)
-{
- int a1, a2, g;
- Multab *m, *m1;
- char hint[10];
-
- if(v < 0)
- v = -v;
-
- /*
- * look in cache
- */
- m = multab;
- for(g=0; g<nelem(multab); g++) {
- if(m->val == v) {
- if(m->code[0] == 0)
- return 0;
- return m;
- }
- m++;
- }
-
- /*
- * select a spot in cache to overwrite
- */
- multabp++;
- if(multabp < 0 || multabp >= nelem(multab))
- multabp = 0;
- m = multab+multabp;
- m->val = v;
- mulval = v;
-
- /*
- * look in execption hint table
- */
- a1 = 0;
- a2 = hintabsize;
- for(;;) {
- if(a1 >= a2)
- goto no;
- g = (a2 + a1)/2;
- if(v < hintab[g].val) {
- a2 = g;
- continue;
- }
- if(v > hintab[g].val) {
- a1 = g+1;
- continue;
- }
- break;
- }
-
- if(docode(hintab[g].hint, m->code, 1, 0))
- return m;
- print("%L: multiply table failure %ld\n", n->lineno, v);
- m->code[0] = 0;
- return 0;
-
-no:
- /*
- * try to search
- */
- hint[0] = 0;
- for(g=1; g<=6; g++) {
- if(g >= 6 && v >= 65535)
- break;
- mulcp = hint+g;
- *mulcp = 0;
- if(gen1(g)) {
- if(docode(hint, m->code, 1, 0))
- return m;
- print("%L: multiply table failure (g=%d h=%s) %ld\n",
- n->lineno, g, hint, v);
- break;
- }
- }
-
- /*
- * try a recur followed by a shift
- */
- g = 0;
- while(!(v & 1)) {
- g++;
- v >>= 1;
- }
- if(g) {
- m1 = mulcon0(n, v);
- if(m1) {
- strcpy(m->code, m1->code);
- sprint(strchr(m->code, 0), "%c0", g+'a');
- return m;
- }
- }
- m->code[0] = 0;
- return 0;
-}
-
-static int
-docode(char *hp, char *cp, int r0, int r1)
-{
- int c, i;
-
- c = *hp++;
- *cp = c;
- cp += 2;
- switch(c) {
- default:
- c -= 'a';
- if(c < 1 || c >= 30)
- break;
- for(i=0; i<4; i++) {
- switch(i) {
- case 0:
- if(docode(hp, cp, r0<<c, r1))
- goto out;
- break;
- case 1:
- if(docode(hp, cp, r1<<c, r1))
- goto out;
- break;
- case 2:
- if(docode(hp, cp, r0, r0<<c))
- goto out;
- break;
- case 3:
- if(docode(hp, cp, r0, r1<<c))
- goto out;
- break;
- }
- }
- break;
-
- case '+':
- for(i=0; i<8; i++) {
- cp[-1] = i+'0';
- switch(i) {
- case 1:
- if(docode(hp, cp, r0+r1, r1))
- goto out;
- break;
- case 5:
- if(docode(hp, cp, r0, r0+r1))
- goto out;
- break;
- }
- }
- break;
-
- case '-':
- for(i=0; i<8; i++) {
- cp[-1] = i+'0';
- switch(i) {
- case 1:
- if(docode(hp, cp, r0-r1, r1))
- goto out;
- break;
- case 2:
- if(docode(hp, cp, r1-r0, r1))
- goto out;
- break;
- case 5:
- if(docode(hp, cp, r0, r0-r1))
- goto out;
- break;
- case 6:
- if(docode(hp, cp, r0, r1-r0))
- goto out;
- break;
- }
- }
- break;
-
- case 0:
- if(r0 == mulval)
- return 1;
- }
- return 0;
-
-out:
- cp[-1] = i+'0';
- return 1;
-}
-
-static int
-gen1(int len)
-{
- int i;
-
- for(shmax=1; shmax<30; shmax++) {
- valmax = 1<<shmax;
- if(valmax >= mulval)
- break;
- }
- if(mulval == 1)
- return 1;
-
- len--;
- for(i=1; i<=shmax; i++)
- if(gen2(len, 1<<i)) {
- *--mulcp = 'a'+i;
- return 1;
- }
- return 0;
-}
-
-static int
-gen2(int len, int32 r1)
-{
- int i;
-
- if(len <= 0) {
- if(r1 == mulval)
- return 1;
- return 0;
- }
-
- len--;
- if(len == 0)
- goto calcr0;
-
- if(gen3(len, r1, r1+1, UR1)) {
- i = '+';
- goto out;
- }
- if(gen3(len, r1-1, r1, UR0)) {
- i = '-';
- goto out;
- }
- if(gen3(len, 1, r1+1, UR1)) {
- i = '+';
- goto out;
- }
- if(gen3(len, 1, r1-1, UR1)) {
- i = '-';
- goto out;
- }
-
- return 0;
-
-calcr0:
- if(mulval == r1+1) {
- i = '+';
- goto out;
- }
- if(mulval == r1-1) {
- i = '-';
- goto out;
- }
- return 0;
-
-out:
- *--mulcp = i;
- return 1;
-}
-
-static int
-gen3(int len, int32 r0, int32 r1, int flag)
-{
- int i, f1, f2;
- int32 x;
-
- if(r0 <= 0 ||
- r0 >= r1 ||
- r1 > valmax)
- return 0;
-
- len--;
- if(len == 0)
- goto calcr0;
-
- if(!(flag & UR1)) {
- f1 = UR1|SR1;
- for(i=1; i<=shmax; i++) {
- x = r0<<i;
- if(x > valmax)
- break;
- if(gen3(len, r0, x, f1)) {
- i += 'a';
- goto out;
- }
- }
- }
-
- if(!(flag & UR0)) {
- f1 = UR1|SR1;
- for(i=1; i<=shmax; i++) {
- x = r1<<i;
- if(x > valmax)
- break;
- if(gen3(len, r1, x, f1)) {
- i += 'a';
- goto out;
- }
- }
- }
-
- if(!(flag & SR1)) {
- f1 = UR1|SR1|(flag&UR0);
- for(i=1; i<=shmax; i++) {
- x = r1<<i;
- if(x > valmax)
- break;
- if(gen3(len, r0, x, f1)) {
- i += 'a';
- goto out;
- }
- }
- }
-
- if(!(flag & SR0)) {
- f1 = UR0|SR0|(flag&(SR1|UR1));
-
- f2 = UR1|SR1;
- if(flag & UR1)
- f2 |= UR0;
- if(flag & SR1)
- f2 |= SR0;
-
- for(i=1; i<=shmax; i++) {
- x = r0<<i;
- if(x > valmax)
- break;
- if(x > r1) {
- if(gen3(len, r1, x, f2)) {
- i += 'a';
- goto out;
- }
- } else
- if(gen3(len, x, r1, f1)) {
- i += 'a';
- goto out;
- }
- }
- }
-
- x = r1+r0;
- if(gen3(len, r0, x, UR1)) {
- i = '+';
- goto out;
- }
-
- if(gen3(len, r1, x, UR1)) {
- i = '+';
- goto out;
- }
-
- x = r1-r0;
- if(gen3(len, x, r1, UR0)) {
- i = '-';
- goto out;
- }
-
- if(x > r0) {
- if(gen3(len, r0, x, UR1)) {
- i = '-';
- goto out;
- }
- } else
- if(gen3(len, x, r0, UR0)) {
- i = '-';
- goto out;
- }
-
- return 0;
-
-calcr0:
- f1 = flag & (UR0|UR1);
- if(f1 == UR1) {
- for(i=1; i<=shmax; i++) {
- x = r1<<i;
- if(x >= mulval) {
- if(x == mulval) {
- i += 'a';
- goto out;
- }
- break;
- }
- }
- }
-
- if(mulval == r1+r0) {
- i = '+';
- goto out;
- }
- if(mulval == r1-r0) {
- i = '-';
- goto out;
- }
-
- return 0;
-
-out:
- *--mulcp = i;
- return 1;
-}
-
-/*
- * hint table has numbers that
- * the search algorithm fails on.
- * <1000:
- * all numbers
- * <5000:
- * ÷ by 5
- * <10000:
- * ÷ by 50
- * <65536:
- * ÷ by 250
- */
-Hintab hintab[] =
-{
- 683, "b++d+e+",
- 687, "b+e++e-",
- 691, "b++d+e+",
- 731, "b++d+e+",
- 811, "b++d+i+",
- 821, "b++e+e+",
- 843, "b+d++e+",
- 851, "b+f-+e-",
- 853, "b++e+e+",
- 877, "c++++g-",
- 933, "b+c++g-",
- 981, "c-+e-d+",
- 1375, "b+c+b+h-",
- 1675, "d+b++h+",
- 2425, "c++f-e+",
- 2675, "c+d++f-",
- 2750, "b+d-b+h-",
- 2775, "c-+g-e-",
- 3125, "b++e+g+",
- 3275, "b+c+g+e+",
- 3350, "c++++i+",
- 3475, "c-+e-f-",
- 3525, "c-+d+g-",
- 3625, "c-+e-j+",
- 3675, "b+d+d+e+",
- 3725, "b+d-+h+",
- 3925, "b+d+f-d-",
- 4275, "b+g++e+",
- 4325, "b+h-+d+",
- 4425, "b+b+g-j-",
- 4525, "b+d-d+f+",
- 4675, "c++d-g+",
- 4775, "b+d+b+g-",
- 4825, "c+c-+i-",
- 4850, "c++++i-",
- 4925, "b++e-g-",
- 4975, "c+f++e-",
- 5500, "b+g-c+d+",
- 6700, "d+b++i+",
- 9700, "d++++j-",
- 11000, "b+f-c-h-",
- 11750, "b+d+g+j-",
- 12500, "b+c+e-k+",
- 13250, "b+d+e-f+",
- 13750, "b+h-c-d+",
- 14250, "b+g-c+e-",
- 14500, "c+f+j-d-",
- 14750, "d-g--f+",
- 16750, "b+e-d-n+",
- 17750, "c+h-b+e+",
- 18250, "d+b+h-d+",
- 18750, "b+g-++f+",
- 19250, "b+e+b+h+",
- 19750, "b++h--f-",
- 20250, "b+e-l-c+",
- 20750, "c++bi+e-",
- 21250, "b+i+l+c+",
- 22000, "b+e+d-g-",
- 22250, "b+d-h+k-",
- 22750, "b+d-e-g+",
- 23250, "b+c+h+e-",
- 23500, "b+g-c-g-",
- 23750, "b+g-b+h-",
- 24250, "c++g+m-",
- 24750, "b+e+e+j-",
- 25000, "b++dh+g+",
- 25250, "b+e+d-g-",
- 25750, "b+e+b+j+",
- 26250, "b+h+c+e+",
- 26500, "b+h+c+g+",
- 26750, "b+d+e+g-",
- 27250, "b+e+e+f+",
- 27500, "c-i-c-d+",
- 27750, "b+bd++j+",
- 28250, "d-d-++i-",
- 28500, "c+c-h-e-",
- 29000, "b+g-d-f+",
- 29500, "c+h+++e-",
- 29750, "b+g+f-c+",
- 30250, "b+f-g-c+",
- 33500, "c-f-d-n+",
- 33750, "b+d-b+j-",
- 34250, "c+e+++i+",
- 35250, "e+b+d+k+",
- 35500, "c+e+d-g-",
- 35750, "c+i-++e+",
- 36250, "b+bh-d+e+",
- 36500, "c+c-h-e-",
- 36750, "d+e--i+",
- 37250, "b+g+g+b+",
- 37500, "b+h-b+f+",
- 37750, "c+be++j-",
- 38500, "b+e+b+i+",
- 38750, "d+i-b+d+",
- 39250, "b+g-l-+d+",
- 39500, "b+g-c+g-",
- 39750, "b+bh-c+f-",
- 40250, "b+bf+d+g-",
- 40500, "b+g-c+g+",
- 40750, "c+b+i-e+",
- 41250, "d++bf+h+",
- 41500, "b+j+c+d-",
- 41750, "c+f+b+h-",
- 42500, "c+h++g+",
- 42750, "b+g+d-f-",
- 43250, "b+l-e+d-",
- 43750, "c+bd+h+f-",
- 44000, "b+f+g-d-",
- 44250, "b+d-g--f+",
- 44500, "c+e+c+h+",
- 44750, "b+e+d-h-",
- 45250, "b++g+j-g+",
- 45500, "c+d+e-g+",
- 45750, "b+d-h-e-",
- 46250, "c+bd++j+",
- 46500, "b+d-c-j-",
- 46750, "e-e-b+g-",
- 47000, "b+c+d-j-",
- 47250, "b+e+e-g-",
- 47500, "b+g-c-h-",
- 47750, "b+f-c+h-",
- 48250, "d--h+n-",
- 48500, "b+c-g+m-",
- 48750, "b+e+e-g+",
- 49500, "c-f+e+j-",
- 49750, "c+c+g++f-",
- 50000, "b+e+e+k+",
- 50250, "b++i++g+",
- 50500, "c+g+f-i+",
- 50750, "b+e+d+k-",
- 51500, "b+i+c-f+",
- 51750, "b+bd+g-e-",
- 52250, "b+d+g-j+",
- 52500, "c+c+f+g+",
- 52750, "b+c+e+i+",
- 53000, "b+i+c+g+",
- 53500, "c+g+g-n+",
- 53750, "b+j+d-c+",
- 54250, "b+d-g-j-",
- 54500, "c-f+e+f+",
- 54750, "b+f-+c+g+",
- 55000, "b+g-d-g-",
- 55250, "b+e+e+g+",
- 55500, "b+cd++j+",
- 55750, "b+bh-d-f-",
- 56250, "c+d-b+j-",
- 56500, "c+d+c+i+",
- 56750, "b+e+d++h-",
- 57000, "b+d+g-f+",
- 57250, "b+f-m+d-",
- 57750, "b+i+c+e-",
- 58000, "b+e+d+h+",
- 58250, "c+b+g+g+",
- 58750, "d-e-j--e+",
- 59000, "d-i-+e+",
- 59250, "e--h-m+",
- 59500, "c+c-h+f-",
- 59750, "b+bh-e+i-",
- 60250, "b+bh-e-e-",
- 60500, "c+c-g-g-",
- 60750, "b+e-l-e-",
- 61250, "b+g-g-c+",
- 61750, "b+g-c+g+",
- 62250, "f--+c-i-",
- 62750, "e+f--+g+",
- 64750, "b+f+d+p-",
-};
-int hintabsize = nelem(hintab);
diff --git a/src/cmd/9c/peep.c b/src/cmd/9c/peep.c
deleted file mode 100644
index 2e8e2adcc..000000000
--- a/src/cmd/9c/peep.c
+++ /dev/null
@@ -1,1076 +0,0 @@
-// cmd/9c/peep.c from Vita Nuova.
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-
-/*
-static Reg*
-rnops(Reg *r)
-{
- Prog *p;
- Reg *r1;
-
- if(r != R)
- for(;;){
- p = r->prog;
- if(p->as != ANOP || p->from.type != D_NONE || p->to.type != D_NONE)
- break;
- r1 = uniqs(r);
- if(r1 == R)
- break;
- r = r1;
- }
- return r;
-}
-*/
-
-void
-peep(void)
-{
- Reg *r, *r1, *r2;
- Prog *p, *p1;
- int t;
-/*
- * complete R structure
- */
- t = 0;
- for(r=firstr; r!=R; r=r1) {
- r1 = r->link;
- if(r1 == R)
- break;
- p = r->prog->link;
- while(p != r1->prog)
- switch(p->as) {
- default:
- r2 = rega();
- r->link = r2;
- r2->link = r1;
-
- r2->prog = p;
- r2->p1 = r;
- r->s1 = r2;
- r2->s1 = r1;
- r1->p1 = r2;
-
- r = r2;
- t++;
-
- case ADATA:
- case AGLOBL:
- case ANAME:
- case ASIGNAME:
- p = p->link;
- }
- }
-
-loop1:
- t = 0;
- for(r=firstr; r!=R; r=r->link) {
- p = r->prog;
- if(p->as == AMOVW || p->as == AMOVD || p->as == AFMOVS || p->as == AFMOVD)
- if(regtyp(&p->to)) {
- if(regtyp(&p->from))
- if(p->from.type == p->to.type) {
- if(copyprop(r)) {
- excise(r);
- t++;
- } else
- if(subprop(r) && copyprop(r)) {
- excise(r);
- t++;
- }
- }
- if(regzer(&p->from))
- if(p->to.type == D_REG) {
- p->from.type = D_REG;
- p->from.reg = REGZERO;
- if(copyprop(r)) {
- excise(r);
- t++;
- } else
- if(subprop(r) && copyprop(r)) {
- excise(r);
- t++;
- }
- }
- }
- }
- if(t)
- goto loop1;
- /*
- * look for MOVB x,R; MOVB R,R
- */
- for(r=firstr; r!=R; r=r->link) {
- p = r->prog;
- switch(p->as) {
- default:
- continue;
- case AMOVH:
- case AMOVHZ:
- case AMOVB:
- case AMOVBZ:
- case AMOVW:
- case AMOVWZ:
- if(p->to.type != D_REG)
- continue;
- break;
- }
- r1 = r->link;
- if(r1 == R)
- continue;
- p1 = r1->prog;
- if(p1->as != p->as)
- continue;
- if(p1->from.type != D_REG || p1->from.reg != p->to.reg)
- continue;
- if(p1->to.type != D_REG || p1->to.reg != p->to.reg)
- continue;
- excise(r1);
- }
-
- if(debug['D'] > 1)
- return; /* allow following code improvement to be suppressed */
-
- /*
- * look for OP x,y,R; CMP R, $0 -> OPCC x,y,R
- * when OP can set condition codes correctly
- */
- for(r=firstr; r!=R; r=r->link) {
- p = r->prog;
- switch(p->as) {
- case ACMP:
- case ACMPW: /* always safe? */
- if(!regzer(&p->to))
- continue;
- r1 = r->s1;
- if(r1 == R)
- continue;
- switch(r1->prog->as) {
- default:
- continue;
- case ABCL:
- case ABC:
- /* the conditions can be complex and these are currently little used */
- continue;
- case ABEQ:
- case ABGE:
- case ABGT:
- case ABLE:
- case ABLT:
- case ABNE:
- case ABVC:
- case ABVS:
- break;
- }
- r1 = r;
- do
- r1 = uniqp(r1);
- while (r1 != R && r1->prog->as == ANOP);
- if(r1 == R)
- continue;
- p1 = r1->prog;
- if(p1->to.type != D_REG || p1->to.reg != p->from.reg)
- continue;
- switch(p1->as) {
- case ASUB:
- case AADD:
- case AXOR:
- case AOR:
- /* irregular instructions */
- if(p1->from.type == D_CONST)
- continue;
- break;
- }
- switch(p1->as) {
- default:
- continue;
- case AMOVW:
- case AMOVD:
- if(p1->from.type != D_REG)
- continue;
- continue;
- case AANDCC:
- case AANDNCC:
- case AORCC:
- case AORNCC:
- case AXORCC:
- case ASUBCC:
- case ASUBECC:
- case ASUBMECC:
- case ASUBZECC:
- case AADDCC:
- case AADDCCC:
- case AADDECC:
- case AADDMECC:
- case AADDZECC:
- case ARLWMICC:
- case ARLWNMCC:
- t = p1->as;
- break;
- /* don't deal with floating point instructions for now */
-/*
- case AFABS: t = AFABSCC; break;
- case AFADD: t = AFADDCC; break;
- case AFADDS: t = AFADDSCC; break;
- case AFCTIW: t = AFCTIWCC; break;
- case AFCTIWZ: t = AFCTIWZCC; break;
- case AFDIV: t = AFDIVCC; break;
- case AFDIVS: t = AFDIVSCC; break;
- case AFMADD: t = AFMADDCC; break;
- case AFMADDS: t = AFMADDSCC; break;
- case AFMOVD: t = AFMOVDCC; break;
- case AFMSUB: t = AFMSUBCC; break;
- case AFMSUBS: t = AFMSUBSCC; break;
- case AFMUL: t = AFMULCC; break;
- case AFMULS: t = AFMULSCC; break;
- case AFNABS: t = AFNABSCC; break;
- case AFNEG: t = AFNEGCC; break;
- case AFNMADD: t = AFNMADDCC; break;
- case AFNMADDS: t = AFNMADDSCC; break;
- case AFNMSUB: t = AFNMSUBCC; break;
- case AFNMSUBS: t = AFNMSUBSCC; break;
- case AFRSP: t = AFRSPCC; break;
- case AFSUB: t = AFSUBCC; break;
- case AFSUBS: t = AFSUBSCC; break;
- case ACNTLZW: t = ACNTLZWCC; break;
- case AMTFSB0: t = AMTFSB0CC; break;
- case AMTFSB1: t = AMTFSB1CC; break;
-*/
- case AADD: t = AADDCC; break;
- case AADDV: t = AADDVCC; break;
- case AADDC: t = AADDCCC; break;
- case AADDCV: t = AADDCVCC; break;
- case AADDME: t = AADDMECC; break;
- case AADDMEV: t = AADDMEVCC; break;
- case AADDE: t = AADDECC; break;
- case AADDEV: t = AADDEVCC; break;
- case AADDZE: t = AADDZECC; break;
- case AADDZEV: t = AADDZEVCC; break;
- case AAND: t = AANDCC; break;
- case AANDN: t = AANDNCC; break;
- case ADIVW: t = ADIVWCC; break;
- case ADIVWV: t = ADIVWVCC; break;
- case ADIVWU: t = ADIVWUCC; break;
- case ADIVWUV: t = ADIVWUVCC; break;
- case ADIVD: t = ADIVDCC; break;
- case ADIVDV: t = ADIVDVCC; break;
- case ADIVDU: t = ADIVDUCC; break;
- case ADIVDUV: t = ADIVDUVCC; break;
- case AEQV: t = AEQVCC; break;
- case AEXTSB: t = AEXTSBCC; break;
- case AEXTSH: t = AEXTSHCC; break;
- case AEXTSW: t = AEXTSWCC; break;
- case AMULHW: t = AMULHWCC; break;
- case AMULHWU: t = AMULHWUCC; break;
- case AMULLW: t = AMULLWCC; break;
- case AMULLWV: t = AMULLWVCC; break;
- case AMULHD: t = AMULHDCC; break;
- case AMULHDU: t = AMULHDUCC; break;
- case AMULLD: t = AMULLDCC; break;
- case AMULLDV: t = AMULLDVCC; break;
- case ANAND: t = ANANDCC; break;
- case ANEG: t = ANEGCC; break;
- case ANEGV: t = ANEGVCC; break;
- case ANOR: t = ANORCC; break;
- case AOR: t = AORCC; break;
- case AORN: t = AORNCC; break;
- case AREM: t = AREMCC; break;
- case AREMV: t = AREMVCC; break;
- case AREMU: t = AREMUCC; break;
- case AREMUV: t = AREMUVCC; break;
- case AREMD: t = AREMDCC; break;
- case AREMDV: t = AREMDVCC; break;
- case AREMDU: t = AREMDUCC; break;
- case AREMDUV: t = AREMDUVCC; break;
- case ARLWMI: t = ARLWMICC; break;
- case ARLWNM: t = ARLWNMCC; break;
- case ASLW: t = ASLWCC; break;
- case ASRAW: t = ASRAWCC; break;
- case ASRW: t = ASRWCC; break;
- case ASLD: t = ASLDCC; break;
- case ASRAD: t = ASRADCC; break;
- case ASRD: t = ASRDCC; break;
- case ASUB: t = ASUBCC; break;
- case ASUBV: t = ASUBVCC; break;
- case ASUBC: t = ASUBCCC; break;
- case ASUBCV: t = ASUBCVCC; break;
- case ASUBME: t = ASUBMECC; break;
- case ASUBMEV: t = ASUBMEVCC; break;
- case ASUBE: t = ASUBECC; break;
- case ASUBEV: t = ASUBEVCC; break;
- case ASUBZE: t = ASUBZECC; break;
- case ASUBZEV: t = ASUBZEVCC; break;
- case AXOR: t = AXORCC; break;
- break;
- }
- if(debug['D'])
- print("cmp %P; %P -> ", p1, p);
- p1->as = t;
- if(debug['D'])
- print("%P\n", p1);
- excise(r);
- continue;
- }
- }
-}
-
-void
-excise(Reg *r)
-{
- Prog *p;
-
- p = r->prog;
- p->as = ANOP;
- p->from = zprog.from;
- p->from3 = zprog.from3;
- p->to = zprog.to;
- p->reg = zprog.reg; /**/
-}
-
-Reg*
-uniqp(Reg *r)
-{
- Reg *r1;
-
- r1 = r->p1;
- if(r1 == R) {
- r1 = r->p2;
- if(r1 == R || r1->p2link != R)
- return R;
- } else
- if(r->p2 != R)
- return R;
- return r1;
-}
-
-Reg*
-uniqs(Reg *r)
-{
- Reg *r1;
-
- r1 = r->s1;
- if(r1 == R) {
- r1 = r->s2;
- if(r1 == R)
- return R;
- } else
- if(r->s2 != R)
- return R;
- return r1;
-}
-
-/*
- * if the system forces R0 to be zero,
- * convert references to $0 to references to R0.
- */
-int
-regzer(Addr *a)
-{
- if(R0ISZERO) {
- if(a->type == D_CONST)
- if(a->sym == nil)
- if(a->offset == 0)
- return 1;
- if(a->type == D_REG)
- if(a->reg == REGZERO)
- return 1;
- }
- return 0;
-}
-
-int
-regtyp(Addr *a)
-{
-
- if(a->type == D_REG) {
- if(!R0ISZERO || a->reg != REGZERO)
- return 1;
- return 0;
- }
- if(a->type == D_FREG)
- return 1;
- return 0;
-}
-
-/*
- * the idea is to substitute
- * one register for another
- * from one MOV to another
- * MOV a, R0
- * ADD b, R0 / no use of R1
- * MOV R0, R1
- * would be converted to
- * MOV a, R1
- * ADD b, R1
- * MOV R1, R0
- * hopefully, then the former or latter MOV
- * will be eliminated by copy propagation.
- */
-int
-subprop(Reg *r0)
-{
- Prog *p;
- Addr *v1, *v2;
- Reg *r;
- int t;
-
- p = r0->prog;
- v1 = &p->from;
- if(!regtyp(v1))
- return 0;
- v2 = &p->to;
- if(!regtyp(v2))
- return 0;
- for(r=uniqp(r0); r!=R; r=uniqp(r)) {
- if(uniqs(r) == R)
- break;
- p = r->prog;
- switch(p->as) {
- case ABL:
- return 0;
-
- case AADD:
- case AADDC:
- case AADDCC:
- case AADDE:
- case AADDECC:
- case ASUB:
- case ASUBCC:
- case ASUBC:
- case ASUBCCC:
- case ASUBE:
- case ASUBECC:
- case ASLW:
- case ASRW:
- case ASRWCC:
- case ASRAW:
- case ASRAWCC:
- case ASLD:
- case ASRD:
- case ASRAD:
- case AOR:
- case AORCC:
- case AORN:
- case AORNCC:
- case AAND:
- case AANDCC:
- case AANDN:
- case AANDNCC:
- case ANAND:
- case ANANDCC:
- case ANOR:
- case ANORCC:
- case AXOR:
- case AXORCC:
- case AMULHW:
- case AMULHWU:
- case AMULLW:
- case AMULLD:
- case ADIVW:
- case ADIVWU:
- case ADIVD:
- case ADIVDU:
- case AREM:
- case AREMU:
- case AREMD:
- case AREMDU:
- case ARLWNM:
- case ARLWNMCC:
-
- case AFADD:
- case AFADDS:
- case AFSUB:
- case AFSUBS:
- case AFMUL:
- case AFMULS:
- case AFDIV:
- case AFDIVS:
- if(p->to.type == v1->type)
- if(p->to.reg == v1->reg) {
- if(p->reg == NREG)
- p->reg = p->to.reg;
- goto gotit;
- }
- break;
-
- case AADDME:
- case AADDMECC:
- case AADDZE:
- case AADDZECC:
- case ASUBME:
- case ASUBMECC:
- case ASUBZE:
- case ASUBZECC:
- case ANEG:
- case ANEGCC:
- case AFNEG:
- case AFNEGCC:
- case AFMOVS:
- case AFMOVD:
- case AMOVW:
- case AMOVD:
- if(p->to.type == v1->type)
- if(p->to.reg == v1->reg)
- goto gotit;
- break;
- }
- if(copyau(&p->from, v2) ||
- copyau1(p, v2) ||
- copyau(&p->to, v2))
- break;
- if(copysub(&p->from, v1, v2, 0) ||
- copysub1(p, v1, v2, 0) ||
- copysub(&p->to, v1, v2, 0))
- break;
- }
- return 0;
-
-gotit:
- copysub(&p->to, v1, v2, 1);
- if(debug['P']) {
- print("gotit: %D->%D\n%P", v1, v2, r->prog);
- if(p->from.type == v2->type)
- print(" excise");
- print("\n");
- }
- for(r=uniqs(r); r!=r0; r=uniqs(r)) {
- p = r->prog;
- copysub(&p->from, v1, v2, 1);
- copysub1(p, v1, v2, 1);
- copysub(&p->to, v1, v2, 1);
- if(debug['P'])
- print("%P\n", r->prog);
- }
- t = v1->reg;
- v1->reg = v2->reg;
- v2->reg = t;
- if(debug['P'])
- print("%P last\n", r->prog);
- return 1;
-}
-
-/*
- * The idea is to remove redundant copies.
- * v1->v2 F=0
- * (use v2 s/v2/v1/)*
- * set v1 F=1
- * use v2 return fail
- * -----------------
- * v1->v2 F=0
- * (use v2 s/v2/v1/)*
- * set v1 F=1
- * set v2 return success
- */
-int
-copyprop(Reg *r0)
-{
- Prog *p;
- Addr *v1, *v2;
- Reg *r;
-
- p = r0->prog;
- v1 = &p->from;
- v2 = &p->to;
- if(copyas(v1, v2))
- return 1;
- for(r=firstr; r!=R; r=r->link)
- r->active = 0;
- return copy1(v1, v2, r0->s1, 0);
-}
-
-int
-copy1(Addr *v1, Addr *v2, Reg *r, int f)
-{
- int t;
- Prog *p;
-
- if(r->active) {
- if(debug['P'])
- print("act set; return 1\n");
- return 1;
- }
- r->active = 1;
- if(debug['P'])
- print("copy %D->%D f=%d\n", v1, v2, f);
- for(; r != R; r = r->s1) {
- p = r->prog;
- if(debug['P'])
- print("%P", p);
- if(!f && uniqp(r) == R) {
- f = 1;
- if(debug['P'])
- print("; merge; f=%d", f);
- }
- t = copyu(p, v2, nil);
- switch(t) {
- case 2: /* rar, cant split */
- if(debug['P'])
- print("; %Drar; return 0\n", v2);
- return 0;
-
- case 3: /* set */
- if(debug['P'])
- print("; %Dset; return 1\n", v2);
- return 1;
-
- case 1: /* used, substitute */
- case 4: /* use and set */
- if(f) {
- if(!debug['P'])
- return 0;
- if(t == 4)
- print("; %Dused+set and f=%d; return 0\n", v2, f);
- else
- print("; %Dused and f=%d; return 0\n", v2, f);
- return 0;
- }
- if(copyu(p, v2, v1)) {
- if(debug['P'])
- print("; sub fail; return 0\n");
- return 0;
- }
- if(debug['P'])
- print("; sub%D/%D", v2, v1);
- if(t == 4) {
- if(debug['P'])
- print("; %Dused+set; return 1\n", v2);
- return 1;
- }
- break;
- }
- if(!f) {
- t = copyu(p, v1, nil);
- if(!f && (t == 2 || t == 3 || t == 4)) {
- f = 1;
- if(debug['P'])
- print("; %Dset and !f; f=%d", v1, f);
- }
- }
- if(debug['P'])
- print("\n");
- if(r->s2)
- if(!copy1(v1, v2, r->s2, f))
- return 0;
- }
- return 1;
-}
-
-/*
- * return
- * 1 if v only used (and substitute),
- * 2 if read-alter-rewrite
- * 3 if set
- * 4 if set and used
- * 0 otherwise (not touched)
- */
-int
-copyu(Prog *p, Addr *v, Addr *s)
-{
-
- switch(p->as) {
-
- default:
- if(debug['P'])
- print(" (\?\?\?)");
- return 2;
-
-
- case ANOP: /* read, write */
- case AMOVH:
- case AMOVHZ:
- case AMOVB:
- case AMOVBZ:
- case AMOVW:
- case AMOVWZ:
- case AMOVD:
-
- case ANEG:
- case ANEGCC:
- case AADDME:
- case AADDMECC:
- case AADDZE:
- case AADDZECC:
- case ASUBME:
- case ASUBMECC:
- case ASUBZE:
- case ASUBZECC:
-
- case AFCTIW:
- case AFCTIWZ:
- case AFMOVS:
- case AFMOVD:
- case AFRSP:
- case AFNEG:
- case AFNEGCC:
- if(s != nil) {
- if(copysub(&p->from, v, s, 1))
- return 1;
- if(!copyas(&p->to, v))
- if(copysub(&p->to, v, s, 1))
- return 1;
- return 0;
- }
- if(copyas(&p->to, v)) {
- if(copyau(&p->from, v))
- return 4;
- return 3;
- }
- if(copyau(&p->from, v))
- return 1;
- if(copyau(&p->to, v))
- return 1;
- return 0;
-
- case ARLWMI: /* read read rar */
- case ARLWMICC:
- if(copyas(&p->to, v))
- return 2;
- /* fall through */
-
- case AADD: /* read read write */
- case AADDC:
- case AADDE:
- case ASUB:
- case ASLW:
- case ASRW:
- case ASRAW:
- case ASLD:
- case ASRD:
- case ASRAD:
- case AOR:
- case AORCC:
- case AORN:
- case AORNCC:
- case AAND:
- case AANDCC:
- case AANDN:
- case AANDNCC:
- case ANAND:
- case ANANDCC:
- case ANOR:
- case ANORCC:
- case AXOR:
- case AMULHW:
- case AMULHWU:
- case AMULLW:
- case AMULLD:
- case ADIVW:
- case ADIVD:
- case ADIVWU:
- case ADIVDU:
- case AREM:
- case AREMU:
- case AREMD:
- case AREMDU:
- case ARLWNM:
- case ARLWNMCC:
-
- case AFADDS:
- case AFADD:
- case AFSUBS:
- case AFSUB:
- case AFMULS:
- case AFMUL:
- case AFDIVS:
- case AFDIV:
- if(s != nil) {
- if(copysub(&p->from, v, s, 1))
- return 1;
- if(copysub1(p, v, s, 1))
- return 1;
- if(!copyas(&p->to, v))
- if(copysub(&p->to, v, s, 1))
- return 1;
- return 0;
- }
- if(copyas(&p->to, v)) {
- if(p->reg == NREG)
- p->reg = p->to.reg;
- if(copyau(&p->from, v))
- return 4;
- if(copyau1(p, v))
- return 4;
- return 3;
- }
- if(copyau(&p->from, v))
- return 1;
- if(copyau1(p, v))
- return 1;
- if(copyau(&p->to, v))
- return 1;
- return 0;
-
- case ABEQ:
- case ABGT:
- case ABGE:
- case ABLT:
- case ABLE:
- case ABNE:
- case ABVC:
- case ABVS:
- break;
-
- case ACMP: /* read read */
- case ACMPU:
- case ACMPW:
- case ACMPWU:
- case AFCMPO:
- case AFCMPU:
- if(s != nil) {
- if(copysub(&p->from, v, s, 1))
- return 1;
- return copysub(&p->to, v, s, 1);
- }
- if(copyau(&p->from, v))
- return 1;
- if(copyau(&p->to, v))
- return 1;
- break;
-
- case ABR: /* funny */
- if(s != nil) {
- if(copysub(&p->to, v, s, 1))
- return 1;
- return 0;
- }
- if(copyau(&p->to, v))
- return 1;
- return 0;
-
- case ARETURN: /* funny */
- if(v->type == D_REG)
- if(v->reg == REGRET)
- return 2;
- if(v->type == D_FREG)
- if(v->reg == FREGRET)
- return 2;
-
- case ABL: /* funny */
- if(v->type == D_REG) {
- if(v->reg <= REGEXT && v->reg > exregoffset)
- return 2;
- if(v->reg == REGARG)
- return 2;
- }
- if(v->type == D_FREG) {
- if(v->reg <= FREGEXT && v->reg > exfregoffset)
- return 2;
- }
-
- if(s != nil) {
- if(copysub(&p->to, v, s, 1))
- return 1;
- return 0;
- }
- if(copyau(&p->to, v))
- return 4;
- return 3;
-
- case ATEXT: /* funny */
- if(v->type == D_REG)
- if(v->reg == REGARG)
- return 3;
- return 0;
- }
- return 0;
-}
-
-int
-a2type(Prog *p)
-{
-
- switch(p->as) {
- case AADD:
- case AADDC:
- case AADDCC:
- case AADDCCC:
- case AADDE:
- case AADDECC:
- case AADDME:
- case AADDMECC:
- case AADDZE:
- case AADDZECC:
- case ASUB:
- case ASUBC:
- case ASUBCC:
- case ASUBCCC:
- case ASUBE:
- case ASUBECC:
- case ASUBME:
- case ASUBMECC:
- case ASUBZE:
- case ASUBZECC:
- case ASLW:
- case ASLWCC:
- case ASRW:
- case ASRWCC:
- case ASRAW:
- case ASRAWCC:
- case ASLD:
- case ASLDCC:
- case ASRD:
- case ASRDCC:
- case ASRAD:
- case ASRADCC:
- case AOR:
- case AORCC:
- case AORN:
- case AORNCC:
- case AAND:
- case AANDCC:
- case AANDN:
- case AANDNCC:
- case AXOR:
- case AXORCC:
- case ANEG:
- case ANEGCC:
- case AMULHW:
- case AMULHWU:
- case AMULLW:
- case AMULLWCC:
- case ADIVW:
- case ADIVWCC:
- case ADIVWU:
- case ADIVWUCC:
- case AREM:
- case AREMCC:
- case AREMU:
- case AREMUCC:
- case AMULLD:
- case AMULLDCC:
- case ADIVD:
- case ADIVDCC:
- case ADIVDU:
- case ADIVDUCC:
- case AREMD:
- case AREMDCC:
- case AREMDU:
- case AREMDUCC:
- case ANAND:
- case ANANDCC:
- case ANOR:
- case ANORCC:
- case ARLWMI:
- case ARLWMICC:
- case ARLWNM:
- case ARLWNMCC:
- return D_REG;
-
- case AFADDS:
- case AFADDSCC:
- case AFADD:
- case AFADDCC:
- case AFSUBS:
- case AFSUBSCC:
- case AFSUB:
- case AFSUBCC:
- case AFMULS:
- case AFMULSCC:
- case AFMUL:
- case AFMULCC:
- case AFDIVS:
- case AFDIVSCC:
- case AFDIV:
- case AFDIVCC:
- case AFNEG:
- case AFNEGCC:
- return D_FREG;
- }
- return D_NONE;
-}
-
-/*
- * direct reference,
- * could be set/use depending on
- * semantics
- */
-int
-copyas(Addr *a, Addr *v)
-{
-
- if(regtyp(v))
- if(a->type == v->type)
- if(a->reg == v->reg)
- return 1;
- return 0;
-}
-
-/*
- * either direct or indirect
- */
-int
-copyau(Addr *a, Addr *v)
-{
-
- if(copyas(a, v))
- return 1;
- if(v->type == D_REG)
- if(a->type == D_OREG)
- if(v->reg == a->reg)
- return 1;
- return 0;
-}
-
-int
-copyau1(Prog *p, Addr *v)
-{
-
- if(regtyp(v))
- if(p->from.type == v->type || p->to.type == v->type)
- if(p->reg == v->reg) {
- if(a2type(p) != v->type)
- print("botch a2type %P\n", p);
- return 1;
- }
- return 0;
-}
-
-/*
- * substitute s for v in a
- * return failure to substitute
- */
-int
-copysub(Addr *a, Addr *v, Addr *s, int f)
-{
-
- if(f)
- if(copyau(a, v))
- a->reg = s->reg;
- return 0;
-}
-
-int
-copysub1(Prog *p1, Addr *v, Addr *s, int f)
-{
-
- if(f)
- if(copyau1(p1, v))
- p1->reg = s->reg;
- return 0;
-}
diff --git a/src/cmd/9c/reg.c b/src/cmd/9c/reg.c
deleted file mode 100644
index 81a7c7fe4..000000000
--- a/src/cmd/9c/reg.c
+++ /dev/null
@@ -1,1163 +0,0 @@
-// cmd/9c/reg.c from Vita Nuova.
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-
-Reg*
-rega(void)
-{
- Reg *r;
-
- r = freer;
- if(r == R) {
- r = alloc(sizeof(*r));
- } else
- freer = r->link;
-
- *r = zreg;
- return r;
-}
-
-int
-rcmp(const void *a1, const void *a2)
-{
- const Rgn *p1, *p2;
- int c1, c2;
-
- p1 = a1;
- p2 = a2;
- c1 = p2->cost;
- c2 = p1->cost;
- if(c1 -= c2)
- return c1;
- return p2->varno - p1->varno;
-}
-
-void
-regopt(Prog *p)
-{
- Reg *r, *r1, *r2;
- Prog *p1;
- int i, z;
- int32 initpc, val, npc;
- uint32 vreg;
- Bits bit;
- struct
- {
- int32 m;
- int32 c;
- Reg* p;
- } log5[6], *lp;
-
- firstr = R;
- lastr = R;
- nvar = 0;
- regbits = 0;
- for(z=0; z<BITS; z++) {
- externs.b[z] = 0;
- params.b[z] = 0;
- consts.b[z] = 0;
- addrs.b[z] = 0;
- }
-
- /*
- * pass 1
- * build aux data structure
- * allocate pcs
- * find use and set of variables
- */
- val = 5L * 5L * 5L * 5L * 5L;
- lp = log5;
- for(i=0; i<5; i++) {
- lp->m = val;
- lp->c = 0;
- lp->p = R;
- val /= 5L;
- lp++;
- }
- val = 0;
- for(; p != P; p = p->link) {
- switch(p->as) {
- case ADATA:
- case AGLOBL:
- case ANAME:
- case ASIGNAME:
- case AFUNCDATA:
- continue;
- }
- r = rega();
- if(firstr == R) {
- firstr = r;
- lastr = r;
- } else {
- lastr->link = r;
- r->p1 = lastr;
- lastr->s1 = r;
- lastr = r;
- }
- r->prog = p;
- r->pc = val;
- val++;
-
- lp = log5;
- for(i=0; i<5; i++) {
- lp->c--;
- if(lp->c <= 0) {
- lp->c = lp->m;
- if(lp->p != R)
- lp->p->log5 = r;
- lp->p = r;
- (lp+1)->c = 0;
- break;
- }
- lp++;
- }
-
- r1 = r->p1;
- if(r1 != R)
- switch(r1->prog->as) {
- case ARETURN:
- case ABR:
- case ARFI:
- case ARFCI:
- case ARFID:
- r->p1 = R;
- r1->s1 = R;
- }
-
- /*
- * left side always read
- */
- bit = mkvar(&p->from, p->as==AMOVW || p->as == AMOVWZ || p->as == AMOVD);
- for(z=0; z<BITS; z++)
- r->use1.b[z] |= bit.b[z];
-
- /*
- * right side depends on opcode
- */
- bit = mkvar(&p->to, 0);
- if(bany(&bit))
- switch(p->as) {
- default:
- diag(Z, "reg: unknown asop: %A", p->as);
- break;
-
- /*
- * right side write
- */
- case ANOP:
- case AMOVB:
- case AMOVBU:
- case AMOVBZ:
- case AMOVBZU:
- case AMOVH:
- case AMOVHBR:
- case AMOVWBR:
- case AMOVHU:
- case AMOVHZ:
- case AMOVHZU:
- case AMOVW:
- case AMOVWU:
- case AMOVWZ:
- case AMOVWZU:
- case AMOVD:
- case AMOVDU:
- case AFMOVD:
- case AFMOVDCC:
- case AFMOVDU:
- case AFMOVS:
- case AFMOVSU:
- case AFRSP:
- for(z=0; z<BITS; z++)
- r->set.b[z] |= bit.b[z];
- break;
-
- /*
- * funny
- */
- case ABL:
- for(z=0; z<BITS; z++)
- addrs.b[z] |= bit.b[z];
- break;
- }
- }
- if(firstr == R)
- return;
- initpc = pc - val;
- npc = val;
-
- /*
- * pass 2
- * turn branch references to pointers
- * build back pointers
- */
- for(r = firstr; r != R; r = r->link) {
- p = r->prog;
- if(p->to.type == D_BRANCH) {
- val = p->to.offset - initpc;
- r1 = firstr;
- while(r1 != R) {
- r2 = r1->log5;
- if(r2 != R && val >= r2->pc) {
- r1 = r2;
- continue;
- }
- if(r1->pc == val)
- break;
- r1 = r1->link;
- }
- if(r1 == R) {
- nearln = p->lineno;
- diag(Z, "ref not found\n%P", p);
- continue;
- }
- if(r1 == r) {
- nearln = p->lineno;
- diag(Z, "ref to self\n%P", p);
- continue;
- }
- r->s2 = r1;
- r->p2link = r1->p2;
- r1->p2 = r;
- }
- }
- if(debug['R']) {
- p = firstr->prog;
- print("\n%L %D\n", p->lineno, &p->from);
- }
-
- /*
- * pass 2.5
- * find looping structure
- */
- for(r = firstr; r != R; r = r->link)
- r->active = 0;
- change = 0;
- loopit(firstr, npc);
- if(debug['R'] && debug['v']) {
- print("\nlooping structure:\n");
- for(r = firstr; r != R; r = r->link) {
- print("%ld:%P", r->loop, r->prog);
- for(z=0; z<BITS; z++)
- bit.b[z] = r->use1.b[z] |
- r->use2.b[z] | r->set.b[z];
- if(bany(&bit)) {
- print("\t");
- if(bany(&r->use1))
- print(" u1=%B", r->use1);
- if(bany(&r->use2))
- print(" u2=%B", r->use2);
- if(bany(&r->set))
- print(" st=%B", r->set);
- }
- print("\n");
- }
- }
-
- /*
- * pass 3
- * iterate propagating usage
- * back until flow graph is complete
- */
-loop1:
- change = 0;
- for(r = firstr; r != R; r = r->link)
- r->active = 0;
- for(r = firstr; r != R; r = r->link)
- if(r->prog->as == ARETURN)
- prop(r, zbits, zbits);
-loop11:
- /* pick up unreachable code */
- i = 0;
- for(r = firstr; r != R; r = r1) {
- r1 = r->link;
- if(r1 && r1->active && !r->active) {
- prop(r, zbits, zbits);
- i = 1;
- }
- }
- if(i)
- goto loop11;
- if(change)
- goto loop1;
-
-
- /*
- * pass 4
- * iterate propagating register/variable synchrony
- * forward until graph is complete
- */
-loop2:
- change = 0;
- for(r = firstr; r != R; r = r->link)
- r->active = 0;
- synch(firstr, zbits);
- if(change)
- goto loop2;
-
-
- /*
- * pass 5
- * isolate regions
- * calculate costs (paint1)
- */
- r = firstr;
- if(r) {
- for(z=0; z<BITS; z++)
- bit.b[z] = (r->refahead.b[z] | r->calahead.b[z]) &
- ~(externs.b[z] | params.b[z] | addrs.b[z] | consts.b[z]);
- if(bany(&bit)) {
- nearln = r->prog->lineno;
- warn(Z, "used and not set: %B", bit);
- if(debug['R'] && !debug['w'])
- print("used and not set: %B\n", bit);
- }
- }
- if(debug['R'] && debug['v'])
- print("\nprop structure:\n");
- for(r = firstr; r != R; r = r->link)
- r->act = zbits;
- rgp = region;
- nregion = 0;
- for(r = firstr; r != R; r = r->link) {
- if(debug['R'] && debug['v'])
- print("%P\n set = %B; rah = %B; cal = %B\n",
- r->prog, r->set, r->refahead, r->calahead);
- for(z=0; z<BITS; z++)
- bit.b[z] = r->set.b[z] &
- ~(r->refahead.b[z] | r->calahead.b[z] | addrs.b[z]);
- if(bany(&bit)) {
- nearln = r->prog->lineno;
- warn(Z, "set and not used: %B", bit);
- if(debug['R'])
- print("set an not used: %B\n", bit);
- excise(r);
- }
- for(z=0; z<BITS; z++)
- bit.b[z] = LOAD(r) & ~(r->act.b[z] | addrs.b[z]);
- while(bany(&bit)) {
- i = bnum(bit);
- rgp->enter = r;
- rgp->varno = i;
- change = 0;
- if(debug['R'] && debug['v'])
- print("\n");
- paint1(r, i);
- bit.b[i/32] &= ~(1L<<(i%32));
- if(change <= 0) {
- if(debug['R'])
- print("%L$%d: %B\n",
- r->prog->lineno, change, blsh(i));
- continue;
- }
- rgp->cost = change;
- nregion++;
- if(nregion >= NRGN)
- fatal(Z, "too many regions");
- rgp++;
- }
- }
- qsort(region, nregion, sizeof(region[0]), rcmp);
-
- /*
- * pass 6
- * determine used registers (paint2)
- * replace code (paint3)
- */
- rgp = region;
- for(i=0; i<nregion; i++) {
- bit = blsh(rgp->varno);
- vreg = paint2(rgp->enter, rgp->varno);
- vreg = allreg(vreg, rgp);
- if(debug['R']) {
- if(rgp->regno >= NREG)
- print("%L$%d F%d: %B\n",
- rgp->enter->prog->lineno,
- rgp->cost,
- rgp->regno-NREG,
- bit);
- else
- print("%L$%d R%d: %B\n",
- rgp->enter->prog->lineno,
- rgp->cost,
- rgp->regno,
- bit);
- }
- if(rgp->regno != 0)
- paint3(rgp->enter, rgp->varno, vreg, rgp->regno);
- rgp++;
- }
- /*
- * pass 7
- * peep-hole on basic block
- */
- if(!debug['R'] || debug['P'])
- peep();
-
- /*
- * pass 8
- * recalculate pc
- */
- val = initpc;
- for(r = firstr; r != R; r = r1) {
- r->pc = val;
- p = r->prog;
- p1 = P;
- r1 = r->link;
- if(r1 != R)
- p1 = r1->prog;
- for(; p != p1; p = p->link) {
- switch(p->as) {
- default:
- val++;
- break;
-
- case ANOP:
- case ADATA:
- case AGLOBL:
- case ANAME:
- case ASIGNAME:
- case AFUNCDATA:
- break;
- }
- }
- }
- pc = val;
-
- /*
- * fix up branches
- */
- if(debug['R'])
- if(bany(&addrs))
- print("addrs: %B\n", addrs);
-
- r1 = 0; /* set */
- for(r = firstr; r != R; r = r->link) {
- p = r->prog;
- if(p->to.type == D_BRANCH) {
- p->to.offset = r->s2->pc;
- p->to.u.branch = r->s2->prog;
- }
- r1 = r;
- }
-
- /*
- * last pass
- * eliminate nops
- * free aux structures
- */
- for(p = firstr->prog; p != P; p = p->link){
- while(p->link && p->link->as == ANOP)
- p->link = p->link->link;
- }
- if(r1 != R) {
- r1->link = freer;
- freer = firstr;
- }
-}
-
-/*
- * add mov b,rn
- * just after r
- */
-void
-addmove(Reg *r, int bn, int rn, int f)
-{
- Prog *p, *p1;
- Addr *a;
- Var *v;
-
- p1 = alloc(sizeof(*p1));
- *p1 = zprog;
- p = r->prog;
-
- p1->link = p->link;
- p->link = p1;
- p1->lineno = p->lineno;
-
- v = var + bn;
-
- a = &p1->to;
- a->sym = v->sym;
- a->name = v->name;
- a->offset = v->offset;
- a->etype = v->etype;
- a->type = D_OREG;
- if(a->etype == TARRAY || a->sym == nil)
- a->type = D_CONST;
-
- p1->as = AMOVW;
- if(v->etype == TCHAR || v->etype == TUCHAR)
- p1->as = AMOVB;
- if(v->etype == TSHORT || v->etype == TUSHORT)
- p1->as = AMOVH;
- if(v->etype == TVLONG || v->etype == TUVLONG || v->etype == TIND)
- p1->as = AMOVD;
- if(v->etype == TFLOAT)
- p1->as = AFMOVS;
- if(v->etype == TDOUBLE)
- p1->as = AFMOVD;
-
- p1->from.type = D_REG;
- p1->from.reg = rn;
- if(rn >= NREG) {
- p1->from.type = D_FREG;
- p1->from.reg = rn-NREG;
- }
- if(!f) {
- p1->from = *a;
- *a = zprog.from;
- a->type = D_REG;
- a->reg = rn;
- if(rn >= NREG) {
- a->type = D_FREG;
- a->reg = rn-NREG;
- }
- if(v->etype == TUCHAR)
- p1->as = AMOVBZ;
- if(v->etype == TUSHORT)
- p1->as = AMOVHZ;
- if(v->etype == TUINT || v->etype == TULONG)
- p1->as = AMOVWZ;
- }
- if(debug['R'])
- print("%P\t.a%P\n", p, p1);
-}
-
-Bits
-mkvar(Addr *a, int docon)
-{
- Var *v;
- int i, t, n, et, z;
- int64 o;
- Bits bit;
- LSym *s;
-
- t = a->type;
- if(t == D_REG && a->reg != NREG)
- regbits |= RtoB(a->reg);
- if(t == D_FREG && a->reg != NREG)
- regbits |= FtoB(a->reg);
- s = a->sym;
- o = a->offset;
- et = a->etype;
- if(s == nil) {
- if(t != D_CONST || !docon || a->reg != NREG)
- goto none;
- et = TLONG;
- }
- if(t == D_CONST) {
- if(s == nil && sval(o))
- goto none;
- }
- n = a->name;
- v = var;
- for(i=0; i<nvar; i++) {
- if(s == v->sym)
- if(n == v->name)
- if(o == v->offset)
- goto out;
- v++;
- }
- if(s)
- if(s->name[0] == '.')
- goto none;
- if(nvar >= NVAR)
- fatal(Z, "variable not optimized: %s", s->name);
- i = nvar;
- nvar++;
- v = &var[i];
- v->sym = s;
- v->offset = o;
- v->etype = et;
- v->name = n;
- if(debug['R'])
- print("bit=%2d et=%2d %D\n", i, et, a);
-out:
- bit = blsh(i);
- if(n == D_EXTERN || n == D_STATIC)
- for(z=0; z<BITS; z++)
- externs.b[z] |= bit.b[z];
- if(n == D_PARAM)
- for(z=0; z<BITS; z++)
- params.b[z] |= bit.b[z];
- if(v->etype != et || !(typechlpfd[et] || typev[et])) /* funny punning */
- for(z=0; z<BITS; z++)
- addrs.b[z] |= bit.b[z];
- if(t == D_CONST) {
- if((int32)o != o)
- v->etype = TVLONG;
- if(s == nil) {
- for(z=0; z<BITS; z++)
- consts.b[z] |= bit.b[z];
- return bit;
- }
- if(et != TARRAY)
- for(z=0; z<BITS; z++)
- addrs.b[z] |= bit.b[z];
- for(z=0; z<BITS; z++)
- params.b[z] |= bit.b[z];
- return bit;
- }
- if(t == D_OREG)
- return bit;
-
-none:
- return zbits;
-}
-
-void
-prop(Reg *r, Bits ref, Bits cal)
-{
- Reg *r1, *r2;
- int z;
-
- for(r1 = r; r1 != R; r1 = r1->p1) {
- for(z=0; z<BITS; z++) {
- ref.b[z] |= r1->refahead.b[z];
- if(ref.b[z] != r1->refahead.b[z]) {
- r1->refahead.b[z] = ref.b[z];
- change++;
- }
- cal.b[z] |= r1->calahead.b[z];
- if(cal.b[z] != r1->calahead.b[z]) {
- r1->calahead.b[z] = cal.b[z];
- change++;
- }
- }
- switch(r1->prog->as) {
- case ABL:
- for(z=0; z<BITS; z++) {
- cal.b[z] |= ref.b[z] | externs.b[z];
- ref.b[z] = 0;
- }
- break;
-
- case ATEXT:
- for(z=0; z<BITS; z++) {
- cal.b[z] = 0;
- ref.b[z] = 0;
- }
- break;
-
- case ARETURN:
- for(z=0; z<BITS; z++) {
- cal.b[z] = externs.b[z];
- ref.b[z] = 0;
- }
- }
- for(z=0; z<BITS; z++) {
- ref.b[z] = (ref.b[z] & ~r1->set.b[z]) |
- r1->use1.b[z] | r1->use2.b[z];
- cal.b[z] &= ~(r1->set.b[z] | r1->use1.b[z] | r1->use2.b[z]);
- r1->refbehind.b[z] = ref.b[z];
- r1->calbehind.b[z] = cal.b[z];
- }
- if(r1->active)
- break;
- r1->active = 1;
- }
- for(; r != r1; r = r->p1)
- for(r2 = r->p2; r2 != R; r2 = r2->p2link)
- prop(r2, r->refbehind, r->calbehind);
-}
-
-/*
- * find looping structure
- *
- * 1) find reverse postordering
- * 2) find approximate dominators,
- * the actual dominators if the flow graph is reducible
- * otherwise, dominators plus some other non-dominators.
- * See Matthew S. Hecht and Jeffrey D. Ullman,
- * "Analysis of a Simple Algorithm for Global Data Flow Problems",
- * Conf. Record of ACM Symp. on Principles of Prog. Langs, Boston, Massachusetts,
- * Oct. 1-3, 1973, pp. 207-217.
- * 3) find all nodes with a predecessor dominated by the current node.
- * such a node is a loop head.
- * recursively, all preds with a greater rpo number are in the loop
- */
-int32
-postorder(Reg *r, Reg **rpo2r, int32 n)
-{
- Reg *r1;
-
- r->rpo = 1;
- r1 = r->s1;
- if(r1 && !r1->rpo)
- n = postorder(r1, rpo2r, n);
- r1 = r->s2;
- if(r1 && !r1->rpo)
- n = postorder(r1, rpo2r, n);
- rpo2r[n] = r;
- n++;
- return n;
-}
-
-int32
-rpolca(int32 *idom, int32 rpo1, int32 rpo2)
-{
- int32 t;
-
- if(rpo1 == -1)
- return rpo2;
- while(rpo1 != rpo2){
- if(rpo1 > rpo2){
- t = rpo2;
- rpo2 = rpo1;
- rpo1 = t;
- }
- while(rpo1 < rpo2){
- t = idom[rpo2];
- if(t >= rpo2)
- fatal(Z, "bad idom");
- rpo2 = t;
- }
- }
- return rpo1;
-}
-
-int
-doms(int32 *idom, int32 r, int32 s)
-{
- while(s > r)
- s = idom[s];
- return s == r;
-}
-
-int
-loophead(int32 *idom, Reg *r)
-{
- int32 src;
-
- src = r->rpo;
- if(r->p1 != R && doms(idom, src, r->p1->rpo))
- return 1;
- for(r = r->p2; r != R; r = r->p2link)
- if(doms(idom, src, r->rpo))
- return 1;
- return 0;
-}
-
-void
-loopmark(Reg **rpo2r, int32 head, Reg *r)
-{
- if(r->rpo < head || r->active == head)
- return;
- r->active = head;
- r->loop += LOOP;
- if(r->p1 != R)
- loopmark(rpo2r, head, r->p1);
- for(r = r->p2; r != R; r = r->p2link)
- loopmark(rpo2r, head, r);
-}
-
-void
-loopit(Reg *r, int32 nr)
-{
- Reg *r1;
- int32 i, d, me;
-
- if(nr > maxnr) {
- rpo2r = alloc(nr * sizeof(Reg*));
- idom = alloc(nr * sizeof(int32));
- maxnr = nr;
- }
-
- d = postorder(r, rpo2r, 0);
- if(d > nr)
- fatal(Z, "too many reg nodes");
- nr = d;
- for(i = 0; i < nr / 2; i++){
- r1 = rpo2r[i];
- rpo2r[i] = rpo2r[nr - 1 - i];
- rpo2r[nr - 1 - i] = r1;
- }
- for(i = 0; i < nr; i++)
- rpo2r[i]->rpo = i;
-
- idom[0] = 0;
- for(i = 0; i < nr; i++){
- r1 = rpo2r[i];
- me = r1->rpo;
- d = -1;
- if(r1->p1 != R && r1->p1->rpo < me)
- d = r1->p1->rpo;
- for(r1 = r1->p2; r1 != nil; r1 = r1->p2link)
- if(r1->rpo < me)
- d = rpolca(idom, d, r1->rpo);
- idom[i] = d;
- }
-
- for(i = 0; i < nr; i++){
- r1 = rpo2r[i];
- r1->loop++;
- if(r1->p2 != R && loophead(idom, r1))
- loopmark(rpo2r, i, r1);
- }
-}
-
-void
-synch(Reg *r, Bits dif)
-{
- Reg *r1;
- int z;
-
- for(r1 = r; r1 != R; r1 = r1->s1) {
- for(z=0; z<BITS; z++) {
- dif.b[z] = (dif.b[z] &
- ~(~r1->refbehind.b[z] & r1->refahead.b[z])) |
- r1->set.b[z] | r1->regdiff.b[z];
- if(dif.b[z] != r1->regdiff.b[z]) {
- r1->regdiff.b[z] = dif.b[z];
- change++;
- }
- }
- if(r1->active)
- break;
- r1->active = 1;
- for(z=0; z<BITS; z++)
- dif.b[z] &= ~(~r1->calbehind.b[z] & r1->calahead.b[z]);
- if(r1->s2 != R)
- synch(r1->s2, dif);
- }
-}
-
-uint32
-allreg(uint32 b, Rgn *r)
-{
- Var *v;
- int i;
-
- v = var + r->varno;
- r->regno = 0;
- switch(v->etype) {
-
- default:
- diag(Z, "unknown etype %d/%d", bitno(b), v->etype);
- break;
-
- case TCHAR:
- case TUCHAR:
- case TSHORT:
- case TUSHORT:
- case TINT:
- case TUINT:
- case TLONG:
- case TULONG:
- case TIND:
- case TVLONG:
- case TUVLONG:
- case TARRAY:
- i = BtoR(~b);
- if(i && r->cost > 0) {
- r->regno = i;
- return RtoB(i);
- }
- break;
-
- case TDOUBLE:
- case TFLOAT:
- i = BtoF(~b);
- if(i && r->cost > 0) {
- r->regno = i+NREG;
- return FtoB(i);
- }
- break;
- }
- return 0;
-}
-
-void
-paint1(Reg *r, int bn)
-{
- Reg *r1;
- Prog *p;
- int z;
- uint32 bb;
-
- z = bn/32;
- bb = 1L<<(bn%32);
- if(r->act.b[z] & bb)
- return;
- for(;;) {
- if(!(r->refbehind.b[z] & bb))
- break;
- r1 = r->p1;
- if(r1 == R)
- break;
- if(!(r1->refahead.b[z] & bb))
- break;
- if(r1->act.b[z] & bb)
- break;
- r = r1;
- }
-
- if(LOAD(r) & ~(r->set.b[z]&~(r->use1.b[z]|r->use2.b[z])) & bb) {
- change -= CLOAD * r->loop;
- if(debug['R'] && debug['v'])
- print("%ld%P\tld %B $%d\n", r->loop,
- r->prog, blsh(bn), change);
- }
- for(;;) {
- r->act.b[z] |= bb;
- p = r->prog;
-
- if(r->use1.b[z] & bb) {
- change += CREF * r->loop;
- if(p->to.type == D_FREG && (p->as == AMOVW || p->as == AMOVD))
- change = -CINF; /* cant go Rreg to Freg */
- if(debug['R'] && debug['v'])
- print("%ld%P\tu1 %B $%d\n", r->loop,
- p, blsh(bn), change);
- }
-
- if((r->use2.b[z]|r->set.b[z]) & bb) {
- change += CREF * r->loop;
- if(p->from.type == D_FREG && (p->as == AMOVW || p->as == AMOVD))
- change = -CINF; /* cant go Rreg to Freg */
- if(debug['R'] && debug['v'])
- print("%ld%P\tu2 %B $%d\n", r->loop,
- p, blsh(bn), change);
- }
-
- if(STORE(r) & r->regdiff.b[z] & bb) {
- change -= CLOAD * r->loop;
- if(debug['R'] && debug['v'])
- print("%ld%P\tst %B $%d\n", r->loop,
- p, blsh(bn), change);
- }
-
- if(r->refbehind.b[z] & bb)
- for(r1 = r->p2; r1 != R; r1 = r1->p2link)
- if(r1->refahead.b[z] & bb)
- paint1(r1, bn);
-
- if(!(r->refahead.b[z] & bb))
- break;
- r1 = r->s2;
- if(r1 != R)
- if(r1->refbehind.b[z] & bb)
- paint1(r1, bn);
- r = r->s1;
- if(r == R)
- break;
- if(r->act.b[z] & bb)
- break;
- if(!(r->refbehind.b[z] & bb))
- break;
- }
-}
-
-uint32
-paint2(Reg *r, int bn)
-{
- Reg *r1;
- int z;
- uint32 bb, vreg;
-
- z = bn/32;
- bb = 1L << (bn%32);
- vreg = regbits;
- if(!(r->act.b[z] & bb))
- return vreg;
- for(;;) {
- if(!(r->refbehind.b[z] & bb))
- break;
- r1 = r->p1;
- if(r1 == R)
- break;
- if(!(r1->refahead.b[z] & bb))
- break;
- if(!(r1->act.b[z] & bb))
- break;
- r = r1;
- }
- for(;;) {
- r->act.b[z] &= ~bb;
-
- vreg |= r->regu;
-
- if(r->refbehind.b[z] & bb)
- for(r1 = r->p2; r1 != R; r1 = r1->p2link)
- if(r1->refahead.b[z] & bb)
- vreg |= paint2(r1, bn);
-
- if(!(r->refahead.b[z] & bb))
- break;
- r1 = r->s2;
- if(r1 != R)
- if(r1->refbehind.b[z] & bb)
- vreg |= paint2(r1, bn);
- r = r->s1;
- if(r == R)
- break;
- if(!(r->act.b[z] & bb))
- break;
- if(!(r->refbehind.b[z] & bb))
- break;
- }
- return vreg;
-}
-
-void
-paint3(Reg *r, int bn, int32 rb, int rn)
-{
- Reg *r1;
- Prog *p;
- int z;
- uint32 bb;
-
- z = bn/32;
- bb = 1L << (bn%32);
- if(r->act.b[z] & bb)
- return;
- for(;;) {
- if(!(r->refbehind.b[z] & bb))
- break;
- r1 = r->p1;
- if(r1 == R)
- break;
- if(!(r1->refahead.b[z] & bb))
- break;
- if(r1->act.b[z] & bb)
- break;
- r = r1;
- }
-
- if(LOAD(r) & ~(r->set.b[z] & ~(r->use1.b[z]|r->use2.b[z])) & bb)
- addmove(r, bn, rn, 0);
- for(;;) {
- r->act.b[z] |= bb;
- p = r->prog;
-
- if(r->use1.b[z] & bb) {
- if(debug['R'])
- print("%P", p);
- addreg(&p->from, rn);
- if(debug['R'])
- print("\t.c%P\n", p);
- }
- if((r->use2.b[z]|r->set.b[z]) & bb) {
- if(debug['R'])
- print("%P", p);
- addreg(&p->to, rn);
- if(debug['R'])
- print("\t.c%P\n", p);
- }
-
- if(STORE(r) & r->regdiff.b[z] & bb)
- addmove(r, bn, rn, 1);
- r->regu |= rb;
-
- if(r->refbehind.b[z] & bb)
- for(r1 = r->p2; r1 != R; r1 = r1->p2link)
- if(r1->refahead.b[z] & bb)
- paint3(r1, bn, rb, rn);
-
- if(!(r->refahead.b[z] & bb))
- break;
- r1 = r->s2;
- if(r1 != R)
- if(r1->refbehind.b[z] & bb)
- paint3(r1, bn, rb, rn);
- r = r->s1;
- if(r == R)
- break;
- if(r->act.b[z] & bb)
- break;
- if(!(r->refbehind.b[z] & bb))
- break;
- }
-}
-
-void
-addreg(Addr *a, int rn)
-{
-
- a->sym = 0;
- a->name = D_NONE;
- a->type = D_REG;
- a->reg = rn;
- if(rn >= NREG) {
- a->type = D_FREG;
- a->reg = rn-NREG;
- }
-}
-
-/*
- * track register variables including external registers:
- * bit reg
- * 0 R7
- * 1 R8
- * ... ...
- * 21 R28
- */
-int32
-RtoB(int r)
-{
-
- if(r >= REGMIN && r <= REGMAX)
- return 1L << (r-REGMIN);
- return 0;
-}
-
-int
-BtoR(int32 b)
-{
- b &= 0x001fffffL;
- if(b == 0)
- return 0;
- return bitno(b) + REGMIN;
-}
-
-/*
- * bit reg
- * 22 F17
- * 23 F18
- * ... ...
- * 31 F26
- */
-int32
-FtoB(int f)
-{
- if(f < FREGMIN || f > FREGEXT)
- return 0;
- return 1L << (f - FREGMIN + 22);
-}
-
-int
-BtoF(int32 b)
-{
-
- b &= 0xffc00000L;
- if(b == 0)
- return 0;
- return bitno(b) - 22 + FREGMIN;
-}
diff --git a/src/cmd/9c/sgen.c b/src/cmd/9c/sgen.c
deleted file mode 100644
index b03c17267..000000000
--- a/src/cmd/9c/sgen.c
+++ /dev/null
@@ -1,291 +0,0 @@
-// cmd/9c/sgen.c from Vita Nuova.
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-
-Prog*
-gtext(Sym *s, int32 stkoff)
-{
- vlong v;
-
- v = ((uvlong)argsize(1) << 32) | (stkoff & 0xffffffff);
- if((textflag & NOSPLIT) && stkoff >= 128)
- yyerror("stack frame too large for NOSPLIT function");
-
- gpseudo(ATEXT, s, nodgconst(v, types[TVLONG]));
- return p;
-}
-
-
-void
-noretval(int n)
-{
-
- if(n & 1) {
- gins(ANOP, Z, Z);
- p->to.type = D_REG;
- p->to.reg = REGRET;
- }
- if(n & 2) {
- gins(ANOP, Z, Z);
- p->to.type = D_FREG;
- p->to.reg = FREGRET;
- }
-}
-
-/*
- * calculate addressability as follows
- * CONST ==> 20 $value
- * NAME ==> 10 name
- * REGISTER ==> 11 register
- * INDREG ==> 12 *[(reg)+offset]
- * &10 ==> 2 $name
- * ADD(2, 20) ==> 2 $name+offset
- * ADD(3, 20) ==> 3 $(reg)+offset
- * &12 ==> 3 $(reg)+offset
- * *11 ==> 11 ??
- * *2 ==> 10 name
- * *3 ==> 12 *(reg)+offset
- * calculate complexity (number of registers)
- */
-void
-xcom(Node *n)
-{
- Node *l, *r;
- int v;
-
- if(n == Z)
- return;
- l = n->left;
- r = n->right;
- n->addable = 0;
- n->complex = 0;
- switch(n->op) {
- case OCONST:
- n->addable = 20;
- return;
-
- case OREGISTER:
- n->addable = 11;
- return;
-
- case OINDREG:
- n->addable = 12;
- return;
-
- case ONAME:
- n->addable = 10;
- return;
-
- case OADDR:
- xcom(l);
- if(l->addable == 10)
- n->addable = 2;
- if(l->addable == 12)
- n->addable = 3;
- break;
-
- case OIND:
- xcom(l);
- if(l->addable == 11)
- n->addable = 12;
- if(l->addable == 3)
- n->addable = 12;
- if(l->addable == 2)
- n->addable = 10;
- break;
-
- case OADD:
- xcom(l);
- xcom(r);
- if(l->addable == 20) {
- if(r->addable == 2)
- n->addable = 2;
- if(r->addable == 3)
- n->addable = 3;
- }
- if(r->addable == 20) {
- if(l->addable == 2)
- n->addable = 2;
- if(l->addable == 3)
- n->addable = 3;
- }
- break;
-
- case OASMUL:
- case OASLMUL:
- xcom(l);
- xcom(r);
- v = vlog(r);
- if(v >= 0) {
- n->op = OASASHL;
- r->vconst = v;
- r->type = types[TINT];
- }
- break;
-
- case OMUL:
- case OLMUL:
- xcom(l);
- xcom(r);
- v = vlog(r);
- if(v >= 0) {
- n->op = OASHL;
- r->vconst = v;
- r->type = types[TINT];
- }
- v = vlog(l);
- if(v >= 0) {
- n->op = OASHL;
- n->left = r;
- n->right = l;
- r = l;
- l = n->left;
- r->vconst = v;
- r->type = types[TINT];
- simplifyshift(n);
- }
- break;
-
- case OASLDIV:
- xcom(l);
- xcom(r);
- v = vlog(r);
- if(v >= 0) {
- n->op = OASLSHR;
- r->vconst = v;
- r->type = types[TINT];
- }
- break;
-
- case OLDIV:
- xcom(l);
- xcom(r);
- v = vlog(r);
- if(v >= 0) {
- n->op = OLSHR;
- r->vconst = v;
- r->type = types[TINT];
- simplifyshift(n);
- }
- break;
-
- case OASLMOD:
- xcom(l);
- xcom(r);
- v = vlog(r);
- if(v >= 0) {
- n->op = OASAND;
- r->vconst--;
- }
- break;
-
- case OLMOD:
- xcom(l);
- xcom(r);
- v = vlog(r);
- if(v >= 0) {
- n->op = OAND;
- r->vconst--;
- }
- break;
-
- case OLSHR:
- case OASHL:
- case OASHR:
- xcom(l);
- xcom(r);
- simplifyshift(n);
- break;
-
- default:
- if(l != Z)
- xcom(l);
- if(r != Z)
- xcom(r);
- break;
- }
- if(n->addable >= 10)
- return;
- if(l != Z)
- n->complex = l->complex;
- if(r != Z) {
- if(r->complex == n->complex)
- n->complex = r->complex+1;
- else
- if(r->complex > n->complex)
- n->complex = r->complex;
- }
- if(n->complex == 0)
- n->complex++;
-
-// if(com64(n))
-// return;
-
- switch(n->op) {
-
- case OFUNC:
- n->complex = FNX;
- break;
-
- case OEQ:
- case ONE:
- case OLE:
- case OLT:
- case OGE:
- case OGT:
- case OHI:
- case OHS:
- case OLO:
- case OLS:
- /*
- * immediate operators, make const on right
- */
- if(l->op == OCONST) {
- n->left = r;
- n->right = l;
- n->op = invrel[relindex(n->op)];
- }
- break;
-
- case OADD:
- case OXOR:
- case OAND:
- case OOR:
- /*
- * immediate operators, make const on right
- */
- if(l->op == OCONST) {
- n->left = r;
- n->right = l;
- }
- break;
- }
-}
-
diff --git a/src/cmd/9c/swt.c b/src/cmd/9c/swt.c
deleted file mode 100644
index a63db60b2..000000000
--- a/src/cmd/9c/swt.c
+++ /dev/null
@@ -1,407 +0,0 @@
-// cmd/9c/swt.c from Vita Nuova.
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-
-void
-swit1(C1 *q, int nc, int32 def, Node *n)
-{
- Node tn, nod;
-
- regalloc(&nod, n, Z);
- /* always signed */
- if(typev[n->type->etype])
- nod.type = types[TVLONG];
- else
- nod.type = types[TLONG];
- cgen(n, &nod);
- regalloc(&tn, &regnode, Z);
- swit2(q, nc, def, &nod, &tn);
- regfree(&tn);
- regfree(&nod);
-}
-
-void
-swit2(C1 *q, int nc, int32 def, Node *n, Node *tn)
-{
- C1 *r;
- int i;
- Prog *sp;
-
- if(nc < 5) {
- for(i=0; i<nc; i++) {
- if(sval(q->val)) {
- gopcode(OEQ, n, Z, nodconst(q->val));
- } else {
- gopcode(OSUB, nodconst(q->val), n, tn);
- gopcode(OEQ, tn, Z, nodconst(0));
- }
- patch(p, q->label);
- q++;
- }
- gbranch(OGOTO);
- patch(p, def);
- return;
- }
- i = nc / 2;
- r = q+i;
- if(sval(r->val)) {
- gopcode(OGT, n, Z, nodconst(r->val));
- sp = p;
- } else {
- gopcode(OSUB, nodconst(r->val), n, tn);
- gopcode(OGT, tn, Z, nodconst(0));
- sp = p;
- }
- gbranch(OGOTO);
- p->as = ABEQ;
- patch(p, r->label);
- swit2(q, i, def, n, tn);
-
- patch(sp, pc);
- swit2(r+1, nc-i-1, def, n, tn);
-}
-
-void
-bitload(Node *b, Node *n1, Node *n2, Node *n3, Node *nn)
-{
- int sh;
- int32 v;
- Node *l;
-
- /*
- * n1 gets adjusted/masked value
- * n2 gets address of cell
- * n3 gets contents of cell
- */
- l = b->left;
- if(n2 != Z) {
- regalloc(n1, l, nn);
- reglcgen(n2, l, Z);
- regalloc(n3, l, Z);
- gopcode(OAS, n2, Z, n3);
- gopcode(OAS, n3, Z, n1);
- } else {
- regalloc(n1, l, nn);
- cgen(l, n1);
- }
- if(b->type->shift == 0 && typeu[b->type->etype]) {
- v = ~0 + (1L << b->type->nbits);
- gopcode(OAND, nodconst(v), Z, n1);
- } else {
- sh = 32 - b->type->shift - b->type->nbits;
- if(sh > 0)
- gopcode(OASHL, nodconst(sh), Z, n1);
- sh += b->type->shift;
- if(sh > 0)
- if(typeu[b->type->etype])
- gopcode(OLSHR, nodconst(sh), Z, n1);
- else
- gopcode(OASHR, nodconst(sh), Z, n1);
- }
-}
-
-void
-bitstore(Node *b, Node *n1, Node *n2, Node *n3, Node *nn)
-{
- int32 v;
- Node nod, *l;
- int sh;
-
- /*
- * n1 has adjusted/masked value
- * n2 has address of cell
- * n3 has contents of cell
- */
- l = b->left;
- regalloc(&nod, l, Z);
- v = ~0 + (1L << b->type->nbits);
- gopcode(OAND, nodconst(v), Z, n1);
- gopcode(OAS, n1, Z, &nod);
- if(nn != Z)
- gopcode(OAS, n1, Z, nn);
- sh = b->type->shift;
- if(sh > 0)
- gopcode(OASHL, nodconst(sh), Z, &nod);
- v <<= sh;
- gopcode(OAND, nodconst(~v), Z, n3);
- gopcode(OOR, n3, Z, &nod);
- gopcode(OAS, &nod, Z, n2);
-
- regfree(&nod);
- regfree(n1);
- regfree(n2);
- regfree(n3);
-}
-
-int32
-outstring(char *s, int32 n)
-{
- int32 r;
-
- if(suppress)
- return nstring;
- r = nstring;
- while(n) {
- string[mnstring] = *s++;
- mnstring++;
- nstring++;
- if(mnstring >= NSNAME) {
- gpseudo(ADATA, symstring, nodconst(0L));
- p->from.offset += nstring - NSNAME;
- p->reg = NSNAME;
- p->to.type = D_SCONST;
- memmove(p->to.u.sval, string, NSNAME);
- mnstring = 0;
- }
- n--;
- }
- return r;
-}
-
-int
-mulcon(Node *n, Node *nn)
-{
- Node *l, *r, nod1, nod2;
- Multab *m;
- int32 v;
- int o;
- char code[sizeof(m->code)+2], *p;
-
- if(typefd[n->type->etype])
- return 0;
- l = n->left;
- r = n->right;
- if(l->op == OCONST) {
- l = r;
- r = n->left;
- }
- if(r->op != OCONST)
- return 0;
- v = convvtox(r->vconst, n->type->etype);
- if(v != r->vconst) {
- if(debug['M'])
- print("%L multiply conv: %lld\n", n->lineno, r->vconst);
- return 0;
- }
- m = mulcon0(n, v);
- if(!m) {
- if(debug['M'])
- print("%L multiply table: %lld\n", n->lineno, r->vconst);
- return 0;
- }
-
- memmove(code, m->code, sizeof(m->code));
- code[sizeof(m->code)] = 0;
-
- p = code;
- if(p[1] == 'i')
- p += 2;
- regalloc(&nod1, n, nn);
- cgen(l, &nod1);
- if(v < 0)
- gopcode(ONEG, &nod1, Z, &nod1);
- regalloc(&nod2, n, Z);
-
-loop:
- switch(*p) {
- case 0:
- regfree(&nod2);
- gopcode(OAS, &nod1, Z, nn);
- regfree(&nod1);
- return 1;
- case '+':
- o = OADD;
- goto addsub;
- case '-':
- o = OSUB;
- addsub: /* number is r,n,l */
- v = p[1] - '0';
- r = &nod1;
- if(v&4)
- r = &nod2;
- n = &nod1;
- if(v&2)
- n = &nod2;
- l = &nod1;
- if(v&1)
- l = &nod2;
- gopcode(o, l, n, r);
- break;
- default: /* op is shiftcount, number is r,l */
- v = p[1] - '0';
- r = &nod1;
- if(v&2)
- r = &nod2;
- l = &nod1;
- if(v&1)
- l = &nod2;
- v = *p - 'a';
- if(v < 0 || v >= 32) {
- diag(n, "mulcon unknown op: %c%c", p[0], p[1]);
- break;
- }
- gopcode(OASHL, nodconst(v), l, r);
- break;
- }
- p += 2;
- goto loop;
-}
-
-void
-sextern(Sym *s, Node *a, int32 o, int32 w)
-{
- int32 e, lw;
-
- for(e=0; e<w; e+=NSNAME) {
- lw = NSNAME;
- if(w-e < lw)
- lw = w-e;
- gpseudo(ADATA, s, nodconst(0));
- p->from.offset += o+e;
- p->reg = lw;
- p->to.type = D_SCONST;
- memmove(p->to.u.sval, a->cstring+e, lw);
- }
-}
-
-void
-gextern(Sym *s, Node *a, int32 o, int32 w)
-{
- gpseudo(ADATA, s, a);
- p->from.offset += o;
- p->reg = w;
- if(p->to.type == D_OREG)
- p->to.type = D_CONST;
-}
-
-void
-outcode(void)
-{
- Bprint(&outbuf, "go object %s %s %s\n", getgoos(), getgoarch(), getgoversion());
- if(pragcgobuf.to > pragcgobuf.start) {
- Bprint(&outbuf, "\n");
- Bprint(&outbuf, "$$ // exports\n\n");
- Bprint(&outbuf, "$$ // local types\n\n");
- Bprint(&outbuf, "$$ // cgo\n");
- Bprint(&outbuf, "%s", fmtstrflush(&pragcgobuf));
- Bprint(&outbuf, "\n$$\n\n");
- }
- Bprint(&outbuf, "!\n");
-
- writeobj(ctxt, &outbuf);
- lastp = nil;
-}
-
-int32
-align(int32 i, Type *t, int op, int32 *maxalign)
-{
- int32 o;
- Type *v;
- int w, packw;
-
- o = i;
- w = 1;
- packw = 0;
- switch(op) {
- default:
- diag(Z, "unknown align opcode %d", op);
- break;
-
- case Asu2: /* padding at end of a struct */
- w = *maxalign;
- if(w < 1)
- w = 1;
- if(packflg)
- packw = packflg;
- break;
-
- case Ael1: /* initial allign of struct element */
- for(v=t; v->etype==TARRAY; v=v->link)
- ;
- if(v->etype == TSTRUCT || v->etype == TUNION)
- w = v->align;
- else
- w = ewidth[v->etype];
- if(w < 1 || w > SZ_VLONG)
- fatal(Z, "align");
- if(packflg)
- packw = packflg;
- break;
-
- case Ael2: /* width of a struct element */
- o += t->width;
- break;
-
- case Aarg0: /* initial passbyptr argument in arg list */
- if(typesu[t->etype]) {
- o = align(o, types[TIND], Aarg1, nil);
- o = align(o, types[TIND], Aarg2, nil);
- }
- break;
-
- case Aarg1: /* initial align of parameter */
- w = ewidth[t->etype];
- if(w <= 0 || w >= SZ_VLONG) {
- w = SZ_VLONG;
- break;
- }
- w = 1;
- break;
-
- case Aarg2: /* width of a parameter */
- o += t->width;
- w = t->width;
- if(w > SZ_VLONG)
- w = SZ_VLONG;
- break;
-
- case Aaut3: /* total align of automatic */
- o = align(o, t, Ael1, nil);
- o = align(o, t, Ael2, nil);
- break;
- }
- if(packw != 0 && xround(o, w) != xround(o, packw))
- diag(Z, "#pragma pack changes offset of %T", t);
- o = xround(o, w);
- if(maxalign && *maxalign < w)
- *maxalign = w;
- if(debug['A'])
- print("align %s %ld %T = %ld\n", bnames[op], i, t, o);
- return o;
-}
-
-int32
-maxround(int32 max, int32 v)
-{
- v = xround(v, SZ_VLONG);
- if(v > max)
- return v;
- return max;
-}
diff --git a/src/cmd/9c/txt.c b/src/cmd/9c/txt.c
deleted file mode 100644
index e46aba84e..000000000
--- a/src/cmd/9c/txt.c
+++ /dev/null
@@ -1,1537 +0,0 @@
-// cmd/9c/txt.c from Vita Nuova.
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-
-static int resvreg[nelem(reg)];
-
-#define isv(et) ((et) == TVLONG || (et) == TUVLONG || (et) == TIND)
-
-int thechar = '9';
-char *thestring = "power64";
-
-LinkArch *thelinkarch;
-
-void
-linkarchinit(void)
-{
- thestring = getgoarch();
- if(strcmp(thestring, "power64le") == 0)
- thelinkarch = &linkpower64le;
- else
- thelinkarch = &linkpower64;
-}
-
-
-void
-ginit(void)
-{
- Type *t;
-
- dodefine("_64BITREG");
- dodefine("_64BIT");
- exregoffset = REGEXT;
- exfregoffset = FREGEXT;
- listinit();
- nstring = 0;
- mnstring = 0;
- nrathole = 0;
- pc = 0;
- breakpc = -1;
- continpc = -1;
- cases = C;
- lastp = P;
- tfield = types[TLONG];
-
- typeword = typechlvp;
- typecmplx = typesu;
- /* TO DO */
- memmove(typechlpv, typechlp, sizeof(typechlpv));
- typechlpv[TVLONG] = 1;
- typechlpv[TUVLONG] = 1;
-
- zprog.link = P;
- zprog.as = AGOK;
- zprog.reg = NREG;
- zprog.from.type = D_NONE;
- zprog.from.name = D_NONE;
- zprog.from.reg = NREG;
- zprog.from3 = zprog.from;
- zprog.to = zprog.from;
-
- regnode.op = OREGISTER;
- regnode.class = CEXREG;
- regnode.reg = 0;
- regnode.complex = 0;
- regnode.addable = 11;
- regnode.type = types[TLONG];
-
- qregnode = regnode;
- qregnode.type = types[TVLONG];
-
- constnode.op = OCONST;
- constnode.class = CXXX;
- constnode.complex = 0;
- constnode.addable = 20;
- constnode.type = types[TLONG];
-
- vconstnode = constnode;
- vconstnode.type = types[TVLONG];
-
- fconstnode.op = OCONST;
- fconstnode.class = CXXX;
- fconstnode.complex = 0;
- fconstnode.addable = 20;
- fconstnode.type = types[TDOUBLE];
-
- nodsafe = new(ONAME, Z, Z);
- nodsafe->sym = slookup(".safe");
- nodsafe->type = types[TINT];
- nodsafe->etype = types[TINT]->etype;
- nodsafe->class = CAUTO;
- complex(nodsafe);
-
- t = typ(TARRAY, types[TCHAR]);
- symrathole = slookup(".rathole");
- symrathole->class = CGLOBL;
- symrathole->type = t;
-
- nodrat = new(ONAME, Z, Z);
- nodrat->sym = symrathole;
- nodrat->type = types[TIND];
- nodrat->etype = TVOID;
- nodrat->class = CGLOBL;
- complex(nodrat);
- nodrat->type = t;
-
- nodret = new(ONAME, Z, Z);
- nodret->sym = slookup(".ret");
- nodret->type = types[TIND];
- nodret->etype = TIND;
- nodret->class = CPARAM;
- nodret = new(OIND, nodret, Z);
- complex(nodret);
-
- com64init();
-
- memset(reg, 0, sizeof(reg));
- reg[REGZERO] = 1; /* don't use */
- reg[REGTMP] = 1;
- reg[FREGCVI+NREG] = 1;
- reg[FREGZERO+NREG] = 1;
- reg[FREGHALF+NREG] = 1;
- reg[FREGONE+NREG] = 1;
- reg[FREGTWO+NREG] = 1;
- memmove(resvreg, reg, sizeof(reg));
-}
-
-void
-gclean(void)
-{
- int i;
- Sym *s;
-
- for(i=0; i<NREG; i++)
- if(reg[i] && !resvreg[i])
- diag(Z, "reg %d left allocated", i);
- for(i=NREG; i<NREG+NREG; i++)
- if(reg[i] && !resvreg[i])
- diag(Z, "freg %d left allocated", i-NREG);
- while(mnstring)
- outstring("", 1L);
- symstring->type->width = nstring;
- symrathole->type->width = nrathole;
- for(i=0; i<NHASH; i++)
- for(s = hash[i]; s != S; s = s->link) {
- if(s->type == T)
- continue;
- if(s->type->width == 0)
- continue;
- if(s->class != CGLOBL && s->class != CSTATIC)
- continue;
- if(s->type == types[TENUM])
- continue;
- gpseudo(AGLOBL, s, nodconst(s->type->width));
- }
- nextpc();
- p->as = AEND;
- outcode();
-}
-
-void
-nextpc(void)
-{
- Plist *pl;
-
- p = alloc(sizeof(*p));
- *p = zprog;
- p->lineno = nearln;
- p->pc = pc;
- pc++;
- if(lastp == P) {
- pl = linknewplist(ctxt);
- pl->firstpc = p;
- } else
- lastp->link = p;
- lastp = p;
-}
-
-void
-gargs(Node *n, Node *tn1, Node *tn2)
-{
- int32 regs;
- Node fnxargs[20], *fnxp;
-
- regs = cursafe;
-
- fnxp = fnxargs;
- garg1(n, tn1, tn2, 0, &fnxp); /* compile fns to temps */
-
- curarg = 0;
- fnxp = fnxargs;
- garg1(n, tn1, tn2, 1, &fnxp); /* compile normal args and temps */
-
- cursafe = regs;
-}
-
-void
-garg1(Node *n, Node *tn1, Node *tn2, int f, Node **fnxp)
-{
- Node nod;
-
- if(n == Z)
- return;
- if(n->op == OLIST) {
- garg1(n->left, tn1, tn2, f, fnxp);
- garg1(n->right, tn1, tn2, f, fnxp);
- return;
- }
- if(f == 0) {
- if(n->complex >= FNX) {
- regsalloc(*fnxp, n);
- nod = znode;
- nod.op = OAS;
- nod.left = *fnxp;
- nod.right = n;
- nod.type = n->type;
- cgen(&nod, Z);
- (*fnxp)++;
- }
- return;
- }
- if(typesu[n->type->etype]) {
- regaalloc(tn2, n);
- if(n->complex >= FNX) {
- sugen(*fnxp, tn2, n->type->width);
- (*fnxp)++;
- } else
- sugen(n, tn2, n->type->width);
- return;
- }
- if(REGARG>=0 && curarg == 0 && typechlpv[n->type->etype]) {
- regaalloc1(tn1, n);
- if(n->complex >= FNX) {
- cgen(*fnxp, tn1);
- (*fnxp)++;
- } else
- cgen(n, tn1);
- return;
- }
- if(vconst(n) == 0) {
- regaalloc(tn2, n);
- gopcode(OAS, n, Z, tn2);
- return;
- }
- regalloc(tn1, n, Z);
- if(n->complex >= FNX) {
- cgen(*fnxp, tn1);
- (*fnxp)++;
- } else
- cgen(n, tn1);
- regaalloc(tn2, n);
- gopcode(OAS, tn1, Z, tn2);
- regfree(tn1);
-}
-
-Node*
-nod32const(vlong v)
-{
- constnode.vconst = v & MASK(32);
- return &constnode;
-}
-
-Node*
-nodgconst(vlong v, Type *t)
-{
- if(!typev[t->etype])
- return nodconst((int32)v);
- vconstnode.vconst = v;
- return &vconstnode;
-}
-
-Node*
-nodconst(int32 v)
-{
- constnode.vconst = v;
- return &constnode;
-}
-
-Node*
-nodfconst(double d)
-{
- fconstnode.fconst = d;
- return &fconstnode;
-}
-
-void
-nodreg(Node *n, Node *nn, int reg)
-{
- *n = qregnode;
- n->reg = reg;
- n->type = nn->type;
- n->lineno = nn->lineno;
-}
-
-void
-regret(Node *n, Node *nn, Type *t, int mode)
-{
- int r;
-
- if(mode == 0 || hasdotdotdot(t) || nn->type->width == 0) {
- r = REGRET;
- if(typefd[nn->type->etype])
- r = FREGRET+NREG;
- nodreg(n, nn, r);
- reg[r]++;
- return;
- }
-
- if(mode == 1) {
- // fetch returned value after call.
- // already called gargs, so curarg is set.
- curarg = (curarg+7) & ~7;
- regaalloc(n, nn);
- return;
- }
-
- if(mode == 2) {
- // store value to be returned.
- // must compute arg offset.
- if(t->etype != TFUNC)
- fatal(Z, "bad regret func %T", t);
- *n = *nn;
- n->op = ONAME;
- n->class = CPARAM;
- n->sym = slookup(".ret");
- n->complex = nodret->complex;
- n->addable = 20;
- n->xoffset = argsize(0);
- return;
- }
-
- fatal(Z, "bad regret");
-}
-
-void
-regalloc(Node *n, Node *tn, Node *o)
-{
- int i, j;
- static int lasti;
-
- switch(tn->type->etype) {
- case TCHAR:
- case TUCHAR:
- case TSHORT:
- case TUSHORT:
- case TINT:
- case TUINT:
- case TLONG:
- case TULONG:
- case TVLONG:
- case TUVLONG:
- case TIND:
- if(o != Z && o->op == OREGISTER) {
- i = o->reg;
- if(i > 0 && i < NREG)
- goto out;
- }
- j = lasti + REGRET+1;
- for(i=REGRET+1; i<NREG; i++) {
- if(j >= NREG)
- j = REGRET+1;
- if(reg[j] == 0) {
- i = j;
- goto out;
- }
- j++;
- }
- diag(tn, "out of fixed registers");
- goto err;
-
- case TFLOAT:
- case TDOUBLE:
- if(o != Z && o->op == OREGISTER) {
- i = o->reg;
- if(i >= NREG && i < NREG+NREG)
- goto out;
- }
- j = lasti + NREG;
- for(i=NREG; i<NREG+NREG; i++) {
- if(j >= NREG+NREG)
- j = NREG;
- if(reg[j] == 0) {
- i = j;
- goto out;
- }
- j++;
- }
- diag(tn, "out of float registers");
- goto err;
- }
- diag(tn, "unknown type in regalloc: %T", tn->type);
-err:
- i = 0;
-out:
- if(i)
- reg[i]++;
- lasti++;
- if(lasti >= 5)
- lasti = 0;
- nodreg(n, tn, i);
-}
-
-void
-regialloc(Node *n, Node *tn, Node *o)
-{
- Node nod;
-
- nod = *tn;
- nod.type = types[TIND];
- regalloc(n, &nod, o);
-}
-
-void
-regfree(Node *n)
-{
- int i;
-
- i = 0;
- if(n->op != OREGISTER && n->op != OINDREG)
- goto err;
- i = n->reg;
- if(i < 0 || i >= sizeof(reg))
- goto err;
- if(reg[i] <= 0)
- goto err;
- reg[i]--;
- return;
-err:
- diag(n, "error in regfree: %d", i);
-}
-
-void
-regsalloc(Node *n, Node *nn)
-{
- cursafe = align(cursafe, nn->type, Aaut3, nil);
- maxargsafe = maxround(maxargsafe, cursafe+curarg);
- *n = *nodsafe;
- n->xoffset = -(stkoff + cursafe);
- n->type = nn->type;
- n->etype = nn->type->etype;
- n->lineno = nn->lineno;
-}
-
-void
-regaalloc1(Node *n, Node *nn)
-{
- if(REGARG < 0)
- return;
- nodreg(n, nn, REGARG);
- reg[REGARG]++;
- curarg = align(curarg, nn->type, Aarg1, nil);
- curarg = align(curarg, nn->type, Aarg2, nil);
- maxargsafe = maxround(maxargsafe, cursafe+curarg);
-}
-
-void
-regaalloc(Node *n, Node *nn)
-{
- curarg = align(curarg, nn->type, Aarg1, nil);
- *n = *nn;
- n->op = OINDREG;
- n->reg = REGSP;
- n->xoffset = curarg + SZ_VLONG;
- n->complex = 0;
- n->addable = 20;
- curarg = align(curarg, nn->type, Aarg2, nil);
- maxargsafe = maxround(maxargsafe, cursafe+curarg);
-}
-
-void
-regind(Node *n, Node *nn)
-{
-
- if(n->op != OREGISTER) {
- diag(n, "regind not OREGISTER");
- return;
- }
- n->op = OINDREG;
- n->type = nn->type;
-}
-
-void
-raddr(Node *n, Prog *p)
-{
- Addr a;
-
- naddr(n, &a);
- if(R0ISZERO && a.type == D_CONST && a.offset == 0) {
- a.type = D_REG;
- a.reg = REGZERO;
- }
- if(a.type != D_REG && a.type != D_FREG) {
- if(n)
- diag(n, "bad in raddr: %O", n->op);
- else
- diag(n, "bad in raddr: <null>");
- p->reg = NREG;
- } else
- p->reg = a.reg;
-}
-
-void
-naddr(Node *n, Addr *a)
-{
- int32 v;
-
- a->type = D_NONE;
- if(n == Z)
- return;
- switch(n->op) {
- default:
- bad:
- prtree(n, "naddr");
- diag(n, "%L: !bad in naddr: %O", n->lineno, n->op);
- break;
-
- case OREGISTER:
- a->type = D_REG;
- a->sym = nil;
- a->reg = n->reg;
- if(a->reg >= NREG) {
- a->type = D_FREG;
- a->reg -= NREG;
- }
- break;
-
- case OIND:
- naddr(n->left, a);
- if(a->type == D_REG) {
- a->type = D_OREG;
- break;
- }
- if(a->type == D_CONST) {
- a->type = D_OREG;
- break;
- }
- goto bad;
-
- case OINDREG:
- a->type = D_OREG;
- a->sym = nil;
- a->offset = n->xoffset;
- a->reg = n->reg;
- break;
-
- case ONAME:
- a->etype = n->etype;
- a->type = D_OREG;
- a->name = D_STATIC;
- a->sym = linksym(n->sym);
- a->offset = n->xoffset;
- if(n->class == CSTATIC)
- break;
- if(n->class == CEXTERN || n->class == CGLOBL) {
- a->name = D_EXTERN;
- break;
- }
- if(n->class == CAUTO) {
- a->name = D_AUTO;
- break;
- }
- if(n->class == CPARAM) {
- a->name = D_PARAM;
- break;
- }
- goto bad;
-
- case OCONST:
- a->sym = nil;
- a->reg = NREG;
- if(typefd[n->type->etype]) {
- a->type = D_FCONST;
- a->u.dval = n->fconst;
- } else {
- a->type = D_CONST;
- a->offset = n->vconst;
- }
- break;
-
- case OADDR:
- naddr(n->left, a);
- if(a->type == D_OREG) {
- a->type = D_CONST;
- break;
- }
- goto bad;
-
- case OADD:
- if(n->left->op == OCONST) {
- naddr(n->left, a);
- v = a->offset;
- naddr(n->right, a);
- } else {
- naddr(n->right, a);
- v = a->offset;
- naddr(n->left, a);
- }
- a->offset += v;
- break;
-
- }
-}
-
-void
-fop(int as, int f1, int f2, Node *t)
-{
- Node nod1, nod2, nod3;
-
- nodreg(&nod1, t, NREG+f1);
- nodreg(&nod2, t, NREG+f2);
- regalloc(&nod3, t, t);
- gopcode(as, &nod1, &nod2, &nod3);
- gmove(&nod3, t);
- regfree(&nod3);
-}
-
-void
-gmove(Node *f, Node *t)
-{
- int ft, tt, a;
- Node nod, fxc0, fxc1, fxc2, fxrat;
- Prog *p1;
- double d;
-
- ft = f->type->etype;
- tt = t->type->etype;
-
- if(ft == TDOUBLE && f->op == OCONST) {
- d = f->fconst;
- if(d == 0.0) {
- a = FREGZERO;
- goto ffreg;
- }
- if(d == 0.5) {
- a = FREGHALF;
- goto ffreg;
- }
- if(d == 1.0) {
- a = FREGONE;
- goto ffreg;
- }
- if(d == 2.0) {
- a = FREGTWO;
- goto ffreg;
- }
- if(d == -.5) {
- fop(OSUB, FREGHALF, FREGZERO, t);
- return;
- }
- if(d == -1.0) {
- fop(OSUB, FREGONE, FREGZERO, t);
- return;
- }
- if(d == -2.0) {
- fop(OSUB, FREGTWO, FREGZERO, t);
- return;
- }
- if(d == 1.5) {
- fop(OADD, FREGONE, FREGHALF, t);
- return;
- }
- if(d == 2.5) {
- fop(OADD, FREGTWO, FREGHALF, t);
- return;
- }
- if(d == 3.0) {
- fop(OADD, FREGTWO, FREGONE, t);
- return;
- }
- }
- if(ft == TFLOAT && f->op == OCONST) {
- d = f->fconst;
- if(d == 0) {
- a = FREGZERO;
- ffreg:
- nodreg(&nod, f, NREG+a);
- gmove(&nod, t);
- return;
- }
- }
- /*
- * a load --
- * put it into a register then
- * worry what to do with it.
- */
- if(f->op == ONAME || f->op == OINDREG || f->op == OIND) {
- switch(ft) {
- default:
- if(ewidth[ft] == 4){
- if(typeu[ft])
- a = AMOVWZ;
- else
- a = AMOVW;
- }else
- a = AMOVD;
- break;
- case TINT:
- a = AMOVW;
- break;
- case TUINT:
- a = AMOVWZ;
- break;
- case TFLOAT:
- a = AFMOVS;
- break;
- case TDOUBLE:
- a = AFMOVD;
- break;
- case TCHAR:
- a = AMOVB;
- break;
- case TUCHAR:
- a = AMOVBZ;
- break;
- case TSHORT:
- a = AMOVH;
- break;
- case TUSHORT:
- a = AMOVHZ;
- break;
- }
- regalloc(&nod, f, t);
- gins(a, f, &nod);
- gmove(&nod, t);
- regfree(&nod);
- return;
- }
-
- /*
- * a store --
- * put it into a register then
- * store it.
- */
- if(t->op == ONAME || t->op == OINDREG || t->op == OIND) {
- switch(tt) {
- default:
- if(ewidth[tt] == 4)
- a = AMOVW;
- else
- a = AMOVD;
- break;
- case TINT:
- a = AMOVW;
- break;
- case TUINT:
- a = AMOVWZ;
- break;
- case TUCHAR:
- a = AMOVBZ;
- break;
- case TCHAR:
- a = AMOVB;
- break;
- case TUSHORT:
- a = AMOVHZ;
- break;
- case TSHORT:
- a = AMOVH;
- break;
- case TFLOAT:
- a = AFMOVS;
- break;
- case TDOUBLE:
- a = AFMOVD;
- break;
- }
- if(!typefd[ft] && vconst(f) == 0) {
- gins(a, f, t);
- return;
- }
- if(ft == tt)
- regalloc(&nod, t, f);
- else
- regalloc(&nod, t, Z);
- gmove(f, &nod);
- gins(a, &nod, t);
- regfree(&nod);
- return;
- }
-
- /*
- * type x type cross table
- */
- a = AGOK;
- switch(ft) {
- case TDOUBLE:
- case TFLOAT:
- switch(tt) {
- case TDOUBLE:
- a = AFMOVD;
- if(ft == TFLOAT)
- a = AFMOVS; /* AFMOVSD */
- break;
- case TFLOAT:
- a = AFRSP;
- if(ft == TFLOAT)
- a = AFMOVS;
- break;
- case TINT:
- case TUINT:
- case TLONG:
- case TULONG:
- case TIND:
- case TSHORT:
- case TUSHORT:
- case TCHAR:
- case TUCHAR:
- /* BUG: not right for unsigned int32 */
- regalloc(&nod, f, Z); /* should be type float */
- regsalloc(&fxrat, f);
- gins(AFCTIWZ, f, &nod);
- gins(AFMOVD, &nod, &fxrat);
- regfree(&nod);
- fxrat.type = nodrat->type;
- fxrat.etype = nodrat->etype;
- fxrat.xoffset += 4;
- gins(AMOVW, &fxrat, t); /* TO DO */
- gmove(t, t);
- return;
- case TVLONG:
- case TUVLONG:
- /* BUG: not right for unsigned int32 */
- regalloc(&nod, f, Z); /* should be type float */
- regsalloc(&fxrat, f);
- gins(AFCTIDZ, f, &nod);
- gins(AFMOVD, &nod, &fxrat);
- regfree(&nod);
- fxrat.type = nodrat->type;
- fxrat.etype = nodrat->etype;
- gins(AMOVD, &fxrat, t);
- gmove(t, t);
- return;
- }
- break;
- case TINT:
- case TUINT:
- case TLONG:
- case TULONG:
- switch(tt) {
- case TDOUBLE:
- case TFLOAT:
- goto fxtofl;
- case TINT:
- case TUINT:
- case TLONG:
- case TULONG:
- case TSHORT:
- case TUSHORT:
- case TCHAR:
- case TUCHAR:
- if(typeu[tt])
- a = AMOVWZ;
- else
- a = AMOVW;
- break;
- case TVLONG:
- case TUVLONG:
- case TIND:
- a = AMOVD;
- break;
- }
- break;
- case TVLONG:
- case TUVLONG:
- case TIND:
- switch(tt) {
- case TDOUBLE:
- case TFLOAT:
- goto fxtofl;
- case TINT:
- case TUINT:
- case TLONG:
- case TULONG:
- case TVLONG:
- case TUVLONG:
- case TIND:
- case TSHORT:
- case TUSHORT:
- case TCHAR:
- case TUCHAR:
- a = AMOVD; /* TO DO: conversion done? */
- break;
- }
- break;
- case TSHORT:
- switch(tt) {
- case TDOUBLE:
- case TFLOAT:
- goto fxtofl;
- case TINT:
- case TUINT:
- case TLONG:
- case TULONG:
- case TVLONG:
- case TUVLONG:
- case TIND:
- a = AMOVH;
- break;
- case TSHORT:
- case TUSHORT:
- case TCHAR:
- case TUCHAR:
- a = AMOVD;
- break;
- }
- break;
- case TUSHORT:
- switch(tt) {
- case TDOUBLE:
- case TFLOAT:
- goto fxtofl;
- case TINT:
- case TUINT:
- case TLONG:
- case TULONG:
- case TVLONG:
- case TUVLONG:
- case TIND:
- a = AMOVHZ;
- break;
- case TSHORT:
- case TUSHORT:
- case TCHAR:
- case TUCHAR:
- a = AMOVD;
- break;
- }
- break;
- case TCHAR:
- switch(tt) {
- case TDOUBLE:
- case TFLOAT:
- goto fxtofl;
- case TINT:
- case TUINT:
- case TLONG:
- case TULONG:
- case TVLONG:
- case TUVLONG:
- case TIND:
- case TSHORT:
- case TUSHORT:
- a = AMOVB;
- break;
- case TCHAR:
- case TUCHAR:
- a = AMOVD;
- break;
- }
- break;
- case TUCHAR:
- switch(tt) {
- case TDOUBLE:
- case TFLOAT:
- fxtofl:
- /*
- * rat[0] = 0x43300000; rat[1] = f^0x80000000;
- * t = *(double*)rat - FREGCVI;
- * is-unsigned(t) => if(t<0) t += 2^32;
- * could be streamlined for int-to-float
- */
- regalloc(&fxc0, f, Z);
- regalloc(&fxc2, f, Z);
- regsalloc(&fxrat, t); /* should be type float */
- gins(AMOVW, nodconst(0x43300000L), &fxc0);
- gins(AMOVW, f, &fxc2);
- gins(AXOR, nodconst(0x80000000L), &fxc2);
- if(ctxt->arch->endian == BigEndian) {
- gins(AMOVW, &fxc0, &fxrat);
- fxc1 = fxrat;
- fxc1.type = nodrat->type;
- fxc1.etype = nodrat->etype;
- fxc1.xoffset += SZ_LONG;
- gins(AMOVW, &fxc2, &fxc1);
- } else {
- gins(AMOVW, &fxc2, &fxrat);
- fxc1 = fxrat;
- fxc1.type = nodrat->type;
- fxc1.etype = nodrat->etype;
- fxc1.xoffset += SZ_LONG;
- gins(AMOVW, &fxc0, &fxc1);
- }
- regfree(&fxc2);
- regfree(&fxc0);
- regalloc(&nod, t, t); /* should be type float */
- gins(AFMOVD, &fxrat, &nod);
- nodreg(&fxc1, t, NREG+FREGCVI);
- gins(AFSUB, &fxc1, &nod);
- a = AFMOVD;
- if(tt == TFLOAT)
- a = AFRSP;
- gins(a, &nod, t);
- regfree(&nod);
- if(ft == TULONG) {
- regalloc(&nod, t, Z);
- if(tt == TFLOAT) {
- gins(AFCMPU, t, Z);
- p->to.type = D_FREG;
- p->to.reg = FREGZERO;
- gins(ABGE, Z, Z);
- p1 = p;
- gins(AFMOVS, nodfconst(4294967296.), &nod);
- gins(AFADDS, &nod, t);
- } else {
- gins(AFCMPU, t, Z);
- p->to.type = D_FREG;
- p->to.reg = FREGZERO;
- gins(ABGE, Z, Z);
- p1 = p;
- gins(AFMOVD, nodfconst(4294967296.), &nod);
- gins(AFADD, &nod, t);
- }
- patch(p1, pc);
- regfree(&nod);
- }
- return;
- case TINT:
- case TUINT:
- case TLONG:
- case TULONG:
- case TVLONG:
- case TUVLONG:
- case TIND:
- case TSHORT:
- case TUSHORT:
- a = AMOVBZ;
- break;
- case TCHAR:
- case TUCHAR:
- a = AMOVD;
- break;
- }
- break;
- }
- if(a == AGOK)
- diag(Z, "bad opcode in gmove %T -> %T", f->type, t->type);
- if(a == AMOVD || (a == AMOVW || a == AMOVWZ) && ewidth[ft] == ewidth[tt] || a == AFMOVS || a == AFMOVD)
- if(samaddr(f, t))
- return;
- gins(a, f, t);
-}
-
-void
-gins(int a, Node *f, Node *t)
-{
-
- nextpc();
- p->as = a;
- if(f != Z)
- naddr(f, &p->from);
- if(t != Z)
- naddr(t, &p->to);
- if(debug['g'])
- print("%P\n", p);
-}
-
-void
-gopcode(int o, Node *f1, Node *f2, Node *t)
-{
- int a, et;
- Addr ta;
- int uns;
-
- uns = 0;
- et = TLONG;
- if(f1 != Z && f1->type != T) {
- if(f1->op == OCONST && t != Z && t->type != T)
- et = t->type->etype;
- else
- et = f1->type->etype;
- }
- a = AGOK;
- switch(o) {
- case OAS:
- gmove(f1, t);
- return;
-
- case OASADD:
- case OADD:
- a = AADD;
- if(et == TFLOAT)
- a = AFADDS;
- else
- if(et == TDOUBLE)
- a = AFADD;
- break;
-
- case OASSUB:
- case OSUB:
- a = ASUB;
- if(et == TFLOAT)
- a = AFSUBS;
- else
- if(et == TDOUBLE)
- a = AFSUB;
- break;
-
- case OASOR:
- case OOR:
- a = AOR;
- break;
-
- case OASAND:
- case OAND:
- a = AAND;
- if(f1->op == OCONST)
- a = AANDCC;
- break;
-
- case OASXOR:
- case OXOR:
- a = AXOR;
- break;
-
- case OASLSHR:
- case OLSHR:
- a = ASRW;
- if(isv(et))
- a = ASRD;
- break;
-
- case OASASHR:
- case OASHR:
- a = ASRAW;
- if(isv(et))
- a = ASRAD;
- break;
-
- case OASASHL:
- case OASHL:
- a = ASLW;
- if(isv(et))
- a = ASLD;
- break;
-
- case OFUNC:
- a = ABL;
- break;
-
- case OASLMUL:
- case OLMUL:
- case OASMUL:
- case OMUL:
- if(et == TFLOAT) {
- a = AFMULS;
- break;
- } else
- if(et == TDOUBLE) {
- a = AFMUL;
- break;
- }
- a = AMULLW;
- if(isv(et))
- a = AMULLD;
- break;
-
- case OASDIV:
- case ODIV:
- if(et == TFLOAT) {
- a = AFDIVS;
- break;
- } else
- if(et == TDOUBLE) {
- a = AFDIV;
- break;
- } else
- a = ADIVW;
- if(isv(et))
- a = ADIVD;
- break;
-
- case OASMOD:
- case OMOD:
- a = AREM;
- if(isv(et))
- a = AREMD;
- break;
-
- case OASLMOD:
- case OLMOD:
- a = AREMU;
- if(isv(et))
- a = AREMDU;
- break;
-
- case OASLDIV:
- case OLDIV:
- a = ADIVWU;
- if(isv(et))
- a = ADIVDU;
- break;
-
- case OCOM:
- a = ANOR;
- break;
-
- case ONEG:
- a = ANEG;
- if(et == TFLOAT || et == TDOUBLE)
- a = AFNEG;
- break;
-
- case OEQ:
- a = ABEQ;
- goto cmp;
-
- case ONE:
- a = ABNE;
- goto cmp;
-
- case OLT:
- a = ABLT;
- goto cmp;
-
- case OLE:
- a = ABLE;
- goto cmp;
-
- case OGE:
- a = ABGE;
- goto cmp;
-
- case OGT:
- a = ABGT;
- goto cmp;
-
- case OLO:
- a = ABLT;
- goto cmpu;
-
- case OLS:
- a = ABLE;
- goto cmpu;
-
- case OHS:
- a = ABGE;
- goto cmpu;
-
- case OHI:
- a = ABGT;
- goto cmpu;
-
- cmpu:
- uns = 1;
- cmp:
- nextpc();
- switch(et){
- case TINT:
- case TLONG:
- p->as = ACMPW;
- break;
- case TUINT:
- case TULONG:
- p->as = ACMPWU;
- break;
- case TFLOAT:
- case TDOUBLE:
- p->as = AFCMPU;
- break;
- default:
- p->as = uns? ACMPU: ACMP;
- break;
- }
- if(f1 != Z)
- naddr(f1, &p->from);
- if(t != Z)
- naddr(t, &p->to);
- if(f1 == Z || t == Z || f2 != Z)
- diag(Z, "bad cmp in gopcode %O", o);
- if(debug['g'])
- print("%P\n", p);
- f1 = Z;
- f2 = Z;
- t = Z;
- break;
- }
- if(a == AGOK)
- diag(Z, "bad in gopcode %O", o);
- nextpc();
- p->as = a;
- if(f1 != Z)
- naddr(f1, &p->from);
- if(f2 != Z) {
- naddr(f2, &ta);
- p->reg = ta.reg;
- if(ta.type == D_CONST && ta.offset == 0) {
- if(R0ISZERO)
- p->reg = REGZERO;
- else
- diag(Z, "REGZERO in gopcode %O", o);
- }
- }
- if(t != Z)
- naddr(t, &p->to);
- if(debug['g'])
- print("%P\n", p);
-}
-
-int
-samaddr(Node *f, Node *t)
-{
- return f->op == OREGISTER && t->op == OREGISTER && f->reg == t->reg;
-}
-
-void
-gbranch(int o)
-{
- int a;
-
- a = AGOK;
- switch(o) {
- case ORETURN:
- a = ARETURN;
- break;
- case OGOTO:
- a = ABR;
- break;
- }
- nextpc();
- if(a == AGOK) {
- diag(Z, "bad in gbranch %O", o);
- nextpc();
- }
- p->as = a;
-}
-
-void
-patch(Prog *op, int32 pc)
-{
-
- op->to.offset = pc;
- op->to.type = D_BRANCH;
-}
-
-void
-gpseudo(int a, Sym *s, Node *n)
-{
-
- nextpc();
- p->as = a;
- p->from.type = D_OREG;
- p->from.sym = linksym(s);
-
- switch(a) {
- case ATEXT:
- p->reg = textflag;
- textflag = 0;
- break;
- case AGLOBL:
- p->reg = s->dataflag;
- break;
- }
-
- p->from.name = D_EXTERN;
- if(s->class == CSTATIC)
- p->from.name = D_STATIC;
- naddr(n, &p->to);
- if(a == ADATA || a == AGLOBL)
- pc--;
-}
-
-int
-sval(int32 v)
-{
-
- if(v >= -(1<<15) && v < (1<<15))
- return 1;
- return 0;
-}
-
-void
-gpcdata(int index, int value)
-{
- Node n1;
-
- n1 = *nodconst(index);
- gins(APCDATA, &n1, nodconst(value));
-}
-
-void
-gprefetch(Node *n)
-{
- // TODO(minux)
- USED(n);
- /*
- Node n1;
-
- regalloc(&n1, n, Z);
- gmove(n, &n1);
- n1.op = OINDREG;
- gins(ADCBT, &n1, Z);
- regfree(&n1);
- */
-}
-
-
-int
-sconst(Node *n)
-{
- vlong vv;
-
- if(n->op == OCONST) {
- if(!typefd[n->type->etype]) {
- vv = n->vconst;
- if(vv >= -(((vlong)1)<<15) && vv < (((vlong)1)<<15))
- return 1;
- }
- }
- return 0;
-}
-
-int
-uconst(Node *n)
-{
- vlong vv;
-
- if(n->op == OCONST) {
- if(!typefd[n->type->etype]) {
- vv = n->vconst;
- if(vv >= 0 && vv < (((vlong)1)<<16))
- return 1;
- }
- }
- return 0;
-}
-
-int
-immconst(Node *n)
-{
- vlong v;
-
- if(n->op != OCONST || typefd[n->type->etype])
- return 0;
- v = n->vconst;
- if((v & 0xFFFF) == 0)
- v >>= 16;
- if(v >= 0 && v < ((vlong)1<<16))
- return 1;
- if(v >= -((vlong)1<<15) && v <= ((vlong)1<<15))
- return 1;
- return 0;
-}
-
-int32
-exreg(Type *t)
-{
- int32 o;
-
- if(typechlpv[t->etype]) {
- if(exregoffset <= 3)
- return 0;
- o = exregoffset;
- exregoffset--;
- return o;
- }
- if(typefd[t->etype]) {
- if(exfregoffset <= 16)
- return 0;
- o = exfregoffset + NREG;
- exfregoffset--;
- return o;
- }
- return 0;
-}
-
-schar ewidth[NTYPE] =
-{
- -1, /* [TXXX] */
- SZ_CHAR, /* [TCHAR] */
- SZ_CHAR, /* [TUCHAR] */
- SZ_SHORT, /* [TSHORT] */
- SZ_SHORT, /* [TUSHORT] */
- SZ_INT, /* [TINT] */
- SZ_INT, /* [TUINT] */
- SZ_LONG, /* [TLONG] */
- SZ_LONG, /* [TULONG] */
- SZ_VLONG, /* [TVLONG] */
- SZ_VLONG, /* [TUVLONG] */
- SZ_FLOAT, /* [TFLOAT] */
- SZ_DOUBLE, /* [TDOUBLE] */
- SZ_IND, /* [TIND] */
- 0, /* [TFUNC] */
- -1, /* [TARRAY] */
- 0, /* [TVOID] */
- -1, /* [TSTRUCT] */
- -1, /* [TUNION] */
- SZ_INT, /* [TENUM] */
-};
-int32 ncast[NTYPE] =
-{
- 0, /* [TXXX] */
- BCHAR|BUCHAR, /* [TCHAR] */
- BCHAR|BUCHAR, /* [TUCHAR] */
- BSHORT|BUSHORT, /* [TSHORT] */
- BSHORT|BUSHORT, /* [TUSHORT] */
- BINT|BUINT|BLONG|BULONG, /* [TINT] */
- BINT|BUINT|BLONG|BULONG, /* [TUINT] */
- BINT|BUINT|BLONG|BULONG, /* [TLONG] */
- BINT|BUINT|BLONG|BULONG, /* [TULONG] */
- BVLONG|BUVLONG|BIND, /* [TVLONG] */
- BVLONG|BUVLONG|BIND, /* [TUVLONG] */
- BFLOAT, /* [TFLOAT] */
- BDOUBLE, /* [TDOUBLE] */
- BVLONG|BUVLONG|BIND, /* [TIND] */
- 0, /* [TFUNC] */
- 0, /* [TARRAY] */
- 0, /* [TVOID] */
- BSTRUCT, /* [TSTRUCT] */
- BUNION, /* [TUNION] */
- 0, /* [TENUM] */
-};
diff --git a/src/cmd/cc/Makefile b/src/cmd/cc/Makefile
deleted file mode 100644
index 34df31d6f..000000000
--- a/src/cmd/cc/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-# Copyright 2012 The Go Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style
-# license that can be found in the LICENSE file.
-
-include ../../Make.dist
-
-install: y.tab.h
-
-y.tab.h: cc.y
- LANG=C LANGUAGE=en_US.UTF8 bison -d -v -y cc.y
diff --git a/src/cmd/cc/acid.c b/src/cmd/cc/acid.c
deleted file mode 100644
index 23147e519..000000000
--- a/src/cmd/cc/acid.c
+++ /dev/null
@@ -1,344 +0,0 @@
-// Inferno utils/cc/acid.c
-// http://code.google.com/p/inferno-os/source/browse/utils/cc/acid.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include <u.h>
-#include "cc.h"
-
-static char *kwd[] =
-{
- "$adt", "$aggr", "$append", "$complex", "$defn",
- "$delete", "$do", "$else", "$eval", "$head", "$if",
- "$local", "$loop", "$return", "$tail", "$then",
- "$union", "$whatis", "$while",
-};
-
-char*
-amap(char *s)
-{
- int i, bot, top, new;
-
- bot = 0;
- top = bot + nelem(kwd) - 1;
- while(bot <= top){
- new = bot + (top - bot)/2;
- i = strcmp(kwd[new]+1, s);
- if(i == 0)
- return kwd[new];
-
- if(i < 0)
- bot = new + 1;
- else
- top = new - 1;
- }
- return s;
-}
-
-Sym*
-acidsue(Type *t)
-{
- int h;
- Sym *s;
-
- if(t != T)
- for(h=0; h<nelem(hash); h++)
- for(s = hash[h]; s != S; s = s->link)
- if(s->suetag && s->suetag->link == t)
- return s;
- return 0;
-}
-
-Sym*
-acidfun(Type *t)
-{
- int h;
- Sym *s;
-
- for(h=0; h<nelem(hash); h++)
- for(s = hash[h]; s != S; s = s->link)
- if(s->type == t)
- return s;
- return 0;
-}
-
-char acidchar[NTYPE];
-Init acidcinit[] =
-{
- TCHAR, 'C', 0,
- TUCHAR, 'b', 0,
- TSHORT, 'd', 0,
- TUSHORT, 'u', 0,
- TLONG, 'D', 0,
- TULONG, 'U', 0,
- TVLONG, 'V', 0,
- TUVLONG, 'W', 0,
- TFLOAT, 'f', 0,
- TDOUBLE, 'F', 0,
- TARRAY, 'a', 0,
- TIND, 'X', 0,
- -1, 0, 0,
-};
-
-static void
-acidinit(void)
-{
- Init *p;
-
- for(p=acidcinit; p->code >= 0; p++)
- acidchar[p->code] = p->value;
-
- acidchar[TINT] = acidchar[TLONG];
- acidchar[TUINT] = acidchar[TULONG];
- if(types[TINT]->width != types[TLONG]->width) {
- acidchar[TINT] = acidchar[TSHORT];
- acidchar[TUINT] = acidchar[TUSHORT];
- if(types[TINT]->width != types[TSHORT]->width)
- warn(Z, "acidmember int not long or short");
- }
- if(types[TIND]->width == types[TUVLONG]->width)
- acidchar[TIND] = 'Y';
-
-}
-
-void
-acidmember(Type *t, int32 off, int flag)
-{
- Sym *s, *s1;
- Type *l;
- static int acidcharinit = 0;
-
- if(acidcharinit == 0) {
- acidinit();
- acidcharinit = 1;
- }
- s = t->sym;
- switch(t->etype) {
- default:
- Bprint(&outbuf, " T%d\n", t->etype);
- break;
-
- case TIND:
- if(s == S)
- break;
- l = t->link;
- if(flag) {
- if(typesu[l->etype]) {
- s1 = acidsue(l->link);
- if(s1 != S) {
- Bprint(&outbuf, " 'A' %s %d %s;\n",
- amap(s1->name),
- t->offset+off, amap(s->name));
- break;
- }
- }
- } else {
- l = t->link;
- s1 = S;
- if(typesu[l->etype])
- s1 = acidsue(l->link);
- if(s1 != S) {
- Bprint(&outbuf,
- "\tprint(indent, \"%s\t(%s)\", addr.%s\\X, \"\\n\");\n",
- amap(s->name), amap(s1->name), amap(s->name));
- } else {
- Bprint(&outbuf,
- "\tprint(indent, \"%s\t\", addr.%s\\X, \"\\n\");\n",
- amap(s->name), amap(s->name));
- }
- break;
- }
-
- case TINT:
- case TUINT:
- case TCHAR:
- case TUCHAR:
- case TSHORT:
- case TUSHORT:
- case TLONG:
- case TULONG:
- case TVLONG:
- case TUVLONG:
- case TFLOAT:
- case TDOUBLE:
- case TARRAY:
- if(s == S)
- break;
- if(flag) {
- Bprint(&outbuf, " '%c' %d %s;\n",
- acidchar[t->etype], t->offset+off, amap(s->name));
- } else {
- Bprint(&outbuf, "\tprint(indent, \"%s\t\", addr.%s, \"\\n\");\n",
- amap(s->name), amap(s->name));
- }
- break;
-
- case TSTRUCT:
- case TUNION:
- s1 = acidsue(t->link);
- if(s1 == S)
- break;
- if(flag) {
- if(s == S) {
- Bprint(&outbuf, " {\n");
- for(l = t->link; l != T; l = l->down)
- acidmember(l, t->offset+off, flag);
- Bprint(&outbuf, " };\n");
- } else {
- Bprint(&outbuf, " %s %d %s;\n",
- amap(s1->name),
- t->offset+off, amap(s->name));
- }
- } else {
- if(s != S) {
- Bprint(&outbuf, "\tprint(indent, \"%s %s {\\n\");\n",
- amap(s1->name), amap(s->name));
- Bprint(&outbuf, "\tindent_%s(addr.%s, indent+\"\\t\");\n",
- amap(s1->name), amap(s->name));
- Bprint(&outbuf, "\tprint(indent, \"}\\n\");\n");
- } else {
- Bprint(&outbuf, "\tprint(indent, \"%s {\\n\");\n",
- amap(s1->name));
- Bprint(&outbuf, "\tindent_%s(addr+%d, indent+\"\\t\");\n",
- amap(s1->name), t->offset+off);
- Bprint(&outbuf, "\tprint(indent, \"}\\n\");\n");
- }
- }
- break;
- }
-}
-
-void
-acidtype(Type *t)
-{
- Sym *s;
- Type *l;
- Io *i;
- int n;
- char *an;
-
- if(!debug['a'])
- return;
- if(debug['a'] > 1) {
- n = 0;
- for(i=iostack; i; i=i->link)
- n++;
- if(n > 1)
- return;
- }
- s = acidsue(t->link);
- if(s == S)
- return;
- switch(t->etype) {
- default:
- Bprint(&outbuf, "T%d\n", t->etype);
- return;
-
- case TUNION:
- case TSTRUCT:
- if(debug['s'])
- goto asmstr;
- an = amap(s->name);
- Bprint(&outbuf, "sizeof%s = %d;\n", an, t->width);
- Bprint(&outbuf, "aggr %s\n{\n", an);
- for(l = t->link; l != T; l = l->down)
- acidmember(l, 0, 1);
- Bprint(&outbuf, "};\n\n");
-
- Bprint(&outbuf, "defn\n%s(addr) {\n\tindent_%s(addr, \"\\t\");\n}\n", an, an);
- Bprint(&outbuf, "defn\nindent_%s(addr, indent) {\n\tcomplex %s addr;\n", an, an);
- for(l = t->link; l != T; l = l->down)
- acidmember(l, 0, 0);
- Bprint(&outbuf, "};\n\n");
- break;
- asmstr:
- if(s == S)
- break;
- for(l = t->link; l != T; l = l->down)
- if(l->sym != S)
- Bprint(&outbuf, "#define\t%s.%s\t%d\n",
- s->name,
- l->sym->name,
- l->offset);
- break;
- }
-}
-
-void
-acidvar(Sym *s)
-{
- int n;
- Io *i;
- Type *t;
- Sym *s1, *s2;
-
- if(!debug['a'] || debug['s'])
- return;
- if(debug['a'] > 1) {
- n = 0;
- for(i=iostack; i; i=i->link)
- n++;
- if(n > 1)
- return;
- }
- t = s->type;
- while(t && t->etype == TIND)
- t = t->link;
- if(t == T)
- return;
- if(t->etype == TENUM) {
- Bprint(&outbuf, "%s = ", amap(s->name));
- if(!typefd[t->etype])
- Bprint(&outbuf, "%lld;\n", s->vconst);
- else
- Bprint(&outbuf, "%f\n;", s->fconst);
- return;
- }
- if(!typesu[t->etype])
- return;
- s1 = acidsue(t->link);
- if(s1 == S)
- return;
- switch(s->class) {
- case CAUTO:
- case CPARAM:
- s2 = acidfun(thisfn);
- if(s2)
- Bprint(&outbuf, "complex %s %s:%s;\n",
- amap(s1->name), amap(s2->name), amap(s->name));
- break;
-
- case CSTATIC:
- case CEXTERN:
- case CGLOBL:
- case CLOCAL:
- Bprint(&outbuf, "complex %s %s;\n",
- amap(s1->name), amap(s->name));
- break;
- }
-}
diff --git a/src/cmd/cc/bits.c b/src/cmd/cc/bits.c
deleted file mode 100644
index 4496d65e7..000000000
--- a/src/cmd/cc/bits.c
+++ /dev/null
@@ -1,120 +0,0 @@
-// Inferno utils/cc/bits.c
-// http://code.google.com/p/inferno-os/source/browse/utils/cc/bits.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include <u.h>
-#include "cc.h"
-
-Bits
-bor(Bits a, Bits b)
-{
- Bits c;
- int i;
-
- for(i=0; i<BITS; i++)
- c.b[i] = a.b[i] | b.b[i];
- return c;
-}
-
-Bits
-band(Bits a, Bits b)
-{
- Bits c;
- int i;
-
- for(i=0; i<BITS; i++)
- c.b[i] = a.b[i] & b.b[i];
- return c;
-}
-
-/*
-Bits
-bnot(Bits a)
-{
- Bits c;
- int i;
-
- for(i=0; i<BITS; i++)
- c.b[i] = ~a.b[i];
- return c;
-}
-*/
-
-int
-bany(Bits *a)
-{
- int i;
-
- for(i=0; i<BITS; i++)
- if(a->b[i])
- return 1;
- return 0;
-}
-
-int
-beq(Bits a, Bits b)
-{
- int i;
-
- for(i=0; i<BITS; i++)
- if(a.b[i] != b.b[i])
- return 0;
- return 1;
-}
-
-int
-bnum(Bits a)
-{
- int i;
- int32 b;
-
- for(i=0; i<BITS; i++)
- if(b = a.b[i])
- return 32*i + bitno(b);
- diag(Z, "bad in bnum");
- return 0;
-}
-
-Bits
-blsh(uint n)
-{
- Bits c;
-
- c = zbits;
- c.b[n/32] = 1L << (n%32);
- return c;
-}
-
-int
-bset(Bits a, uint n)
-{
- if(a.b[n/32] & (1L << (n%32)))
- return 1;
- return 0;
-}
diff --git a/src/cmd/cc/cc.h b/src/cmd/cc/cc.h
deleted file mode 100644
index 9530f5cf6..000000000
--- a/src/cmd/cc/cc.h
+++ /dev/null
@@ -1,835 +0,0 @@
-// Inferno utils/cc/cc.h
-// http://code.google.com/p/inferno-os/source/browse/utils/cc/cc.h
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include <libc.h>
-#include <bio.h>
-#include <link.h>
-
-#ifndef EXTERN
-#define EXTERN extern
-#endif
-
-#undef getc
-#undef ungetc
-#undef BUFSIZ
-
-#define getc ccgetc
-#define ungetc ccungetc
-
-typedef struct Node Node;
-typedef struct Sym Sym;
-typedef struct Type Type;
-typedef struct Funct Funct;
-typedef struct Decl Decl;
-typedef struct Io Io;
-typedef struct Term Term;
-typedef struct Init Init;
-typedef struct Bits Bits;
-typedef struct Bvec Bvec;
-typedef struct Dynimp Dynimp;
-typedef struct Dynexp Dynexp;
-typedef struct Var Var;
-
-typedef Rune TRune; /* target system type */
-
-#define BUFSIZ 8192
-#define NSYMB 500
-#define NHASH 1024
-#define STRINGSZ 200
-#define HISTSZ 20
-#define YYMAXDEPTH 500
-#define NTERM 10
-#define MAXALIGN 7
-
-#define SIGN(n) ((uvlong)1<<(n-1))
-#define MASK(n) (SIGN(n)|(SIGN(n)-1))
-
-#define BITS 5
-#define NVAR (BITS*sizeof(uint32)*8)
-struct Bits
-{
- uint32 b[BITS];
-};
-
-struct Bvec
-{
- int32 n; // number of bits
- uint32 b[];
-};
-
-struct Var
-{
- vlong offset;
- LSym* sym;
- char name;
- char etype;
-};
-
-struct Node
-{
- Node* left;
- Node* right;
- void* label;
- int32 pc;
- int reg;
- int32 xoffset;
- double fconst; /* fp constant */
- vlong vconst; /* non fp const */
- char* cstring; /* character string */
- TRune* rstring; /* rune string */
-
- Sym* sym;
- Type* type;
- int32 lineno;
- uchar op;
- uchar oldop;
- uchar xcast;
- uchar class;
- uchar etype;
- uchar complex;
- uchar addable;
- uchar scale;
- uchar garb;
-};
-#define Z ((Node*)0)
-
-struct Sym
-{
- Sym* link;
- LSym* lsym;
- Type* type;
- Type* suetag;
- Type* tenum;
- char* macro;
- int32 varlineno;
- int32 offset;
- vlong vconst;
- double fconst;
- Node* label;
- ushort lexical;
- char *name;
- ushort block;
- ushort sueblock;
- uchar class;
- uchar sym;
- uchar aused;
- uchar sig;
- uchar dataflag;
-};
-#define S ((Sym*)0)
-
-enum{
- SIGNONE = 0,
- SIGDONE = 1,
- SIGINTERN = 2,
-
- SIGNINTERN = 1729*325*1729,
-};
-
-struct Decl
-{
- Decl* link;
- Sym* sym;
- Type* type;
- int32 varlineno;
- int32 offset;
- short val;
- ushort block;
- uchar class;
- uchar aused;
-};
-#define D ((Decl*)0)
-
-struct Type
-{
- Sym* sym;
- Sym* tag;
- Funct* funct;
- Type* link;
- Type* down;
- int32 width;
- int32 offset;
- int32 lineno;
- uchar shift;
- uchar nbits;
- uchar etype;
- uchar garb;
- uchar align;
-};
-
-#define T ((Type*)0)
-#define NODECL ((void(*)(int, Type*, Sym*))0)
-
-struct Init /* general purpose initialization */
-{
- int code;
- uint32 value;
- char* s;
-};
-
-EXTERN struct
-{
- char* p;
- int c;
-} fi;
-
-struct Io
-{
- Io* link;
- char* p;
- char b[BUFSIZ];
- short c;
- short f;
-};
-#define I ((Io*)0)
-
-struct Term
-{
- vlong mult;
- Node *node;
-};
-
-enum
-{
- Axxx,
- Ael1,
- Ael2,
- Asu2,
- Aarg0,
- Aarg1,
- Aarg2,
- Aaut3,
- NALIGN,
-};
-
-enum
-{
- DMARK,
- DAUTO,
- DSUE,
- DLABEL,
-};
-enum
-{
- OXXX,
- OADD,
- OADDR,
- OAND,
- OANDAND,
- OARRAY,
- OAS,
- OASI,
- OASADD,
- OASAND,
- OASASHL,
- OASASHR,
- OASDIV,
- OASHL,
- OASHR,
- OASLDIV,
- OASLMOD,
- OASLMUL,
- OASLSHR,
- OASMOD,
- OASMUL,
- OASOR,
- OASSUB,
- OASXOR,
- OBIT,
- OBREAK,
- OCASE,
- OCAST,
- OCOMMA,
- OCOND,
- OCONST,
- OCONTINUE,
- ODIV,
- ODOT,
- ODOTDOT,
- ODWHILE,
- OENUM,
- OEQ,
- OEXREG,
- OFOR,
- OFUNC,
- OGE,
- OGOTO,
- OGT,
- OHI,
- OHS,
- OIF,
- OIND,
- OINDREG,
- OINIT,
- OLABEL,
- OLDIV,
- OLE,
- OLIST,
- OLMOD,
- OLMUL,
- OLO,
- OLS,
- OLSHR,
- OLT,
- OMOD,
- OMUL,
- ONAME,
- ONE,
- ONOT,
- OOR,
- OOROR,
- OPOSTDEC,
- OPOSTINC,
- OPREDEC,
- OPREINC,
- OPREFETCH,
- OPROTO,
- OREGISTER,
- ORETURN,
- OSET,
- OSIGN,
- OSIZE,
- OSTRING,
- OLSTRING,
- OSTRUCT,
- OSUB,
- OSWITCH,
- OUNION,
- OUSED,
- OWHILE,
- OXOR,
- ONEG,
- OCOM,
- OPOS,
- OELEM,
-
- OTST, /* used in some compilers */
- OINDEX,
- OFAS,
- OREGPAIR,
- OROTL,
-
- OEND
-};
-enum
-{
- TXXX,
- TCHAR,
- TUCHAR,
- TSHORT,
- TUSHORT,
- TINT,
- TUINT,
- TLONG,
- TULONG,
- TVLONG,
- TUVLONG,
- TFLOAT,
- TDOUBLE,
- TIND,
- TFUNC,
- TARRAY,
- TVOID,
- TSTRUCT,
- TUNION,
- TENUM,
- NTYPE,
-
- TAUTO = NTYPE,
- TEXTERN,
- TSTATIC,
- TTYPEDEF,
- TTYPESTR,
- TREGISTER,
- TCONSTNT,
- TVOLATILE,
- TUNSIGNED,
- TSIGNED,
- TDOT,
- TFILE,
- TOLD,
- NALLTYPES,
-
- /* adapt size of Rune to target system's size */
- TRUNE = sizeof(TRune)==4? TUINT: TUSHORT,
-};
-enum
-{
- CXXX,
- CAUTO,
- CEXTERN,
- CGLOBL,
- CSTATIC,
- CLOCAL,
- CTYPEDEF,
- CTYPESTR,
- CPARAM,
- CSELEM,
- CLABEL,
- CEXREG,
- NCTYPES,
-};
-enum
-{
- GXXX = 0,
- GCONSTNT = 1<<0,
- GVOLATILE = 1<<1,
- NGTYPES = 1<<2,
-
- GINCOMPLETE = 1<<2,
-};
-enum
-{
- BCHAR = 1L<<TCHAR,
- BUCHAR = 1L<<TUCHAR,
- BSHORT = 1L<<TSHORT,
- BUSHORT = 1L<<TUSHORT,
- BINT = 1L<<TINT,
- BUINT = 1L<<TUINT,
- BLONG = 1L<<TLONG,
- BULONG = 1L<<TULONG,
- BVLONG = 1L<<TVLONG,
- BUVLONG = 1L<<TUVLONG,
- BFLOAT = 1L<<TFLOAT,
- BDOUBLE = 1L<<TDOUBLE,
- BIND = 1L<<TIND,
- BFUNC = 1L<<TFUNC,
- BARRAY = 1L<<TARRAY,
- BVOID = 1L<<TVOID,
- BSTRUCT = 1L<<TSTRUCT,
- BUNION = 1L<<TUNION,
- BENUM = 1L<<TENUM,
- BFILE = 1L<<TFILE,
- BDOT = 1L<<TDOT,
- BCONSTNT = 1L<<TCONSTNT,
- BVOLATILE = 1L<<TVOLATILE,
- BUNSIGNED = 1L<<TUNSIGNED,
- BSIGNED = 1L<<TSIGNED,
- BAUTO = 1L<<TAUTO,
- BEXTERN = 1L<<TEXTERN,
- BSTATIC = 1L<<TSTATIC,
- BTYPEDEF = 1L<<TTYPEDEF,
- BTYPESTR = 1L<<TTYPESTR,
- BREGISTER = 1L<<TREGISTER,
-
- BINTEGER = BCHAR|BUCHAR|BSHORT|BUSHORT|BINT|BUINT|
- BLONG|BULONG|BVLONG|BUVLONG,
- BNUMBER = BINTEGER|BFLOAT|BDOUBLE,
-
-/* these can be overloaded with complex types */
-
- BCLASS = BAUTO|BEXTERN|BSTATIC|BTYPEDEF|BTYPESTR|BREGISTER,
- BGARB = BCONSTNT|BVOLATILE,
-};
-
-struct Funct
-{
- Sym* sym[OEND];
- Sym* castto[NTYPE];
- Sym* castfr[NTYPE];
-};
-
-EXTERN struct
-{
- Type* tenum; /* type of entire enum */
- Type* cenum; /* type of current enum run */
- vlong lastenum; /* value of current enum */
- double floatenum; /* value of current enum */
-} en;
-
-EXTERN int autobn;
-EXTERN int32 autoffset;
-EXTERN int blockno;
-EXTERN Decl* dclstack;
-EXTERN int debug[256];
-EXTERN int32 firstbit;
-EXTERN Sym* firstarg;
-EXTERN Type* firstargtype;
-EXTERN Decl* firstdcl;
-EXTERN int fperror;
-EXTERN Sym* hash[NHASH];
-EXTERN char* hunk;
-EXTERN char** include;
-EXTERN Io* iofree;
-EXTERN Io* ionext;
-EXTERN Io* iostack;
-EXTERN int32 lastbit;
-EXTERN char lastclass;
-EXTERN Type* lastdcl;
-EXTERN int32 lastfield;
-EXTERN Type* lasttype;
-EXTERN int32 lineno;
-EXTERN int32 nearln;
-EXTERN int nerrors;
-EXTERN int newflag;
-EXTERN int32 nhunk;
-EXTERN int ninclude;
-EXTERN Node* nodproto;
-EXTERN Node* nodcast;
-EXTERN int32 nsymb;
-EXTERN Biobuf outbuf;
-EXTERN Biobuf diagbuf;
-EXTERN char* outfile;
-EXTERN int peekc;
-EXTERN int32 stkoff;
-EXTERN Type* strf;
-EXTERN Type* strl;
-EXTERN char* symb;
-EXTERN Sym* symstring;
-EXTERN int taggen;
-EXTERN Type* tfield;
-EXTERN Type* tufield;
-extern int thechar;
-extern char* thestring;
-extern LinkArch* thelinkarch;
-EXTERN Type* thisfn;
-EXTERN int32 thunk;
-EXTERN Type* types[NALLTYPES];
-EXTERN Type* fntypes[NALLTYPES];
-EXTERN Node* initlist;
-EXTERN Term term[NTERM];
-EXTERN int nterm;
-EXTERN int packflg;
-EXTERN int fproundflg;
-EXTERN int textflag;
-EXTERN int dataflag;
-EXTERN int flag_largemodel;
-EXTERN int ncontin;
-EXTERN int canreach;
-EXTERN int warnreach;
-EXTERN int nacl;
-EXTERN Bits zbits;
-EXTERN Fmt pragcgobuf;
-EXTERN Biobuf bstdout;
-EXTERN Var var[NVAR];
-
-extern char *onames[], *tnames[], *gnames[];
-extern char *cnames[], *qnames[], *bnames[];
-extern uchar tab[NTYPE][NTYPE];
-extern uchar comrel[], invrel[], logrel[];
-extern int32 ncast[], tadd[], tand[];
-extern int32 targ[], tasadd[], tasign[], tcast[];
-extern int32 tdot[], tfunct[], tindir[], tmul[];
-extern int32 tnot[], trel[], tsub[];
-
-extern uchar typeaf[];
-extern uchar typefd[];
-extern uchar typei[];
-extern uchar typesu[];
-extern uchar typesuv[];
-extern uchar typeu[];
-extern uchar typev[];
-extern uchar typec[];
-extern uchar typeh[];
-extern uchar typeil[];
-extern uchar typeilp[];
-extern uchar typechl[];
-extern uchar typechlv[];
-extern uchar typechlvp[];
-extern uchar typechlp[];
-extern uchar typechlpfd[];
-
-EXTERN uchar* typeword;
-EXTERN uchar* typecmplx;
-EXTERN Link* ctxt;
-
-extern uint32 thash1;
-extern uint32 thash2;
-extern uint32 thash3;
-extern uint32 thash[];
-
-/*
- * compat.c/unix.c/windows.c
- */
-int systemtype(int);
-int pathchar(void);
-
-/*
- * parser
- */
-int yyparse(void);
-int mpatov(char*, vlong*);
-
-/*
- * lex.c
- */
-void* allocn(void*, int32, int32);
-void* alloc(int32);
-void ensuresymb(int32);
-void cinit(void);
-int compile(char*, char**, int);
-void errorexit(void);
-int filbuf(void);
-int getc(void);
-int32 getr(void);
-int getnsc(void);
-Sym* lookup(void);
-void main(int, char*[]);
-void newfile(char*, int);
-void newio(void);
-void pushio(void);
-int32 escchar(int32, int, int);
-Sym* slookup(char*);
-void syminit(Sym*);
-void unget(int);
-int32 yylex(void);
-int Lconv(Fmt*);
-int Tconv(Fmt*);
-int FNconv(Fmt*);
-int Oconv(Fmt*);
-int Qconv(Fmt*);
-int VBconv(Fmt*);
-int Bconv(Fmt*);
-void setinclude(char*);
-
-/*
- * mac.c
- */
-void dodefine(char*);
-void domacro(void);
-Sym* getsym(void);
-int32 getnsn(void);
-void macdef(void);
-void macprag(void);
-void macend(void);
-void macexpand(Sym*, char*);
-void macif(int);
-void macinc(void);
-void maclin(void);
-void macund(void);
-
-/*
- * dcl.c
- */
-Node* doinit(Sym*, Type*, int32, Node*);
-Type* tcopy(Type*);
-Node* init1(Sym*, Type*, int32, int);
-Node* newlist(Node*, Node*);
-void adecl(int, Type*, Sym*);
-int anyproto(Node*);
-void argmark(Node*, int);
-void dbgdecl(Sym*);
-Node* dcllabel(Sym*, int);
-Node* dodecl(void(*)(int, Type*, Sym*), int, Type*, Node*);
-Sym* mkstatic(Sym*);
-void doenum(Sym*, Node*);
-void snap(Type*);
-Type* dotag(Sym*, int, int);
-void edecl(int, Type*, Sym*);
-Type* fnproto(Node*);
-Type* fnproto1(Node*);
-void markdcl(void);
-Type* paramconv(Type*, int);
-void pdecl(int, Type*, Sym*);
-Decl* push(void);
-Decl* push1(Sym*);
-Node* revertdcl(void);
-int32 xround(int32, int);
-int rsametype(Type*, Type*, int, int);
-int sametype(Type*, Type*);
-uint32 sign(Sym*);
-uint32 signature(Type*);
-void sualign(Type*);
-void tmerge(Type*, Sym*);
-void walkparam(Node*, int);
-void xdecl(int, Type*, Sym*);
-Node* contig(Sym*, Node*, int32);
-
-/*
- * com.c
- */
-void ccom(Node*);
-void complex(Node*);
-int tcom(Node*);
-int tcoma(Node*, Node*, Type*, int);
-int tcomd(Node*);
-int tcomo(Node*, int);
-int tcomx(Node*);
-int tlvalue(Node*);
-void constas(Node*, Type*, Type*);
-
-/*
- * con.c
- */
-void acom(Node*);
-void acom1(vlong, Node*);
-void acom2(Node*, Type*);
-int acomcmp1(const void*, const void*);
-int acomcmp2(const void*, const void*);
-int addo(Node*);
-void evconst(Node*);
-
-/*
- * funct.c
- */
-int isfunct(Node*);
-void dclfunct(Type*, Sym*);
-
-/*
- * sub.c
- */
-void arith(Node*, int);
-int deadheads(Node*);
-Type* dotsearch(Sym*, Type*, Node*, int32*);
-int32 dotoffset(Type*, Type*, Node*);
-void gethunk(void);
-Node* invert(Node*);
-int bitno(int32);
-void makedot(Node*, Type*, int32);
-int mixedasop(Type*, Type*);
-Node* new(int, Node*, Node*);
-Node* new1(int, Node*, Node*);
-int nilcast(Type*, Type*);
-int nocast(Type*, Type*);
-void prtree(Node*, char*);
-void prtree1(Node*, int, int);
-void relcon(Node*, Node*);
-int relindex(int);
-int simpleg(int32);
-Type* garbt(Type*, int32);
-int simplec(int32);
-Type* simplet(int32);
-int stcompat(Node*, Type*, Type*, int32[]);
-int tcompat(Node*, Type*, Type*, int32[]);
-void tinit(void);
-Type* typ(int, Type*);
-Type* copytyp(Type*);
-void typeext(Type*, Node*);
-void typeext1(Type*, Node*);
-int side(Node*);
-int vconst(Node*);
-int xlog2(uvlong);
-int vlog(Node*);
-int topbit(uint32);
-void simplifyshift(Node*);
-int32 typebitor(int32, int32);
-void diag(Node*, char*, ...);
-void warn(Node*, char*, ...);
-void yyerror(char*, ...);
-void fatal(Node*, char*, ...);
-LSym* linksym(Sym*);
-
-/*
- * acid.c
- */
-void acidtype(Type*);
-void acidvar(Sym*);
-
-/*
- * godefs.c
- */
-int Uconv(Fmt*);
-void godeftype(Type*);
-void godefvar(Sym*);
-
-/*
- * bits.c
- */
-Bits bor(Bits, Bits);
-Bits band(Bits, Bits);
-Bits bnot(Bits);
-int bany(Bits*);
-int bnum(Bits);
-Bits blsh(uint);
-int beq(Bits, Bits);
-int bset(Bits, uint);
-
-/*
- * dpchk.c
- */
-void dpcheck(Node*);
-void arginit(void);
-void pragvararg(void);
-void pragpack(void);
-void pragfpround(void);
-void pragdataflag(void);
-void pragtextflag(void);
-void pragincomplete(void);
-void pragcgo(char*);
-
-/*
- * calls to machine depend part
- */
-void codgen(Node*, Node*);
-void gclean(void);
-void gextern(Sym*, Node*, int32, int32);
-void ginit(void);
-int32 outstring(char*, int32);
-int32 outlstring(TRune*, int32);
-void sextern(Sym*, Node*, int32, int32);
-void xcom(Node*);
-int32 exreg(Type*);
-int32 align(int32, Type*, int, int32*);
-int32 maxround(int32, int32);
-int hasdotdotdot(Type*);
-void linkarchinit(void);
-
-extern schar ewidth[];
-
-/*
- * com64
- */
-int com64(Node*);
-void com64init(void);
-void bool64(Node*);
-double convvtof(vlong);
-vlong convftov(double);
-double convftox(double, int);
-vlong convvtox(vlong, int);
-
-/*
- * machcap
- */
-int machcap(Node*);
-
-#pragma varargck argpos warn 2
-#pragma varargck argpos diag 2
-#pragma varargck argpos yyerror 1
-
-#pragma varargck type "B" Bits
-#pragma varargck type "F" Node*
-#pragma varargck type "L" int32
-#pragma varargck type "Q" int32
-#pragma varargck type "O" int
-#pragma varargck type "O" uint
-#pragma varargck type "T" Type*
-#pragma varargck type "U" char*
-#pragma varargck type "|" int
-
-enum
-{
- Plan9 = 1<<0,
- Unix = 1<<1,
- Windows = 1<<2,
-};
-int pathchar(void);
-int systemtype(int);
-void* alloc(int32 n);
-void* allocn(void*, int32, int32);
diff --git a/src/cmd/cc/cc.y b/src/cmd/cc/cc.y
deleted file mode 100644
index 8d7cb1472..000000000
--- a/src/cmd/cc/cc.y
+++ /dev/null
@@ -1,1220 +0,0 @@
-// Inferno utils/cc/cc.y
-// http://code.google.com/p/inferno-os/source/browse/utils/cc/cc.y
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-%{
-#include <u.h>
-#include <stdio.h> /* if we don't, bison will, and cc.h re-#defines getc */
-#include "cc.h"
-%}
-%union {
- Node* node;
- Sym* sym;
- Type* type;
- struct
- {
- Type* t;
- uchar c;
- } tycl;
- struct
- {
- Type* t1;
- Type* t2;
- Type* t3;
- uchar c;
- } tyty;
- struct
- {
- char* s;
- int32 l;
- } sval;
- int32 lval;
- double dval;
- vlong vval;
-}
-%type <sym> ltag
-%type <lval> gctname gcname cname gname tname
-%type <lval> gctnlist gcnlist zgnlist
-%type <type> tlist sbody complex
-%type <tycl> types
-%type <node> zarglist arglist zcexpr
-%type <node> name block stmnt cexpr expr xuexpr pexpr
-%type <node> zelist elist adecl slist uexpr string lstring
-%type <node> xdecor xdecor2 labels label ulstmnt
-%type <node> adlist edecor tag qual qlist
-%type <node> abdecor abdecor1 abdecor2 abdecor3
-%type <node> zexpr lexpr init ilist forexpr
-
-%left ';'
-%left ','
-%right '=' LPE LME LMLE LDVE LMDE LRSHE LLSHE LANDE LXORE LORE
-%right '?' ':'
-%left LOROR
-%left LANDAND
-%left '|'
-%left '^'
-%left '&'
-%left LEQ LNE
-%left '<' '>' LLE LGE
-%left LLSH LRSH
-%left '+' '-'
-%left '*' '/' '%'
-%right LMM LPP LMG '.' '[' '('
-
-%token <sym> LNAME LTYPE
-%token <dval> LFCONST LDCONST
-%token <vval> LCONST LLCONST LUCONST LULCONST LVLCONST LUVLCONST
-%token <sval> LSTRING LLSTRING
-%token LAUTO LBREAK LCASE LCHAR LCONTINUE LDEFAULT LDO
-%token LDOUBLE LELSE LEXTERN LFLOAT LFOR LGOTO
-%token LIF LINT LLONG LPREFETCH LREGISTER LRETURN LSHORT LSIZEOF LUSED
-%token LSTATIC LSTRUCT LSWITCH LTYPEDEF LTYPESTR LUNION LUNSIGNED
-%token LWHILE LVOID LENUM LSIGNED LCONSTNT LVOLATILE LSET LSIGNOF
-%token LRESTRICT LINLINE
-%%
-prog:
-| prog xdecl
-
-/*
- * external declarator
- */
-xdecl:
- zctlist ';'
- {
- dodecl(xdecl, lastclass, lasttype, Z);
- }
-| zctlist xdlist ';'
-| zctlist xdecor
- {
- lastdcl = T;
- firstarg = S;
- dodecl(xdecl, lastclass, lasttype, $2);
- if(lastdcl == T || lastdcl->etype != TFUNC) {
- diag($2, "not a function");
- lastdcl = types[TFUNC];
- }
- thisfn = lastdcl;
- markdcl();
- firstdcl = dclstack;
- argmark($2, 0);
- }
- pdecl
- {
- argmark($2, 1);
- }
- block
- {
- Node *n;
-
- n = revertdcl();
- if(n)
- $6 = new(OLIST, n, $6);
- if(!debug['a'] && !debug['Z'])
- codgen($6, $2);
- }
-
-xdlist:
- xdecor
- {
- dodecl(xdecl, lastclass, lasttype, $1);
- }
-| xdecor
- {
- $1 = dodecl(xdecl, lastclass, lasttype, $1);
- }
- '=' init
- {
- doinit($1->sym, $1->type, 0L, $4);
- }
-| xdlist ',' xdlist
-
-xdecor:
- xdecor2
-| '*' zgnlist xdecor
- {
- $$ = new(OIND, $3, Z);
- $$->garb = simpleg($2);
- }
-
-xdecor2:
- tag
-| '(' xdecor ')'
- {
- $$ = $2;
- }
-| xdecor2 '(' zarglist ')'
- {
- $$ = new(OFUNC, $1, $3);
- }
-| xdecor2 '[' zexpr ']'
- {
- $$ = new(OARRAY, $1, $3);
- }
-
-/*
- * automatic declarator
- */
-adecl:
- ctlist ';'
- {
- $$ = dodecl(adecl, lastclass, lasttype, Z);
- }
-| ctlist adlist ';'
- {
- $$ = $2;
- }
-
-adlist:
- xdecor
- {
- dodecl(adecl, lastclass, lasttype, $1);
- $$ = Z;
- }
-| xdecor
- {
- $1 = dodecl(adecl, lastclass, lasttype, $1);
- }
- '=' init
- {
- int32 w;
-
- w = $1->sym->type->width;
- $$ = doinit($1->sym, $1->type, 0L, $4);
- $$ = contig($1->sym, $$, w);
- }
-| adlist ',' adlist
- {
- $$ = $1;
- if($3 != Z) {
- $$ = $3;
- if($1 != Z)
- $$ = new(OLIST, $1, $3);
- }
- }
-
-/*
- * parameter declarator
- */
-pdecl:
-| pdecl ctlist pdlist ';'
-
-pdlist:
- xdecor
- {
- dodecl(pdecl, lastclass, lasttype, $1);
- }
-| pdlist ',' pdlist
-
-/*
- * structure element declarator
- */
-edecl:
- tlist
- {
- lasttype = $1;
- }
- zedlist ';'
-| edecl tlist
- {
- lasttype = $2;
- }
- zedlist ';'
-
-zedlist: /* extension */
- {
- lastfield = 0;
- edecl(CXXX, lasttype, S);
- }
-| edlist
-
-edlist:
- edecor
- {
- dodecl(edecl, CXXX, lasttype, $1);
- }
-| edlist ',' edlist
-
-edecor:
- xdecor
- {
- lastbit = 0;
- firstbit = 1;
- }
-| tag ':' lexpr
- {
- $$ = new(OBIT, $1, $3);
- }
-| ':' lexpr
- {
- $$ = new(OBIT, Z, $2);
- }
-
-/*
- * abstract declarator
- */
-abdecor:
- {
- $$ = (Z);
- }
-| abdecor1
-
-abdecor1:
- '*' zgnlist
- {
- $$ = new(OIND, (Z), Z);
- $$->garb = simpleg($2);
- }
-| '*' zgnlist abdecor1
- {
- $$ = new(OIND, $3, Z);
- $$->garb = simpleg($2);
- }
-| abdecor2
-
-abdecor2:
- abdecor3
-| abdecor2 '(' zarglist ')'
- {
- $$ = new(OFUNC, $1, $3);
- }
-| abdecor2 '[' zexpr ']'
- {
- $$ = new(OARRAY, $1, $3);
- }
-
-abdecor3:
- '(' ')'
- {
- $$ = new(OFUNC, (Z), Z);
- }
-| '[' zexpr ']'
- {
- $$ = new(OARRAY, (Z), $2);
- }
-| '(' abdecor1 ')'
- {
- $$ = $2;
- }
-
-init:
- expr
-| '{' ilist '}'
- {
- $$ = new(OINIT, invert($2), Z);
- }
-
-qual:
- '[' lexpr ']'
- {
- $$ = new(OARRAY, $2, Z);
- }
-| '.' ltag
- {
- $$ = new(OELEM, Z, Z);
- $$->sym = $2;
- }
-| qual '='
-
-qlist:
- init ','
-| qlist init ','
- {
- $$ = new(OLIST, $1, $2);
- }
-| qual
-| qlist qual
- {
- $$ = new(OLIST, $1, $2);
- }
-
-ilist:
- qlist
-| init
-| qlist init
- {
- $$ = new(OLIST, $1, $2);
- }
-
-zarglist:
- {
- $$ = Z;
- }
-| arglist
- {
- $$ = invert($1);
- }
-
-
-arglist:
- name
-| tlist abdecor
- {
- $$ = new(OPROTO, $2, Z);
- $$->type = $1;
- }
-| tlist xdecor
- {
- $$ = new(OPROTO, $2, Z);
- $$->type = $1;
- }
-| '.' '.' '.'
- {
- $$ = new(ODOTDOT, Z, Z);
- }
-| arglist ',' arglist
- {
- $$ = new(OLIST, $1, $3);
- }
-
-block:
- '{' slist '}'
- {
- $$ = invert($2);
- // if($2 != Z)
- // $$ = new(OLIST, $2, $$);
- if($$ == Z)
- $$ = new(OLIST, Z, Z);
- }
-
-slist:
- {
- $$ = Z;
- }
-| slist adecl
- {
- $$ = new(OLIST, $1, $2);
- }
-| slist stmnt
- {
- $$ = new(OLIST, $1, $2);
- }
-
-labels:
- label
-| labels label
- {
- $$ = new(OLIST, $1, $2);
- }
-
-label:
- LCASE expr ':'
- {
- $$ = new(OCASE, $2, Z);
- }
-| LDEFAULT ':'
- {
- $$ = new(OCASE, Z, Z);
- }
-| LNAME ':'
- {
- $$ = new(OLABEL, dcllabel($1, 1), Z);
- }
-
-stmnt:
- error ';'
- {
- $$ = Z;
- }
-| ulstmnt
-| labels ulstmnt
- {
- $$ = new(OLIST, $1, $2);
- }
-
-forexpr:
- zcexpr
-| ctlist adlist
- {
- $$ = $2;
- }
-
-ulstmnt:
- zcexpr ';'
-| {
- markdcl();
- }
- block
- {
- $$ = revertdcl();
- if($$)
- $$ = new(OLIST, $$, $2);
- else
- $$ = $2;
- }
-| LIF '(' cexpr ')' stmnt
- {
- $$ = new(OIF, $3, new(OLIST, $5, Z));
- if($5 == Z)
- warn($3, "empty if body");
- }
-| LIF '(' cexpr ')' stmnt LELSE stmnt
- {
- $$ = new(OIF, $3, new(OLIST, $5, $7));
- if($5 == Z)
- warn($3, "empty if body");
- if($7 == Z)
- warn($3, "empty else body");
- }
-| { markdcl(); } LFOR '(' forexpr ';' zcexpr ';' zcexpr ')' stmnt
- {
- $$ = revertdcl();
- if($$){
- if($4)
- $4 = new(OLIST, $$, $4);
- else
- $4 = $$;
- }
- $$ = new(OFOR, new(OLIST, $6, new(OLIST, $4, $8)), $10);
- }
-| LWHILE '(' cexpr ')' stmnt
- {
- $$ = new(OWHILE, $3, $5);
- }
-| LDO stmnt LWHILE '(' cexpr ')' ';'
- {
- $$ = new(ODWHILE, $5, $2);
- }
-| LRETURN zcexpr ';'
- {
- $$ = new(ORETURN, $2, Z);
- $$->type = thisfn->link;
- }
-| LSWITCH '(' cexpr ')' stmnt
- {
- $$ = new(OCONST, Z, Z);
- $$->vconst = 0;
- $$->type = types[TINT];
- $3 = new(OSUB, $$, $3);
-
- $$ = new(OCONST, Z, Z);
- $$->vconst = 0;
- $$->type = types[TINT];
- $3 = new(OSUB, $$, $3);
-
- $$ = new(OSWITCH, $3, $5);
- }
-| LBREAK ';'
- {
- $$ = new(OBREAK, Z, Z);
- }
-| LCONTINUE ';'
- {
- $$ = new(OCONTINUE, Z, Z);
- }
-| LGOTO ltag ';'
- {
- $$ = new(OGOTO, dcllabel($2, 0), Z);
- }
-| LUSED '(' zelist ')' ';'
- {
- $$ = new(OUSED, $3, Z);
- }
-| LPREFETCH '(' zelist ')' ';'
- {
- $$ = new(OPREFETCH, $3, Z);
- }
-| LSET '(' zelist ')' ';'
- {
- $$ = new(OSET, $3, Z);
- }
-
-zcexpr:
- {
- $$ = Z;
- }
-| cexpr
-
-zexpr:
- {
- $$ = Z;
- }
-| lexpr
-
-lexpr:
- expr
- {
- $$ = new(OCAST, $1, Z);
- $$->type = types[TLONG];
- }
-
-cexpr:
- expr
-| cexpr ',' cexpr
- {
- $$ = new(OCOMMA, $1, $3);
- }
-
-expr:
- xuexpr
-| expr '*' expr
- {
- $$ = new(OMUL, $1, $3);
- }
-| expr '/' expr
- {
- $$ = new(ODIV, $1, $3);
- }
-| expr '%' expr
- {
- $$ = new(OMOD, $1, $3);
- }
-| expr '+' expr
- {
- $$ = new(OADD, $1, $3);
- }
-| expr '-' expr
- {
- $$ = new(OSUB, $1, $3);
- }
-| expr LRSH expr
- {
- $$ = new(OASHR, $1, $3);
- }
-| expr LLSH expr
- {
- $$ = new(OASHL, $1, $3);
- }
-| expr '<' expr
- {
- $$ = new(OLT, $1, $3);
- }
-| expr '>' expr
- {
- $$ = new(OGT, $1, $3);
- }
-| expr LLE expr
- {
- $$ = new(OLE, $1, $3);
- }
-| expr LGE expr
- {
- $$ = new(OGE, $1, $3);
- }
-| expr LEQ expr
- {
- $$ = new(OEQ, $1, $3);
- }
-| expr LNE expr
- {
- $$ = new(ONE, $1, $3);
- }
-| expr '&' expr
- {
- $$ = new(OAND, $1, $3);
- }
-| expr '^' expr
- {
- $$ = new(OXOR, $1, $3);
- }
-| expr '|' expr
- {
- $$ = new(OOR, $1, $3);
- }
-| expr LANDAND expr
- {
- $$ = new(OANDAND, $1, $3);
- }
-| expr LOROR expr
- {
- $$ = new(OOROR, $1, $3);
- }
-| expr '?' cexpr ':' expr
- {
- $$ = new(OCOND, $1, new(OLIST, $3, $5));
- }
-| expr '=' expr
- {
- $$ = new(OAS, $1, $3);
- }
-| expr LPE expr
- {
- $$ = new(OASADD, $1, $3);
- }
-| expr LME expr
- {
- $$ = new(OASSUB, $1, $3);
- }
-| expr LMLE expr
- {
- $$ = new(OASMUL, $1, $3);
- }
-| expr LDVE expr
- {
- $$ = new(OASDIV, $1, $3);
- }
-| expr LMDE expr
- {
- $$ = new(OASMOD, $1, $3);
- }
-| expr LLSHE expr
- {
- $$ = new(OASASHL, $1, $3);
- }
-| expr LRSHE expr
- {
- $$ = new(OASASHR, $1, $3);
- }
-| expr LANDE expr
- {
- $$ = new(OASAND, $1, $3);
- }
-| expr LXORE expr
- {
- $$ = new(OASXOR, $1, $3);
- }
-| expr LORE expr
- {
- $$ = new(OASOR, $1, $3);
- }
-
-xuexpr:
- uexpr
-| '(' tlist abdecor ')' xuexpr
- {
- $$ = new(OCAST, $5, Z);
- dodecl(NODECL, CXXX, $2, $3);
- $$->type = lastdcl;
- $$->xcast = 1;
- }
-| '(' tlist abdecor ')' '{' ilist '}' /* extension */
- {
- $$ = new(OSTRUCT, $6, Z);
- dodecl(NODECL, CXXX, $2, $3);
- $$->type = lastdcl;
- }
-
-uexpr:
- pexpr
-| '*' xuexpr
- {
- $$ = new(OIND, $2, Z);
- }
-| '&' xuexpr
- {
- $$ = new(OADDR, $2, Z);
- }
-| '+' xuexpr
- {
- $$ = new(OPOS, $2, Z);
- }
-| '-' xuexpr
- {
- $$ = new(ONEG, $2, Z);
- }
-| '!' xuexpr
- {
- $$ = new(ONOT, $2, Z);
- }
-| '~' xuexpr
- {
- $$ = new(OCOM, $2, Z);
- }
-| LPP xuexpr
- {
- $$ = new(OPREINC, $2, Z);
- }
-| LMM xuexpr
- {
- $$ = new(OPREDEC, $2, Z);
- }
-| LSIZEOF uexpr
- {
- $$ = new(OSIZE, $2, Z);
- }
-| LSIGNOF uexpr
- {
- $$ = new(OSIGN, $2, Z);
- }
-
-pexpr:
- '(' cexpr ')'
- {
- $$ = $2;
- }
-| LSIZEOF '(' tlist abdecor ')'
- {
- $$ = new(OSIZE, Z, Z);
- dodecl(NODECL, CXXX, $3, $4);
- $$->type = lastdcl;
- }
-| LSIGNOF '(' tlist abdecor ')'
- {
- $$ = new(OSIGN, Z, Z);
- dodecl(NODECL, CXXX, $3, $4);
- $$->type = lastdcl;
- }
-| pexpr '(' zelist ')'
- {
- $$ = new(OFUNC, $1, Z);
- if($1->op == ONAME)
- if($1->type == T)
- dodecl(xdecl, CXXX, types[TINT], $$);
- $$->right = invert($3);
- }
-| pexpr '[' cexpr ']'
- {
- $$ = new(OIND, new(OADD, $1, $3), Z);
- }
-| pexpr LMG ltag
- {
- $$ = new(ODOT, new(OIND, $1, Z), Z);
- $$->sym = $3;
- }
-| pexpr '.' ltag
- {
- $$ = new(ODOT, $1, Z);
- $$->sym = $3;
- }
-| pexpr LPP
- {
- $$ = new(OPOSTINC, $1, Z);
- }
-| pexpr LMM
- {
- $$ = new(OPOSTDEC, $1, Z);
- }
-| name
-| LCONST
- {
- $$ = new(OCONST, Z, Z);
- $$->type = types[TINT];
- $$->vconst = $1;
- $$->cstring = strdup(symb);
- }
-| LLCONST
- {
- $$ = new(OCONST, Z, Z);
- $$->type = types[TLONG];
- $$->vconst = $1;
- $$->cstring = strdup(symb);
- }
-| LUCONST
- {
- $$ = new(OCONST, Z, Z);
- $$->type = types[TUINT];
- $$->vconst = $1;
- $$->cstring = strdup(symb);
- }
-| LULCONST
- {
- $$ = new(OCONST, Z, Z);
- $$->type = types[TULONG];
- $$->vconst = $1;
- $$->cstring = strdup(symb);
- }
-| LDCONST
- {
- $$ = new(OCONST, Z, Z);
- $$->type = types[TDOUBLE];
- $$->fconst = $1;
- $$->cstring = strdup(symb);
- }
-| LFCONST
- {
- $$ = new(OCONST, Z, Z);
- $$->type = types[TFLOAT];
- $$->fconst = $1;
- $$->cstring = strdup(symb);
- }
-| LVLCONST
- {
- $$ = new(OCONST, Z, Z);
- $$->type = types[TVLONG];
- $$->vconst = $1;
- $$->cstring = strdup(symb);
- }
-| LUVLCONST
- {
- $$ = new(OCONST, Z, Z);
- $$->type = types[TUVLONG];
- $$->vconst = $1;
- $$->cstring = strdup(symb);
- }
-| string
-| lstring
-
-string:
- LSTRING
- {
- $$ = new(OSTRING, Z, Z);
- $$->type = typ(TARRAY, types[TCHAR]);
- $$->type->width = $1.l + 1;
- $$->cstring = $1.s;
- $$->sym = symstring;
- $$->etype = TARRAY;
- $$->class = CSTATIC;
- }
-| string LSTRING
- {
- char *s;
- int n;
-
- n = $1->type->width - 1;
- s = alloc(n+$2.l+MAXALIGN);
-
- memcpy(s, $1->cstring, n);
- memcpy(s+n, $2.s, $2.l);
- s[n+$2.l] = 0;
-
- $$ = $1;
- $$->type->width += $2.l;
- $$->cstring = s;
- }
-
-lstring:
- LLSTRING
- {
- $$ = new(OLSTRING, Z, Z);
- $$->type = typ(TARRAY, types[TRUNE]);
- $$->type->width = $1.l + sizeof(TRune);
- $$->rstring = (TRune*)$1.s;
- $$->sym = symstring;
- $$->etype = TARRAY;
- $$->class = CSTATIC;
- }
-| lstring LLSTRING
- {
- char *s;
- int n;
-
- n = $1->type->width - sizeof(TRune);
- s = alloc(n+$2.l+MAXALIGN);
-
- memcpy(s, $1->rstring, n);
- memcpy(s+n, $2.s, $2.l);
- *(TRune*)(s+n+$2.l) = 0;
-
- $$ = $1;
- $$->type->width += $2.l;
- $$->rstring = (TRune*)s;
- }
-
-zelist:
- {
- $$ = Z;
- }
-| elist
-
-elist:
- expr
-| elist ',' elist
- {
- $$ = new(OLIST, $1, $3);
- }
-
-sbody:
- '{'
- {
- $<tyty>$.t1 = strf;
- $<tyty>$.t2 = strl;
- $<tyty>$.t3 = lasttype;
- $<tyty>$.c = lastclass;
- strf = T;
- strl = T;
- lastbit = 0;
- firstbit = 1;
- lastclass = CXXX;
- lasttype = T;
- }
- edecl '}'
- {
- $$ = strf;
- strf = $<tyty>2.t1;
- strl = $<tyty>2.t2;
- lasttype = $<tyty>2.t3;
- lastclass = $<tyty>2.c;
- }
-
-zctlist:
- {
- lastclass = CXXX;
- lasttype = types[TINT];
- }
-| ctlist
-
-types:
- complex
- {
- $$.t = $1;
- $$.c = CXXX;
- }
-| tname
- {
- $$.t = simplet($1);
- $$.c = CXXX;
- }
-| gcnlist
- {
- $$.t = simplet($1);
- $$.c = simplec($1);
- $$.t = garbt($$.t, $1);
- }
-| complex gctnlist
- {
- $$.t = $1;
- $$.c = simplec($2);
- $$.t = garbt($$.t, $2);
- if($2 & ~BCLASS & ~BGARB)
- diag(Z, "duplicate types given: %T and %Q", $1, $2);
- }
-| tname gctnlist
- {
- $$.t = simplet(typebitor($1, $2));
- $$.c = simplec($2);
- $$.t = garbt($$.t, $2);
- }
-| gcnlist complex zgnlist
- {
- $$.t = $2;
- $$.c = simplec($1);
- $$.t = garbt($$.t, $1|$3);
- }
-| gcnlist tname
- {
- $$.t = simplet($2);
- $$.c = simplec($1);
- $$.t = garbt($$.t, $1);
- }
-| gcnlist tname gctnlist
- {
- $$.t = simplet(typebitor($2, $3));
- $$.c = simplec($1|$3);
- $$.t = garbt($$.t, $1|$3);
- }
-
-tlist:
- types
- {
- $$ = $1.t;
- if($1.c != CXXX)
- diag(Z, "illegal combination of class 4: %s", cnames[$1.c]);
- }
-
-ctlist:
- types
- {
- lasttype = $1.t;
- lastclass = $1.c;
- }
-
-complex:
- LSTRUCT ltag
- {
- dotag($2, TSTRUCT, 0);
- $$ = $2->suetag;
- }
-| LSTRUCT ltag
- {
- dotag($2, TSTRUCT, autobn);
- }
- sbody
- {
- $$ = $2->suetag;
- if($$->link != T)
- diag(Z, "redeclare tag: %s", $2->name);
- $$->link = $4;
- sualign($$);
- }
-| LSTRUCT sbody
- {
- diag(Z, "struct must have tag");
- taggen++;
- sprint(symb, "_%d_", taggen);
- $$ = dotag(lookup(), TSTRUCT, autobn);
- $$->link = $2;
- sualign($$);
- }
-| LUNION ltag
- {
- dotag($2, TUNION, 0);
- $$ = $2->suetag;
- }
-| LUNION ltag
- {
- dotag($2, TUNION, autobn);
- }
- sbody
- {
- $$ = $2->suetag;
- if($$->link != T)
- diag(Z, "redeclare tag: %s", $2->name);
- $$->link = $4;
- sualign($$);
- }
-| LUNION sbody
- {
- taggen++;
- sprint(symb, "_%d_", taggen);
- $$ = dotag(lookup(), TUNION, autobn);
- $$->link = $2;
- sualign($$);
- }
-| LENUM ltag
- {
- dotag($2, TENUM, 0);
- $$ = $2->suetag;
- if($$->link == T)
- $$->link = types[TINT];
- $$ = $$->link;
- }
-| LENUM ltag
- {
- dotag($2, TENUM, autobn);
- }
- '{'
- {
- en.tenum = T;
- en.cenum = T;
- }
- enum '}'
- {
- $$ = $2->suetag;
- if($$->link != T)
- diag(Z, "redeclare tag: %s", $2->name);
- if(en.tenum == T) {
- diag(Z, "enum type ambiguous: %s", $2->name);
- en.tenum = types[TINT];
- }
- $$->link = en.tenum;
- $$ = en.tenum;
- }
-| LENUM '{'
- {
- en.tenum = T;
- en.cenum = T;
- }
- enum '}'
- {
- $$ = en.tenum;
- }
-| LTYPE
- {
- $$ = tcopy($1->type);
- }
-
-gctnlist:
- gctname
-| gctnlist gctname
- {
- $$ = typebitor($1, $2);
- }
-
-zgnlist:
- {
- $$ = 0;
- }
-| zgnlist gname
- {
- $$ = typebitor($1, $2);
- }
-
-gctname:
- tname
-| gname
-| cname
-
-gcnlist:
- gcname
-| gcnlist gcname
- {
- $$ = typebitor($1, $2);
- }
-
-gcname:
- gname
-| cname
-
-enum:
- LNAME
- {
- doenum($1, Z);
- }
-| LNAME '=' expr
- {
- doenum($1, $3);
- }
-| enum ','
-| enum ',' enum
-
-tname: /* type words */
- LCHAR { $$ = BCHAR; }
-| LSHORT { $$ = BSHORT; }
-| LINT { $$ = BINT; }
-| LLONG { $$ = BLONG; }
-| LSIGNED { $$ = BSIGNED; }
-| LUNSIGNED { $$ = BUNSIGNED; }
-| LFLOAT { $$ = BFLOAT; }
-| LDOUBLE { $$ = BDOUBLE; }
-| LVOID { $$ = BVOID; }
-
-cname: /* class words */
- LAUTO { $$ = BAUTO; }
-| LSTATIC { $$ = BSTATIC; }
-| LEXTERN { $$ = BEXTERN; }
-| LTYPEDEF { $$ = BTYPEDEF; }
-| LTYPESTR { $$ = BTYPESTR; }
-| LREGISTER { $$ = BREGISTER; }
-| LINLINE { $$ = 0; }
-
-gname: /* garbage words */
- LCONSTNT { $$ = BCONSTNT; }
-| LVOLATILE { $$ = BVOLATILE; }
-| LRESTRICT { $$ = 0; }
-
-name:
- LNAME
- {
- $$ = new(ONAME, Z, Z);
- if($1->class == CLOCAL)
- $1 = mkstatic($1);
- $$->sym = $1;
- $$->type = $1->type;
- $$->etype = TVOID;
- if($$->type != T)
- $$->etype = $$->type->etype;
- $$->xoffset = $1->offset;
- $$->class = $1->class;
- $1->aused = 1;
- }
-tag:
- ltag
- {
- $$ = new(ONAME, Z, Z);
- $$->sym = $1;
- $$->type = $1->type;
- $$->etype = TVOID;
- if($$->type != T)
- $$->etype = $$->type->etype;
- $$->xoffset = $1->offset;
- $$->class = $1->class;
- }
-ltag:
- LNAME
-| LTYPE
-%%
diff --git a/src/cmd/cc/com.c b/src/cmd/cc/com.c
deleted file mode 100644
index 4886b73eb..000000000
--- a/src/cmd/cc/com.c
+++ /dev/null
@@ -1,1384 +0,0 @@
-// Inferno utils/cc/com.c
-// http://code.google.com/p/inferno-os/source/browse/utils/cc/com.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include <u.h>
-#include "cc.h"
-
-int compar(Node*, int);
-
-void
-complex(Node *n)
-{
-
- if(n == Z)
- return;
-
- nearln = n->lineno;
- if(debug['t'])
- if(n->op != OCONST)
- prtree(n, "pre complex");
- if(tcom(n))
- return;
- if(debug['t'])
- if(n->op != OCONST)
- prtree(n, "t complex");
- ccom(n);
- if(debug['t'])
- if(n->op != OCONST)
- prtree(n, "c complex");
- acom(n);
- if(debug['t'])
- if(n->op != OCONST)
- prtree(n, "a complex");
- xcom(n);
- if(debug['t'])
- if(n->op != OCONST)
- prtree(n, "x complex");
-}
-
-/*
- * evaluate types
- * evaluate lvalues (addable == 1)
- */
-enum
-{
- ADDROF = 1<<0,
- CASTOF = 1<<1,
- ADDROP = 1<<2,
-};
-
-int
-tcom(Node *n)
-{
-
- return tcomo(n, ADDROF);
-}
-
-int
-tcomo(Node *n, int f)
-{
- Node *l, *r;
- Type *t;
- int o;
- static TRune zer;
-
- if(n == Z) {
- diag(Z, "Z in tcom");
- errorexit();
- }
- n->addable = 0;
- l = n->left;
- r = n->right;
-
- switch(n->op) {
- default:
- diag(n, "unknown op in type complex: %O", n->op);
- goto bad;
-
- case ODOTDOT:
- /*
- * tcom has already been called on this subtree
- */
- *n = *n->left;
- if(n->type == T)
- goto bad;
- break;
-
- case OCAST:
- if(n->type == T)
- break;
- if(n->type->width == types[TLONG]->width) {
- if(tcomo(l, ADDROF|CASTOF))
- goto bad;
- } else
- if(tcom(l))
- goto bad;
- if(isfunct(n))
- break;
- if(tcompat(n, l->type, n->type, tcast))
- goto bad;
- break;
-
- case ORETURN:
- if(l == Z) {
- if(n->type->etype != TVOID)
- diag(n, "null return of a typed function");
- break;
- }
- if(tcom(l))
- goto bad;
- typeext(n->type, l);
- if(tcompat(n, n->type, l->type, tasign))
- break;
- constas(n, n->type, l->type);
- if(!sametype(n->type, l->type)) {
- l = new1(OCAST, l, Z);
- l->type = n->type;
- n->left = l;
- }
- break;
-
- case OASI: /* same as as, but no test for const */
- n->op = OAS;
- o = tcom(l);
- if(o | tcom(r))
- goto bad;
-
- typeext(l->type, r);
- if(tlvalue(l) || tcompat(n, l->type, r->type, tasign))
- goto bad;
- if(!sametype(l->type, r->type)) {
- r = new1(OCAST, r, Z);
- r->type = l->type;
- n->right = r;
- }
- n->type = l->type;
- break;
-
- case OAS:
- o = tcom(l);
- if(o | tcom(r))
- goto bad;
- if(tlvalue(l))
- goto bad;
- if(isfunct(n))
- break;
- typeext(l->type, r);
- if(tcompat(n, l->type, r->type, tasign))
- goto bad;
- constas(n, l->type, r->type);
- if(!sametype(l->type, r->type)) {
- r = new1(OCAST, r, Z);
- r->type = l->type;
- n->right = r;
- }
- n->type = l->type;
- break;
-
- case OASADD:
- case OASSUB:
- o = tcom(l);
- if(o | tcom(r))
- goto bad;
- if(tlvalue(l))
- goto bad;
- if(isfunct(n))
- break;
- typeext1(l->type, r);
- if(tcompat(n, l->type, r->type, tasadd))
- goto bad;
- constas(n, l->type, r->type);
- t = l->type;
- arith(n, 0);
- while(n->left->op == OCAST)
- n->left = n->left->left;
- if(!sametype(t, n->type) && !mixedasop(t, n->type)) {
- r = new1(OCAST, n->right, Z);
- r->type = t;
- n->right = r;
- n->type = t;
- }
- break;
-
- case OASMUL:
- case OASLMUL:
- case OASDIV:
- case OASLDIV:
- o = tcom(l);
- if(o | tcom(r))
- goto bad;
- if(tlvalue(l))
- goto bad;
- if(isfunct(n))
- break;
- typeext1(l->type, r);
- if(tcompat(n, l->type, r->type, tmul))
- goto bad;
- constas(n, l->type, r->type);
- t = l->type;
- arith(n, 0);
- while(n->left->op == OCAST)
- n->left = n->left->left;
- if(!sametype(t, n->type) && !mixedasop(t, n->type)) {
- r = new1(OCAST, n->right, Z);
- r->type = t;
- n->right = r;
- n->type = t;
- }
- if(typeu[n->type->etype]) {
- if(n->op == OASDIV)
- n->op = OASLDIV;
- if(n->op == OASMUL)
- n->op = OASLMUL;
- }
- break;
-
- case OASLSHR:
- case OASASHR:
- case OASASHL:
- o = tcom(l);
- if(o | tcom(r))
- goto bad;
- if(tlvalue(l))
- goto bad;
- if(isfunct(n))
- break;
- if(tcompat(n, l->type, r->type, tand))
- goto bad;
- n->type = l->type;
- if(typeu[n->type->etype]) {
- if(n->op == OASASHR)
- n->op = OASLSHR;
- }
- break;
-
- case OASMOD:
- case OASLMOD:
- case OASOR:
- case OASAND:
- case OASXOR:
- o = tcom(l);
- if(o | tcom(r))
- goto bad;
- if(tlvalue(l))
- goto bad;
- if(isfunct(n))
- break;
- if(tcompat(n, l->type, r->type, tand))
- goto bad;
- t = l->type;
- arith(n, 0);
- while(n->left->op == OCAST)
- n->left = n->left->left;
- if(!sametype(t, n->type) && !mixedasop(t, n->type)) {
- r = new1(OCAST, n->right, Z);
- r->type = t;
- n->right = r;
- n->type = t;
- }
- if(typeu[n->type->etype]) {
- if(n->op == OASMOD)
- n->op = OASLMOD;
- }
- break;
-
- case OPREINC:
- case OPREDEC:
- case OPOSTINC:
- case OPOSTDEC:
- if(tcom(l))
- goto bad;
- if(tlvalue(l))
- goto bad;
- if(isfunct(n))
- break;
- if(tcompat(n, l->type, types[TINT], tadd))
- goto bad;
- n->type = l->type;
- if(n->type->etype == TIND)
- if(n->type->link->width < 1)
- diag(n, "inc/dec of a void pointer");
- break;
-
- case OEQ:
- case ONE:
- o = tcom(l);
- if(o | tcom(r))
- goto bad;
- if(isfunct(n))
- break;
- typeext(l->type, r);
- typeext(r->type, l);
- if(tcompat(n, l->type, r->type, trel))
- goto bad;
- arith(n, 0);
- n->type = types[TINT];
- break;
-
- case OLT:
- case OGE:
- case OGT:
- case OLE:
- o = tcom(l);
- if(o | tcom(r))
- goto bad;
- if(isfunct(n))
- break;
- typeext1(l->type, r);
- typeext1(r->type, l);
- if(tcompat(n, l->type, r->type, trel))
- goto bad;
- arith(n, 0);
- if(typeu[n->type->etype])
- n->op = logrel[relindex(n->op)];
- n->type = types[TINT];
- break;
-
- case OCOND:
- o = tcom(l);
- o |= tcom(r->left);
- if(o | tcom(r->right))
- goto bad;
- if(r->right->type->etype == TIND && vconst(r->left) == 0) {
- r->left->type = r->right->type;
- r->left->vconst = 0;
- }
- if(r->left->type->etype == TIND && vconst(r->right) == 0) {
- r->right->type = r->left->type;
- r->right->vconst = 0;
- }
- if(sametype(r->right->type, r->left->type)) {
- r->type = r->right->type;
- n->type = r->type;
- break;
- }
- if(tcompat(r, r->left->type, r->right->type, trel))
- goto bad;
- arith(r, 0);
- n->type = r->type;
- break;
-
- case OADD:
- o = tcom(l);
- if(o | tcom(r))
- goto bad;
- if(isfunct(n))
- break;
- if(tcompat(n, l->type, r->type, tadd))
- goto bad;
- arith(n, 1);
- break;
-
- case OSUB:
- o = tcom(l);
- if(o | tcom(r))
- goto bad;
- if(isfunct(n))
- break;
- if(tcompat(n, l->type, r->type, tsub))
- goto bad;
- arith(n, 1);
- break;
-
- case OMUL:
- case OLMUL:
- case ODIV:
- case OLDIV:
- o = tcom(l);
- if(o | tcom(r))
- goto bad;
- if(isfunct(n))
- break;
- if(tcompat(n, l->type, r->type, tmul))
- goto bad;
- arith(n, 1);
- if(typeu[n->type->etype]) {
- if(n->op == ODIV)
- n->op = OLDIV;
- if(n->op == OMUL)
- n->op = OLMUL;
- }
- break;
-
- case OLSHR:
- case OASHL:
- case OASHR:
- o = tcom(l);
- if(o | tcom(r))
- goto bad;
- if(isfunct(n))
- break;
- if(tcompat(n, l->type, r->type, tand))
- goto bad;
- n->right = Z;
- arith(n, 1);
- n->right = new1(OCAST, r, Z);
- n->right->type = types[TINT];
- if(typeu[n->type->etype])
- if(n->op == OASHR)
- n->op = OLSHR;
- break;
-
- case OAND:
- case OOR:
- case OXOR:
- o = tcom(l);
- if(o | tcom(r))
- goto bad;
- if(isfunct(n))
- break;
- if(tcompat(n, l->type, r->type, tand))
- goto bad;
- arith(n, 1);
- break;
-
- case OMOD:
- case OLMOD:
- o = tcom(l);
- if(o | tcom(r))
- goto bad;
- if(isfunct(n))
- break;
- if(tcompat(n, l->type, r->type, tand))
- goto bad;
- arith(n, 1);
- if(typeu[n->type->etype])
- n->op = OLMOD;
- break;
-
- case OPOS:
- if(tcom(l))
- goto bad;
- if(isfunct(n))
- break;
-
- r = l;
- l = new(OCONST, Z, Z);
- l->vconst = 0;
- l->type = types[TINT];
- n->op = OADD;
- n->right = r;
- n->left = l;
-
- if(tcom(l))
- goto bad;
- if(tcompat(n, l->type, r->type, tsub))
- goto bad;
- arith(n, 1);
- break;
-
- case ONEG:
- if(tcom(l))
- goto bad;
- if(isfunct(n))
- break;
-
- if(!machcap(n)) {
- r = l;
- l = new(OCONST, Z, Z);
- l->vconst = 0;
- l->type = types[TINT];
- n->op = OSUB;
- n->right = r;
- n->left = l;
-
- if(tcom(l))
- goto bad;
- if(tcompat(n, l->type, r->type, tsub))
- goto bad;
- }
- arith(n, 1);
- break;
-
- case OCOM:
- if(tcom(l))
- goto bad;
- if(isfunct(n))
- break;
-
- if(!machcap(n)) {
- r = l;
- l = new(OCONST, Z, Z);
- l->vconst = -1;
- l->type = types[TINT];
- n->op = OXOR;
- n->right = r;
- n->left = l;
-
- if(tcom(l))
- goto bad;
- if(tcompat(n, l->type, r->type, tand))
- goto bad;
- }
- arith(n, 1);
- break;
-
- case ONOT:
- if(tcom(l))
- goto bad;
- if(isfunct(n))
- break;
- if(tcompat(n, T, l->type, tnot))
- goto bad;
- n->type = types[TINT];
- break;
-
- case OANDAND:
- case OOROR:
- o = tcom(l);
- if(o | tcom(r))
- goto bad;
- if(tcompat(n, T, l->type, tnot) |
- tcompat(n, T, r->type, tnot))
- goto bad;
- n->type = types[TINT];
- break;
-
- case OCOMMA:
- o = tcom(l);
- if(o | tcom(r))
- goto bad;
- n->type = r->type;
- break;
-
-
- case OSIGN: /* extension signof(type) returns a hash */
- if(l != Z) {
- if(l->op != OSTRING && l->op != OLSTRING)
- if(tcomo(l, 0))
- goto bad;
- if(l->op == OBIT) {
- diag(n, "signof bitfield");
- goto bad;
- }
- n->type = l->type;
- }
- if(n->type == T)
- goto bad;
- if(n->type->width < 0) {
- diag(n, "signof undefined type");
- goto bad;
- }
- n->op = OCONST;
- n->left = Z;
- n->right = Z;
- n->vconst = convvtox(signature(n->type), TULONG);
- n->type = types[TULONG];
- break;
-
- case OSIZE:
- if(l != Z) {
- if(l->op != OSTRING && l->op != OLSTRING)
- if(tcomo(l, 0))
- goto bad;
- if(l->op == OBIT) {
- diag(n, "sizeof bitfield");
- goto bad;
- }
- n->type = l->type;
- }
- if(n->type == T)
- goto bad;
- if(n->type->width <= 0) {
- diag(n, "sizeof undefined type");
- goto bad;
- }
- if(n->type->etype == TFUNC) {
- diag(n, "sizeof function");
- goto bad;
- }
- n->op = OCONST;
- n->left = Z;
- n->right = Z;
- n->vconst = convvtox(n->type->width, TINT);
- n->type = types[TINT];
- break;
-
- case OFUNC:
- o = tcomo(l, 0);
- if(o)
- goto bad;
- if(l->type->etype == TIND && l->type->link->etype == TFUNC) {
- l = new1(OIND, l, Z);
- l->type = l->left->type->link;
- n->left = l;
- }
- if(tcompat(n, T, l->type, tfunct))
- goto bad;
- if(o | tcoma(l, r, l->type->down, 1))
- goto bad;
- n->type = l->type->link;
- if(!debug['B'])
- if(l->type->down == T || l->type->down->etype == TOLD) {
- nerrors--;
- diag(n, "function args not checked: %F", l);
- }
- dpcheck(n);
- break;
-
- case ONAME:
- if(n->type == T) {
- diag(n, "name not declared: %F", n);
- goto bad;
- }
- if(n->type->etype == TENUM) {
- n->op = OCONST;
- n->type = n->sym->tenum;
- if(!typefd[n->type->etype])
- n->vconst = n->sym->vconst;
- else
- n->fconst = n->sym->fconst;
- break;
- }
- n->addable = 1;
- if(n->class == CEXREG) {
- n->op = OREGISTER;
- // on 386 or amd64, "extern register" generates
- // memory references relative to the
- // gs or fs segment.
- if(thechar == '8' || thechar == '6') // [sic]
- n->op = OEXREG;
- n->reg = n->sym->offset;
- n->xoffset = 0;
- break;
- }
- break;
-
- case OLSTRING:
- if(n->type->link != types[TRUNE]) {
- o = outstring(0, 0);
- while(o & 3) {
- outlstring(&zer, sizeof(TRune));
- o = outlstring(0, 0);
- }
- }
- n->op = ONAME;
- n->xoffset = outlstring(n->rstring, n->type->width);
- n->addable = 1;
- break;
-
- case OSTRING:
- if(n->type->link != types[TCHAR]) {
- o = outstring(0, 0);
- while(o & 3) {
- outstring("", 1);
- o = outstring(0, 0);
- }
- }
- n->op = ONAME;
- n->xoffset = outstring(n->cstring, n->type->width);
- n->addable = 1;
- break;
-
- case OCONST:
- break;
-
- case ODOT:
- if(tcom(l))
- goto bad;
- if(tcompat(n, T, l->type, tdot))
- goto bad;
- if(tcomd(n))
- goto bad;
- break;
-
- case OADDR:
- if(tcomo(l, ADDROP))
- goto bad;
- if(tlvalue(l))
- goto bad;
- if(l->type->nbits) {
- diag(n, "address of a bit field");
- goto bad;
- }
- if(l->op == OREGISTER) {
- diag(n, "address of a register");
- goto bad;
- }
- n->type = typ(TIND, l->type);
- n->type->width = types[TIND]->width;
- break;
-
- case OIND:
- if(tcom(l))
- goto bad;
- if(tcompat(n, T, l->type, tindir))
- goto bad;
- n->type = l->type->link;
- n->addable = 1;
- break;
-
- case OSTRUCT:
- if(tcomx(n))
- goto bad;
- break;
- }
- t = n->type;
- if(t == T)
- goto bad;
- if(t->width < 0) {
- snap(t);
- if(t->width < 0) {
- if(typesu[t->etype] && t->tag)
- diag(n, "structure not fully declared %s", t->tag->name);
- else
- diag(n, "structure not fully declared");
- goto bad;
- }
- }
- if(typeaf[t->etype]) {
- if(f & ADDROF)
- goto addaddr;
- if(f & ADDROP)
- warn(n, "address of array/func ignored");
- }
- return 0;
-
-addaddr:
- if(tlvalue(n))
- goto bad;
- l = new1(OXXX, Z, Z);
- *l = *n;
- n->op = OADDR;
- if(l->type->etype == TARRAY)
- l->type = l->type->link;
- n->left = l;
- n->right = Z;
- n->addable = 0;
- n->type = typ(TIND, l->type);
- n->type->width = types[TIND]->width;
- return 0;
-
-bad:
- n->type = T;
- return 1;
-}
-
-int
-tcoma(Node *l, Node *n, Type *t, int f)
-{
- Node *n1;
- int o;
-
- if(t != T)
- if(t->etype == TOLD || t->etype == TDOT) /* .../old in prototype */
- t = T;
- if(n == Z) {
- if(t != T && !sametype(t, types[TVOID])) {
- diag(n, "not enough function arguments: %F", l);
- return 1;
- }
- return 0;
- }
- if(n->op == OLIST) {
- o = tcoma(l, n->left, t, 0);
- if(t != T) {
- t = t->down;
- if(t == T)
- t = types[TVOID];
- }
- return o | tcoma(l, n->right, t, 1);
- }
- if(f && t != T)
- tcoma(l, Z, t->down, 0);
- if(tcom(n) || tcompat(n, T, n->type, targ))
- return 1;
- if(sametype(t, types[TVOID])) {
- diag(n, "too many function arguments: %F", l);
- return 1;
- }
- if(t != T) {
- typeext(t, n);
- if(stcompat(nodproto, t, n->type, tasign)) {
- diag(l, "argument prototype mismatch \"%T\" for \"%T\": %F",
- n->type, t, l);
- return 1;
- }
-// switch(t->etype) {
-// case TCHAR:
-// case TSHORT:
-// t = types[TINT];
-// break;
-//
-// case TUCHAR:
-// case TUSHORT:
-// t = types[TUINT];
-// break;
-// }
- } else {
- switch(n->type->etype) {
- case TCHAR:
- case TSHORT:
- t = types[TINT];
- break;
-
- case TUCHAR:
- case TUSHORT:
- t = types[TUINT];
- break;
-
- case TFLOAT:
- t = types[TDOUBLE];
- }
- }
-
- if(t != T && !sametype(t, n->type)) {
- n1 = new1(OXXX, Z, Z);
- *n1 = *n;
- n->op = OCAST;
- n->left = n1;
- n->right = Z;
- n->type = t;
- n->addable = 0;
- }
- return 0;
-}
-
-int
-tcomd(Node *n)
-{
- Type *t;
- int32 o;
-
- o = 0;
- t = dotsearch(n->sym, n->left->type->link, n, &o);
- if(t == T) {
- diag(n, "not a member of struct/union: %F", n);
- return 1;
- }
- makedot(n, t, o);
- return 0;
-}
-
-int
-tcomx(Node *n)
-{
- Type *t;
- Node *l, *r, **ar, **al;
- int e;
-
- e = 0;
- if(n->type->etype != TSTRUCT) {
- diag(n, "constructor must be a structure");
- return 1;
- }
- l = invert(n->left);
- n->left = l;
- al = &n->left;
- for(t = n->type->link; t != T; t = t->down) {
- if(l == Z) {
- diag(n, "constructor list too short");
- return 1;
- }
- if(l->op == OLIST) {
- r = l->left;
- ar = &l->left;
- al = &l->right;
- l = l->right;
- } else {
- r = l;
- ar = al;
- l = Z;
- }
- if(tcom(r))
- e++;
- typeext(t, r);
- if(tcompat(n, t, r->type, tasign))
- e++;
- constas(n, t, r->type);
- if(!e && !sametype(t, r->type)) {
- r = new1(OCAST, r, Z);
- r->type = t;
- *ar = r;
- }
- }
- if(l != Z) {
- diag(n, "constructor list too long");
- return 1;
- }
- return e;
-}
-
-int
-tlvalue(Node *n)
-{
-
- if(!n->addable) {
- diag(n, "not an l-value");
- return 1;
- }
- return 0;
-}
-
-/*
- * general rewrite
- * (IND(ADDR x)) ==> x
- * (ADDR(IND x)) ==> x
- * remove some zero operands
- * remove no op casts
- * evaluate constants
- */
-void
-ccom(Node *n)
-{
- Node *l, *r;
- int t;
-
-loop:
- if(n == Z)
- return;
- l = n->left;
- r = n->right;
- switch(n->op) {
-
- case OAS:
- case OASXOR:
- case OASAND:
- case OASOR:
- case OASMOD:
- case OASLMOD:
- case OASLSHR:
- case OASASHR:
- case OASASHL:
- case OASDIV:
- case OASLDIV:
- case OASMUL:
- case OASLMUL:
- case OASSUB:
- case OASADD:
- ccom(l);
- ccom(r);
- if(n->op == OASLSHR || n->op == OASASHR || n->op == OASASHL)
- if(r->op == OCONST) {
- t = n->type->width * 8; /* bits per byte */
- if(r->vconst >= t || r->vconst < 0)
- warn(n, "stupid shift: %lld", r->vconst);
- }
- break;
-
- case OCAST:
- ccom(l);
- if(l->op == OCONST) {
- evconst(n);
- if(n->op == OCONST)
- break;
- }
- if(nocast(l->type, n->type)) {
- l->type = n->type;
- *n = *l;
- }
- break;
-
- case OCOND:
- ccom(l);
- ccom(r);
- if(l->op == OCONST)
- if(vconst(l) == 0)
- *n = *r->right;
- else
- *n = *r->left;
- break;
-
- case OREGISTER:
- case OINDREG:
- case OCONST:
- case ONAME:
- break;
-
- case OADDR:
- ccom(l);
- l->etype = TVOID;
- if(l->op == OIND) {
- l->left->type = n->type;
- *n = *l->left;
- break;
- }
- goto common;
-
- case OIND:
- ccom(l);
- if(l->op == OADDR) {
- l->left->type = n->type;
- *n = *l->left;
- break;
- }
- goto common;
-
- case OEQ:
- case ONE:
-
- case OLE:
- case OGE:
- case OLT:
- case OGT:
-
- case OLS:
- case OHS:
- case OLO:
- case OHI:
- ccom(l);
- ccom(r);
- if(compar(n, 0) || compar(n, 1))
- break;
- relcon(l, r);
- relcon(r, l);
- goto common;
-
- case OASHR:
- case OASHL:
- case OLSHR:
- ccom(l);
- if(vconst(l) == 0 && !side(r)) {
- *n = *l;
- break;
- }
- ccom(r);
- if(vconst(r) == 0) {
- *n = *l;
- break;
- }
- if(r->op == OCONST) {
- t = n->type->width * 8; /* bits per byte */
- if(r->vconst >= t || r->vconst <= -t)
- warn(n, "stupid shift: %lld", r->vconst);
- }
- goto common;
-
- case OMUL:
- case OLMUL:
- ccom(l);
- t = vconst(l);
- if(t == 0 && !side(r)) {
- *n = *l;
- break;
- }
- if(t == 1) {
- *n = *r;
- goto loop;
- }
- ccom(r);
- t = vconst(r);
- if(t == 0 && !side(l)) {
- *n = *r;
- break;
- }
- if(t == 1) {
- *n = *l;
- break;
- }
- goto common;
-
- case ODIV:
- case OLDIV:
- ccom(l);
- if(vconst(l) == 0 && !side(r)) {
- *n = *l;
- break;
- }
- ccom(r);
- t = vconst(r);
- if(t == 0) {
- diag(n, "divide check");
- *n = *r;
- break;
- }
- if(t == 1) {
- *n = *l;
- break;
- }
- goto common;
-
- case OSUB:
- ccom(r);
- if(r->op == OCONST) {
- if(typefd[r->type->etype]) {
- n->op = OADD;
- r->fconst = -r->fconst;
- goto loop;
- } else {
- n->op = OADD;
- r->vconst = -r->vconst;
- goto loop;
- }
- }
- ccom(l);
- goto common;
-
- case OXOR:
- case OOR:
- case OADD:
- ccom(l);
- if(vconst(l) == 0) {
- *n = *r;
- goto loop;
- }
- ccom(r);
- if(vconst(r) == 0) {
- *n = *l;
- break;
- }
- goto commute;
-
- case OAND:
- ccom(l);
- ccom(r);
- if(vconst(l) == 0 && !side(r)) {
- *n = *l;
- break;
- }
- if(vconst(r) == 0 && !side(l)) {
- *n = *r;
- break;
- }
-
- commute:
- /* look for commutative constant */
- if(r->op == OCONST) {
- if(l->op == n->op) {
- if(l->left->op == OCONST) {
- n->right = l->right;
- l->right = r;
- goto loop;
- }
- if(l->right->op == OCONST) {
- n->right = l->left;
- l->left = r;
- goto loop;
- }
- }
- }
- if(l->op == OCONST) {
- if(r->op == n->op) {
- if(r->left->op == OCONST) {
- n->left = r->right;
- r->right = l;
- goto loop;
- }
- if(r->right->op == OCONST) {
- n->left = r->left;
- r->left = l;
- goto loop;
- }
- }
- }
- goto common;
-
- case OANDAND:
- ccom(l);
- if(vconst(l) == 0) {
- *n = *l;
- break;
- }
- ccom(r);
- goto common;
-
- case OOROR:
- ccom(l);
- if(l->op == OCONST && l->vconst != 0) {
- *n = *l;
- n->vconst = 1;
- break;
- }
- ccom(r);
- goto common;
-
- default:
- if(l != Z)
- ccom(l);
- if(r != Z)
- ccom(r);
- common:
- if(l != Z)
- if(l->op != OCONST)
- break;
- if(r != Z)
- if(r->op != OCONST)
- break;
- evconst(n);
- }
-}
-
-/* OEQ, ONE, OLE, OLS, OLT, OLO, OGE, OHS, OGT, OHI */
-static char *cmps[12] =
-{
- "==", "!=", "<=", "<=", "<", "<", ">=", ">=", ">", ">",
-};
-
-/* 128-bit numbers */
-typedef struct Big Big;
-struct Big
-{
- vlong a;
- uvlong b;
-};
-static int
-cmp(Big x, Big y)
-{
- if(x.a != y.a){
- if(x.a < y.a)
- return -1;
- return 1;
- }
- if(x.b != y.b){
- if(x.b < y.b)
- return -1;
- return 1;
- }
- return 0;
-}
-static Big
-add(Big x, int y)
-{
- uvlong ob;
-
- ob = x.b;
- x.b += y;
- if(y > 0 && x.b < ob)
- x.a++;
- if(y < 0 && x.b > ob)
- x.a--;
- return x;
-}
-
-Big
-big(vlong a, uvlong b)
-{
- Big x;
-
- x.a = a;
- x.b = b;
- return x;
-}
-
-int
-compar(Node *n, int reverse)
-{
- Big lo, hi, x;
- int op;
- char xbuf[40], cmpbuf[50];
- Node *l, *r;
- Type *lt, *rt;
-
- /*
- * The point of this function is to diagnose comparisons
- * that can never be true or that look misleading because
- * of the `usual arithmetic conversions'. As an example
- * of the latter, if x is a ulong, then if(x <= -1) really means
- * if(x <= 0xFFFFFFFF), while if(x <= -1LL) really means
- * what it says (but 8c compiles it wrong anyway).
- */
-
- if(reverse){
- r = n->left;
- l = n->right;
- op = comrel[relindex(n->op)];
- }else{
- l = n->left;
- r = n->right;
- op = n->op;
- }
-
- /*
- * Skip over left casts to find out the original expression range.
- */
- while(l->op == OCAST)
- l = l->left;
- if(l->op == OCONST)
- return 0;
- lt = l->type;
- if(l->op == ONAME && l->sym->type){
- lt = l->sym->type;
- if(lt->etype == TARRAY)
- lt = lt->link;
- }
- if(lt == T)
- return 0;
- if(lt->etype == TXXX || lt->etype > TUVLONG)
- return 0;
-
- /*
- * Skip over the right casts to find the on-screen value.
- */
- if(r->op != OCONST)
- return 0;
- while(r->oldop == OCAST && !r->xcast)
- r = r->left;
- rt = r->type;
- if(rt == T)
- return 0;
-
- x.b = r->vconst;
- x.a = 0;
- if((rt->etype&1) && r->vconst < 0) /* signed negative */
- x.a = ~0ULL;
-
- if((lt->etype&1)==0){
- /* unsigned */
- lo = big(0, 0);
- if(lt->width == 8)
- hi = big(0, ~0ULL);
- else
- hi = big(0, (1ULL<<(l->type->width*8))-1);
- }else{
- lo = big(~0ULL, -(1ULL<<(l->type->width*8-1)));
- hi = big(0, (1ULL<<(l->type->width*8-1))-1);
- }
-
- switch(op){
- case OLT:
- case OLO:
- case OGE:
- case OHS:
- if(cmp(x, lo) <= 0)
- goto useless;
- if(cmp(x, add(hi, 1)) >= 0)
- goto useless;
- break;
- case OLE:
- case OLS:
- case OGT:
- case OHI:
- if(cmp(x, add(lo, -1)) <= 0)
- goto useless;
- if(cmp(x, hi) >= 0)
- goto useless;
- break;
- case OEQ:
- case ONE:
- /*
- * Don't warn about comparisons if the expression
- * is as wide as the value: the compiler-supplied casts
- * will make both outcomes possible.
- */
- if(lt->width >= rt->width && debug['w'] < 2)
- return 0;
- if(cmp(x, lo) < 0 || cmp(x, hi) > 0)
- goto useless;
- break;
- }
- return 0;
-
-useless:
- if((x.a==0 && x.b<=9) || (x.a==~0LL && x.b >= -9ULL))
- snprint(xbuf, sizeof xbuf, "%lld", x.b);
- else if(x.a == 0)
- snprint(xbuf, sizeof xbuf, "%#llux", x.b);
- else
- snprint(xbuf, sizeof xbuf, "%#llx", x.b);
- if(reverse)
- snprint(cmpbuf, sizeof cmpbuf, "%s %s %T",
- xbuf, cmps[relindex(n->op)], lt);
- else
- snprint(cmpbuf, sizeof cmpbuf, "%T %s %s",
- lt, cmps[relindex(n->op)], xbuf);
- warn(n, "useless or misleading comparison: %s", cmpbuf);
- return 0;
-}
-
diff --git a/src/cmd/cc/com64.c b/src/cmd/cc/com64.c
deleted file mode 100644
index f46fedc16..000000000
--- a/src/cmd/cc/com64.c
+++ /dev/null
@@ -1,644 +0,0 @@
-// Inferno utils/cc/com64.c
-// http://code.google.com/p/inferno-os/source/browse/utils/cc/com64.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include <u.h>
-#include "cc.h"
-
-/*
- * this is machine depend, but it is totally
- * common on all of the 64-bit symulating machines.
- */
-
-#define FNX 100 /* botch -- redefinition */
-
-Node* nodaddv;
-Node* nodsubv;
-Node* nodmulv;
-Node* noddivv;
-Node* noddivvu;
-Node* nodmodv;
-Node* nodmodvu;
-Node* nodlshv;
-Node* nodrshav;
-Node* nodrshlv;
-Node* nodandv;
-Node* nodorv;
-Node* nodxorv;
-Node* nodnegv;
-Node* nodcomv;
-
-Node* nodtestv;
-Node* nodeqv;
-Node* nodnev;
-Node* nodlev;
-Node* nodltv;
-Node* nodgev;
-Node* nodgtv;
-Node* nodhiv;
-Node* nodhsv;
-Node* nodlov;
-Node* nodlsv;
-
-Node* nodf2v;
-Node* nodd2v;
-Node* nodp2v;
-Node* nodsi2v;
-Node* nodui2v;
-Node* nodsl2v;
-Node* nodul2v;
-Node* nodsh2v;
-Node* noduh2v;
-Node* nodsc2v;
-Node* noduc2v;
-
-Node* nodv2f;
-Node* nodv2d;
-Node* nodv2ui;
-Node* nodv2si;
-Node* nodv2ul;
-Node* nodv2sl;
-Node* nodv2uh;
-Node* nodv2sh;
-Node* nodv2uc;
-Node* nodv2sc;
-
-Node* nodvpp;
-Node* nodppv;
-Node* nodvmm;
-Node* nodmmv;
-
-Node* nodvasop;
-
-char etconv[NALLTYPES]; /* for _vasop */
-Init initetconv[] =
-{
- TCHAR, 1, 0,
- TUCHAR, 2, 0,
- TSHORT, 3, 0,
- TUSHORT, 4, 0,
- TLONG, 5, 0,
- TULONG, 6, 0,
- TVLONG, 7, 0,
- TUVLONG, 8, 0,
- TINT, 9, 0,
- TUINT, 10, 0,
- -1, 0, 0,
-};
-
-Node*
-fvn(char *name, int type)
-{
- Node *n;
-
- n = new(ONAME, Z, Z);
- n->sym = slookup(name);
- n->sym->sig = SIGINTERN;
- if(fntypes[type] == 0)
- fntypes[type] = typ(TFUNC, types[type]);
- n->type = fntypes[type];
- n->etype = type;
- n->class = CGLOBL;
- n->addable = 10;
- n->complex = 0;
- return n;
-}
-
-void
-com64init(void)
-{
- Init *p;
-
- nodaddv = fvn("_addv", TVLONG);
- nodsubv = fvn("_subv", TVLONG);
- nodmulv = fvn("_mulv", TVLONG);
- noddivv = fvn("_divv", TVLONG);
- noddivvu = fvn("_divvu", TVLONG);
- nodmodv = fvn("_modv", TVLONG);
- nodmodvu = fvn("_modvu", TVLONG);
- nodlshv = fvn("_lshv", TVLONG);
- nodrshav = fvn("_rshav", TVLONG);
- nodrshlv = fvn("_rshlv", TVLONG);
- nodandv = fvn("_andv", TVLONG);
- nodorv = fvn("_orv", TVLONG);
- nodxorv = fvn("_xorv", TVLONG);
- nodnegv = fvn("_negv", TVLONG);
- nodcomv = fvn("_comv", TVLONG);
-
- nodtestv = fvn("_testv", TLONG);
- nodeqv = fvn("_eqv", TLONG);
- nodnev = fvn("_nev", TLONG);
- nodlev = fvn("_lev", TLONG);
- nodltv = fvn("_ltv", TLONG);
- nodgev = fvn("_gev", TLONG);
- nodgtv = fvn("_gtv", TLONG);
- nodhiv = fvn("_hiv", TLONG);
- nodhsv = fvn("_hsv", TLONG);
- nodlov = fvn("_lov", TLONG);
- nodlsv = fvn("_lsv", TLONG);
-
- nodf2v = fvn("_f2v", TVLONG);
- nodd2v = fvn("_d2v", TVLONG);
- nodp2v = fvn("_p2v", TVLONG);
- nodsi2v = fvn("_si2v", TVLONG);
- nodui2v = fvn("_ui2v", TVLONG);
- nodsl2v = fvn("_sl2v", TVLONG);
- nodul2v = fvn("_ul2v", TVLONG);
- nodsh2v = fvn("_sh2v", TVLONG);
- noduh2v = fvn("_uh2v", TVLONG);
- nodsc2v = fvn("_sc2v", TVLONG);
- noduc2v = fvn("_uc2v", TVLONG);
-
- nodv2f = fvn("_v2f", TFLOAT);
- nodv2d = fvn("_v2d", TDOUBLE);
- nodv2sl = fvn("_v2sl", TLONG);
- nodv2ul = fvn("_v2ul", TULONG);
- nodv2si = fvn("_v2si", TINT);
- nodv2ui = fvn("_v2ui", TUINT);
- nodv2sh = fvn("_v2sh", TSHORT);
- nodv2uh = fvn("_v2ul", TUSHORT);
- nodv2sc = fvn("_v2sc", TCHAR);
- nodv2uc = fvn("_v2uc", TUCHAR);
-
- nodvpp = fvn("_vpp", TVLONG);
- nodppv = fvn("_ppv", TVLONG);
- nodvmm = fvn("_vmm", TVLONG);
- nodmmv = fvn("_mmv", TVLONG);
-
- nodvasop = fvn("_vasop", TVLONG);
-
- for(p = initetconv; p->code >= 0; p++)
- etconv[p->code] = p->value;
-}
-
-int
-com64(Node *n)
-{
- Node *l, *r, *a, *t;
- int lv, rv;
-
- if(n->type == 0)
- return 0;
-
- l = n->left;
- r = n->right;
-
- lv = 0;
- if(l && l->type && typev[l->type->etype])
- lv = 1;
- rv = 0;
- if(r && r->type && typev[r->type->etype])
- rv = 1;
-
- if(lv) {
- switch(n->op) {
- case OEQ:
- a = nodeqv;
- goto setbool;
- case ONE:
- a = nodnev;
- goto setbool;
- case OLE:
- a = nodlev;
- goto setbool;
- case OLT:
- a = nodltv;
- goto setbool;
- case OGE:
- a = nodgev;
- goto setbool;
- case OGT:
- a = nodgtv;
- goto setbool;
- case OHI:
- a = nodhiv;
- goto setbool;
- case OHS:
- a = nodhsv;
- goto setbool;
- case OLO:
- a = nodlov;
- goto setbool;
- case OLS:
- a = nodlsv;
- goto setbool;
-
- case OANDAND:
- case OOROR:
- if(machcap(n))
- return 1;
-
- if(rv) {
- r = new(OFUNC, nodtestv, r);
- n->right = r;
- r->complex = FNX;
- r->op = OFUNC;
- r->type = types[TLONG];
- }
-
- case OCOND:
- case ONOT:
- if(machcap(n))
- return 1;
-
- l = new(OFUNC, nodtestv, l);
- n->left = l;
- l->complex = FNX;
- l->op = OFUNC;
- l->type = types[TLONG];
- n->complex = FNX;
- return 1;
- }
- }
-
- if(rv) {
- if(machcap(n))
- return 1;
- switch(n->op) {
- case OANDAND:
- case OOROR:
- r = new(OFUNC, nodtestv, r);
- n->right = r;
- r->complex = FNX;
- r->op = OFUNC;
- r->type = types[TLONG];
- return 1;
- }
- }
-
- if(typev[n->type->etype]) {
- if(machcap(n))
- return 1;
- switch(n->op) {
- default:
- diag(n, "unknown vlong %O", n->op);
- case OFUNC:
- n->complex = FNX;
- case ORETURN:
- case OAS:
- case OIND:
- return 1;
- case OADD:
- a = nodaddv;
- goto setbop;
- case OSUB:
- a = nodsubv;
- goto setbop;
- case OMUL:
- case OLMUL:
- a = nodmulv;
- goto setbop;
- case ODIV:
- a = noddivv;
- goto setbop;
- case OLDIV:
- a = noddivvu;
- goto setbop;
- case OMOD:
- a = nodmodv;
- goto setbop;
- case OLMOD:
- a = nodmodvu;
- goto setbop;
- case OASHL:
- a = nodlshv;
- goto setbop;
- case OASHR:
- a = nodrshav;
- goto setbop;
- case OLSHR:
- a = nodrshlv;
- goto setbop;
- case OAND:
- a = nodandv;
- goto setbop;
- case OOR:
- a = nodorv;
- goto setbop;
- case OXOR:
- a = nodxorv;
- goto setbop;
- case OPOSTINC:
- a = nodvpp;
- goto setvinc;
- case OPOSTDEC:
- a = nodvmm;
- goto setvinc;
- case OPREINC:
- a = nodppv;
- goto setvinc;
- case OPREDEC:
- a = nodmmv;
- goto setvinc;
- case ONEG:
- a = nodnegv;
- goto setfnx;
- case OCOM:
- a = nodcomv;
- goto setfnx;
- case OCAST:
- switch(l->type->etype) {
- case TCHAR:
- a = nodsc2v;
- goto setfnxl;
- case TUCHAR:
- a = noduc2v;
- goto setfnxl;
- case TSHORT:
- a = nodsh2v;
- goto setfnxl;
- case TUSHORT:
- a = noduh2v;
- goto setfnxl;
- case TINT:
- a = nodsi2v;
- goto setfnx;
- case TUINT:
- a = nodui2v;
- goto setfnx;
- case TLONG:
- a = nodsl2v;
- goto setfnx;
- case TULONG:
- a = nodul2v;
- goto setfnx;
- case TFLOAT:
- a = nodf2v;
- goto setfnx;
- case TDOUBLE:
- a = nodd2v;
- goto setfnx;
- case TIND:
- a = nodp2v;
- goto setfnx;
- }
- diag(n, "unknown %T->vlong cast", l->type);
- return 1;
- case OASADD:
- a = nodaddv;
- goto setasop;
- case OASSUB:
- a = nodsubv;
- goto setasop;
- case OASMUL:
- case OASLMUL:
- a = nodmulv;
- goto setasop;
- case OASDIV:
- a = noddivv;
- goto setasop;
- case OASLDIV:
- a = noddivvu;
- goto setasop;
- case OASMOD:
- a = nodmodv;
- goto setasop;
- case OASLMOD:
- a = nodmodvu;
- goto setasop;
- case OASASHL:
- a = nodlshv;
- goto setasop;
- case OASASHR:
- a = nodrshav;
- goto setasop;
- case OASLSHR:
- a = nodrshlv;
- goto setasop;
- case OASAND:
- a = nodandv;
- goto setasop;
- case OASOR:
- a = nodorv;
- goto setasop;
- case OASXOR:
- a = nodxorv;
- goto setasop;
- }
- }
-
- if(typefd[n->type->etype] && l && l->op == OFUNC) {
- switch(n->op) {
- case OASADD:
- case OASSUB:
- case OASMUL:
- case OASLMUL:
- case OASDIV:
- case OASLDIV:
- case OASMOD:
- case OASLMOD:
- case OASASHL:
- case OASASHR:
- case OASLSHR:
- case OASAND:
- case OASOR:
- case OASXOR:
- if(l->right && typev[l->right->etype]) {
- diag(n, "sorry float <asop> vlong not implemented\n");
- }
- }
- }
-
- if(n->op == OCAST) {
- if(l->type && typev[l->type->etype]) {
- if(machcap(n))
- return 1;
- switch(n->type->etype) {
- case TDOUBLE:
- a = nodv2d;
- goto setfnx;
- case TFLOAT:
- a = nodv2f;
- goto setfnx;
- case TLONG:
- a = nodv2sl;
- goto setfnx;
- case TULONG:
- a = nodv2ul;
- goto setfnx;
- case TINT:
- a = nodv2si;
- goto setfnx;
- case TUINT:
- a = nodv2ui;
- goto setfnx;
- case TSHORT:
- a = nodv2sh;
- goto setfnx;
- case TUSHORT:
- a = nodv2uh;
- goto setfnx;
- case TCHAR:
- a = nodv2sc;
- goto setfnx;
- case TUCHAR:
- a = nodv2uc;
- goto setfnx;
- case TIND: // small pun here
- a = nodv2ul;
- goto setfnx;
- }
- diag(n, "unknown vlong->%T cast", n->type);
- return 1;
- }
- }
-
- return 0;
-
-setbop:
- n->left = a;
- n->right = new(OLIST, l, r);
- n->complex = FNX;
- n->op = OFUNC;
- return 1;
-
-setfnxl:
- l = new(OCAST, l, 0);
- l->type = types[TLONG];
- l->complex = l->left->complex;
-
-setfnx:
- n->left = a;
- n->right = l;
- n->complex = FNX;
- n->op = OFUNC;
- return 1;
-
-setvinc:
- n->left = a;
- l = new(OADDR, l, Z);
- l->type = typ(TIND, l->left->type);
- n->right = new(OLIST, l, r);
- n->complex = FNX;
- n->op = OFUNC;
- return 1;
-
-setbool:
- if(machcap(n))
- return 1;
- n->left = a;
- n->right = new(OLIST, l, r);
- n->complex = FNX;
- n->op = OFUNC;
- n->type = types[TLONG];
- return 1;
-
-setasop:
- if(l->op == OFUNC) {
- l = l->right;
- goto setasop;
- }
-
- t = new(OCONST, 0, 0);
- t->vconst = etconv[l->type->etype];
- t->type = types[TLONG];
- t->addable = 20;
- r = new(OLIST, t, r);
-
- t = new(OADDR, a, 0);
- t->type = typ(TIND, a->type);
- r = new(OLIST, t, r);
-
- t = new(OADDR, l, 0);
- t->type = typ(TIND, l->type);
- r = new(OLIST, t, r);
-
- n->left = nodvasop;
- n->right = r;
- n->complex = FNX;
- n->op = OFUNC;
-
- return 1;
-}
-
-void
-bool64(Node *n)
-{
- Node *n1;
-
- if(machcap(Z))
- return;
- if(typev[n->type->etype]) {
- n1 = new(OXXX, 0, 0);
- *n1 = *n;
-
- n->right = n1;
- n->left = nodtestv;
- n->complex = FNX;
- n->addable = 0;
- n->op = OFUNC;
- n->type = types[TLONG];
- }
-}
-
-/*
- * more machine depend stuff.
- * this is common for 8,16,32,64 bit machines.
- * this is common for ieee machines.
- */
-double
-convvtof(vlong v)
-{
- double d;
-
- d = v; /* BOTCH */
- return d;
-}
-
-vlong
-convftov(double d)
-{
- vlong v;
-
-
- v = d; /* BOTCH */
- return v;
-}
-
-double
-convftox(double d, int et)
-{
-
- if(!typefd[et])
- diag(Z, "bad type in castftox %s", tnames[et]);
- return d;
-}
-
-vlong
-convvtox(vlong c, int et)
-{
- int n;
-
- n = 8 * ewidth[et];
- c &= MASK(n);
- if(!typeu[et])
- if(c & SIGN(n))
- c |= ~MASK(n);
- return c;
-}
diff --git a/src/cmd/cc/dcl.c b/src/cmd/cc/dcl.c
deleted file mode 100644
index 117508fd6..000000000
--- a/src/cmd/cc/dcl.c
+++ /dev/null
@@ -1,1707 +0,0 @@
-// Inferno utils/cc/dcl.c
-// http://code.google.com/p/inferno-os/source/browse/utils/cc/dcl.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include <u.h>
-#include "cc.h"
-#include "../ld/textflag.h"
-
-static int haspointers(Type*);
-
-Node*
-dodecl(void (*f)(int,Type*,Sym*), int c, Type *t, Node *n)
-{
- Sym *s;
- Node *n1;
- int32 v;
-
- nearln = lineno;
- lastfield = 0;
-
-loop:
- if(n != Z)
- switch(n->op) {
- default:
- diag(n, "unknown declarator: %O", n->op);
- break;
-
- case OARRAY:
- t = typ(TARRAY, t);
- t->width = 0;
- n1 = n->right;
- n = n->left;
- if(n1 != Z) {
- complex(n1);
- v = -1;
- if(n1->op == OCONST)
- v = n1->vconst;
- if(v <= 0) {
- diag(n, "array size must be a positive constant");
- v = 1;
- }
- t->width = v * t->link->width;
- }
- goto loop;
-
- case OIND:
- t = typ(TIND, t);
- t->garb = n->garb;
- n = n->left;
- goto loop;
-
- case OFUNC:
- t = typ(TFUNC, t);
- t->down = fnproto(n);
- n = n->left;
- goto loop;
-
- case OBIT:
- n1 = n->right;
- complex(n1);
- lastfield = -1;
- if(n1->op == OCONST)
- lastfield = n1->vconst;
- if(lastfield < 0) {
- diag(n, "field width must be non-negative constant");
- lastfield = 1;
- }
- if(lastfield == 0) {
- lastbit = 0;
- firstbit = 1;
- if(n->left != Z) {
- diag(n, "zero width named field");
- lastfield = 1;
- }
- }
- if(!typei[t->etype]) {
- diag(n, "field type must be int-like");
- t = types[TINT];
- lastfield = 1;
- }
- if(lastfield > tfield->width*8) {
- diag(n, "field width larger than field unit");
- lastfield = 1;
- }
- lastbit += lastfield;
- if(lastbit > tfield->width*8) {
- lastbit = lastfield;
- firstbit = 1;
- }
- n = n->left;
- goto loop;
-
- case ONAME:
- if(f == NODECL)
- break;
- s = n->sym;
- (*f)(c, t, s);
- if(s->class == CLOCAL)
- s = mkstatic(s);
- if(dataflag) {
- s->dataflag = dataflag;
- dataflag = 0;
- } else if(s->type != T && !haspointers(s->type))
- s->dataflag = NOPTR;
- firstbit = 0;
- n->sym = s;
- n->type = s->type;
- n->xoffset = s->offset;
- n->class = s->class;
- n->etype = TVOID;
- if(n->type != T)
- n->etype = n->type->etype;
- if(debug['d'])
- dbgdecl(s);
- acidvar(s);
- godefvar(s);
- s->varlineno = lineno;
- break;
- }
- lastdcl = t;
- return n;
-}
-
-Sym*
-mkstatic(Sym *s)
-{
- Sym *s1;
-
- if(s->class != CLOCAL)
- return s;
- snprint(symb, NSYMB, "%s$%d", s->name, s->block);
- s1 = lookup();
- if(s1->class != CSTATIC) {
- s1->type = s->type;
- s1->offset = s->offset;
- s1->block = s->block;
- s1->class = CSTATIC;
- }
- return s1;
-}
-
-/*
- * make a copy of a typedef
- * the problem is to split out incomplete
- * arrays so that it is in the variable
- * rather than the typedef.
- */
-Type*
-tcopy(Type *t)
-{
- Type *tl, *tx;
- int et;
-
- if(t == T)
- return t;
- et = t->etype;
- if(typesu[et])
- return t;
- tl = tcopy(t->link);
- if(tl != t->link ||
- (et == TARRAY && t->width == 0)) {
- tx = copytyp(t);
- tx->link = tl;
- return tx;
- }
- return t;
-}
-
-Node*
-doinit(Sym *s, Type *t, int32 o, Node *a)
-{
- Node *n;
-
- if(t == T)
- return Z;
- if(s->class == CEXTERN) {
- s->class = CGLOBL;
- if(debug['d'])
- dbgdecl(s);
- }
- if(debug['i']) {
- print("t = %T; o = %d; n = %s\n", t, o, s->name);
- prtree(a, "doinit value");
- }
-
-
- n = initlist;
- if(a->op == OINIT)
- a = a->left;
- initlist = a;
-
- a = init1(s, t, o, 0);
- if(initlist != Z)
- diag(initlist, "more initializers than structure: %s",
- s->name);
- initlist = n;
-
- return a;
-}
-
-/*
- * get next major operator,
- * dont advance initlist.
- */
-Node*
-peekinit(void)
-{
- Node *a;
-
- a = initlist;
-
-loop:
- if(a == Z)
- return a;
- if(a->op == OLIST) {
- a = a->left;
- goto loop;
- }
- return a;
-}
-
-/*
- * consume and return next element on
- * initlist. expand strings.
- */
-Node*
-nextinit(void)
-{
- Node *a, *b, *n;
-
- a = initlist;
- n = Z;
-
- if(a == Z)
- return a;
- if(a->op == OLIST) {
- n = a->right;
- a = a->left;
- }
- if(a->op == OUSED) {
- a = a->left;
- b = new(OCONST, Z, Z);
- b->type = a->type->link;
- if(a->op == OSTRING) {
- b->vconst = convvtox(*a->cstring, TCHAR);
- a->cstring++;
- }
- if(a->op == OLSTRING) {
- b->vconst = convvtox(*a->rstring, TRUNE);
- a->rstring++;
- }
- a->type->width -= b->type->width;
- if(a->type->width <= 0)
- initlist = n;
- return b;
- }
- initlist = n;
- return a;
-}
-
-int
-isstruct(Node *a, Type *t)
-{
- Node *n;
-
- switch(a->op) {
- case ODOTDOT:
- n = a->left;
- if(n && n->type && sametype(n->type, t))
- return 1;
- case OSTRING:
- case OLSTRING:
- case OCONST:
- case OINIT:
- case OELEM:
- return 0;
- }
-
- n = new(ODOTDOT, Z, Z);
- *n = *a;
-
- /*
- * ODOTDOT is a flag for tcom
- * a second tcom will not be performed
- */
- a->op = ODOTDOT;
- a->left = n;
- a->right = Z;
-
- if(tcom(n))
- return 0;
-
- if(sametype(n->type, t))
- return 1;
- return 0;
-}
-
-Node*
-init1(Sym *s, Type *t, int32 o, int exflag)
-{
- Node *a, *l, *r, nod;
- Type *t1;
- int32 e, w, so, mw;
-
- a = peekinit();
- if(a == Z)
- return Z;
-
- if(debug['i']) {
- print("t = %T; o = %d; n = %s\n", t, o, s->name);
- prtree(a, "init1 value");
- }
-
- if(exflag && a->op == OINIT)
- return doinit(s, t, o, nextinit());
-
- switch(t->etype) {
- default:
- diag(Z, "unknown type in initialization: %T to: %s", t, s->name);
- return Z;
-
- case TCHAR:
- case TUCHAR:
- case TINT:
- case TUINT:
- case TSHORT:
- case TUSHORT:
- case TLONG:
- case TULONG:
- case TVLONG:
- case TUVLONG:
- case TFLOAT:
- case TDOUBLE:
- case TIND:
- single:
- if(a->op == OARRAY || a->op == OELEM)
- return Z;
-
- a = nextinit();
- if(a == Z)
- return Z;
-
- if(t->nbits)
- diag(Z, "cannot initialize bitfields");
- if(s->class == CAUTO) {
- l = new(ONAME, Z, Z);
- l->sym = s;
- l->type = t;
- l->etype = TVOID;
- if(s->type)
- l->etype = s->type->etype;
- l->xoffset = s->offset + o;
- l->class = s->class;
-
- l = new(OASI, l, a);
- return l;
- }
-
- complex(a);
- if(a->type == T)
- return Z;
-
- if(a->op == OCONST) {
- if(vconst(a) && t->etype == TIND && a->type && a->type->etype != TIND){
- diag(a, "initialize pointer to an integer: %s", s->name);
- return Z;
- }
- if(!sametype(a->type, t)) {
- /* hoop jumping to save malloc */
- if(nodcast == Z)
- nodcast = new(OCAST, Z, Z);
- nod = *nodcast;
- nod.left = a;
- nod.type = t;
- nod.lineno = a->lineno;
- complex(&nod);
- if(nod.type)
- *a = nod;
- }
- if(a->op != OCONST) {
- diag(a, "initializer is not a constant: %s",
- s->name);
- return Z;
- }
- if(vconst(a) == 0)
- return Z;
- goto gext;
- }
- if(t->etype == TIND) {
- while(a->op == OCAST) {
- warn(a, "CAST in initialization ignored");
- a = a->left;
- }
- if(!sametype(t, a->type)) {
- diag(a, "initialization of incompatible pointers: %s\n%T and %T",
- s->name, t, a->type);
- }
- if(a->op == OADDR)
- a = a->left;
- goto gext;
- }
-
- while(a->op == OCAST)
- a = a->left;
- if(a->op == OADDR) {
- warn(a, "initialize pointer to an integer: %s", s->name);
- a = a->left;
- goto gext;
- }
- diag(a, "initializer is not a constant: %s", s->name);
- return Z;
-
- gext:
- gextern(s, a, o, t->width);
-
- return Z;
-
- case TARRAY:
- w = t->link->width;
- if(a->op == OSTRING || a->op == OLSTRING)
- if(typei[t->link->etype]) {
- /*
- * get rid of null if sizes match exactly
- */
- a = nextinit();
- mw = t->width/w;
- so = a->type->width/a->type->link->width;
- if(mw && so > mw) {
- if(so != mw+1)
- diag(a, "string initialization larger than array");
- a->type->width -= a->type->link->width;
- }
-
- /*
- * arrange strings to be expanded
- * inside OINIT braces.
- */
- a = new(OUSED, a, Z);
- return doinit(s, t, o, a);
- }
-
- mw = -w;
- l = Z;
- for(e=0;;) {
- /*
- * peek ahead for element initializer
- */
- a = peekinit();
- if(a == Z)
- break;
- if(a->op == OELEM && t->link->etype != TSTRUCT)
- break;
- if(a->op == OARRAY) {
- if(e && exflag)
- break;
- a = nextinit();
- r = a->left;
- complex(r);
- if(r->op != OCONST) {
- diag(r, "initializer subscript must be constant");
- return Z;
- }
- e = r->vconst;
- if(t->width != 0)
- if(e < 0 || e*w >= t->width) {
- diag(a, "initialization index out of range: %d", e);
- continue;
- }
- }
-
- so = e*w;
- if(so > mw)
- mw = so;
- if(t->width != 0)
- if(mw >= t->width)
- break;
- r = init1(s, t->link, o+so, 1);
- l = newlist(l, r);
- e++;
- }
- if(t->width == 0)
- t->width = mw+w;
- return l;
-
- case TUNION:
- case TSTRUCT:
- /*
- * peek ahead to find type of rhs.
- * if its a structure, then treat
- * this element as a variable
- * rather than an aggregate.
- */
- if(isstruct(a, t))
- goto single;
-
- if(t->width <= 0) {
- diag(Z, "incomplete structure: %s", s->name);
- return Z;
- }
- l = Z;
-
- again:
- for(t1 = t->link; t1 != T; t1 = t1->down) {
- if(a->op == OARRAY && t1->etype != TARRAY)
- break;
- if(a->op == OELEM) {
- if(t1->sym != a->sym)
- continue;
- nextinit();
- }
- r = init1(s, t1, o+t1->offset, 1);
- l = newlist(l, r);
- a = peekinit();
- if(a == Z)
- break;
- if(a->op == OELEM)
- goto again;
- }
- if(a && a->op == OELEM)
- diag(a, "structure element not found %F", a);
- return l;
- }
-}
-
-Node*
-newlist(Node *l, Node *r)
-{
- if(r == Z)
- return l;
- if(l == Z)
- return r;
- return new(OLIST, l, r);
-}
-
-static int
-haspointers(Type *t)
-{
- Type *fld;
-
- switch(t->etype) {
- case TSTRUCT:
- for(fld = t->link; fld != T; fld = fld->down) {
- if(haspointers(fld))
- return 1;
- }
- return 0;
- case TARRAY:
- return haspointers(t->link);
- case TIND:
- return t->link->etype != TFUNC;
- default:
- return 0;
- }
-}
-
-void
-sualign(Type *t)
-{
- Type *l;
- int32 o, w, maxal;
-
- o = 0;
- maxal = 0;
- switch(t->etype) {
-
- case TSTRUCT:
- t->offset = 0;
- w = 0;
- for(l = t->link; l != T; l = l->down) {
- if(l->nbits) {
- if(l->shift <= 0) {
- l->shift = -l->shift;
- w = xround(w, tfield->width);
- o = w;
- w += tfield->width;
- }
- l->offset = o;
- } else {
- if(l->width <= 0)
- if(l->down != T)
- if(l->sym)
- diag(Z, "incomplete structure element: %s",
- l->sym->name);
- else
- diag(Z, "incomplete structure element");
- w = align(w, l, Ael1, &maxal);
- l->offset = w;
- w = align(w, l, Ael2, &maxal);
- }
- }
- w = align(w, t, Asu2, &maxal);
- t->width = w;
- t->align = maxal;
- acidtype(t);
- godeftype(t);
- return;
-
- case TUNION:
- t->offset = 0;
- w = 0;
- for(l = t->link; l != T; l = l->down) {
- if(l->width <= 0)
- if(l->sym)
- diag(Z, "incomplete union element: %s",
- l->sym->name);
- else
- diag(Z, "incomplete union element");
- l->offset = 0;
- l->shift = 0;
- if((debug['q'] || debug['Q']) && haspointers(l))
- diag(Z, "precise garbage collector cannot handle unions with pointers");
-
- o = align(align(0, l, Ael1, &maxal), l, Ael2, &maxal);
- if(o > w)
- w = o;
- }
- w = align(w, t, Asu2, &maxal);
- t->width = w;
- t->align = maxal;
- acidtype(t);
- godeftype(t);
- return;
-
- default:
- diag(Z, "unknown type in sualign: %T", t);
- break;
- }
-}
-
-int32
-xround(int32 v, int w)
-{
- int r;
-
- if(w <= 0 || w > 8) {
- diag(Z, "rounding by %d", w);
- w = 1;
- }
- r = v%w;
- if(r)
- v += w-r;
- return v;
-}
-
-Type*
-ofnproto(Node *n)
-{
- Type *tl, *tr, *t;
-
- if(n == Z)
- return T;
- switch(n->op) {
- case OLIST:
- tl = ofnproto(n->left);
- tr = ofnproto(n->right);
- if(tl == T)
- return tr;
- tl->down = tr;
- return tl;
-
- case ONAME:
- t = copytyp(n->sym->type);
- t->down = T;
- return t;
- }
- return T;
-}
-
-#define ANSIPROTO 1
-#define OLDPROTO 2
-
-void
-argmark(Node *n, int pass)
-{
- Type *t;
-
- if(hasdotdotdot(thisfn->link))
- autoffset = align(0, thisfn->link, Aarg0, nil);
- stkoff = 0;
- for(; n->left != Z; n = n->left) {
- if(n->op != OFUNC || n->left->op != ONAME)
- continue;
- walkparam(n->right, pass);
- if(pass != 0 && anyproto(n->right) == OLDPROTO) {
- t = typ(TFUNC, n->left->sym->type->link);
- t->down = typ(TOLD, T);
- t->down->down = ofnproto(n->right);
- tmerge(t, n->left->sym);
- n->left->sym->type = t;
- }
- break;
- }
- autoffset = 0;
- stkoff = 0;
-}
-
-void
-walkparam(Node *n, int pass)
-{
- Sym *s;
- Node *n1;
-
- if(n != Z && n->op == OPROTO && n->left == Z && n->type == types[TVOID])
- return;
-
-loop:
- if(n == Z)
- return;
- switch(n->op) {
- default:
- diag(n, "argument not a name/prototype: %O", n->op);
- break;
-
- case OLIST:
- walkparam(n->left, pass);
- n = n->right;
- goto loop;
-
- case OPROTO:
- for(n1 = n; n1 != Z; n1=n1->left)
- if(n1->op == ONAME) {
- if(pass == 0) {
- s = n1->sym;
- push1(s);
- s->offset = -1;
- break;
- }
- dodecl(pdecl, CPARAM, n->type, n->left);
- break;
- }
- if(n1)
- break;
- if(pass == 0) {
- /*
- * extension:
- * allow no name in argument declaration
- diag(Z, "no name in argument declaration");
- */
- break;
- }
- dodecl(NODECL, CPARAM, n->type, n->left);
- pdecl(CPARAM, lastdcl, S);
- break;
-
- case ODOTDOT:
- break;
-
- case ONAME:
- s = n->sym;
- if(pass == 0) {
- push1(s);
- s->offset = -1;
- break;
- }
- if(s->offset != -1) {
- if(autoffset == 0) {
- firstarg = s;
- firstargtype = s->type;
- }
- autoffset = align(autoffset, s->type, Aarg1, nil);
- s->offset = autoffset;
- autoffset = align(autoffset, s->type, Aarg2, nil);
- } else
- dodecl(pdecl, CXXX, types[TINT], n);
- break;
- }
-}
-
-void
-markdcl(void)
-{
- Decl *d;
-
- blockno++;
- d = push();
- d->val = DMARK;
- d->offset = autoffset;
- d->block = autobn;
- autobn = blockno;
-}
-
-Node*
-revertdcl(void)
-{
- Decl *d;
- Sym *s;
- Node *n, *n1;
-
- n = Z;
- for(;;) {
- d = dclstack;
- if(d == D) {
- diag(Z, "pop off dcl stack");
- break;
- }
- dclstack = d->link;
- s = d->sym;
- switch(d->val) {
- case DMARK:
- autoffset = d->offset;
- autobn = d->block;
- return n;
-
- case DAUTO:
- if(debug['d'])
- print("revert1 \"%s\"\n", s->name);
- if(s->aused == 0) {
- nearln = s->varlineno;
- if(s->class == CAUTO)
- warn(Z, "auto declared and not used: %s", s->name);
- if(s->class == CPARAM)
- warn(Z, "param declared and not used: %s", s->name);
- }
- if(s->type && (s->type->garb & GVOLATILE)) {
- n1 = new(ONAME, Z, Z);
- n1->sym = s;
- n1->type = s->type;
- n1->etype = TVOID;
- if(n1->type != T)
- n1->etype = n1->type->etype;
- n1->xoffset = s->offset;
- n1->class = s->class;
-
- n1 = new(OADDR, n1, Z);
- n1 = new(OUSED, n1, Z);
- if(n == Z)
- n = n1;
- else
- n = new(OLIST, n1, n);
- }
- s->type = d->type;
- s->class = d->class;
- s->offset = d->offset;
- s->block = d->block;
- s->varlineno = d->varlineno;
- s->aused = d->aused;
- break;
-
- case DSUE:
- if(debug['d'])
- print("revert2 \"%s\"\n", s->name);
- s->suetag = d->type;
- s->sueblock = d->block;
- break;
-
- case DLABEL:
- if(debug['d'])
- print("revert3 \"%s\"\n", s->name);
- if(s->label && s->label->addable == 0)
- warn(s->label, "label declared and not used \"%s\"", s->name);
- s->label = Z;
- break;
- }
- }
- return n;
-}
-
-Type*
-fnproto(Node *n)
-{
- int r;
-
- r = anyproto(n->right);
- if(r == 0 || (r & OLDPROTO)) {
- if(r & ANSIPROTO)
- diag(n, "mixed ansi/old function declaration: %F", n->left);
- return T;
- }
- return fnproto1(n->right);
-}
-
-int
-anyproto(Node *n)
-{
- int r;
-
- r = 0;
-
-loop:
- if(n == Z)
- return r;
- switch(n->op) {
- case OLIST:
- r |= anyproto(n->left);
- n = n->right;
- goto loop;
-
- case ODOTDOT:
- case OPROTO:
- return r | ANSIPROTO;
- }
- return r | OLDPROTO;
-}
-
-Type*
-fnproto1(Node *n)
-{
- Type *t;
-
- if(n == Z)
- return T;
- switch(n->op) {
- case OLIST:
- t = fnproto1(n->left);
- if(t != T)
- t->down = fnproto1(n->right);
- return t;
-
- case OPROTO:
- lastdcl = T;
- dodecl(NODECL, CXXX, n->type, n->left);
- t = typ(TXXX, T);
- if(lastdcl != T)
- *t = *paramconv(lastdcl, 1);
- return t;
-
- case ONAME:
- diag(n, "incomplete argument prototype");
- return typ(TINT, T);
-
- case ODOTDOT:
- return typ(TDOT, T);
- }
- diag(n, "unknown op in fnproto");
- return T;
-}
-
-void
-dbgdecl(Sym *s)
-{
- print("decl \"%s\": C=%s [B=%d:O=%d] T=%T\n",
- s->name, cnames[s->class], s->block, s->offset, s->type);
-}
-
-Decl*
-push(void)
-{
- Decl *d;
-
- d = alloc(sizeof(*d));
- d->link = dclstack;
- dclstack = d;
- return d;
-}
-
-Decl*
-push1(Sym *s)
-{
- Decl *d;
-
- d = push();
- d->sym = s;
- d->val = DAUTO;
- d->type = s->type;
- d->class = s->class;
- d->offset = s->offset;
- d->block = s->block;
- d->varlineno = s->varlineno;
- d->aused = s->aused;
- return d;
-}
-
-int
-sametype(Type *t1, Type *t2)
-{
-
- if(t1 == t2)
- return 1;
- return rsametype(t1, t2, 5, 1);
-}
-
-int
-rsametype(Type *t1, Type *t2, int n, int f)
-{
- int et;
-
- n--;
- for(;;) {
- if(t1 == t2)
- return 1;
- if(t1 == T || t2 == T)
- return 0;
- if(n <= 0)
- return 1;
- et = t1->etype;
- if(et != t2->etype)
- return 0;
- if(et == TFUNC) {
- if(!rsametype(t1->link, t2->link, n, 0))
- return 0;
- t1 = t1->down;
- t2 = t2->down;
- while(t1 != T && t2 != T) {
- if(t1->etype == TOLD) {
- t1 = t1->down;
- continue;
- }
- if(t2->etype == TOLD) {
- t2 = t2->down;
- continue;
- }
- while(t1 != T || t2 != T) {
- if(!rsametype(t1, t2, n, 0))
- return 0;
- t1 = t1->down;
- t2 = t2->down;
- }
- break;
- }
- return 1;
- }
- if(et == TARRAY)
- if(t1->width != t2->width && t1->width != 0 && t2->width != 0)
- return 0;
- if(typesu[et]) {
- if(t1->link == T)
- snap(t1);
- if(t2->link == T)
- snap(t2);
- t1 = t1->link;
- t2 = t2->link;
- for(;;) {
- if(t1 == t2)
- return 1;
- if(!rsametype(t1, t2, n, 0))
- return 0;
- t1 = t1->down;
- t2 = t2->down;
- }
- }
- t1 = t1->link;
- t2 = t2->link;
- if((f || !debug['V']) && et == TIND) {
- if(t1 != T && t1->etype == TVOID)
- return 1;
- if(t2 != T && t2->etype == TVOID)
- return 1;
- }
- }
-}
-
-typedef struct Typetab Typetab;
-
-struct Typetab{
- int n;
- Type **a;
-};
-
-static int
-sigind(Type *t, Typetab *tt)
-{
- int n;
- Type **a, **na, **p, **e;
-
- n = tt->n;
- a = tt->a;
- e = a+n;
- /* linear search seems ok */
- for(p = a ; p < e; p++)
- if(sametype(*p, t))
- return p-a;
- if((n&15) == 0){
- na = malloc((n+16)*sizeof(Type*));
- if(na == nil) {
- print("%s: out of memory", argv0);
- errorexit();
- }
- memmove(na, a, n*sizeof(Type*));
- free(a);
- a = tt->a = na;
- }
- a[tt->n++] = t;
- return -1;
-}
-
-static uint32
-signat(Type *t, Typetab *tt)
-{
- int i;
- Type *t1;
- int32 s;
-
- s = 0;
- for(; t; t=t->link) {
- s = s*thash1 + thash[t->etype];
- if(t->garb&GINCOMPLETE)
- return s;
- switch(t->etype) {
- default:
- return s;
- case TARRAY:
- s = s*thash2 + 0; /* was t->width */
- break;
- case TFUNC:
- for(t1=t->down; t1; t1=t1->down)
- s = s*thash3 + signat(t1, tt);
- break;
- case TSTRUCT:
- case TUNION:
- if((i = sigind(t, tt)) >= 0){
- s = s*thash2 + i;
- return s;
- }
- for(t1=t->link; t1; t1=t1->down)
- s = s*thash3 + signat(t1, tt);
- return s;
- case TIND:
- break;
- }
- }
- return s;
-}
-
-uint32
-signature(Type *t)
-{
- uint32 s;
- Typetab tt;
-
- tt.n = 0;
- tt.a = nil;
- s = signat(t, &tt);
- free(tt.a);
- return s;
-}
-
-uint32
-sign(Sym *s)
-{
- uint32 v;
- Type *t;
-
- if(s->sig == SIGINTERN)
- return SIGNINTERN;
- if((t = s->type) == T)
- return 0;
- v = signature(t);
- if(v == 0)
- v = SIGNINTERN;
- return v;
-}
-
-void
-snap(Type *t)
-{
- if(typesu[t->etype])
- if(t->link == T && t->tag && t->tag->suetag) {
- t->link = t->tag->suetag->link;
- t->width = t->tag->suetag->width;
- }
-}
-
-Type*
-dotag(Sym *s, int et, int bn)
-{
- Decl *d;
-
- if(bn != 0 && bn != s->sueblock) {
- d = push();
- d->sym = s;
- d->val = DSUE;
- d->type = s->suetag;
- d->block = s->sueblock;
- s->suetag = T;
- }
- if(s->suetag == T) {
- s->suetag = typ(et, T);
- s->sueblock = autobn;
- }
- if(s->suetag->etype != et)
- diag(Z, "tag used for more than one type: %s",
- s->name);
- if(s->suetag->tag == S)
- s->suetag->tag = s;
- return s->suetag;
-}
-
-Node*
-dcllabel(Sym *s, int f)
-{
- Decl *d, d1;
- Node *n;
-
- n = s->label;
- if(n != Z) {
- if(f) {
- if(n->complex)
- diag(Z, "label reused: %s", s->name);
- n->complex = 1; // declared
- } else
- n->addable = 1; // used
- return n;
- }
-
- d = push();
- d->sym = s;
- d->val = DLABEL;
- dclstack = d->link;
-
- d1 = *firstdcl;
- *firstdcl = *d;
- *d = d1;
-
- firstdcl->link = d;
- firstdcl = d;
-
- n = new(OXXX, Z, Z);
- n->sym = s;
- n->complex = f;
- n->addable = !f;
- s->label = n;
-
- if(debug['d'])
- dbgdecl(s);
- return n;
-}
-
-Type*
-paramconv(Type *t, int f)
-{
-
- switch(t->etype) {
- case TUNION:
- case TSTRUCT:
- if(t->width <= 0)
- diag(Z, "incomplete structure: %s", t->tag->name);
- break;
-
- case TARRAY:
- t = typ(TIND, t->link);
- t->width = types[TIND]->width;
- break;
-
- case TFUNC:
- t = typ(TIND, t);
- t->width = types[TIND]->width;
- break;
-
- case TFLOAT:
- if(!f)
- t = types[TDOUBLE];
- break;
-
- case TCHAR:
- case TSHORT:
- if(!f)
- t = types[TINT];
- break;
-
- case TUCHAR:
- case TUSHORT:
- if(!f)
- t = types[TUINT];
- break;
- }
- return t;
-}
-
-void
-adecl(int c, Type *t, Sym *s)
-{
-
- if(c == CSTATIC)
- c = CLOCAL;
- if(t->etype == TFUNC) {
- if(c == CXXX)
- c = CEXTERN;
- if(c == CLOCAL)
- c = CSTATIC;
- if(c == CAUTO || c == CEXREG)
- diag(Z, "function cannot be %s %s", cnames[c], s->name);
- }
- if(c == CXXX)
- c = CAUTO;
- if(s) {
- if(s->class == CSTATIC)
- if(c == CEXTERN || c == CGLOBL) {
- warn(Z, "just say static: %s", s->name);
- c = CSTATIC;
- }
- if(s->class == CAUTO || s->class == CPARAM || s->class == CLOCAL)
- if(s->block == autobn)
- diag(Z, "auto redeclaration of: %s", s->name);
- if(c != CPARAM)
- push1(s);
- s->block = autobn;
- s->offset = 0;
- s->type = t;
- s->class = c;
- s->aused = 0;
- }
- switch(c) {
- case CAUTO:
- autoffset = align(autoffset, t, Aaut3, nil);
- stkoff = maxround(stkoff, autoffset);
- s->offset = -autoffset;
- break;
-
- case CPARAM:
- if(autoffset == 0) {
- firstarg = s;
- firstargtype = t;
- }
- autoffset = align(autoffset, t, Aarg1, nil);
- if(s)
- s->offset = autoffset;
- autoffset = align(autoffset, t, Aarg2, nil);
- break;
- }
-}
-
-void
-pdecl(int c, Type *t, Sym *s)
-{
- if(s && s->offset != -1) {
- diag(Z, "not a parameter: %s", s->name);
- return;
- }
- t = paramconv(t, c==CPARAM);
- if(c == CXXX)
- c = CPARAM;
- if(c != CPARAM) {
- diag(Z, "parameter cannot have class: %s", s->name);
- c = CPARAM;
- }
- adecl(c, t, s);
-}
-
-void
-xdecl(int c, Type *t, Sym *s)
-{
- int32 o;
-
- o = 0;
- switch(c) {
- case CEXREG:
- o = exreg(t);
- if(o == 0)
- c = CEXTERN;
- if(s->class == CGLOBL)
- c = CGLOBL;
- break;
-
- case CEXTERN:
- if(s->class == CGLOBL)
- c = CGLOBL;
- break;
-
- case CXXX:
- c = CGLOBL;
- if(s->class == CEXTERN)
- s->class = CGLOBL;
- break;
-
- case CAUTO:
- diag(Z, "overspecified class: %s %s %s", s->name, cnames[c], cnames[s->class]);
- c = CEXTERN;
- break;
-
- case CTYPESTR:
- if(!typesuv[t->etype]) {
- diag(Z, "typestr must be struct/union: %s", s->name);
- break;
- }
- dclfunct(t, s);
- break;
- }
-
- if(s->class == CSTATIC)
- if(c == CEXTERN || c == CGLOBL) {
- warn(Z, "overspecified class: %s %s %s", s->name, cnames[c], cnames[s->class]);
- c = CSTATIC;
- }
- if(s->type != T)
- if(s->class != c || !sametype(t, s->type) || t->etype == TENUM) {
- diag(Z, "external redeclaration of: %s", s->name);
- Bprint(&diagbuf, " %s %T %L\n", cnames[c], t, nearln);
- Bprint(&diagbuf, " %s %T %L\n", cnames[s->class], s->type, s->varlineno);
- }
- tmerge(t, s);
- s->type = t;
- if(c == CTYPEDEF && (typechlv[t->etype] || typefd[t->etype])) {
- s->type = copytyp(t);
- s->type->tag = s;
- }
- s->class = c;
- s->block = 0;
- s->offset = o;
-}
-
-void
-tmerge(Type *t1, Sym *s)
-{
- Type *ta, *tb, *t2;
-
- t2 = s->type;
- for(;;) {
- if(t1 == T || t2 == T || t1 == t2)
- break;
- if(t1->etype != t2->etype)
- break;
- switch(t1->etype) {
- case TFUNC:
- ta = t1->down;
- tb = t2->down;
- if(ta == T) {
- t1->down = tb;
- break;
- }
- if(tb == T)
- break;
- while(ta != T && tb != T) {
- if(ta == tb)
- break;
- /* ignore old-style flag */
- if(ta->etype == TOLD) {
- ta = ta->down;
- continue;
- }
- if(tb->etype == TOLD) {
- tb = tb->down;
- continue;
- }
- /* checking terminated by ... */
- if(ta->etype == TDOT && tb->etype == TDOT) {
- ta = T;
- tb = T;
- break;
- }
- if(!sametype(ta, tb))
- break;
- ta = ta->down;
- tb = tb->down;
- }
- if(ta != tb)
- diag(Z, "function inconsistently declared: %s", s->name);
-
- /* take new-style over old-style */
- ta = t1->down;
- tb = t2->down;
- if(ta != T && ta->etype == TOLD)
- if(tb != T && tb->etype != TOLD)
- t1->down = tb;
- break;
-
- case TARRAY:
- /* should we check array size change? */
- if(t2->width > t1->width)
- t1->width = t2->width;
- break;
-
- case TUNION:
- case TSTRUCT:
- return;
- }
- t1 = t1->link;
- t2 = t2->link;
- }
-}
-
-void
-edecl(int c, Type *t, Sym *s)
-{
- Type *t1;
-
- if(s == S)
- diag(Z, "unnamed structure elements not supported");
- else
- if(c != CXXX)
- diag(Z, "structure element cannot have class: %s", s->name);
- t1 = t;
- t = copytyp(t1);
- t->sym = s;
- t->down = T;
- if(lastfield) {
- t->shift = lastbit - lastfield;
- t->nbits = lastfield;
- if(firstbit)
- t->shift = -t->shift;
- if(typeu[t->etype])
- t->etype = tufield->etype;
- else
- t->etype = tfield->etype;
- }
- if(strf == T)
- strf = t;
- else
- strl->down = t;
- strl = t;
-}
-
-/*
- * this routine is very suspect.
- * ansi requires the enum type to
- * be represented as an 'int'
- * this means that 0x81234567
- * would be illegal. this routine
- * makes signed and unsigned go
- * to unsigned.
- */
-Type*
-maxtype(Type *t1, Type *t2)
-{
-
- if(t1 == T)
- return t2;
- if(t2 == T)
- return t1;
- if(t1->etype > t2->etype)
- return t1;
- return t2;
-}
-
-void
-doenum(Sym *s, Node *n)
-{
-
- if(n) {
- complex(n);
- if(n->op != OCONST) {
- diag(n, "enum not a constant: %s", s->name);
- return;
- }
- en.cenum = n->type;
- en.tenum = maxtype(en.cenum, en.tenum);
-
- if(!typefd[en.cenum->etype])
- en.lastenum = n->vconst;
- else
- en.floatenum = n->fconst;
- }
- if(dclstack)
- push1(s);
- xdecl(CXXX, types[TENUM], s);
-
- if(en.cenum == T) {
- en.tenum = types[TINT];
- en.cenum = types[TINT];
- en.lastenum = 0;
- }
- s->tenum = en.cenum;
-
- if(!typefd[s->tenum->etype]) {
- s->vconst = convvtox(en.lastenum, s->tenum->etype);
- en.lastenum++;
- } else {
- s->fconst = en.floatenum;
- en.floatenum++;
- }
-
- if(debug['d'])
- dbgdecl(s);
- acidvar(s);
- godefvar(s);
-}
-
-void
-symadjust(Sym *s, Node *n, int32 del)
-{
-
- switch(n->op) {
- default:
- if(n->left)
- symadjust(s, n->left, del);
- if(n->right)
- symadjust(s, n->right, del);
- return;
-
- case ONAME:
- if(n->sym == s)
- n->xoffset -= del;
- return;
-
- case OCONST:
- case OSTRING:
- case OLSTRING:
- case OINDREG:
- case OREGISTER:
- return;
- }
-}
-
-Node*
-contig(Sym *s, Node *n, int32 v)
-{
- Node *p, *r, *q, *m;
- int32 w;
- Type *zt;
-
- if(debug['i']) {
- print("contig v = %d; s = %s\n", v, s->name);
- prtree(n, "doinit value");
- }
-
- if(n == Z)
- goto no;
- w = s->type->width;
-
- /*
- * nightmare: an automatic array whose size
- * increases when it is initialized
- */
- if(v != w) {
- if(v != 0)
- diag(n, "automatic adjustable array: %s", s->name);
- v = s->offset;
- autoffset = align(autoffset, s->type, Aaut3, nil);
- s->offset = -autoffset;
- stkoff = maxround(stkoff, autoffset);
- symadjust(s, n, v - s->offset);
- }
- if(w <= ewidth[TIND])
- goto no;
- if(n->op == OAS)
- diag(Z, "oops in contig");
-/*ZZZ this appears incorrect
-need to check if the list completely covers the data.
-if not, bail
- */
- if(n->op == OLIST)
- goto no;
- if(n->op == OASI)
- if(n->left->type)
- if(n->left->type->width == w)
- goto no;
- while(w & (ewidth[TIND]-1))
- w++;
-/*
- * insert the following code, where long becomes vlong if pointers are fat
- *
- *(long**)&X = (long*)((char*)X + sizeof(X));
- do {
- *(long**)&X -= 1;
- **(long**)&X = 0;
- } while(*(long**)&X);
- */
-
- for(q=n; q->op != ONAME; q=q->left)
- ;
-
- zt = ewidth[TIND] > ewidth[TLONG]? types[TVLONG]: types[TLONG];
-
- p = new(ONAME, Z, Z);
- *p = *q;
- p->type = typ(TIND, zt);
- p->xoffset = s->offset;
-
- r = new(ONAME, Z, Z);
- *r = *p;
- r = new(OPOSTDEC, r, Z);
-
- q = new(ONAME, Z, Z);
- *q = *p;
- q = new(OIND, q, Z);
-
- m = new(OCONST, Z, Z);
- m->vconst = 0;
- m->type = zt;
-
- q = new(OAS, q, m);
-
- r = new(OLIST, r, q);
-
- q = new(ONAME, Z, Z);
- *q = *p;
- r = new(ODWHILE, q, r);
-
- q = new(ONAME, Z, Z);
- *q = *p;
- q->type = q->type->link;
- q->xoffset += w;
- q = new(OADDR, q, 0);
-
- q = new(OASI, p, q);
- r = new(OLIST, q, r);
-
- n = new(OLIST, r, n);
-
-no:
- return n;
-}
diff --git a/src/cmd/cc/doc.go b/src/cmd/cc/doc.go
deleted file mode 100644
index 10901b441..000000000
--- a/src/cmd/cc/doc.go
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build ignore
-
-/*
-
-This directory contains the portable section of the Plan 9 C compilers.
-See ../6c, ../8c, and ../5c for more information.
-
-*/
-package main
diff --git a/src/cmd/cc/dpchk.c b/src/cmd/cc/dpchk.c
deleted file mode 100644
index 606bf40dd..000000000
--- a/src/cmd/cc/dpchk.c
+++ /dev/null
@@ -1,793 +0,0 @@
-// Inferno utils/cc/dpchk.c
-// http://code.google.com/p/inferno-os/source/browse/utils/cc/dpchk.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include <u.h>
-#include "cc.h"
-#include "y.tab.h"
-
-enum
-{
- Fnone = 0,
- Fl,
- Fvl,
- Fignor,
- Fstar,
- Fadj,
-
- Fverb = 10,
-};
-
-typedef struct Tprot Tprot;
-struct Tprot
-{
- Type* type;
- Bits flag;
- Tprot* link;
-};
-
-typedef struct Tname Tname;
-struct Tname
-{
- char* name;
- int param;
- int count;
- Tname* link;
- Tprot* prot;
-};
-
-static Type* indchar;
-static uchar flagbits[512];
-static char* lastfmt;
-static int lastadj;
-static int lastverb;
-static int nstar;
-static Tprot* tprot;
-static Tname* tname;
-
-void
-argflag(int c, int v)
-{
-
- switch(v) {
- case Fignor:
- case Fstar:
- case Fl:
- case Fvl:
- flagbits[c] = v;
- break;
- case Fverb:
- flagbits[c] = lastverb;
-/*print("flag-v %c %d\n", c, lastadj);*/
- lastverb++;
- break;
- case Fadj:
- flagbits[c] = lastadj;
-/*print("flag-l %c %d\n", c, lastadj);*/
- lastadj++;
- break;
- }
-}
-
-Bits
-getflag(char *s)
-{
- Bits flag;
- int f;
- Fmt fmt;
- Rune c;
-
- flag = zbits;
- nstar = 0;
- fmtstrinit(&fmt);
- for(;;) {
- s += chartorune(&c, s);
- if(c == 0 || c >= nelem(flagbits))
- break;
- fmtrune(&fmt, c);
- f = flagbits[c];
- switch(f) {
- case Fnone:
- argflag(c, Fverb);
- f = flagbits[c];
- break;
- case Fstar:
- nstar++;
- case Fignor:
- continue;
- case Fl:
- if(bset(flag, Fl))
- flag = bor(flag, blsh(Fvl));
- }
- flag = bor(flag, blsh(f));
- if(f >= Fverb)
- break;
- }
- free(lastfmt);
- lastfmt = fmtstrflush(&fmt);
- return flag;
-}
-
-static void
-newprot(Sym *m, Type *t, char *s, Tprot **prot)
-{
- Bits flag;
- Tprot *l;
-
- if(t == T) {
- warn(Z, "%s: newprot: type not defined", m->name);
- return;
- }
- flag = getflag(s);
- for(l=*prot; l; l=l->link)
- if(beq(flag, l->flag) && sametype(t, l->type))
- return;
- l = alloc(sizeof(*l));
- l->type = t;
- l->flag = flag;
- l->link = *prot;
- *prot = l;
-}
-
-static Tname*
-newname(char *s, int p, int count)
-{
- Tname *l;
-
- for(l=tname; l; l=l->link)
- if(strcmp(l->name, s) == 0) {
- if(p >= 0 && l->param != p)
- yyerror("vargck %s already defined\n", s);
- return l;
- }
- if(p < 0)
- return nil;
-
- l = alloc(sizeof(*l));
- l->name = s;
- l->param = p;
- l->link = tname;
- l->count = count;
- tname = l;
- return l;
-}
-
-void
-arginit(void)
-{
- int i;
-
-/* debug['F'] = 1;*/
-/* debug['w'] = 1;*/
-
- lastadj = Fadj;
- lastverb = Fverb;
- indchar = typ(TIND, types[TCHAR]);
-
- memset(flagbits, Fnone, sizeof(flagbits));
-
- for(i='0'; i<='9'; i++)
- argflag(i, Fignor);
- argflag('.', Fignor);
- argflag('#', Fignor);
- argflag('u', Fignor);
- argflag('h', Fignor);
- argflag('+', Fignor);
- argflag('-', Fignor);
-
- argflag('*', Fstar);
- argflag('l', Fl);
-
- argflag('o', Fverb);
- flagbits['x'] = flagbits['o'];
- flagbits['X'] = flagbits['o'];
-}
-
-static char*
-getquoted(void)
-{
- int c;
- Rune r;
- Fmt fmt;
-
- c = getnsc();
- if(c != '"')
- return nil;
- fmtstrinit(&fmt);
- for(;;) {
- r = getr();
- if(r == '\n') {
- free(fmtstrflush(&fmt));
- return nil;
- }
- if(r == '"')
- break;
- fmtrune(&fmt, r);
- }
- free(lastfmt);
- lastfmt = fmtstrflush(&fmt);
- return strdup(lastfmt);
-}
-
-void
-pragvararg(void)
-{
- Sym *s;
- int n, c;
- char *t;
- Type *ty;
- Tname *l;
-
- if(!debug['F'])
- goto out;
- s = getsym();
- if(s && strcmp(s->name, "argpos") == 0)
- goto ckpos;
- if(s && strcmp(s->name, "type") == 0)
- goto cktype;
- if(s && strcmp(s->name, "flag") == 0)
- goto ckflag;
- if(s && strcmp(s->name, "countpos") == 0)
- goto ckcount;
- yyerror("syntax in #pragma varargck");
- goto out;
-
-ckpos:
-/*#pragma varargck argpos warn 2*/
- s = getsym();
- if(s == S)
- goto bad;
- n = getnsn();
- if(n < 0)
- goto bad;
- newname(s->name, n, 0);
- goto out;
-
-ckcount:
-/*#pragma varargck countpos name 2*/
- s = getsym();
- if(s == S)
- goto bad;
- n = getnsn();
- if(n < 0)
- goto bad;
- newname(s->name, 0, n);
- goto out;
-
-ckflag:
-/*#pragma varargck flag 'c'*/
- c = getnsc();
- if(c != '\'')
- goto bad;
- c = getr();
- if(c == '\\')
- c = getr();
- else if(c == '\'')
- goto bad;
- if(c == '\n')
- goto bad;
- if(getc() != '\'')
- goto bad;
- argflag(c, Fignor);
- goto out;
-
-cktype:
- c = getnsc();
- unget(c);
- if(c != '"') {
-/*#pragma varargck type name int*/
- s = getsym();
- if(s == S)
- goto bad;
- l = newname(s->name, -1, -1);
- s = getsym();
- if(s == S)
- goto bad;
- ty = s->type;
- while((c = getnsc()) == '*')
- ty = typ(TIND, ty);
- unget(c);
- newprot(s, ty, "a", &l->prot);
- goto out;
- }
-
-/*#pragma varargck type O int*/
- t = getquoted();
- if(t == nil)
- goto bad;
- s = getsym();
- if(s == S)
- goto bad;
- ty = s->type;
- while((c = getnsc()) == '*')
- ty = typ(TIND, ty);
- unget(c);
- newprot(s, ty, t, &tprot);
- goto out;
-
-bad:
- yyerror("syntax in #pragma varargck");
-
-out:
- while(getnsc() != '\n')
- ;
-}
-
-Node*
-nextarg(Node *n, Node **a)
-{
- if(n == Z) {
- *a = Z;
- return Z;
- }
- if(n->op == OLIST) {
- *a = n->left;
- return n->right;
- }
- *a = n;
- return Z;
-}
-
-void
-checkargs(Node *nn, char *s, int pos)
-{
- Node *a, *n;
- Bits flag;
- Tprot *l;
-
- if(!debug['F'])
- return;
- n = nn;
- for(;;) {
- s = strchr(s, '%');
- if(s == 0) {
- nextarg(n, &a);
- if(a != Z)
- warn(nn, "more arguments than format %T",
- a->type);
- return;
- }
- s++;
- flag = getflag(s);
- while(nstar > 0) {
- n = nextarg(n, &a);
- pos++;
- nstar--;
- if(a == Z) {
- warn(nn, "more format than arguments %s",
- lastfmt);
- return;
- }
- if(a->type == T)
- continue;
- if(!sametype(types[TINT], a->type) &&
- !sametype(types[TUINT], a->type))
- warn(nn, "format mismatch '*' in %s %T, arg %d",
- lastfmt, a->type, pos);
- }
- for(l=tprot; l; l=l->link)
- if(sametype(types[TVOID], l->type)) {
- if(beq(flag, l->flag)) {
- s++;
- goto loop;
- }
- }
-
- n = nextarg(n, &a);
- pos++;
- if(a == Z) {
- warn(nn, "more format than arguments %s",
- lastfmt);
- return;
- }
- if(a->type == 0)
- continue;
- for(l=tprot; l; l=l->link)
- if(sametype(a->type, l->type)) {
-/*print("checking %T/%ux %T/%ux\n", a->type, flag.b[0], l->type, l->flag.b[0]);*/
- if(beq(flag, l->flag))
- goto loop;
- }
- warn(nn, "format mismatch %s %T, arg %d", lastfmt, a->type, pos);
- loop:;
- }
-}
-
-void
-dpcheck(Node *n)
-{
- char *s;
- Node *a, *b;
- Tname *l;
- Tprot *tl;
- int i, j;
-
- if(n == Z)
- return;
- b = n->left;
- if(b == Z || b->op != ONAME)
- return;
- s = b->sym->name;
- for(l=tname; l; l=l->link)
- if(strcmp(s, l->name) == 0)
- break;
- if(l == 0)
- return;
-
- if(l->count > 0) {
- // fetch count, then check remaining length
- i = l->count;
- a = nil;
- b = n->right;
- while(i > 0) {
- b = nextarg(b, &a);
- i--;
- }
- if(a == Z) {
- diag(n, "can't find count arg");
- return;
- }
- if(a->op != OCONST || !typechl[a->type->etype]) {
- diag(n, "count is invalid constant");
- return;
- }
- j = a->vconst;
- i = 0;
- while(b != Z) {
- b = nextarg(b, &a);
- i++;
- }
- if(i != j)
- diag(n, "found %d argument%s after count %d", i, i == 1 ? "" : "s", j);
- }
-
- if(l->prot != nil) {
- // check that all arguments after param or count
- // are listed in type list.
- i = l->count;
- if(i == 0)
- i = l->param;
- if(i == 0)
- return;
- a = nil;
- b = n->right;
- while(i > 0) {
- b = nextarg(b, &a);
- i--;
- }
- if(a == Z) {
- diag(n, "can't find count/param arg");
- return;
- }
- while(b != Z) {
- b = nextarg(b, &a);
- for(tl=l->prot; tl; tl=tl->link)
- if(sametype(a->type, tl->type))
- break;
- if(tl == nil)
- diag(a, "invalid type %T in call to %s", a->type, s);
- }
- }
-
- if(l->param <= 0)
- return;
- i = l->param;
- a = nil;
- b = n->right;
- while(i > 0) {
- b = nextarg(b, &a);
- i--;
- }
- if(a == Z) {
- diag(n, "can't find format arg");
- return;
- }
- if(!sametype(indchar, a->type)) {
- diag(n, "format arg type %T", a->type);
- return;
- }
- if(a->op != OADDR || a->left->op != ONAME || a->left->sym != symstring) {
-/* warn(n, "format arg not constant string");*/
- return;
- }
- s = a->left->cstring;
- checkargs(b, s, l->param);
-}
-
-void
-pragpack(void)
-{
- Sym *s;
-
- packflg = 0;
- s = getsym();
- if(s) {
- packflg = atoi(s->name+1);
- if(strcmp(s->name, "on") == 0 ||
- strcmp(s->name, "yes") == 0)
- packflg = 1;
- }
- while(getnsc() != '\n')
- ;
- if(debug['f'])
- if(packflg)
- print("%4d: pack %d\n", lineno, packflg);
- else
- print("%4d: pack off\n", lineno);
-}
-
-void
-pragfpround(void)
-{
- Sym *s;
-
- fproundflg = 0;
- s = getsym();
- if(s) {
- fproundflg = atoi(s->name+1);
- if(strcmp(s->name, "on") == 0 ||
- strcmp(s->name, "yes") == 0)
- fproundflg = 1;
- }
- while(getnsc() != '\n')
- ;
- if(debug['f'])
- if(fproundflg)
- print("%4d: fproundflg %d\n", lineno, fproundflg);
- else
- print("%4d: fproundflg off\n", lineno);
-}
-
-void
-pragtextflag(void)
-{
- Sym *s;
-
- s = getsym();
- if(s == S) {
- textflag = getnsn();
- } else {
- if(s->macro) {
- macexpand(s, symb);
- }
- if(symb[0] < '0' || symb[0] > '9')
- yyerror("pragma textflag not an integer");
- textflag = atoi(symb);
- }
- while(getnsc() != '\n')
- ;
- if(debug['f'])
- print("%4d: textflag %d\n", lineno, textflag);
-}
-
-void
-pragdataflag(void)
-{
- Sym *s;
-
- s = getsym();
- if(s == S) {
- dataflag = getnsn();
- } else {
- if(s->macro) {
- macexpand(s, symb);
- }
- if(symb[0] < '0' || symb[0] > '9')
- yyerror("pragma dataflag not an integer");
- dataflag = atoi(symb);
- }
- while(getnsc() != '\n')
- ;
- if(debug['f'])
- print("%4d: dataflag %d\n", lineno, dataflag);
-}
-
-void
-pragincomplete(void)
-{
- Sym *s;
- Type *t;
- int istag, w, et;
-
- istag = 0;
- s = getsym();
- if(s == nil)
- goto out;
- et = 0;
- w = s->lexical;
- if(w == LSTRUCT)
- et = TSTRUCT;
- else if(w == LUNION)
- et = TUNION;
- if(et != 0){
- s = getsym();
- if(s == nil){
- yyerror("missing struct/union tag in pragma incomplete");
- goto out;
- }
- if(s->lexical != LNAME && s->lexical != LTYPE){
- yyerror("invalid struct/union tag: %s", s->name);
- goto out;
- }
- dotag(s, et, 0);
- istag = 1;
- }else if(strcmp(s->name, "_off_") == 0){
- debug['T'] = 0;
- goto out;
- }else if(strcmp(s->name, "_on_") == 0){
- debug['T'] = 1;
- goto out;
- }
- t = s->type;
- if(istag)
- t = s->suetag;
- if(t == T)
- yyerror("unknown type %s in pragma incomplete", s->name);
- else if(!typesu[t->etype])
- yyerror("not struct/union type in pragma incomplete: %s", s->name);
- else
- t->garb |= GINCOMPLETE;
-out:
- while(getnsc() != '\n')
- ;
- if(debug['f'])
- print("%s incomplete\n", s->name);
-}
-
-Sym*
-getimpsym(void)
-{
- int c;
- char *cp;
-
- c = getnsc();
- if(isspace(c) || c == '"') {
- unget(c);
- return S;
- }
- for(cp = symb;;) {
- if(cp <= symb+NSYMB-4)
- *cp++ = c;
- c = getc();
- if(c > 0 && !isspace(c) && c != '"')
- continue;
- unget(c);
- break;
- }
- *cp = 0;
- if(cp > symb+NSYMB-4)
- yyerror("symbol too large: %s", symb);
- return lookup();
-}
-
-static int
-more(void)
-{
- int c;
-
- do
- c = getnsc();
- while(c == ' ' || c == '\t');
- unget(c);
- return c != '\n';
-}
-
-void
-pragcgo(char *verb)
-{
- Sym *local, *remote;
- char *p;
-
- if(strcmp(verb, "cgo_dynamic_linker") == 0 || strcmp(verb, "dynlinker") == 0) {
- p = getquoted();
- if(p == nil)
- goto err1;
- fmtprint(&pragcgobuf, "cgo_dynamic_linker %q\n", p);
- goto out;
-
- err1:
- yyerror("usage: #pragma cgo_dynamic_linker \"path\"");
- goto out;
- }
-
- if(strcmp(verb, "dynexport") == 0)
- verb = "cgo_export_dynamic";
- if(strcmp(verb, "cgo_export_static") == 0 || strcmp(verb, "cgo_export_dynamic") == 0) {
- local = getimpsym();
- if(local == nil)
- goto err2;
- if(!more()) {
- fmtprint(&pragcgobuf, "%s %q\n", verb, local->name);
- goto out;
- }
- remote = getimpsym();
- if(remote == nil)
- goto err2;
- fmtprint(&pragcgobuf, "%s %q %q\n", verb, local->name, remote->name);
- goto out;
-
- err2:
- yyerror("usage: #pragma %s local [remote]", verb);
- goto out;
- }
-
- if(strcmp(verb, "cgo_import_dynamic") == 0 || strcmp(verb, "dynimport") == 0) {
- local = getimpsym();
- if(local == nil)
- goto err3;
- if(!more()) {
- fmtprint(&pragcgobuf, "cgo_import_dynamic %q\n", local->name);
- goto out;
- }
- remote = getimpsym();
- if(remote == nil)
- goto err3;
- if(!more()) {
- fmtprint(&pragcgobuf, "cgo_import_dynamic %q %q\n", local->name, remote->name);
- goto out;
- }
- p = getquoted();
- if(p == nil)
- goto err3;
- fmtprint(&pragcgobuf, "cgo_import_dynamic %q %q %q\n", local->name, remote->name, p);
- goto out;
-
- err3:
- yyerror("usage: #pragma cgo_import_dynamic local [remote [\"library\"]]");
- goto out;
- }
-
- if(strcmp(verb, "cgo_import_static") == 0) {
- local = getimpsym();
- if(local == nil)
- goto err4;
- fmtprint(&pragcgobuf, "cgo_import_static %q\n", local->name);
- goto out;
-
- err4:
- yyerror("usage: #pragma cgo_import_static local [remote]");
- goto out;
- }
-
- if(strcmp(verb, "cgo_ldflag") == 0) {
- p = getquoted();
- if(p == nil)
- goto err5;
- fmtprint(&pragcgobuf, "cgo_ldflag %q\n", p);
- goto out;
-
- err5:
- yyerror("usage: #pragma cgo_ldflag \"arg\"");
- goto out;
- }
-
-out:
- while(getnsc() != '\n')
- ;
-}
diff --git a/src/cmd/cc/funct.c b/src/cmd/cc/funct.c
deleted file mode 100644
index 92c067db8..000000000
--- a/src/cmd/cc/funct.c
+++ /dev/null
@@ -1,431 +0,0 @@
-// Inferno utils/cc/funct.c
-// http://code.google.com/p/inferno-os/source/browse/utils/cc/funct.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include <u.h>
-#include "cc.h"
-
-typedef struct Ftab Ftab;
-struct Ftab
-{
- char op;
- char* name;
- char typ;
-};
-typedef struct Gtab Gtab;
-struct Gtab
-{
- char etype;
- char* name;
-};
-
-Ftab ftabinit[OEND];
-Gtab gtabinit[NALLTYPES];
-
-int
-isfunct(Node *n)
-{
- Type *t, *t1;
- Funct *f;
- Node *l;
- Sym *s;
- int o;
-
- o = n->op;
- if(n->left == Z)
- goto no;
- t = n->left->type;
- if(t == T)
- goto no;
- f = t->funct;
-
- switch(o) {
- case OAS: // put cast on rhs
- case OASI:
- case OASADD:
- case OASAND:
- case OASASHL:
- case OASASHR:
- case OASDIV:
- case OASLDIV:
- case OASLMOD:
- case OASLMUL:
- case OASLSHR:
- case OASMOD:
- case OASMUL:
- case OASOR:
- case OASSUB:
- case OASXOR:
- if(n->right == Z)
- goto no;
- t1 = n->right->type;
- if(t1 == T)
- goto no;
- if(t1->funct == f)
- break;
-
- l = new(OXXX, Z, Z);
- *l = *n->right;
-
- n->right->left = l;
- n->right->right = Z;
- n->right->type = t;
- n->right->op = OCAST;
-
- if(!isfunct(n->right))
- prtree(n, "isfunc !");
- break;
-
- case OCAST: // t f(T) or T f(t)
- t1 = n->type;
- if(t1 == T)
- goto no;
- if(f != nil) {
- s = f->castfr[t1->etype];
- if(s == S)
- goto no;
- n->right = n->left;
- goto build;
- }
- f = t1->funct;
- if(f != nil) {
- s = f->castto[t->etype];
- if(s == S)
- goto no;
- n->right = n->left;
- goto build;
- }
- goto no;
- }
-
- if(f == nil)
- goto no;
- s = f->sym[o];
- if(s == S)
- goto no;
-
- /*
- * the answer is yes,
- * now we rewrite the node
- * and give diagnostics
- */
- switch(o) {
- default:
- diag(n, "isfunct op missing %O\n", o);
- goto bad;
-
- case OADD: // T f(T, T)
- case OAND:
- case OASHL:
- case OASHR:
- case ODIV:
- case OLDIV:
- case OLMOD:
- case OLMUL:
- case OLSHR:
- case OMOD:
- case OMUL:
- case OOR:
- case OSUB:
- case OXOR:
-
- case OEQ: // int f(T, T)
- case OGE:
- case OGT:
- case OHI:
- case OHS:
- case OLE:
- case OLO:
- case OLS:
- case OLT:
- case ONE:
- if(n->right == Z)
- goto bad;
- t1 = n->right->type;
- if(t1 == T)
- goto bad;
- if(t1->funct != f)
- goto bad;
- n->right = new(OLIST, n->left, n->right);
- break;
-
- case OAS: // structure copies done by the compiler
- case OASI:
- goto no;
-
- case OASADD: // T f(T*, T)
- case OASAND:
- case OASASHL:
- case OASASHR:
- case OASDIV:
- case OASLDIV:
- case OASLMOD:
- case OASLMUL:
- case OASLSHR:
- case OASMOD:
- case OASMUL:
- case OASOR:
- case OASSUB:
- case OASXOR:
- if(n->right == Z)
- goto bad;
- t1 = n->right->type;
- if(t1 == T)
- goto bad;
- if(t1->funct != f)
- goto bad;
- n->right = new(OLIST, new(OADDR, n->left, Z), n->right);
- break;
-
- case OPOS: // T f(T)
- case ONEG:
- case ONOT:
- case OCOM:
- n->right = n->left;
- break;
-
-
- }
-
-build:
- l = new(ONAME, Z, Z);
- l->sym = s;
- l->type = s->type;
- l->etype = s->type->etype;
- l->xoffset = s->offset;
- l->class = s->class;
- tcomo(l, 0);
-
- n->op = OFUNC;
- n->left = l;
- n->type = l->type->link;
- if(tcompat(n, T, l->type, tfunct))
- goto bad;
- if(tcoma(n->left, n->right, l->type->down, 1))
- goto bad;
- return 1;
-
-no:
- return 0;
-
-bad:
- diag(n, "can't rewrite typestr for op %O\n", o);
- prtree(n, "isfunct");
- n->type = T;
- return 1;
-}
-
-void
-dclfunct(Type *t, Sym *s)
-{
- Funct *f;
- Node *n;
- Type *f1, *f2, *f3, *f4;
- int o, i, c;
- char str[100];
-
- if(t->funct)
- return;
-
- // recognize generated tag of dorm _%d_
- if(t->tag == S)
- goto bad;
- for(i=0; c = t->tag->name[i]; i++) {
- if(c == '_') {
- if(i == 0 || t->tag->name[i+1] == 0)
- continue;
- break;
- }
- if(c < '0' || c > '9')
- break;
- }
- if(c == 0)
- goto bad;
-
- f = alloc(sizeof(*f));
- for(o=0; o<nelem(f->sym); o++)
- f->sym[o] = S;
-
- t->funct = f;
-
- f1 = typ(TFUNC, t);
- f1->down = copytyp(t);
- f1->down->down = t;
-
- f2 = typ(TFUNC, types[TINT]);
- f2->down = copytyp(t);
- f2->down->down = t;
-
- f3 = typ(TFUNC, t);
- f3->down = typ(TIND, t);
- f3->down->down = t;
-
- f4 = typ(TFUNC, t);
- f4->down = t;
-
- for(i=0;; i++) {
- o = ftabinit[i].op;
- if(o == OXXX)
- break;
- sprint(str, "%s_%s_", t->tag->name, ftabinit[i].name);
- n = new(ONAME, Z, Z);
- n->sym = slookup(str);
- f->sym[o] = n->sym;
- switch(ftabinit[i].typ) {
- default:
- diag(Z, "dclfunct op missing %d\n", ftabinit[i].typ);
- break;
-
- case 1: // T f(T,T) +
- dodecl(xdecl, CEXTERN, f1, n);
- break;
-
- case 2: // int f(T,T) ==
- dodecl(xdecl, CEXTERN, f2, n);
- break;
-
- case 3: // void f(T*,T) +=
- dodecl(xdecl, CEXTERN, f3, n);
- break;
-
- case 4: // T f(T) ~
- dodecl(xdecl, CEXTERN, f4, n);
- break;
- }
- }
- for(i=0;; i++) {
- o = gtabinit[i].etype;
- if(o == TXXX)
- break;
-
- /*
- * OCAST types T1 _T2_T1_(T2)
- */
- sprint(str, "_%s%s_", gtabinit[i].name, t->tag->name);
- n = new(ONAME, Z, Z);
- n->sym = slookup(str);
- f->castto[o] = n->sym;
-
- f1 = typ(TFUNC, t);
- f1->down = types[o];
- dodecl(xdecl, CEXTERN, f1, n);
-
- sprint(str, "%s_%s_", t->tag->name, gtabinit[i].name);
- n = new(ONAME, Z, Z);
- n->sym = slookup(str);
- f->castfr[o] = n->sym;
-
- f1 = typ(TFUNC, types[o]);
- f1->down = t;
- dodecl(xdecl, CEXTERN, f1, n);
- }
- return;
-bad:
- diag(Z, "dclfunct bad %T %s\n", t, s->name);
-}
-
-Gtab gtabinit[NALLTYPES] =
-{
- TCHAR, "c",
- TUCHAR, "uc",
- TSHORT, "h",
- TUSHORT, "uh",
- TINT, "i",
- TUINT, "ui",
- TLONG, "l",
- TULONG, "ul",
- TVLONG, "v",
- TUVLONG, "uv",
- TFLOAT, "f",
- TDOUBLE, "d",
- TXXX
-};
-
-Ftab ftabinit[OEND] =
-{
- OADD, "add", 1,
- OAND, "and", 1,
- OASHL, "ashl", 1,
- OASHR, "ashr", 1,
- ODIV, "div", 1,
- OLDIV, "ldiv", 1,
- OLMOD, "lmod", 1,
- OLMUL, "lmul", 1,
- OLSHR, "lshr", 1,
- OMOD, "mod", 1,
- OMUL, "mul", 1,
- OOR, "or", 1,
- OSUB, "sub", 1,
- OXOR, "xor", 1,
-
- OEQ, "eq", 2,
- OGE, "ge", 2,
- OGT, "gt", 2,
- OHI, "hi", 2,
- OHS, "hs", 2,
- OLE, "le", 2,
- OLO, "lo", 2,
- OLS, "ls", 2,
- OLT, "lt", 2,
- ONE, "ne", 2,
-
- OASADD, "asadd", 3,
- OASAND, "asand", 3,
- OASASHL, "asashl", 3,
- OASASHR, "asashr", 3,
- OASDIV, "asdiv", 3,
- OASLDIV, "asldiv", 3,
- OASLMOD, "aslmod", 3,
- OASLMUL, "aslmul", 3,
- OASLSHR, "aslshr", 3,
- OASMOD, "asmod", 3,
- OASMUL, "asmul", 3,
- OASOR, "asor", 3,
- OASSUB, "assub", 3,
- OASXOR, "asxor", 3,
-
- OPOS, "pos", 4,
- ONEG, "neg", 4,
- OCOM, "com", 4,
- ONOT, "not", 4,
-
-// OPOSTDEC,
-// OPOSTINC,
-// OPREDEC,
-// OPREINC,
-
- OXXX,
-};
-
-// Node* nodtestv;
-
-// Node* nodvpp;
-// Node* nodppv;
-// Node* nodvmm;
-// Node* nodmmv;
diff --git a/src/cmd/cc/godefs.c b/src/cmd/cc/godefs.c
deleted file mode 100644
index d9f67f0ae..000000000
--- a/src/cmd/cc/godefs.c
+++ /dev/null
@@ -1,367 +0,0 @@
-// cmd/cc/godefs.cc
-//
-// derived from pickle.cc which itself was derived from acid.cc.
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-// Portions Copyright © 2009-2011 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include <u.h>
-#include "cc.h"
-
-static int upper;
-
-static char *kwd[] =
-{
- "_bool",
- "_break",
- "_byte",
- "_case",
- "_chan",
- "_complex128",
- "_complex64",
- "_const",
- "_continue",
- "_default",
- "_defer",
- "_else",
- "_fallthrough",
- "_false",
- "_float32",
- "_float64",
- "_for",
- "_func",
- "_go",
- "_goto",
- "_if",
- "_import",
- "_int",
- "_int16",
- "_int32",
- "_int64",
- "_int8",
- "_interface",
- "_intptr",
- "_map",
- "_package",
- "_panic",
- "_range",
- "_return",
- "_select",
- "_string",
- "_struct",
- "_switch",
- "_true",
- "_type",
- "_uint",
- "_uint16",
- "_uint32",
- "_uint64",
- "_uint8",
- "_uintptr",
- "_var",
-};
-
-static char*
-pmap(char *s)
-{
- int i, bot, top, mid;
-
- bot = -1;
- top = nelem(kwd);
- while(top - bot > 1){
- mid = (bot + top) / 2;
- i = strcmp(kwd[mid]+1, s);
- if(i == 0)
- return kwd[mid];
- if(i < 0)
- bot = mid;
- else
- top = mid;
- }
-
- return s;
-}
-
-
-int
-Uconv(Fmt *fp)
-{
- char str[STRINGSZ+1];
- char *s, *n;
- int i;
-
- str[0] = 0;
- s = va_arg(fp->args, char*);
-
- // strip package name
- n = strrchr(s, '.');
- if(n != nil)
- s = n + 1;
-
- if(s && *s) {
- if(upper)
- str[0] = toupper((uchar)*s);
- else
- str[0] = tolower((uchar)*s);
- for(i = 1; i < STRINGSZ && s[i] != 0; i++)
- str[i] = tolower((uchar)s[i]);
- str[i] = 0;
- }
-
- return fmtstrcpy(fp, pmap(str));
-}
-
-
-static Sym*
-findsue(Type *t)
-{
- int h;
- Sym *s;
-
- if(t != T)
- for(h=0; h<nelem(hash); h++)
- for(s = hash[h]; s != S; s = s->link)
- if(s->suetag && s->suetag->link == t)
- return s;
- return 0;
-}
-
-static void
-printtypename(Type *t)
-{
- Sym *s;
- int w;
- char *n;
-
- for( ; t != nil; t = t->link) {
- switch(t->etype) {
- case TIND:
- // Special handling of *void.
- if(t->link != nil && t->link->etype==TVOID) {
- Bprint(&outbuf, "unsafe.Pointer");
- return;
- }
- // *func == func
- if(t->link != nil && t->link->etype==TFUNC)
- continue;
- Bprint(&outbuf, "*");
- continue;
- case TARRAY:
- w = t->width;
- if(t->link && t->link->width)
- w /= t->link->width;
- Bprint(&outbuf, "[%d]", w);
- continue;
- }
- break;
- }
-
- if(t == nil) {
- Bprint(&outbuf, "bad // should not happen");
- return;
- }
-
- switch(t->etype) {
- case TINT:
- case TUINT:
- case TCHAR:
- case TUCHAR:
- case TSHORT:
- case TUSHORT:
- case TLONG:
- case TULONG:
- case TVLONG:
- case TUVLONG:
- case TFLOAT:
- case TDOUBLE:
- // All names used in the runtime code should be typedefs.
- if(t->tag != nil) {
- if(strcmp(t->tag->name, "intgo") == 0)
- Bprint(&outbuf, "int");
- else if(strcmp(t->tag->name, "uintgo") == 0)
- Bprint(&outbuf, "uint");
- else
- Bprint(&outbuf, "%s", t->tag->name);
- } else
- Bprint(&outbuf, "C.%T", t);
- break;
- case TUNION:
- case TSTRUCT:
- s = findsue(t->link);
- n = "bad";
- if(s != S)
- n = s->name;
- else if(t->tag)
- n = t->tag->name;
- if(strcmp(n, "String") == 0)
- Bprint(&outbuf, "string");
- else if(strcmp(n, "Slice") == 0)
- Bprint(&outbuf, "[]byte");
- else if(strcmp(n, "Eface") == 0)
- Bprint(&outbuf, "interface{}");
- else
- Bprint(&outbuf, "%U", n);
- break;
- case TFUNC:
- // There's no equivalent to a C function in the Go world.
- Bprint(&outbuf, "unsafe.Pointer");
- break;
- case TDOT:
- Bprint(&outbuf, "...interface{}");
- break;
- default:
- Bprint(&outbuf, " weird<%T>", t);
- }
-}
-
-static int
-dontrun(void)
-{
- Io *i;
- int n;
-
- if(!debug['q'] && !debug['Q'])
- return 1;
- if(debug['q'] + debug['Q'] > 1) {
- n = 0;
- for(i=iostack; i; i=i->link)
- n++;
- if(n > 1)
- return 1;
- }
-
- upper = debug['Q'];
- return 0;
-}
-
-void
-godeftype(Type *t)
-{
- Sym *s;
- Type *l;
- int gotone;
-
- if(dontrun())
- return;
-
- switch(t->etype) {
- case TUNION:
- case TSTRUCT:
- s = findsue(t->link);
- if(s == S) {
- Bprint(&outbuf, "/* can't find %T */\n\n", t);
- return;
- }
-
- gotone = 0; // for unions, take first member of size equal to union
- Bprint(&outbuf, "type %U struct {\n", s->name);
- for(l = t->link; l != T; l = l->down) {
- Bprint(&outbuf, "\t");
- if(t->etype == TUNION) {
- if(!gotone && l->width == t->width)
- gotone = 1;
- else
- Bprint(&outbuf, "// (union)\t");
- }
- if(l->sym != nil) // not anonymous field
- Bprint(&outbuf, "%U\t", l->sym->name);
- printtypename(l);
- Bprint(&outbuf, "\n");
- }
- Bprint(&outbuf, "}\n\n");
- break;
-
- default:
- Bprint(&outbuf, "/* %T */\n\n", t);
- break;
- }
-}
-
-void
-godefvar(Sym *s)
-{
- Type *t, *t1;
- char n;
-
- if(dontrun())
- return;
-
- t = s->type;
- if(t == nil)
- return;
-
- switch(t->etype) {
- case TENUM:
- if(!typefd[t->etype])
- Bprint(&outbuf, "const %s = %lld\n", s->name, s->vconst);
- else
- Bprint(&outbuf, "const %s = %f\n;", s->name, s->fconst);
- break;
-
- case TFUNC:
- Bprint(&outbuf, "func %U(", s->name);
- n = 'a';
- for(t1 = t->down; t1 != T; t1 = t1->down) {
- if(t1->etype == TVOID)
- break;
- if(t1 != t->down)
- Bprint(&outbuf, ", ");
- Bprint(&outbuf, "%c ", n++);
- printtypename(t1);
- }
- Bprint(&outbuf, ")");
- if(t->link && t->link->etype != TVOID) {
- Bprint(&outbuf, " ");
- printtypename(t->link);
- }
- Bprint(&outbuf, "\n");
- break;
-
- default:
- switch(s->class) {
- case CTYPEDEF:
- if(!typesu[t->etype]) {
- Bprint(&outbuf, "// type %U\t", s->name);
- printtypename(t);
- Bprint(&outbuf, "\n");
- }
- break;
- case CSTATIC:
- case CEXTERN:
- case CGLOBL:
- if(strchr(s->name, '$') != nil)
- break;
- if(strncmp(s->name, "go.weak.", 8) == 0)
- break;
- Bprint(&outbuf, "var %U\t", s->name);
- printtypename(t);
- Bprint(&outbuf, "\n");
- break;
- }
- break;
- }
-}
diff --git a/src/cmd/cc/lex.c b/src/cmd/cc/lex.c
deleted file mode 100644
index 7c9f718c0..000000000
--- a/src/cmd/cc/lex.c
+++ /dev/null
@@ -1,1593 +0,0 @@
-// Inferno utils/cc/lex.c
-// http://code.google.com/p/inferno-os/source/browse/utils/cc/lex.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include <u.h>
-#include "cc.h"
-#include "y.tab.h"
-#include "../ld/textflag.h"
-
-#ifndef CPP
-#define CPP "cpp"
-#endif
-
-int
-systemtype(int sys)
-{
-#ifdef _WIN32
- return sys&Windows;
-#else
- return sys&Plan9;
-#endif
-}
-
-int
-pathchar(void)
-{
- return '/';
-}
-
-/*
- * known debug flags
- * -a acid declaration output
- * -A !B
- * -B non ANSI
- * -d print declarations
- * -D name define
- * -F format specification check
- * -G print pgen stuff
- * -g print cgen trees
- * -i print initialization
- * -I path include
- * -l generate little-endian code
- * -L print every NAME symbol
- * -M constant multiplication
- * -m print add/sub/mul trees
- * -n print acid or godefs to file (%.c=%.acid) (with -a or -aa)
- * -o file output file
- * -p use standard cpp ANSI preprocessor (not on windows)
- * -p something with peepholes
- * -q print equivalent Go code for variables and types (lower-case identifiers)
- * -Q print equivalent Go code for variables and types (upper-case identifiers)
- * -r print registerization
- * -s print structure offsets (with -a or -aa)
- * -S print assembly
- * -t print type trees
- * -V enable void* conversion warnings
- * -v verbose printing
- * -w print warnings
- * -X abort on error
- * -. Inhibit search for includes in source directory
- */
-
-void
-usage(void)
-{
- print("usage: %cc [options] file.c...\n", thechar);
- flagprint(1);
- errorexit();
-}
-
-void
-dospim(void)
-{
- thechar = '0';
- thestring = "spim";
-}
-
-char **defs;
-int ndef;
-
-void
-dodef(char *p)
-{
- if(ndef%8 == 0)
- defs = allocn(defs, ndef*sizeof(char *),
- 8*sizeof(char *));
- defs[ndef++] = p;
- dodefine(p);
-}
-
-void
-main(int argc, char *argv[])
-{
- int c;
- char *p;
-
- // Allow GOARCH=thestring or GOARCH=thestringsuffix,
- // but not other values.
- p = getgoarch();
- if(strncmp(p, thestring, strlen(thestring)) != 0)
- sysfatal("cannot use %cc with GOARCH=%s", thechar, p);
- if(strcmp(p, "amd64p32") == 0) // must be before cinit
- ewidth[TIND] = 4;
-
- nacl = strcmp(getgoos(), "nacl") == 0;
- if(nacl)
- flag_largemodel = 1;
-
- quotefmtinstall(); // before cinit, which overrides %Q
-
- linkarchinit();
- ctxt = linknew(thelinkarch);
- ctxt->diag = yyerror;
- ctxt->bso = &bstdout;
- Binit(&bstdout, 1, OWRITE);
-
- ensuresymb(NSYMB);
- memset(debug, 0, sizeof(debug));
- tinit();
- cinit();
- ginit();
- arginit();
-
- fmtstrinit(&pragcgobuf);
-
- tufield = simplet((1L<<tfield->etype) | BUNSIGNED);
- ndef = 0;
- defs = nil;
- outfile = 0;
- setinclude(".");
-
- flagcount("+", "pass -+ to preprocessor", &debug['+']);
- flagcount(".", "pass -. to preprocessor", &debug['.']);
- flagcount("<", "debug shift", &debug['<']);
- flagcount("A", "debug alignment", &debug['A']);
- flagcount("B", "allow pre-ANSI code", &debug['B']);
- if(thechar == '5')
- flagcount("C", "debug constant propagation", &debug['C']);
- flagfn1("D", "name[=value]: add #define", dodef);
- flagcount("F", "enable print format checks", &debug['F']);
- if(thechar == '5')
- flagcount("H", "debug shift propagation", &debug['H']);
- flagfn1("I", "dir: add dir to include path", setinclude);
- flagcount("L", "debug lexer", &debug['L']);
- flagcount("M", "debug move generation", &debug['M']);
- flagcount("N", "disable optimizations", &debug['N']);
- flagcount("P", "debug peephole optimizer", &debug['P']);
- flagcount("Q", "print exported Go definitions", &debug['Q']);
- flagcount("R", "debug register optimizer", &debug['R']);
- flagcount("S", "print assembly", &debug['S']);
- flagcount("T", "enable type signatures", &debug['T']);
- flagcount("V", "enable pointer type checks", &debug['V']);
- flagcount("W", "debug switch generation", &debug['W']);
- flagcount("X", "abort on error", &debug['X']);
- flagcount("Y", "debug index generation", &debug['Y']);
- flagcount("Z", "skip code generation", &debug['Z']);
- flagcount("a", "print acid definitions", &debug['a']);
- flagcount("c", "debug constant evaluation", &debug['c']);
- flagcount("d", "debug declarations", &debug['d']);
- flagcount("e", "debug macro expansion", &debug['e']);
- flagcount("f", "debug pragmas", &debug['f']);
- flagcount("g", "debug code generation", &debug['g']);
- flagcount("i", "debug initialization", &debug['i']);
- if(thechar == 'v')
- flagfn0("l", "little-endian mips mode", dospim);
- flagcount("m", "debug multiplication", &debug['m']);
- flagcount("n", "print acid/Go to file, not stdout", &debug['n']);
- flagstr("o", "file: set output file", &outfile);
- flagcount("p", "invoke C preprocessor", &debug['p']);
- flagcount("q", "print Go definitions", &debug['q']);
- flagcount("s", "print #define assembly offsets", &debug['s']);
- flagcount("t", "debug code generation", &debug['t']);
- flagstr("trimpath", "prefix: remove prefix from recorded source file paths", &ctxt->trimpath);
- flagcount("w", "enable warnings", &debug['w']);
- flagcount("v", "increase debug verbosity", &debug['v']);
- if(thechar == '6')
- flagcount("largemodel", "generate code that assumes a large memory model", &flag_largemodel);
-
- flagparse(&argc, &argv, usage);
- ctxt->debugasm = debug['S'];
- ctxt->debugvlog = debug['v'];
-
- if(argc < 1 && outfile == 0)
- usage();
-
- if(argc > 1){
- print("can't compile multiple files\n");
- errorexit();
- }
-
- if(argc == 0)
- c = compile("stdin", defs, ndef);
- else
- c = compile(argv[0], defs, ndef);
-
- Bflush(&bstdout);
- if(c)
- errorexit();
- exits(0);
-}
-
-int
-compile(char *file, char **defs, int ndef)
-{
- char *ofile;
- char *p, **av, opt[256];
- int i, c, fd[2];
- static int first = 1;
-
- ofile = alloc(strlen(file)+10);
- strcpy(ofile, file);
- p = utfrrune(ofile, pathchar());
- if(p) {
- *p++ = 0;
- if(!debug['.'])
- include[0] = strdup(ofile);
- } else
- p = ofile;
-
- if(outfile == 0) {
- outfile = p;
- if(outfile) {
- if(p = utfrrune(outfile, '.'))
- if(p[1] == 'c' && p[2] == 0)
- p[0] = 0;
- p = utfrune(outfile, 0);
- if(debug['a'] && debug['n'])
- strcat(p, ".acid");
- else if((debug['q'] || debug['Q']) && debug['n'])
- strcat(p, ".go");
- else {
- p[0] = '.';
- p[1] = thechar;
- p[2] = 0;
- }
- } else
- outfile = "/dev/null";
- }
-
- if (first)
- Binit(&diagbuf, 1, OWRITE);
- /*
- * if we're writing acid to standard output, don't keep scratching
- * outbuf.
- */
- if((debug['a'] || debug['q'] || debug['Q']) && !debug['n']) {
- if (first) {
- outfile = 0;
- Binit(&outbuf, dup(1, -1), OWRITE);
- dup(2, 1);
- }
- } else {
- c = create(outfile, OWRITE, 0664);
- if(c < 0) {
- diag(Z, "cannot open %s - %r", outfile);
- outfile = 0;
- errorexit();
- }
- Binit(&outbuf, c, OWRITE);
- outfile = strdup(outfile);
- }
- newio();
- first = 0;
-
- /* Use an ANSI preprocessor */
- if(debug['p']) {
- if(systemtype(Windows)) {
- diag(Z, "-p option not supported on windows");
- errorexit();
- }
- if(access(file, AREAD) < 0) {
- diag(Z, "%s does not exist", file);
- errorexit();
- }
- if(pipe(fd) < 0) {
- diag(Z, "pipe failed");
- errorexit();
- }
- switch(fork()) {
- case -1:
- diag(Z, "fork failed");
- errorexit();
- case 0:
- close(fd[0]);
- dup(fd[1], 1);
- close(fd[1]);
- av = alloc((ndef+ninclude+5)*sizeof(char *));
- av[0] = CPP;
- i = 1;
- if(debug['.']){
- sprint(opt, "-.");
- av[i++] = strdup(opt);
- }
- if(debug['+']) {
- sprint(opt, "-+");
- av[i++] = strdup(opt);
- }
- for(c = 0; c < ndef; c++)
- av[i++] = smprint("-D%s", defs[c]);
- for(c = 0; c < ninclude; c++)
- av[i++] = smprint("-I%s", include[c]);
- if(strcmp(file, "stdin") != 0)
- av[i++] = file;
- av[i] = 0;
- if(debug['p'] > 1) {
- for(c = 0; c < i; c++)
- fprint(2, "%s ", av[c]);
- fprint(2, "\n");
- }
- exec(av[0], av);
- fprint(2, "can't exec C preprocessor %s: %r\n", CPP);
- errorexit();
- default:
- close(fd[1]);
- newfile(file, fd[0]);
- break;
- }
- } else {
- if(strcmp(file, "stdin") == 0)
- newfile(file, 0);
- else
- newfile(file, -1);
- }
- yyparse();
- if(!debug['a'] && !debug['q'] && !debug['Q'])
- gclean();
- return nerrors;
-}
-
-void
-errorexit(void)
-{
- Bflush(&bstdout);
- if(outfile)
- remove(outfile);
- exits("error");
-}
-
-void
-pushio(void)
-{
- Io *i;
-
- i = iostack;
- if(i == I) {
- yyerror("botch in pushio");
- errorexit();
- }
- i->p = fi.p;
- i->c = fi.c;
-}
-
-void
-newio(void)
-{
- Io *i;
- static int pushdepth = 0;
-
- i = iofree;
- if(i == I) {
- pushdepth++;
- if(pushdepth > 1000) {
- yyerror("macro/io expansion too deep");
- errorexit();
- }
- i = alloc(sizeof(*i));
- } else
- iofree = i->link;
- i->c = 0;
- i->f = -1;
- ionext = i;
-}
-
-void
-newfile(char *s, int f)
-{
- Io *i;
-
- if(debug['e'])
- print("%L: %s\n", lineno, s);
-
- i = ionext;
- i->link = iostack;
- iostack = i;
- i->f = f;
- if(f < 0)
- i->f = open(s, 0);
- if(i->f < 0) {
- yyerror("%cc: %r: %s", thechar, s);
- errorexit();
- }
- fi.c = 0;
- linklinehist(ctxt, lineno, s, 0);
-}
-
-Sym*
-slookup(char *s)
-{
- ensuresymb(strlen(s));
- strcpy(symb, s);
- return lookup();
-}
-
-Sym*
-lookup(void)
-{
- Sym *s;
- uint32 h;
- char *p;
- int c, n;
- char *r, *w;
-
- if((uchar)symb[0] == 0xc2 && (uchar)symb[1] == 0xb7) {
- // turn leading · into ""·
- h = strlen(symb);
- ensuresymb(h+2);
- memmove(symb+2, symb, h+1);
- symb[0] = '"';
- symb[1] = '"';
- }
-
- for(r=w=symb; *r; r++) {
- // turn · (U+00B7) into .
- // turn ∕ (U+2215) into /
- if((uchar)*r == 0xc2 && (uchar)*(r+1) == 0xb7) {
- *w++ = '.';
- r++;
- }else if((uchar)*r == 0xe2 && (uchar)*(r+1) == 0x88 && (uchar)*(r+2) == 0x95) {
- *w++ = '/';
- r++;
- r++;
- }else
- *w++ = *r;
- }
- *w = '\0';
-
- h = 0;
- for(p=symb; *p;) {
- h = h * 3;
- h += *p++;
- }
- n = (p - symb) + 1;
- h &= 0xffffff;
- h %= NHASH;
- c = symb[0];
- for(s = hash[h]; s != S; s = s->link) {
- if(s->name[0] != c)
- continue;
- if(strcmp(s->name, symb) == 0)
- return s;
- }
- s = alloc(sizeof(*s));
- s->name = alloc(n);
- memmove(s->name, symb, n);
- s->link = hash[h];
- hash[h] = s;
- syminit(s);
-
- return s;
-}
-
-void
-syminit(Sym *s)
-{
- s->lexical = LNAME;
- s->block = 0;
- s->offset = 0;
- s->type = T;
- s->suetag = T;
- s->class = CXXX;
- s->aused = 0;
- s->sig = SIGNONE;
-}
-
-#define EOF (-1)
-#define IGN (-2)
-#define ESC (1<<20)
-#define GETC() ((--fi.c < 0)? filbuf(): (*fi.p++ & 0xff))
-
-enum
-{
- Numdec = 1<<0,
- Numlong = 1<<1,
- Numuns = 1<<2,
- Numvlong = 1<<3,
- Numflt = 1<<4,
-};
-
-int32
-yylex(void)
-{
- vlong vv;
- int32 c, c1, t;
- char *cp;
- Rune rune;
- Sym *s;
-
- if(peekc != IGN) {
- c = peekc;
- peekc = IGN;
- goto l1;
- }
-l0:
- c = GETC();
-
-l1:
- if(c >= Runeself) {
- /*
- * extension --
- * all multibyte runes are alpha
- */
- cp = symb;
- goto talph;
- }
- if(isspace(c)) {
- if(c == '\n')
- lineno++;
- goto l0;
- }
- if(isalpha(c)) {
- cp = symb;
- if(c != 'L')
- goto talph;
- *cp++ = c;
- c = GETC();
- if(c == '\'') {
- /* L'x' */
- c = escchar('\'', 1, 0);
- if(c == EOF)
- c = '\'';
- c1 = escchar('\'', 1, 0);
- if(c1 != EOF) {
- yyerror("missing '");
- peekc = c1;
- }
- yylval.vval = convvtox(c, TRUNE);
- return LUCONST;
- }
- if(c == '"') {
- goto caselq;
- }
- goto talph;
- }
- if(isdigit(c))
- goto tnum;
- switch(c)
- {
-
- case EOF:
- peekc = EOF;
- return -1;
-
- case '_':
- cp = symb;
- goto talph;
-
- case '#':
- domacro();
- goto l0;
-
- case '.':
- c1 = GETC();
- if(isdigit(c1)) {
- cp = symb;
- *cp++ = c;
- c = c1;
- c1 = 0;
- goto casedot;
- }
- break;
-
- case '"':
- strcpy(symb, "\"<string>\"");
- cp = alloc(0);
- c1 = 0;
-
- /* "..." */
- for(;;) {
- c = escchar('"', 0, 1);
- if(c == EOF)
- break;
- if(c & ESC) {
- cp = allocn(cp, c1, 1);
- cp[c1++] = c;
- } else {
- rune = c;
- c = runelen(rune);
- cp = allocn(cp, c1, c);
- runetochar(cp+c1, &rune);
- c1 += c;
- }
- }
- yylval.sval.l = c1;
- do {
- cp = allocn(cp, c1, 1);
- cp[c1++] = 0;
- } while(c1 & MAXALIGN);
- yylval.sval.s = cp;
- return LSTRING;
-
- caselq:
- /* L"..." */
- strcpy(symb, "\"L<string>\"");
- cp = alloc(0);
- c1 = 0;
- for(;;) {
- c = escchar('"', 1, 0);
- if(c == EOF)
- break;
- cp = allocn(cp, c1, sizeof(TRune));
- *(TRune*)(cp + c1) = c;
- c1 += sizeof(TRune);
- }
- yylval.sval.l = c1;
- do {
- cp = allocn(cp, c1, sizeof(TRune));
- *(TRune*)(cp + c1) = 0;
- c1 += sizeof(TRune);
- } while(c1 & MAXALIGN);
- yylval.sval.s = cp;
- return LLSTRING;
-
- case '\'':
- /* '.' */
- c = escchar('\'', 0, 0);
- if(c == EOF)
- c = '\'';
- c1 = escchar('\'', 0, 0);
- if(c1 != EOF) {
- yyerror("missing '");
- peekc = c1;
- }
- vv = c;
- yylval.vval = convvtox(vv, TUCHAR);
- if(yylval.vval != vv)
- yyerror("overflow in character constant: 0x%x", c);
- else
- if(c & 0x80){
- nearln = lineno;
- warn(Z, "sign-extended character constant");
- }
- yylval.vval = convvtox(vv, TCHAR);
- return LCONST;
-
- case '/':
- c1 = GETC();
- if(c1 == '*') {
- for(;;) {
- c = getr();
- while(c == '*') {
- c = getr();
- if(c == '/')
- goto l0;
- }
- if(c == EOF) {
- yyerror("eof in comment");
- errorexit();
- }
- }
- }
- if(c1 == '/') {
- for(;;) {
- c = getr();
- if(c == '\n')
- goto l0;
- if(c == EOF) {
- yyerror("eof in comment");
- errorexit();
- }
- }
- }
- if(c1 == '=')
- return LDVE;
- break;
-
- case '*':
- c1 = GETC();
- if(c1 == '=')
- return LMLE;
- break;
-
- case '%':
- c1 = GETC();
- if(c1 == '=')
- return LMDE;
- break;
-
- case '+':
- c1 = GETC();
- if(c1 == '+')
- return LPP;
- if(c1 == '=')
- return LPE;
- break;
-
- case '-':
- c1 = GETC();
- if(c1 == '-')
- return LMM;
- if(c1 == '=')
- return LME;
- if(c1 == '>')
- return LMG;
- break;
-
- case '>':
- c1 = GETC();
- if(c1 == '>') {
- c = LRSH;
- c1 = GETC();
- if(c1 == '=')
- return LRSHE;
- break;
- }
- if(c1 == '=')
- return LGE;
- break;
-
- case '<':
- c1 = GETC();
- if(c1 == '<') {
- c = LLSH;
- c1 = GETC();
- if(c1 == '=')
- return LLSHE;
- break;
- }
- if(c1 == '=')
- return LLE;
- break;
-
- case '=':
- c1 = GETC();
- if(c1 == '=')
- return LEQ;
- break;
-
- case '!':
- c1 = GETC();
- if(c1 == '=')
- return LNE;
- break;
-
- case '&':
- c1 = GETC();
- if(c1 == '&')
- return LANDAND;
- if(c1 == '=')
- return LANDE;
- break;
-
- case '|':
- c1 = GETC();
- if(c1 == '|')
- return LOROR;
- if(c1 == '=')
- return LORE;
- break;
-
- case '^':
- c1 = GETC();
- if(c1 == '=')
- return LXORE;
- break;
-
- default:
- return c;
- }
- peekc = c1;
- return c;
-
-talph:
- /*
- * cp is set to symb and some
- * prefix has been stored
- */
- for(;;) {
- if(c >= Runeself) {
- for(c1=0;;) {
- cp[c1++] = c;
- if(fullrune(cp, c1))
- break;
- c = GETC();
- }
- cp += c1;
- c = GETC();
- continue;
- }
- if(!isalnum(c) && c != '_')
- break;
- *cp++ = c;
- c = GETC();
- }
- *cp = 0;
- if(debug['L'])
- print("%L: %s\n", lineno, symb);
- peekc = c;
- s = lookup();
- if(s->macro) {
- newio();
- cp = ionext->b;
- macexpand(s, cp);
- pushio();
- ionext->link = iostack;
- iostack = ionext;
- fi.p = cp;
- fi.c = strlen(cp);
- if(peekc != IGN) {
- cp[fi.c++] = peekc;
- cp[fi.c] = 0;
- peekc = IGN;
- }
- goto l0;
- }
- yylval.sym = s;
- if(s->class == CTYPEDEF || s->class == CTYPESTR)
- return LTYPE;
- return s->lexical;
-
-tnum:
- c1 = 0;
- cp = symb;
- if(c != '0') {
- c1 |= Numdec;
- for(;;) {
- *cp++ = c;
- c = GETC();
- if(isdigit(c))
- continue;
- goto dc;
- }
- }
- *cp++ = c;
- c = GETC();
- if(c == 'x' || c == 'X')
- for(;;) {
- *cp++ = c;
- c = GETC();
- if(isdigit(c))
- continue;
- if(c >= 'a' && c <= 'f')
- continue;
- if(c >= 'A' && c <= 'F')
- continue;
- if(cp == symb+2)
- yyerror("malformed hex constant");
- goto ncu;
- }
- if(c < '0' || c > '7')
- goto dc;
- for(;;) {
- if(c >= '0' && c <= '7') {
- *cp++ = c;
- c = GETC();
- continue;
- }
- goto ncu;
- }
-
-dc:
- if(c == '.')
- goto casedot;
- if(c == 'e' || c == 'E')
- goto casee;
-
-ncu:
- if((c == 'U' || c == 'u') && !(c1 & Numuns)) {
- c = GETC();
- c1 |= Numuns;
- goto ncu;
- }
- if((c == 'L' || c == 'l') && !(c1 & Numvlong)) {
- c = GETC();
- if(c1 & Numlong)
- c1 |= Numvlong;
- c1 |= Numlong;
- goto ncu;
- }
- *cp = 0;
- peekc = c;
- if(mpatov(symb, &yylval.vval))
- yyerror("overflow in constant");
-
- vv = yylval.vval;
- if(c1 & Numvlong) {
- if((c1 & Numuns) || convvtox(vv, TVLONG) < 0) {
- c = LUVLCONST;
- t = TUVLONG;
- goto nret;
- }
- c = LVLCONST;
- t = TVLONG;
- goto nret;
- }
- if(c1 & Numlong) {
- if((c1 & Numuns) || convvtox(vv, TLONG) < 0) {
- c = LULCONST;
- t = TULONG;
- goto nret;
- }
- c = LLCONST;
- t = TLONG;
- goto nret;
- }
- if((c1 & Numuns) || convvtox(vv, TINT) < 0) {
- c = LUCONST;
- t = TUINT;
- goto nret;
- }
- c = LCONST;
- t = TINT;
- goto nret;
-
-nret:
- yylval.vval = convvtox(vv, t);
- if(yylval.vval != vv){
- nearln = lineno;
- warn(Z, "truncated constant: %T %s", types[t], symb);
- }
- return c;
-
-casedot:
- for(;;) {
- *cp++ = c;
- c = GETC();
- if(!isdigit(c))
- break;
- }
- if(c != 'e' && c != 'E')
- goto caseout;
-
-casee:
- *cp++ = 'e';
- c = GETC();
- if(c == '+' || c == '-') {
- *cp++ = c;
- c = GETC();
- }
- if(!isdigit(c))
- yyerror("malformed fp constant exponent");
- while(isdigit(c)) {
- *cp++ = c;
- c = GETC();
- }
-
-caseout:
- if(c == 'L' || c == 'l') {
- c = GETC();
- c1 |= Numlong;
- } else
- if(c == 'F' || c == 'f') {
- c = GETC();
- c1 |= Numflt;
- }
- *cp = 0;
- peekc = c;
- yylval.dval = strtod(symb, nil);
- if(isInf(yylval.dval, 1) || isInf(yylval.dval, -1)) {
- yyerror("overflow in float constant");
- yylval.dval = 0;
- }
- if(c1 & Numflt)
- return LFCONST;
- return LDCONST;
-}
-
-/*
- * convert a string, s, to vlong in *v
- * return conversion overflow.
- * required syntax is [0[x]]d*
- */
-int
-mpatov(char *s, vlong *v)
-{
- vlong n, nn;
- int c;
-
- n = 0;
- c = *s;
- if(c == '0')
- goto oct;
- while(c = *s++) {
- if(c >= '0' && c <= '9')
- nn = n*10 + c-'0';
- else
- goto bad;
- if(n < 0 && nn >= 0)
- goto bad;
- n = nn;
- }
- goto out;
-
-oct:
- s++;
- c = *s;
- if(c == 'x' || c == 'X')
- goto hex;
- while(c = *s++) {
- if(c >= '0' || c <= '7')
- nn = n*8 + c-'0';
- else
- goto bad;
- if(n < 0 && nn >= 0)
- goto bad;
- n = nn;
- }
- goto out;
-
-hex:
- s++;
- while(c = *s++) {
- if(c >= '0' && c <= '9')
- c += 0-'0';
- else
- if(c >= 'a' && c <= 'f')
- c += 10-'a';
- else
- if(c >= 'A' && c <= 'F')
- c += 10-'A';
- else
- goto bad;
- nn = (uvlong)n*16 + c;
- if(n < 0 && nn >= 0)
- goto bad;
- n = nn;
- }
-out:
- *v = n;
- return 0;
-
-bad:
- *v = ~0;
- return 1;
-}
-
-int
-getc(void)
-{
- int c;
-
- if(peekc != IGN) {
- c = peekc;
- peekc = IGN;
- } else
- c = GETC();
- if(c == '\n')
- lineno++;
- if(c == EOF) {
- yyerror("End of file");
- errorexit();
- }
- return c;
-}
-
-int32
-getr(void)
-{
- int c, i;
- char str[UTFmax+1];
- Rune rune;
-
-
- c = getc();
- if(c < Runeself)
- return c;
- i = 0;
- str[i++] = c;
-
-loop:
- c = getc();
- str[i++] = c;
- if(!fullrune(str, i))
- goto loop;
- c = chartorune(&rune, str);
- if(rune == Runeerror && c == 1) {
- nearln = lineno;
- diag(Z, "illegal rune in string");
- for(c=0; c<i; c++)
- print(" %.2x", *(uchar*)(str+c));
- print("\n");
- }
- return rune;
-}
-
-int
-getnsc(void)
-{
- int c;
-
- if(peekc != IGN) {
- c = peekc;
- peekc = IGN;
- } else
- c = GETC();
- for(;;) {
- if(c >= Runeself || !isspace(c))
- return c;
- if(c == '\n') {
- lineno++;
- return c;
- }
- c = GETC();
- }
-}
-
-void
-unget(int c)
-{
-
- peekc = c;
- if(c == '\n')
- lineno--;
-}
-
-int32
-escchar(int32 e, int longflg, int escflg)
-{
- int32 c, l;
- int i;
-
-loop:
- c = getr();
- if(c == '\n') {
- yyerror("newline in string");
- return EOF;
- }
- if(c != '\\') {
- if(c == e)
- c = EOF;
- return c;
- }
- c = getr();
- if(c == 'x') {
- /*
- * note this is not ansi,
- * supposed to only accept 2 hex
- */
- i = 2;
- if(longflg)
- i = 6;
- l = 0;
- for(; i>0; i--) {
- c = getc();
- if(c >= '0' && c <= '9') {
- l = l*16 + c-'0';
- continue;
- }
- if(c >= 'a' && c <= 'f') {
- l = l*16 + c-'a' + 10;
- continue;
- }
- if(c >= 'A' && c <= 'F') {
- l = l*16 + c-'A' + 10;
- continue;
- }
- unget(c);
- break;
- }
- if(escflg)
- l |= ESC;
- return l;
- }
- if(c >= '0' && c <= '7') {
- /*
- * note this is not ansi,
- * supposed to only accept 3 oct
- */
- i = 2;
- if(longflg)
- i = 8;
- l = c - '0';
- for(; i>0; i--) {
- c = getc();
- if(c >= '0' && c <= '7') {
- l = l*8 + c-'0';
- continue;
- }
- unget(c);
- }
- if(escflg)
- l |= ESC;
- return l;
- }
- switch(c)
- {
- case '\n': goto loop;
- case 'n': return '\n';
- case 't': return '\t';
- case 'b': return '\b';
- case 'r': return '\r';
- case 'f': return '\f';
- case 'a': return '\a';
- case 'v': return '\v';
- }
- return c;
-}
-
-struct
-{
- char *name;
- ushort lexical;
- ushort type;
-} itab[] =
-{
- "auto", LAUTO, 0,
- "break", LBREAK, 0,
- "case", LCASE, 0,
- "char", LCHAR, TCHAR,
- "const", LCONSTNT, 0,
- "continue", LCONTINUE, 0,
- "default", LDEFAULT, 0,
- "do", LDO, 0,
- "double", LDOUBLE, TDOUBLE,
- "else", LELSE, 0,
- "enum", LENUM, 0,
- "extern", LEXTERN, 0,
- "float", LFLOAT, TFLOAT,
- "for", LFOR, 0,
- "goto", LGOTO, 0,
- "if", LIF, 0,
- "inline", LINLINE, 0,
- "int", LINT, TINT,
- "long", LLONG, TLONG,
- "PREFETCH", LPREFETCH, 0,
- "register", LREGISTER, 0,
- "restrict", LRESTRICT, 0,
- "return", LRETURN, 0,
- "SET", LSET, 0,
- "short", LSHORT, TSHORT,
- "signed", LSIGNED, 0,
- "signof", LSIGNOF, 0,
- "sizeof", LSIZEOF, 0,
- "static", LSTATIC, 0,
- "struct", LSTRUCT, 0,
- "switch", LSWITCH, 0,
- "typedef", LTYPEDEF, 0,
- "typestr", LTYPESTR, 0,
- "union", LUNION, 0,
- "unsigned", LUNSIGNED, 0,
- "USED", LUSED, 0,
- "void", LVOID, TVOID,
- "volatile", LVOLATILE, 0,
- "while", LWHILE, 0,
- 0
-};
-
-void
-cinit(void)
-{
- Sym *s;
- int i;
- Type *t;
-
- nerrors = 0;
- lineno = 1;
- iostack = I;
- iofree = I;
- peekc = IGN;
- nhunk = 0;
-
- types[TXXX] = T;
- types[TCHAR] = typ(TCHAR, T);
- types[TUCHAR] = typ(TUCHAR, T);
- types[TSHORT] = typ(TSHORT, T);
- types[TUSHORT] = typ(TUSHORT, T);
- types[TINT] = typ(TINT, T);
- types[TUINT] = typ(TUINT, T);
- types[TLONG] = typ(TLONG, T);
- types[TULONG] = typ(TULONG, T);
- types[TVLONG] = typ(TVLONG, T);
- types[TUVLONG] = typ(TUVLONG, T);
- types[TFLOAT] = typ(TFLOAT, T);
- types[TDOUBLE] = typ(TDOUBLE, T);
- types[TVOID] = typ(TVOID, T);
- types[TENUM] = typ(TENUM, T);
- types[TFUNC] = typ(TFUNC, types[TINT]);
- types[TIND] = typ(TIND, types[TVOID]);
-
- for(i=0; i<NHASH; i++)
- hash[i] = S;
- for(i=0; itab[i].name; i++) {
- s = slookup(itab[i].name);
- s->lexical = itab[i].lexical;
- if(itab[i].type != 0)
- s->type = types[itab[i].type];
- }
- blockno = 0;
- autobn = 0;
- autoffset = 0;
-
- t = typ(TARRAY, types[TCHAR]);
- t->width = 0;
- symstring = slookup(".string");
- symstring->class = CSTATIC;
- symstring->dataflag = NOPTR;
- symstring->type = t;
-
- t = typ(TARRAY, types[TCHAR]);
- t->width = 0;
-
- nodproto = new(OPROTO, Z, Z);
- dclstack = D;
-
- fmtinstall('O', Oconv);
- fmtinstall('T', Tconv);
- fmtinstall('F', FNconv);
- fmtinstall('L', Lconv);
- fmtinstall('Q', Qconv);
- fmtinstall('|', VBconv);
- fmtinstall('U', Uconv);
- fmtinstall('B', Bconv);
-}
-
-int
-filbuf(void)
-{
- Io *i;
-
-loop:
- i = iostack;
- if(i == I)
- return EOF;
- if(i->f < 0)
- goto pop;
- fi.c = read(i->f, i->b, BUFSIZ) - 1;
- if(fi.c < 0) {
- close(i->f);
- linklinehist(ctxt, lineno, nil, 0);
- goto pop;
- }
- fi.p = i->b + 1;
- return i->b[0] & 0xff;
-
-pop:
- iostack = i->link;
- i->link = iofree;
- iofree = i;
- i = iostack;
- if(i == I)
- return EOF;
- fi.p = i->p;
- fi.c = i->c;
- if(--fi.c < 0)
- goto loop;
- return *fi.p++ & 0xff;
-}
-
-int
-Oconv(Fmt *fp)
-{
- int a;
-
- a = va_arg(fp->args, int);
- if(a < OXXX || a > OEND)
- return fmtprint(fp, "***badO %d***", a);
-
- return fmtstrcpy(fp, onames[a]);
-}
-
-int
-Lconv(Fmt *fp)
-{
- return linklinefmt(ctxt, fp);
-}
-
-int
-Tconv(Fmt *fp)
-{
- char str[STRINGSZ+20], s[STRINGSZ+20];
- Type *t, *t1;
- int et;
- int32 n;
-
- str[0] = 0;
- for(t = va_arg(fp->args, Type*); t != T; t = t->link) {
- et = t->etype;
- if(str[0])
- strcat(str, " ");
- if(t->garb&~GINCOMPLETE) {
- sprint(s, "%s ", gnames[t->garb&~GINCOMPLETE]);
- if(strlen(str) + strlen(s) < STRINGSZ)
- strcat(str, s);
- }
- sprint(s, "%s", tnames[et]);
- if(strlen(str) + strlen(s) < STRINGSZ)
- strcat(str, s);
- if(et == TFUNC && (t1 = t->down)) {
- sprint(s, "(%T", t1);
- if(strlen(str) + strlen(s) < STRINGSZ)
- strcat(str, s);
- while(t1 = t1->down) {
- sprint(s, ", %T", t1);
- if(strlen(str) + strlen(s) < STRINGSZ)
- strcat(str, s);
- }
- if(strlen(str) + strlen(s) < STRINGSZ)
- strcat(str, ")");
- }
- if(et == TARRAY) {
- n = t->width;
- if(t->link && t->link->width)
- n /= t->link->width;
- sprint(s, "[%d]", n);
- if(strlen(str) + strlen(s) < STRINGSZ)
- strcat(str, s);
- }
- if(t->nbits) {
- sprint(s, " %d:%d", t->shift, t->nbits);
- if(strlen(str) + strlen(s) < STRINGSZ)
- strcat(str, s);
- }
- if(typesu[et]) {
- if(t->tag) {
- strcat(str, " ");
- if(strlen(str) + strlen(t->tag->name) < STRINGSZ)
- strcat(str, t->tag->name);
- } else
- strcat(str, " {}");
- break;
- }
- }
- return fmtstrcpy(fp, str);
-}
-
-int
-FNconv(Fmt *fp)
-{
- char *str;
- Node *n;
-
- n = va_arg(fp->args, Node*);
- str = "<indirect>";
- if(n != Z && (n->op == ONAME || n->op == ODOT || n->op == OELEM))
- str = n->sym->name;
- return fmtstrcpy(fp, str);
-}
-
-int
-Qconv(Fmt *fp)
-{
- char str[STRINGSZ+20], *s;
- int32 b;
- int i;
-
- str[0] = 0;
- for(b = va_arg(fp->args, int32); b;) {
- i = bitno(b);
- if(str[0])
- strcat(str, " ");
- s = qnames[i];
- if(strlen(str) + strlen(s) >= STRINGSZ)
- break;
- strcat(str, s);
- b &= ~(1L << i);
- }
- return fmtstrcpy(fp, str);
-}
-
-int
-VBconv(Fmt *fp)
-{
- char str[STRINGSZ];
- int i, n, t, pc;
-
- n = va_arg(fp->args, int);
- pc = 0; /* BUG: was printcol */
- i = 0;
- while(pc < n) {
- t = (pc+4) & ~3;
- if(t <= n) {
- str[i++] = '\t';
- pc = t;
- continue;
- }
- str[i++] = ' ';
- pc++;
- }
- str[i] = 0;
-
- return fmtstrcpy(fp, str);
-}
-
-int
-Bconv(Fmt *fp)
-{
- char str[STRINGSZ], ss[STRINGSZ], *s;
- Bits bits;
- int i;
-
- str[0] = 0;
- bits = va_arg(fp->args, Bits);
- while(bany(&bits)) {
- i = bnum(bits);
- if(str[0])
- strcat(str, " ");
- if(var[i].sym == nil) {
- sprint(ss, "$%lld", var[i].offset);
- s = ss;
- } else
- s = var[i].sym->name;
- if(strlen(str) + strlen(s) + 1 >= STRINGSZ)
- break;
- strcat(str, s);
- bits.b[i/32] &= ~(1L << (i%32));
- }
- return fmtstrcpy(fp, str);
-}
-
-void
-setinclude(char *p)
-{
- int i;
-
- if(*p != 0) {
- for(i=1; i < ninclude; i++)
- if(strcmp(p, include[i]) == 0)
- return;
-
- if(ninclude%8 == 0)
- include = allocn(include, ninclude*sizeof(char *),
- 8*sizeof(char *));
- include[ninclude++] = p;
- }
-}
-
-void*
-alloc(int32 n)
-{
- void *p;
-
- p = malloc(n);
- if(p == nil) {
- print("alloc out of mem\n");
- exits("alloc: out of mem");
- }
- memset(p, 0, n);
- return p;
-}
-
-void*
-allocn(void *p, int32 n, int32 d)
-{
- if(p == nil)
- return alloc(n+d);
- p = realloc(p, n+d);
- if(p == nil) {
- print("allocn out of mem\n");
- exits("allocn: out of mem");
- }
- if(d > 0)
- memset((char*)p+n, 0, d);
- return p;
-}
-
-void
-ensuresymb(int32 n)
-{
- if(symb == nil) {
- symb = alloc(NSYMB+1);
- nsymb = NSYMB;
- }
-
- if(n > nsymb) {
- symb = allocn(symb, nsymb, n+1-nsymb);
- nsymb = n;
- }
-}
diff --git a/src/cmd/cc/mac.c b/src/cmd/cc/mac.c
deleted file mode 100644
index b969662ae..000000000
--- a/src/cmd/cc/mac.c
+++ /dev/null
@@ -1,34 +0,0 @@
-// Inferno utils/cc/mac.c
-// http://code.google.com/p/inferno-os/source/browse/utils/cc/mac.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include <u.h>
-#include "cc.h"
-
-#include "macbody"
diff --git a/src/cmd/cc/omachcap.c b/src/cmd/cc/omachcap.c
deleted file mode 100644
index f8fc1d88b..000000000
--- a/src/cmd/cc/omachcap.c
+++ /dev/null
@@ -1,40 +0,0 @@
-// Inferno utils/cc/machcap.c
-// http://code.google.com/p/inferno-os/source/browse/utils/cc/machcap.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include <u.h>
-#include "cc.h"
-
-/* default, like old cc */
-int
-machcap(Node *n)
-{
- USED(n);
- return 0;
-}
diff --git a/src/cmd/cc/pgen.c b/src/cmd/cc/pgen.c
deleted file mode 100644
index 54cf0c5e1..000000000
--- a/src/cmd/cc/pgen.c
+++ /dev/null
@@ -1,622 +0,0 @@
-// Inferno utils/6c/sgen.c
-// http://code.google.com/p/inferno-os/source/browse/utils/6c/sgen.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-#include "../../runtime/funcdata.h"
-
-int
-hasdotdotdot(Type *t)
-{
- for(t=t->down; t!=T; t=t->down)
- if(t->etype == TDOT)
- return 1;
- return 0;
-}
-
-vlong
-argsize(int doret)
-{
- Type *t;
- int32 s;
-
-//print("t=%T\n", thisfn);
- s = 0;
- if(hasdotdotdot(thisfn))
- s = align(s, thisfn->link, Aarg0, nil);
- for(t=thisfn->down; t!=T; t=t->down) {
- switch(t->etype) {
- case TVOID:
- break;
- case TDOT:
- if((textflag & NOSPLIT) == 0)
- yyerror("function takes ... without textflag NOSPLIT");
- return ArgsSizeUnknown;
- default:
- s = align(s, t, Aarg1, nil);
- s = align(s, t, Aarg2, nil);
- break;
- }
-//print(" %d %T\n", s, t);
- }
- if(thechar == '6' || thechar == '9')
- s = (s+7) & ~7;
- else
- s = (s+3) & ~3;
- if(doret && thisfn->link->etype != TVOID) {
- s = align(s, thisfn->link, Aarg1, nil);
- s = align(s, thisfn->link, Aarg2, nil);
- if(thechar == '6' || thechar == '9')
- s = (s+7) & ~7;
- else
- s = (s+3) & ~3;
- }
- return s;
-}
-
-void
-codgen(Node *n, Node *nn)
-{
- Prog *sp;
- Node *n1, nod, nod1;
-
- cursafe = 0;
- curarg = 0;
- maxargsafe = 0;
-
- /*
- * isolate name
- */
- for(n1 = nn;; n1 = n1->left) {
- if(n1 == Z) {
- diag(nn, "can't find function name");
- return;
- }
- if(n1->op == ONAME)
- break;
- }
- nearln = nn->lineno;
-
- p = gtext(n1->sym, stkoff);
- p->from.sym->cfunc = 1;
- sp = p;
-
- /*
- * isolate first argument
- */
- if(REGARG >= 0) {
- if(typesuv[thisfn->link->etype]) {
- nod1 = *nodret->left;
- nodreg(&nod, &nod1, REGARG);
- gmove(&nod, &nod1);
- } else
- if(firstarg && typechlp[firstargtype->etype]) {
- nod1 = *nodret->left;
- nod1.sym = firstarg;
- nod1.type = firstargtype;
- nod1.xoffset = align(0, firstargtype, Aarg1, nil);
- nod1.etype = firstargtype->etype;
- nodreg(&nod, &nod1, REGARG);
- gmove(&nod, &nod1);
- }
- }
-
- canreach = 1;
- warnreach = 1;
- gen(n);
- if(canreach && thisfn->link->etype != TVOID)
- diag(Z, "no return at end of function: %s", n1->sym->name);
- noretval(3);
- gbranch(ORETURN);
-
- if(!debug['N'] || debug['R'] || debug['P'])
- regopt(sp);
-
- if(thechar=='6' || thechar=='7') /* [sic] */
- maxargsafe = xround(maxargsafe, 8);
- sp->to.offset += maxargsafe;
-}
-
-void
-supgen(Node *n)
-{
- int owarn;
- long spc;
- Prog *sp;
-
- if(n == Z)
- return;
- suppress++;
- owarn = warnreach;
- warnreach = 0;
- spc = pc;
- sp = lastp;
- gen(n);
- lastp = sp;
- pc = spc;
- sp->link = nil;
- suppress--;
- warnreach = owarn;
-}
-
-void
-gen(Node *n)
-{
- Node *l, nod, nod1;
- Prog *sp, *spc, *spb;
- Case *cn;
- long sbc, scc;
- int snbreak, sncontin;
- int f, o, oldreach;
-
-loop:
- if(n == Z)
- return;
- nearln = n->lineno;
- o = n->op;
- if(debug['G'])
- if(o != OLIST)
- print("%L %O\n", nearln, o);
-
- if(!canreach) {
- switch(o) {
- case OLABEL:
- case OCASE:
- case OLIST:
- case OBREAK:
- case OFOR:
- case OWHILE:
- case ODWHILE:
- /* all handled specially - see switch body below */
- break;
- default:
- if(warnreach) {
- warn(n, "unreachable code %O", o);
- warnreach = 0;
- }
- }
- }
-
- switch(o) {
-
- default:
- complex(n);
- cgen(n, Z);
- break;
-
- case OLIST:
- gen(n->left);
-
- rloop:
- n = n->right;
- goto loop;
-
- case ORETURN:
- canreach = 0;
- warnreach = !suppress;
- complex(n);
- if(n->type == T)
- break;
- l = n->left;
- if(l == Z) {
- noretval(3);
- gbranch(ORETURN);
- break;
- }
- if(typecmplx[n->type->etype] && !hasdotdotdot(thisfn)) {
- regret(&nod, n, thisfn, 2);
- sugen(l, &nod, n->type->width);
- noretval(3);
- gbranch(ORETURN);
- break;
- }
- if(typecmplx[n->type->etype]) {
- sugen(l, nodret, n->type->width);
- noretval(3);
- gbranch(ORETURN);
- break;
- }
- regret(&nod1, n, thisfn, 2);
- nod = nod1;
- if(nod.op != OREGISTER)
- regalloc(&nod, n, Z);
- cgen(l, &nod);
- if(nod1.op != OREGISTER)
- gmove(&nod, &nod1);
- regfree(&nod);
- if(typefd[n->type->etype])
- noretval(1);
- else
- noretval(2);
- gbranch(ORETURN);
- break;
-
- case OLABEL:
- canreach = 1;
- l = n->left;
- if(l) {
- l->pc = pc;
- if(l->label)
- patch(l->label, pc);
- }
- gbranch(OGOTO); /* prevent self reference in reg */
- patch(p, pc);
- goto rloop;
-
- case OGOTO:
- canreach = 0;
- warnreach = !suppress;
- n = n->left;
- if(n == Z)
- return;
- if(n->complex == 0) {
- diag(Z, "label undefined: %s", n->sym->name);
- return;
- }
- if(suppress)
- return;
- gbranch(OGOTO);
- if(n->pc) {
- patch(p, n->pc);
- return;
- }
- if(n->label)
- patch(n->label, pc-1);
- n->label = p;
- return;
-
- case OCASE:
- canreach = 1;
- l = n->left;
- if(cases == C)
- diag(n, "case/default outside a switch");
- if(l == Z) {
- newcase();
- cases->val = 0;
- cases->def = 1;
- cases->label = pc;
- cases->isv = 0;
- goto rloop;
- }
- complex(l);
- if(l->type == T)
- goto rloop;
- if(l->op == OCONST)
- if(typeword[l->type->etype] && l->type->etype != TIND) {
- newcase();
- cases->val = l->vconst;
- cases->def = 0;
- cases->label = pc;
- cases->isv = typev[l->type->etype];
- goto rloop;
- }
- diag(n, "case expression must be integer constant");
- goto rloop;
-
- case OSWITCH:
- l = n->left;
- complex(l);
- if(l->type == T)
- break;
- if(!typechlvp[l->type->etype] || l->type->etype == TIND) {
- diag(n, "switch expression must be integer");
- break;
- }
-
- gbranch(OGOTO); /* entry */
- sp = p;
-
- cn = cases;
- cases = C;
- newcase();
-
- sbc = breakpc;
- breakpc = pc;
- snbreak = nbreak;
- nbreak = 0;
- gbranch(OGOTO);
- spb = p;
-
- gen(n->right); /* body */
- if(canreach){
- gbranch(OGOTO);
- patch(p, breakpc);
- nbreak++;
- }
-
- patch(sp, pc);
- doswit(l);
- patch(spb, pc);
-
- cases = cn;
- breakpc = sbc;
- canreach = nbreak!=0;
- if(canreach == 0)
- warnreach = !suppress;
- nbreak = snbreak;
- break;
-
- case OWHILE:
- case ODWHILE:
- l = n->left;
- gbranch(OGOTO); /* entry */
- sp = p;
-
- scc = continpc;
- continpc = pc;
- gbranch(OGOTO);
- spc = p;
-
- sbc = breakpc;
- breakpc = pc;
- snbreak = nbreak;
- nbreak = 0;
- gbranch(OGOTO);
- spb = p;
-
- patch(spc, pc);
- if(n->op == OWHILE)
- patch(sp, pc);
- bcomplex(l, Z); /* test */
- patch(p, breakpc);
- if(l->op != OCONST || vconst(l) == 0)
- nbreak++;
-
- if(n->op == ODWHILE)
- patch(sp, pc);
- gen(n->right); /* body */
- gbranch(OGOTO);
- patch(p, continpc);
-
- patch(spb, pc);
- continpc = scc;
- breakpc = sbc;
- canreach = nbreak!=0;
- if(canreach == 0)
- warnreach = !suppress;
- nbreak = snbreak;
- break;
-
- case OFOR:
- l = n->left;
- if(!canreach && l->right->left && warnreach) {
- warn(n, "unreachable code FOR");
- warnreach = 0;
- }
- gen(l->right->left); /* init */
- gbranch(OGOTO); /* entry */
- sp = p;
-
- /*
- * if there are no incoming labels in the
- * body and the top's not reachable, warn
- */
- if(!canreach && warnreach && deadheads(n)) {
- warn(n, "unreachable code %O", o);
- warnreach = 0;
- }
-
- scc = continpc;
- continpc = pc;
- gbranch(OGOTO);
- spc = p;
-
- sbc = breakpc;
- breakpc = pc;
- snbreak = nbreak;
- nbreak = 0;
- sncontin = ncontin;
- ncontin = 0;
- gbranch(OGOTO);
- spb = p;
-
- patch(spc, pc);
- gen(l->right->right); /* inc */
- patch(sp, pc);
- if(l->left != Z) { /* test */
- bcomplex(l->left, Z);
- patch(p, breakpc);
- if(l->left->op != OCONST || vconst(l->left) == 0)
- nbreak++;
- }
- canreach = 1;
- gen(n->right); /* body */
- if(canreach){
- gbranch(OGOTO);
- patch(p, continpc);
- ncontin++;
- }
- if(!ncontin && l->right->right && warnreach) {
- warn(l->right->right, "unreachable FOR inc");
- warnreach = 0;
- }
-
- patch(spb, pc);
- continpc = scc;
- breakpc = sbc;
- canreach = nbreak!=0;
- if(canreach == 0)
- warnreach = !suppress;
- nbreak = snbreak;
- ncontin = sncontin;
- break;
-
- case OCONTINUE:
- if(continpc < 0) {
- diag(n, "continue not in a loop");
- break;
- }
- gbranch(OGOTO);
- patch(p, continpc);
- ncontin++;
- canreach = 0;
- warnreach = !suppress;
- break;
-
- case OBREAK:
- if(breakpc < 0) {
- diag(n, "break not in a loop");
- break;
- }
- /*
- * Don't complain about unreachable break statements.
- * There are breaks hidden in yacc's output and some people
- * write return; break; in their switch statements out of habit.
- * However, don't confuse the analysis by inserting an
- * unreachable reference to breakpc either.
- */
- if(!canreach)
- break;
- gbranch(OGOTO);
- patch(p, breakpc);
- nbreak++;
- canreach = 0;
- warnreach = !suppress;
- break;
-
- case OIF:
- l = n->left;
- if(bcomplex(l, n->right)) {
- if(typefd[l->type->etype])
- f = !l->fconst;
- else
- f = !l->vconst;
- if(debug['c'])
- print("%L const if %s\n", nearln, f ? "false" : "true");
- if(f) {
- canreach = 1;
- supgen(n->right->left);
- oldreach = canreach;
- canreach = 1;
- gen(n->right->right);
- /*
- * treat constant ifs as regular ifs for
- * reachability warnings.
- */
- if(!canreach && oldreach && debug['w'] < 2)
- warnreach = 0;
- }
- else {
- canreach = 1;
- gen(n->right->left);
- oldreach = canreach;
- canreach = 1;
- supgen(n->right->right);
- /*
- * treat constant ifs as regular ifs for
- * reachability warnings.
- */
- if(!oldreach && canreach && debug['w'] < 2)
- warnreach = 0;
- canreach = oldreach;
- }
- }
- else {
- sp = p;
- canreach = 1;
- if(n->right->left != Z)
- gen(n->right->left);
- oldreach = canreach;
- canreach = 1;
- if(n->right->right != Z) {
- gbranch(OGOTO);
- patch(sp, pc);
- sp = p;
- gen(n->right->right);
- }
- patch(sp, pc);
- canreach = canreach || oldreach;
- if(canreach == 0)
- warnreach = !suppress;
- }
- break;
-
- case OSET:
- case OUSED:
- case OPREFETCH:
- usedset(n->left, o);
- break;
- }
-}
-
-void
-usedset(Node *n, int o)
-{
- if(n->op == OLIST) {
- usedset(n->left, o);
- usedset(n->right, o);
- return;
- }
- complex(n);
- if(o == OPREFETCH) {
- gprefetch(n);
- return;
- }
- switch(n->op) {
- case OADDR: /* volatile */
- gins(ANOP, n, Z);
- break;
- case ONAME:
- if(o == OSET)
- gins(ANOP, Z, n);
- else
- gins(ANOP, n, Z);
- break;
- }
-}
-
-int
-bcomplex(Node *n, Node *c)
-{
- Node *b, nod;
-
- complex(n);
- if(n->type != T)
- if(tcompat(n, T, n->type, tnot))
- n->type = T;
- if(n->type == T) {
- gbranch(OGOTO);
- return 0;
- }
- if(c != Z && n->op == OCONST && deadheads(c))
- return 1;
- if(typev[n->type->etype] && machcap(Z)) {
- b = &nod;
- b->op = ONE;
- b->left = n;
- b->right = new(0, Z, Z);
- *b->right = *nodconst(0);
- b->right->type = n->type;
- b->type = types[TLONG];
- n = b;
- }
- bool64(n);
- boolgen(n, 1, Z);
- return 0;
-}
diff --git a/src/cmd/cc/pswt.c b/src/cmd/cc/pswt.c
deleted file mode 100644
index bae57c64d..000000000
--- a/src/cmd/cc/pswt.c
+++ /dev/null
@@ -1,140 +0,0 @@
-// Inferno utils/6c/swt.c
-// http://code.google.com/p/inferno-os/source/browse/utils/6c/swt.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include "gc.h"
-
-int
-swcmp(const void *a1, const void *a2)
-{
- C1 *p1, *p2;
-
- p1 = (C1*)a1;
- p2 = (C1*)a2;
- if(p1->val < p2->val)
- return -1;
- return p1->val > p2->val;
-}
-
-void
-doswit(Node *n)
-{
- Case *c;
- C1 *q, *iq;
- int32 def, nc, i, isv;
-
- def = 0;
- nc = 0;
- isv = 0;
- for(c = cases; c->link != C; c = c->link) {
- if(c->def) {
- if(def)
- diag(n, "more than one default in switch");
- def = c->label;
- continue;
- }
- isv |= c->isv;
- nc++;
- }
- if(isv && !typev[n->type->etype])
- warn(n, "32-bit switch expression with 64-bit case constant");
-
- iq = alloc(nc*sizeof(C1));
- q = iq;
- for(c = cases; c->link != C; c = c->link) {
- if(c->def)
- continue;
- q->label = c->label;
- if(isv)
- q->val = c->val;
- else
- q->val = (int32)c->val; /* cast ensures correct value for 32-bit switch on 64-bit architecture */
- q++;
- }
- qsort(iq, nc, sizeof(C1), swcmp);
- if(debug['W'])
- for(i=0; i<nc; i++)
- print("case %2d: = %.8llux\n", i, (vlong)iq[i].val);
- for(i=0; i<nc-1; i++)
- if(iq[i].val == iq[i+1].val)
- diag(n, "duplicate cases in switch %lld", (vlong)iq[i].val);
- if(def == 0) {
- def = breakpc;
- nbreak++;
- }
- swit1(iq, nc, def, n);
-}
-
-void
-newcase(void)
-{
- Case *c;
-
- c = alloc(sizeof(*c));
- c->link = cases;
- cases = c;
-}
-
-int32
-outlstring(TRune *s, int32 n)
-{
- char buf[sizeof(TRune)];
- uint c;
- int i;
- int32 r;
-
- if(suppress)
- return nstring;
- while(nstring & (sizeof(TRune)-1))
- outstring("", 1);
- r = nstring;
- while(n > 0) {
- c = *s++;
- if(align(0, types[TCHAR], Aarg1, nil)) {
- for(i = 0; i < sizeof(TRune); i++)
- buf[i] = c>>(8*(sizeof(TRune) - i - 1));
- } else {
- for(i = 0; i < sizeof(TRune); i++)
- buf[i] = c>>(8*i);
- }
- outstring(buf, sizeof(TRune));
- n -= sizeof(TRune);
- }
- return r;
-}
-
-void
-nullwarn(Node *l, Node *r)
-{
- warn(Z, "result of operation not used");
- if(l != Z)
- cgen(l, Z);
- if(r != Z)
- cgen(r, Z);
-}
diff --git a/src/cmd/cc/scon.c b/src/cmd/cc/scon.c
deleted file mode 100644
index b0b909759..000000000
--- a/src/cmd/cc/scon.c
+++ /dev/null
@@ -1,640 +0,0 @@
-// Inferno utils/cc/scon.c
-// http://code.google.com/p/inferno-os/source/browse/utils/cc/scon.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include <u.h>
-#include "cc.h"
-
-static Node*
-acast(Type *t, Node *n)
-{
- if(n->type->etype != t->etype || n->op == OBIT) {
- n = new1(OCAST, n, Z);
- if(nocast(n->left->type, t))
- *n = *n->left;
- n->type = t;
- }
- return n;
-}
-
-
-void
-evconst(Node *n)
-{
- Node *l, *r;
- int et, isf;
- vlong v;
- double d;
-
- if(n == Z || n->type == T)
- return;
-
- et = n->type->etype;
- isf = typefd[et];
-
- l = n->left;
- r = n->right;
-
- d = 0;
- v = 0;
-
- switch(n->op) {
- default:
- return;
-
- case ONEG:
- if(isf)
- d = -l->fconst;
- else
- v = -l->vconst;
- break;
-
- case OCOM:
- v = ~l->vconst;
- break;
-
- case OCAST:
- if(et == TVOID)
- return;
- et = l->type->etype;
- if(isf) {
- if(typefd[et])
- d = l->fconst;
- else
- d = l->vconst;
- } else {
- if(typefd[et])
- v = l->fconst;
- else
- v = convvtox(l->vconst, n->type->etype);
- }
- break;
-
- case OCONST:
- break;
-
- case OADD:
- if(isf)
- d = l->fconst + r->fconst;
- else {
- v = l->vconst + r->vconst;
- }
- break;
-
- case OSUB:
- if(isf)
- d = l->fconst - r->fconst;
- else
- v = l->vconst - r->vconst;
- break;
-
- case OMUL:
- if(isf)
- d = l->fconst * r->fconst;
- else {
- v = l->vconst * r->vconst;
- }
- break;
-
- case OLMUL:
- v = (uvlong)l->vconst * (uvlong)r->vconst;
- break;
-
-
- case ODIV:
- if(vconst(r) == 0) {
- warn(n, "divide by zero");
- return;
- }
- if(isf)
- d = l->fconst / r->fconst;
- else
- v = l->vconst / r->vconst;
- break;
-
- case OLDIV:
- if(vconst(r) == 0) {
- warn(n, "divide by zero");
- return;
- }
- v = (uvlong)l->vconst / (uvlong)r->vconst;
- break;
-
- case OMOD:
- if(vconst(r) == 0) {
- warn(n, "modulo by zero");
- return;
- }
- v = l->vconst % r->vconst;
- break;
-
- case OLMOD:
- if(vconst(r) == 0) {
- warn(n, "modulo by zero");
- return;
- }
- v = (uvlong)l->vconst % (uvlong)r->vconst;
- break;
-
- case OAND:
- v = l->vconst & r->vconst;
- break;
-
- case OOR:
- v = l->vconst | r->vconst;
- break;
-
- case OXOR:
- v = l->vconst ^ r->vconst;
- break;
-
- case OLSHR:
- if(l->type->width != sizeof(uvlong))
- v = ((uvlong)l->vconst & 0xffffffffULL) >> r->vconst;
- else
- v = (uvlong)l->vconst >> r->vconst;
- break;
-
- case OASHR:
- v = l->vconst >> r->vconst;
- break;
-
- case OASHL:
- v = (uvlong)l->vconst << r->vconst;
- break;
-
- case OLO:
- v = (uvlong)l->vconst < (uvlong)r->vconst;
- break;
-
- case OLT:
- if(typefd[l->type->etype])
- v = l->fconst < r->fconst;
- else
- v = l->vconst < r->vconst;
- break;
-
- case OHI:
- v = (uvlong)l->vconst > (uvlong)r->vconst;
- break;
-
- case OGT:
- if(typefd[l->type->etype])
- v = l->fconst > r->fconst;
- else
- v = l->vconst > r->vconst;
- break;
-
- case OLS:
- v = (uvlong)l->vconst <= (uvlong)r->vconst;
- break;
-
- case OLE:
- if(typefd[l->type->etype])
- v = l->fconst <= r->fconst;
- else
- v = l->vconst <= r->vconst;
- break;
-
- case OHS:
- v = (uvlong)l->vconst >= (uvlong)r->vconst;
- break;
-
- case OGE:
- if(typefd[l->type->etype])
- v = l->fconst >= r->fconst;
- else
- v = l->vconst >= r->vconst;
- break;
-
- case OEQ:
- if(typefd[l->type->etype])
- v = l->fconst == r->fconst;
- else
- v = l->vconst == r->vconst;
- break;
-
- case ONE:
- if(typefd[l->type->etype])
- v = l->fconst != r->fconst;
- else
- v = l->vconst != r->vconst;
- break;
-
- case ONOT:
- if(typefd[l->type->etype])
- v = !l->fconst;
- else
- v = !l->vconst;
- break;
-
- case OANDAND:
- if(typefd[l->type->etype])
- v = l->fconst && r->fconst;
- else
- v = l->vconst && r->vconst;
- break;
-
- case OOROR:
- if(typefd[l->type->etype])
- v = l->fconst || r->fconst;
- else
- v = l->vconst || r->vconst;
- break;
- }
- if(isf) {
- n->fconst = d;
- } else {
- n->vconst = convvtox(v, n->type->etype);
- }
- n->oldop = n->op;
- n->op = OCONST;
-}
-
-void
-acom(Node *n)
-{
- Type *t;
- Node *l, *r;
- int i;
-
- switch(n->op)
- {
-
- case ONAME:
- case OCONST:
- case OSTRING:
- case OINDREG:
- case OREGISTER:
- return;
-
- case ONEG:
- l = n->left;
- if(addo(n) && addo(l))
- break;
- acom(l);
- return;
-
- case OADD:
- case OSUB:
- case OMUL:
- l = n->left;
- r = n->right;
- if(addo(n)) {
- if(addo(r))
- break;
- if(addo(l))
- break;
- }
- acom(l);
- acom(r);
- return;
-
- default:
- l = n->left;
- r = n->right;
- if(l != Z)
- acom(l);
- if(r != Z)
- acom(r);
- return;
- }
-
- /* bust terms out */
- t = n->type;
- term[0].mult = 0;
- term[0].node = Z;
- nterm = 1;
- acom1(1, n);
- if(debug['m'])
- for(i=0; i<nterm; i++) {
- print("%d %3lld ", i, term[i].mult);
- prtree1(term[i].node, 1, 0);
- }
- if(nterm < NTERM)
- acom2(n, t);
- n->type = t;
-}
-
-int
-acomcmp1(const void *a1, const void *a2)
-{
- vlong c1, c2;
- Term *t1, *t2;
-
- t1 = (Term*)a1;
- t2 = (Term*)a2;
- c1 = t1->mult;
- if(c1 < 0)
- c1 = -c1;
- c2 = t2->mult;
- if(c2 < 0)
- c2 = -c2;
- if(c1 > c2)
- return 1;
- if(c1 < c2)
- return -1;
- c1 = 1;
- if(t1->mult < 0)
- c1 = 0;
- c2 = 1;
- if(t2->mult < 0)
- c2 = 0;
- if(c2 -= c1)
- return c2;
- if(t2 > t1)
- return 1;
- return -1;
-}
-
-int
-acomcmp2(const void *a1, const void *a2)
-{
- vlong c1, c2;
- Term *t1, *t2;
-
- t1 = (Term*)a1;
- t2 = (Term*)a2;
- c1 = t1->mult;
- c2 = t2->mult;
- if(c1 > c2)
- return 1;
- if(c1 < c2)
- return -1;
- if(t2 > t1)
- return 1;
- return -1;
-}
-
-void
-acom2(Node *n, Type *t)
-{
- Node *l, *r;
- Term trm[NTERM];
- int et, nt, i, j;
- vlong c1, c2;
-
- /*
- * copy into automatic
- */
- c2 = 0;
- nt = nterm;
- for(i=0; i<nt; i++)
- trm[i] = term[i];
- /*
- * recur on subtrees
- */
- j = 0;
- for(i=1; i<nt; i++) {
- c1 = trm[i].mult;
- if(c1 == 0)
- continue;
- l = trm[i].node;
- if(l != Z) {
- j = 1;
- acom(l);
- }
- }
- c1 = trm[0].mult;
- if(j == 0) {
- n->oldop = n->op;
- n->op = OCONST;
- n->vconst = c1;
- return;
- }
- et = t->etype;
-
- /*
- * prepare constant term,
- * combine it with an addressing term
- */
- if(c1 != 0) {
- l = new1(OCONST, Z, Z);
- l->type = t;
- l->vconst = c1;
- trm[0].mult = 1;
- for(i=1; i<nt; i++) {
- if(trm[i].mult != 1)
- continue;
- r = trm[i].node;
- if(r->op != OADDR)
- continue;
- r->type = t;
- l = new1(OADD, r, l);
- l->type = t;
- trm[i].mult = 0;
- break;
- }
- trm[0].node = l;
- }
- /*
- * look for factorable terms
- * c1*i + c1*c2*j -> c1*(i + c2*j)
- */
- qsort(trm+1, nt-1, sizeof(trm[0]), acomcmp1);
- for(i=nt-1; i>=0; i--) {
- c1 = trm[i].mult;
- if(c1 < 0)
- c1 = -c1;
- if(c1 <= 1)
- continue;
- for(j=i+1; j<nt; j++) {
- c2 = trm[j].mult;
- if(c2 < 0)
- c2 = -c2;
- if(c2 <= 1)
- continue;
- if(c2 % c1)
- continue;
- r = trm[j].node;
- if(r->type->etype != et)
- r = acast(t, r);
- c2 = trm[j].mult/trm[i].mult;
- if(c2 != 1 && c2 != -1) {
- r = new1(OMUL, r, new(OCONST, Z, Z));
- r->type = t;
- r->right->type = t;
- r->right->vconst = c2;
- }
- l = trm[i].node;
- if(l->type->etype != et)
- l = acast(t, l);
- r = new1(OADD, l, r);
- r->type = t;
- if(c2 == -1)
- r->op = OSUB;
- trm[i].node = r;
- trm[j].mult = 0;
- }
- }
- if(debug['m']) {
- print("\n");
- for(i=0; i<nt; i++) {
- print("%d %3lld ", i, trm[i].mult);
- prtree1(trm[i].node, 1, 0);
- }
- }
-
- /*
- * put it all back together
- */
- qsort(trm+1, nt-1, sizeof(trm[0]), acomcmp2);
- l = Z;
- for(i=nt-1; i>=0; i--) {
- c1 = trm[i].mult;
- if(c1 == 0)
- continue;
- r = trm[i].node;
- if(r->type->etype != et || r->op == OBIT)
- r = acast(t, r);
- if(c1 != 1 && c1 != -1) {
- r = new1(OMUL, r, new(OCONST, Z, Z));
- r->type = t;
- r->right->type = t;
- if(c1 < 0) {
- r->right->vconst = -c1;
- c1 = -1;
- } else {
- r->right->vconst = c1;
- c1 = 1;
- }
- }
- if(l == Z) {
- l = r;
- c2 = c1;
- continue;
- }
- if(c1 < 0)
- if(c2 < 0)
- l = new1(OADD, l, r);
- else
- l = new1(OSUB, l, r);
- else
- if(c2 < 0) {
- l = new1(OSUB, r, l);
- c2 = 1;
- } else
- l = new1(OADD, l, r);
- l->type = t;
- }
- if(c2 < 0) {
- r = new1(OCONST, 0, 0);
- r->vconst = 0;
- r->type = t;
- l = new1(OSUB, r, l);
- l->type = t;
- }
- *n = *l;
-}
-
-void
-acom1(vlong v, Node *n)
-{
- Node *l, *r;
-
- if(v == 0 || nterm >= NTERM)
- return;
- if(!addo(n)) {
- if(n->op == OCONST)
- if(!typefd[n->type->etype]) {
- term[0].mult += v*n->vconst;
- return;
- }
- term[nterm].mult = v;
- term[nterm].node = n;
- nterm++;
- return;
- }
- switch(n->op) {
-
- case OCAST:
- acom1(v, n->left);
- break;
-
- case ONEG:
- acom1(-v, n->left);
- break;
-
- case OADD:
- acom1(v, n->left);
- acom1(v, n->right);
- break;
-
- case OSUB:
- acom1(v, n->left);
- acom1(-v, n->right);
- break;
-
- case OMUL:
- l = n->left;
- r = n->right;
- if(l->op == OCONST)
- if(!typefd[n->type->etype]) {
- acom1(v*l->vconst, r);
- break;
- }
- if(r->op == OCONST)
- if(!typefd[n->type->etype]) {
- acom1(v*r->vconst, l);
- break;
- }
- break;
-
- default:
- diag(n, "not addo");
- }
-}
-
-int
-addo(Node *n)
-{
-
- if(n != Z)
- if(!typefd[n->type->etype])
- if(!typev[n->type->etype] || ewidth[TVLONG] == ewidth[TIND])
- switch(n->op) {
-
- case OCAST:
- if(nilcast(n->left->type, n->type))
- return 1;
- break;
-
- case ONEG:
- case OADD:
- case OSUB:
- return 1;
-
- case OMUL:
- if(n->left->op == OCONST)
- return 1;
- if(n->right->op == OCONST)
- return 1;
- }
- return 0;
-}
diff --git a/src/cmd/cc/sub.c b/src/cmd/cc/sub.c
deleted file mode 100644
index 94c11d021..000000000
--- a/src/cmd/cc/sub.c
+++ /dev/null
@@ -1,2068 +0,0 @@
-// Inferno utils/cc/sub.c
-// http://code.google.com/p/inferno-os/source/browse/utils/cc/sub.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-#include <u.h>
-#include "cc.h"
-
-Node*
-new(int t, Node *l, Node *r)
-{
- Node *n;
-
- n = alloc(sizeof(*n));
- n->op = t;
- n->left = l;
- n->right = r;
- if(l && t != OGOTO)
- n->lineno = l->lineno;
- else if(r)
- n->lineno = r->lineno;
- else
- n->lineno = lineno;
- newflag = 1;
- return n;
-}
-
-Node*
-new1(int o, Node *l, Node *r)
-{
- Node *n;
-
- n = new(o, l, r);
- n->lineno = nearln;
- return n;
-}
-
-void
-prtree(Node *n, char *s)
-{
-
- print(" == %s ==\n", s);
- prtree1(n, 0, 0);
- print("\n");
-}
-
-void
-prtree1(Node *n, int d, int f)
-{
- int i;
-
- if(f)
- for(i=0; i<d; i++)
- print(" ");
- if(n == Z) {
- print("Z\n");
- return;
- }
- if(n->op == OLIST) {
- prtree1(n->left, d, 0);
- prtree1(n->right, d, 1);
- return;
- }
- d++;
- print("%O", n->op);
- i = 3;
- switch(n->op)
- {
- case ONAME:
- print(" \"%F\"", n);
- print(" %d", n->xoffset);
- i = 0;
- break;
-
- case OINDREG:
- print(" %d(R%d)", n->xoffset, n->reg);
- i = 0;
- break;
-
- case OREGISTER:
- if(n->xoffset)
- print(" %d+R%d", n->xoffset, n->reg);
- else
- print(" R%d", n->reg);
- i = 0;
- break;
-
- case OSTRING:
- print(" \"%s\"", n->cstring);
- i = 0;
- break;
-
- case OLSTRING:
- if(sizeof(TRune) == sizeof(Rune))
- print(" \"%S\"", (Rune*)n->rstring);
- else
- print(" \"...\"");
- i = 0;
- break;
-
- case ODOT:
- case OELEM:
- print(" \"%F\"", n);
- break;
-
- case OCONST:
- if(typefd[n->type->etype])
- print(" \"%.8e\"", n->fconst);
- else
- print(" \"%lld\"", n->vconst);
- i = 0;
- break;
- }
- if(n->addable != 0)
- print(" <%d>", n->addable);
- if(n->type != T)
- print(" %T", n->type);
- if(n->complex != 0)
- print(" (%d)", n->complex);
- print(" %L\n", n->lineno);
- if(i & 2)
- prtree1(n->left, d, 1);
- if(i & 1)
- prtree1(n->right, d, 1);
-}
-
-Type*
-typ(int et, Type *d)
-{
- Type *t;
-
- t = alloc(sizeof(*t));
- t->etype = et;
- t->link = d;
- t->down = T;
- t->sym = S;
- if(et < NTYPE)
- t->width = ewidth[et];
- else
- t->width = -1; // for TDOT or TOLD in prototype
- t->offset = 0;
- t->shift = 0;
- t->nbits = 0;
- t->garb = 0;
- return t;
-}
-
-Type*
-copytyp(Type *t)
-{
- Type *nt;
-
- nt = typ(TXXX, T);
- *nt = *t;
- return nt;
-}
-
-Type*
-garbt(Type *t, int32 b)
-{
- Type *t1;
-
- if(b & BGARB) {
- t1 = copytyp(t);
- t1->garb = simpleg(b);
- return t1;
- }
- return t;
-}
-
-int
-simpleg(int32 b)
-{
-
- b &= BGARB;
- switch(b) {
- case BCONSTNT:
- return GCONSTNT;
- case BVOLATILE:
- return GVOLATILE;
- case BVOLATILE|BCONSTNT:
- return GCONSTNT|GVOLATILE;
- }
- return GXXX;
-}
-
-int
-simplec(int32 b)
-{
-
- b &= BCLASS;
- switch(b) {
- case 0:
- case BREGISTER:
- return CXXX;
- case BAUTO:
- case BAUTO|BREGISTER:
- return CAUTO;
- case BEXTERN:
- return CEXTERN;
- case BEXTERN|BREGISTER:
- return CEXREG;
- case BSTATIC:
- return CSTATIC;
- case BTYPEDEF:
- return CTYPEDEF;
- case BTYPESTR:
- return CTYPESTR;
- }
- diag(Z, "illegal combination of classes %Q", b);
- return CXXX;
-}
-
-Type*
-simplet(int32 b)
-{
-
- b &= ~BCLASS & ~BGARB;
- switch(b) {
- case BCHAR:
- case BCHAR|BSIGNED:
- return types[TCHAR];
-
- case BCHAR|BUNSIGNED:
- return types[TUCHAR];
-
- case BSHORT:
- case BSHORT|BINT:
- case BSHORT|BSIGNED:
- case BSHORT|BINT|BSIGNED:
- return types[TSHORT];
-
- case BUNSIGNED|BSHORT:
- case BUNSIGNED|BSHORT|BINT:
- return types[TUSHORT];
-
- case 0:
- case BINT:
- case BINT|BSIGNED:
- case BSIGNED:
- return types[TINT];
-
- case BUNSIGNED:
- case BUNSIGNED|BINT:
- return types[TUINT];
-
- case BLONG:
- case BLONG|BINT:
- case BLONG|BSIGNED:
- case BLONG|BINT|BSIGNED:
- return types[TLONG];
-
- case BUNSIGNED|BLONG:
- case BUNSIGNED|BLONG|BINT:
- return types[TULONG];
-
- case BVLONG|BLONG:
- case BVLONG|BLONG|BINT:
- case BVLONG|BLONG|BSIGNED:
- case BVLONG|BLONG|BINT|BSIGNED:
- return types[TVLONG];
-
- case BVLONG|BLONG|BUNSIGNED:
- case BVLONG|BLONG|BINT|BUNSIGNED:
- return types[TUVLONG];
-
- case BFLOAT:
- return types[TFLOAT];
-
- case BDOUBLE:
- case BDOUBLE|BLONG:
- case BFLOAT|BLONG:
- return types[TDOUBLE];
-
- case BVOID:
- return types[TVOID];
- }
-
- diag(Z, "illegal combination of types %Q", b);
- return types[TINT];
-}
-
-int
-stcompat(Node *n, Type *t1, Type *t2, int32 ttab[])
-{
- int i;
- uint32 b;
-
- i = 0;
- if(t2 != T)
- i = t2->etype;
- b = 1L << i;
- i = 0;
- if(t1 != T)
- i = t1->etype;
- if(b & ttab[i]) {
- if(ttab == tasign)
- if(b == BSTRUCT || b == BUNION)
- if(!sametype(t1, t2))
- return 1;
- if(n->op != OCAST)
- if(b == BIND && i == TIND)
- if(!sametype(t1, t2))
- return 1;
- return 0;
- }
- return 1;
-}
-
-int
-tcompat(Node *n, Type *t1, Type *t2, int32 ttab[])
-{
-
- if(stcompat(n, t1, t2, ttab)) {
- if(t1 == T)
- diag(n, "incompatible type: \"%T\" for op \"%O\"",
- t2, n->op);
- else
- diag(n, "incompatible types: \"%T\" and \"%T\" for op \"%O\"",
- t1, t2, n->op);
- return 1;
- }
- return 0;
-}
-
-void
-makedot(Node *n, Type *t, int32 o)
-{
- Node *n1, *n2;
-
- if(t->nbits) {
- n1 = new(OXXX, Z, Z);
- *n1 = *n;
- n->op = OBIT;
- n->left = n1;
- n->right = Z;
- n->type = t;
- n->addable = n1->left->addable;
- n = n1;
- }
- n->addable = n->left->addable;
- if(n->addable == 0) {
- n1 = new1(OCONST, Z, Z);
- n1->vconst = o;
- n1->type = types[TLONG];
- n->right = n1;
- n->type = t;
- return;
- }
- n->left->type = t;
- if(o == 0) {
- *n = *n->left;
- return;
- }
- n->type = t;
- n1 = new1(OCONST, Z, Z);
- n1->vconst = o;
- t = typ(TIND, t);
- t->width = types[TIND]->width;
- n1->type = t;
-
- n2 = new1(OADDR, n->left, Z);
- n2->type = t;
-
- n1 = new1(OADD, n1, n2);
- n1->type = t;
-
- n->op = OIND;
- n->left = n1;
- n->right = Z;
-}
-
-Type*
-dotsearch(Sym *s, Type *t, Node *n, int32 *off)
-{
- Type *t1, *xt, *rt;
-
- xt = T;
-
- /*
- * look it up by name
- */
- for(t1 = t; t1 != T; t1 = t1->down)
- if(t1->sym == s) {
- if(xt != T)
- goto ambig;
- xt = t1;
- }
-
- /*
- * look it up by type
- */
- if(s->class == CTYPEDEF || s->class == CTYPESTR)
- for(t1 = t; t1 != T; t1 = t1->down)
- if(t1->sym == S && typesu[t1->etype])
- if(sametype(s->type, t1)) {
- if(xt != T)
- goto ambig;
- xt = t1;
- }
- if(xt != T) {
- *off = xt->offset;
- return xt;
- }
-
- /*
- * look it up in unnamed substructures
- */
- for(t1 = t; t1 != T; t1 = t1->down)
- if(t1->sym == S && typesu[t1->etype]){
- rt = dotsearch(s, t1->link, n, off);
- if(rt != T) {
- if(xt != T)
- goto ambig;
- xt = rt;
- *off += t1->offset;
- }
- }
- return xt;
-
-ambig:
- diag(n, "ambiguous structure element: %s", s->name);
- return xt;
-}
-
-int32
-dotoffset(Type *st, Type *lt, Node *n)
-{
- Type *t;
- Sym *g;
- int32 o, o1;
-
- o = -1;
- /*
- * first try matching at the top level
- * for matching tag names
- */
- g = st->tag;
- if(g != S)
- for(t=lt->link; t!=T; t=t->down)
- if(t->sym == S)
- if(g == t->tag) {
- if(o >= 0)
- goto ambig;
- o = t->offset;
- }
- if(o >= 0)
- return o;
-
- /*
- * second try matching at the top level
- * for similar types
- */
- for(t=lt->link; t!=T; t=t->down)
- if(t->sym == S)
- if(sametype(st, t)) {
- if(o >= 0)
- goto ambig;
- o = t->offset;
- }
- if(o >= 0)
- return o;
-
- /*
- * last try matching sub-levels
- */
- for(t=lt->link; t!=T; t=t->down)
- if(t->sym == S)
- if(typesu[t->etype]) {
- o1 = dotoffset(st, t, n);
- if(o1 >= 0) {
- if(o >= 0)
- goto ambig;
- o = o1 + t->offset;
- }
- }
- return o;
-
-ambig:
- diag(n, "ambiguous unnamed structure element");
- return o;
-}
-
-/*
- * look into tree for floating point constant expressions
- */
-int
-allfloat(Node *n, int flag)
-{
-
- if(n != Z) {
- if(n->type->etype != TDOUBLE)
- return 1;
- switch(n->op) {
- case OCONST:
- if(flag)
- n->type = types[TFLOAT];
- return 1;
- case OADD: /* no need to get more exotic than this */
- case OSUB:
- case OMUL:
- case ODIV:
- if(!allfloat(n->right, flag))
- break;
- case OCAST:
- if(!allfloat(n->left, flag))
- break;
- if(flag)
- n->type = types[TFLOAT];
- return 1;
- }
- }
- return 0;
-}
-
-void
-constas(Node *n, Type *il, Type *ir)
-{
- Type *l, *r;
-
- l = il;
- r = ir;
-
- if(l == T)
- return;
- if(l->garb & GCONSTNT) {
- warn(n, "assignment to a constant type (%T)", il);
- return;
- }
- if(r == T)
- return;
- for(;;) {
- if(l->etype != TIND || r->etype != TIND)
- break;
- l = l->link;
- r = r->link;
- if(l == T || r == T)
- break;
- if(r->garb & GCONSTNT)
- if(!(l->garb & GCONSTNT)) {
- warn(n, "assignment of a constant pointer type (%T)", ir);
- break;
- }
- }
-}
-
-void
-typeext1(Type *st, Node *l)
-{
- if(st->etype == TFLOAT && allfloat(l, 0))
- allfloat(l, 1);
-}
-
-void
-typeext(Type *st, Node *l)
-{
- Type *lt;
- Node *n1, *n2;
- int32 o;
-
- lt = l->type;
- if(lt == T)
- return;
- if(st->etype == TIND && vconst(l) == 0) {
- l->type = st;
- l->vconst = 0;
- return;
- }
- typeext1(st, l);
-
- /*
- * extension of C
- * if assign of struct containing unnamed sub-struct
- * to type of sub-struct, insert the DOT.
- * if assign of *struct containing unnamed substruct
- * to type of *sub-struct, insert the add-offset
- */
- if(typesu[st->etype] && typesu[lt->etype]) {
- o = dotoffset(st, lt, l);
- if(o >= 0) {
- n1 = new1(OXXX, Z, Z);
- *n1 = *l;
- l->op = ODOT;
- l->left = n1;
- l->right = Z;
- makedot(l, st, o);
- }
- return;
- }
- if(st->etype == TIND && typesu[st->link->etype])
- if(lt->etype == TIND && typesu[lt->link->etype]) {
- o = dotoffset(st->link, lt->link, l);
- if(o >= 0) {
- l->type = st;
- if(o == 0)
- return;
- n1 = new1(OXXX, Z, Z);
- *n1 = *l;
- n2 = new1(OCONST, Z, Z);
- n2->vconst = o;
- n2->type = st;
- l->op = OADD;
- l->left = n1;
- l->right = n2;
- }
- return;
- }
-}
-
-/*
- * a cast that generates no code
- * (same size move)
- */
-int
-nocast(Type *t1, Type *t2)
-{
- int i, b;
-
- if(t1->nbits)
- return 0;
- i = 0;
- if(t2 != T)
- i = t2->etype;
- b = 1<<i;
- i = 0;
- if(t1 != T)
- i = t1->etype;
- if(b & ncast[i])
- return 1;
- return 0;
-}
-
-/*
- * a cast that has a noop semantic
- * (small to large, convert)
- */
-int
-nilcast(Type *t1, Type *t2)
-{
- int et1, et2;
-
- if(t1 == T)
- return 0;
- if(t1->nbits)
- return 0;
- if(t2 == T)
- return 0;
- et1 = t1->etype;
- et2 = t2->etype;
- if(et1 == et2)
- return 1;
- if(typefd[et1] && typefd[et2]) {
- if(ewidth[et1] < ewidth[et2])
- return 1;
- return 0;
- }
- if(typechlp[et1] && typechlp[et2]) {
- if(ewidth[et1] < ewidth[et2])
- return 1;
- return 0;
- }
- return 0;
-}
-
-/*
- * "the usual arithmetic conversions are performed"
- */
-void
-arith(Node *n, int f)
-{
- Type *t1, *t2;
- int i, j, k;
- Node *n1;
- int32 w;
-
- t1 = n->left->type;
- if(n->right == Z)
- t2 = t1;
- else
- t2 = n->right->type;
- i = TXXX;
- if(t1 != T)
- i = t1->etype;
- j = TXXX;
- if(t2 != T)
- j = t2->etype;
- k = tab[i][j];
- if(k == TIND) {
- if(i == TIND)
- n->type = t1;
- else
- if(j == TIND)
- n->type = t2;
- } else {
- /* convert up to at least int */
- if(f == 1)
- while(k < TINT)
- k += 2;
- n->type = types[k];
- }
- if(n->op == OSUB)
- if(i == TIND && j == TIND) {
- w = n->right->type->link->width;
- if(w < 1 || n->left->type->link == T || n->left->type->link->width < 1)
- goto bad;
- n->type = types[ewidth[TIND] <= ewidth[TLONG]? TLONG: TVLONG];
- if(0 && ewidth[TIND] > ewidth[TLONG]){
- n1 = new1(OXXX, Z, Z);
- *n1 = *n;
- n->op = OCAST;
- n->left = n1;
- n->right = Z;
- n->type = types[TLONG];
- }
- if(w > 1) {
- n1 = new1(OXXX, Z, Z);
- *n1 = *n;
- n->op = ODIV;
- n->left = n1;
- n1 = new1(OCONST, Z, Z);
- n1->vconst = w;
- n1->type = n->type;
- n->right = n1;
- w = vlog(n1);
- if(w >= 0) {
- n->op = OASHR;
- n1->vconst = w;
- }
- }
- return;
- }
- if(!sametype(n->type, n->left->type)) {
- n->left = new1(OCAST, n->left, Z);
- n->left->type = n->type;
- if(n->type->etype == TIND) {
- w = n->type->link->width;
- if(w < 1) {
- snap(n->type->link);
- w = n->type->link->width;
- if(w < 1)
- goto bad;
- }
- if(w > 1) {
- n1 = new1(OCONST, Z, Z);
- n1->vconst = w;
- n1->type = n->type;
- n->left = new1(OMUL, n->left, n1);
- n->left->type = n->type;
- }
- }
- }
- if(n->right != Z)
- if(!sametype(n->type, n->right->type)) {
- n->right = new1(OCAST, n->right, Z);
- n->right->type = n->type;
- if(n->type->etype == TIND) {
- w = n->type->link->width;
- if(w < 1) {
- snap(n->type->link);
- w = n->type->link->width;
- if(w < 1)
- goto bad;
- }
- if(w != 1) {
- n1 = new1(OCONST, Z, Z);
- n1->vconst = w;
- n1->type = n->type;
- n->right = new1(OMUL, n->right, n1);
- n->right->type = n->type;
- }
- }
- }
- return;
-bad:
- diag(n, "pointer addition not fully declared: %T", n->type->link);
-}
-
-/*
- * try to rewrite shift & mask
- */
-void
-simplifyshift(Node *n)
-{
- uint32 c3;
- int o, s1, s2, c1, c2;
-
- if(!typechlp[n->type->etype])
- return;
- switch(n->op) {
- default:
- return;
- case OASHL:
- s1 = 0;
- break;
- case OLSHR:
- s1 = 1;
- break;
- case OASHR:
- s1 = 2;
- break;
- }
- if(n->right->op != OCONST)
- return;
- if(n->left->op != OAND)
- return;
- if(n->left->right->op != OCONST)
- return;
- switch(n->left->left->op) {
- default:
- return;
- case OASHL:
- s2 = 0;
- break;
- case OLSHR:
- s2 = 1;
- break;
- case OASHR:
- s2 = 2;
- break;
- }
- if(n->left->left->right->op != OCONST)
- return;
-
- c1 = n->right->vconst;
- c2 = n->left->left->right->vconst;
- c3 = n->left->right->vconst;
-
- o = n->op;
- switch((s1<<3)|s2) {
- case 000: /* (((e <<u c2) & c3) <<u c1) */
- c3 >>= c2;
- c1 += c2;
- if(c1 >= 32)
- break;
- goto rewrite1;
-
- case 002: /* (((e >>s c2) & c3) <<u c1) */
- if(topbit(c3) >= (32-c2))
- break;
- case 001: /* (((e >>u c2) & c3) <<u c1) */
- if(c1 > c2) {
- c3 <<= c2;
- c1 -= c2;
- o = OASHL;
- goto rewrite1;
- }
- c3 <<= c1;
- if(c1 == c2)
- goto rewrite0;
- c1 = c2-c1;
- o = OLSHR;
- goto rewrite2;
-
- case 022: /* (((e >>s c2) & c3) >>s c1) */
- if(c2 <= 0)
- break;
- case 012: /* (((e >>s c2) & c3) >>u c1) */
- if(topbit(c3) >= (32-c2))
- break;
- goto s11;
- case 021: /* (((e >>u c2) & c3) >>s c1) */
- if(topbit(c3) >= 31 && c2 <= 0)
- break;
- goto s11;
- case 011: /* (((e >>u c2) & c3) >>u c1) */
- s11:
- c3 <<= c2;
- c1 += c2;
- if(c1 >= 32)
- break;
- o = OLSHR;
- goto rewrite1;
-
- case 020: /* (((e <<u c2) & c3) >>s c1) */
- if(topbit(c3) >= 31)
- break;
- case 010: /* (((e <<u c2) & c3) >>u c1) */
- c3 >>= c1;
- if(c1 == c2)
- goto rewrite0;
- if(c1 > c2) {
- c1 -= c2;
- goto rewrite2;
- }
- c1 = c2 - c1;
- o = OASHL;
- goto rewrite2;
- }
- return;
-
-rewrite0: /* get rid of both shifts */
-if(debug['<'])prtree(n, "rewrite0");
- *n = *n->left;
- n->left = n->left->left;
- n->right->vconst = c3;
- return;
-rewrite1: /* get rid of lower shift */
-if(debug['<'])prtree(n, "rewrite1");
- n->left->left = n->left->left->left;
- n->left->right->vconst = c3;
- n->right->vconst = c1;
- n->op = o;
- return;
-rewrite2: /* get rid of upper shift */
-if(debug['<'])prtree(n, "rewrite2");
- *n = *n->left;
- n->right->vconst = c3;
- n->left->right->vconst = c1;
- n->left->op = o;
-}
-
-int
-side(Node *n)
-{
-
-loop:
- if(n != Z)
- switch(n->op) {
- case OCAST:
- case ONOT:
- case OADDR:
- case OIND:
- n = n->left;
- goto loop;
-
- case OCOND:
- if(side(n->left))
- break;
- n = n->right;
-
- case OEQ:
- case ONE:
- case OLT:
- case OGE:
- case OGT:
- case OLE:
- case OADD:
- case OSUB:
- case OMUL:
- case OLMUL:
- case ODIV:
- case OLDIV:
- case OLSHR:
- case OASHL:
- case OASHR:
- case OAND:
- case OOR:
- case OXOR:
- case OMOD:
- case OLMOD:
- case OANDAND:
- case OOROR:
- case OCOMMA:
- case ODOT:
- if(side(n->left))
- break;
- n = n->right;
- goto loop;
-
- case OSIGN:
- case OSIZE:
- case OCONST:
- case OSTRING:
- case OLSTRING:
- case ONAME:
- return 0;
- }
- return 1;
-}
-
-int
-vconst(Node *n)
-{
- int i;
-
- if(n == Z)
- goto no;
- if(n->op != OCONST)
- goto no;
- if(n->type == T)
- goto no;
- switch(n->type->etype)
- {
- case TFLOAT:
- case TDOUBLE:
- i = 100;
- if(n->fconst > i || n->fconst < -i)
- goto no;
- i = n->fconst;
- if(i != n->fconst)
- goto no;
- return i;
-
- case TVLONG:
- case TUVLONG:
- i = n->vconst;
- if(i != n->vconst)
- goto no;
- return i;
-
- case TCHAR:
- case TUCHAR:
- case TSHORT:
- case TUSHORT:
- case TINT:
- case TUINT:
- case TLONG:
- case TULONG:
- case TIND:
- i = n->vconst;
- if(i != n->vconst)
- goto no;
- return i;
- }
-no:
- return -159; /* first uninteresting constant */
-}
-
-/*
- * return log(n) if n is a power of 2 constant
- */
-int
-xlog2(uvlong v)
-{
- int s, i;
- uvlong m;
-
- s = 0;
- m = MASK(8*sizeof(uvlong));
- for(i=32; i; i>>=1) {
- m >>= i;
- if(!(v & m)) {
- v >>= i;
- s += i;
- }
- }
- if(v == 1)
- return s;
- return -1;
-}
-
-int
-vlog(Node *n)
-{
- if(n->op != OCONST)
- goto bad;
- if(typefd[n->type->etype])
- goto bad;
-
- return xlog2(n->vconst);
-
-bad:
- return -1;
-}
-
-int
-topbit(uint32 v)
-{
- int i;
-
- for(i = -1; v; i++)
- v >>= 1;
- return i;
-}
-
-/*
- * try to cast a constant down
- * rather than cast a variable up
- * example:
- * if(c == 'a')
- */
-void
-relcon(Node *l, Node *r)
-{
- vlong v;
-
- if(l->op != OCONST)
- return;
- if(r->op != OCAST)
- return;
- if(!nilcast(r->left->type, r->type))
- return;
- switch(r->type->etype) {
- default:
- return;
- case TCHAR:
- case TUCHAR:
- case TSHORT:
- case TUSHORT:
- v = convvtox(l->vconst, r->type->etype);
- if(v != l->vconst)
- return;
- break;
- }
- l->type = r->left->type;
- *r = *r->left;
-}
-
-int
-relindex(int o)
-{
-
- switch(o) {
- default:
- diag(Z, "bad in relindex: %O", o);
- case OEQ: return 0;
- case ONE: return 1;
- case OLE: return 2;
- case OLS: return 3;
- case OLT: return 4;
- case OLO: return 5;
- case OGE: return 6;
- case OHS: return 7;
- case OGT: return 8;
- case OHI: return 9;
- }
-}
-
-Node*
-invert(Node *n)
-{
- Node *i;
-
- if(n == Z || n->op != OLIST)
- return n;
- i = n;
- for(n = n->left; n != Z; n = n->left) {
- if(n->op != OLIST)
- break;
- i->left = n->right;
- n->right = i;
- i = n;
- }
- i->left = n;
- return i;
-}
-
-int
-bitno(int32 b)
-{
- int i;
-
- for(i=0; i<32; i++)
- if(b & (1L<<i))
- return i;
- diag(Z, "bad in bitno");
- return 0;
-}
-
-int32
-typebitor(int32 a, int32 b)
-{
- int32 c;
-
- c = a | b;
- if(a & b)
- if((a & b) == BLONG)
- c |= BVLONG; /* long long => vlong */
- else
- warn(Z, "once is enough: %Q", a & b);
- return c;
-}
-
-void
-diag(Node *n, char *fmt, ...)
-{
- char buf[STRINGSZ];
- va_list arg;
-
- va_start(arg, fmt);
- vseprint(buf, buf+sizeof(buf), fmt, arg);
- va_end(arg);
- Bprint(&diagbuf, "%L %s\n", (n==Z)? nearln: n->lineno, buf);
-
- if(debug['X']){
- Bflush(&diagbuf);
- abort();
- }
- if(n != Z)
- if(debug['v'])
- prtree(n, "diagnostic");
-
- nerrors++;
- if(nerrors > 10) {
- Bprint(&diagbuf, "too many errors\n");
- errorexit();
- }
-}
-
-void
-warn(Node *n, char *fmt, ...)
-{
- char buf[STRINGSZ];
- va_list arg;
-
- if(debug['w']) {
- Bprint(&diagbuf, "warning: ");
- va_start(arg, fmt);
- vseprint(buf, buf+sizeof(buf), fmt, arg);
- va_end(arg);
- Bprint(&diagbuf, "%L %s\n", (n==Z)? nearln: n->lineno, buf);
-
- if(n != Z)
- if(debug['v'])
- prtree(n, "warning");
- }
-}
-
-void
-yyerror(char *fmt, ...)
-{
- char buf[STRINGSZ];
- va_list arg;
-
- /*
- * hack to intercept message from yaccpar
- */
- if(strcmp(fmt, "syntax error") == 0) {
- yyerror("syntax error, last name: %s", symb);
- return;
- }
- va_start(arg, fmt);
- vseprint(buf, buf+sizeof(buf), fmt, arg);
- va_end(arg);
- Bprint(&diagbuf, "%L %s\n", lineno, buf);
- nerrors++;
- if(nerrors > 10) {
- Bprint(&diagbuf, "too many errors\n");
- errorexit();
- }
-}
-
-void
-fatal(Node *n, char *fmt, ...)
-{
- char buf[STRINGSZ];
- va_list arg;
-
- va_start(arg, fmt);
- vseprint(buf, buf+sizeof(buf), fmt, arg);
- va_end(arg);
- Bprint(&diagbuf, "%L %s\n", (n==Z)? nearln: n->lineno, buf);
-
- if(debug['X']){
- Bflush(&diagbuf);
- abort();
- }
- if(n != Z)
- if(debug['v'])
- prtree(n, "diagnostic");
-
- nerrors++;
- errorexit();
-}
-
-uint32 thash1 = 0x2edab8c9;
-uint32 thash2 = 0x1dc74fb8;
-uint32 thash3 = 0x1f241331;
-uint32 thash[NALLTYPES];
-Init thashinit[] =
-{
- TXXX, 0x17527bbd, 0,
- TCHAR, 0x5cedd32b, 0,
- TUCHAR, 0x552c4454, 0,
- TSHORT, 0x63040b4b, 0,
- TUSHORT, 0x32a45878, 0,
- TINT, 0x4151d5bd, 0,
- TUINT, 0x5ae707d6, 0,
- TLONG, 0x5ef20f47, 0,
- TULONG, 0x36d8eb8f, 0,
- TVLONG, 0x6e5e9590, 0,
- TUVLONG, 0x75910105, 0,
- TFLOAT, 0x25fd7af1, 0,
- TDOUBLE, 0x7c40a1b2, 0,
- TIND, 0x1b832357, 0,
- TFUNC, 0x6babc9cb, 0,
- TARRAY, 0x7c50986d, 0,
- TVOID, 0x44112eff, 0,
- TSTRUCT, 0x7c2da3bf, 0,
- TUNION, 0x3eb25e98, 0,
- TENUM, 0x44b54f61, 0,
- TFILE, 0x19242ac3, 0,
- TOLD, 0x22b15988, 0,
- TDOT, 0x0204f6b3, 0,
- -1, 0, 0,
-};
-
-char* bnames[NALIGN];
-Init bnamesinit[] =
-{
- Axxx, 0, "Axxx",
- Ael1, 0, "el1",
- Ael2, 0, "el2",
- Asu2, 0, "su2",
- Aarg0, 0, "arg0",
- Aarg1, 0, "arg1",
- Aarg2, 0, "arg2",
- Aaut3, 0, "aut3",
- -1, 0, 0,
-};
-
-char* tnames[NALLTYPES];
-Init tnamesinit[] =
-{
- TXXX, 0, "TXXX",
- TCHAR, 0, "CHAR",
- TUCHAR, 0, "UCHAR",
- TSHORT, 0, "SHORT",
- TUSHORT, 0, "USHORT",
- TINT, 0, "INT",
- TUINT, 0, "UINT",
- TLONG, 0, "LONG",
- TULONG, 0, "ULONG",
- TVLONG, 0, "VLONG",
- TUVLONG, 0, "UVLONG",
- TFLOAT, 0, "FLOAT",
- TDOUBLE, 0, "DOUBLE",
- TIND, 0, "IND",
- TFUNC, 0, "FUNC",
- TARRAY, 0, "ARRAY",
- TVOID, 0, "VOID",
- TSTRUCT, 0, "STRUCT",
- TUNION, 0, "UNION",
- TENUM, 0, "ENUM",
- TFILE, 0, "FILE",
- TOLD, 0, "OLD",
- TDOT, 0, "DOT",
- -1, 0, 0,
-};
-
-char* gnames[NGTYPES];
-Init gnamesinit[] =
-{
- GXXX, 0, "GXXX",
- GCONSTNT, 0, "CONST",
- GVOLATILE, 0, "VOLATILE",
- GVOLATILE|GCONSTNT, 0, "CONST-VOLATILE",
- -1, 0, 0,
-};
-
-char* qnames[NALLTYPES];
-Init qnamesinit[] =
-{
- TXXX, 0, "TXXX",
- TCHAR, 0, "CHAR",
- TUCHAR, 0, "UCHAR",
- TSHORT, 0, "SHORT",
- TUSHORT, 0, "USHORT",
- TINT, 0, "INT",
- TUINT, 0, "UINT",
- TLONG, 0, "LONG",
- TULONG, 0, "ULONG",
- TVLONG, 0, "VLONG",
- TUVLONG, 0, "UVLONG",
- TFLOAT, 0, "FLOAT",
- TDOUBLE, 0, "DOUBLE",
- TIND, 0, "IND",
- TFUNC, 0, "FUNC",
- TARRAY, 0, "ARRAY",
- TVOID, 0, "VOID",
- TSTRUCT, 0, "STRUCT",
- TUNION, 0, "UNION",
- TENUM, 0, "ENUM",
-
- TAUTO, 0, "AUTO",
- TEXTERN, 0, "EXTERN",
- TSTATIC, 0, "STATIC",
- TTYPEDEF, 0, "TYPEDEF",
- TTYPESTR, 0, "TYPESTR",
- TREGISTER, 0, "REGISTER",
- TCONSTNT, 0, "CONSTNT",
- TVOLATILE, 0, "VOLATILE",
- TUNSIGNED, 0, "UNSIGNED",
- TSIGNED, 0, "SIGNED",
- TDOT, 0, "DOT",
- TFILE, 0, "FILE",
- TOLD, 0, "OLD",
- -1, 0, 0,
-};
-char* cnames[NCTYPES];
-Init cnamesinit[] =
-{
- CXXX, 0, "CXXX",
- CAUTO, 0, "AUTO",
- CEXTERN, 0, "EXTERN",
- CGLOBL, 0, "GLOBL",
- CSTATIC, 0, "STATIC",
- CLOCAL, 0, "LOCAL",
- CTYPEDEF, 0, "TYPEDEF",
- CTYPESTR, 0, "TYPESTR",
- CPARAM, 0, "PARAM",
- CSELEM, 0, "SELEM",
- CLABEL, 0, "LABEL",
- CEXREG, 0, "EXREG",
- -1, 0, 0,
-};
-
-char* onames[OEND+1];
-Init onamesinit[] =
-{
- OXXX, 0, "OXXX",
- OADD, 0, "ADD",
- OADDR, 0, "ADDR",
- OAND, 0, "AND",
- OANDAND, 0, "ANDAND",
- OARRAY, 0, "ARRAY",
- OAS, 0, "AS",
- OASI, 0, "ASI",
- OASADD, 0, "ASADD",
- OASAND, 0, "ASAND",
- OASASHL, 0, "ASASHL",
- OASASHR, 0, "ASASHR",
- OASDIV, 0, "ASDIV",
- OASHL, 0, "ASHL",
- OASHR, 0, "ASHR",
- OASLDIV, 0, "ASLDIV",
- OASLMOD, 0, "ASLMOD",
- OASLMUL, 0, "ASLMUL",
- OASLSHR, 0, "ASLSHR",
- OASMOD, 0, "ASMOD",
- OASMUL, 0, "ASMUL",
- OASOR, 0, "ASOR",
- OASSUB, 0, "ASSUB",
- OASXOR, 0, "ASXOR",
- OBIT, 0, "BIT",
- OBREAK, 0, "BREAK",
- OCASE, 0, "CASE",
- OCAST, 0, "CAST",
- OCOMMA, 0, "COMMA",
- OCOND, 0, "COND",
- OCONST, 0, "CONST",
- OCONTINUE, 0, "CONTINUE",
- ODIV, 0, "DIV",
- ODOT, 0, "DOT",
- ODOTDOT, 0, "DOTDOT",
- ODWHILE, 0, "DWHILE",
- OENUM, 0, "ENUM",
- OEQ, 0, "EQ",
- OEXREG, 0, "EXREG",
- OFOR, 0, "FOR",
- OFUNC, 0, "FUNC",
- OGE, 0, "GE",
- OGOTO, 0, "GOTO",
- OGT, 0, "GT",
- OHI, 0, "HI",
- OHS, 0, "HS",
- OIF, 0, "IF",
- OIND, 0, "IND",
- OINDREG, 0, "INDREG",
- OINIT, 0, "INIT",
- OLABEL, 0, "LABEL",
- OLDIV, 0, "LDIV",
- OLE, 0, "LE",
- OLIST, 0, "LIST",
- OLMOD, 0, "LMOD",
- OLMUL, 0, "LMUL",
- OLO, 0, "LO",
- OLS, 0, "LS",
- OLSHR, 0, "LSHR",
- OLT, 0, "LT",
- OMOD, 0, "MOD",
- OMUL, 0, "MUL",
- ONAME, 0, "NAME",
- ONE, 0, "NE",
- ONOT, 0, "NOT",
- OOR, 0, "OR",
- OOROR, 0, "OROR",
- OPOSTDEC, 0, "POSTDEC",
- OPOSTINC, 0, "POSTINC",
- OPREDEC, 0, "PREDEC",
- OPREINC, 0, "PREINC",
- OPREFETCH, 0, "PREFETCH",
- OPROTO, 0, "PROTO",
- OREGISTER, 0, "REGISTER",
- ORETURN, 0, "RETURN",
- OSET, 0, "SET",
- OSIGN, 0, "SIGN",
- OSIZE, 0, "SIZE",
- OSTRING, 0, "STRING",
- OLSTRING, 0, "LSTRING",
- OSTRUCT, 0, "STRUCT",
- OSUB, 0, "SUB",
- OSWITCH, 0, "SWITCH",
- OUNION, 0, "UNION",
- OUSED, 0, "USED",
- OWHILE, 0, "WHILE",
- OXOR, 0, "XOR",
- OPOS, 0, "POS",
- ONEG, 0, "NEG",
- OCOM, 0, "COM",
- OELEM, 0, "ELEM",
- OTST, 0, "TST",
- OINDEX, 0, "INDEX",
- OFAS, 0, "FAS",
- OREGPAIR, 0, "REGPAIR",
- OROTL, 0, "ROTL",
- OEND, 0, "END",
- -1, 0, 0,
-};
-
-/* OEQ, ONE, OLE, OLS, OLT, OLO, OGE, OHS, OGT, OHI */
-uchar comrel[12] =
-{
- ONE, OEQ, OGT, OHI, OGE, OHS, OLT, OLO, OLE, OLS,
-};
-uchar invrel[12] =
-{
- OEQ, ONE, OGE, OHS, OGT, OHI, OLE, OLS, OLT, OLO,
-};
-uchar logrel[12] =
-{
- OEQ, ONE, OLS, OLS, OLO, OLO, OHS, OHS, OHI, OHI,
-};
-
-uchar typei[NALLTYPES];
-int typeiinit[] =
-{
- TCHAR, TUCHAR, TSHORT, TUSHORT, TINT, TUINT, TLONG, TULONG, TVLONG, TUVLONG, -1,
-};
-uchar typeu[NALLTYPES];
-int typeuinit[] =
-{
- TUCHAR, TUSHORT, TUINT, TULONG, TUVLONG, TIND, -1,
-};
-
-uchar typesuv[NALLTYPES];
-int typesuvinit[] =
-{
- TVLONG, TUVLONG, TSTRUCT, TUNION, -1,
-};
-
-uchar typeilp[NALLTYPES];
-int typeilpinit[] =
-{
- TINT, TUINT, TLONG, TULONG, TIND, -1
-};
-
-uchar typechl[NALLTYPES];
-uchar typechlv[NALLTYPES];
-uchar typechlvp[NALLTYPES];
-int typechlinit[] =
-{
- TCHAR, TUCHAR, TSHORT, TUSHORT, TINT, TUINT, TLONG, TULONG, -1,
-};
-
-uchar typechlp[NALLTYPES];
-int typechlpinit[] =
-{
- TCHAR, TUCHAR, TSHORT, TUSHORT, TINT, TUINT, TLONG, TULONG, TIND, -1,
-};
-
-uchar typechlpfd[NALLTYPES];
-int typechlpfdinit[] =
-{
- TCHAR, TUCHAR, TSHORT, TUSHORT, TINT, TUINT, TLONG, TULONG, TFLOAT, TDOUBLE, TIND, -1,
-};
-
-uchar typec[NALLTYPES];
-int typecinit[] =
-{
- TCHAR, TUCHAR, -1
-};
-
-uchar typeh[NALLTYPES];
-int typehinit[] =
-{
- TSHORT, TUSHORT, -1,
-};
-
-uchar typeil[NALLTYPES];
-int typeilinit[] =
-{
- TINT, TUINT, TLONG, TULONG, -1,
-};
-
-uchar typev[NALLTYPES];
-int typevinit[] =
-{
- TVLONG, TUVLONG, -1,
-};
-
-uchar typefd[NALLTYPES];
-int typefdinit[] =
-{
- TFLOAT, TDOUBLE, -1,
-};
-
-uchar typeaf[NALLTYPES];
-int typeafinit[] =
-{
- TFUNC, TARRAY, -1,
-};
-
-uchar typesu[NALLTYPES];
-int typesuinit[] =
-{
- TSTRUCT, TUNION, -1,
-};
-
-int32 tasign[NALLTYPES];
-Init tasigninit[] =
-{
- TCHAR, BNUMBER, 0,
- TUCHAR, BNUMBER, 0,
- TSHORT, BNUMBER, 0,
- TUSHORT, BNUMBER, 0,
- TINT, BNUMBER, 0,
- TUINT, BNUMBER, 0,
- TLONG, BNUMBER, 0,
- TULONG, BNUMBER, 0,
- TVLONG, BNUMBER, 0,
- TUVLONG, BNUMBER, 0,
- TFLOAT, BNUMBER, 0,
- TDOUBLE, BNUMBER, 0,
- TIND, BIND, 0,
- TSTRUCT, BSTRUCT, 0,
- TUNION, BUNION, 0,
- -1, 0, 0,
-};
-
-int32 tasadd[NALLTYPES];
-Init tasaddinit[] =
-{
- TCHAR, BNUMBER, 0,
- TUCHAR, BNUMBER, 0,
- TSHORT, BNUMBER, 0,
- TUSHORT, BNUMBER, 0,
- TINT, BNUMBER, 0,
- TUINT, BNUMBER, 0,
- TLONG, BNUMBER, 0,
- TULONG, BNUMBER, 0,
- TVLONG, BNUMBER, 0,
- TUVLONG, BNUMBER, 0,
- TFLOAT, BNUMBER, 0,
- TDOUBLE, BNUMBER, 0,
- TIND, BINTEGER, 0,
- -1, 0, 0,
-};
-
-int32 tcast[NALLTYPES];
-Init tcastinit[] =
-{
- TCHAR, BNUMBER|BIND|BVOID, 0,
- TUCHAR, BNUMBER|BIND|BVOID, 0,
- TSHORT, BNUMBER|BIND|BVOID, 0,
- TUSHORT, BNUMBER|BIND|BVOID, 0,
- TINT, BNUMBER|BIND|BVOID, 0,
- TUINT, BNUMBER|BIND|BVOID, 0,
- TLONG, BNUMBER|BIND|BVOID, 0,
- TULONG, BNUMBER|BIND|BVOID, 0,
- TVLONG, BNUMBER|BIND|BVOID, 0,
- TUVLONG, BNUMBER|BIND|BVOID, 0,
- TFLOAT, BNUMBER|BVOID, 0,
- TDOUBLE, BNUMBER|BVOID, 0,
- TIND, BINTEGER|BIND|BVOID, 0,
- TVOID, BVOID, 0,
- TSTRUCT, BSTRUCT|BVOID, 0,
- TUNION, BUNION|BVOID, 0,
- -1, 0, 0,
-};
-
-int32 tadd[NALLTYPES];
-Init taddinit[] =
-{
- TCHAR, BNUMBER|BIND, 0,
- TUCHAR, BNUMBER|BIND, 0,
- TSHORT, BNUMBER|BIND, 0,
- TUSHORT, BNUMBER|BIND, 0,
- TINT, BNUMBER|BIND, 0,
- TUINT, BNUMBER|BIND, 0,
- TLONG, BNUMBER|BIND, 0,
- TULONG, BNUMBER|BIND, 0,
- TVLONG, BNUMBER|BIND, 0,
- TUVLONG, BNUMBER|BIND, 0,
- TFLOAT, BNUMBER, 0,
- TDOUBLE, BNUMBER, 0,
- TIND, BINTEGER, 0,
- -1, 0, 0,
-};
-
-int32 tsub[NALLTYPES];
-Init tsubinit[] =
-{
- TCHAR, BNUMBER, 0,
- TUCHAR, BNUMBER, 0,
- TSHORT, BNUMBER, 0,
- TUSHORT, BNUMBER, 0,
- TINT, BNUMBER, 0,
- TUINT, BNUMBER, 0,
- TLONG, BNUMBER, 0,
- TULONG, BNUMBER, 0,
- TVLONG, BNUMBER, 0,
- TUVLONG, BNUMBER, 0,
- TFLOAT, BNUMBER, 0,
- TDOUBLE, BNUMBER, 0,
- TIND, BINTEGER|BIND, 0,
- -1, 0, 0,
-};
-
-int32 tmul[NALLTYPES];
-Init tmulinit[] =
-{
- TCHAR, BNUMBER, 0,
- TUCHAR, BNUMBER, 0,
- TSHORT, BNUMBER, 0,
- TUSHORT, BNUMBER, 0,
- TINT, BNUMBER, 0,
- TUINT, BNUMBER, 0,
- TLONG, BNUMBER, 0,
- TULONG, BNUMBER, 0,
- TVLONG, BNUMBER, 0,
- TUVLONG, BNUMBER, 0,
- TFLOAT, BNUMBER, 0,
- TDOUBLE, BNUMBER, 0,
- -1, 0, 0,
-};
-
-int32 tand[NALLTYPES];
-Init tandinit[] =
-{
- TCHAR, BINTEGER, 0,
- TUCHAR, BINTEGER, 0,
- TSHORT, BINTEGER, 0,
- TUSHORT, BINTEGER, 0,
- TINT, BNUMBER, 0,
- TUINT, BNUMBER, 0,
- TLONG, BINTEGER, 0,
- TULONG, BINTEGER, 0,
- TVLONG, BINTEGER, 0,
- TUVLONG, BINTEGER, 0,
- -1, 0, 0,
-};
-
-int32 trel[NALLTYPES];
-Init trelinit[] =
-{
- TCHAR, BNUMBER, 0,
- TUCHAR, BNUMBER, 0,
- TSHORT, BNUMBER, 0,
- TUSHORT, BNUMBER, 0,
- TINT, BNUMBER, 0,
- TUINT, BNUMBER, 0,
- TLONG, BNUMBER, 0,
- TULONG, BNUMBER, 0,
- TVLONG, BNUMBER, 0,
- TUVLONG, BNUMBER, 0,
- TFLOAT, BNUMBER, 0,
- TDOUBLE, BNUMBER, 0,
- TIND, BIND, 0,
- -1, 0, 0,
-};
-
-int32 tfunct[1] =
-{
- BFUNC,
-};
-
-int32 tindir[1] =
-{
- BIND,
-};
-
-int32 tdot[1] =
-{
- BSTRUCT|BUNION,
-};
-
-int32 tnot[1] =
-{
- BNUMBER|BIND,
-};
-
-int32 targ[1] =
-{
- BNUMBER|BIND|BSTRUCT|BUNION,
-};
-
-uchar tab[NTYPE][NTYPE] =
-{
-/*TXXX*/ { 0,
- },
-
-/*TCHAR*/ { 0, TCHAR, TUCHAR, TSHORT, TUSHORT, TINT, TUINT, TLONG,
- TULONG, TVLONG, TUVLONG, TFLOAT, TDOUBLE, TIND,
- },
-/*TUCHAR*/ { 0, TUCHAR, TUCHAR, TUSHORT, TUSHORT, TUINT, TUINT, TULONG,
- TULONG, TUVLONG, TUVLONG, TFLOAT, TDOUBLE, TIND,
- },
-/*TSHORT*/ { 0, TSHORT, TUSHORT, TSHORT, TUSHORT, TINT, TUINT, TLONG,
- TULONG, TVLONG, TUVLONG, TFLOAT, TDOUBLE, TIND,
- },
-/*TUSHORT*/ { 0, TUSHORT, TUSHORT, TUSHORT, TUSHORT, TUINT, TUINT, TULONG,
- TULONG, TUVLONG, TUVLONG, TFLOAT, TDOUBLE, TIND,
- },
-/*TINT*/ { 0, TINT, TUINT, TINT, TUINT, TINT, TUINT, TLONG,
- TULONG, TVLONG, TUVLONG, TFLOAT, TDOUBLE, TIND,
- },
-/*TUINT*/ { 0, TUINT, TUINT, TUINT, TUINT, TUINT, TUINT, TULONG,
- TULONG, TUVLONG, TUVLONG, TFLOAT, TDOUBLE, TIND,
- },
-/*TLONG*/ { 0, TLONG, TULONG, TLONG, TULONG, TLONG, TULONG, TLONG,
- TULONG, TVLONG, TUVLONG, TFLOAT, TDOUBLE, TIND,
- },
-/*TULONG*/ { 0, TULONG, TULONG, TULONG, TULONG, TULONG, TULONG, TULONG,
- TULONG, TUVLONG, TUVLONG, TFLOAT, TDOUBLE, TIND,
- },
-/*TVLONG*/ { 0, TVLONG, TUVLONG, TVLONG, TUVLONG, TVLONG, TUVLONG, TVLONG,
- TUVLONG, TVLONG, TUVLONG, TFLOAT, TDOUBLE, TIND,
- },
-/*TUVLONG*/ { 0, TUVLONG, TUVLONG, TUVLONG, TUVLONG, TUVLONG, TUVLONG, TUVLONG,
- TUVLONG, TUVLONG, TUVLONG, TFLOAT, TDOUBLE, TIND,
- },
-/*TFLOAT*/ { 0, TFLOAT, TFLOAT, TFLOAT, TFLOAT, TFLOAT, TFLOAT, TFLOAT,
- TFLOAT, TFLOAT, TFLOAT, TFLOAT, TDOUBLE, TIND,
- },
-/*TDOUBLE*/ { 0, TDOUBLE, TDOUBLE, TDOUBLE, TDOUBLE, TDOUBLE, TDOUBLE, TDOUBLE,
- TDOUBLE, TDOUBLE, TDOUBLE, TFLOAT, TDOUBLE, TIND,
- },
-/*TIND*/ { 0, TIND, TIND, TIND, TIND, TIND, TIND, TIND,
- TIND, TIND, TIND, TIND, TIND, TIND,
- },
-};
-
-void
-urk(char *name, int max, int i)
-{
- if(i >= max) {
- fprint(2, "bad tinit: %s %d>=%d\n", name, i, max);
- exits("init");
- }
-}
-
-void
-tinit(void)
-{
- int *ip;
- Init *p;
-
- for(p=thashinit; p->code >= 0; p++) {
- urk("thash", nelem(thash), p->code);
- thash[p->code] = p->value;
- }
- for(p=bnamesinit; p->code >= 0; p++) {
- urk("bnames", nelem(bnames), p->code);
- bnames[p->code] = p->s;
- }
- for(p=tnamesinit; p->code >= 0; p++) {
- urk("tnames", nelem(tnames), p->code);
- tnames[p->code] = p->s;
- }
- for(p=gnamesinit; p->code >= 0; p++) {
- urk("gnames", nelem(gnames), p->code);
- gnames[p->code] = p->s;
- }
- for(p=qnamesinit; p->code >= 0; p++) {
- urk("qnames", nelem(qnames), p->code);
- qnames[p->code] = p->s;
- }
- for(p=cnamesinit; p->code >= 0; p++) {
- urk("cnames", nelem(cnames), p->code);
- cnames[p->code] = p->s;
- }
- for(p=onamesinit; p->code >= 0; p++) {
- urk("onames", nelem(onames), p->code);
- onames[p->code] = p->s;
- }
- for(ip=typeiinit; *ip>=0; ip++) {
- urk("typei", nelem(typei), *ip);
- typei[*ip] = 1;
- }
- for(ip=typeuinit; *ip>=0; ip++) {
- urk("typeu", nelem(typeu), *ip);
- typeu[*ip] = 1;
- }
- for(ip=typesuvinit; *ip>=0; ip++) {
- urk("typesuv", nelem(typesuv), *ip);
- typesuv[*ip] = 1;
- }
- for(ip=typeilpinit; *ip>=0; ip++) {
- urk("typeilp", nelem(typeilp), *ip);
- typeilp[*ip] = 1;
- }
- for(ip=typechlinit; *ip>=0; ip++) {
- urk("typechl", nelem(typechl), *ip);
- typechl[*ip] = 1;
- typechlv[*ip] = 1;
- typechlvp[*ip] = 1;
- }
- for(ip=typechlpinit; *ip>=0; ip++) {
- urk("typechlp", nelem(typechlp), *ip);
- typechlp[*ip] = 1;
- typechlvp[*ip] = 1;
- }
- for(ip=typechlpfdinit; *ip>=0; ip++) {
- urk("typechlpfd", nelem(typechlpfd), *ip);
- typechlpfd[*ip] = 1;
- }
- for(ip=typecinit; *ip>=0; ip++) {
- urk("typec", nelem(typec), *ip);
- typec[*ip] = 1;
- }
- for(ip=typehinit; *ip>=0; ip++) {
- urk("typeh", nelem(typeh), *ip);
- typeh[*ip] = 1;
- }
- for(ip=typeilinit; *ip>=0; ip++) {
- urk("typeil", nelem(typeil), *ip);
- typeil[*ip] = 1;
- }
- for(ip=typevinit; *ip>=0; ip++) {
- urk("typev", nelem(typev), *ip);
- typev[*ip] = 1;
- typechlv[*ip] = 1;
- typechlvp[*ip] = 1;
- }
- for(ip=typefdinit; *ip>=0; ip++) {
- urk("typefd", nelem(typefd), *ip);
- typefd[*ip] = 1;
- }
- for(ip=typeafinit; *ip>=0; ip++) {
- urk("typeaf", nelem(typeaf), *ip);
- typeaf[*ip] = 1;
- }
- for(ip=typesuinit; *ip >= 0; ip++) {
- urk("typesu", nelem(typesu), *ip);
- typesu[*ip] = 1;
- }
- for(p=tasigninit; p->code >= 0; p++) {
- urk("tasign", nelem(tasign), p->code);
- tasign[p->code] = p->value;
- }
- for(p=tasaddinit; p->code >= 0; p++) {
- urk("tasadd", nelem(tasadd), p->code);
- tasadd[p->code] = p->value;
- }
- for(p=tcastinit; p->code >= 0; p++) {
- urk("tcast", nelem(tcast), p->code);
- tcast[p->code] = p->value;
- }
- for(p=taddinit; p->code >= 0; p++) {
- urk("tadd", nelem(tadd), p->code);
- tadd[p->code] = p->value;
- }
- for(p=tsubinit; p->code >= 0; p++) {
- urk("tsub", nelem(tsub), p->code);
- tsub[p->code] = p->value;
- }
- for(p=tmulinit; p->code >= 0; p++) {
- urk("tmul", nelem(tmul), p->code);
- tmul[p->code] = p->value;
- }
- for(p=tandinit; p->code >= 0; p++) {
- urk("tand", nelem(tand), p->code);
- tand[p->code] = p->value;
- }
- for(p=trelinit; p->code >= 0; p++) {
- urk("trel", nelem(trel), p->code);
- trel[p->code] = p->value;
- }
-
- /* 32-bit defaults */
- typeword = typechlp;
- typecmplx = typesuv;
-}
-
-/*
- * return 1 if it is impossible to jump into the middle of n.
- */
-static int
-deadhead(Node *n, int caseok)
-{
-loop:
- if(n == Z)
- return 1;
- switch(n->op) {
- case OLIST:
- if(!deadhead(n->left, caseok))
- return 0;
- rloop:
- n = n->right;
- goto loop;
-
- case ORETURN:
- break;
-
- case OLABEL:
- return 0;
-
- case OGOTO:
- break;
-
- case OCASE:
- if(!caseok)
- return 0;
- goto rloop;
-
- case OSWITCH:
- return deadhead(n->right, 1);
-
- case OWHILE:
- case ODWHILE:
- goto rloop;
-
- case OFOR:
- goto rloop;
-
- case OCONTINUE:
- break;
-
- case OBREAK:
- break;
-
- case OIF:
- return deadhead(n->right->left, caseok) && deadhead(n->right->right, caseok);
-
- case OSET:
- case OUSED:
- break;
- }
- return 1;
-}
-
-int
-deadheads(Node *c)
-{
- return deadhead(c->left, 0) && deadhead(c->right, 0);
-}
-
-int
-mixedasop(Type *l, Type *r)
-{
- return !typefd[l->etype] && typefd[r->etype];
-}
-
-LSym*
-linksym(Sym *s)
-{
- if(s == nil)
- return nil;
- if(s->lsym != nil)
- return s->lsym;
- return linklookup(ctxt, s->name, s->class == CSTATIC);
-}
diff --git a/src/cmd/cc/y.tab.c b/src/cmd/cc/y.tab.c
deleted file mode 100644
index 94932efe5..000000000
--- a/src/cmd/cc/y.tab.c
+++ /dev/null
@@ -1,3822 +0,0 @@
-/* A Bison parser, made by GNU Bison 2.3. */
-
-/* Skeleton implementation for Bison's Yacc-like parsers in C
-
- Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
- Free Software Foundation, Inc.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
-
-/* As a special exception, you may create a larger work that contains
- part or all of the Bison parser skeleton and distribute that work
- under terms of your choice, so long as that work isn't itself a
- parser generator using the skeleton or a modified version thereof
- as a parser skeleton. Alternatively, if you modify or redistribute
- the parser skeleton itself, you may (at your option) remove this
- special exception, which will cause the skeleton and the resulting
- Bison output files to be licensed under the GNU General Public
- License without this special exception.
-
- This special exception was added by the Free Software Foundation in
- version 2.2 of Bison. */
-
-/* C LALR(1) parser skeleton written by Richard Stallman, by
- simplifying the original so-called "semantic" parser. */
-
-/* All symbols defined below should begin with yy or YY, to avoid
- infringing on user name space. This should be done even for local
- variables, as they might otherwise be expanded by user macros.
- There are some unavoidable exceptions within include files to
- define necessary library symbols; they are noted "INFRINGES ON
- USER NAME SPACE" below. */
-
-/* Identify Bison output. */
-#define YYBISON 1
-
-/* Bison version. */
-#define YYBISON_VERSION "2.3"
-
-/* Skeleton name. */
-#define YYSKELETON_NAME "yacc.c"
-
-/* Pure parsers. */
-#define YYPURE 0
-
-/* Using locations. */
-#define YYLSP_NEEDED 0
-
-
-
-/* Tokens. */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
- /* Put the tokens into the symbol table, so that GDB and other debuggers
- know about them. */
- enum yytokentype {
- LORE = 258,
- LXORE = 259,
- LANDE = 260,
- LLSHE = 261,
- LRSHE = 262,
- LMDE = 263,
- LDVE = 264,
- LMLE = 265,
- LME = 266,
- LPE = 267,
- LOROR = 268,
- LANDAND = 269,
- LNE = 270,
- LEQ = 271,
- LGE = 272,
- LLE = 273,
- LRSH = 274,
- LLSH = 275,
- LMG = 276,
- LPP = 277,
- LMM = 278,
- LNAME = 279,
- LTYPE = 280,
- LFCONST = 281,
- LDCONST = 282,
- LCONST = 283,
- LLCONST = 284,
- LUCONST = 285,
- LULCONST = 286,
- LVLCONST = 287,
- LUVLCONST = 288,
- LSTRING = 289,
- LLSTRING = 290,
- LAUTO = 291,
- LBREAK = 292,
- LCASE = 293,
- LCHAR = 294,
- LCONTINUE = 295,
- LDEFAULT = 296,
- LDO = 297,
- LDOUBLE = 298,
- LELSE = 299,
- LEXTERN = 300,
- LFLOAT = 301,
- LFOR = 302,
- LGOTO = 303,
- LIF = 304,
- LINT = 305,
- LLONG = 306,
- LPREFETCH = 307,
- LREGISTER = 308,
- LRETURN = 309,
- LSHORT = 310,
- LSIZEOF = 311,
- LUSED = 312,
- LSTATIC = 313,
- LSTRUCT = 314,
- LSWITCH = 315,
- LTYPEDEF = 316,
- LTYPESTR = 317,
- LUNION = 318,
- LUNSIGNED = 319,
- LWHILE = 320,
- LVOID = 321,
- LENUM = 322,
- LSIGNED = 323,
- LCONSTNT = 324,
- LVOLATILE = 325,
- LSET = 326,
- LSIGNOF = 327,
- LRESTRICT = 328,
- LINLINE = 329
- };
-#endif
-/* Tokens. */
-#define LORE 258
-#define LXORE 259
-#define LANDE 260
-#define LLSHE 261
-#define LRSHE 262
-#define LMDE 263
-#define LDVE 264
-#define LMLE 265
-#define LME 266
-#define LPE 267
-#define LOROR 268
-#define LANDAND 269
-#define LNE 270
-#define LEQ 271
-#define LGE 272
-#define LLE 273
-#define LRSH 274
-#define LLSH 275
-#define LMG 276
-#define LPP 277
-#define LMM 278
-#define LNAME 279
-#define LTYPE 280
-#define LFCONST 281
-#define LDCONST 282
-#define LCONST 283
-#define LLCONST 284
-#define LUCONST 285
-#define LULCONST 286
-#define LVLCONST 287
-#define LUVLCONST 288
-#define LSTRING 289
-#define LLSTRING 290
-#define LAUTO 291
-#define LBREAK 292
-#define LCASE 293
-#define LCHAR 294
-#define LCONTINUE 295
-#define LDEFAULT 296
-#define LDO 297
-#define LDOUBLE 298
-#define LELSE 299
-#define LEXTERN 300
-#define LFLOAT 301
-#define LFOR 302
-#define LGOTO 303
-#define LIF 304
-#define LINT 305
-#define LLONG 306
-#define LPREFETCH 307
-#define LREGISTER 308
-#define LRETURN 309
-#define LSHORT 310
-#define LSIZEOF 311
-#define LUSED 312
-#define LSTATIC 313
-#define LSTRUCT 314
-#define LSWITCH 315
-#define LTYPEDEF 316
-#define LTYPESTR 317
-#define LUNION 318
-#define LUNSIGNED 319
-#define LWHILE 320
-#define LVOID 321
-#define LENUM 322
-#define LSIGNED 323
-#define LCONSTNT 324
-#define LVOLATILE 325
-#define LSET 326
-#define LSIGNOF 327
-#define LRESTRICT 328
-#define LINLINE 329
-
-
-
-
-/* Copy the first part of user declarations. */
-#line 31 "cc.y"
-
-#include <u.h>
-#include <stdio.h> /* if we don't, bison will, and cc.h re-#defines getc */
-#include "cc.h"
-
-
-/* Enabling traces. */
-#ifndef YYDEBUG
-# define YYDEBUG 0
-#endif
-
-/* Enabling verbose error messages. */
-#ifdef YYERROR_VERBOSE
-# undef YYERROR_VERBOSE
-# define YYERROR_VERBOSE 1
-#else
-# define YYERROR_VERBOSE 0
-#endif
-
-/* Enabling the token table. */
-#ifndef YYTOKEN_TABLE
-# define YYTOKEN_TABLE 0
-#endif
-
-#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-typedef union YYSTYPE
-#line 36 "cc.y"
-{
- Node* node;
- Sym* sym;
- Type* type;
- struct
- {
- Type* t;
- uchar c;
- } tycl;
- struct
- {
- Type* t1;
- Type* t2;
- Type* t3;
- uchar c;
- } tyty;
- struct
- {
- char* s;
- int32 l;
- } sval;
- int32 lval;
- double dval;
- vlong vval;
-}
-/* Line 193 of yacc.c. */
-#line 276 "y.tab.c"
- YYSTYPE;
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
-# define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
-#endif
-
-
-
-/* Copy the second part of user declarations. */
-
-
-/* Line 216 of yacc.c. */
-#line 289 "y.tab.c"
-
-#ifdef short
-# undef short
-#endif
-
-#ifdef YYTYPE_UINT8
-typedef YYTYPE_UINT8 yytype_uint8;
-#else
-typedef unsigned char yytype_uint8;
-#endif
-
-#ifdef YYTYPE_INT8
-typedef YYTYPE_INT8 yytype_int8;
-#elif (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-typedef signed char yytype_int8;
-#else
-typedef short int yytype_int8;
-#endif
-
-#ifdef YYTYPE_UINT16
-typedef YYTYPE_UINT16 yytype_uint16;
-#else
-typedef unsigned short int yytype_uint16;
-#endif
-
-#ifdef YYTYPE_INT16
-typedef YYTYPE_INT16 yytype_int16;
-#else
-typedef short int yytype_int16;
-#endif
-
-#ifndef YYSIZE_T
-# ifdef __SIZE_TYPE__
-# define YYSIZE_T __SIZE_TYPE__
-# elif defined size_t
-# define YYSIZE_T size_t
-# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
-# define YYSIZE_T size_t
-# else
-# define YYSIZE_T unsigned int
-# endif
-#endif
-
-#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
-
-#ifndef YY_
-# if defined YYENABLE_NLS && YYENABLE_NLS
-# if ENABLE_NLS
-# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
-# define YY_(msgid) dgettext ("bison-runtime", msgid)
-# endif
-# endif
-# ifndef YY_
-# define YY_(msgid) msgid
-# endif
-#endif
-
-/* Suppress unused-variable warnings by "using" E. */
-#if ! defined lint || defined __GNUC__
-# define YYUSE(e) ((void) (e))
-#else
-# define YYUSE(e) /* empty */
-#endif
-
-/* Identity function, used to suppress warnings about constant conditions. */
-#ifndef lint
-# define YYID(n) (n)
-#else
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-static int
-YYID (int i)
-#else
-static int
-YYID (i)
- int i;
-#endif
-{
- return i;
-}
-#endif
-
-#if ! defined yyoverflow || YYERROR_VERBOSE
-
-/* The parser invokes alloca or malloc; define the necessary symbols. */
-
-# ifdef YYSTACK_USE_ALLOCA
-# if YYSTACK_USE_ALLOCA
-# ifdef __GNUC__
-# define YYSTACK_ALLOC __builtin_alloca
-# elif defined __BUILTIN_VA_ARG_INCR
-# include <alloca.h> /* INFRINGES ON USER NAME SPACE */
-# elif defined _AIX
-# define YYSTACK_ALLOC __alloca
-# elif defined _MSC_VER
-# include <malloc.h> /* INFRINGES ON USER NAME SPACE */
-# define alloca _alloca
-# else
-# define YYSTACK_ALLOC alloca
-# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-# ifndef _STDLIB_H
-# define _STDLIB_H 1
-# endif
-# endif
-# endif
-# endif
-# endif
-
-# ifdef YYSTACK_ALLOC
- /* Pacify GCC's `empty if-body' warning. */
-# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
-# ifndef YYSTACK_ALLOC_MAXIMUM
- /* The OS might guarantee only one guard page at the bottom of the stack,
- and a page size can be as small as 4096 bytes. So we cannot safely
- invoke alloca (N) if N exceeds 4096. Use a slightly smaller number
- to allow for a few compiler-allocated temporary stack slots. */
-# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
-# endif
-# else
-# define YYSTACK_ALLOC YYMALLOC
-# define YYSTACK_FREE YYFREE
-# ifndef YYSTACK_ALLOC_MAXIMUM
-# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
-# endif
-# if (defined __cplusplus && ! defined _STDLIB_H \
- && ! ((defined YYMALLOC || defined malloc) \
- && (defined YYFREE || defined free)))
-# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-# ifndef _STDLIB_H
-# define _STDLIB_H 1
-# endif
-# endif
-# ifndef YYMALLOC
-# define YYMALLOC malloc
-# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
-# endif
-# endif
-# ifndef YYFREE
-# define YYFREE free
-# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-void free (void *); /* INFRINGES ON USER NAME SPACE */
-# endif
-# endif
-# endif
-#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
-
-
-#if (! defined yyoverflow \
- && (! defined __cplusplus \
- || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
-
-/* A type that is properly aligned for any stack member. */
-union yyalloc
-{
- yytype_int16 yyss;
- YYSTYPE yyvs;
- };
-
-/* The size of the maximum gap between one aligned stack and the next. */
-# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
-
-/* The size of an array large to enough to hold all stacks, each with
- N elements. */
-# define YYSTACK_BYTES(N) \
- ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
- + YYSTACK_GAP_MAXIMUM)
-
-/* Copy COUNT objects from FROM to TO. The source and destination do
- not overlap. */
-# ifndef YYCOPY
-# if defined __GNUC__ && 1 < __GNUC__
-# define YYCOPY(To, From, Count) \
- __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
-# else
-# define YYCOPY(To, From, Count) \
- do \
- { \
- YYSIZE_T yyi; \
- for (yyi = 0; yyi < (Count); yyi++) \
- (To)[yyi] = (From)[yyi]; \
- } \
- while (YYID (0))
-# endif
-# endif
-
-/* Relocate STACK from its old location to the new one. The
- local variables YYSIZE and YYSTACKSIZE give the old and new number of
- elements in the stack, and YYPTR gives the new location of the
- stack. Advance YYPTR to a properly aligned location for the next
- stack. */
-# define YYSTACK_RELOCATE(Stack) \
- do \
- { \
- YYSIZE_T yynewbytes; \
- YYCOPY (&yyptr->Stack, Stack, yysize); \
- Stack = &yyptr->Stack; \
- yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
- yyptr += yynewbytes / sizeof (*yyptr); \
- } \
- while (YYID (0))
-
-#endif
-
-/* YYFINAL -- State number of the termination state. */
-#define YYFINAL 2
-/* YYLAST -- Last index in YYTABLE. */
-#define YYLAST 1188
-
-/* YYNTOKENS -- Number of terminals. */
-#define YYNTOKENS 99
-/* YYNNTS -- Number of nonterminals. */
-#define YYNNTS 75
-/* YYNRULES -- Number of rules. */
-#define YYNRULES 247
-/* YYNRULES -- Number of states. */
-#define YYNSTATES 417
-
-/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
-#define YYUNDEFTOK 2
-#define YYMAXUTOK 329
-
-#define YYTRANSLATE(YYX) \
- ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
-
-/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
-static const yytype_uint8 yytranslate[] =
-{
- 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 97, 2, 2, 2, 35, 22, 2,
- 38, 93, 33, 31, 4, 32, 36, 34, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 17, 3,
- 25, 5, 26, 16, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 37, 2, 94, 21, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 95, 20, 96, 98, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 1, 2, 6, 7,
- 8, 9, 10, 11, 12, 13, 14, 15, 18, 19,
- 23, 24, 27, 28, 29, 30, 39, 40, 41, 42,
- 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
- 53, 54, 55, 56, 57, 58, 59, 60, 61, 62,
- 63, 64, 65, 66, 67, 68, 69, 70, 71, 72,
- 73, 74, 75, 76, 77, 78, 79, 80, 81, 82,
- 83, 84, 85, 86, 87, 88, 89, 90, 91, 92
-};
-
-#if YYDEBUG
-/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
- YYRHS. */
-static const yytype_uint16 yyprhs[] =
-{
- 0, 0, 3, 4, 7, 10, 14, 15, 16, 23,
- 25, 26, 31, 35, 37, 41, 43, 47, 52, 57,
- 60, 64, 66, 67, 72, 76, 77, 82, 84, 88,
- 89, 94, 95, 101, 102, 104, 106, 110, 112, 116,
- 119, 120, 122, 125, 129, 131, 133, 138, 143, 146,
- 150, 154, 156, 160, 164, 167, 170, 173, 177, 179,
- 182, 184, 186, 189, 190, 192, 194, 197, 200, 204,
- 208, 212, 213, 216, 219, 221, 224, 228, 231, 234,
- 237, 239, 242, 244, 247, 250, 251, 254, 260, 268,
- 269, 280, 286, 294, 298, 304, 307, 310, 314, 320,
- 326, 332, 333, 335, 336, 338, 340, 342, 346, 348,
- 352, 356, 360, 364, 368, 372, 376, 380, 384, 388,
- 392, 396, 400, 404, 408, 412, 416, 420, 426, 430,
- 434, 438, 442, 446, 450, 454, 458, 462, 466, 470,
- 472, 478, 486, 488, 491, 494, 497, 500, 503, 506,
- 509, 512, 515, 518, 522, 528, 534, 539, 544, 548,
- 552, 555, 558, 560, 562, 564, 566, 568, 570, 572,
- 574, 576, 578, 580, 582, 585, 587, 590, 591, 593,
- 595, 599, 600, 605, 606, 608, 610, 612, 614, 617,
- 620, 624, 627, 631, 633, 635, 638, 639, 644, 647,
- 650, 651, 656, 659, 662, 663, 664, 672, 673, 679,
- 681, 683, 686, 687, 690, 692, 694, 696, 698, 701,
- 703, 705, 707, 711, 714, 718, 720, 722, 724, 726,
- 728, 730, 732, 734, 736, 738, 740, 742, 744, 746,
- 748, 750, 752, 754, 756, 758, 760, 762
-};
-
-/* YYRHS -- A `-1'-separated list of the rules' RHS. */
-static const yytype_int16 yyrhs[] =
-{
- 100, 0, -1, -1, 100, 101, -1, 152, 3, -1,
- 152, 104, 3, -1, -1, -1, 152, 106, 102, 111,
- 103, 129, -1, 106, -1, -1, 106, 105, 5, 123,
- -1, 104, 4, 104, -1, 107, -1, 33, 163, 106,
- -1, 172, -1, 38, 106, 93, -1, 107, 38, 127,
- 93, -1, 107, 37, 139, 94, -1, 155, 3, -1,
- 155, 109, 3, -1, 106, -1, -1, 106, 110, 5,
- 123, -1, 109, 4, 109, -1, -1, 111, 155, 112,
- 3, -1, 106, -1, 112, 4, 112, -1, -1, 154,
- 114, 116, 3, -1, -1, 113, 154, 115, 116, 3,
- -1, -1, 117, -1, 118, -1, 117, 4, 117, -1,
- 106, -1, 172, 17, 140, -1, 17, 140, -1, -1,
- 120, -1, 33, 163, -1, 33, 163, 120, -1, 121,
- -1, 122, -1, 121, 38, 127, 93, -1, 121, 37,
- 139, 94, -1, 38, 93, -1, 37, 139, 94, -1,
- 38, 120, 93, -1, 142, -1, 95, 126, 96, -1,
- 37, 140, 94, -1, 36, 173, -1, 124, 5, -1,
- 123, 4, -1, 125, 123, 4, -1, 124, -1, 125,
- 124, -1, 125, -1, 123, -1, 125, 123, -1, -1,
- 128, -1, 171, -1, 154, 119, -1, 154, 106, -1,
- 36, 36, 36, -1, 128, 4, 128, -1, 95, 130,
- 96, -1, -1, 130, 108, -1, 130, 133, -1, 132,
- -1, 131, 132, -1, 56, 142, 17, -1, 59, 17,
- -1, 42, 17, -1, 1, 3, -1, 135, -1, 131,
- 135, -1, 138, -1, 155, 109, -1, 138, 3, -1,
- -1, 136, 129, -1, 67, 38, 141, 93, 133, -1,
- 67, 38, 141, 93, 133, 62, 133, -1, -1, 137,
- 65, 38, 134, 3, 138, 3, 138, 93, 133, -1,
- 83, 38, 141, 93, 133, -1, 60, 133, 83, 38,
- 141, 93, 3, -1, 72, 138, 3, -1, 78, 38,
- 141, 93, 133, -1, 55, 3, -1, 58, 3, -1,
- 66, 173, 3, -1, 75, 38, 148, 93, 3, -1,
- 70, 38, 148, 93, 3, -1, 89, 38, 148, 93,
- 3, -1, -1, 141, -1, -1, 140, -1, 142, -1,
- 142, -1, 141, 4, 141, -1, 143, -1, 142, 33,
- 142, -1, 142, 34, 142, -1, 142, 35, 142, -1,
- 142, 31, 142, -1, 142, 32, 142, -1, 142, 29,
- 142, -1, 142, 30, 142, -1, 142, 25, 142, -1,
- 142, 26, 142, -1, 142, 28, 142, -1, 142, 27,
- 142, -1, 142, 24, 142, -1, 142, 23, 142, -1,
- 142, 22, 142, -1, 142, 21, 142, -1, 142, 20,
- 142, -1, 142, 19, 142, -1, 142, 18, 142, -1,
- 142, 16, 141, 17, 142, -1, 142, 5, 142, -1,
- 142, 15, 142, -1, 142, 14, 142, -1, 142, 13,
- 142, -1, 142, 12, 142, -1, 142, 11, 142, -1,
- 142, 9, 142, -1, 142, 10, 142, -1, 142, 8,
- 142, -1, 142, 7, 142, -1, 142, 6, 142, -1,
- 144, -1, 38, 154, 119, 93, 143, -1, 38, 154,
- 119, 93, 95, 126, 96, -1, 145, -1, 33, 143,
- -1, 22, 143, -1, 31, 143, -1, 32, 143, -1,
- 97, 143, -1, 98, 143, -1, 40, 143, -1, 41,
- 143, -1, 74, 144, -1, 90, 144, -1, 38, 141,
- 93, -1, 74, 38, 154, 119, 93, -1, 90, 38,
- 154, 119, 93, -1, 145, 38, 148, 93, -1, 145,
- 37, 141, 94, -1, 145, 39, 173, -1, 145, 36,
- 173, -1, 145, 40, -1, 145, 41, -1, 171, -1,
- 46, -1, 47, -1, 48, -1, 49, -1, 45, -1,
- 44, -1, 50, -1, 51, -1, 146, -1, 147, -1,
- 52, -1, 146, 52, -1, 53, -1, 147, 53, -1,
- -1, 149, -1, 142, -1, 149, 4, 149, -1, -1,
- 95, 151, 113, 96, -1, -1, 155, -1, 156, -1,
- 168, -1, 165, -1, 156, 162, -1, 168, 162, -1,
- 165, 156, 163, -1, 165, 168, -1, 165, 168, 162,
- -1, 153, -1, 153, -1, 77, 173, -1, -1, 77,
- 173, 157, 150, -1, 77, 150, -1, 81, 173, -1,
- -1, 81, 173, 158, 150, -1, 81, 150, -1, 85,
- 173, -1, -1, -1, 85, 173, 159, 95, 160, 167,
- 96, -1, -1, 85, 95, 161, 167, 96, -1, 43,
- -1, 164, -1, 162, 164, -1, -1, 163, 170, -1,
- 168, -1, 170, -1, 169, -1, 166, -1, 165, 166,
- -1, 170, -1, 169, -1, 42, -1, 42, 5, 142,
- -1, 167, 4, -1, 167, 4, 167, -1, 57, -1,
- 73, -1, 68, -1, 69, -1, 86, -1, 82, -1,
- 64, -1, 61, -1, 84, -1, 54, -1, 76, -1,
- 63, -1, 79, -1, 80, -1, 71, -1, 92, -1,
- 87, -1, 88, -1, 91, -1, 42, -1, 173, -1,
- 42, -1, 43, -1
-};
-
-/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
-static const yytype_uint16 yyrline[] =
-{
- 0, 101, 101, 102, 108, 112, 114, 128, 113, 143,
- 148, 147, 155, 158, 159, 166, 167, 171, 175, 184,
- 188, 194, 200, 199, 211, 224, 225, 228, 232, 239,
- 238, 244, 243, 250, 254, 257, 261, 264, 269, 273,
- 282, 285, 288, 293, 298, 301, 302, 306, 312, 316,
- 320, 326, 327, 333, 337, 342, 345, 346, 350, 351,
- 357, 358, 359, 365, 368, 375, 376, 381, 386, 390,
- 396, 406, 409, 413, 419, 420, 426, 430, 434, 440,
- 444, 445, 451, 452, 458, 459, 459, 470, 476, 484,
- 484, 495, 499, 503, 508, 522, 526, 530, 534, 538,
- 542, 548, 551, 554, 557, 560, 567, 568, 574, 575,
- 579, 583, 587, 591, 595, 599, 603, 607, 611, 615,
- 619, 623, 627, 631, 635, 639, 643, 647, 651, 655,
- 659, 663, 667, 671, 675, 679, 683, 687, 691, 697,
- 698, 705, 713, 714, 718, 722, 726, 730, 734, 738,
- 742, 746, 750, 756, 760, 766, 772, 780, 784, 789,
- 794, 798, 802, 803, 810, 817, 824, 831, 838, 845,
- 852, 859, 860, 863, 873, 891, 901, 919, 922, 925,
- 926, 933, 932, 955, 959, 962, 967, 972, 978, 986,
- 992, 998, 1004, 1012, 1020, 1027, 1033, 1032, 1044, 1053,
- 1059, 1058, 1070, 1078, 1087, 1091, 1086, 1108, 1107, 1116,
- 1122, 1123, 1129, 1132, 1138, 1139, 1140, 1143, 1144, 1150,
- 1151, 1154, 1158, 1162, 1163, 1166, 1167, 1168, 1169, 1170,
- 1171, 1172, 1173, 1174, 1177, 1178, 1179, 1180, 1181, 1182,
- 1183, 1186, 1187, 1188, 1191, 1206, 1218, 1219
-};
-#endif
-
-#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
-/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
- First, the terminals, then, starting at YYNTOKENS, nonterminals. */
-static const char *const yytname[] =
-{
- "$end", "error", "$undefined", "';'", "','", "'='", "LORE", "LXORE",
- "LANDE", "LLSHE", "LRSHE", "LMDE", "LDVE", "LMLE", "LME", "LPE", "'?'",
- "':'", "LOROR", "LANDAND", "'|'", "'^'", "'&'", "LNE", "LEQ", "'<'",
- "'>'", "LGE", "LLE", "LRSH", "LLSH", "'+'", "'-'", "'*'", "'/'", "'%'",
- "'.'", "'['", "'('", "LMG", "LPP", "LMM", "LNAME", "LTYPE", "LFCONST",
- "LDCONST", "LCONST", "LLCONST", "LUCONST", "LULCONST", "LVLCONST",
- "LUVLCONST", "LSTRING", "LLSTRING", "LAUTO", "LBREAK", "LCASE", "LCHAR",
- "LCONTINUE", "LDEFAULT", "LDO", "LDOUBLE", "LELSE", "LEXTERN", "LFLOAT",
- "LFOR", "LGOTO", "LIF", "LINT", "LLONG", "LPREFETCH", "LREGISTER",
- "LRETURN", "LSHORT", "LSIZEOF", "LUSED", "LSTATIC", "LSTRUCT", "LSWITCH",
- "LTYPEDEF", "LTYPESTR", "LUNION", "LUNSIGNED", "LWHILE", "LVOID",
- "LENUM", "LSIGNED", "LCONSTNT", "LVOLATILE", "LSET", "LSIGNOF",
- "LRESTRICT", "LINLINE", "')'", "']'", "'{'", "'}'", "'!'", "'~'",
- "$accept", "prog", "xdecl", "@1", "@2", "xdlist", "@3", "xdecor",
- "xdecor2", "adecl", "adlist", "@4", "pdecl", "pdlist", "edecl", "@5",
- "@6", "zedlist", "edlist", "edecor", "abdecor", "abdecor1", "abdecor2",
- "abdecor3", "init", "qual", "qlist", "ilist", "zarglist", "arglist",
- "block", "slist", "labels", "label", "stmnt", "forexpr", "ulstmnt", "@7",
- "@8", "zcexpr", "zexpr", "lexpr", "cexpr", "expr", "xuexpr", "uexpr",
- "pexpr", "string", "lstring", "zelist", "elist", "sbody", "@9",
- "zctlist", "types", "tlist", "ctlist", "complex", "@10", "@11", "@12",
- "@13", "@14", "gctnlist", "zgnlist", "gctname", "gcnlist", "gcname",
- "enum", "tname", "cname", "gname", "name", "tag", "ltag", 0
-};
-#endif
-
-# ifdef YYPRINT
-/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
- token YYLEX-NUM. */
-static const yytype_uint16 yytoknum[] =
-{
- 0, 256, 257, 59, 44, 61, 258, 259, 260, 261,
- 262, 263, 264, 265, 266, 267, 63, 58, 268, 269,
- 124, 94, 38, 270, 271, 60, 62, 272, 273, 274,
- 275, 43, 45, 42, 47, 37, 46, 91, 40, 276,
- 277, 278, 279, 280, 281, 282, 283, 284, 285, 286,
- 287, 288, 289, 290, 291, 292, 293, 294, 295, 296,
- 297, 298, 299, 300, 301, 302, 303, 304, 305, 306,
- 307, 308, 309, 310, 311, 312, 313, 314, 315, 316,
- 317, 318, 319, 320, 321, 322, 323, 324, 325, 326,
- 327, 328, 329, 41, 93, 123, 125, 33, 126
-};
-# endif
-
-/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
-static const yytype_uint8 yyr1[] =
-{
- 0, 99, 100, 100, 101, 101, 102, 103, 101, 104,
- 105, 104, 104, 106, 106, 107, 107, 107, 107, 108,
- 108, 109, 110, 109, 109, 111, 111, 112, 112, 114,
- 113, 115, 113, 116, 116, 117, 117, 118, 118, 118,
- 119, 119, 120, 120, 120, 121, 121, 121, 122, 122,
- 122, 123, 123, 124, 124, 124, 125, 125, 125, 125,
- 126, 126, 126, 127, 127, 128, 128, 128, 128, 128,
- 129, 130, 130, 130, 131, 131, 132, 132, 132, 133,
- 133, 133, 134, 134, 135, 136, 135, 135, 135, 137,
- 135, 135, 135, 135, 135, 135, 135, 135, 135, 135,
- 135, 138, 138, 139, 139, 140, 141, 141, 142, 142,
- 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
- 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
- 142, 142, 142, 142, 142, 142, 142, 142, 142, 143,
- 143, 143, 144, 144, 144, 144, 144, 144, 144, 144,
- 144, 144, 144, 145, 145, 145, 145, 145, 145, 145,
- 145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
- 145, 145, 145, 146, 146, 147, 147, 148, 148, 149,
- 149, 151, 150, 152, 152, 153, 153, 153, 153, 153,
- 153, 153, 153, 154, 155, 156, 157, 156, 156, 156,
- 158, 156, 156, 156, 159, 160, 156, 161, 156, 156,
- 162, 162, 163, 163, 164, 164, 164, 165, 165, 166,
- 166, 167, 167, 167, 167, 168, 168, 168, 168, 168,
- 168, 168, 168, 168, 169, 169, 169, 169, 169, 169,
- 169, 170, 170, 170, 171, 172, 173, 173
-};
-
-/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
-static const yytype_uint8 yyr2[] =
-{
- 0, 2, 0, 2, 2, 3, 0, 0, 6, 1,
- 0, 4, 3, 1, 3, 1, 3, 4, 4, 2,
- 3, 1, 0, 4, 3, 0, 4, 1, 3, 0,
- 4, 0, 5, 0, 1, 1, 3, 1, 3, 2,
- 0, 1, 2, 3, 1, 1, 4, 4, 2, 3,
- 3, 1, 3, 3, 2, 2, 2, 3, 1, 2,
- 1, 1, 2, 0, 1, 1, 2, 2, 3, 3,
- 3, 0, 2, 2, 1, 2, 3, 2, 2, 2,
- 1, 2, 1, 2, 2, 0, 2, 5, 7, 0,
- 10, 5, 7, 3, 5, 2, 2, 3, 5, 5,
- 5, 0, 1, 0, 1, 1, 1, 3, 1, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 5, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 1,
- 5, 7, 1, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 3, 5, 5, 4, 4, 3, 3,
- 2, 2, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 2, 1, 2, 0, 1, 1,
- 3, 0, 4, 0, 1, 1, 1, 1, 2, 2,
- 3, 2, 3, 1, 1, 2, 0, 4, 2, 2,
- 0, 4, 2, 2, 0, 0, 7, 0, 5, 1,
- 1, 2, 0, 2, 1, 1, 1, 1, 2, 1,
- 1, 1, 3, 2, 3, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1
-};
-
-/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
- STATE-NUM when YYTABLE doesn't specify something else to do. Zero
- means the default is an error. */
-static const yytype_uint8 yydefact[] =
-{
- 2, 183, 1, 209, 234, 225, 232, 236, 231, 227,
- 228, 239, 226, 235, 0, 237, 238, 0, 230, 233,
- 0, 229, 241, 242, 243, 240, 3, 0, 194, 184,
- 185, 187, 217, 186, 220, 219, 246, 247, 181, 198,
- 195, 202, 199, 207, 203, 4, 212, 0, 0, 6,
- 13, 15, 245, 188, 210, 214, 216, 215, 212, 218,
- 191, 189, 0, 0, 0, 0, 0, 0, 0, 5,
- 0, 25, 0, 103, 63, 211, 190, 192, 0, 193,
- 29, 197, 201, 221, 0, 205, 14, 213, 16, 12,
- 9, 7, 0, 0, 0, 0, 0, 0, 0, 0,
- 244, 168, 167, 163, 164, 165, 166, 169, 170, 173,
- 175, 0, 0, 0, 0, 0, 104, 105, 108, 139,
- 142, 171, 172, 162, 0, 0, 64, 40, 65, 182,
- 31, 33, 0, 223, 208, 0, 0, 0, 0, 11,
- 51, 144, 145, 146, 143, 0, 106, 40, 149, 150,
- 0, 151, 0, 152, 147, 148, 18, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 177,
- 0, 160, 161, 174, 176, 0, 17, 0, 212, 103,
- 0, 67, 66, 41, 44, 45, 33, 0, 37, 0,
- 34, 35, 15, 222, 224, 0, 71, 8, 27, 0,
- 0, 0, 61, 58, 60, 0, 0, 153, 212, 0,
- 0, 40, 40, 128, 138, 137, 136, 134, 135, 133,
- 132, 131, 130, 129, 0, 126, 125, 124, 123, 122,
- 121, 120, 116, 117, 119, 118, 114, 115, 112, 113,
- 109, 110, 111, 159, 0, 179, 0, 178, 158, 68,
- 69, 42, 0, 48, 0, 103, 63, 0, 39, 30,
- 0, 0, 206, 0, 26, 0, 54, 0, 56, 55,
- 62, 59, 52, 107, 42, 0, 0, 0, 0, 157,
- 156, 0, 43, 49, 50, 0, 0, 32, 36, 38,
- 0, 244, 0, 0, 0, 0, 0, 0, 0, 0,
- 101, 0, 0, 0, 0, 70, 72, 85, 74, 73,
- 80, 0, 0, 0, 102, 0, 28, 53, 57, 0,
- 140, 154, 155, 127, 180, 47, 46, 79, 78, 95,
- 0, 96, 77, 0, 0, 0, 177, 0, 177, 0,
- 0, 177, 75, 81, 86, 0, 84, 19, 21, 0,
- 0, 76, 0, 97, 0, 0, 93, 0, 0, 0,
- 0, 101, 0, 20, 0, 141, 0, 0, 0, 0,
- 0, 0, 0, 0, 82, 0, 0, 24, 0, 87,
- 99, 98, 94, 91, 100, 101, 83, 23, 0, 0,
- 0, 92, 88, 101, 0, 0, 90
-};
-
-/* YYDEFGOTO[NTERM-NUM]. */
-static const yytype_int16 yydefgoto[] =
-{
- -1, 1, 26, 71, 136, 48, 72, 208, 50, 326,
- 369, 382, 91, 219, 78, 131, 206, 209, 210, 211,
- 202, 203, 204, 205, 222, 223, 224, 225, 125, 126,
- 217, 283, 327, 328, 329, 393, 330, 331, 332, 333,
- 115, 116, 334, 146, 118, 119, 120, 121, 122, 266,
- 267, 39, 62, 27, 79, 127, 29, 30, 63, 64,
- 66, 135, 65, 53, 67, 54, 31, 32, 84, 33,
- 34, 35, 123, 51, 52
-};
-
-/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
- STATE-NUM. */
-#define YYPACT_NINF -331
-static const yytype_int16 yypact[] =
-{
- -331, 548, -331, -331, -331, -331, -331, -331, -331, -331,
- -331, -331, -331, -331, -3, -331, -331, -3, -331, -331,
- 149, -331, -331, -331, -331, -331, -331, 264, -331, -331,
- 965, 929, -331, 965, -331, -331, -331, -331, -331, -331,
- -75, -331, -72, -331, -60, -331, -331, 307, 60, 270,
- 156, -331, -331, 965, -331, -331, -331, -331, -331, -331,
- 965, 965, 929, -44, -44, 29, -15, 199, -10, -331,
- 307, -331, 83, 756, 849, -331, 140, 965, 889, -331,
- -331, -331, -331, 86, 12, -331, -331, -331, -331, -331,
- 90, 929, 686, 756, 756, 756, 756, 615, 756, 756,
- -331, -331, -331, -331, -331, -331, -331, -331, -331, -331,
- -331, 791, 826, 756, 756, 9, -331, 1084, -331, -331,
- 708, 54, 57, -331, 110, 56, 152, 310, -331, -331,
- -331, 279, 756, 29, -331, 29, 63, 307, 165, -331,
- 1084, -331, -331, -331, -331, 30, 1084, 44, -331, -331,
- 615, -331, 615, -331, -331, -331, -331, 756, 756, 756,
- 756, 756, 756, 756, 756, 756, 756, 756, 756, 756,
- 756, 756, 756, 756, 756, 756, 756, 756, 756, 756,
- 756, 756, 756, 756, 756, 756, 756, 157, 756, 756,
- 157, -331, -331, -331, -331, 115, -331, 849, -331, 756,
- 128, -331, -331, -331, 182, -331, 279, 756, -331, 164,
- 200, -331, 208, 1084, -331, 13, -331, -331, -331, 262,
- 157, 756, 225, 228, 165, 73, 756, -331, -331, -7,
- 150, 44, 44, 1084, 1084, 1084, 1084, 1084, 1084, 1084,
- 1084, 1084, 1084, 1084, 28, 304, 1100, 1115, 1129, 1142,
- 1153, 1153, 433, 433, 433, 433, 333, 333, 265, 265,
- -331, -331, -331, -331, 8, 1084, 153, 236, -331, -331,
- -331, 147, 158, -331, 161, 756, 849, 247, -331, -331,
- 279, 756, -331, 341, -331, 307, -331, 175, -331, -331,
- 254, 228, -331, -331, 135, 721, 188, 190, 756, -331,
- -331, 756, -331, -331, -331, 191, 211, -331, -331, -331,
- 298, 301, 338, 756, 343, 339, 439, 157, 319, 321,
- 756, 322, 323, 324, 332, -331, -331, 509, -331, -331,
- -331, 63, 306, 372, 373, 277, -331, -331, -331, 165,
- -331, -331, -331, 425, -331, -331, -331, -331, -331, -331,
- 1053, -331, -331, 293, 375, 756, 756, 400, 756, 756,
- 756, 756, -331, -331, -331, 396, -331, -331, 430, 285,
- 377, -331, 431, -331, 55, 381, -331, 382, 62, 64,
- 383, 615, 473, -331, 307, -331, 756, 439, 479, 490,
- 439, 439, 493, 497, -331, 307, 686, -331, 66, 440,
- -331, -331, -331, -331, -331, 756, 499, -331, 498, 439,
- 504, -331, -331, 756, 415, 439, -331
-};
-
-/* YYPGOTO[NTERM-NUM]. */
-static const yytype_int16 yypgoto[] =
-{
- -331, -331, -331, -331, -331, 445, -331, -26, -331, -331,
- -330, -331, -331, 233, -331, -331, -331, 313, 230, -331,
- -132, -187, -331, -331, -82, 292, -331, 181, 245, 326,
- 193, -331, -331, 198, -227, -331, 203, -331, -331, -309,
- -181, -183, -83, -45, -38, 243, -331, -331, -331, -175,
- 226, 10, -331, -331, -1, 0, -88, 495, -331, -331,
- -331, -331, -331, -14, -51, -28, -331, 501, -85, 218,
- 231, -24, -52, -127, -12
-};
-
-/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
- positive, shift that token. If negative, reduce the rule which
- number is the opposite. If zero, do what YYDEFACT says.
- If YYTABLE_NINF, syntax error. */
-#define YYTABLE_NINF -205
-static const yytype_int16 yytable[] =
-{
- 28, 49, 40, 137, 212, 42, 57, 76, 44, 57,
- 139, 357, 226, 274, 145, 230, 133, 133, 272, 61,
- -196, 68, 128, -200, 278, 75, 228, 41, 117, 57,
- 199, 229, 226, 75, 226, -204, 57, 57, 287, 36,
- 37, 86, 274, 87, 90, 298, 77, 140, 214, 75,
- 215, 38, 87, 57, 397, 141, 142, 143, 144, 226,
- 148, 149, 80, 69, 70, 406, 226, 145, 226, 145,
- 226, 83, 394, 81, 82, 154, 155, 228, 130, 212,
- 85, 199, 229, 88, 302, 244, 273, 213, 92, 353,
- 28, 132, 38, 140, 305, -10, 410, 147, 309, 296,
- 297, 201, 299, 156, 414, 264, 193, 302, 134, 282,
- 194, 218, 233, 234, 235, 236, 237, 238, 239, 240,
- 241, 242, 243, 227, 245, 246, 247, 248, 249, 250,
- 251, 252, 253, 254, 255, 256, 257, 258, 259, 260,
- 261, 262, 290, 293, 265, 128, 195, 271, 387, 196,
- 231, 269, 232, 212, 117, 390, 197, 391, 216, 408,
- 399, 198, 117, 402, 403, 199, 200, 279, 228, 292,
- 36, 37, 199, 229, 68, 263, 117, 294, 268, 140,
- 198, 375, 412, 377, 199, 200, 380, 93, 416, 36,
- 37, 36, 37, 73, 74, 335, 94, 95, 96, 36,
- 37, 220, 221, 97, 280, 98, 99, 100, 286, 101,
- 102, 103, 104, 105, 106, 107, 108, 109, 110, 275,
- 276, 273, 22, 23, 128, 281, 24, 22, 23, 288,
- 117, 24, 46, 289, 22, 23, 117, 47, 24, 111,
- 301, 36, 37, 295, 43, 86, 300, 87, 55, 60,
- 307, 55, 303, 343, 304, 112, 265, 340, 338, 218,
- 138, 56, 113, 114, 56, 284, 285, 45, 350, 337,
- 87, 55, 374, -9, -9, -10, 378, 379, 55, 55,
- 367, 341, 28, 342, 56, 345, 22, 23, 383, 384,
- 24, 56, 56, 395, 140, 55, 207, 46, 184, 185,
- 186, 347, 47, 398, 346, 354, 36, 37, 56, 368,
- 46, 265, 46, 265, 407, 47, 265, 47, 348, 36,
- 37, 36, 37, 170, 171, 172, 173, 174, 175, 176,
- 177, 178, 179, 180, 181, 182, 183, 184, 185, 186,
- 46, 349, 310, 198, -101, 47, 351, 199, 200, 36,
- 37, 140, 36, 37, 151, 153, 352, 355, 368, 356,
- 358, 359, 360, 93, 182, 183, 184, 185, 186, 368,
- 361, 365, 94, 95, 96, 366, 372, 226, 373, 97,
- 28, 98, 99, 311, 3, 101, 102, 103, 104, 105,
- 106, 107, 108, 109, 110, 4, 312, 313, 5, 314,
- 315, 316, 6, 376, 7, 8, -89, 317, 318, 9,
- 10, 319, 11, 320, 12, 111, 321, 13, 14, 322,
- 15, 16, 17, 18, 323, 19, 20, 21, 22, 23,
- 324, 112, 24, 25, 381, -22, -85, 325, 113, 114,
- 310, 168, -101, 169, 170, 171, 172, 173, 174, 175,
- 176, 177, 178, 179, 180, 181, 182, 183, 184, 185,
- 186, 93, 180, 181, 182, 183, 184, 185, 186, 386,
- 94, 95, 96, 385, 388, 389, 392, 97, 396, 98,
- 99, 311, 400, 101, 102, 103, 104, 105, 106, 107,
- 108, 109, 110, 401, 312, 313, 404, 314, 315, 316,
- 405, 411, 409, 384, -89, 317, 318, 413, 415, 319,
- 308, 320, -101, 111, 321, 89, 291, 322, 336, 277,
- 370, 306, 323, 270, 364, 362, 58, 344, 324, 112,
- 363, 93, 59, 0, -85, 0, 113, 114, 0, 0,
- 94, 95, 96, 0, 0, 0, 0, 97, 2, 98,
- 99, 311, 0, 101, 102, 103, 104, 105, 106, 107,
- 108, 109, 110, 0, 312, 313, 0, 314, 315, 316,
- 0, 0, 0, 0, -89, 317, 318, 0, 0, 319,
- 0, 320, 0, 111, 321, 0, 0, 322, 0, 0,
- 0, 3, 323, 0, 0, 0, 0, 0, 324, 112,
- 0, 0, 4, 0, 0, 5, 113, 114, 0, 6,
- 0, 7, 8, 0, 0, 0, 9, 10, 0, 11,
- 0, 12, 0, 0, 13, 14, 0, 15, 16, 17,
- 18, 0, 19, 20, 21, 22, 23, 93, 0, 24,
- 25, 0, 0, 0, 0, 0, 94, 95, 96, 0,
- 0, 0, 0, 97, 0, 98, 99, 100, 3, 101,
- 102, 103, 104, 105, 106, 107, 108, 109, 110, 4,
- 0, 0, 5, 0, 0, 0, 6, 0, 7, 8,
- 0, 0, 0, 9, 10, 0, 11, 0, 12, 111,
- 0, 13, 14, 0, 15, 16, 17, 18, 0, 19,
- 20, 21, 22, 23, 0, 112, 24, 25, 93, 0,
- 0, 0, 113, 114, 0, 0, 0, 94, 95, 96,
- 0, 0, 0, 0, 97, 0, 98, 99, 100, 0,
- 101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
- 0, 0, 0, 93, 187, 188, 189, 190, 191, 192,
- 0, 0, 94, 95, 96, 0, 0, 0, 0, 97,
- 111, 98, 99, 100, 0, 101, 102, 103, 104, 105,
- 106, 107, 108, 109, 110, 0, 112, 0, 93, 0,
- 0, 138, 0, 113, 114, 0, 0, 94, 95, 96,
- 0, 0, 0, 0, 97, 111, 98, 99, 100, 0,
- 101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
- 0, 112, 0, 93, 0, 0, 339, 0, 113, 114,
- 0, 0, 94, 95, 96, 0, 0, 0, 0, 150,
- 111, 98, 99, 100, 0, 101, 102, 103, 104, 105,
- 106, 107, 108, 109, 110, 0, 112, 0, 93, 0,
- 0, 0, 0, 113, 114, 0, 0, 94, 95, 96,
- 0, 0, 0, 0, 152, 111, 98, 99, 100, 0,
- 101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
- 0, 112, 0, 0, 0, 124, 0, 0, 113, 114,
- 0, 100, 3, 0, 0, 0, 0, 0, 0, 0,
- 111, 0, 0, 4, 0, 0, 5, 0, 0, 0,
- 6, 0, 7, 8, 0, 0, 112, 9, 10, 0,
- 11, 0, 12, 113, 114, 13, 14, 0, 15, 16,
- 17, 18, 3, 19, 20, 21, 22, 23, 0, 0,
- 24, 25, 0, 4, 0, 0, 5, 0, 0, 0,
- 6, 0, 7, 8, 0, 0, 0, 9, 10, 0,
- 11, 0, 12, 0, 0, 13, 14, 0, 15, 16,
- 17, 18, 3, 19, 20, 21, 22, 23, 0, 0,
- 24, 25, 0, 4, 0, 129, 5, 0, 0, 0,
- 6, 0, 7, 8, 0, 0, 0, 9, 10, 0,
- 11, 0, 12, 0, 0, 13, 14, 0, 15, 16,
- 17, 18, 0, 19, 20, 21, 22, 23, 0, 4,
- 24, 25, 5, 0, 0, 0, 6, 0, 7, 8,
- 0, 0, 0, 9, 10, 0, 11, 0, 12, 0,
- 0, 13, 0, 0, 15, 16, 0, 18, 0, 19,
- 0, 21, 22, 23, 0, 0, 24, 25, 157, 158,
- 159, 160, 161, 162, 163, 164, 165, 166, 167, 168,
- 371, 169, 170, 171, 172, 173, 174, 175, 176, 177,
- 178, 179, 180, 181, 182, 183, 184, 185, 186, 157,
- 158, 159, 160, 161, 162, 163, 164, 165, 166, 167,
- 168, 0, 169, 170, 171, 172, 173, 174, 175, 176,
- 177, 178, 179, 180, 181, 182, 183, 184, 185, 186,
- 171, 172, 173, 174, 175, 176, 177, 178, 179, 180,
- 181, 182, 183, 184, 185, 186, 172, 173, 174, 175,
- 176, 177, 178, 179, 180, 181, 182, 183, 184, 185,
- 186, 173, 174, 175, 176, 177, 178, 179, 180, 181,
- 182, 183, 184, 185, 186, 174, 175, 176, 177, 178,
- 179, 180, 181, 182, 183, 184, 185, 186, 176, 177,
- 178, 179, 180, 181, 182, 183, 184, 185, 186
-};
-
-static const yytype_int16 yycheck[] =
-{
- 1, 27, 14, 91, 131, 17, 30, 58, 20, 33,
- 92, 320, 4, 200, 97, 147, 4, 4, 199, 33,
- 95, 47, 74, 95, 207, 53, 33, 17, 73, 53,
- 37, 38, 4, 61, 4, 95, 60, 61, 221, 42,
- 43, 67, 229, 67, 70, 17, 60, 92, 133, 77,
- 135, 95, 76, 77, 384, 93, 94, 95, 96, 4,
- 98, 99, 62, 3, 4, 395, 4, 150, 4, 152,
- 4, 42, 381, 63, 64, 113, 114, 33, 78, 206,
- 95, 37, 38, 93, 271, 168, 93, 132, 5, 316,
- 91, 5, 95, 138, 275, 5, 405, 97, 281, 231,
- 232, 127, 94, 94, 413, 188, 52, 294, 96, 96,
- 53, 137, 157, 158, 159, 160, 161, 162, 163, 164,
- 165, 166, 167, 93, 169, 170, 171, 172, 173, 174,
- 175, 176, 177, 178, 179, 180, 181, 182, 183, 184,
- 185, 186, 224, 226, 189, 197, 36, 198, 93, 93,
- 150, 36, 152, 280, 199, 93, 4, 93, 95, 93,
- 387, 33, 207, 390, 391, 37, 38, 3, 33, 96,
- 42, 43, 37, 38, 200, 187, 221, 228, 190, 224,
- 33, 356, 409, 358, 37, 38, 361, 22, 415, 42,
- 43, 42, 43, 37, 38, 283, 31, 32, 33, 42,
- 43, 36, 37, 38, 4, 40, 41, 42, 220, 44,
- 45, 46, 47, 48, 49, 50, 51, 52, 53, 37,
- 38, 93, 87, 88, 276, 17, 91, 87, 88, 4,
- 275, 91, 33, 5, 87, 88, 281, 38, 91, 74,
- 4, 42, 43, 93, 95, 271, 93, 271, 30, 31,
- 3, 33, 94, 298, 93, 90, 301, 295, 4, 285,
- 95, 30, 97, 98, 33, 3, 4, 3, 313, 94,
- 294, 53, 355, 3, 4, 5, 359, 360, 60, 61,
- 3, 93, 283, 93, 53, 94, 87, 88, 3, 4,
- 91, 60, 61, 381, 339, 77, 17, 33, 33, 34,
- 35, 3, 38, 386, 93, 317, 42, 43, 77, 335,
- 33, 356, 33, 358, 396, 38, 361, 38, 17, 42,
- 43, 42, 43, 19, 20, 21, 22, 23, 24, 25,
- 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
- 33, 3, 1, 33, 3, 38, 3, 37, 38, 42,
- 43, 396, 42, 43, 111, 112, 17, 38, 384, 38,
- 38, 38, 38, 22, 31, 32, 33, 34, 35, 395,
- 38, 65, 31, 32, 33, 3, 83, 4, 3, 38,
- 381, 40, 41, 42, 43, 44, 45, 46, 47, 48,
- 49, 50, 51, 52, 53, 54, 55, 56, 57, 58,
- 59, 60, 61, 3, 63, 64, 65, 66, 67, 68,
- 69, 70, 71, 72, 73, 74, 75, 76, 77, 78,
- 79, 80, 81, 82, 83, 84, 85, 86, 87, 88,
- 89, 90, 91, 92, 38, 5, 95, 96, 97, 98,
- 1, 16, 3, 18, 19, 20, 21, 22, 23, 24,
- 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
- 35, 22, 29, 30, 31, 32, 33, 34, 35, 38,
- 31, 32, 33, 96, 93, 93, 93, 38, 5, 40,
- 41, 42, 3, 44, 45, 46, 47, 48, 49, 50,
- 51, 52, 53, 3, 55, 56, 3, 58, 59, 60,
- 3, 3, 62, 4, 65, 66, 67, 3, 93, 70,
- 280, 72, 3, 74, 75, 70, 224, 78, 285, 206,
- 339, 276, 83, 197, 331, 327, 31, 301, 89, 90,
- 327, 22, 31, -1, 95, -1, 97, 98, -1, -1,
- 31, 32, 33, -1, -1, -1, -1, 38, 0, 40,
- 41, 42, -1, 44, 45, 46, 47, 48, 49, 50,
- 51, 52, 53, -1, 55, 56, -1, 58, 59, 60,
- -1, -1, -1, -1, 65, 66, 67, -1, -1, 70,
- -1, 72, -1, 74, 75, -1, -1, 78, -1, -1,
- -1, 43, 83, -1, -1, -1, -1, -1, 89, 90,
- -1, -1, 54, -1, -1, 57, 97, 98, -1, 61,
- -1, 63, 64, -1, -1, -1, 68, 69, -1, 71,
- -1, 73, -1, -1, 76, 77, -1, 79, 80, 81,
- 82, -1, 84, 85, 86, 87, 88, 22, -1, 91,
- 92, -1, -1, -1, -1, -1, 31, 32, 33, -1,
- -1, -1, -1, 38, -1, 40, 41, 42, 43, 44,
- 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
- -1, -1, 57, -1, -1, -1, 61, -1, 63, 64,
- -1, -1, -1, 68, 69, -1, 71, -1, 73, 74,
- -1, 76, 77, -1, 79, 80, 81, 82, -1, 84,
- 85, 86, 87, 88, -1, 90, 91, 92, 22, -1,
- -1, -1, 97, 98, -1, -1, -1, 31, 32, 33,
- -1, -1, -1, -1, 38, -1, 40, 41, 42, -1,
- 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
- -1, -1, -1, 22, 36, 37, 38, 39, 40, 41,
- -1, -1, 31, 32, 33, -1, -1, -1, -1, 38,
- 74, 40, 41, 42, -1, 44, 45, 46, 47, 48,
- 49, 50, 51, 52, 53, -1, 90, -1, 22, -1,
- -1, 95, -1, 97, 98, -1, -1, 31, 32, 33,
- -1, -1, -1, -1, 38, 74, 40, 41, 42, -1,
- 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
- -1, 90, -1, 22, -1, -1, 95, -1, 97, 98,
- -1, -1, 31, 32, 33, -1, -1, -1, -1, 38,
- 74, 40, 41, 42, -1, 44, 45, 46, 47, 48,
- 49, 50, 51, 52, 53, -1, 90, -1, 22, -1,
- -1, -1, -1, 97, 98, -1, -1, 31, 32, 33,
- -1, -1, -1, -1, 38, 74, 40, 41, 42, -1,
- 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
- -1, 90, -1, -1, -1, 36, -1, -1, 97, 98,
- -1, 42, 43, -1, -1, -1, -1, -1, -1, -1,
- 74, -1, -1, 54, -1, -1, 57, -1, -1, -1,
- 61, -1, 63, 64, -1, -1, 90, 68, 69, -1,
- 71, -1, 73, 97, 98, 76, 77, -1, 79, 80,
- 81, 82, 43, 84, 85, 86, 87, 88, -1, -1,
- 91, 92, -1, 54, -1, -1, 57, -1, -1, -1,
- 61, -1, 63, 64, -1, -1, -1, 68, 69, -1,
- 71, -1, 73, -1, -1, 76, 77, -1, 79, 80,
- 81, 82, 43, 84, 85, 86, 87, 88, -1, -1,
- 91, 92, -1, 54, -1, 96, 57, -1, -1, -1,
- 61, -1, 63, 64, -1, -1, -1, 68, 69, -1,
- 71, -1, 73, -1, -1, 76, 77, -1, 79, 80,
- 81, 82, -1, 84, 85, 86, 87, 88, -1, 54,
- 91, 92, 57, -1, -1, -1, 61, -1, 63, 64,
- -1, -1, -1, 68, 69, -1, 71, -1, 73, -1,
- -1, 76, -1, -1, 79, 80, -1, 82, -1, 84,
- -1, 86, 87, 88, -1, -1, 91, 92, 5, 6,
- 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
- 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
- 27, 28, 29, 30, 31, 32, 33, 34, 35, 5,
- 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
- 16, -1, 18, 19, 20, 21, 22, 23, 24, 25,
- 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
- 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
- 30, 31, 32, 33, 34, 35, 21, 22, 23, 24,
- 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
- 35, 22, 23, 24, 25, 26, 27, 28, 29, 30,
- 31, 32, 33, 34, 35, 23, 24, 25, 26, 27,
- 28, 29, 30, 31, 32, 33, 34, 35, 25, 26,
- 27, 28, 29, 30, 31, 32, 33, 34, 35
-};
-
-/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
- symbol of state STATE-NUM. */
-static const yytype_uint8 yystos[] =
-{
- 0, 100, 0, 43, 54, 57, 61, 63, 64, 68,
- 69, 71, 73, 76, 77, 79, 80, 81, 82, 84,
- 85, 86, 87, 88, 91, 92, 101, 152, 153, 155,
- 156, 165, 166, 168, 169, 170, 42, 43, 95, 150,
- 173, 150, 173, 95, 173, 3, 33, 38, 104, 106,
- 107, 172, 173, 162, 164, 168, 169, 170, 156, 166,
- 168, 162, 151, 157, 158, 161, 159, 163, 106, 3,
- 4, 102, 105, 37, 38, 164, 163, 162, 113, 153,
- 154, 150, 150, 42, 167, 95, 106, 170, 93, 104,
- 106, 111, 5, 22, 31, 32, 33, 38, 40, 41,
- 42, 44, 45, 46, 47, 48, 49, 50, 51, 52,
- 53, 74, 90, 97, 98, 139, 140, 142, 143, 144,
- 145, 146, 147, 171, 36, 127, 128, 154, 171, 96,
- 154, 114, 5, 4, 96, 160, 103, 155, 95, 123,
- 142, 143, 143, 143, 143, 141, 142, 154, 143, 143,
- 38, 144, 38, 144, 143, 143, 94, 5, 6, 7,
- 8, 9, 10, 11, 12, 13, 14, 15, 16, 18,
- 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
- 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
- 39, 40, 41, 52, 53, 36, 93, 4, 33, 37,
- 38, 106, 119, 120, 121, 122, 115, 17, 106, 116,
- 117, 118, 172, 142, 167, 167, 95, 129, 106, 112,
- 36, 37, 123, 124, 125, 126, 4, 93, 33, 38,
- 119, 154, 154, 142, 142, 142, 142, 142, 142, 142,
- 142, 142, 142, 142, 141, 142, 142, 142, 142, 142,
- 142, 142, 142, 142, 142, 142, 142, 142, 142, 142,
- 142, 142, 142, 173, 141, 142, 148, 149, 173, 36,
- 128, 163, 139, 93, 120, 37, 38, 116, 140, 3,
- 4, 17, 96, 130, 3, 4, 173, 140, 4, 5,
- 123, 124, 96, 141, 163, 93, 119, 119, 17, 94,
- 93, 4, 120, 94, 93, 139, 127, 3, 117, 140,
- 1, 42, 55, 56, 58, 59, 60, 66, 67, 70,
- 72, 75, 78, 83, 89, 96, 108, 131, 132, 133,
- 135, 136, 137, 138, 141, 155, 112, 94, 4, 95,
- 143, 93, 93, 142, 149, 94, 93, 3, 17, 3,
- 142, 3, 17, 133, 173, 38, 38, 138, 38, 38,
- 38, 38, 132, 135, 129, 65, 3, 3, 106, 109,
- 126, 17, 83, 3, 141, 148, 3, 148, 141, 141,
- 148, 38, 110, 3, 4, 96, 38, 93, 93, 93,
- 93, 93, 93, 134, 138, 155, 5, 109, 141, 133,
- 3, 3, 133, 133, 3, 3, 109, 123, 93, 62,
- 138, 3, 133, 3, 138, 93, 133
-};
-
-#define yyerrok (yyerrstatus = 0)
-#define yyclearin (yychar = YYEMPTY)
-#define YYEMPTY (-2)
-#define YYEOF 0
-
-#define YYACCEPT goto yyacceptlab
-#define YYABORT goto yyabortlab
-#define YYERROR goto yyerrorlab
-
-
-/* Like YYERROR except do call yyerror. This remains here temporarily
- to ease the transition to the new meaning of YYERROR, for GCC.
- Once GCC version 2 has supplanted version 1, this can go. */
-
-#define YYFAIL goto yyerrlab
-
-#define YYRECOVERING() (!!yyerrstatus)
-
-#define YYBACKUP(Token, Value) \
-do \
- if (yychar == YYEMPTY && yylen == 1) \
- { \
- yychar = (Token); \
- yylval = (Value); \
- yytoken = YYTRANSLATE (yychar); \
- YYPOPSTACK (1); \
- goto yybackup; \
- } \
- else \
- { \
- yyerror (YY_("syntax error: cannot back up")); \
- YYERROR; \
- } \
-while (YYID (0))
-
-
-#define YYTERROR 1
-#define YYERRCODE 256
-
-
-/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
- If N is 0, then set CURRENT to the empty location which ends
- the previous symbol: RHS[0] (always defined). */
-
-#define YYRHSLOC(Rhs, K) ((Rhs)[K])
-#ifndef YYLLOC_DEFAULT
-# define YYLLOC_DEFAULT(Current, Rhs, N) \
- do \
- if (YYID (N)) \
- { \
- (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \
- (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
- (Current).last_line = YYRHSLOC (Rhs, N).last_line; \
- (Current).last_column = YYRHSLOC (Rhs, N).last_column; \
- } \
- else \
- { \
- (Current).first_line = (Current).last_line = \
- YYRHSLOC (Rhs, 0).last_line; \
- (Current).first_column = (Current).last_column = \
- YYRHSLOC (Rhs, 0).last_column; \
- } \
- while (YYID (0))
-#endif
-
-
-/* YY_LOCATION_PRINT -- Print the location on the stream.
- This macro was not mandated originally: define only if we know
- we won't break user code: when these are the locations we know. */
-
-#ifndef YY_LOCATION_PRINT
-# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
-# define YY_LOCATION_PRINT(File, Loc) \
- fprintf (File, "%d.%d-%d.%d", \
- (Loc).first_line, (Loc).first_column, \
- (Loc).last_line, (Loc).last_column)
-# else
-# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
-# endif
-#endif
-
-
-/* YYLEX -- calling `yylex' with the right arguments. */
-
-#ifdef YYLEX_PARAM
-# define YYLEX yylex (YYLEX_PARAM)
-#else
-# define YYLEX yylex ()
-#endif
-
-/* Enable debugging if requested. */
-#if YYDEBUG
-
-# ifndef YYFPRINTF
-# include <stdio.h> /* INFRINGES ON USER NAME SPACE */
-# define YYFPRINTF fprintf
-# endif
-
-# define YYDPRINTF(Args) \
-do { \
- if (yydebug) \
- YYFPRINTF Args; \
-} while (YYID (0))
-
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
-do { \
- if (yydebug) \
- { \
- YYFPRINTF (stderr, "%s ", Title); \
- yy_symbol_print (stderr, \
- Type, Value); \
- YYFPRINTF (stderr, "\n"); \
- } \
-} while (YYID (0))
-
-
-/*--------------------------------.
-| Print this symbol on YYOUTPUT. |
-`--------------------------------*/
-
-/*ARGSUSED*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-static void
-yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
-#else
-static void
-yy_symbol_value_print (yyoutput, yytype, yyvaluep)
- FILE *yyoutput;
- int yytype;
- YYSTYPE const * const yyvaluep;
-#endif
-{
- if (!yyvaluep)
- return;
-# ifdef YYPRINT
- if (yytype < YYNTOKENS)
- YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
-# else
- YYUSE (yyoutput);
-# endif
- switch (yytype)
- {
- default:
- break;
- }
-}
-
-
-/*--------------------------------.
-| Print this symbol on YYOUTPUT. |
-`--------------------------------*/
-
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-static void
-yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
-#else
-static void
-yy_symbol_print (yyoutput, yytype, yyvaluep)
- FILE *yyoutput;
- int yytype;
- YYSTYPE const * const yyvaluep;
-#endif
-{
- if (yytype < YYNTOKENS)
- YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
- else
- YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
-
- yy_symbol_value_print (yyoutput, yytype, yyvaluep);
- YYFPRINTF (yyoutput, ")");
-}
-
-/*------------------------------------------------------------------.
-| yy_stack_print -- Print the state stack from its BOTTOM up to its |
-| TOP (included). |
-`------------------------------------------------------------------*/
-
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-static void
-yy_stack_print (yytype_int16 *bottom, yytype_int16 *top)
-#else
-static void
-yy_stack_print (bottom, top)
- yytype_int16 *bottom;
- yytype_int16 *top;
-#endif
-{
- YYFPRINTF (stderr, "Stack now");
- for (; bottom <= top; ++bottom)
- YYFPRINTF (stderr, " %d", *bottom);
- YYFPRINTF (stderr, "\n");
-}
-
-# define YY_STACK_PRINT(Bottom, Top) \
-do { \
- if (yydebug) \
- yy_stack_print ((Bottom), (Top)); \
-} while (YYID (0))
-
-
-/*------------------------------------------------.
-| Report that the YYRULE is going to be reduced. |
-`------------------------------------------------*/
-
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-static void
-yy_reduce_print (YYSTYPE *yyvsp, int yyrule)
-#else
-static void
-yy_reduce_print (yyvsp, yyrule)
- YYSTYPE *yyvsp;
- int yyrule;
-#endif
-{
- int yynrhs = yyr2[yyrule];
- int yyi;
- unsigned long int yylno = yyrline[yyrule];
- YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
- yyrule - 1, yylno);
- /* The symbols being reduced. */
- for (yyi = 0; yyi < yynrhs; yyi++)
- {
- fprintf (stderr, " $%d = ", yyi + 1);
- yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
- &(yyvsp[(yyi + 1) - (yynrhs)])
- );
- fprintf (stderr, "\n");
- }
-}
-
-# define YY_REDUCE_PRINT(Rule) \
-do { \
- if (yydebug) \
- yy_reduce_print (yyvsp, Rule); \
-} while (YYID (0))
-
-/* Nonzero means print parse trace. It is left uninitialized so that
- multiple parsers can coexist. */
-int yydebug;
-#else /* !YYDEBUG */
-# define YYDPRINTF(Args)
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
-# define YY_STACK_PRINT(Bottom, Top)
-# define YY_REDUCE_PRINT(Rule)
-#endif /* !YYDEBUG */
-
-
-/* YYINITDEPTH -- initial size of the parser's stacks. */
-#ifndef YYINITDEPTH
-# define YYINITDEPTH 200
-#endif
-
-/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
- if the built-in stack extension method is used).
-
- Do not make this value too large; the results are undefined if
- YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
- evaluated with infinite-precision integer arithmetic. */
-
-#ifndef YYMAXDEPTH
-# define YYMAXDEPTH 10000
-#endif
-
-
-
-#if YYERROR_VERBOSE
-
-# ifndef yystrlen
-# if defined __GLIBC__ && defined _STRING_H
-# define yystrlen strlen
-# else
-/* Return the length of YYSTR. */
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-static YYSIZE_T
-yystrlen (const char *yystr)
-#else
-static YYSIZE_T
-yystrlen (yystr)
- const char *yystr;
-#endif
-{
- YYSIZE_T yylen;
- for (yylen = 0; yystr[yylen]; yylen++)
- continue;
- return yylen;
-}
-# endif
-# endif
-
-# ifndef yystpcpy
-# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
-# define yystpcpy stpcpy
-# else
-/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
- YYDEST. */
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-static char *
-yystpcpy (char *yydest, const char *yysrc)
-#else
-static char *
-yystpcpy (yydest, yysrc)
- char *yydest;
- const char *yysrc;
-#endif
-{
- char *yyd = yydest;
- const char *yys = yysrc;
-
- while ((*yyd++ = *yys++) != '\0')
- continue;
-
- return yyd - 1;
-}
-# endif
-# endif
-
-# ifndef yytnamerr
-/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
- quotes and backslashes, so that it's suitable for yyerror. The
- heuristic is that double-quoting is unnecessary unless the string
- contains an apostrophe, a comma, or backslash (other than
- backslash-backslash). YYSTR is taken from yytname. If YYRES is
- null, do not copy; instead, return the length of what the result
- would have been. */
-static YYSIZE_T
-yytnamerr (char *yyres, const char *yystr)
-{
- if (*yystr == '"')
- {
- YYSIZE_T yyn = 0;
- char const *yyp = yystr;
-
- for (;;)
- switch (*++yyp)
- {
- case '\'':
- case ',':
- goto do_not_strip_quotes;
-
- case '\\':
- if (*++yyp != '\\')
- goto do_not_strip_quotes;
- /* Fall through. */
- default:
- if (yyres)
- yyres[yyn] = *yyp;
- yyn++;
- break;
-
- case '"':
- if (yyres)
- yyres[yyn] = '\0';
- return yyn;
- }
- do_not_strip_quotes: ;
- }
-
- if (! yyres)
- return yystrlen (yystr);
-
- return yystpcpy (yyres, yystr) - yyres;
-}
-# endif
-
-/* Copy into YYRESULT an error message about the unexpected token
- YYCHAR while in state YYSTATE. Return the number of bytes copied,
- including the terminating null byte. If YYRESULT is null, do not
- copy anything; just return the number of bytes that would be
- copied. As a special case, return 0 if an ordinary "syntax error"
- message will do. Return YYSIZE_MAXIMUM if overflow occurs during
- size calculation. */
-static YYSIZE_T
-yysyntax_error (char *yyresult, int yystate, int yychar)
-{
- int yyn = yypact[yystate];
-
- if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
- return 0;
- else
- {
- int yytype = YYTRANSLATE (yychar);
- YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
- YYSIZE_T yysize = yysize0;
- YYSIZE_T yysize1;
- int yysize_overflow = 0;
- enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
- char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
- int yyx;
-
-# if 0
- /* This is so xgettext sees the translatable formats that are
- constructed on the fly. */
- YY_("syntax error, unexpected %s");
- YY_("syntax error, unexpected %s, expecting %s");
- YY_("syntax error, unexpected %s, expecting %s or %s");
- YY_("syntax error, unexpected %s, expecting %s or %s or %s");
- YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
-# endif
- char *yyfmt;
- char const *yyf;
- static char const yyunexpected[] = "syntax error, unexpected %s";
- static char const yyexpecting[] = ", expecting %s";
- static char const yyor[] = " or %s";
- char yyformat[sizeof yyunexpected
- + sizeof yyexpecting - 1
- + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
- * (sizeof yyor - 1))];
- char const *yyprefix = yyexpecting;
-
- /* Start YYX at -YYN if negative to avoid negative indexes in
- YYCHECK. */
- int yyxbegin = yyn < 0 ? -yyn : 0;
-
- /* Stay within bounds of both yycheck and yytname. */
- int yychecklim = YYLAST - yyn + 1;
- int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
- int yycount = 1;
-
- yyarg[0] = yytname[yytype];
- yyfmt = yystpcpy (yyformat, yyunexpected);
-
- for (yyx = yyxbegin; yyx < yyxend; ++yyx)
- if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
- {
- if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
- {
- yycount = 1;
- yysize = yysize0;
- yyformat[sizeof yyunexpected - 1] = '\0';
- break;
- }
- yyarg[yycount++] = yytname[yyx];
- yysize1 = yysize + yytnamerr (0, yytname[yyx]);
- yysize_overflow |= (yysize1 < yysize);
- yysize = yysize1;
- yyfmt = yystpcpy (yyfmt, yyprefix);
- yyprefix = yyor;
- }
-
- yyf = YY_(yyformat);
- yysize1 = yysize + yystrlen (yyf);
- yysize_overflow |= (yysize1 < yysize);
- yysize = yysize1;
-
- if (yysize_overflow)
- return YYSIZE_MAXIMUM;
-
- if (yyresult)
- {
- /* Avoid sprintf, as that infringes on the user's name space.
- Don't have undefined behavior even if the translation
- produced a string with the wrong number of "%s"s. */
- char *yyp = yyresult;
- int yyi = 0;
- while ((*yyp = *yyf) != '\0')
- {
- if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
- {
- yyp += yytnamerr (yyp, yyarg[yyi++]);
- yyf += 2;
- }
- else
- {
- yyp++;
- yyf++;
- }
- }
- }
- return yysize;
- }
-}
-#endif /* YYERROR_VERBOSE */
-
-
-/*-----------------------------------------------.
-| Release the memory associated to this symbol. |
-`-----------------------------------------------*/
-
-/*ARGSUSED*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-static void
-yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep)
-#else
-static void
-yydestruct (yymsg, yytype, yyvaluep)
- const char *yymsg;
- int yytype;
- YYSTYPE *yyvaluep;
-#endif
-{
- YYUSE (yyvaluep);
-
- if (!yymsg)
- yymsg = "Deleting";
- YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
-
- switch (yytype)
- {
-
- default:
- break;
- }
-}
-
-
-/* Prevent warnings from -Wmissing-prototypes. */
-
-#ifdef YYPARSE_PARAM
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void *YYPARSE_PARAM);
-#else
-int yyparse ();
-#endif
-#else /* ! YYPARSE_PARAM */
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void);
-#else
-int yyparse ();
-#endif
-#endif /* ! YYPARSE_PARAM */
-
-
-
-/* The look-ahead symbol. */
-int yychar;
-
-/* The semantic value of the look-ahead symbol. */
-YYSTYPE yylval;
-
-/* Number of syntax errors so far. */
-int yynerrs;
-
-
-
-/*----------.
-| yyparse. |
-`----------*/
-
-#ifdef YYPARSE_PARAM
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-int
-yyparse (void *YYPARSE_PARAM)
-#else
-int
-yyparse (YYPARSE_PARAM)
- void *YYPARSE_PARAM;
-#endif
-#else /* ! YYPARSE_PARAM */
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-int
-yyparse (void)
-#else
-int
-yyparse ()
-
-#endif
-#endif
-{
-
- int yystate;
- int yyn;
- int yyresult;
- /* Number of tokens to shift before error messages enabled. */
- int yyerrstatus;
- /* Look-ahead token as an internal (translated) token number. */
- int yytoken = 0;
-#if YYERROR_VERBOSE
- /* Buffer for error messages, and its allocated size. */
- char yymsgbuf[128];
- char *yymsg = yymsgbuf;
- YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
-#endif
-
- /* Three stacks and their tools:
- `yyss': related to states,
- `yyvs': related to semantic values,
- `yyls': related to locations.
-
- Refer to the stacks thru separate pointers, to allow yyoverflow
- to reallocate them elsewhere. */
-
- /* The state stack. */
- yytype_int16 yyssa[YYINITDEPTH];
- yytype_int16 *yyss = yyssa;
- yytype_int16 *yyssp;
-
- /* The semantic value stack. */
- YYSTYPE yyvsa[YYINITDEPTH];
- YYSTYPE *yyvs = yyvsa;
- YYSTYPE *yyvsp;
-
-
-
-#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N))
-
- YYSIZE_T yystacksize = YYINITDEPTH;
-
- /* The variables used to return semantic value and location from the
- action routines. */
- YYSTYPE yyval;
-
-
- /* The number of symbols on the RHS of the reduced rule.
- Keep to zero when no symbol should be popped. */
- int yylen = 0;
-
- YYDPRINTF ((stderr, "Starting parse\n"));
-
- yystate = 0;
- yyerrstatus = 0;
- yynerrs = 0;
- yychar = YYEMPTY; /* Cause a token to be read. */
-
- /* Initialize stack pointers.
- Waste one element of value and location stack
- so that they stay on the same level as the state stack.
- The wasted elements are never initialized. */
-
- yyssp = yyss;
- yyvsp = yyvs;
-
- goto yysetstate;
-
-/*------------------------------------------------------------.
-| yynewstate -- Push a new state, which is found in yystate. |
-`------------------------------------------------------------*/
- yynewstate:
- /* In all cases, when you get here, the value and location stacks
- have just been pushed. So pushing a state here evens the stacks. */
- yyssp++;
-
- yysetstate:
- *yyssp = yystate;
-
- if (yyss + yystacksize - 1 <= yyssp)
- {
- /* Get the current used size of the three stacks, in elements. */
- YYSIZE_T yysize = yyssp - yyss + 1;
-
-#ifdef yyoverflow
- {
- /* Give user a chance to reallocate the stack. Use copies of
- these so that the &'s don't force the real ones into
- memory. */
- YYSTYPE *yyvs1 = yyvs;
- yytype_int16 *yyss1 = yyss;
-
-
- /* Each stack pointer address is followed by the size of the
- data in use in that stack, in bytes. This used to be a
- conditional around just the two extra args, but that might
- be undefined if yyoverflow is a macro. */
- yyoverflow (YY_("memory exhausted"),
- &yyss1, yysize * sizeof (*yyssp),
- &yyvs1, yysize * sizeof (*yyvsp),
-
- &yystacksize);
-
- yyss = yyss1;
- yyvs = yyvs1;
- }
-#else /* no yyoverflow */
-# ifndef YYSTACK_RELOCATE
- goto yyexhaustedlab;
-# else
- /* Extend the stack our own way. */
- if (YYMAXDEPTH <= yystacksize)
- goto yyexhaustedlab;
- yystacksize *= 2;
- if (YYMAXDEPTH < yystacksize)
- yystacksize = YYMAXDEPTH;
-
- {
- yytype_int16 *yyss1 = yyss;
- union yyalloc *yyptr =
- (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
- if (! yyptr)
- goto yyexhaustedlab;
- YYSTACK_RELOCATE (yyss);
- YYSTACK_RELOCATE (yyvs);
-
-# undef YYSTACK_RELOCATE
- if (yyss1 != yyssa)
- YYSTACK_FREE (yyss1);
- }
-# endif
-#endif /* no yyoverflow */
-
- yyssp = yyss + yysize - 1;
- yyvsp = yyvs + yysize - 1;
-
-
- YYDPRINTF ((stderr, "Stack size increased to %lu\n",
- (unsigned long int) yystacksize));
-
- if (yyss + yystacksize - 1 <= yyssp)
- YYABORT;
- }
-
- YYDPRINTF ((stderr, "Entering state %d\n", yystate));
-
- goto yybackup;
-
-/*-----------.
-| yybackup. |
-`-----------*/
-yybackup:
-
- /* Do appropriate processing given the current state. Read a
- look-ahead token if we need one and don't already have one. */
-
- /* First try to decide what to do without reference to look-ahead token. */
- yyn = yypact[yystate];
- if (yyn == YYPACT_NINF)
- goto yydefault;
-
- /* Not known => get a look-ahead token if don't already have one. */
-
- /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */
- if (yychar == YYEMPTY)
- {
- YYDPRINTF ((stderr, "Reading a token: "));
- yychar = YYLEX;
- }
-
- if (yychar <= YYEOF)
- {
- yychar = yytoken = YYEOF;
- YYDPRINTF ((stderr, "Now at end of input.\n"));
- }
- else
- {
- yytoken = YYTRANSLATE (yychar);
- YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
- }
-
- /* If the proper action on seeing token YYTOKEN is to reduce or to
- detect an error, take that action. */
- yyn += yytoken;
- if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
- goto yydefault;
- yyn = yytable[yyn];
- if (yyn <= 0)
- {
- if (yyn == 0 || yyn == YYTABLE_NINF)
- goto yyerrlab;
- yyn = -yyn;
- goto yyreduce;
- }
-
- if (yyn == YYFINAL)
- YYACCEPT;
-
- /* Count tokens shifted since error; after three, turn off error
- status. */
- if (yyerrstatus)
- yyerrstatus--;
-
- /* Shift the look-ahead token. */
- YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
-
- /* Discard the shifted token unless it is eof. */
- if (yychar != YYEOF)
- yychar = YYEMPTY;
-
- yystate = yyn;
- *++yyvsp = yylval;
-
- goto yynewstate;
-
-
-/*-----------------------------------------------------------.
-| yydefault -- do the default action for the current state. |
-`-----------------------------------------------------------*/
-yydefault:
- yyn = yydefact[yystate];
- if (yyn == 0)
- goto yyerrlab;
- goto yyreduce;
-
-
-/*-----------------------------.
-| yyreduce -- Do a reduction. |
-`-----------------------------*/
-yyreduce:
- /* yyn is the number of a rule to reduce with. */
- yylen = yyr2[yyn];
-
- /* If YYLEN is nonzero, implement the default value of the action:
- `$$ = $1'.
-
- Otherwise, the following line sets YYVAL to garbage.
- This behavior is undocumented and Bison
- users should not rely upon it. Assigning to YYVAL
- unconditionally makes the parser a bit smaller, and it avoids a
- GCC warning that YYVAL may be used uninitialized. */
- yyval = yyvsp[1-yylen];
-
-
- YY_REDUCE_PRINT (yyn);
- switch (yyn)
- {
- case 4:
-#line 109 "cc.y"
- {
- dodecl(xdecl, lastclass, lasttype, Z);
- }
- break;
-
- case 6:
-#line 114 "cc.y"
- {
- lastdcl = T;
- firstarg = S;
- dodecl(xdecl, lastclass, lasttype, (yyvsp[(2) - (2)].node));
- if(lastdcl == T || lastdcl->etype != TFUNC) {
- diag((yyvsp[(2) - (2)].node), "not a function");
- lastdcl = types[TFUNC];
- }
- thisfn = lastdcl;
- markdcl();
- firstdcl = dclstack;
- argmark((yyvsp[(2) - (2)].node), 0);
- }
- break;
-
- case 7:
-#line 128 "cc.y"
- {
- argmark((yyvsp[(2) - (4)].node), 1);
- }
- break;
-
- case 8:
-#line 132 "cc.y"
- {
- Node *n;
-
- n = revertdcl();
- if(n)
- (yyvsp[(6) - (6)].node) = new(OLIST, n, (yyvsp[(6) - (6)].node));
- if(!debug['a'] && !debug['Z'])
- codgen((yyvsp[(6) - (6)].node), (yyvsp[(2) - (6)].node));
- }
- break;
-
- case 9:
-#line 144 "cc.y"
- {
- dodecl(xdecl, lastclass, lasttype, (yyvsp[(1) - (1)].node));
- }
- break;
-
- case 10:
-#line 148 "cc.y"
- {
- (yyvsp[(1) - (1)].node) = dodecl(xdecl, lastclass, lasttype, (yyvsp[(1) - (1)].node));
- }
- break;
-
- case 11:
-#line 152 "cc.y"
- {
- doinit((yyvsp[(1) - (4)].node)->sym, (yyvsp[(1) - (4)].node)->type, 0L, (yyvsp[(4) - (4)].node));
- }
- break;
-
- case 14:
-#line 160 "cc.y"
- {
- (yyval.node) = new(OIND, (yyvsp[(3) - (3)].node), Z);
- (yyval.node)->garb = simpleg((yyvsp[(2) - (3)].lval));
- }
- break;
-
- case 16:
-#line 168 "cc.y"
- {
- (yyval.node) = (yyvsp[(2) - (3)].node);
- }
- break;
-
- case 17:
-#line 172 "cc.y"
- {
- (yyval.node) = new(OFUNC, (yyvsp[(1) - (4)].node), (yyvsp[(3) - (4)].node));
- }
- break;
-
- case 18:
-#line 176 "cc.y"
- {
- (yyval.node) = new(OARRAY, (yyvsp[(1) - (4)].node), (yyvsp[(3) - (4)].node));
- }
- break;
-
- case 19:
-#line 185 "cc.y"
- {
- (yyval.node) = dodecl(adecl, lastclass, lasttype, Z);
- }
- break;
-
- case 20:
-#line 189 "cc.y"
- {
- (yyval.node) = (yyvsp[(2) - (3)].node);
- }
- break;
-
- case 21:
-#line 195 "cc.y"
- {
- dodecl(adecl, lastclass, lasttype, (yyvsp[(1) - (1)].node));
- (yyval.node) = Z;
- }
- break;
-
- case 22:
-#line 200 "cc.y"
- {
- (yyvsp[(1) - (1)].node) = dodecl(adecl, lastclass, lasttype, (yyvsp[(1) - (1)].node));
- }
- break;
-
- case 23:
-#line 204 "cc.y"
- {
- int32 w;
-
- w = (yyvsp[(1) - (4)].node)->sym->type->width;
- (yyval.node) = doinit((yyvsp[(1) - (4)].node)->sym, (yyvsp[(1) - (4)].node)->type, 0L, (yyvsp[(4) - (4)].node));
- (yyval.node) = contig((yyvsp[(1) - (4)].node)->sym, (yyval.node), w);
- }
- break;
-
- case 24:
-#line 212 "cc.y"
- {
- (yyval.node) = (yyvsp[(1) - (3)].node);
- if((yyvsp[(3) - (3)].node) != Z) {
- (yyval.node) = (yyvsp[(3) - (3)].node);
- if((yyvsp[(1) - (3)].node) != Z)
- (yyval.node) = new(OLIST, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
- }
- }
- break;
-
- case 27:
-#line 229 "cc.y"
- {
- dodecl(pdecl, lastclass, lasttype, (yyvsp[(1) - (1)].node));
- }
- break;
-
- case 29:
-#line 239 "cc.y"
- {
- lasttype = (yyvsp[(1) - (1)].type);
- }
- break;
-
- case 31:
-#line 244 "cc.y"
- {
- lasttype = (yyvsp[(2) - (2)].type);
- }
- break;
-
- case 33:
-#line 250 "cc.y"
- {
- lastfield = 0;
- edecl(CXXX, lasttype, S);
- }
- break;
-
- case 35:
-#line 258 "cc.y"
- {
- dodecl(edecl, CXXX, lasttype, (yyvsp[(1) - (1)].node));
- }
- break;
-
- case 37:
-#line 265 "cc.y"
- {
- lastbit = 0;
- firstbit = 1;
- }
- break;
-
- case 38:
-#line 270 "cc.y"
- {
- (yyval.node) = new(OBIT, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
- }
- break;
-
- case 39:
-#line 274 "cc.y"
- {
- (yyval.node) = new(OBIT, Z, (yyvsp[(2) - (2)].node));
- }
- break;
-
- case 40:
-#line 282 "cc.y"
- {
- (yyval.node) = (Z);
- }
- break;
-
- case 42:
-#line 289 "cc.y"
- {
- (yyval.node) = new(OIND, (Z), Z);
- (yyval.node)->garb = simpleg((yyvsp[(2) - (2)].lval));
- }
- break;
-
- case 43:
-#line 294 "cc.y"
- {
- (yyval.node) = new(OIND, (yyvsp[(3) - (3)].node), Z);
- (yyval.node)->garb = simpleg((yyvsp[(2) - (3)].lval));
- }
- break;
-
- case 46:
-#line 303 "cc.y"
- {
- (yyval.node) = new(OFUNC, (yyvsp[(1) - (4)].node), (yyvsp[(3) - (4)].node));
- }
- break;
-
- case 47:
-#line 307 "cc.y"
- {
- (yyval.node) = new(OARRAY, (yyvsp[(1) - (4)].node), (yyvsp[(3) - (4)].node));
- }
- break;
-
- case 48:
-#line 313 "cc.y"
- {
- (yyval.node) = new(OFUNC, (Z), Z);
- }
- break;
-
- case 49:
-#line 317 "cc.y"
- {
- (yyval.node) = new(OARRAY, (Z), (yyvsp[(2) - (3)].node));
- }
- break;
-
- case 50:
-#line 321 "cc.y"
- {
- (yyval.node) = (yyvsp[(2) - (3)].node);
- }
- break;
-
- case 52:
-#line 328 "cc.y"
- {
- (yyval.node) = new(OINIT, invert((yyvsp[(2) - (3)].node)), Z);
- }
- break;
-
- case 53:
-#line 334 "cc.y"
- {
- (yyval.node) = new(OARRAY, (yyvsp[(2) - (3)].node), Z);
- }
- break;
-
- case 54:
-#line 338 "cc.y"
- {
- (yyval.node) = new(OELEM, Z, Z);
- (yyval.node)->sym = (yyvsp[(2) - (2)].sym);
- }
- break;
-
- case 57:
-#line 347 "cc.y"
- {
- (yyval.node) = new(OLIST, (yyvsp[(1) - (3)].node), (yyvsp[(2) - (3)].node));
- }
- break;
-
- case 59:
-#line 352 "cc.y"
- {
- (yyval.node) = new(OLIST, (yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].node));
- }
- break;
-
- case 62:
-#line 360 "cc.y"
- {
- (yyval.node) = new(OLIST, (yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].node));
- }
- break;
-
- case 63:
-#line 365 "cc.y"
- {
- (yyval.node) = Z;
- }
- break;
-
- case 64:
-#line 369 "cc.y"
- {
- (yyval.node) = invert((yyvsp[(1) - (1)].node));
- }
- break;
-
- case 66:
-#line 377 "cc.y"
- {
- (yyval.node) = new(OPROTO, (yyvsp[(2) - (2)].node), Z);
- (yyval.node)->type = (yyvsp[(1) - (2)].type);
- }
- break;
-
- case 67:
-#line 382 "cc.y"
- {
- (yyval.node) = new(OPROTO, (yyvsp[(2) - (2)].node), Z);
- (yyval.node)->type = (yyvsp[(1) - (2)].type);
- }
- break;
-
- case 68:
-#line 387 "cc.y"
- {
- (yyval.node) = new(ODOTDOT, Z, Z);
- }
- break;
-
- case 69:
-#line 391 "cc.y"
- {
- (yyval.node) = new(OLIST, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
- }
- break;
-
- case 70:
-#line 397 "cc.y"
- {
- (yyval.node) = invert((yyvsp[(2) - (3)].node));
- // if($2 != Z)
- // $$ = new(OLIST, $2, $$);
- if((yyval.node) == Z)
- (yyval.node) = new(OLIST, Z, Z);
- }
- break;
-
- case 71:
-#line 406 "cc.y"
- {
- (yyval.node) = Z;
- }
- break;
-
- case 72:
-#line 410 "cc.y"
- {
- (yyval.node) = new(OLIST, (yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].node));
- }
- break;
-
- case 73:
-#line 414 "cc.y"
- {
- (yyval.node) = new(OLIST, (yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].node));
- }
- break;
-
- case 75:
-#line 421 "cc.y"
- {
- (yyval.node) = new(OLIST, (yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].node));
- }
- break;
-
- case 76:
-#line 427 "cc.y"
- {
- (yyval.node) = new(OCASE, (yyvsp[(2) - (3)].node), Z);
- }
- break;
-
- case 77:
-#line 431 "cc.y"
- {
- (yyval.node) = new(OCASE, Z, Z);
- }
- break;
-
- case 78:
-#line 435 "cc.y"
- {
- (yyval.node) = new(OLABEL, dcllabel((yyvsp[(1) - (2)].sym), 1), Z);
- }
- break;
-
- case 79:
-#line 441 "cc.y"
- {
- (yyval.node) = Z;
- }
- break;
-
- case 81:
-#line 446 "cc.y"
- {
- (yyval.node) = new(OLIST, (yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].node));
- }
- break;
-
- case 83:
-#line 453 "cc.y"
- {
- (yyval.node) = (yyvsp[(2) - (2)].node);
- }
- break;
-
- case 85:
-#line 459 "cc.y"
- {
- markdcl();
- }
- break;
-
- case 86:
-#line 463 "cc.y"
- {
- (yyval.node) = revertdcl();
- if((yyval.node))
- (yyval.node) = new(OLIST, (yyval.node), (yyvsp[(2) - (2)].node));
- else
- (yyval.node) = (yyvsp[(2) - (2)].node);
- }
- break;
-
- case 87:
-#line 471 "cc.y"
- {
- (yyval.node) = new(OIF, (yyvsp[(3) - (5)].node), new(OLIST, (yyvsp[(5) - (5)].node), Z));
- if((yyvsp[(5) - (5)].node) == Z)
- warn((yyvsp[(3) - (5)].node), "empty if body");
- }
- break;
-
- case 88:
-#line 477 "cc.y"
- {
- (yyval.node) = new(OIF, (yyvsp[(3) - (7)].node), new(OLIST, (yyvsp[(5) - (7)].node), (yyvsp[(7) - (7)].node)));
- if((yyvsp[(5) - (7)].node) == Z)
- warn((yyvsp[(3) - (7)].node), "empty if body");
- if((yyvsp[(7) - (7)].node) == Z)
- warn((yyvsp[(3) - (7)].node), "empty else body");
- }
- break;
-
- case 89:
-#line 484 "cc.y"
- { markdcl(); }
- break;
-
- case 90:
-#line 485 "cc.y"
- {
- (yyval.node) = revertdcl();
- if((yyval.node)){
- if((yyvsp[(4) - (10)].node))
- (yyvsp[(4) - (10)].node) = new(OLIST, (yyval.node), (yyvsp[(4) - (10)].node));
- else
- (yyvsp[(4) - (10)].node) = (yyval.node);
- }
- (yyval.node) = new(OFOR, new(OLIST, (yyvsp[(6) - (10)].node), new(OLIST, (yyvsp[(4) - (10)].node), (yyvsp[(8) - (10)].node))), (yyvsp[(10) - (10)].node));
- }
- break;
-
- case 91:
-#line 496 "cc.y"
- {
- (yyval.node) = new(OWHILE, (yyvsp[(3) - (5)].node), (yyvsp[(5) - (5)].node));
- }
- break;
-
- case 92:
-#line 500 "cc.y"
- {
- (yyval.node) = new(ODWHILE, (yyvsp[(5) - (7)].node), (yyvsp[(2) - (7)].node));
- }
- break;
-
- case 93:
-#line 504 "cc.y"
- {
- (yyval.node) = new(ORETURN, (yyvsp[(2) - (3)].node), Z);
- (yyval.node)->type = thisfn->link;
- }
- break;
-
- case 94:
-#line 509 "cc.y"
- {
- (yyval.node) = new(OCONST, Z, Z);
- (yyval.node)->vconst = 0;
- (yyval.node)->type = types[TINT];
- (yyvsp[(3) - (5)].node) = new(OSUB, (yyval.node), (yyvsp[(3) - (5)].node));
-
- (yyval.node) = new(OCONST, Z, Z);
- (yyval.node)->vconst = 0;
- (yyval.node)->type = types[TINT];
- (yyvsp[(3) - (5)].node) = new(OSUB, (yyval.node), (yyvsp[(3) - (5)].node));
-
- (yyval.node) = new(OSWITCH, (yyvsp[(3) - (5)].node), (yyvsp[(5) - (5)].node));
- }
- break;
-
- case 95:
-#line 523 "cc.y"
- {
- (yyval.node) = new(OBREAK, Z, Z);
- }
- break;
-
- case 96:
-#line 527 "cc.y"
- {
- (yyval.node) = new(OCONTINUE, Z, Z);
- }
- break;
-
- case 97:
-#line 531 "cc.y"
- {
- (yyval.node) = new(OGOTO, dcllabel((yyvsp[(2) - (3)].sym), 0), Z);
- }
- break;
-
- case 98:
-#line 535 "cc.y"
- {
- (yyval.node) = new(OUSED, (yyvsp[(3) - (5)].node), Z);
- }
- break;
-
- case 99:
-#line 539 "cc.y"
- {
- (yyval.node) = new(OPREFETCH, (yyvsp[(3) - (5)].node), Z);
- }
- break;
-
- case 100:
-#line 543 "cc.y"
- {
- (yyval.node) = new(OSET, (yyvsp[(3) - (5)].node), Z);
- }
- break;
-
- case 101:
-#line 548 "cc.y"
- {
- (yyval.node) = Z;
- }
- break;
-
- case 103:
-#line 554 "cc.y"
- {
- (yyval.node) = Z;
- }
- break;
-
- case 105:
-#line 561 "cc.y"
- {
- (yyval.node) = new(OCAST, (yyvsp[(1) - (1)].node), Z);
- (yyval.node)->type = types[TLONG];
- }
- break;
-
- case 107:
-#line 569 "cc.y"
- {
- (yyval.node) = new(OCOMMA, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
- }
- break;
-
- case 109:
-#line 576 "cc.y"
- {
- (yyval.node) = new(OMUL, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
- }
- break;
-
- case 110:
-#line 580 "cc.y"
- {
- (yyval.node) = new(ODIV, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
- }
- break;
-
- case 111:
-#line 584 "cc.y"
- {
- (yyval.node) = new(OMOD, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
- }
- break;
-
- case 112:
-#line 588 "cc.y"
- {
- (yyval.node) = new(OADD, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
- }
- break;
-
- case 113:
-#line 592 "cc.y"
- {
- (yyval.node) = new(OSUB, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
- }
- break;
-
- case 114:
-#line 596 "cc.y"
- {
- (yyval.node) = new(OASHR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
- }
- break;
-
- case 115:
-#line 600 "cc.y"
- {
- (yyval.node) = new(OASHL, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
- }
- break;
-
- case 116:
-#line 604 "cc.y"
- {
- (yyval.node) = new(OLT, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
- }
- break;
-
- case 117:
-#line 608 "cc.y"
- {
- (yyval.node) = new(OGT, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
- }
- break;
-
- case 118:
-#line 612 "cc.y"
- {
- (yyval.node) = new(OLE, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
- }
- break;
-
- case 119:
-#line 616 "cc.y"
- {
- (yyval.node) = new(OGE, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
- }
- break;
-
- case 120:
-#line 620 "cc.y"
- {
- (yyval.node) = new(OEQ, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
- }
- break;
-
- case 121:
-#line 624 "cc.y"
- {
- (yyval.node) = new(ONE, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
- }
- break;
-
- case 122:
-#line 628 "cc.y"
- {
- (yyval.node) = new(OAND, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
- }
- break;
-
- case 123:
-#line 632 "cc.y"
- {
- (yyval.node) = new(OXOR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
- }
- break;
-
- case 124:
-#line 636 "cc.y"
- {
- (yyval.node) = new(OOR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
- }
- break;
-
- case 125:
-#line 640 "cc.y"
- {
- (yyval.node) = new(OANDAND, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
- }
- break;
-
- case 126:
-#line 644 "cc.y"
- {
- (yyval.node) = new(OOROR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
- }
- break;
-
- case 127:
-#line 648 "cc.y"
- {
- (yyval.node) = new(OCOND, (yyvsp[(1) - (5)].node), new(OLIST, (yyvsp[(3) - (5)].node), (yyvsp[(5) - (5)].node)));
- }
- break;
-
- case 128:
-#line 652 "cc.y"
- {
- (yyval.node) = new(OAS, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
- }
- break;
-
- case 129:
-#line 656 "cc.y"
- {
- (yyval.node) = new(OASADD, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
- }
- break;
-
- case 130:
-#line 660 "cc.y"
- {
- (yyval.node) = new(OASSUB, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
- }
- break;
-
- case 131:
-#line 664 "cc.y"
- {
- (yyval.node) = new(OASMUL, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
- }
- break;
-
- case 132:
-#line 668 "cc.y"
- {
- (yyval.node) = new(OASDIV, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
- }
- break;
-
- case 133:
-#line 672 "cc.y"
- {
- (yyval.node) = new(OASMOD, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
- }
- break;
-
- case 134:
-#line 676 "cc.y"
- {
- (yyval.node) = new(OASASHL, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
- }
- break;
-
- case 135:
-#line 680 "cc.y"
- {
- (yyval.node) = new(OASASHR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
- }
- break;
-
- case 136:
-#line 684 "cc.y"
- {
- (yyval.node) = new(OASAND, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
- }
- break;
-
- case 137:
-#line 688 "cc.y"
- {
- (yyval.node) = new(OASXOR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
- }
- break;
-
- case 138:
-#line 692 "cc.y"
- {
- (yyval.node) = new(OASOR, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
- }
- break;
-
- case 140:
-#line 699 "cc.y"
- {
- (yyval.node) = new(OCAST, (yyvsp[(5) - (5)].node), Z);
- dodecl(NODECL, CXXX, (yyvsp[(2) - (5)].type), (yyvsp[(3) - (5)].node));
- (yyval.node)->type = lastdcl;
- (yyval.node)->xcast = 1;
- }
- break;
-
- case 141:
-#line 706 "cc.y"
- {
- (yyval.node) = new(OSTRUCT, (yyvsp[(6) - (7)].node), Z);
- dodecl(NODECL, CXXX, (yyvsp[(2) - (7)].type), (yyvsp[(3) - (7)].node));
- (yyval.node)->type = lastdcl;
- }
- break;
-
- case 143:
-#line 715 "cc.y"
- {
- (yyval.node) = new(OIND, (yyvsp[(2) - (2)].node), Z);
- }
- break;
-
- case 144:
-#line 719 "cc.y"
- {
- (yyval.node) = new(OADDR, (yyvsp[(2) - (2)].node), Z);
- }
- break;
-
- case 145:
-#line 723 "cc.y"
- {
- (yyval.node) = new(OPOS, (yyvsp[(2) - (2)].node), Z);
- }
- break;
-
- case 146:
-#line 727 "cc.y"
- {
- (yyval.node) = new(ONEG, (yyvsp[(2) - (2)].node), Z);
- }
- break;
-
- case 147:
-#line 731 "cc.y"
- {
- (yyval.node) = new(ONOT, (yyvsp[(2) - (2)].node), Z);
- }
- break;
-
- case 148:
-#line 735 "cc.y"
- {
- (yyval.node) = new(OCOM, (yyvsp[(2) - (2)].node), Z);
- }
- break;
-
- case 149:
-#line 739 "cc.y"
- {
- (yyval.node) = new(OPREINC, (yyvsp[(2) - (2)].node), Z);
- }
- break;
-
- case 150:
-#line 743 "cc.y"
- {
- (yyval.node) = new(OPREDEC, (yyvsp[(2) - (2)].node), Z);
- }
- break;
-
- case 151:
-#line 747 "cc.y"
- {
- (yyval.node) = new(OSIZE, (yyvsp[(2) - (2)].node), Z);
- }
- break;
-
- case 152:
-#line 751 "cc.y"
- {
- (yyval.node) = new(OSIGN, (yyvsp[(2) - (2)].node), Z);
- }
- break;
-
- case 153:
-#line 757 "cc.y"
- {
- (yyval.node) = (yyvsp[(2) - (3)].node);
- }
- break;
-
- case 154:
-#line 761 "cc.y"
- {
- (yyval.node) = new(OSIZE, Z, Z);
- dodecl(NODECL, CXXX, (yyvsp[(3) - (5)].type), (yyvsp[(4) - (5)].node));
- (yyval.node)->type = lastdcl;
- }
- break;
-
- case 155:
-#line 767 "cc.y"
- {
- (yyval.node) = new(OSIGN, Z, Z);
- dodecl(NODECL, CXXX, (yyvsp[(3) - (5)].type), (yyvsp[(4) - (5)].node));
- (yyval.node)->type = lastdcl;
- }
- break;
-
- case 156:
-#line 773 "cc.y"
- {
- (yyval.node) = new(OFUNC, (yyvsp[(1) - (4)].node), Z);
- if((yyvsp[(1) - (4)].node)->op == ONAME)
- if((yyvsp[(1) - (4)].node)->type == T)
- dodecl(xdecl, CXXX, types[TINT], (yyval.node));
- (yyval.node)->right = invert((yyvsp[(3) - (4)].node));
- }
- break;
-
- case 157:
-#line 781 "cc.y"
- {
- (yyval.node) = new(OIND, new(OADD, (yyvsp[(1) - (4)].node), (yyvsp[(3) - (4)].node)), Z);
- }
- break;
-
- case 158:
-#line 785 "cc.y"
- {
- (yyval.node) = new(ODOT, new(OIND, (yyvsp[(1) - (3)].node), Z), Z);
- (yyval.node)->sym = (yyvsp[(3) - (3)].sym);
- }
- break;
-
- case 159:
-#line 790 "cc.y"
- {
- (yyval.node) = new(ODOT, (yyvsp[(1) - (3)].node), Z);
- (yyval.node)->sym = (yyvsp[(3) - (3)].sym);
- }
- break;
-
- case 160:
-#line 795 "cc.y"
- {
- (yyval.node) = new(OPOSTINC, (yyvsp[(1) - (2)].node), Z);
- }
- break;
-
- case 161:
-#line 799 "cc.y"
- {
- (yyval.node) = new(OPOSTDEC, (yyvsp[(1) - (2)].node), Z);
- }
- break;
-
- case 163:
-#line 804 "cc.y"
- {
- (yyval.node) = new(OCONST, Z, Z);
- (yyval.node)->type = types[TINT];
- (yyval.node)->vconst = (yyvsp[(1) - (1)].vval);
- (yyval.node)->cstring = strdup(symb);
- }
- break;
-
- case 164:
-#line 811 "cc.y"
- {
- (yyval.node) = new(OCONST, Z, Z);
- (yyval.node)->type = types[TLONG];
- (yyval.node)->vconst = (yyvsp[(1) - (1)].vval);
- (yyval.node)->cstring = strdup(symb);
- }
- break;
-
- case 165:
-#line 818 "cc.y"
- {
- (yyval.node) = new(OCONST, Z, Z);
- (yyval.node)->type = types[TUINT];
- (yyval.node)->vconst = (yyvsp[(1) - (1)].vval);
- (yyval.node)->cstring = strdup(symb);
- }
- break;
-
- case 166:
-#line 825 "cc.y"
- {
- (yyval.node) = new(OCONST, Z, Z);
- (yyval.node)->type = types[TULONG];
- (yyval.node)->vconst = (yyvsp[(1) - (1)].vval);
- (yyval.node)->cstring = strdup(symb);
- }
- break;
-
- case 167:
-#line 832 "cc.y"
- {
- (yyval.node) = new(OCONST, Z, Z);
- (yyval.node)->type = types[TDOUBLE];
- (yyval.node)->fconst = (yyvsp[(1) - (1)].dval);
- (yyval.node)->cstring = strdup(symb);
- }
- break;
-
- case 168:
-#line 839 "cc.y"
- {
- (yyval.node) = new(OCONST, Z, Z);
- (yyval.node)->type = types[TFLOAT];
- (yyval.node)->fconst = (yyvsp[(1) - (1)].dval);
- (yyval.node)->cstring = strdup(symb);
- }
- break;
-
- case 169:
-#line 846 "cc.y"
- {
- (yyval.node) = new(OCONST, Z, Z);
- (yyval.node)->type = types[TVLONG];
- (yyval.node)->vconst = (yyvsp[(1) - (1)].vval);
- (yyval.node)->cstring = strdup(symb);
- }
- break;
-
- case 170:
-#line 853 "cc.y"
- {
- (yyval.node) = new(OCONST, Z, Z);
- (yyval.node)->type = types[TUVLONG];
- (yyval.node)->vconst = (yyvsp[(1) - (1)].vval);
- (yyval.node)->cstring = strdup(symb);
- }
- break;
-
- case 173:
-#line 864 "cc.y"
- {
- (yyval.node) = new(OSTRING, Z, Z);
- (yyval.node)->type = typ(TARRAY, types[TCHAR]);
- (yyval.node)->type->width = (yyvsp[(1) - (1)].sval).l + 1;
- (yyval.node)->cstring = (yyvsp[(1) - (1)].sval).s;
- (yyval.node)->sym = symstring;
- (yyval.node)->etype = TARRAY;
- (yyval.node)->class = CSTATIC;
- }
- break;
-
- case 174:
-#line 874 "cc.y"
- {
- char *s;
- int n;
-
- n = (yyvsp[(1) - (2)].node)->type->width - 1;
- s = alloc(n+(yyvsp[(2) - (2)].sval).l+MAXALIGN);
-
- memcpy(s, (yyvsp[(1) - (2)].node)->cstring, n);
- memcpy(s+n, (yyvsp[(2) - (2)].sval).s, (yyvsp[(2) - (2)].sval).l);
- s[n+(yyvsp[(2) - (2)].sval).l] = 0;
-
- (yyval.node) = (yyvsp[(1) - (2)].node);
- (yyval.node)->type->width += (yyvsp[(2) - (2)].sval).l;
- (yyval.node)->cstring = s;
- }
- break;
-
- case 175:
-#line 892 "cc.y"
- {
- (yyval.node) = new(OLSTRING, Z, Z);
- (yyval.node)->type = typ(TARRAY, types[TRUNE]);
- (yyval.node)->type->width = (yyvsp[(1) - (1)].sval).l + sizeof(TRune);
- (yyval.node)->rstring = (TRune*)(yyvsp[(1) - (1)].sval).s;
- (yyval.node)->sym = symstring;
- (yyval.node)->etype = TARRAY;
- (yyval.node)->class = CSTATIC;
- }
- break;
-
- case 176:
-#line 902 "cc.y"
- {
- char *s;
- int n;
-
- n = (yyvsp[(1) - (2)].node)->type->width - sizeof(TRune);
- s = alloc(n+(yyvsp[(2) - (2)].sval).l+MAXALIGN);
-
- memcpy(s, (yyvsp[(1) - (2)].node)->rstring, n);
- memcpy(s+n, (yyvsp[(2) - (2)].sval).s, (yyvsp[(2) - (2)].sval).l);
- *(TRune*)(s+n+(yyvsp[(2) - (2)].sval).l) = 0;
-
- (yyval.node) = (yyvsp[(1) - (2)].node);
- (yyval.node)->type->width += (yyvsp[(2) - (2)].sval).l;
- (yyval.node)->rstring = (TRune*)s;
- }
- break;
-
- case 177:
-#line 919 "cc.y"
- {
- (yyval.node) = Z;
- }
- break;
-
- case 180:
-#line 927 "cc.y"
- {
- (yyval.node) = new(OLIST, (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
- }
- break;
-
- case 181:
-#line 933 "cc.y"
- {
- (yyval.tyty).t1 = strf;
- (yyval.tyty).t2 = strl;
- (yyval.tyty).t3 = lasttype;
- (yyval.tyty).c = lastclass;
- strf = T;
- strl = T;
- lastbit = 0;
- firstbit = 1;
- lastclass = CXXX;
- lasttype = T;
- }
- break;
-
- case 182:
-#line 946 "cc.y"
- {
- (yyval.type) = strf;
- strf = (yyvsp[(2) - (4)].tyty).t1;
- strl = (yyvsp[(2) - (4)].tyty).t2;
- lasttype = (yyvsp[(2) - (4)].tyty).t3;
- lastclass = (yyvsp[(2) - (4)].tyty).c;
- }
- break;
-
- case 183:
-#line 955 "cc.y"
- {
- lastclass = CXXX;
- lasttype = types[TINT];
- }
- break;
-
- case 185:
-#line 963 "cc.y"
- {
- (yyval.tycl).t = (yyvsp[(1) - (1)].type);
- (yyval.tycl).c = CXXX;
- }
- break;
-
- case 186:
-#line 968 "cc.y"
- {
- (yyval.tycl).t = simplet((yyvsp[(1) - (1)].lval));
- (yyval.tycl).c = CXXX;
- }
- break;
-
- case 187:
-#line 973 "cc.y"
- {
- (yyval.tycl).t = simplet((yyvsp[(1) - (1)].lval));
- (yyval.tycl).c = simplec((yyvsp[(1) - (1)].lval));
- (yyval.tycl).t = garbt((yyval.tycl).t, (yyvsp[(1) - (1)].lval));
- }
- break;
-
- case 188:
-#line 979 "cc.y"
- {
- (yyval.tycl).t = (yyvsp[(1) - (2)].type);
- (yyval.tycl).c = simplec((yyvsp[(2) - (2)].lval));
- (yyval.tycl).t = garbt((yyval.tycl).t, (yyvsp[(2) - (2)].lval));
- if((yyvsp[(2) - (2)].lval) & ~BCLASS & ~BGARB)
- diag(Z, "duplicate types given: %T and %Q", (yyvsp[(1) - (2)].type), (yyvsp[(2) - (2)].lval));
- }
- break;
-
- case 189:
-#line 987 "cc.y"
- {
- (yyval.tycl).t = simplet(typebitor((yyvsp[(1) - (2)].lval), (yyvsp[(2) - (2)].lval)));
- (yyval.tycl).c = simplec((yyvsp[(2) - (2)].lval));
- (yyval.tycl).t = garbt((yyval.tycl).t, (yyvsp[(2) - (2)].lval));
- }
- break;
-
- case 190:
-#line 993 "cc.y"
- {
- (yyval.tycl).t = (yyvsp[(2) - (3)].type);
- (yyval.tycl).c = simplec((yyvsp[(1) - (3)].lval));
- (yyval.tycl).t = garbt((yyval.tycl).t, (yyvsp[(1) - (3)].lval)|(yyvsp[(3) - (3)].lval));
- }
- break;
-
- case 191:
-#line 999 "cc.y"
- {
- (yyval.tycl).t = simplet((yyvsp[(2) - (2)].lval));
- (yyval.tycl).c = simplec((yyvsp[(1) - (2)].lval));
- (yyval.tycl).t = garbt((yyval.tycl).t, (yyvsp[(1) - (2)].lval));
- }
- break;
-
- case 192:
-#line 1005 "cc.y"
- {
- (yyval.tycl).t = simplet(typebitor((yyvsp[(2) - (3)].lval), (yyvsp[(3) - (3)].lval)));
- (yyval.tycl).c = simplec((yyvsp[(1) - (3)].lval)|(yyvsp[(3) - (3)].lval));
- (yyval.tycl).t = garbt((yyval.tycl).t, (yyvsp[(1) - (3)].lval)|(yyvsp[(3) - (3)].lval));
- }
- break;
-
- case 193:
-#line 1013 "cc.y"
- {
- (yyval.type) = (yyvsp[(1) - (1)].tycl).t;
- if((yyvsp[(1) - (1)].tycl).c != CXXX)
- diag(Z, "illegal combination of class 4: %s", cnames[(yyvsp[(1) - (1)].tycl).c]);
- }
- break;
-
- case 194:
-#line 1021 "cc.y"
- {
- lasttype = (yyvsp[(1) - (1)].tycl).t;
- lastclass = (yyvsp[(1) - (1)].tycl).c;
- }
- break;
-
- case 195:
-#line 1028 "cc.y"
- {
- dotag((yyvsp[(2) - (2)].sym), TSTRUCT, 0);
- (yyval.type) = (yyvsp[(2) - (2)].sym)->suetag;
- }
- break;
-
- case 196:
-#line 1033 "cc.y"
- {
- dotag((yyvsp[(2) - (2)].sym), TSTRUCT, autobn);
- }
- break;
-
- case 197:
-#line 1037 "cc.y"
- {
- (yyval.type) = (yyvsp[(2) - (4)].sym)->suetag;
- if((yyval.type)->link != T)
- diag(Z, "redeclare tag: %s", (yyvsp[(2) - (4)].sym)->name);
- (yyval.type)->link = (yyvsp[(4) - (4)].type);
- sualign((yyval.type));
- }
- break;
-
- case 198:
-#line 1045 "cc.y"
- {
- diag(Z, "struct must have tag");
- taggen++;
- sprint(symb, "_%d_", taggen);
- (yyval.type) = dotag(lookup(), TSTRUCT, autobn);
- (yyval.type)->link = (yyvsp[(2) - (2)].type);
- sualign((yyval.type));
- }
- break;
-
- case 199:
-#line 1054 "cc.y"
- {
- dotag((yyvsp[(2) - (2)].sym), TUNION, 0);
- (yyval.type) = (yyvsp[(2) - (2)].sym)->suetag;
- }
- break;
-
- case 200:
-#line 1059 "cc.y"
- {
- dotag((yyvsp[(2) - (2)].sym), TUNION, autobn);
- }
- break;
-
- case 201:
-#line 1063 "cc.y"
- {
- (yyval.type) = (yyvsp[(2) - (4)].sym)->suetag;
- if((yyval.type)->link != T)
- diag(Z, "redeclare tag: %s", (yyvsp[(2) - (4)].sym)->name);
- (yyval.type)->link = (yyvsp[(4) - (4)].type);
- sualign((yyval.type));
- }
- break;
-
- case 202:
-#line 1071 "cc.y"
- {
- taggen++;
- sprint(symb, "_%d_", taggen);
- (yyval.type) = dotag(lookup(), TUNION, autobn);
- (yyval.type)->link = (yyvsp[(2) - (2)].type);
- sualign((yyval.type));
- }
- break;
-
- case 203:
-#line 1079 "cc.y"
- {
- dotag((yyvsp[(2) - (2)].sym), TENUM, 0);
- (yyval.type) = (yyvsp[(2) - (2)].sym)->suetag;
- if((yyval.type)->link == T)
- (yyval.type)->link = types[TINT];
- (yyval.type) = (yyval.type)->link;
- }
- break;
-
- case 204:
-#line 1087 "cc.y"
- {
- dotag((yyvsp[(2) - (2)].sym), TENUM, autobn);
- }
- break;
-
- case 205:
-#line 1091 "cc.y"
- {
- en.tenum = T;
- en.cenum = T;
- }
- break;
-
- case 206:
-#line 1096 "cc.y"
- {
- (yyval.type) = (yyvsp[(2) - (7)].sym)->suetag;
- if((yyval.type)->link != T)
- diag(Z, "redeclare tag: %s", (yyvsp[(2) - (7)].sym)->name);
- if(en.tenum == T) {
- diag(Z, "enum type ambiguous: %s", (yyvsp[(2) - (7)].sym)->name);
- en.tenum = types[TINT];
- }
- (yyval.type)->link = en.tenum;
- (yyval.type) = en.tenum;
- }
- break;
-
- case 207:
-#line 1108 "cc.y"
- {
- en.tenum = T;
- en.cenum = T;
- }
- break;
-
- case 208:
-#line 1113 "cc.y"
- {
- (yyval.type) = en.tenum;
- }
- break;
-
- case 209:
-#line 1117 "cc.y"
- {
- (yyval.type) = tcopy((yyvsp[(1) - (1)].sym)->type);
- }
- break;
-
- case 211:
-#line 1124 "cc.y"
- {
- (yyval.lval) = typebitor((yyvsp[(1) - (2)].lval), (yyvsp[(2) - (2)].lval));
- }
- break;
-
- case 212:
-#line 1129 "cc.y"
- {
- (yyval.lval) = 0;
- }
- break;
-
- case 213:
-#line 1133 "cc.y"
- {
- (yyval.lval) = typebitor((yyvsp[(1) - (2)].lval), (yyvsp[(2) - (2)].lval));
- }
- break;
-
- case 218:
-#line 1145 "cc.y"
- {
- (yyval.lval) = typebitor((yyvsp[(1) - (2)].lval), (yyvsp[(2) - (2)].lval));
- }
- break;
-
- case 221:
-#line 1155 "cc.y"
- {
- doenum((yyvsp[(1) - (1)].sym), Z);
- }
- break;
-
- case 222:
-#line 1159 "cc.y"
- {
- doenum((yyvsp[(1) - (3)].sym), (yyvsp[(3) - (3)].node));
- }
- break;
-
- case 225:
-#line 1166 "cc.y"
- { (yyval.lval) = BCHAR; }
- break;
-
- case 226:
-#line 1167 "cc.y"
- { (yyval.lval) = BSHORT; }
- break;
-
- case 227:
-#line 1168 "cc.y"
- { (yyval.lval) = BINT; }
- break;
-
- case 228:
-#line 1169 "cc.y"
- { (yyval.lval) = BLONG; }
- break;
-
- case 229:
-#line 1170 "cc.y"
- { (yyval.lval) = BSIGNED; }
- break;
-
- case 230:
-#line 1171 "cc.y"
- { (yyval.lval) = BUNSIGNED; }
- break;
-
- case 231:
-#line 1172 "cc.y"
- { (yyval.lval) = BFLOAT; }
- break;
-
- case 232:
-#line 1173 "cc.y"
- { (yyval.lval) = BDOUBLE; }
- break;
-
- case 233:
-#line 1174 "cc.y"
- { (yyval.lval) = BVOID; }
- break;
-
- case 234:
-#line 1177 "cc.y"
- { (yyval.lval) = BAUTO; }
- break;
-
- case 235:
-#line 1178 "cc.y"
- { (yyval.lval) = BSTATIC; }
- break;
-
- case 236:
-#line 1179 "cc.y"
- { (yyval.lval) = BEXTERN; }
- break;
-
- case 237:
-#line 1180 "cc.y"
- { (yyval.lval) = BTYPEDEF; }
- break;
-
- case 238:
-#line 1181 "cc.y"
- { (yyval.lval) = BTYPESTR; }
- break;
-
- case 239:
-#line 1182 "cc.y"
- { (yyval.lval) = BREGISTER; }
- break;
-
- case 240:
-#line 1183 "cc.y"
- { (yyval.lval) = 0; }
- break;
-
- case 241:
-#line 1186 "cc.y"
- { (yyval.lval) = BCONSTNT; }
- break;
-
- case 242:
-#line 1187 "cc.y"
- { (yyval.lval) = BVOLATILE; }
- break;
-
- case 243:
-#line 1188 "cc.y"
- { (yyval.lval) = 0; }
- break;
-
- case 244:
-#line 1192 "cc.y"
- {
- (yyval.node) = new(ONAME, Z, Z);
- if((yyvsp[(1) - (1)].sym)->class == CLOCAL)
- (yyvsp[(1) - (1)].sym) = mkstatic((yyvsp[(1) - (1)].sym));
- (yyval.node)->sym = (yyvsp[(1) - (1)].sym);
- (yyval.node)->type = (yyvsp[(1) - (1)].sym)->type;
- (yyval.node)->etype = TVOID;
- if((yyval.node)->type != T)
- (yyval.node)->etype = (yyval.node)->type->etype;
- (yyval.node)->xoffset = (yyvsp[(1) - (1)].sym)->offset;
- (yyval.node)->class = (yyvsp[(1) - (1)].sym)->class;
- (yyvsp[(1) - (1)].sym)->aused = 1;
- }
- break;
-
- case 245:
-#line 1207 "cc.y"
- {
- (yyval.node) = new(ONAME, Z, Z);
- (yyval.node)->sym = (yyvsp[(1) - (1)].sym);
- (yyval.node)->type = (yyvsp[(1) - (1)].sym)->type;
- (yyval.node)->etype = TVOID;
- if((yyval.node)->type != T)
- (yyval.node)->etype = (yyval.node)->type->etype;
- (yyval.node)->xoffset = (yyvsp[(1) - (1)].sym)->offset;
- (yyval.node)->class = (yyvsp[(1) - (1)].sym)->class;
- }
- break;
-
-
-/* Line 1267 of yacc.c. */
-#line 3607 "y.tab.c"
- default: break;
- }
- YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
-
- YYPOPSTACK (yylen);
- yylen = 0;
- YY_STACK_PRINT (yyss, yyssp);
-
- *++yyvsp = yyval;
-
-
- /* Now `shift' the result of the reduction. Determine what state
- that goes to, based on the state we popped back to and the rule
- number reduced by. */
-
- yyn = yyr1[yyn];
-
- yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
- if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
- yystate = yytable[yystate];
- else
- yystate = yydefgoto[yyn - YYNTOKENS];
-
- goto yynewstate;
-
-
-/*------------------------------------.
-| yyerrlab -- here on detecting error |
-`------------------------------------*/
-yyerrlab:
- /* If not already recovering from an error, report this error. */
- if (!yyerrstatus)
- {
- ++yynerrs;
-#if ! YYERROR_VERBOSE
- yyerror (YY_("syntax error"));
-#else
- {
- YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
- if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
- {
- YYSIZE_T yyalloc = 2 * yysize;
- if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
- yyalloc = YYSTACK_ALLOC_MAXIMUM;
- if (yymsg != yymsgbuf)
- YYSTACK_FREE (yymsg);
- yymsg = (char *) YYSTACK_ALLOC (yyalloc);
- if (yymsg)
- yymsg_alloc = yyalloc;
- else
- {
- yymsg = yymsgbuf;
- yymsg_alloc = sizeof yymsgbuf;
- }
- }
-
- if (0 < yysize && yysize <= yymsg_alloc)
- {
- (void) yysyntax_error (yymsg, yystate, yychar);
- yyerror (yymsg);
- }
- else
- {
- yyerror (YY_("syntax error"));
- if (yysize != 0)
- goto yyexhaustedlab;
- }
- }
-#endif
- }
-
-
-
- if (yyerrstatus == 3)
- {
- /* If just tried and failed to reuse look-ahead token after an
- error, discard it. */
-
- if (yychar <= YYEOF)
- {
- /* Return failure if at end of input. */
- if (yychar == YYEOF)
- YYABORT;
- }
- else
- {
- yydestruct ("Error: discarding",
- yytoken, &yylval);
- yychar = YYEMPTY;
- }
- }
-
- /* Else will try to reuse look-ahead token after shifting the error
- token. */
- goto yyerrlab1;
-
-
-/*---------------------------------------------------.
-| yyerrorlab -- error raised explicitly by YYERROR. |
-`---------------------------------------------------*/
-yyerrorlab:
-
- /* Pacify compilers like GCC when the user code never invokes
- YYERROR and the label yyerrorlab therefore never appears in user
- code. */
- if (/*CONSTCOND*/ 0)
- goto yyerrorlab;
-
- /* Do not reclaim the symbols of the rule which action triggered
- this YYERROR. */
- YYPOPSTACK (yylen);
- yylen = 0;
- YY_STACK_PRINT (yyss, yyssp);
- yystate = *yyssp;
- goto yyerrlab1;
-
-
-/*-------------------------------------------------------------.
-| yyerrlab1 -- common code for both syntax error and YYERROR. |
-`-------------------------------------------------------------*/
-yyerrlab1:
- yyerrstatus = 3; /* Each real token shifted decrements this. */
-
- for (;;)
- {
- yyn = yypact[yystate];
- if (yyn != YYPACT_NINF)
- {
- yyn += YYTERROR;
- if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
- {
- yyn = yytable[yyn];
- if (0 < yyn)
- break;
- }
- }
-
- /* Pop the current state because it cannot handle the error token. */
- if (yyssp == yyss)
- YYABORT;
-
-
- yydestruct ("Error: popping",
- yystos[yystate], yyvsp);
- YYPOPSTACK (1);
- yystate = *yyssp;
- YY_STACK_PRINT (yyss, yyssp);
- }
-
- if (yyn == YYFINAL)
- YYACCEPT;
-
- *++yyvsp = yylval;
-
-
- /* Shift the error token. */
- YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
-
- yystate = yyn;
- goto yynewstate;
-
-
-/*-------------------------------------.
-| yyacceptlab -- YYACCEPT comes here. |
-`-------------------------------------*/
-yyacceptlab:
- yyresult = 0;
- goto yyreturn;
-
-/*-----------------------------------.
-| yyabortlab -- YYABORT comes here. |
-`-----------------------------------*/
-yyabortlab:
- yyresult = 1;
- goto yyreturn;
-
-#ifndef yyoverflow
-/*-------------------------------------------------.
-| yyexhaustedlab -- memory exhaustion comes here. |
-`-------------------------------------------------*/
-yyexhaustedlab:
- yyerror (YY_("memory exhausted"));
- yyresult = 2;
- /* Fall through. */
-#endif
-
-yyreturn:
- if (yychar != YYEOF && yychar != YYEMPTY)
- yydestruct ("Cleanup: discarding lookahead",
- yytoken, &yylval);
- /* Do not reclaim the symbols of the rule which action triggered
- this YYABORT or YYACCEPT. */
- YYPOPSTACK (yylen);
- YY_STACK_PRINT (yyss, yyssp);
- while (yyssp != yyss)
- {
- yydestruct ("Cleanup: popping",
- yystos[*yyssp], yyvsp);
- YYPOPSTACK (1);
- }
-#ifndef yyoverflow
- if (yyss != yyssa)
- YYSTACK_FREE (yyss);
-#endif
-#if YYERROR_VERBOSE
- if (yymsg != yymsgbuf)
- YYSTACK_FREE (yymsg);
-#endif
- /* Make sure YYID is used. */
- return YYID (yyresult);
-}
-
-
-#line 1220 "cc.y"
-
-
diff --git a/src/cmd/cc/y.tab.h b/src/cmd/cc/y.tab.h
deleted file mode 100644
index 32daca9b6..000000000
--- a/src/cmd/cc/y.tab.h
+++ /dev/null
@@ -1,230 +0,0 @@
-/* A Bison parser, made by GNU Bison 2.3. */
-
-/* Skeleton interface for Bison's Yacc-like parsers in C
-
- Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
- Free Software Foundation, Inc.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
-
-/* As a special exception, you may create a larger work that contains
- part or all of the Bison parser skeleton and distribute that work
- under terms of your choice, so long as that work isn't itself a
- parser generator using the skeleton or a modified version thereof
- as a parser skeleton. Alternatively, if you modify or redistribute
- the parser skeleton itself, you may (at your option) remove this
- special exception, which will cause the skeleton and the resulting
- Bison output files to be licensed under the GNU General Public
- License without this special exception.
-
- This special exception was added by the Free Software Foundation in
- version 2.2 of Bison. */
-
-/* Tokens. */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
- /* Put the tokens into the symbol table, so that GDB and other debuggers
- know about them. */
- enum yytokentype {
- LORE = 258,
- LXORE = 259,
- LANDE = 260,
- LLSHE = 261,
- LRSHE = 262,
- LMDE = 263,
- LDVE = 264,
- LMLE = 265,
- LME = 266,
- LPE = 267,
- LOROR = 268,
- LANDAND = 269,
- LNE = 270,
- LEQ = 271,
- LGE = 272,
- LLE = 273,
- LRSH = 274,
- LLSH = 275,
- LMG = 276,
- LPP = 277,
- LMM = 278,
- LNAME = 279,
- LTYPE = 280,
- LFCONST = 281,
- LDCONST = 282,
- LCONST = 283,
- LLCONST = 284,
- LUCONST = 285,
- LULCONST = 286,
- LVLCONST = 287,
- LUVLCONST = 288,
- LSTRING = 289,
- LLSTRING = 290,
- LAUTO = 291,
- LBREAK = 292,
- LCASE = 293,
- LCHAR = 294,
- LCONTINUE = 295,
- LDEFAULT = 296,
- LDO = 297,
- LDOUBLE = 298,
- LELSE = 299,
- LEXTERN = 300,
- LFLOAT = 301,
- LFOR = 302,
- LGOTO = 303,
- LIF = 304,
- LINT = 305,
- LLONG = 306,
- LPREFETCH = 307,
- LREGISTER = 308,
- LRETURN = 309,
- LSHORT = 310,
- LSIZEOF = 311,
- LUSED = 312,
- LSTATIC = 313,
- LSTRUCT = 314,
- LSWITCH = 315,
- LTYPEDEF = 316,
- LTYPESTR = 317,
- LUNION = 318,
- LUNSIGNED = 319,
- LWHILE = 320,
- LVOID = 321,
- LENUM = 322,
- LSIGNED = 323,
- LCONSTNT = 324,
- LVOLATILE = 325,
- LSET = 326,
- LSIGNOF = 327,
- LRESTRICT = 328,
- LINLINE = 329
- };
-#endif
-/* Tokens. */
-#define LORE 258
-#define LXORE 259
-#define LANDE 260
-#define LLSHE 261
-#define LRSHE 262
-#define LMDE 263
-#define LDVE 264
-#define LMLE 265
-#define LME 266
-#define LPE 267
-#define LOROR 268
-#define LANDAND 269
-#define LNE 270
-#define LEQ 271
-#define LGE 272
-#define LLE 273
-#define LRSH 274
-#define LLSH 275
-#define LMG 276
-#define LPP 277
-#define LMM 278
-#define LNAME 279
-#define LTYPE 280
-#define LFCONST 281
-#define LDCONST 282
-#define LCONST 283
-#define LLCONST 284
-#define LUCONST 285
-#define LULCONST 286
-#define LVLCONST 287
-#define LUVLCONST 288
-#define LSTRING 289
-#define LLSTRING 290
-#define LAUTO 291
-#define LBREAK 292
-#define LCASE 293
-#define LCHAR 294
-#define LCONTINUE 295
-#define LDEFAULT 296
-#define LDO 297
-#define LDOUBLE 298
-#define LELSE 299
-#define LEXTERN 300
-#define LFLOAT 301
-#define LFOR 302
-#define LGOTO 303
-#define LIF 304
-#define LINT 305
-#define LLONG 306
-#define LPREFETCH 307
-#define LREGISTER 308
-#define LRETURN 309
-#define LSHORT 310
-#define LSIZEOF 311
-#define LUSED 312
-#define LSTATIC 313
-#define LSTRUCT 314
-#define LSWITCH 315
-#define LTYPEDEF 316
-#define LTYPESTR 317
-#define LUNION 318
-#define LUNSIGNED 319
-#define LWHILE 320
-#define LVOID 321
-#define LENUM 322
-#define LSIGNED 323
-#define LCONSTNT 324
-#define LVOLATILE 325
-#define LSET 326
-#define LSIGNOF 327
-#define LRESTRICT 328
-#define LINLINE 329
-
-
-
-
-#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-typedef union YYSTYPE
-#line 36 "cc.y"
-{
- Node* node;
- Sym* sym;
- Type* type;
- struct
- {
- Type* t;
- uchar c;
- } tycl;
- struct
- {
- Type* t1;
- Type* t2;
- Type* t3;
- uchar c;
- } tyty;
- struct
- {
- char* s;
- int32 l;
- } sval;
- int32 lval;
- double dval;
- vlong vval;
-}
-/* Line 1529 of yacc.c. */
-#line 223 "y.tab.h"
- YYSTYPE;
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
-# define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
-#endif
-
-extern YYSTYPE yylval;
-
diff --git a/src/cmd/cgo/main.go b/src/cmd/cgo/main.go
index 0dc22dcd4..28ded816d 100644
--- a/src/cmd/cgo/main.go
+++ b/src/cmd/cgo/main.go
@@ -155,6 +155,7 @@ var fset = token.NewFileSet()
var dynobj = flag.String("dynimport", "", "if non-empty, print dynamic import data for that file")
var dynout = flag.String("dynout", "", "write -dynobj output to this file")
+var dynpackage = flag.String("dynpackage", "main", "set Go package for dynobj output")
var dynlinker = flag.Bool("dynlinker", false, "record dynamic linker information in dynimport mode")
// These flags are for bootstrapping a new Go implementation,
diff --git a/src/cmd/cgo/out.go b/src/cmd/cgo/out.go
index d92bed9bf..78ecfd397 100644
--- a/src/cmd/cgo/out.go
+++ b/src/cmd/cgo/out.go
@@ -13,6 +13,7 @@ import (
"go/ast"
"go/printer"
"go/token"
+ "io"
"os"
"sort"
"strings"
@@ -23,8 +24,15 @@ var conf = printer.Config{Mode: printer.SourcePos, Tabwidth: 8}
// writeDefs creates output files to be compiled by 6g, 6c, and gcc.
// (The comments here say 6g and 6c but the code applies to the 8 and 5 tools too.)
func (p *Package) writeDefs() {
- fgo2 := creat(*objDir + "_cgo_gotypes.go")
- fc := creat(*objDir + "_cgo_defun.c")
+ var fgo2, fc io.Writer
+ f := creat(*objDir + "_cgo_gotypes.go")
+ defer f.Close()
+ fgo2 = f
+ if *gccgo {
+ f := creat(*objDir + "_cgo_defun.c")
+ defer f.Close()
+ fc = f
+ }
fm := creat(*objDir + "_cgo_main.c")
var gccgoInit bytes.Buffer
@@ -34,7 +42,7 @@ func (p *Package) writeDefs() {
fmt.Fprintf(fflg, "_CGO_%s=%s\n", k, strings.Join(v, " "))
if k == "LDFLAGS" && !*gccgo {
for _, arg := range v {
- fmt.Fprintf(fc, "#pragma cgo_ldflag %q\n", arg)
+ fmt.Fprintf(fgo2, "//go:cgo_ldflag %q\n", arg)
}
}
}
@@ -88,7 +96,6 @@ func (p *Package) writeDefs() {
if *gccgo {
fmt.Fprint(fc, p.cPrologGccgo())
} else {
- fmt.Fprint(fc, cProlog)
fmt.Fprint(fgo2, goProlog)
}
@@ -104,42 +111,42 @@ func (p *Package) writeDefs() {
if !cVars[n.C] {
fmt.Fprintf(fm, "extern char %s[];\n", n.C)
fmt.Fprintf(fm, "void *_cgohack_%s = %s;\n\n", n.C, n.C)
-
- if !*gccgo {
- fmt.Fprintf(fc, "#pragma cgo_import_static %s\n", n.C)
+ if *gccgo {
+ fmt.Fprintf(fc, "extern byte *%s;\n", n.C)
+ } else {
+ fmt.Fprintf(fgo2, "//go:linkname __cgo_%s %s\n", n.C, n.C)
+ fmt.Fprintf(fgo2, "//go:cgo_import_static %s\n", n.C)
+ fmt.Fprintf(fgo2, "var __cgo_%s byte\n", n.C)
}
-
- fmt.Fprintf(fc, "extern byte *%s;\n", n.C)
-
cVars[n.C] = true
}
- var amp string
+
var node ast.Node
if n.Kind == "var" {
- amp = "&"
node = &ast.StarExpr{X: n.Type.Go}
} else if n.Kind == "fpvar" {
node = n.Type.Go
- if *gccgo {
- amp = "&"
- }
} else {
panic(fmt.Errorf("invalid var kind %q", n.Kind))
}
if *gccgo {
fmt.Fprintf(fc, `extern void *%s __asm__("%s.%s");`, n.Mangle, gccgoSymbolPrefix, n.Mangle)
- fmt.Fprintf(&gccgoInit, "\t%s = %s%s;\n", n.Mangle, amp, n.C)
- } else {
- fmt.Fprintf(fc, "#pragma dataflag NOPTR /* C pointer, not heap pointer */ \n")
- fmt.Fprintf(fc, "void *·%s = %s%s;\n", n.Mangle, amp, n.C)
+ fmt.Fprintf(&gccgoInit, "\t%s = &%s;\n", n.Mangle, n.C)
+ fmt.Fprintf(fc, "\n")
}
- fmt.Fprintf(fc, "\n")
fmt.Fprintf(fgo2, "var %s ", n.Mangle)
conf.Fprint(fgo2, fset, node)
+ if !*gccgo {
+ fmt.Fprintf(fgo2, " = (")
+ conf.Fprint(fgo2, fset, node)
+ fmt.Fprintf(fgo2, ")(unsafe.Pointer(&__cgo_%s))", n.C)
+ }
fmt.Fprintf(fgo2, "\n")
}
- fmt.Fprintf(fc, "\n")
+ if *gccgo {
+ fmt.Fprintf(fc, "\n")
+ }
for _, key := range nameKeys(p.Name) {
n := p.Name[key]
@@ -169,9 +176,6 @@ func (p *Package) writeDefs() {
fmt.Fprint(fc, init)
fmt.Fprintln(fc, "}")
}
-
- fgo2.Close()
- fc.Close()
}
func dynimport(obj string) {
@@ -184,13 +188,15 @@ func dynimport(obj string) {
stdout = f
}
+ fmt.Fprintf(stdout, "package %s\n", *dynpackage)
+
if f, err := elf.Open(obj); err == nil {
if *dynlinker {
// Emit the cgo_dynamic_linker line.
if sec := f.Section(".interp"); sec != nil {
if data, err := sec.Data(); err == nil && len(data) > 1 {
// skip trailing \0 in data
- fmt.Fprintf(stdout, "#pragma cgo_dynamic_linker %q\n", string(data[:len(data)-1]))
+ fmt.Fprintf(stdout, "//go:cgo_dynamic_linker %q\n", string(data[:len(data)-1]))
}
}
}
@@ -203,14 +209,14 @@ func dynimport(obj string) {
if s.Version != "" {
targ += "#" + s.Version
}
- fmt.Fprintf(stdout, "#pragma cgo_import_dynamic %s %s %q\n", s.Name, targ, s.Library)
+ fmt.Fprintf(stdout, "//go:cgo_import_dynamic %s %s %q\n", s.Name, targ, s.Library)
}
lib, err := f.ImportedLibraries()
if err != nil {
fatalf("cannot load imported libraries from ELF file %s: %v", obj, err)
}
for _, l := range lib {
- fmt.Fprintf(stdout, "#pragma cgo_import_dynamic _ _ %q\n", l)
+ fmt.Fprintf(stdout, "//go:cgo_import_dynamic _ _ %q\n", l)
}
return
}
@@ -224,14 +230,14 @@ func dynimport(obj string) {
if len(s) > 0 && s[0] == '_' {
s = s[1:]
}
- fmt.Fprintf(stdout, "#pragma cgo_import_dynamic %s %s %q\n", s, s, "")
+ fmt.Fprintf(stdout, "//go:cgo_import_dynamic %s %s %q\n", s, s, "")
}
lib, err := f.ImportedLibraries()
if err != nil {
fatalf("cannot load imported libraries from Mach-O file %s: %v", obj, err)
}
for _, l := range lib {
- fmt.Fprintf(stdout, "#pragma cgo_import_dynamic _ _ %q\n", l)
+ fmt.Fprintf(stdout, "//go:cgo_import_dynamic _ _ %q\n", l)
}
return
}
@@ -244,7 +250,7 @@ func dynimport(obj string) {
for _, s := range sym {
ss := strings.Split(s, ":")
name := strings.Split(ss[0], "@")[0]
- fmt.Fprintf(stdout, "#pragma cgo_import_dynamic %s %s %q\n", name, ss[0], strings.ToLower(ss[1]))
+ fmt.Fprintf(stdout, "//go:cgo_import_dynamic %s %s %q\n", name, ss[0], strings.ToLower(ss[1]))
}
return
}
@@ -304,7 +310,7 @@ func (p *Package) structType(n *Name) (string, int64) {
return buf.String(), off
}
-func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
+func (p *Package) writeDefsFunc(fc, fgo2 io.Writer, n *Name) {
name := n.Go
gtype := n.FuncType.Go
void := gtype.Results == nil || len(gtype.Results.List) == 0
@@ -397,10 +403,10 @@ func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
}
// C wrapper calls into gcc, passing a pointer to the argument frame.
- fmt.Fprintf(fc, "#pragma cgo_import_static %s\n", cname)
- fmt.Fprintf(fc, "void %s(void*);\n", cname)
- fmt.Fprintf(fc, "#pragma dataflag NOPTR\n")
- fmt.Fprintf(fc, "void *·%s = %s;\n", cname, cname)
+ fmt.Fprintf(fgo2, "//go:cgo_import_static %s\n", cname)
+ fmt.Fprintf(fgo2, "//go:linkname __cgofn_%s %s\n", cname, cname)
+ fmt.Fprintf(fgo2, "var __cgofn_%s byte\n", cname)
+ fmt.Fprintf(fgo2, "var %s = unsafe.Pointer(&__cgofn_%s)\n", cname, cname)
nret := 0
if !void {
@@ -412,7 +418,6 @@ func (p *Package) writeDefsFunc(fc, fgo2 *os.File, n *Name) {
}
fmt.Fprint(fgo2, "\n")
- fmt.Fprintf(fgo2, "var %s unsafe.Pointer\n", cname)
conf.Fprint(fgo2, fset, d)
fmt.Fprint(fgo2, " {\n")
@@ -626,7 +631,7 @@ func (p *Package) packedAttribute() string {
// Write out the various stubs we need to support functions exported
// from Go so that they are callable from C.
-func (p *Package) writeExports(fgo2, fc, fm *os.File) {
+func (p *Package) writeExports(fgo2, fc, fm io.Writer) {
fgcc := creat(*objDir + "_cgo_export.c")
fgcch := creat(*objDir + "_cgo_export.h")
@@ -763,15 +768,15 @@ func (p *Package) writeExports(fgo2, fc, fm *os.File) {
if fn.Recv != nil {
goname = "_cgoexpwrap" + cPrefix + "_" + fn.Recv.List[0].Names[0].Name + "_" + goname
}
- fmt.Fprintf(fc, "#pragma cgo_export_dynamic %s\n", goname)
- fmt.Fprintf(fc, "extern void ·%s();\n\n", goname)
- fmt.Fprintf(fc, "#pragma cgo_export_static _cgoexp%s_%s\n", cPrefix, exp.ExpName)
- fmt.Fprintf(fc, "#pragma textflag 7\n") // no split stack, so no use of m or g
- fmt.Fprintf(fc, "void\n")
- fmt.Fprintf(fc, "_cgoexp%s_%s(void *a, int32 n)\n", cPrefix, exp.ExpName)
- fmt.Fprintf(fc, "{\n")
- fmt.Fprintf(fc, "\truntime·cgocallback(·%s, a, n);\n", goname)
- fmt.Fprintf(fc, "}\n")
+ fmt.Fprintf(fgo2, "//go:cgo_export_dynamic %s\n", goname)
+ fmt.Fprintf(fgo2, "//go:linkname _cgoexp%s_%s _cgoexp%s_%s\n", cPrefix, exp.ExpName, cPrefix, exp.ExpName)
+ fmt.Fprintf(fgo2, "//go:cgo_export_static _cgoexp%s_%s\n", cPrefix, exp.ExpName)
+ fmt.Fprintf(fgo2, "//go:nosplit\n") // no split stack, so no use of m or g
+ fmt.Fprintf(fgo2, "func _cgoexp%s_%s(a unsafe.Pointer, n int32) {", cPrefix, exp.ExpName)
+ fmt.Fprintf(fgo2, "\tfn := %s\n", goname)
+ // The indirect here is converting from a Go function pointer to a C function pointer.
+ fmt.Fprintf(fgo2, "\t_cgo_runtime_cgocallback(**(**unsafe.Pointer)(unsafe.Pointer(&fn)), a, uintptr(n));\n")
+ fmt.Fprintf(fgo2, "}\n")
fmt.Fprintf(fm, "int _cgoexp%s_%s;\n", cPrefix, exp.ExpName)
@@ -817,7 +822,7 @@ func (p *Package) writeExports(fgo2, fc, fm *os.File) {
}
// Write out the C header allowing C code to call exported gccgo functions.
-func (p *Package) writeGccgoExports(fgo2, fc, fm *os.File) {
+func (p *Package) writeGccgoExports(fgo2, fc, fm io.Writer) {
fgcc := creat(*objDir + "_cgo_export.c")
fgcch := creat(*objDir + "_cgo_export.h")
@@ -1164,60 +1169,39 @@ char *CString(_GoString_);
void *_CMalloc(size_t);
`
-const cProlog = `
-#include "runtime.h"
-#include "cgocall.h"
-#include "textflag.h"
-
-#pragma dataflag NOPTR
-static void *cgocall_errno = runtime·cgocall_errno;
-#pragma dataflag NOPTR
-void *·_cgo_runtime_cgocall_errno = &cgocall_errno;
-
-#pragma dataflag NOPTR
-static void *runtime_gostring = runtime·gostring;
-#pragma dataflag NOPTR
-void *·_cgo_runtime_gostring = &runtime_gostring;
-
-#pragma dataflag NOPTR
-static void *runtime_gostringn = runtime·gostringn;
-#pragma dataflag NOPTR
-void *·_cgo_runtime_gostringn = &runtime_gostringn;
-
-#pragma dataflag NOPTR
-static void *runtime_gobytes = runtime·gobytes;
-#pragma dataflag NOPTR
-void *·_cgo_runtime_gobytes = &runtime_gobytes;
-
-#pragma dataflag NOPTR
-static void *runtime_cmalloc = runtime·cmalloc;
-#pragma dataflag NOPTR
-void *·_cgo_runtime_cmalloc = &runtime_cmalloc;
-
-void ·_Cerrno(void*, int32);
-`
-
const goProlog = `
-var _cgo_runtime_cgocall_errno func(unsafe.Pointer, uintptr) int32
-var _cgo_runtime_cmalloc func(uintptr) unsafe.Pointer
+//go:linkname _cgo_runtime_cgocall_errno runtime.cgocall_errno
+func _cgo_runtime_cgocall_errno(unsafe.Pointer, uintptr) int32
+
+//go:linkname _cgo_runtime_cmalloc runtime.cmalloc
+func _cgo_runtime_cmalloc(uintptr) unsafe.Pointer
+
+//go:linkname _cgo_runtime_cgocallback runtime.cgocallback
+func _cgo_runtime_cgocallback(unsafe.Pointer, unsafe.Pointer, uintptr)
`
const goStringDef = `
-var _cgo_runtime_gostring func(*_Ctype_char) string
+//go:linkname _cgo_runtime_gostring runtime.gostring
+func _cgo_runtime_gostring(*_Ctype_char) string
+
func _Cfunc_GoString(p *_Ctype_char) string {
return _cgo_runtime_gostring(p)
}
`
const goStringNDef = `
-var _cgo_runtime_gostringn func(*_Ctype_char, int) string
+//go:linkname _cgo_runtime_gostringn runtime.gostringn
+func _cgo_runtime_gostringn(*_Ctype_char, int) string
+
func _Cfunc_GoStringN(p *_Ctype_char, l _Ctype_int) string {
return _cgo_runtime_gostringn(p, int(l))
}
`
const goBytesDef = `
-var _cgo_runtime_gobytes func(unsafe.Pointer, int) []byte
+//go:linkname _cgo_runtime_gobytes runtime.gobytes
+func _cgo_runtime_gobytes(unsafe.Pointer, int) []byte
+
func _Cfunc_GoBytes(p unsafe.Pointer, l _Ctype_int) []byte {
return _cgo_runtime_gobytes(p, int(l))
}
diff --git a/src/cmd/dist/build.c b/src/cmd/dist/build.c
index 8fd2e998a..bfb3d15b8 100644
--- a/src/cmd/dist/build.c
+++ b/src/cmd/dist/build.c
@@ -526,10 +526,6 @@ static struct {
"anames8.c",
"anames9.c",
}},
- {"cmd/cc", {
- "-pgen.c",
- "-pswt.c",
- }},
{"cmd/gc", {
"-cplx.c",
"-pgen.c",
@@ -538,26 +534,6 @@ static struct {
"-y1.tab.c", // makefile dreg
"opnames.h",
}},
- {"cmd/5c", {
- "../cc/pgen.c",
- "../cc/pswt.c",
- "$GOROOT/pkg/obj/$GOHOSTOS_$GOHOSTARCH/libcc.a",
- }},
- {"cmd/6c", {
- "../cc/pgen.c",
- "../cc/pswt.c",
- "$GOROOT/pkg/obj/$GOHOSTOS_$GOHOSTARCH/libcc.a",
- }},
- {"cmd/8c", {
- "../cc/pgen.c",
- "../cc/pswt.c",
- "$GOROOT/pkg/obj/$GOHOSTOS_$GOHOSTARCH/libcc.a",
- }},
- {"cmd/9c", {
- "../cc/pgen.c",
- "../cc/pswt.c",
- "$GOROOT/pkg/obj/$GOHOSTOS_$GOHOSTARCH/libcc.a",
- }},
{"cmd/5g", {
"../gc/cplx.c",
"../gc/pgen.c",
@@ -611,12 +587,10 @@ static struct {
"$GOROOT/pkg/obj/$GOHOSTOS_$GOHOSTARCH/lib9.a",
}},
{"runtime", {
- "zaexperiment.h", // must sort above zasm
- "zasm_$GOOS_$GOARCH.h",
+ "zaexperiment.h",
"zsys_$GOOS_$GOARCH.s",
"zgoarch_$GOARCH.go",
"zgoos_$GOOS.go",
- "zruntime_defs_$GOOS_$GOARCH.go",
"zversion.go",
}},
};
@@ -639,12 +613,8 @@ static struct {
{"anames6.c", mkanames},
{"anames8.c", mkanames},
{"anames9.c", mkanames},
- {"zasm_", mkzasm},
{"zdefaultcc.go", mkzdefaultcc},
{"zsys_", mkzsys},
- {"zgoarch_", mkzgoarch},
- {"zgoos_", mkzgoos},
- {"zruntime_defs_", mkzruntimedefs},
{"zversion.go", mkzversion},
{"zaexperiment.h", mkzexperiment},
@@ -659,7 +629,7 @@ install(char *dir)
{
char *name, *p, *elem, *prefix, *exe;
bool islib, ispkg, isgo, stale, ispackcmd;
- Buf b, b1, path, final_path, final_name;
+ Buf b, b1, path, final_path, final_name, archive;
Vec compile, files, link, go, missing, clean, lib, extra;
Time ttarg, t;
int i, j, k, n, doclean, targ;
@@ -676,6 +646,7 @@ install(char *dir)
binit(&path);
binit(&final_path);
binit(&final_name);
+ binit(&archive);
vinit(&compile);
vinit(&files);
vinit(&link);
@@ -691,13 +662,6 @@ install(char *dir)
bpathf(&final_path, "%s/src/%s", goroot_final, dir);
name = lastelem(dir);
- // For misc/prof, copy into the tool directory and we're done.
- if(hasprefix(dir, "misc/")) {
- copyfile(bpathf(&b, "%s/%s", tooldir, name),
- bpathf(&b1, "%s/misc/%s", goroot, name), 1);
- goto out;
- }
-
// set up gcc command line on first run.
if(gccargs.len == 0) {
bprintf(&b, "%s %s", defaultcc, defaultcflags);
@@ -726,7 +690,7 @@ install(char *dir)
splitfields(&ldargs, bstr(&b));
}
- islib = hasprefix(dir, "lib") || streq(dir, "cmd/cc") || streq(dir, "cmd/gc");
+ islib = hasprefix(dir, "lib") || streq(dir, "cmd/gc");
ispkg = !islib && !hasprefix(dir, "cmd/");
isgo = ispkg || streq(dir, "cmd/go") || streq(dir, "cmd/cgo");
@@ -905,17 +869,6 @@ install(char *dir)
// For package runtime, copy some files into the work space.
if(streq(dir, "runtime")) {
- copyfile(bpathf(&b, "%s/arch_GOARCH.h", workdir),
- bpathf(&b1, "%s/arch_%s.h", bstr(&path), goarch), 0);
- copyfile(bpathf(&b, "%s/defs_GOOS_GOARCH.h", workdir),
- bpathf(&b1, "%s/defs_%s_%s.h", bstr(&path), goos, goarch), 0);
- p = bpathf(&b1, "%s/signal_%s_%s.h", bstr(&path), goos, goarch);
- if(isfile(p))
- copyfile(bpathf(&b, "%s/signal_GOOS_GOARCH.h", workdir), p, 0);
- copyfile(bpathf(&b, "%s/os_GOOS.h", workdir),
- bpathf(&b1, "%s/os_%s.h", bstr(&path), goos), 0);
- copyfile(bpathf(&b, "%s/signals_GOOS.h", workdir),
- bpathf(&b1, "%s/signals_%s.h", bstr(&path), goos), 0);
copyfile(bpathf(&b, "%s/pkg/%s_%s/textflag.h", goroot, goos, goarch),
bpathf(&b1, "%s/src/cmd/ld/textflag.h", goroot), 0);
copyfile(bpathf(&b, "%s/pkg/%s_%s/funcdata.h", goroot, goos, goarch),
@@ -949,14 +902,6 @@ install(char *dir)
built:;
}
- // One more copy for package runtime.
- // The last batch was required for the generators.
- // This one is generated.
- if(streq(dir, "runtime")) {
- copyfile(bpathf(&b, "%s/zasm_GOOS_GOARCH.h", workdir),
- bpathf(&b1, "%s/zasm_%s_%s.h", bstr(&path), goos, goarch), 0);
- }
-
if((!streq(goos, gohostos) || !streq(goarch, gohostarch)) && isgo) {
// We've generated the right files; the go command can do the build.
if(vflag > 1)
@@ -964,6 +909,42 @@ install(char *dir)
goto nobuild;
}
+ if(isgo) {
+ // The next loop will compile individual non-Go files.
+ // Hand the Go files to the compiler en masse.
+ // For package runtime, this writes go_asm.h, which
+ // the assembly files will need.
+ vreset(&compile);
+ vadd(&compile, bpathf(&b, "%s/%sg", tooldir, gochar));
+
+ bpathf(&b, "%s/_go_.a", workdir);
+ vadd(&compile, "-pack");
+ vadd(&compile, "-o");
+ vadd(&compile, bstr(&b));
+ vadd(&clean, bstr(&b));
+ if(!ispackcmd)
+ vadd(&link, bstr(&b));
+ else
+ bwriteb(&archive, &b);
+
+ vadd(&compile, "-p");
+ if(hasprefix(dir, "cmd/"))
+ vadd(&compile, "main");
+ else
+ vadd(&compile, dir);
+
+ if(streq(dir, "runtime")) {
+ vadd(&compile, "-+");
+ vadd(&compile, "-asmhdr");
+ bpathf(&b1, "%s/go_asm.h", workdir);
+ vadd(&compile, bstr(&b1));
+ }
+
+ vcopy(&compile, go.p, go.len);
+
+ runv(nil, bstr(&path), CheckExit, &compile);
+ }
+
// Compile the files.
for(i=0; i<files.len; i++) {
if(!hassuffix(files.p[i], ".c") && !hassuffix(files.p[i], ".s"))
@@ -1077,38 +1058,10 @@ install(char *dir)
}
bgwait();
- if(isgo) {
- // The last loop was compiling individual files.
- // Hand the Go files to the compiler en masse.
- vreset(&compile);
- vadd(&compile, bpathf(&b, "%s/%sg", tooldir, gochar));
-
- bpathf(&b, "%s/_go_.a", workdir);
- vadd(&compile, "-pack");
- vadd(&compile, "-o");
- vadd(&compile, bstr(&b));
- vadd(&clean, bstr(&b));
- if(!ispackcmd)
- vadd(&link, bstr(&b));
-
- vadd(&compile, "-p");
- if(hasprefix(dir, "pkg/"))
- vadd(&compile, dir+4);
- else
- vadd(&compile, "main");
-
- if(streq(dir, "runtime"))
- vadd(&compile, "-+");
-
- vcopy(&compile, go.p, go.len);
-
- runv(nil, bstr(&path), CheckExit, &compile);
-
- if(ispackcmd) {
- xremove(link.p[targ]);
- dopack(link.p[targ], bstr(&b), &link.p[targ+1], link.len - (targ+1));
- goto nobuild;
- }
+ if(isgo && ispackcmd) {
+ xremove(link.p[targ]);
+ dopack(link.p[targ], bstr(&archive), &link.p[targ+1], link.len - (targ+1));
+ goto nobuild;
}
if(!islib && !isgo) {
@@ -1122,17 +1075,7 @@ install(char *dir)
xremove(link.p[targ]);
runv(nil, nil, CheckExit, &link);
-
nobuild:
- // In package runtime, we install runtime.h and cgocall.h too,
- // for use by cgo compilation.
- if(streq(dir, "runtime")) {
- copyfile(bpathf(&b, "%s/pkg/%s_%s/cgocall.h", goroot, goos, goarch),
- bpathf(&b1, "%s/src/runtime/cgocall.h", goroot), 0);
- copyfile(bpathf(&b, "%s/pkg/%s_%s/runtime.h", goroot, goos, goarch),
- bpathf(&b1, "%s/src/runtime/runtime.h", goroot), 0);
- }
-
out:
for(i=0; i<clean.len; i++)
@@ -1141,6 +1084,7 @@ out:
bfree(&b);
bfree(&b1);
bfree(&path);
+ bfree(&archive);
vfree(&compile);
vfree(&files);
vfree(&link);
@@ -1328,13 +1272,9 @@ static char *buildorder[] = {
"libbio",
"liblink",
- "misc/pprof",
-
- "cmd/cc", // must be before c
"cmd/gc", // must be before g
- "cmd/%sl", // must be before a, c, g
+ "cmd/%sl", // must be before a, g
"cmd/%sa",
- "cmd/%sc",
"cmd/%sg",
// The dependency order here was copied from a buildscript
@@ -1391,22 +1331,17 @@ static char *buildorder[] = {
static char *cleantab[] = {
// Commands and C libraries.
"cmd/5a",
- "cmd/5c",
"cmd/5g",
"cmd/5l",
"cmd/6a",
- "cmd/6c",
"cmd/6g",
"cmd/6l",
"cmd/8a",
- "cmd/8c",
"cmd/8g",
"cmd/8l",
"cmd/9a",
- "cmd/9c",
"cmd/9g",
"cmd/9l",
- "cmd/cc",
"cmd/gc",
"cmd/go",
"lib9",
@@ -1482,12 +1417,13 @@ clean(void)
xremove(bpathf(&b, "%s/%s", bstr(&path), cleantab[i]+4));
}
- // remove src/runtime/z* unconditionally
+ // remove src/runtime/z* unconditionally,
+ // except leave zgoos and zgoarch, now maintained with go generate.
vreset(&dir);
bpathf(&path, "%s/src/runtime", goroot);
xreaddir(&dir, bstr(&path));
for(j=0; j<dir.len; j++) {
- if(hasprefix(dir.p[j], "z"))
+ if(hasprefix(dir.p[j], "z") && !hasprefix(dir.p[j], "zg"))
xremove(bpathf(&b, "%s/%s", bstr(&path), dir.p[j]));
}
diff --git a/src/cmd/dist/buildruntime.c b/src/cmd/dist/buildruntime.c
index d22e09955..38e99e116 100644
--- a/src/cmd/dist/buildruntime.c
+++ b/src/cmd/dist/buildruntime.c
@@ -67,234 +67,8 @@ mkzexperiment(char *dir, char *file)
bfree(&exp);
}
-// mkzgoarch writes zgoarch_$GOARCH.go:
-//
-// package runtime
-// const theGoarch = <goarch>
-//
-void
-mkzgoarch(char *dir, char *file)
-{
- Buf b, out;
-
- USED(dir);
-
- binit(&b);
- binit(&out);
-
- bwritestr(&out, bprintf(&b,
- "// auto generated by go tool dist\n"
- "\n"
- "package runtime\n"
- "\n"
- "const theGoarch = `%s`\n", goarch));
-
- writefile(&out, file, 0);
-
- bfree(&b);
- bfree(&out);
-}
-
-// mkzgoos writes zgoos_$GOOS.go:
-//
-// package runtime
-// const theGoos = <goos>
-//
-void
-mkzgoos(char *dir, char *file)
-{
- Buf b, out;
-
- USED(dir);
-
- binit(&b);
- binit(&out);
-
- bwritestr(&out, "// auto generated by go tool dist\n\n");
-
- if(streq(goos, "linux")) {
- bwritestr(&out, "// +build !android\n\n");
- }
-
- bwritestr(&out, bprintf(&b,
- "package runtime\n"
- "\n"
- "const theGoos = `%s`\n", goos));
-
- writefile(&out, file, 0);
-
- bfree(&b);
- bfree(&out);
-}
-
-static struct {
- char *goarch;
- char *goos;
- char *hdr;
-} zasmhdr[] = {
- {"386", "",
- "#define get_tls(r) MOVL TLS, r\n"
- "#define g(r) 0(r)(TLS*1)\n"
- },
- {"amd64p32", "",
- "#define get_tls(r) MOVL TLS, r\n"
- "#define g(r) 0(r)(TLS*1)\n"
- },
- {"amd64", "",
- "#define get_tls(r) MOVQ TLS, r\n"
- "#define g(r) 0(r)(TLS*1)\n"
- },
-
- {"arm", "",
- "#define LR R14\n"
- },
-
- {"power64", "",
- "#define g R30\n"
- },
- {"power64le", "",
- "#define g R30\n"
- },
-};
-
#define MAXWINCB 2000 /* maximum number of windows callbacks allowed */
-// mkzasm writes zasm_$GOOS_$GOARCH.h,
-// which contains struct offsets for use by
-// assembly files. It also writes a copy to the work space
-// under the name zasm_GOOS_GOARCH.h (no expansion).
-//
-void
-mkzasm(char *dir, char *file)
-{
- int i, n;
- char *aggr, *p;
- Buf in, b, b1, out, exp;
- Vec argv, lines, fields;
-
- binit(&in);
- binit(&b);
- binit(&b1);
- binit(&out);
- binit(&exp);
- vinit(&argv);
- vinit(&lines);
- vinit(&fields);
-
- bwritestr(&out, "// auto generated by go tool dist\n\n");
- if(streq(goos, "linux")) {
- bwritestr(&out, "// +build !android\n\n");
- }
-
- for(i=0; i<nelem(zasmhdr); i++) {
- if(hasprefix(goarch, zasmhdr[i].goarch) && hasprefix(goos, zasmhdr[i].goos)) {
- bwritestr(&out, zasmhdr[i].hdr);
- goto ok;
- }
- }
- fatal("unknown $GOOS/$GOARCH in mkzasm");
-ok:
-
- copyfile(bpathf(&b, "%s/pkg/%s_%s/textflag.h", goroot, goos, goarch),
- bpathf(&b1, "%s/src/cmd/ld/textflag.h", goroot), 0);
-
- // Run 6c -D GOOS_goos -D GOARCH_goarch -I workdir -a -n -o workdir/proc.acid proc.c
- // to get acid [sic] output. Run once without the -a -o workdir/proc.acid in order to
- // report compilation failures (the -o redirects all messages, unfortunately).
- vreset(&argv);
- vadd(&argv, bpathf(&b, "%s/%sc", tooldir, gochar));
- vadd(&argv, "-D");
- vadd(&argv, bprintf(&b, "GOOS_%s", goos));
- vadd(&argv, "-D");
- vadd(&argv, bprintf(&b, "GOARCH_%s", goarch));
- vadd(&argv, "-I");
- vadd(&argv, bprintf(&b, "%s", workdir));
- vadd(&argv, "-I");
- vadd(&argv, bprintf(&b, "%s/pkg/%s_%s", goroot, goos, goarch));
- vadd(&argv, "-n");
- vadd(&argv, "-a");
- vadd(&argv, "-o");
- vadd(&argv, bpathf(&b, "%s/proc.acid", workdir));
- vadd(&argv, "proc.c");
- runv(nil, dir, CheckExit, &argv);
- readfile(&in, bpathf(&b, "%s/proc.acid", workdir));
-
- // Convert input like
- // aggr G
- // {
- // Gobuf 24 sched;
- // 'Y' 48 stack0;
- // }
- // StackMin = 128;
- // into output like
- // #define g_sched 24
- // #define g_stack0 48
- // #define const_StackMin 128
- aggr = nil;
- splitlines(&lines, bstr(&in));
- for(i=0; i<lines.len; i++) {
- splitfields(&fields, lines.p[i]);
- if(fields.len == 2 && streq(fields.p[0], "aggr")) {
- if(streq(fields.p[1], "G"))
- aggr = "g";
- else if(streq(fields.p[1], "M"))
- aggr = "m";
- else if(streq(fields.p[1], "P"))
- aggr = "p";
- else if(streq(fields.p[1], "Gobuf"))
- aggr = "gobuf";
- else if(streq(fields.p[1], "LibCall"))
- aggr = "libcall";
- else if(streq(fields.p[1], "WinCallbackContext"))
- aggr = "cbctxt";
- else if(streq(fields.p[1], "SEH"))
- aggr = "seh";
- else if(streq(fields.p[1], "Alg"))
- aggr = "alg";
- else if(streq(fields.p[1], "Panic"))
- aggr = "panic";
- else if(streq(fields.p[1], "Stack"))
- aggr = "stack";
- }
- if(hasprefix(lines.p[i], "}"))
- aggr = nil;
- if(aggr && hasprefix(lines.p[i], "\t") && fields.len >= 2) {
- n = fields.len;
- p = fields.p[n-1];
- if(p[xstrlen(p)-1] == ';')
- p[xstrlen(p)-1] = '\0';
- bwritestr(&out, bprintf(&b, "#define %s_%s %s\n", aggr, fields.p[n-1], fields.p[n-2]));
- }
- if(fields.len == 3 && streq(fields.p[1], "=")) { // generated from enumerated constants
- p = fields.p[2];
- if(p[xstrlen(p)-1] == ';')
- p[xstrlen(p)-1] = '\0';
- bwritestr(&out, bprintf(&b, "#define const_%s %s\n", fields.p[0], p));
- }
- }
-
- // Some #defines that are used for .c files.
- if(streq(goos, "windows")) {
- bwritestr(&out, bprintf(&b, "#define cb_max %d\n", MAXWINCB));
- }
-
- xgetenv(&exp, "GOEXPERIMENT");
- bwritestr(&out, bprintf(&b, "#define GOEXPERIMENT \"%s\"\n", bstr(&exp)));
-
- // Write both to file and to workdir/zasm_GOOS_GOARCH.h.
- writefile(&out, file, 0);
- writefile(&out, bprintf(&b, "%s/zasm_GOOS_GOARCH.h", workdir), 0);
-
- bfree(&in);
- bfree(&b);
- bfree(&b1);
- bfree(&out);
- bfree(&exp);
- vfree(&argv);
- vfree(&lines);
- vfree(&fields);
-}
-
// mkzsys writes zsys_$GOOS_$GOARCH.s,
// which contains arch or os specific asm code.
//
@@ -333,143 +107,3 @@ mkzsys(char *dir, char *file)
bfree(&out);
}
-
-static char *runtimedefs[] = {
- "defs.c",
- "malloc.c",
- "mcache.c",
- "mgc0.c",
- "proc.c",
- "parfor.c",
- "stack.c",
-};
-
-// mkzruntimedefs writes zruntime_defs_$GOOS_$GOARCH.h,
-// which contains Go struct definitions equivalent to the C ones.
-// Mostly we just write the output of 6c -q to the file.
-// However, we run it on multiple files, so we have to delete
-// the duplicated definitions, and we don't care about the funcs,
-// so we delete those too.
-//
-void
-mkzruntimedefs(char *dir, char *file)
-{
- int i, skip;
- char *p;
- Buf in, b, b1, out;
- Vec argv, lines, fields, seen;
-
- binit(&in);
- binit(&b);
- binit(&b1);
- binit(&out);
- vinit(&argv);
- vinit(&lines);
- vinit(&fields);
- vinit(&seen);
-
- bwritestr(&out, "// auto generated by go tool dist\n"
- "\n");
-
- if(streq(goos, "linux")) {
- bwritestr(&out, "// +build !android\n\n");
- }
-
- bwritestr(&out,
- "package runtime\n"
- "import \"unsafe\"\n"
- "var _ unsafe.Pointer\n"
- "\n"
- );
-
- // Do not emit definitions for these.
- vadd(&seen, "true");
- vadd(&seen, "false");
- vadd(&seen, "raceenabled");
- vadd(&seen, "allgs");
-
- // Run 6c -D GOOS_goos -D GOARCH_goarch -I workdir -q -n -o workdir/runtimedefs
- // on each of the runtimedefs C files.
- vadd(&argv, bpathf(&b, "%s/%sc", tooldir, gochar));
- vadd(&argv, "-D");
- vadd(&argv, bprintf(&b, "GOOS_%s", goos));
- vadd(&argv, "-D");
- vadd(&argv, bprintf(&b, "GOARCH_%s", goarch));
- vadd(&argv, "-I");
- vadd(&argv, bprintf(&b, "%s", workdir));
- vadd(&argv, "-I");
- vadd(&argv, bprintf(&b, "%s/pkg/%s_%s", goroot, goos, goarch));
- vadd(&argv, "-q");
- vadd(&argv, "-n");
- vadd(&argv, "-o");
- vadd(&argv, bpathf(&b, "%s/runtimedefs", workdir));
- vadd(&argv, "");
- p = argv.p[argv.len-1];
- for(i=0; i<nelem(runtimedefs); i++) {
- argv.p[argv.len-1] = runtimedefs[i];
- runv(nil, dir, CheckExit, &argv);
- readfile(&b, bpathf(&b1, "%s/runtimedefs", workdir));
- bwriteb(&in, &b);
- }
- argv.p[argv.len-1] = p;
-
- // Process the aggregate output.
- skip = 0;
- splitlines(&lines, bstr(&in));
- for(i=0; i<lines.len; i++) {
- p = lines.p[i];
- // Drop comment and func lines.
- if(hasprefix(p, "//") || hasprefix(p, "func"))
- continue;
-
- // Note beginning of type or var decl, which can be multiline.
- // Remove duplicates. The linear check of seen here makes the
- // whole processing quadratic in aggregate, but there are only
- // about 100 declarations, so this is okay (and simple).
- if(hasprefix(p, "type ") || hasprefix(p, "var ") || hasprefix(p, "const ")) {
- splitfields(&fields, p);
- if(fields.len < 2)
- continue;
- if(find(fields.p[1], seen.p, seen.len) >= 0) {
- if(streq(fields.p[fields.len-1], "{"))
- skip = 1; // skip until }
- continue;
- }
- vadd(&seen, fields.p[1]);
- }
-
- // Const lines are printed in original case (usually upper). Add a leading _ as needed.
- if(hasprefix(p, "const ")) {
- if('A' <= p[6] && p[6] <= 'Z')
- bwritestr(&out, "const _");
- else
- bwritestr(&out, "const ");
- bwritestr(&out, p+6);
- continue;
- }
-
- if(skip) {
- if(hasprefix(p, "}"))
- skip = 0;
- continue;
- }
-
- bwritestr(&out, p);
- }
-
- // Some windows specific const.
- if(streq(goos, "windows")) {
- bwritestr(&out, bprintf(&b, "const cb_max = %d\n", MAXWINCB));
- }
-
- writefile(&out, file, 0);
-
- bfree(&in);
- bfree(&b);
- bfree(&b1);
- bfree(&out);
- vfree(&argv);
- vfree(&lines);
- vfree(&fields);
- vfree(&seen);
-}
diff --git a/src/cmd/gc/export.c b/src/cmd/gc/export.c
index da5984ceb..aeee55236 100644
--- a/src/cmd/gc/export.c
+++ b/src/cmd/gc/export.c
@@ -7,6 +7,8 @@
#include "go.h"
#include "y.tab.h"
+static NodeList *asmlist;
+
static void dumpexporttype(Type *t);
// Mark n's symbol as exported
@@ -68,6 +70,11 @@ autoexport(Node *n, int ctxt)
// -A is for cmd/gc/mkbuiltin script, so export everything
if(debug['A'] || exportname(n->sym->name) || initname(n->sym->name))
exportsym(n);
+ if(asmhdr && n->sym->pkg == localpkg && !(n->sym->flags & SymAsm)) {
+ n->sym->flags |= SymAsm;
+ asmlist = list(asmlist, n);
+ }
+
}
static void
@@ -519,3 +526,37 @@ importtype(Type *pt, Type *t)
if(debug['E'])
print("import type %T %lT\n", pt, t);
}
+
+void
+dumpasmhdr(void)
+{
+ Biobuf *b;
+ NodeList *l;
+ Node *n;
+ Type *t;
+
+ b = Bopen(asmhdr, OWRITE);
+ if(b == nil)
+ fatal("open %s: %r", asmhdr);
+ Bprint(b, "// generated by %cg -asmhdr from package %s\n\n", thechar, localpkg->name);
+ for(l=asmlist; l; l=l->next) {
+ n = l->n;
+ if(isblanksym(n->sym))
+ continue;
+ switch(n->op) {
+ case OLITERAL:
+ Bprint(b, "#define const_%s %#V\n", n->sym->name, &n->val);
+ break;
+ case OTYPE:
+ t = n->type;
+ if(t->etype != TSTRUCT || t->map != T || t->funarg)
+ break;
+ for(t=t->type; t != T; t=t->down)
+ if(!isblanksym(t->sym))
+ Bprint(b, "#define %s_%s %d\n", n->sym->name, t->sym->name, (int)t->width);
+ break;
+ }
+ }
+
+ Bterm(b);
+}
diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h
index d3c4193b5..6e326961d 100644
--- a/src/cmd/gc/go.h
+++ b/src/cmd/gc/go.h
@@ -382,6 +382,7 @@ enum
SymExported = 1<<2, // already written out by export
SymUniq = 1<<3,
SymSiggen = 1<<4,
+ SymAsm = 1<<5,
};
struct Sym
@@ -393,6 +394,7 @@ struct Sym
int32 npkg; // number of imported packages with this name
uint32 uniqgen;
Pkg* importdef; // where imported definition was found
+ char* linkname; // link name
// saved and restored by dcopy
Pkg* pkg;
@@ -860,6 +862,8 @@ EXTERN int32 lexlineno;
EXTERN int32 lineno;
EXTERN int32 prevlineno;
+EXTERN Fmt pragcgobuf;
+
EXTERN char* infile;
EXTERN char* outfile;
EXTERN Biobuf* bout;
@@ -890,6 +894,7 @@ EXTERN Pkg* typelinkpkg; // fake package for runtime type info (data)
EXTERN Pkg* weaktypepkg; // weak references to runtime type info
EXTERN Pkg* unsafepkg; // package unsafe
EXTERN Pkg* trackpkg; // fake package for field tracking
+EXTERN Pkg* rawpkg; // fake package for raw symbol names
EXTERN Pkg* phash[128];
EXTERN int tptr; // either TPTR32 or TPTR64
extern char* runtimeimport;
@@ -897,6 +902,7 @@ extern char* unsafeimport;
EXTERN char* myimportpath;
EXTERN Idir* idirs;
EXTERN char* localimport;
+EXTERN char* asmhdr;
EXTERN Type* types[NTYPE];
EXTERN Type* idealstring;
@@ -1147,6 +1153,7 @@ void escapes(NodeList*);
*/
void autoexport(Node *n, int ctxt);
void dumpexport(void);
+void dumpasmhdr(void);
int exportname(char *s);
void exportsym(Node *n);
void importconst(Sym *s, Type *t, Node *n);
diff --git a/src/cmd/gc/lex.c b/src/cmd/gc/lex.c
index 2303b442c..2bd7adfb6 100644
--- a/src/cmd/gc/lex.c
+++ b/src/cmd/gc/lex.c
@@ -17,6 +17,8 @@ extern int yychar;
int yyprev;
int yylast;
+static int imported_unsafe;
+
static void lexinit(void);
static void lexinit1(void);
static void lexfini(void);
@@ -271,6 +273,9 @@ main(int argc, char *argv[])
flag_largemodel = 1;
setexp();
+
+ fmtstrinit(&pragcgobuf);
+ quotefmtinstall();
outfile = nil;
flagcount("+", "compiling runtime", &compiling_runtime);
@@ -289,6 +294,7 @@ main(int argc, char *argv[])
flagcount("S", "print assembly listing", &debug['S']);
flagfn0("V", "print compiler version", doversion);
flagcount("W", "debug parse tree after type checking", &debug['W']);
+ flagstr("asmhdr", "file: write assembly header to named file", &asmhdr);
flagcount("complete", "compiling complete package (no C or assembly)", &pure_go);
flagstr("d", "list: print debug information about items in list", &debugstr);
flagcount("e", "no limit on number of errors reported", &debug['e']);
@@ -344,8 +350,8 @@ main(int argc, char *argv[])
break;
}
}
- if(j == nelem(debugtab))
- fatal("unknown debug information -d '%s'\n", f[i]);
+ if(debugtab[j].name == nil)
+ sysfatal("unknown debug information -d '%s'\n", f[i]);
}
}
@@ -403,6 +409,8 @@ main(int argc, char *argv[])
block = 1;
iota = -1000000;
+
+ imported_unsafe = 0;
yyparse();
if(nsyntaxerrors != 0)
@@ -509,6 +517,9 @@ main(int argc, char *argv[])
errorexit();
dumpobj();
+
+ if(asmhdr)
+ dumpasmhdr();
if(nerrors+nsavederrors)
errorexit();
@@ -724,6 +735,7 @@ importfile(Val *f, int line)
}
importpkg = mkpkg(f->u.sval);
cannedimports("unsafe.6", unsafeimport);
+ imported_unsafe = 1;
return;
}
@@ -1501,6 +1513,20 @@ caseout:
return LLITERAL;
}
+static void pragcgo(char*);
+
+static int
+more(char **pp)
+{
+ char *p;
+
+ p = *pp;
+ while(yy_isspace(*p))
+ p++;
+ *pp = p;
+ return *p != '\0';
+}
+
/*
* read and interpret syntax that looks like
* //line parse.y:15
@@ -1583,9 +1609,39 @@ go:
*cp++ = c;
}
*cp = 0;
+
+ if(strncmp(lexbuf, "go:cgo_", 7) == 0)
+ pragcgo(lexbuf);
+
ep = strchr(lexbuf, ' ');
if(ep != nil)
*ep = 0;
+
+ if(strcmp(lexbuf, "go:linkname") == 0) {
+ if(!imported_unsafe)
+ yyerror("//go:linkname only allowed in Go files that import \"unsafe\"");
+ if(ep == nil) {
+ yyerror("usage: //go:linkname localname linkname");
+ goto out;
+ }
+ cp = ep+1;
+ while(yy_isspace(*cp))
+ cp++;
+ ep = strchr(cp, ' ');
+ if(ep == nil) {
+ yyerror("usage: //go:linkname localname linkname");
+ goto out;
+ }
+ *ep++ = 0;
+ while(yy_isspace(*ep))
+ ep++;
+ if(*ep == 0) {
+ yyerror("usage: //go:linkname localname linkname");
+ goto out;
+ }
+ lookup(cp)->linkname = strdup(ep);
+ goto out;
+ }
if(strcmp(lexbuf, "go:nointerface") == 0 && fieldtrack_enabled) {
nointerface = 1;
@@ -1604,6 +1660,150 @@ out:
return c;
}
+static char*
+getimpsym(char **pp)
+{
+ char *p, *start;
+
+ more(pp); // skip spaces
+
+ p = *pp;
+ if(*p == '\0' || *p == '"')
+ return nil;
+
+ start = p;
+ while(*p != '\0' && !yy_isspace(*p) && *p != '"')
+ p++;
+ if(*p != '\0')
+ *p++ = '\0';
+
+ *pp = p;
+ return start;
+}
+
+static char*
+getquoted(char **pp)
+{
+ char *p, *start;
+
+ more(pp); // skip spaces
+
+ p = *pp;
+ if(*p != '"')
+ return nil;
+ p++;
+
+ start = p;
+ while(*p != '"') {
+ if(*p == '\0')
+ return nil;
+ p++;
+ }
+ *p++ = '\0';
+ *pp = p;
+ return start;
+}
+
+// Copied nearly verbatim from the C compiler's #pragma parser.
+// TODO: Rewrite more cleanly once the compiler is written in Go.
+static void
+pragcgo(char *text)
+{
+ char *local, *remote, *p, *q, *verb;
+
+ for(q=text; *q != '\0' && *q != ' '; q++)
+ ;
+ if(*q == ' ')
+ *q++ = '\0';
+
+ verb = text+3; // skip "go:"
+
+ if(strcmp(verb, "cgo_dynamic_linker") == 0 || strcmp(verb, "dynlinker") == 0) {
+ p = getquoted(&q);
+ if(p == nil)
+ goto err1;
+ fmtprint(&pragcgobuf, "cgo_dynamic_linker %q\n", p);
+ goto out;
+
+ err1:
+ yyerror("usage: //go:cgo_dynamic_linker \"path\"");
+ goto out;
+ }
+
+ if(strcmp(verb, "dynexport") == 0)
+ verb = "cgo_export_dynamic";
+ if(strcmp(verb, "cgo_export_static") == 0 || strcmp(verb, "cgo_export_dynamic") == 0) {
+ local = getimpsym(&q);
+ if(local == nil)
+ goto err2;
+ if(!more(&q)) {
+ fmtprint(&pragcgobuf, "%s %q\n", verb, local);
+ goto out;
+ }
+ remote = getimpsym(&q);
+ if(remote == nil)
+ goto err2;
+ fmtprint(&pragcgobuf, "%s %q %q\n", verb, local, remote);
+ goto out;
+
+ err2:
+ yyerror("usage: //go:%s local [remote]", verb);
+ goto out;
+ }
+
+ if(strcmp(verb, "cgo_import_dynamic") == 0 || strcmp(verb, "dynimport") == 0) {
+ local = getimpsym(&q);
+ if(local == nil)
+ goto err3;
+ if(!more(&q)) {
+ fmtprint(&pragcgobuf, "cgo_import_dynamic %q\n", local);
+ goto out;
+ }
+ remote = getimpsym(&q);
+ if(remote == nil)
+ goto err3;
+ if(!more(&q)) {
+ fmtprint(&pragcgobuf, "cgo_import_dynamic %q %q\n", local, remote);
+ goto out;
+ }
+ p = getquoted(&q);
+ if(p == nil)
+ goto err3;
+ fmtprint(&pragcgobuf, "cgo_import_dynamic %q %q %q\n", local, remote, p);
+ goto out;
+
+ err3:
+ yyerror("usage: //go:cgo_import_dynamic local [remote [\"library\"]]");
+ goto out;
+ }
+
+ if(strcmp(verb, "cgo_import_static") == 0) {
+ local = getimpsym(&q);
+ if(local == nil || more(&q))
+ goto err4;
+ fmtprint(&pragcgobuf, "cgo_import_static %q\n", local);
+ goto out;
+
+ err4:
+ yyerror("usage: //go:cgo_import_static local");
+ goto out;
+ }
+
+ if(strcmp(verb, "cgo_ldflag") == 0) {
+ p = getquoted(&q);
+ if(p == nil)
+ goto err5;
+ fmtprint(&pragcgobuf, "cgo_ldflag %q\n", p);
+ goto out;
+
+ err5:
+ yyerror("usage: //go:cgo_ldflag \"arg\"");
+ goto out;
+ }
+
+out:;
+}
+
int32
yylex(void)
{
diff --git a/src/cmd/gc/obj.c b/src/cmd/gc/obj.c
index b752a13ce..7e4e97854 100644
--- a/src/cmd/gc/obj.c
+++ b/src/cmd/gc/obj.c
@@ -67,6 +67,16 @@ dumpobj(void)
startobj = Boffset(bout);
Bprint(bout, "go object %s %s %s %s\n", getgoos(), getgoarch(), getgoversion(), expstring());
}
+
+ if(pragcgobuf.to > pragcgobuf.start) {
+ if(writearchive) {
+ // write empty export section; must be before cgo section
+ Bprint(bout, "\n$$\n\n$$\n\n");
+ }
+ Bprint(bout, "\n$$ // cgo\n");
+ Bprint(bout, "%s\n$$\n\n", fmtstrflush(&pragcgobuf));
+ }
+
Bprint(bout, "\n!\n");
@@ -153,6 +163,8 @@ linksym(Sym *s)
return s->lsym;
if(isblanksym(s))
s->lsym = linklookup(ctxt, "_", 0);
+ else if(s->linkname != nil)
+ s->lsym = linklookup(ctxt, s->linkname, 0);
else {
p = smprint("%s.%s", s->pkg->prefix, s->name);
s->lsym = linklookup(ctxt, p, 0);
diff --git a/src/cmd/gc/plive.c b/src/cmd/gc/plive.c
index 0feb2c710..3bfa69b1f 100644
--- a/src/cmd/gc/plive.c
+++ b/src/cmd/gc/plive.c
@@ -1092,7 +1092,7 @@ twobitwalktype1(Type *t, vlong *xoffset, Bvec *bv)
case TCOMPLEX64:
case TCOMPLEX128:
for(i = 0; i < t->width; i++) {
- bvset(bv, ((*xoffset + i) / widthptr) * BitsPerPointer); // 1 = live scalar
+ bvset(bv, ((*xoffset + i) / widthptr) * BitsPerPointer); // 1 = live scalar (BitsScalar)
}
*xoffset += t->width;
break;
@@ -1105,7 +1105,7 @@ twobitwalktype1(Type *t, vlong *xoffset, Bvec *bv)
case TMAP:
if((*xoffset & (widthptr-1)) != 0)
fatal("twobitwalktype1: invalid alignment, %T", t);
- bvset(bv, (*xoffset / widthptr) * BitsPerPointer + 1); // 2 = live ptr
+ bvset(bv, (*xoffset / widthptr) * BitsPerPointer + 1); // 2 = live ptr (BitsPointer)
*xoffset += t->width;
break;
@@ -1113,7 +1113,7 @@ twobitwalktype1(Type *t, vlong *xoffset, Bvec *bv)
// struct { byte *str; intgo len; }
if((*xoffset & (widthptr-1)) != 0)
fatal("twobitwalktype1: invalid alignment, %T", t);
- bvset(bv, (*xoffset / widthptr) * BitsPerPointer + 1); // 2 = live ptr in first slot
+ bvset(bv, (*xoffset / widthptr) * BitsPerPointer + 1); // 2 = live ptr in first slot (BitsPointer)
*xoffset += t->width;
break;
@@ -1123,15 +1123,8 @@ twobitwalktype1(Type *t, vlong *xoffset, Bvec *bv)
// struct { Type *type; union { void *ptr, uintptr val } data; }
if((*xoffset & (widthptr-1)) != 0)
fatal("twobitwalktype1: invalid alignment, %T", t);
- bvset(bv, ((*xoffset / widthptr) * BitsPerPointer) + 0);
- bvset(bv, ((*xoffset / widthptr) * BitsPerPointer) + 1); // 3 = multiword
- // next word contains 2 = Iface, 3 = Eface
- if(isnilinter(t)) {
- bvset(bv, ((*xoffset / widthptr) * BitsPerPointer) + 2);
- bvset(bv, ((*xoffset / widthptr) * BitsPerPointer) + 3);
- } else {
- bvset(bv, ((*xoffset / widthptr) * BitsPerPointer) + 3);
- }
+ bvset(bv, (*xoffset / widthptr) * BitsPerPointer + 1); // 2 = live ptr in first slot (BitsPointer)
+ bvset(bv, (*xoffset / widthptr) * BitsPerPointer + 3); // 2 = live ptr in second slot (BitsPointer)
*xoffset += t->width;
break;
@@ -1144,7 +1137,7 @@ twobitwalktype1(Type *t, vlong *xoffset, Bvec *bv)
// struct { byte *array; uintgo len; uintgo cap; }
if((*xoffset & (widthptr-1)) != 0)
fatal("twobitwalktype1: invalid TARRAY alignment, %T", t);
- bvset(bv, (*xoffset / widthptr) * BitsPerPointer + 1); // 2 = live ptr in first slot
+ bvset(bv, (*xoffset / widthptr) * BitsPerPointer + 1); // 2 = live ptr in first slot (BitsPointer)
*xoffset += t->width;
} else
for(i = 0; i < t->bound; i++)
diff --git a/src/cmd/gc/reflect.c b/src/cmd/gc/reflect.c
index b2ff2fbc5..4155953be 100644
--- a/src/cmd/gc/reflect.c
+++ b/src/cmd/gc/reflect.c
@@ -1318,7 +1318,7 @@ gengcmask(Type *t, uint8 gcmask[16])
{
Bvec *vec;
vlong xoffset, nptr, i, j;
- int half, mw;
+ int half;
uint8 bits, *pos;
memset(gcmask, 0, 16);
@@ -1335,7 +1335,6 @@ gengcmask(Type *t, uint8 gcmask[16])
pos = (uint8*)gcmask;
nptr = (t->width+widthptr-1)/widthptr;
half = 0;
- mw = 0;
// If number of words is odd, repeat the mask.
// This makes simpler handling of arrays in runtime.
for(j=0; j<=(nptr%2); j++) {
@@ -1344,9 +1343,8 @@ gengcmask(Type *t, uint8 gcmask[16])
// Some fake types (e.g. Hmap) has missing fileds.
// twobitwalktype1 generates BitsDead for that holes,
// replace BitsDead with BitsScalar.
- if(!mw && bits == BitsDead)
+ if(bits == BitsDead)
bits = BitsScalar;
- mw = !mw && bits == BitsMultiWord;
bits <<= 2;
if(half)
bits <<= 4;
@@ -1525,11 +1523,9 @@ gengcprog1(ProgGen *g, Type *t, vlong *xoffset)
*xoffset += t->width;
break;
case TINTER:
- proggendata(g, BitsMultiWord);
- if(isnilinter(t))
- proggendata(g, BitsEface);
- else
- proggendata(g, BitsIface);
+ // Assuming IfacePointerOnly=1.
+ proggendata(g, BitsPointer);
+ proggendata(g, BitsPointer);
*xoffset += t->width;
break;
case TARRAY:
diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c
index c3bc5af3b..5e369b695 100644
--- a/src/cmd/gc/subr.c
+++ b/src/cmd/gc/subr.c
@@ -3802,39 +3802,25 @@ checknil(Node *x, NodeList **init)
/*
* Can this type be stored directly in an interface word?
+ * Yes, if the representation is a single pointer.
*/
int
isdirectiface(Type *t)
{
- // Setting IfacePointerOnly = 1 changes the
- // interface representation so that the data word
- // in an interface value must always be a pointer.
- // Setting it to 0 uses the original representation,
- // where the data word can hold a pointer or any
- // non-pointer value no bigger than a pointer.
- enum {
- IfacePointerOnly = 1,
- };
-
- if(IfacePointerOnly) {
- switch(t->etype) {
- case TPTR32:
- case TPTR64:
- case TCHAN:
- case TMAP:
- case TFUNC:
- case TUNSAFEPTR:
- return 1;
- case TARRAY:
- // Array of 1 direct iface type can be direct.
- return t->bound == 1 && isdirectiface(t->type);
- case TSTRUCT:
- // Struct with 1 field of direct iface type can be direct.
- return t->type != T && t->type->down == T && isdirectiface(t->type->type);
- }
- return 0;
+ switch(t->etype) {
+ case TPTR32:
+ case TPTR64:
+ case TCHAN:
+ case TMAP:
+ case TFUNC:
+ case TUNSAFEPTR:
+ return 1;
+ case TARRAY:
+ // Array of 1 direct iface type can be direct.
+ return t->bound == 1 && isdirectiface(t->type);
+ case TSTRUCT:
+ // Struct with 1 field of direct iface type can be direct.
+ return t->type != T && t->type->down == T && isdirectiface(t->type->type);
}
-
- dowidth(t);
- return t->width <= widthptr;
+ return 0;
}
diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c
index d4d0f449c..77f9c80f9 100644
--- a/src/cmd/gc/walk.c
+++ b/src/cmd/gc/walk.c
@@ -1766,7 +1766,6 @@ walkprint(Node *nn, NodeList **init)
int notfirst, et, op;
NodeList *calls;
- on = nil;
op = nn->op;
all = nn->list;
calls = nil;
diff --git a/src/cmd/go/build.go b/src/cmd/go/build.go
index 79a27116a..5dcaa04a1 100644
--- a/src/cmd/go/build.go
+++ b/src/cmd/go/build.go
@@ -813,7 +813,7 @@ func (b *builder) build(a *action) (err error) {
}
if a.p.Standard && a.p.ImportPath == "runtime" && buildContext.Compiler == "gc" &&
- !hasString(a.p.HFiles, "zasm_"+buildContext.GOOS+"_"+buildContext.GOARCH+".h") {
+ !hasString(a.p.SFiles, "zsys_"+buildContext.GOOS+"_"+buildContext.GOARCH+".s") {
return fmt.Errorf("%s/%s must be bootstrapped using make%v", buildContext.GOOS, buildContext.GOARCH, defaultSuffix())
}
@@ -941,7 +941,7 @@ func (b *builder) build(a *action) (err error) {
inc := b.includeArgs("-I", a.deps)
// Compile Go.
- ofile, out, err := buildToolchain.gc(b, a.p, a.objpkg, obj, inc, gofiles)
+ ofile, out, err := buildToolchain.gc(b, a.p, a.objpkg, obj, len(sfiles) > 0, inc, gofiles)
if len(out) > 0 {
b.showOutput(a.p.Dir, a.p.ImportPath, b.processOutput(out))
if err != nil {
@@ -1550,7 +1550,7 @@ type toolchain interface {
// gc runs the compiler in a specific directory on a set of files
// and returns the name of the generated output file.
// The compiler runs in the directory dir.
- gc(b *builder, p *Package, archive, obj string, importArgs []string, gofiles []string) (ofile string, out []byte, err error)
+ gc(b *builder, p *Package, archive, obj string, asmhdr bool, importArgs []string, gofiles []string) (ofile string, out []byte, err error)
// cc runs the toolchain's C compiler in a directory on a C file
// to produce an output file.
cc(b *builder, p *Package, objdir, ofile, cfile string) error
@@ -1587,7 +1587,7 @@ func (noToolchain) linker() string {
return ""
}
-func (noToolchain) gc(b *builder, p *Package, archive, obj string, importArgs []string, gofiles []string) (ofile string, out []byte, err error) {
+func (noToolchain) gc(b *builder, p *Package, archive, obj string, asmhdr bool, importArgs []string, gofiles []string) (ofile string, out []byte, err error) {
return "", nil, noCompiler()
}
@@ -1623,7 +1623,7 @@ func (gcToolchain) linker() string {
return tool(archChar + "l")
}
-func (gcToolchain) gc(b *builder, p *Package, archive, obj string, importArgs []string, gofiles []string) (ofile string, output []byte, err error) {
+func (gcToolchain) gc(b *builder, p *Package, archive, obj string, asmhdr bool, importArgs []string, gofiles []string) (ofile string, output []byte, err error) {
if archive != "" {
ofile = archive
} else {
@@ -1660,6 +1660,9 @@ func (gcToolchain) gc(b *builder, p *Package, archive, obj string, importArgs []
if ofile == archive {
args = append(args, "-pack")
}
+ if asmhdr {
+ args = append(args, "-asmhdr", obj+"go_asm.h")
+ }
for _, f := range gofiles {
args = append(args, mkAbs(p.Dir, f))
}
@@ -1824,10 +1827,7 @@ func (gcToolchain) ld(b *builder, p *Package, out string, allactions []*action,
}
func (gcToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error {
- inc := filepath.Join(goroot, "pkg", fmt.Sprintf("%s_%s", goos, goarch))
- cfile = mkAbs(p.Dir, cfile)
- args := stringList(tool(archChar+"c"), "-F", "-V", "-w", "-trimpath", b.work, "-I", objdir, "-I", inc, "-o", ofile, buildCcflags, "-D", "GOOS_"+goos, "-D", "GOARCH_"+goarch, cfile)
- return b.run(p.Dir, p.ImportPath, nil, args)
+ return fmt.Errorf("%s: C source files not supported without cgo", mkAbs(p.Dir, cfile))
}
// The Gccgo toolchain.
@@ -1851,7 +1851,7 @@ func (gccgoToolchain) linker() string {
return gccgoBin
}
-func (gccgoToolchain) gc(b *builder, p *Package, archive, obj string, importArgs []string, gofiles []string) (ofile string, output []byte, err error) {
+func (gccgoToolchain) gc(b *builder, p *Package, archive, obj string, asmhdr bool, importArgs []string, gofiles []string) (ofile string, output []byte, err error) {
out := "_go_.o"
ofile = obj + out
gcargs := []string{"-g"}
@@ -2217,11 +2217,14 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, gccfi
outGo = append(outGo, gofiles...)
// cc _cgo_defun.c
- defunObj := obj + "_cgo_defun." + objExt
- if err := buildToolchain.cc(b, p, obj, defunObj, defunC); err != nil {
- return nil, nil, err
+ _, gccgo := buildToolchain.(gccgoToolchain)
+ if gccgo {
+ defunObj := obj + "_cgo_defun." + objExt
+ if err := buildToolchain.cc(b, p, obj, defunObj, defunC); err != nil {
+ return nil, nil, err
+ }
+ outObj = append(outObj, defunObj)
}
- outObj = append(outObj, defunObj)
// gcc
var linkobj []string
@@ -2335,20 +2338,15 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, gccfi
}
// cgo -dynimport
- importC := obj + "_cgo_import.c"
+ importGo := obj + "_cgo_import.go"
cgoflags = []string{}
if p.Standard && p.ImportPath == "runtime/cgo" {
cgoflags = append(cgoflags, "-dynlinker") // record path to dynamic linker
}
- if err := b.run(p.Dir, p.ImportPath, nil, cgoExe, "-objdir", obj, "-dynimport", dynobj, "-dynout", importC, cgoflags); err != nil {
- return nil, nil, err
- }
-
- // cc _cgo_import.ARCH
- importObj := obj + "_cgo_import." + objExt
- if err := buildToolchain.cc(b, p, obj, importObj, importC); err != nil {
+ if err := b.run(p.Dir, p.ImportPath, nil, cgoExe, "-objdir", obj, "-dynpackage", p.Name, "-dynimport", dynobj, "-dynout", importGo, cgoflags); err != nil {
return nil, nil, err
}
+ outGo = append(outGo, importGo)
ofile := obj + "_all.o"
var gccObjs, nonGccObjs []string
@@ -2382,7 +2380,7 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, gccfi
// NOTE(rsc): The importObj is a 5c/6c/8c object and on Windows
// must be processed before the gcc-generated objects.
// Put it first. http://golang.org/issue/2601
- outObj = stringList(importObj, nonGccObjs, ofile)
+ outObj = stringList(nonGccObjs, ofile)
return outGo, outObj, nil
}
@@ -2518,7 +2516,7 @@ func (b *builder) swigIntSize(obj string) (intsize string, err error) {
p := goFilesPackage(srcs)
- if _, _, e := buildToolchain.gc(b, p, "", obj, nil, srcs); e != nil {
+ if _, _, e := buildToolchain.gc(b, p, "", obj, false, nil, srcs); e != nil {
return "32", nil
}
return "64", nil
diff --git a/src/cmd/go/doc.go b/src/cmd/go/doc.go
index cf3a54565..43a315944 100644
--- a/src/cmd/go/doc.go
+++ b/src/cmd/go/doc.go
@@ -590,7 +590,7 @@ Usage:
Vet runs the Go vet command on the packages named by the import paths.
-For more about vet, see 'godoc code.google.com/p/go.tools/cmd/vet'.
+For more about vet, see 'godoc golang.org/x/tools/cmd/vet'.
For more about specifying packages, see 'go help packages'.
To run the vet tool with specific options, run 'go tool vet'.
diff --git a/src/cmd/go/pkg.go b/src/cmd/go/pkg.go
index e17326442..b71feb7a6 100644
--- a/src/cmd/go/pkg.go
+++ b/src/cmd/go/pkg.go
@@ -383,9 +383,10 @@ func findInternal(path string) (index int, ok bool) {
type targetDir int
const (
- toRoot targetDir = iota // to bin dir inside package root (default)
- toTool // GOROOT/pkg/tool
- toBin // GOROOT/bin
+ toRoot targetDir = iota // to bin dir inside package root (default)
+ toTool // GOROOT/pkg/tool
+ toBin // GOROOT/bin
+ stalePath // the old import path; fail to build
)
// goTools is a map of Go program import path to install target directory.
@@ -398,10 +399,14 @@ var goTools = map[string]targetDir{
"cmd/nm": toTool,
"cmd/objdump": toTool,
"cmd/pack": toTool,
+ "cmd/pprof": toTool,
"cmd/yacc": toTool,
- "code.google.com/p/go.tools/cmd/cover": toTool,
- "code.google.com/p/go.tools/cmd/godoc": toBin,
- "code.google.com/p/go.tools/cmd/vet": toTool,
+ "golang.org/x/tools/cmd/cover": toTool,
+ "golang.org/x/tools/cmd/godoc": toBin,
+ "golang.org/x/tools/cmd/vet": toTool,
+ "code.google.com/p/go.tools/cmd/cover": stalePath,
+ "code.google.com/p/go.tools/cmd/godoc": stalePath,
+ "code.google.com/p/go.tools/cmd/vet": stalePath,
}
// expandScanner expands a scanner.List error into all the errors in the list.
@@ -462,6 +467,13 @@ func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package
}
if p.Name == "main" {
+ // Report an error when the old code.google.com/p/go.tools paths are used.
+ if goTools[p.ImportPath] == stalePath {
+ newPath := strings.Replace(p.ImportPath, "code.google.com/p/go.", "golang.org/x/", 1)
+ e := fmt.Sprintf("the %v command has moved; use %v instead.", p.ImportPath, newPath)
+ p.Error = &PackageError{Err: e}
+ return p
+ }
_, elem := filepath.Split(p.Dir)
full := buildContext.GOOS + "_" + buildContext.GOARCH + "/" + elem
if buildContext.GOOS != toolGOOS || buildContext.GOARCH != toolGOARCH {
diff --git a/src/cmd/go/test.bash b/src/cmd/go/test.bash
index 2b5230b1a..e0f066f18 100755
--- a/src/cmd/go/test.bash
+++ b/src/cmd/go/test.bash
@@ -433,20 +433,20 @@ TEST godoc installs into GOBIN
d=$(mktemp -d -t testgoXXX)
export GOPATH=$d
mkdir $d/gobin
-GOBIN=$d/gobin ./testgo get code.google.com/p/go.tools/cmd/godoc || ok=false
+GOBIN=$d/gobin ./testgo get golang.org/x/tools/cmd/godoc || ok=false
if [ ! -x $d/gobin/godoc ]; then
echo did not install godoc to '$GOBIN'
- GOBIN=$d/gobin ./testgo list -f 'Target: {{.Target}}' code.google.com/p/go.tools/cmd/godoc || true
+ GOBIN=$d/gobin ./testgo list -f 'Target: {{.Target}}' golang.org/x/tools/cmd/godoc || true
ok=false
fi
TEST godoc installs into GOROOT
GOROOT=$(./testgo env GOROOT)
rm -f $GOROOT/bin/godoc
-./testgo install code.google.com/p/go.tools/cmd/godoc || ok=false
+./testgo install golang.org/x/tools/cmd/godoc || ok=false
if [ ! -x $GOROOT/bin/godoc ]; then
echo did not install godoc to '$GOROOT/bin'
- ./testgo list -f 'Target: {{.Target}}' code.google.com/p/go.tools/cmd/godoc || true
+ ./testgo list -f 'Target: {{.Target}}' golang.org/x/tools/cmd/godoc || true
ok=false
fi
@@ -561,8 +561,8 @@ fi
TEST without GOPATH, go get fails
d=$(mktemp -d -t testgoXXX)
mkdir -p $d/src
-if GOPATH= GOROOT=$d ./testgo get -d code.google.com/p/go.codereview/cmd/hgpatch ; then
- echo 'go get code.google.com/p/go.codereview/cmd/hgpatch should not succeed with $GOPATH unset'
+if GOPATH= GOROOT=$d ./testgo get -d golang.org/x/codereview/cmd/hgpatch ; then
+ echo 'go get golang.org/x/codereview/cmd/hgpatch should not succeed with $GOPATH unset'
ok=false
fi
rm -rf $d
@@ -571,8 +571,8 @@ rm -rf $d
TEST with GOPATH=GOROOT, go get fails
d=$(mktemp -d -t testgoXXX)
mkdir -p $d/src
-if GOPATH=$d GOROOT=$d ./testgo get -d code.google.com/p/go.codereview/cmd/hgpatch ; then
- echo 'go get code.google.com/p/go.codereview/cmd/hgpatch should not succeed with GOPATH=$GOROOT'
+if GOPATH=$d GOROOT=$d ./testgo get -d golang.org/x/codereview/cmd/hgpatch ; then
+ echo 'go get golang.org/x/codereview/cmd/hgpatch should not succeed with GOPATH=$GOROOT'
ok=false
fi
rm -rf $d
@@ -728,7 +728,7 @@ elif ! grep "case-insensitive file name collision" $d/out >/dev/null; then
fi
TEST go get cover
-./testgo get code.google.com/p/go.tools/cmd/cover || ok=false
+./testgo get golang.org/x/tools/cmd/cover || ok=false
unset GOPATH
rm -rf $d
diff --git a/src/cmd/go/tool.go b/src/cmd/go/tool.go
index 6d26f7a4b..c96161e0f 100644
--- a/src/cmd/go/tool.go
+++ b/src/cmd/go/tool.go
@@ -53,7 +53,7 @@ func tool(toolName string) string {
// Give a nice message if there is no tool with that name.
if _, err := os.Stat(toolPath); err != nil {
if isInGoToolsRepo(toolName) {
- fmt.Fprintf(os.Stderr, "go tool: no such tool %q; to install:\n\tgo get code.google.com/p/go.tools/cmd/%s\n", toolName, toolName)
+ fmt.Fprintf(os.Stderr, "go tool: no such tool %q; to install:\n\tgo get golang.org/x/tools/cmd/%s\n", toolName, toolName)
} else {
fmt.Fprintf(os.Stderr, "go tool: no such tool %q\n", toolName)
}
diff --git a/src/cmd/go/vet.go b/src/cmd/go/vet.go
index de7befc61..02ff54b2a 100644
--- a/src/cmd/go/vet.go
+++ b/src/cmd/go/vet.go
@@ -17,7 +17,7 @@ var cmdVet = &Command{
Long: `
Vet runs the Go vet command on the packages named by the import paths.
-For more about vet, see 'godoc code.google.com/p/go.tools/cmd/vet'.
+For more about vet, see 'godoc golang.org/x/tools/cmd/vet'.
For more about specifying packages, see 'go help packages'.
To run the vet tool with specific options, run 'go tool vet'.
diff --git a/src/cmd/internal/objfile/disasm.go b/src/cmd/internal/objfile/disasm.go
new file mode 100644
index 000000000..1a339c321
--- /dev/null
+++ b/src/cmd/internal/objfile/disasm.go
@@ -0,0 +1,248 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package objfile
+
+import (
+ "bufio"
+ "debug/gosym"
+ "encoding/binary"
+ "fmt"
+ "io"
+ "regexp"
+ "sort"
+ "strings"
+ "text/tabwriter"
+
+ "cmd/internal/rsc.io/arm/armasm"
+ "cmd/internal/rsc.io/x86/x86asm"
+)
+
+// Disasm is a disassembler for a given File.
+type Disasm struct {
+ syms []Sym //symbols in file, sorted by address
+ pcln *gosym.Table // pcln table
+ text []byte // bytes of text segment (actual instructions)
+ textStart uint64 // start PC of text
+ textEnd uint64 // end PC of text
+ goarch string // GOARCH string
+ disasm disasmFunc // disassembler function for goarch
+ byteOrder binary.ByteOrder // byte order for goarch
+}
+
+// Disasm returns a disassembler for the file f.
+func (f *File) Disasm() (*Disasm, error) {
+ syms, err := f.Symbols()
+ if err != nil {
+ return nil, err
+ }
+
+ pcln, err := f.PCLineTable()
+ if err != nil {
+ return nil, err
+ }
+
+ textStart, textBytes, err := f.Text()
+ if err != nil {
+ return nil, err
+ }
+
+ goarch := f.GOARCH()
+ disasm := disasms[goarch]
+ byteOrder := byteOrders[goarch]
+ if disasm == nil || byteOrder == nil {
+ return nil, fmt.Errorf("unsupported architecture")
+ }
+
+ // Filter out section symbols, overwriting syms in place.
+ keep := syms[:0]
+ for _, sym := range syms {
+ switch sym.Name {
+ case "runtime.text", "text", "_text", "runtime.etext", "etext", "_etext":
+ // drop
+ default:
+ keep = append(keep, sym)
+ }
+ }
+ syms = keep
+ d := &Disasm{
+ syms: syms,
+ pcln: pcln,
+ text: textBytes,
+ textStart: textStart,
+ textEnd: textStart + uint64(len(textBytes)),
+ goarch: goarch,
+ disasm: disasm,
+ byteOrder: byteOrder,
+ }
+
+ return d, nil
+}
+
+// lookup finds the symbol name containing addr.
+func (d *Disasm) lookup(addr uint64) (name string, base uint64) {
+ i := sort.Search(len(d.syms), func(i int) bool { return addr < d.syms[i].Addr })
+ if i > 0 {
+ s := d.syms[i-1]
+ if s.Addr != 0 && s.Addr <= addr && addr < s.Addr+uint64(s.Size) {
+ return s.Name, s.Addr
+ }
+ }
+ return "", 0
+}
+
+// base returns the final element in the path.
+// It works on both Windows and Unix paths,
+// regardless of host operating system.
+func base(path string) string {
+ path = path[strings.LastIndex(path, "/")+1:]
+ path = path[strings.LastIndex(path, `\`)+1:]
+ return path
+}
+
+// Print prints a disassembly of the file to w.
+// If filter is non-nil, the disassembly only includes functions with names matching filter.
+// The disassembly only includes functions that overlap the range [start, end).
+func (d *Disasm) Print(w io.Writer, filter *regexp.Regexp, start, end uint64) {
+ if start < d.textStart {
+ start = d.textStart
+ }
+ if end > d.textEnd {
+ end = d.textEnd
+ }
+ printed := false
+ bw := bufio.NewWriter(w)
+ for _, sym := range d.syms {
+ symStart := sym.Addr
+ symEnd := sym.Addr + uint64(sym.Size)
+ if sym.Code != 'T' && sym.Code != 't' ||
+ symStart < d.textStart ||
+ symEnd <= start || end <= symStart ||
+ filter != nil && !filter.MatchString(sym.Name) {
+ continue
+ }
+ if printed {
+ fmt.Fprintf(bw, "\n")
+ }
+ printed = true
+
+ file, _, _ := d.pcln.PCToLine(sym.Addr)
+ fmt.Fprintf(bw, "TEXT %s(SB) %s\n", sym.Name, file)
+
+ tw := tabwriter.NewWriter(bw, 1, 8, 1, '\t', 0)
+ if symEnd > end {
+ symEnd = end
+ }
+ code := d.text[:end-d.textStart]
+ d.Decode(symStart, symEnd, func(pc, size uint64, file string, line int, text string) {
+ i := pc - d.textStart
+ fmt.Fprintf(tw, "\t%s:%d\t%#x\t", base(file), line, pc)
+ if size%4 != 0 || d.goarch == "386" || d.goarch == "amd64" {
+ // Print instruction as bytes.
+ fmt.Fprintf(tw, "%x", code[i:i+size])
+ } else {
+ // Print instruction as 32-bit words.
+ for j := uint64(0); j < size; j += 4 {
+ if j > 0 {
+ fmt.Fprintf(tw, " ")
+ }
+ fmt.Fprintf(tw, "%08x", d.byteOrder.Uint32(code[i+j:]))
+ }
+ }
+ fmt.Fprintf(tw, "\t%s\n", text)
+ })
+ tw.Flush()
+ }
+ bw.Flush()
+}
+
+// Decode disassembles the text segment range [start, end), calling f for each instruction.
+func (d *Disasm) Decode(start, end uint64, f func(pc, size uint64, file string, line int, text string)) {
+ if start < d.textStart {
+ start = d.textStart
+ }
+ if end > d.textEnd {
+ end = d.textEnd
+ }
+ code := d.text[:end-d.textStart]
+ lookup := d.lookup
+ for pc := start; pc < end; {
+ i := pc - d.textStart
+ text, size := d.disasm(code[i:], pc, lookup)
+ file, line, _ := d.pcln.PCToLine(pc)
+ f(pc, uint64(size), file, line, text)
+ pc += uint64(size)
+ }
+}
+
+type lookupFunc func(addr uint64) (sym string, base uint64)
+type disasmFunc func(code []byte, pc uint64, lookup lookupFunc) (text string, size int)
+
+func disasm_386(code []byte, pc uint64, lookup lookupFunc) (string, int) {
+ return disasm_x86(code, pc, lookup, 32)
+}
+
+func disasm_amd64(code []byte, pc uint64, lookup lookupFunc) (string, int) {
+ return disasm_x86(code, pc, lookup, 64)
+}
+
+func disasm_x86(code []byte, pc uint64, lookup lookupFunc, arch int) (string, int) {
+ inst, err := x86asm.Decode(code, 64)
+ var text string
+ size := inst.Len
+ if err != nil || size == 0 || inst.Op == 0 {
+ size = 1
+ text = "?"
+ } else {
+ text = x86asm.Plan9Syntax(inst, pc, lookup)
+ }
+ return text, size
+}
+
+type textReader struct {
+ code []byte
+ pc uint64
+}
+
+func (r textReader) ReadAt(data []byte, off int64) (n int, err error) {
+ if off < 0 || uint64(off) < r.pc {
+ return 0, io.EOF
+ }
+ d := uint64(off) - r.pc
+ if d >= uint64(len(r.code)) {
+ return 0, io.EOF
+ }
+ n = copy(data, r.code[d:])
+ if n < len(data) {
+ err = io.ErrUnexpectedEOF
+ }
+ return
+}
+
+func disasm_arm(code []byte, pc uint64, lookup lookupFunc) (string, int) {
+ inst, err := armasm.Decode(code, armasm.ModeARM)
+ var text string
+ size := inst.Len
+ if err != nil || size == 0 || inst.Op == 0 {
+ size = 4
+ text = "?"
+ } else {
+ text = armasm.Plan9Syntax(inst, pc, lookup, textReader{code, pc})
+ }
+ return text, size
+}
+
+var disasms = map[string]disasmFunc{
+ "386": disasm_386,
+ "amd64": disasm_amd64,
+ "arm": disasm_arm,
+}
+
+var byteOrders = map[string]binary.ByteOrder{
+ "386": binary.LittleEndian,
+ "amd64": binary.LittleEndian,
+ "arm": binary.LittleEndian,
+ "power64": binary.BigEndian,
+ "power64le": binary.LittleEndian,
+}
diff --git a/src/cmd/internal/objfile/objfile.go b/src/cmd/internal/objfile/objfile.go
index 3d4a5d27c..9227ef387 100644
--- a/src/cmd/internal/objfile/objfile.go
+++ b/src/cmd/internal/objfile/objfile.go
@@ -9,6 +9,7 @@ import (
"debug/gosym"
"fmt"
"os"
+ "sort"
)
type rawFile interface {
@@ -62,9 +63,20 @@ func (f *File) Close() error {
}
func (f *File) Symbols() ([]Sym, error) {
- return f.raw.symbols()
+ syms, err := f.raw.symbols()
+ if err != nil {
+ return nil, err
+ }
+ sort.Sort(byAddr(syms))
+ return syms, nil
}
+type byAddr []Sym
+
+func (x byAddr) Less(i, j int) bool { return x[i].Addr < x[j].Addr }
+func (x byAddr) Len() int { return len(x) }
+func (x byAddr) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
+
func (f *File) PCLineTable() (*gosym.Table, error) {
textStart, symtab, pclntab, err := f.raw.pcln()
if err != nil {
diff --git a/src/cmd/objdump/main.go b/src/cmd/objdump/main.go
index 0f125c98b..708a85370 100644
--- a/src/cmd/objdump/main.go
+++ b/src/cmd/objdump/main.go
@@ -32,24 +32,15 @@
package main
import (
- "bufio"
- "debug/gosym"
- "encoding/binary"
"flag"
"fmt"
- "io"
"log"
"os"
"regexp"
- "sort"
"strconv"
"strings"
- "text/tabwriter"
"cmd/internal/objfile"
-
- "cmd/internal/rsc.io/arm/armasm"
- "cmd/internal/rsc.io/x86/x86asm"
)
var symregexp = flag.String("s", "", "only dump symbols matching this regexp")
@@ -87,227 +78,30 @@ func main() {
log.Fatal(err)
}
- syms, err := f.Symbols()
+ dis, err := f.Disasm()
if err != nil {
- log.Fatalf("reading %s: %v", flag.Arg(0), err)
+ log.Fatal("disassemble %s: %v", flag.Arg(0), err)
}
- tab, err := f.PCLineTable()
- if err != nil {
- log.Fatalf("reading %s: %v", flag.Arg(0), err)
- }
-
- textStart, textBytes, err := f.Text()
- if err != nil {
- log.Fatalf("reading %s: %v", flag.Arg(0), err)
- }
-
- goarch := f.GOARCH()
-
- disasm := disasms[goarch]
- if disasm == nil {
- log.Fatalf("reading %s: unknown architecture", flag.Arg(0))
- }
-
- // Filter out section symbols, overwriting syms in place.
- keep := syms[:0]
- for _, sym := range syms {
- switch sym.Name {
- case "runtime.text", "text", "_text", "runtime.etext", "etext", "_etext":
- // drop
- default:
- keep = append(keep, sym)
- }
- }
- syms = keep
-
- sort.Sort(ByAddr(syms))
- lookup := func(addr uint64) (string, uint64) {
- i := sort.Search(len(syms), func(i int) bool { return addr < syms[i].Addr })
- if i > 0 {
- s := syms[i-1]
- if s.Addr != 0 && s.Addr <= addr && addr < s.Addr+uint64(s.Size) {
- return s.Name, s.Addr
- }
- }
- return "", 0
- }
-
- if flag.NArg() == 1 {
- // disassembly of entire object - our format
- dump(tab, lookup, disasm, goarch, syms, textBytes, textStart)
+ switch flag.NArg() {
+ default:
+ usage()
+ case 1:
+ // disassembly of entire object
+ dis.Print(os.Stdout, symRE, 0, ^uint64(0))
os.Exit(0)
- }
-
- // disassembly of specific piece of object - gnu objdump format for pprof
- gnuDump(tab, lookup, disasm, textBytes, textStart)
- os.Exit(0)
-}
-
-// base returns the final element in the path.
-// It works on both Windows and Unix paths.
-func base(path string) string {
- path = path[strings.LastIndex(path, "/")+1:]
- path = path[strings.LastIndex(path, `\`)+1:]
- return path
-}
-
-func dump(tab *gosym.Table, lookup lookupFunc, disasm disasmFunc, goarch string, syms []objfile.Sym, textData []byte, textStart uint64) {
- stdout := bufio.NewWriter(os.Stdout)
- defer stdout.Flush()
-
- printed := false
- for _, sym := range syms {
- if (sym.Code != 'T' && sym.Code != 't') || sym.Size == 0 || sym.Addr < textStart || symRE != nil && !symRE.MatchString(sym.Name) {
- continue
- }
- if sym.Addr >= textStart+uint64(len(textData)) || sym.Addr+uint64(sym.Size) > textStart+uint64(len(textData)) {
- break
- }
- if printed {
- fmt.Fprintf(stdout, "\n")
- } else {
- printed = true
- }
- file, _, _ := tab.PCToLine(sym.Addr)
- fmt.Fprintf(stdout, "TEXT %s(SB) %s\n", sym.Name, file)
- tw := tabwriter.NewWriter(stdout, 1, 8, 1, '\t', 0)
- start := sym.Addr
- end := sym.Addr + uint64(sym.Size)
- for pc := start; pc < end; {
- i := pc - textStart
- text, size := disasm(textData[i:end-textStart], pc, lookup)
- file, line, _ := tab.PCToLine(pc)
-
- // ARM is word-based, so show actual word hex, not byte hex.
- // Since ARM is little endian, they're different.
- if goarch == "arm" && size == 4 {
- fmt.Fprintf(tw, "\t%s:%d\t%#x\t%08x\t%s\n", base(file), line, pc, binary.LittleEndian.Uint32(textData[i:i+uint64(size)]), text)
- } else {
- fmt.Fprintf(tw, "\t%s:%d\t%#x\t%x\t%s\n", base(file), line, pc, textData[i:i+uint64(size)], text)
- }
- pc += uint64(size)
- }
- tw.Flush()
- }
-}
-
-func disasm_386(code []byte, pc uint64, lookup lookupFunc) (string, int) {
- return disasm_x86(code, pc, lookup, 32)
-}
-
-func disasm_amd64(code []byte, pc uint64, lookup lookupFunc) (string, int) {
- return disasm_x86(code, pc, lookup, 64)
-}
-
-func disasm_x86(code []byte, pc uint64, lookup lookupFunc, arch int) (string, int) {
- inst, err := x86asm.Decode(code, 64)
- var text string
- size := inst.Len
- if err != nil || size == 0 || inst.Op == 0 {
- size = 1
- text = "?"
- } else {
- text = x86asm.Plan9Syntax(inst, pc, lookup)
- }
- return text, size
-}
-
-type textReader struct {
- code []byte
- pc uint64
-}
-
-func (r textReader) ReadAt(data []byte, off int64) (n int, err error) {
- if off < 0 || uint64(off) < r.pc {
- return 0, io.EOF
- }
- d := uint64(off) - r.pc
- if d >= uint64(len(r.code)) {
- return 0, io.EOF
- }
- n = copy(data, r.code[d:])
- if n < len(data) {
- err = io.ErrUnexpectedEOF
- }
- return
-}
-
-func disasm_arm(code []byte, pc uint64, lookup lookupFunc) (string, int) {
- inst, err := armasm.Decode(code, armasm.ModeARM)
- var text string
- size := inst.Len
- if err != nil || size == 0 || inst.Op == 0 {
- size = 4
- text = "?"
- } else {
- text = armasm.Plan9Syntax(inst, pc, lookup, textReader{code, pc})
- }
- return text, size
-}
-
-var disasms = map[string]disasmFunc{
- "386": disasm_386,
- "amd64": disasm_amd64,
- "arm": disasm_arm,
-}
-
-func gnuDump(tab *gosym.Table, lookup lookupFunc, disasm disasmFunc, textData []byte, textStart uint64) {
- start, err := strconv.ParseUint(strings.TrimPrefix(flag.Arg(1), "0x"), 16, 64)
- if err != nil {
- log.Fatalf("invalid start PC: %v", err)
- }
- end, err := strconv.ParseUint(strings.TrimPrefix(flag.Arg(2), "0x"), 16, 64)
- if err != nil {
- log.Fatalf("invalid end PC: %v", err)
- }
- if start < textStart {
- start = textStart
- }
- if end < start {
- end = start
- }
- if end > textStart+uint64(len(textData)) {
- end = textStart + uint64(len(textData))
- }
-
- stdout := bufio.NewWriter(os.Stdout)
- defer stdout.Flush()
-
- // For now, find spans of same PC/line/fn and
- // emit them as having dummy instructions.
- var (
- spanPC uint64
- spanFile string
- spanLine int
- spanFn *gosym.Func
- )
- flush := func(endPC uint64) {
- if spanPC == 0 {
- return
- }
- fmt.Fprintf(stdout, "%s:%d\n", spanFile, spanLine)
- for pc := spanPC; pc < endPC; {
- text, size := disasm(textData[pc-textStart:], pc, lookup)
- fmt.Fprintf(stdout, " %x: %s\n", pc, text)
- pc += uint64(size)
+ case 3:
+ // disassembly of PC range
+ start, err := strconv.ParseUint(strings.TrimPrefix(flag.Arg(1), "0x"), 16, 64)
+ if err != nil {
+ log.Fatalf("invalid start PC: %v", err)
}
- spanPC = 0
- }
-
- for pc := start; pc < end; pc++ {
- file, line, fn := tab.PCToLine(pc)
- if file != spanFile || line != spanLine || fn != spanFn {
- flush(pc)
- spanPC, spanFile, spanLine, spanFn = pc, file, line, fn
+ end, err := strconv.ParseUint(strings.TrimPrefix(flag.Arg(2), "0x"), 16, 64)
+ if err != nil {
+ log.Fatalf("invalid end PC: %v", err)
}
+ dis.Print(os.Stdout, symRE, start, end)
+ os.Exit(0)
}
- flush(end)
}
-
-type ByAddr []objfile.Sym
-
-func (x ByAddr) Less(i, j int) bool { return x[i].Addr < x[j].Addr }
-func (x ByAddr) Len() int { return len(x) }
-func (x ByAddr) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
diff --git a/src/cmd/objdump/objdump_test.go b/src/cmd/objdump/objdump_test.go
index 5047f9aa8..bd09ae9f9 100644
--- a/src/cmd/objdump/objdump_test.go
+++ b/src/cmd/objdump/objdump_test.go
@@ -5,117 +5,15 @@
package main
import (
- "bufio"
- "bytes"
- "fmt"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"runtime"
- "strconv"
"strings"
"testing"
)
-func loadSyms(t *testing.T) map[string]string {
- switch runtime.GOOS {
- case "android", "nacl":
- t.Skipf("skipping on %s", runtime.GOOS)
- }
-
- cmd := exec.Command("go", "tool", "nm", os.Args[0])
- out, err := cmd.CombinedOutput()
- if err != nil {
- t.Fatalf("go tool nm %v: %v\n%s", os.Args[0], err, string(out))
- }
- syms := make(map[string]string)
- scanner := bufio.NewScanner(bytes.NewReader(out))
- for scanner.Scan() {
- f := strings.Fields(scanner.Text())
- if len(f) < 3 {
- continue
- }
- syms[f[2]] = f[0]
- }
- if err := scanner.Err(); err != nil {
- t.Fatalf("error reading symbols: %v", err)
- }
- return syms
-}
-
-func runObjDump(t *testing.T, exe, startaddr, endaddr string) (path, lineno string) {
- switch runtime.GOOS {
- case "android", "nacl":
- t.Skipf("skipping on %s", runtime.GOOS)
- }
- switch runtime.GOARCH {
- case "power64", "power64le":
- t.Skipf("skipping on %s, issue 9039", runtime.GOARCH)
- }
-
- cmd := exec.Command(exe, os.Args[0], startaddr, endaddr)
- out, err := cmd.CombinedOutput()
- if err != nil {
- t.Fatalf("go tool objdump %v: %v\n%s", os.Args[0], err, string(out))
- }
- f := strings.Split(string(out), "\n")
- if len(f) < 1 {
- t.Fatal("objdump output must have at least one line")
- }
- pathAndLineNo := f[0]
- f = strings.Split(pathAndLineNo, ":")
- if runtime.GOOS == "windows" {
- switch len(f) {
- case 2:
- return f[0], f[1]
- case 3:
- return f[0] + ":" + f[1], f[2]
- default:
- t.Fatalf("no line number found in %q", pathAndLineNo)
- }
- }
- if len(f) != 2 {
- t.Fatalf("no line number found in %q", pathAndLineNo)
- }
- return f[0], f[1]
-}
-
-func testObjDump(t *testing.T, exe, startaddr, endaddr string, line int) {
- srcPath, srcLineNo := runObjDump(t, exe, startaddr, endaddr)
- fi1, err := os.Stat("objdump_test.go")
- if err != nil {
- t.Fatalf("Stat failed: %v", err)
- }
- fi2, err := os.Stat(srcPath)
- if err != nil {
- t.Fatalf("Stat failed: %v", err)
- }
- if !os.SameFile(fi1, fi2) {
- t.Fatalf("objdump_test.go and %s are not same file", srcPath)
- }
- if srcLineNo != fmt.Sprint(line) {
- t.Fatalf("line number = %v; want %d", srcLineNo, line)
- }
-}
-
-func TestObjDump(t *testing.T) {
- _, _, line, _ := runtime.Caller(0)
- syms := loadSyms(t)
-
- tmp, exe := buildObjdump(t)
- defer os.RemoveAll(tmp)
-
- startaddr := syms["cmd/objdump.TestObjDump"]
- addr, err := strconv.ParseUint(startaddr, 16, 64)
- if err != nil {
- t.Fatalf("invalid start address %v: %v", startaddr, err)
- }
- endaddr := fmt.Sprintf("%x", addr+10)
- testObjDump(t, exe, startaddr, endaddr, line-1)
- testObjDump(t, exe, "0x"+startaddr, "0x"+endaddr, line-1)
-}
-
func buildObjdump(t *testing.T) (tmp, exe string) {
switch runtime.GOOS {
case "android", "nacl":
diff --git a/src/cmd/pprof/README b/src/cmd/pprof/README
new file mode 100644
index 000000000..a728ef235
--- /dev/null
+++ b/src/cmd/pprof/README
@@ -0,0 +1,8 @@
+The pprof in this directory is adapted from the pprof used inside Google
+for C++, Java, and Go programs. Because it was developed for that broader
+context, it is overgeneralized when used here for the specific use case
+of profiling standard Go programs. However, we've left the abstractions
+intact in order to share updates between this copy and Google's internal one.
+
+Please do not take the level of abstraction in this program as an example
+to follow in your own.
diff --git a/src/cmd/pprof/doc.go b/src/cmd/pprof/doc.go
new file mode 100644
index 000000000..c6ff11d10
--- /dev/null
+++ b/src/cmd/pprof/doc.go
@@ -0,0 +1,12 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Pprof interprets and displays profiles of Go programs.
+//
+// Usage:
+//
+// go tool pprof binary profile
+//
+// For more information, see http://blog.golang.org/profiling-go-programs.
+package main
diff --git a/src/cmd/pprof/pprof.go b/src/cmd/pprof/pprof.go
index 89a5bb7d2..44f4f6cb7 100644
--- a/src/cmd/pprof/pprof.go
+++ b/src/cmd/pprof/pprof.go
@@ -11,6 +11,7 @@ import (
"os"
"regexp"
"strings"
+ "sync"
"cmd/internal/objfile"
"cmd/pprof/internal/commands"
@@ -100,7 +101,10 @@ func (flags) ExtraUsage() string {
// objTool implements plugin.ObjTool using Go libraries
// (instead of invoking GNU binutils).
-type objTool struct{}
+type objTool struct {
+ mu sync.Mutex
+ disasmCache map[string]*objfile.Disasm
+}
func (*objTool) Open(name string, start uint64) (plugin.ObjFile, error) {
of, err := objfile.Open(name)
@@ -119,8 +123,39 @@ func (*objTool) Demangle(names []string) (map[string]string, error) {
return make(map[string]string), nil
}
-func (*objTool) Disasm(file string, start, end uint64) ([]plugin.Inst, error) {
- return nil, fmt.Errorf("disassembly not supported")
+func (t *objTool) Disasm(file string, start, end uint64) ([]plugin.Inst, error) {
+ d, err := t.cachedDisasm(file)
+ if err != nil {
+ return nil, err
+ }
+ var asm []plugin.Inst
+ d.Decode(start, end, func(pc, size uint64, file string, line int, text string) {
+ asm = append(asm, plugin.Inst{Addr: pc, File: file, Line: line, Text: text})
+ })
+ return asm, nil
+}
+
+func (t *objTool) cachedDisasm(file string) (*objfile.Disasm, error) {
+ t.mu.Lock()
+ defer t.mu.Unlock()
+ if t.disasmCache == nil {
+ t.disasmCache = make(map[string]*objfile.Disasm)
+ }
+ d := t.disasmCache[file]
+ if d != nil {
+ return d, nil
+ }
+ f, err := objfile.Open(file)
+ if err != nil {
+ return nil, err
+ }
+ d, err = f.Disasm()
+ f.Close()
+ if err != nil {
+ return nil, err
+ }
+ t.disasmCache[file] = d
+ return d, nil
}
func (*objTool) SetConfig(config string) {