summaryrefslogtreecommitdiff
path: root/src/cmd
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd')
-rw-r--r--src/cmd/6g/ggen.c2
-rw-r--r--src/cmd/6g/peep.c5
-rw-r--r--src/cmd/8g/ggen.c2
-rw-r--r--src/cmd/8g/peep.c5
-rw-r--r--src/cmd/cgo/gcc.go57
-rw-r--r--src/cmd/gc/array.c14
-rw-r--r--src/cmd/gc/bv.c36
-rw-r--r--src/cmd/gc/go.h2
-rw-r--r--src/cmd/gc/plive.c52
9 files changed, 125 insertions, 50 deletions
diff --git a/src/cmd/6g/ggen.c b/src/cmd/6g/ggen.c
index c385798f2..9665d831b 100644
--- a/src/cmd/6g/ggen.c
+++ b/src/cmd/6g/ggen.c
@@ -943,7 +943,7 @@ cgen_hmul(Node *nl, Node *nr, Node *res)
if(t->width == 1) {
// byte multiply behaves differently.
nodreg(&ax, t, D_AH);
- nodreg(&dx, t, D_DL);
+ nodreg(&dx, t, D_DX);
gmove(&ax, &dx);
}
nodreg(&dx, t, D_DX);
diff --git a/src/cmd/6g/peep.c b/src/cmd/6g/peep.c
index 0f2720443..24617836f 100644
--- a/src/cmd/6g/peep.c
+++ b/src/cmd/6g/peep.c
@@ -838,6 +838,11 @@ copyu(Prog *p, Adr *v, Adr *s)
static int
copyas(Adr *a, Adr *v)
{
+ if(D_AL <= a->type && a->type <= D_R15B)
+ fatal("use of byte register");
+ if(D_AL <= v->type && v->type <= D_R15B)
+ fatal("use of byte register");
+
if(a->type != v->type)
return 0;
if(regtyp(v))
diff --git a/src/cmd/8g/ggen.c b/src/cmd/8g/ggen.c
index 2285a04e6..5e3140480 100644
--- a/src/cmd/8g/ggen.c
+++ b/src/cmd/8g/ggen.c
@@ -991,7 +991,7 @@ cgen_hmul(Node *nl, Node *nr, Node *res)
if(t->width == 1) {
// byte multiply behaves differently.
nodreg(&ax, t, D_AH);
- nodreg(&dx, t, D_DL);
+ nodreg(&dx, t, D_DX);
gmove(&ax, &dx);
}
nodreg(&dx, t, D_DX);
diff --git a/src/cmd/8g/peep.c b/src/cmd/8g/peep.c
index a4e516dd3..e2f3a003d 100644
--- a/src/cmd/8g/peep.c
+++ b/src/cmd/8g/peep.c
@@ -634,6 +634,11 @@ copyu(Prog *p, Adr *v, Adr *s)
static int
copyas(Adr *a, Adr *v)
{
+ if(D_AL <= a->type && a->type <= D_BL)
+ fatal("use of byte register");
+ if(D_AL <= v->type && v->type <= D_BL)
+ fatal("use of byte register");
+
if(a->type != v->type)
return 0;
if(regtyp(v))
diff --git a/src/cmd/cgo/gcc.go b/src/cmd/cgo/gcc.go
index 7a802102d..f55cfbac4 100644
--- a/src/cmd/cgo/gcc.go
+++ b/src/cmd/cgo/gcc.go
@@ -552,8 +552,8 @@ func (p *Package) loadDWARF(f *File, names []*Name) {
n.Const = fmt.Sprintf("%#x", enumVal[i])
}
}
+ conv.FinishType(pos)
}
-
}
// mangleName does name mangling to translate names
@@ -926,6 +926,12 @@ type typeConv struct {
m map[dwarf.Type]*Type
typedef map[string]ast.Expr
+ // Map from types to incomplete pointers to those types.
+ ptrs map[dwarf.Type][]*Type
+
+ // Fields to be processed by godefsField after completing pointers.
+ todoFlds [][]*ast.Field
+
// Predeclared types.
bool ast.Expr
byte ast.Expr // denotes padding
@@ -950,6 +956,7 @@ func (c *typeConv) Init(ptrSize, intSize int64) {
c.ptrSize = ptrSize
c.intSize = intSize
c.m = make(map[dwarf.Type]*Type)
+ c.ptrs = make(map[dwarf.Type][]*Type)
c.bool = c.Ident("bool")
c.byte = c.Ident("byte")
c.int8 = c.Ident("int8")
@@ -1029,6 +1036,32 @@ func (tr *TypeRepr) Set(repr string, fargs ...interface{}) {
tr.FormatArgs = fargs
}
+// FinishType completes any outstanding type mapping work.
+// In particular, it resolves incomplete pointer types and also runs
+// godefsFields on any new struct types.
+func (c *typeConv) FinishType(pos token.Pos) {
+ // Completing one pointer type might produce more to complete.
+ // Keep looping until they're all done.
+ for len(c.ptrs) > 0 {
+ for dtype := range c.ptrs {
+ // Note Type might invalidate c.ptrs[dtype].
+ t := c.Type(dtype, pos)
+ for _, ptr := range c.ptrs[dtype] {
+ ptr.Go.(*ast.StarExpr).X = t.Go
+ ptr.C.Set("%s*", t.C)
+ }
+ delete(c.ptrs, dtype)
+ }
+ }
+
+ // Now that pointer types are completed, we can invoke godefsFields
+ // to rewrite struct definitions.
+ for _, fld := range c.todoFlds {
+ godefsFields(fld)
+ }
+ c.todoFlds = nil
+}
+
// Type returns a *Type with the same memory layout as
// dtype when used as the type of a variable or a struct field.
func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
@@ -1068,13 +1101,12 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
t.Go = c.Opaque(t.Size)
break
}
- gt := &ast.ArrayType{
- Len: c.intExpr(dt.Count),
- }
- t.Go = gt // publish before recursive call
sub := c.Type(dt.Type, pos)
t.Align = sub.Align
- gt.Elt = sub.Go
+ t.Go = &ast.ArrayType{
+ Len: c.intExpr(dt.Count),
+ Elt: sub.Go,
+ }
t.C.Set("__typeof__(%s[%d])", sub.C, dt.Count)
case *dwarf.BoolType:
@@ -1184,11 +1216,10 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
break
}
- gt := &ast.StarExpr{}
- t.Go = gt // publish before recursive call
- sub := c.Type(dt.Type, pos)
- gt.X = sub.Go
- t.C.Set("%s*", sub.C)
+ // Placeholder initialization; completed in FinishType.
+ t.Go = &ast.StarExpr{}
+ t.C.Set("<incomplete>*")
+ c.ptrs[dt.Type] = append(c.ptrs[dt.Type], t)
case *dwarf.QualType:
// Ignore qualifier.
@@ -1265,8 +1296,8 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
}
name := c.Ident("_Ctype_" + dt.Name)
goIdent[name.Name] = name
- t.Go = name // publish before recursive call
sub := c.Type(dt.Type, pos)
+ t.Go = name
t.Size = sub.Size
t.Align = sub.Align
oldType := typedef[name.Name]
@@ -1604,7 +1635,7 @@ func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.Struct
csyntax = buf.String()
if *godefs || *cdefs {
- godefsFields(fld)
+ c.todoFlds = append(c.todoFlds, fld)
}
expr = &ast.StructType{Fields: &ast.FieldList{List: fld}}
return
diff --git a/src/cmd/gc/array.c b/src/cmd/gc/array.c
index 5e53c1ff0..611fc9fbd 100644
--- a/src/cmd/gc/array.c
+++ b/src/cmd/gc/array.c
@@ -108,20 +108,6 @@ arrayadd(Array *array, void *element)
arrayset(array, array->length - 1, element);
}
-int32
-arrayindexof(Array *array, void *element)
-{
- void *p;
- int32 i;
-
- for(i = 0; i < array->length; i++) {
- p = arrayget(array, i);
- if(memcmp(p, &element, array->size) == 0)
- return i;
- }
- return -1;
-}
-
void
arraysort(Array *array, int (*cmp)(const void*, const void*))
{
diff --git a/src/cmd/gc/bv.c b/src/cmd/gc/bv.c
index 2efbbc565..0e8f8d473 100644
--- a/src/cmd/gc/bv.c
+++ b/src/cmd/gc/bv.c
@@ -9,6 +9,8 @@
enum {
WORDSIZE = sizeof(uint32),
WORDBITS = 32,
+ WORDMASK = WORDBITS - 1,
+ WORDSHIFT = 5,
};
static uintptr
@@ -94,13 +96,35 @@ bvconcat(Bvec *src1, Bvec *src2)
int
bvget(Bvec *bv, int32 i)
{
- uint32 mask, word;
-
if(i < 0 || i >= bv->n)
fatal("bvget: index %d is out of bounds with length %d\n", i, bv->n);
- mask = 1U << (i % WORDBITS);
- word = bv->b[i / WORDBITS] & mask;
- return word ? 1 : 0;
+ return (bv->b[i>>WORDSHIFT] >> (i&WORDMASK)) & 1;
+}
+
+// bvnext returns the smallest index >= i for which bvget(bv, i) == 1.
+// If there is no such index, bvnext returns -1.
+int
+bvnext(Bvec *bv, int32 i)
+{
+ uint32 w;
+
+ // Jump i ahead to next word with bits.
+ if((bv->b[i>>WORDSHIFT]>>(i&WORDMASK)) == 0) {
+ i &= ~WORDMASK;
+ i += WORDBITS;
+ while(i < bv->n && bv->b[i>>WORDSHIFT] == 0)
+ i += WORDBITS;
+ }
+ if(i >= bv->n)
+ return -1;
+
+ // Find 1 bit.
+ w = bv->b[i>>WORDSHIFT]>>(i&WORDMASK);
+ while((w&1) == 0) {
+ w>>=1;
+ i++;
+ }
+ return i;
}
int
@@ -109,7 +133,7 @@ bvisempty(Bvec *bv)
int32 i;
for(i = 0; i < bv->n; i += WORDBITS)
- if(bv->b[i / WORDBITS] != 0)
+ if(bv->b[i>>WORDSHIFT] != 0)
return 0;
return 1;
}
diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h
index 413e71069..ee879f67f 100644
--- a/src/cmd/gc/go.h
+++ b/src/cmd/gc/go.h
@@ -1017,7 +1017,6 @@ int32 arraylength(Array *array);
void* arrayget(Array *array, int32 index);
void arrayset(Array *array, int32 index, void *element);
void arrayadd(Array *array, void *element);
-int32 arrayindexof(Array* array, void *element);
void arraysort(Array* array, int (*cmp)(const void*, const void*));
/*
@@ -1043,6 +1042,7 @@ int bvcmp(Bvec *bv1, Bvec *bv2);
void bvcopy(Bvec *dst, Bvec *src);
Bvec* bvconcat(Bvec *src1, Bvec *src2);
int bvget(Bvec *bv, int32 i);
+int32 bvnext(Bvec *bv, int32 i);
int bvisempty(Bvec *bv);
void bvnot(Bvec *bv);
void bvor(Bvec *dst, Bvec *src1, Bvec *src2);
diff --git a/src/cmd/gc/plive.c b/src/cmd/gc/plive.c
index eb8901733..7a40ab559 100644
--- a/src/cmd/gc/plive.c
+++ b/src/cmd/gc/plive.c
@@ -283,13 +283,30 @@ getvariables(Node *fn)
// For arguments and results, the bitmap covers all variables,
// so we must include all the variables, even the ones without
// pointers.
+ //
+ // The Node.opt field is available for use by optimization passes.
+ // We use it to hold the index of the node in the variables array, plus 1
+ // (so that 0 means the Node is not in the variables array).
+ // Each pass should clear opt when done, but you never know,
+ // so clear them all ourselves too.
+ // The Node.curfn field is supposed to be set to the current function
+ // already, but for some compiler-introduced names it seems not to be,
+ // so fix that here.
+ // Later, when we want to find the index of a node in the variables list,
+ // we will check that n->curfn == curfn and n->opt > 0. Then n->opt - 1
+ // is the index in the variables list.
+ ll->n->opt = nil;
+ ll->n->curfn = curfn;
switch(ll->n->class) {
case PAUTO:
- if(haspointers(ll->n->type))
+ if(haspointers(ll->n->type)) {
+ ll->n->opt = (void*)(uintptr)(arraylength(result)+1);
arrayadd(result, &ll->n);
+ }
break;
case PPARAM:
case PPARAMOUT:
+ ll->n->opt = (void*)(uintptr)(arraylength(result)+1);
arrayadd(result, &ll->n);
break;
}
@@ -718,14 +735,16 @@ progeffects(Prog *prog, Array *vars, Bvec *uevar, Bvec *varkill, Bvec *avarinit)
}
if(info.flags & (LeftRead | LeftWrite | LeftAddr)) {
from = &prog->from;
- if (from->node != nil && from->sym != nil) {
+ if (from->node != nil && from->sym != nil && from->node->curfn == curfn) {
switch(from->node->class & ~PHEAP) {
case PAUTO:
case PPARAM:
case PPARAMOUT:
- pos = arrayindexof(vars, from->node);
+ pos = (int)(uintptr)from->node->opt - 1; // index in vars
if(pos == -1)
goto Next;
+ if(pos >= arraylength(vars) || *(Node**)arrayget(vars, pos) != from->node)
+ fatal("bad bookkeeping in liveness %N %d", from->node, pos);
if(from->node->addrtaken) {
bvset(avarinit, pos);
} else {
@@ -741,14 +760,16 @@ progeffects(Prog *prog, Array *vars, Bvec *uevar, Bvec *varkill, Bvec *avarinit)
Next:
if(info.flags & (RightRead | RightWrite | RightAddr)) {
to = &prog->to;
- if (to->node != nil && to->sym != nil) {
+ if (to->node != nil && to->sym != nil && to->node->curfn == curfn) {
switch(to->node->class & ~PHEAP) {
case PAUTO:
case PPARAM:
case PPARAMOUT:
- pos = arrayindexof(vars, to->node);
+ pos = (int)(uintptr)to->node->opt - 1; // index in vars
if(pos == -1)
goto Next1;
+ if(pos >= arraylength(vars) || *(Node**)arrayget(vars, pos) != to->node)
+ fatal("bad bookkeeping in liveness %N %d", to->node, pos);
if(to->node->addrtaken) {
if(prog->as != AVARKILL)
bvset(avarinit, pos);
@@ -1020,6 +1041,9 @@ checkptxt(Node *fn, Prog *firstp)
{
Prog *p;
+ if(debuglive == 0)
+ return;
+
for(p = firstp; p != P; p = p->link) {
if(0)
print("analyzing '%P'\n", p);
@@ -1172,21 +1196,17 @@ twobitlivepointermap(Liveness *lv, Bvec *liveout, Array *vars, Bvec *args, Bvec
vlong xoffset;
int32 i;
- for(i = 0; i < arraylength(vars); i++) {
+ for(i = 0; (i = bvnext(liveout, i)) >= 0; i++) {
node = *(Node**)arrayget(vars, i);
switch(node->class) {
case PAUTO:
- if(bvget(liveout, i)) {
- xoffset = node->xoffset + stkptrsize;
- twobitwalktype1(node->type, &xoffset, locals);
- }
+ xoffset = node->xoffset + stkptrsize;
+ twobitwalktype1(node->type, &xoffset, locals);
break;
case PPARAM:
case PPARAMOUT:
- if(bvget(liveout, i)) {
- xoffset = node->xoffset;
- twobitwalktype1(node->type, &xoffset, args);
- }
+ xoffset = node->xoffset;
+ twobitwalktype1(node->type, &xoffset, args);
break;
}
}
@@ -1937,6 +1957,7 @@ liveness(Node *fn, Prog *firstp, Sym *argssym, Sym *livesym)
Array *cfg, *vars;
Liveness *lv;
int debugdelta;
+ NodeList *l;
// Change name to dump debugging information only for a specific function.
debugdelta = 0;
@@ -1977,6 +1998,9 @@ liveness(Node *fn, Prog *firstp, Sym *argssym, Sym *livesym)
twobitwritesymbol(lv->argslivepointers, argssym);
// Free everything.
+ for(l=fn->dcl; l != nil; l = l->next)
+ if(l->n != N)
+ l->n->opt = nil;
freeliveness(lv);
arrayfree(vars);
freecfg(cfg);