2009-03-13 16:03:07 -06:00
|
|
|
// 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.
|
|
|
|
|
2009-07-07 11:07:15 -06:00
|
|
|
#include "gc.h"
|
2009-03-13 16:03:07 -06:00
|
|
|
|
|
|
|
void
|
2009-07-07 11:07:15 -06:00
|
|
|
swit1(C1 *q, int nc, int32 def, Node *n)
|
2011-12-14 15:30:40 -07:00
|
|
|
{
|
|
|
|
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)
|
2009-03-13 16:03:07 -06:00
|
|
|
{
|
|
|
|
C1 *r;
|
|
|
|
int i;
|
2009-03-25 17:31:38 -06:00
|
|
|
int32 v;
|
2009-03-13 16:03:07 -06:00
|
|
|
Prog *sp;
|
|
|
|
|
|
|
|
if(nc >= 3) {
|
|
|
|
i = (q+nc-1)->val - (q+0)->val;
|
|
|
|
if(i > 0 && i < nc*2)
|
|
|
|
goto direct;
|
|
|
|
}
|
|
|
|
if(nc < 5) {
|
|
|
|
for(i=0; i<nc; i++) {
|
|
|
|
if(debug['W'])
|
2010-10-13 14:20:22 -06:00
|
|
|
print("case = %.8ux\n", q->val);
|
2009-03-13 16:03:07 -06:00
|
|
|
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'])
|
2010-10-13 14:20:22 -06:00
|
|
|
print("case > %.8ux\n", r->val);
|
2009-03-13 16:03:07 -06:00
|
|
|
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);
|
2011-12-14 15:30:40 -07:00
|
|
|
swit2(q, i, def, n);
|
2009-03-13 16:03:07 -06:00
|
|
|
|
|
|
|
if(debug['W'])
|
2010-10-13 14:20:22 -06:00
|
|
|
print("case < %.8ux\n", r->val);
|
2009-03-13 16:03:07 -06:00
|
|
|
patch(sp, pc);
|
2011-12-14 15:30:40 -07:00
|
|
|
swit2(r+1, nc-i-1, def, n);
|
2009-03-13 16:03:07 -06:00
|
|
|
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'])
|
2010-10-13 14:20:22 -06:00
|
|
|
print("case = %.8ux\n", q->val);
|
2009-03-13 16:03:07 -06:00
|
|
|
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;
|
2009-03-25 17:31:38 -06:00
|
|
|
int32 v;
|
2009-03-13 16:03:07 -06:00
|
|
|
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);
|
2009-07-07 11:07:15 -06:00
|
|
|
cgen(l, n1);
|
2009-03-13 16:03:07 -06:00
|
|
|
}
|
|
|
|
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)
|
|
|
|
{
|
2009-03-25 17:31:38 -06:00
|
|
|
int32 v;
|
2009-03-13 16:03:07 -06:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2009-03-25 17:31:38 -06:00
|
|
|
int32
|
|
|
|
outstring(char *s, int32 n)
|
2009-03-13 16:03:07 -06:00
|
|
|
{
|
2009-03-25 17:31:38 -06:00
|
|
|
int32 r;
|
2009-03-13 16:03:07 -06:00
|
|
|
|
|
|
|
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.sval, string, NSNAME);
|
|
|
|
mnstring = 0;
|
|
|
|
}
|
|
|
|
n--;
|
|
|
|
}
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
mulcon(Node *n, Node *nn)
|
|
|
|
{
|
|
|
|
Node *l, *r, nod1, nod2;
|
|
|
|
Multab *m;
|
2009-03-25 17:31:38 -06:00
|
|
|
int32 v, vs;
|
2009-03-13 16:03:07 -06:00
|
|
|
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'])
|
2010-10-13 14:20:22 -06:00
|
|
|
print("%L multiply: %d\n", n->lineno, v);
|
2009-03-13 16:03:07 -06:00
|
|
|
|
|
|
|
memmove(code, m->code, sizeof(m->code));
|
|
|
|
code[sizeof(m->code)] = 0;
|
|
|
|
|
|
|
|
p = code;
|
|
|
|
if(p[1] == 'i')
|
|
|
|
p += 2;
|
|
|
|
regalloc(&nod1, n, nn);
|
2009-07-07 11:07:15 -06:00
|
|
|
cgen(l, &nod1);
|
2009-03-13 16:03:07 -06:00
|
|
|
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);
|
2009-06-16 12:25:58 -06:00
|
|
|
} else
|
2009-03-13 16:03:07 -06:00
|
|
|
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
|
2009-03-25 17:31:38 -06:00
|
|
|
sextern(Sym *s, Node *a, int32 o, int32 w)
|
2009-03-13 16:03:07 -06:00
|
|
|
{
|
2009-03-25 17:31:38 -06:00
|
|
|
int32 e, lw;
|
2009-03-13 16:03:07 -06:00
|
|
|
|
|
|
|
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.sval, a->cstring+e, lw);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-03-25 17:31:38 -06:00
|
|
|
gextern(Sym *s, Node *a, int32 o, int32 w)
|
2009-03-13 16:03:07 -06:00
|
|
|
{
|
|
|
|
|
|
|
|
if(a->op == OCONST && typev[a->type->etype]) {
|
2009-10-12 14:35:28 -06:00
|
|
|
if(isbigendian)
|
2009-03-13 16:03:07 -06:00
|
|
|
gpseudo(ADATA, s, nod32const(a->vconst>>32));
|
|
|
|
else
|
|
|
|
gpseudo(ADATA, s, nod32const(a->vconst));
|
|
|
|
p->from.offset += o;
|
|
|
|
p->reg = 4;
|
2009-10-12 14:35:28 -06:00
|
|
|
if(isbigendian)
|
2009-03-13 16:03:07 -06:00
|
|
|
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 zname(Biobuf*, Sym*, int);
|
|
|
|
char* zaddr(char*, Adr*, int);
|
|
|
|
void zwrite(Biobuf*, Prog*, int, int);
|
|
|
|
void outhist(Biobuf*);
|
|
|
|
|
|
|
|
void
|
|
|
|
zwrite(Biobuf *b, Prog *p, int sf, int st)
|
|
|
|
{
|
|
|
|
char bf[100], *bp;
|
|
|
|
|
|
|
|
bf[0] = p->as;
|
|
|
|
bf[1] = p->scond;
|
|
|
|
bf[2] = p->reg;
|
|
|
|
bf[3] = p->lineno;
|
|
|
|
bf[4] = p->lineno>>8;
|
|
|
|
bf[5] = p->lineno>>16;
|
|
|
|
bf[6] = p->lineno>>24;
|
|
|
|
bp = zaddr(bf+7, &p->from, sf);
|
|
|
|
bp = zaddr(bp, &p->to, st);
|
|
|
|
Bwrite(b, bf, bp-bf);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
outcode(void)
|
|
|
|
{
|
|
|
|
struct { Sym *sym; short type; } h[NSYM];
|
|
|
|
Prog *p;
|
|
|
|
Sym *s;
|
|
|
|
int sf, st, t, sym;
|
|
|
|
|
|
|
|
if(debug['S']) {
|
|
|
|
for(p = firstp; p != P; p = p->link)
|
|
|
|
if(p->as != ADATA && p->as != AGLOBL)
|
|
|
|
pc--;
|
|
|
|
for(p = firstp; p != P; p = p->link) {
|
|
|
|
print("%P\n", p);
|
|
|
|
if(p->as != ADATA && p->as != AGLOBL)
|
|
|
|
pc++;
|
|
|
|
}
|
|
|
|
}
|
2009-06-09 21:51:53 -06:00
|
|
|
|
2011-02-03 11:51:43 -07:00
|
|
|
Bprint(&outbuf, "go object %s %s %s\n", getgoos(), thestring, getgoversion());
|
2010-03-23 07:46:30 -06:00
|
|
|
if(ndynimp > 0 || ndynexp > 0) {
|
2010-03-22 20:58:55 -06:00
|
|
|
int i;
|
|
|
|
|
|
|
|
Bprint(&outbuf, "\n");
|
|
|
|
Bprint(&outbuf, "$$ // exports\n\n");
|
|
|
|
Bprint(&outbuf, "$$ // local types\n\n");
|
2011-07-15 09:58:28 -06:00
|
|
|
Bprint(&outbuf, "$$ // dynimport\n");
|
2010-03-22 20:58:55 -06:00
|
|
|
for(i=0; i<ndynimp; i++)
|
|
|
|
Bprint(&outbuf, "dynimport %s %s %s\n", dynimp[i].local, dynimp[i].remote, dynimp[i].path);
|
2011-07-15 09:58:28 -06:00
|
|
|
Bprint(&outbuf, "\n$$ // dynexport\n");
|
2010-03-23 07:46:30 -06:00
|
|
|
for(i=0; i<ndynexp; i++)
|
|
|
|
Bprint(&outbuf, "dynexport %s %s\n", dynexp[i].local, dynexp[i].remote);
|
2012-05-04 11:54:16 -06:00
|
|
|
Bprint(&outbuf, "\n$$ // dynlinker\n");
|
|
|
|
if(dynlinker != nil) {
|
|
|
|
Bprint(&outbuf, "dynlinker %s\n", dynlinker);
|
|
|
|
}
|
2010-03-23 07:46:30 -06:00
|
|
|
Bprint(&outbuf, "\n$$\n\n");
|
2010-03-22 20:58:55 -06:00
|
|
|
}
|
2009-06-09 21:51:53 -06:00
|
|
|
Bprint(&outbuf, "!\n");
|
|
|
|
|
2009-03-13 16:03:07 -06:00
|
|
|
outhist(&outbuf);
|
|
|
|
for(sym=0; sym<NSYM; sym++) {
|
|
|
|
h[sym].sym = S;
|
|
|
|
h[sym].type = 0;
|
|
|
|
}
|
|
|
|
sym = 1;
|
|
|
|
for(p = firstp; p != P; p = p->link) {
|
|
|
|
jackpot:
|
|
|
|
sf = 0;
|
|
|
|
s = p->from.sym;
|
|
|
|
while(s != S) {
|
|
|
|
sf = s->sym;
|
|
|
|
if(sf < 0 || sf >= NSYM)
|
|
|
|
sf = 0;
|
|
|
|
t = p->from.name;
|
|
|
|
if(h[sf].type == t)
|
|
|
|
if(h[sf].sym == s)
|
|
|
|
break;
|
|
|
|
s->sym = sym;
|
|
|
|
zname(&outbuf, s, t);
|
|
|
|
h[sym].sym = s;
|
|
|
|
h[sym].type = t;
|
|
|
|
sf = sym;
|
|
|
|
sym++;
|
|
|
|
if(sym >= NSYM)
|
|
|
|
sym = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
st = 0;
|
|
|
|
s = p->to.sym;
|
|
|
|
while(s != S) {
|
|
|
|
st = s->sym;
|
|
|
|
if(st < 0 || st >= NSYM)
|
|
|
|
st = 0;
|
|
|
|
t = p->to.name;
|
|
|
|
if(h[st].type == t)
|
|
|
|
if(h[st].sym == s)
|
|
|
|
break;
|
|
|
|
s->sym = sym;
|
|
|
|
zname(&outbuf, s, t);
|
|
|
|
h[sym].sym = s;
|
|
|
|
h[sym].type = t;
|
|
|
|
st = sym;
|
|
|
|
sym++;
|
|
|
|
if(sym >= NSYM)
|
|
|
|
sym = 1;
|
|
|
|
if(st == sf)
|
|
|
|
goto jackpot;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
zwrite(&outbuf, p, sf, st);
|
|
|
|
}
|
|
|
|
firstp = P;
|
|
|
|
lastp = P;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
outhist(Biobuf *b)
|
|
|
|
{
|
|
|
|
Hist *h;
|
|
|
|
char *p, *q, *op, c;
|
|
|
|
Prog pg;
|
|
|
|
int n;
|
2012-04-03 10:04:36 -06:00
|
|
|
char *tofree;
|
|
|
|
static int first = 1;
|
|
|
|
static char *goroot, *goroot_final;
|
|
|
|
|
|
|
|
if(first) {
|
|
|
|
// Decide whether we need to rewrite paths from $GOROOT to $GOROOT_FINAL.
|
|
|
|
first = 0;
|
|
|
|
goroot = getenv("GOROOT");
|
|
|
|
goroot_final = getenv("GOROOT_FINAL");
|
|
|
|
if(goroot == nil)
|
|
|
|
goroot = "";
|
|
|
|
if(goroot_final == nil)
|
|
|
|
goroot_final = goroot;
|
|
|
|
if(strcmp(goroot, goroot_final) == 0) {
|
|
|
|
goroot = nil;
|
|
|
|
goroot_final = nil;
|
|
|
|
}
|
|
|
|
}
|
2009-03-13 16:03:07 -06:00
|
|
|
|
2012-04-03 10:04:36 -06:00
|
|
|
tofree = nil;
|
2009-03-13 16:03:07 -06:00
|
|
|
pg = zprog;
|
|
|
|
pg.as = AHISTORY;
|
|
|
|
c = pathchar();
|
|
|
|
for(h = hist; h != H; h = h->link) {
|
|
|
|
p = h->name;
|
2012-04-03 10:04:36 -06:00
|
|
|
if(p != nil && goroot != nil) {
|
|
|
|
n = strlen(goroot);
|
|
|
|
if(strncmp(p, goroot, strlen(goroot)) == 0 && p[n] == '/') {
|
|
|
|
tofree = smprint("%s%s", goroot_final, p+n);
|
|
|
|
p = tofree;
|
|
|
|
}
|
|
|
|
}
|
2009-03-13 16:03:07 -06:00
|
|
|
op = 0;
|
|
|
|
if(systemtype(Windows) && p && p[1] == ':'){
|
2011-09-07 13:49:56 -06:00
|
|
|
c = p[2];
|
|
|
|
} else if(p && p[0] != c && h->offset == 0 && pathname){
|
2009-03-13 16:03:07 -06:00
|
|
|
if(systemtype(Windows) && pathname[1] == ':') {
|
|
|
|
op = p;
|
2011-09-07 13:49:56 -06:00
|
|
|
p = pathname;
|
|
|
|
c = p[2];
|
2009-03-13 16:03:07 -06:00
|
|
|
} else if(pathname[0] == c){
|
|
|
|
op = p;
|
|
|
|
p = pathname;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
while(p) {
|
|
|
|
q = utfrune(p, c);
|
|
|
|
if(q) {
|
|
|
|
n = q-p;
|
|
|
|
if(n == 0){
|
|
|
|
n = 1; /* leading "/" */
|
|
|
|
*p = '/'; /* don't emit "\" on windows */
|
|
|
|
}
|
|
|
|
q++;
|
|
|
|
} else {
|
|
|
|
n = strlen(p);
|
|
|
|
q = 0;
|
|
|
|
}
|
|
|
|
if(n) {
|
|
|
|
Bputc(b, ANAME);
|
|
|
|
Bputc(b, D_FILE);
|
|
|
|
Bputc(b, 1);
|
|
|
|
Bputc(b, '<');
|
|
|
|
Bwrite(b, p, n);
|
|
|
|
Bputc(b, 0);
|
|
|
|
}
|
|
|
|
p = q;
|
|
|
|
if(p == 0 && op) {
|
|
|
|
p = op;
|
|
|
|
op = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pg.lineno = h->line;
|
|
|
|
pg.to.type = zprog.to.type;
|
|
|
|
pg.to.offset = h->offset;
|
|
|
|
if(h->offset)
|
|
|
|
pg.to.type = D_CONST;
|
|
|
|
|
|
|
|
zwrite(b, &pg, 0, 0);
|
2012-04-03 10:04:36 -06:00
|
|
|
|
|
|
|
if(tofree) {
|
|
|
|
free(tofree);
|
|
|
|
tofree = nil;
|
|
|
|
}
|
2009-03-13 16:03:07 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
zname(Biobuf *b, Sym *s, int t)
|
|
|
|
{
|
|
|
|
char *n, bf[7];
|
2009-03-25 17:31:38 -06:00
|
|
|
uint32 sig;
|
2009-03-13 16:03:07 -06:00
|
|
|
|
|
|
|
n = s->name;
|
|
|
|
if(debug['T'] && t == D_EXTERN && s->sig != SIGDONE && s->type != types[TENUM] && s != symrathole){
|
|
|
|
sig = sign(s);
|
|
|
|
bf[0] = ASIGNAME;
|
|
|
|
bf[1] = sig;
|
|
|
|
bf[2] = sig>>8;
|
|
|
|
bf[3] = sig>>16;
|
|
|
|
bf[4] = sig>>24;
|
|
|
|
bf[5] = t;
|
|
|
|
bf[6] = s->sym;
|
|
|
|
Bwrite(b, bf, 7);
|
|
|
|
s->sig = SIGDONE;
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
bf[0] = ANAME;
|
|
|
|
bf[1] = t; /* type */
|
|
|
|
bf[2] = s->sym; /* sym */
|
|
|
|
Bwrite(b, bf, 3);
|
|
|
|
}
|
|
|
|
Bwrite(b, n, strlen(n)+1);
|
|
|
|
}
|
|
|
|
|
|
|
|
char*
|
|
|
|
zaddr(char *bp, Adr *a, int s)
|
|
|
|
{
|
2009-03-25 17:31:38 -06:00
|
|
|
int32 l;
|
2009-03-13 16:03:07 -06:00
|
|
|
Ieee e;
|
|
|
|
|
|
|
|
bp[0] = a->type;
|
|
|
|
bp[1] = a->reg;
|
2012-02-21 20:08:42 -07:00
|
|
|
bp[2] = s;
|
|
|
|
bp[3] = a->name;
|
|
|
|
bp += 4;
|
2009-03-13 16:03:07 -06:00
|
|
|
switch(a->type) {
|
|
|
|
default:
|
|
|
|
diag(Z, "unknown type %d in zaddr", a->type);
|
|
|
|
|
|
|
|
case D_NONE:
|
|
|
|
case D_REG:
|
|
|
|
case D_FREG:
|
|
|
|
case D_PSR:
|
|
|
|
break;
|
|
|
|
|
2009-06-16 12:25:58 -06:00
|
|
|
case D_CONST2:
|
|
|
|
l = a->offset2;
|
|
|
|
bp[0] = l;
|
|
|
|
bp[1] = l>>8;
|
|
|
|
bp[2] = l>>16;
|
|
|
|
bp[3] = l>>24;
|
|
|
|
bp += 4; // fall through
|
2009-03-13 16:03:07 -06:00
|
|
|
case D_OREG:
|
|
|
|
case D_CONST:
|
|
|
|
case D_BRANCH:
|
|
|
|
case D_SHIFT:
|
|
|
|
l = a->offset;
|
|
|
|
bp[0] = l;
|
|
|
|
bp[1] = l>>8;
|
|
|
|
bp[2] = l>>16;
|
|
|
|
bp[3] = l>>24;
|
|
|
|
bp += 4;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case D_SCONST:
|
|
|
|
memmove(bp, a->sval, NSNAME);
|
|
|
|
bp += NSNAME;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case D_FCONST:
|
|
|
|
ieeedtod(&e, a->dval);
|
|
|
|
l = e.l;
|
|
|
|
bp[0] = l;
|
|
|
|
bp[1] = l>>8;
|
|
|
|
bp[2] = l>>16;
|
|
|
|
bp[3] = l>>24;
|
|
|
|
bp += 4;
|
|
|
|
l = e.h;
|
|
|
|
bp[0] = l;
|
|
|
|
bp[1] = l>>8;
|
|
|
|
bp[2] = l>>16;
|
|
|
|
bp[3] = l>>24;
|
|
|
|
bp += 4;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return bp;
|
|
|
|
}
|
|
|
|
|
2009-03-25 17:31:38 -06:00
|
|
|
int32
|
2010-12-13 14:22:19 -07:00
|
|
|
align(int32 i, Type *t, int op, int32 *maxalign)
|
2009-03-13 16:03:07 -06:00
|
|
|
{
|
2009-03-25 17:31:38 -06:00
|
|
|
int32 o;
|
2009-03-13 16:03:07 -06:00
|
|
|
Type *v;
|
|
|
|
int w;
|
|
|
|
|
|
|
|
o = i;
|
|
|
|
w = 1;
|
|
|
|
switch(op) {
|
|
|
|
default:
|
|
|
|
diag(Z, "unknown align opcode %d", op);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case Asu2: /* padding at end of a struct */
|
2010-12-13 14:22:19 -07:00
|
|
|
w = *maxalign;
|
|
|
|
if(w < 1)
|
|
|
|
w = 1;
|
2009-03-13 16:03:07 -06:00
|
|
|
if(packflg)
|
|
|
|
w = packflg;
|
|
|
|
break;
|
|
|
|
|
2010-03-26 10:56:57 -06:00
|
|
|
case Ael1: /* initial align of struct element */
|
2009-03-13 16:03:07 -06:00
|
|
|
for(v=t; v->etype==TARRAY; v=v->link)
|
|
|
|
;
|
2010-12-13 14:22:19 -07:00
|
|
|
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)
|
2009-03-13 16:03:07 -06:00
|
|
|
w = 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]) {
|
2010-12-13 14:22:19 -07:00
|
|
|
o = align(o, types[TIND], Aarg1, nil);
|
|
|
|
o = align(o, types[TIND], Aarg2, nil);
|
2009-03-13 16:03:07 -06:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2010-03-26 10:56:57 -06:00
|
|
|
case Aarg1: /* initial align of parameter */
|
2009-03-13 16:03:07 -06:00
|
|
|
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;
|
2011-04-18 16:50:31 -06:00
|
|
|
w = t->width;
|
|
|
|
if(w > SZ_LONG)
|
|
|
|
w = SZ_LONG;
|
2009-03-13 16:03:07 -06:00
|
|
|
break;
|
|
|
|
|
2010-03-26 10:56:57 -06:00
|
|
|
case Aaut3: /* total align of automatic */
|
2010-12-13 14:22:19 -07:00
|
|
|
o = align(o, t, Ael2, nil);
|
|
|
|
o = align(o, t, Ael1, nil);
|
2009-03-13 16:03:07 -06:00
|
|
|
w = SZ_LONG; /* because of a pun in cc/dcl.c:contig() */
|
|
|
|
break;
|
|
|
|
}
|
2009-03-25 17:31:38 -06:00
|
|
|
o = xround(o, w);
|
2010-12-13 14:22:19 -07:00
|
|
|
if(maxalign != nil && *maxalign < w)
|
|
|
|
*maxalign = w;
|
2009-03-13 16:03:07 -06:00
|
|
|
if(debug['A'])
|
2010-10-13 14:20:22 -06:00
|
|
|
print("align %s %d %T = %d\n", bnames[op], i, t, o);
|
2009-03-13 16:03:07 -06:00
|
|
|
return o;
|
|
|
|
}
|
|
|
|
|
2009-03-25 17:31:38 -06:00
|
|
|
int32
|
|
|
|
maxround(int32 max, int32 v)
|
2009-03-13 16:03:07 -06:00
|
|
|
{
|
2009-03-25 17:31:38 -06:00
|
|
|
v = xround(v, SZ_LONG);
|
2009-03-13 16:03:07 -06:00
|
|
|
if(v > max)
|
|
|
|
return v;
|
|
|
|
return max;
|
|
|
|
}
|