Fixes #219.
R=ken2, r
CC=golang-dev
https://golang.org/cl/194097
char *runtimeimport =
"package runtime\n"
- "func \"\".mal (? int32) (? *any)\n"
+ "func \"\".mal (? int32) *any\n"
"func \"\".throwindex ()\n"
"func \"\".throwreturn ()\n"
"func \"\".throwinit ()\n"
"func \"\".printslice (? any)\n"
"func \"\".printnl ()\n"
"func \"\".printsp ()\n"
- "func \"\".catstring (? string, ? string) (? string)\n"
- "func \"\".cmpstring (? string, ? string) (? int)\n"
- "func \"\".slicestring (? string, ? int, ? int) (? string)\n"
- "func \"\".slicestring1 (? string, ? int) (? string)\n"
- "func \"\".indexstring (? string, ? int) (? uint8)\n"
- "func \"\".intstring (? int64) (? string)\n"
- "func \"\".slicebytetostring (? []uint8) (? string)\n"
- "func \"\".sliceinttostring (? []int) (? string)\n"
- "func \"\".stringiter (? string, ? int) (? int)\n"
+ "func \"\".printf ()\n"
+ "func \"\".catstring (? string, ? string) string\n"
+ "func \"\".cmpstring (? string, ? string) int\n"
+ "func \"\".slicestring (? string, ? int, ? int) string\n"
+ "func \"\".slicestring1 (? string, ? int) string\n"
+ "func \"\".indexstring (? string, ? int) uint8\n"
+ "func \"\".intstring (? int64) string\n"
+ "func \"\".slicebytetostring (? []uint8) string\n"
+ "func \"\".sliceinttostring (? []int) string\n"
+ "func \"\".stringiter (? string, ? int) int\n"
"func \"\".stringiter2 (? string, ? int) (retk int, retv int)\n"
- "func \"\".slicecopy (to any, fr any, wid uint32) (? int)\n"
+ "func \"\".slicecopy (to any, fr any, wid uint32) int\n"
"func \"\".ifaceI2E (iface any) (ret any)\n"
"func \"\".ifaceE2I (typ *uint8, iface any) (ret any)\n"
"func \"\".ifaceT2E (typ *uint8, elem any) (ret any)\n"
"func \"\".chansend1 (hchan chan<- any, elem any)\n"
"func \"\".chansend2 (hchan chan<- any, elem any) (pres bool)\n"
"func \"\".closechan (hchan any)\n"
- "func \"\".closedchan (hchan any) (? bool)\n"
+ "func \"\".closedchan (hchan any) bool\n"
"func \"\".newselect (size int) (sel *uint8)\n"
"func \"\".selectsend (sel *uint8, hchan chan<- any, elem any) (selected bool)\n"
"func \"\".selectrecv (sel *uint8, hchan <-chan any, elem *any) (selected bool)\n"
"func \"\".sliceslice (old []any, lb int, hb int, width int) (ary []any)\n"
"func \"\".slicearray (old *any, nel int, lb int, hb int, width int) (ary []any)\n"
"func \"\".closure ()\n"
- "func \"\".int64div (? int64, ? int64) (? int64)\n"
- "func \"\".uint64div (? uint64, ? uint64) (? uint64)\n"
- "func \"\".int64mod (? int64, ? int64) (? int64)\n"
- "func \"\".uint64mod (? uint64, ? uint64) (? uint64)\n"
- "func \"\".float64toint64 (? float64) (? int64)\n"
- "func \"\".int64tofloat64 (? int64) (? float64)\n"
+ "func \"\".int64div (? int64, ? int64) int64\n"
+ "func \"\".uint64div (? uint64, ? uint64) uint64\n"
+ "func \"\".int64mod (? int64, ? int64) int64\n"
+ "func \"\".uint64mod (? uint64, ? uint64) uint64\n"
+ "func \"\".float64toint64 (? float64) int64\n"
+ "func \"\".int64tofloat64 (? int64) float64\n"
"\n"
"$$\n";
char *unsafeimport =
"package unsafe\n"
"type \"\".Pointer *any\n"
- "func \"\".Offsetof (? any) (? int)\n"
- "func \"\".Sizeof (? any) (? int)\n"
- "func \"\".Alignof (? any) (? int)\n"
+ "func \"\".Offsetof (? any) int\n"
+ "func \"\".Sizeof (? any) int\n"
+ "func \"\".Alignof (? any) int\n"
"func \"\".Typeof (i interface { }) (typ interface { })\n"
"func \"\".Reflect (i interface { }) (typ interface { }, addr \"\".Pointer)\n"
"func \"\".Unreflect (typ interface { }, addr \"\".Pointer) (ret interface { })\n"
- "func \"\".New (typ interface { }) (? \"\".Pointer)\n"
- "func \"\".NewArray (typ interface { }, n int) (? \"\".Pointer)\n"
+ "func \"\".New (typ interface { }) \"\".Pointer\n"
+ "func \"\".NewArray (typ interface { }, n int) \"\".Pointer\n"
"\n"
"$$\n";
func printslice(any)
func printnl()
func printsp()
+func printf()
func catstring(string, string) string
func cmpstring(string, string) int
#include "go.h"
-static Node* walkprint(Node*, NodeList**);
+static Node* walkprint(Node*, NodeList**, int);
static Node* conv(Node*, Type*);
static Node* mapfn(char*, Type*);
static Node* makenewvar(Type*, NodeList**, Node**);
case ODEFER:
hasdefer = 1;
- walkexpr(&n->left, &n->ninit);
+ switch(n->left->op) {
+ case OPRINT:
+ case OPRINTN:
+ case OPANIC:
+ case OPANICN:
+ walkexprlist(n->left->list, &n->ninit);
+ n->left = walkprint(n->left, &n->ninit, 1);
+ break;
+ default:
+ walkexpr(&n->left, &n->ninit);
+ break;
+ }
break;
case OFOR:
case OPANIC:
case OPANICN:
walkexprlist(n->list, init);
- n = walkprint(n, init);
+ n = walkprint(n, init, 0);
goto ret;
case OLITERAL:
// generate code for print
static Node*
-walkprint(Node *nn, NodeList **init)
+walkprint(Node *nn, NodeList **init, int defer)
{
Node *r;
Node *n;
Node *on;
Type *t;
int notfirst, et, op;
- NodeList *calls;
+ NodeList *calls, *intypes, *args;
+ Fmt fmt;
+ on = nil;
op = nn->op;
all = nn->list;
calls = nil;
notfirst = 0;
+ intypes = nil;
+ args = nil;
+
+ memset(&fmt, 0, sizeof fmt);
+ if(defer) {
+ // defer print turns into defer printf with format string
+ fmtstrinit(&fmt);
+ intypes = list(intypes, nod(ODCLFIELD, N, typenod(types[TSTRING])));
+ args = list1(nod(OXXX, N, N));
+ }
for(l=all; l; l=l->next) {
- if(notfirst)
- calls = list(calls, mkcall("printsp", T, init));
+ if(notfirst) {
+ if(defer)
+ fmtprint(&fmt, " ");
+ else
+ calls = list(calls, mkcall("printsp", T, init));
+ }
notfirst = op == OPRINTN || op == OPANICN;
n = l->n;
if(n->type == T || n->type->etype == TFORW)
continue;
+ t = n->type;
et = n->type->etype;
if(isinter(n->type)) {
- if(isnilinter(n->type))
- on = syslook("printeface", 1);
- else
- on = syslook("printiface", 1);
- argtype(on, n->type); // any-1
+ if(defer) {
+ if(isnilinter(n->type))
+ fmtprint(&fmt, "%%e");
+ else
+ fmtprint(&fmt, "%%i");
+ } else {
+ if(isnilinter(n->type))
+ on = syslook("printeface", 1);
+ else
+ on = syslook("printiface", 1);
+ argtype(on, n->type); // any-1
+ }
} else if(isptr[et] || et == TCHAN || et == TMAP || et == TFUNC) {
- on = syslook("printpointer", 1);
- argtype(on, n->type); // any-1
+ if(defer) {
+ fmtprint(&fmt, "%%p");
+ } else {
+ on = syslook("printpointer", 1);
+ argtype(on, n->type); // any-1
+ }
} else if(isslice(n->type)) {
- on = syslook("printslice", 1);
- argtype(on, n->type); // any-1
+ if(defer) {
+ fmtprint(&fmt, "%%a");
+ } else {
+ on = syslook("printslice", 1);
+ argtype(on, n->type); // any-1
+ }
} else if(isint[et]) {
- if(et == TUINT64)
- on = syslook("printuint", 0);
- else
- on = syslook("printint", 0);
+ if(defer) {
+ if(et == TUINT64)
+ fmtprint(&fmt, "%%U");
+ else {
+ fmtprint(&fmt, "%%D");
+ t = types[TINT64];
+ }
+ } else {
+ if(et == TUINT64)
+ on = syslook("printuint", 0);
+ else
+ on = syslook("printint", 0);
+ }
} else if(isfloat[et]) {
- on = syslook("printfloat", 0);
+ if(defer) {
+ fmtprint(&fmt, "%%f");
+ t = types[TFLOAT64];
+ } else
+ on = syslook("printfloat", 0);
} else if(et == TBOOL) {
- on = syslook("printbool", 0);
+ if(defer)
+ fmtprint(&fmt, "%%t");
+ else
+ on = syslook("printbool", 0);
} else if(et == TSTRING) {
- on = syslook("printstring", 0);
+ if(defer)
+ fmtprint(&fmt, "%%S");
+ else
+ on = syslook("printstring", 0);
} else {
badtype(OPRINT, n->type, T);
continue;
}
- t = *getinarg(on->type);
- if(t != nil)
- t = t->type;
- if(t != nil)
- t = t->type;
+ if(!defer) {
+ t = *getinarg(on->type);
+ if(t != nil)
+ t = t->type;
+ if(t != nil)
+ t = t->type;
+ }
if(!eqtype(t, n->type)) {
n = nod(OCONV, n, N);
n->type = t;
}
- r = nod(OCALL, on, N);
- r->list = list1(n);
- calls = list(calls, r);
+
+ if(defer) {
+ intypes = list(intypes, nod(ODCLFIELD, N, typenod(t)));
+ args = list(args, n);
+ } else {
+ r = nod(OCALL, on, N);
+ r->list = list1(n);
+ calls = list(calls, r);
+ }
}
- if(op == OPRINTN)
- calls = list(calls, mkcall("printnl", T, nil));
- typechecklist(calls, Etop);
- walkexprlist(calls, init);
-
- if(op == OPANIC || op == OPANICN)
- r = mkcall("panicl", T, nil);
- else
- r = nod(OEMPTY, N, N);
- typecheck(&r, Etop);
- walkexpr(&r, init);
- r->ninit = calls;
+ if(defer) {
+ if(op == OPRINTN)
+ fmtprint(&fmt, "\n");
+ if(op == OPANIC || op == OPANICN)
+ fmtprint(&fmt, "%%!");
+ on = syslook("printf", 1);
+ on->type = functype(nil, intypes, nil);
+ args->n = nod(OLITERAL, N, N);
+ args->n->val.ctype = CTSTR;
+ args->n->val.u.sval = strlit(fmtstrflush(&fmt));
+ r = nod(OCALL, on, N);
+ r->list = args;
+ typecheck(&r, Etop);
+ walkexpr(&r, init);
+ } else {
+ if(op == OPRINTN)
+ calls = list(calls, mkcall("printnl", T, nil));
+ typechecklist(calls, Etop);
+ walkexprlist(calls, init);
+
+ if(op == OPANIC || op == OPANICN)
+ r = mkcall("panicl", T, nil);
+ else
+ r = nod(OEMPTY, N, N);
+ typecheck(&r, Etop);
+ walkexpr(&r, init);
+ r->ninit = calls;
+ }
return r;
}
//static Lock debuglock;
+static void vprintf(int8*, byte*);
+
void
dump(byte *p, int32 n)
{
write(fd, s, findnull((byte*)s));
}
-// Very simple printf. Only for debugging prints.
-// Do not add to this without checking with Rob.
+#pragma textflag 7
void
printf(int8 *s, ...)
+{
+ byte *arg;
+
+ arg = (byte*)(&s+1);
+ vprintf(s, arg);
+}
+
+static byte*
+vrnd(byte *p, int32 x)
+{
+ if((uint32)(uintptr)p&(x-1))
+ p += x - ((uint32)(uintptr)p&(x-1));
+ return p;
+}
+
+// Very simple printf. Only for debugging prints.
+// Do not add to this without checking with Rob.
+static void
+vprintf(int8 *s, byte *arg)
{
int8 *p, *lp;
- byte *arg, *narg;
+ byte *narg;
// lock(&debuglock);
lp = p = s;
- arg = (byte*)(&s+1);
for(; *p; p++) {
if(*p != '%')
continue;
p++;
narg = nil;
switch(*p) {
+ case 't':
+ narg = arg + 1;
+ break;
case 'd': // 32-bit
case 'x':
+ arg = vrnd(arg, 4);
narg = arg + 4;
break;
case 'D': // 64-bit
+ case 'U':
case 'X':
- if(sizeof(uintptr) == 8 && ((uint32)(uint64)arg)&4)
- arg += 4;
+ case 'f':
+ arg = vrnd(arg, sizeof(uintptr));
narg = arg + 8;
break;
case 'p': // pointer-sized
case 's':
- if(sizeof(uintptr) == 8 && ((uint32)(uint64)arg)&4)
- arg += 4;
+ arg = vrnd(arg, sizeof(uintptr));
narg = arg + sizeof(uintptr);
break;
case 'S': // pointer-aligned but bigger
- if(sizeof(uintptr) == 8 && ((uint32)(uint64)arg)&4)
- arg += 4;
+ arg = vrnd(arg, sizeof(uintptr));
narg = arg + sizeof(String);
break;
+ case 'a': // pointer-aligned but bigger
+ arg = vrnd(arg, sizeof(uintptr));
+ narg = arg + sizeof(Slice);
+ break;
+ case 'i': // pointer-aligned but bigger
+ case 'e':
+ arg = vrnd(arg, sizeof(uintptr));
+ narg = arg + sizeof(Eface);
+ break;
}
switch(*p) {
+ case 'a':
+ ·printslice(*(Slice*)arg);
+ break;
case 'd':
·printint(*(int32*)arg);
break;
case 'D':
·printint(*(int64*)arg);
break;
- case 'x':
- ·printhex(*(uint32*)arg);
+ case 'e':
+ ·printeface(*(Eface*)arg);
break;
- case 'X':
- ·printhex(*(uint64*)arg);
+ case 'f':
+ ·printfloat(*(float64*)arg);
+ break;
+ case 'i':
+ ·printiface(*(Iface*)arg);
break;
case 'p':
·printpointer(*(void**)arg);
case 'S':
·printstring(*(String*)arg);
break;
+ case 't':
+ ·printbool(*(bool*)arg);
+ break;
+ case 'U':
+ ·printuint(*(uint64*)arg);
+ break;
+ case 'x':
+ ·printhex(*(uint32*)arg);
+ break;
+ case 'X':
+ ·printhex(*(uint64*)arg);
+ break;
+ case '!':
+ ·panicl(-1);
}
arg = narg;
lp = p+1;
// unlock(&debuglock);
}
+void
+·printf(String s, ...)
+{
+ // Can assume s has terminating NUL because only
+ // the Go compiler generates calls to ·printf, using
+ // string constants, and all the string constants have NULs.
+ vprintf((int8*)s.str, (byte*)(&s+1));
+}
void
·printpc(void *p)
void runtime_printuint(uint64);
void runtime_printhex(uint64);
void runtime_printslice(Slice);
+void ·panicl(int32);
/*
* wrapped for go users
--- /dev/null
+// $G $D/$F.go && $L $F.$A && ./$A.out
+
+// Copyright 2010 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 main
+
+func main() {
+ defer println(42, true, false, true, 1.5, "world", (chan int)(nil), []int(nil), (map[string]int)(nil), (func())(nil), byte(255))
+ defer println(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20)
+// defer panic("dead")
+ defer print("printing: ")
+}
panic PC=xxx
+=========== ./deferprint.go
+printing: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
+42 true false true +1.500000e+000 world 0x0 [0/0]0x0 0x0 0x0 255
+
=========== ./helloworld.go
hello, world