Commit 01eaf780 authored by Russ Cox's avatar Russ Cox

gc: add panic and recover (still unimplemented in runtime)

main semantic change is to enforce single argument to panic.

runtime: change to 1-argument panic.
use String method on argument if it has one.

R=ken2, r
CC=golang-dev
https://golang.org/cl/812043
parent c7122a3c
...@@ -542,6 +542,7 @@ typeinit(void) ...@@ -542,6 +542,7 @@ typeinit(void)
/* types used in front end */ /* types used in front end */
// types[TNIL] got set early in lexinit // types[TNIL] got set early in lexinit
types[TIDEAL] = typ(TIDEAL); types[TIDEAL] = typ(TIDEAL);
types[TINTER] = typ(TINTER);
/* simple aliases */ /* simple aliases */
simtype[TMAP] = tptr; simtype[TMAP] = tptr;
......
...@@ -4,7 +4,8 @@ char *runtimeimport = ...@@ -4,7 +4,8 @@ char *runtimeimport =
"func \"\".throwindex ()\n" "func \"\".throwindex ()\n"
"func \"\".throwreturn ()\n" "func \"\".throwreturn ()\n"
"func \"\".throwinit ()\n" "func \"\".throwinit ()\n"
"func \"\".panicl ()\n" "func \"\".panic (? interface { })\n"
"func \"\".recover () interface { }\n"
"func \"\".printbool (? bool)\n" "func \"\".printbool (? bool)\n"
"func \"\".printfloat (? float64)\n" "func \"\".printfloat (? float64)\n"
"func \"\".printint (? int64)\n" "func \"\".printint (? int64)\n"
......
...@@ -379,6 +379,7 @@ enum ...@@ -379,6 +379,7 @@ enum
OPANIC, OPRINT, OPRINTN, OPANIC, OPRINT, OPRINTN,
OSEND, OSENDNB, OSEND, OSENDNB,
OSLICE, OSLICEARR, OSLICESTR, OSLICE, OSLICEARR, OSLICESTR,
ORECOVER,
ORECV, ORECV,
ORUNESTR, ORUNESTR,
OSELRECV, OSELRECV,
......
...@@ -1309,6 +1309,7 @@ static struct ...@@ -1309,6 +1309,7 @@ static struct
"print", LNAME, Txxx, OPRINT, "print", LNAME, Txxx, OPRINT,
"println", LNAME, Txxx, OPRINTN, "println", LNAME, Txxx, OPRINTN,
"real", LNAME, Txxx, OREAL, "real", LNAME, Txxx, OREAL,
"recover", LNAME, Txxx, ORECOVER,
"notwithstanding", LIGNORE, Txxx, OXXX, "notwithstanding", LIGNORE, Txxx, OXXX,
"thetruthofthematter", LIGNORE, Txxx, OXXX, "thetruthofthematter", LIGNORE, Txxx, OXXX,
......
...@@ -14,7 +14,9 @@ func mal(int32) *any ...@@ -14,7 +14,9 @@ func mal(int32) *any
func throwindex() func throwindex()
func throwreturn() func throwreturn()
func throwinit() func throwinit()
func panicl()
func panic(interface{})
func recover() interface{}
func printbool(bool) func printbool(bool)
func printfloat(float64) func printfloat(float64)
......
...@@ -1012,13 +1012,31 @@ reswitch: ...@@ -1012,13 +1012,31 @@ reswitch:
n->type = ptrto(t); n->type = ptrto(t);
goto ret; goto ret;
case OPANIC:
case OPRINT: case OPRINT:
case OPRINTN: case OPRINTN:
ok |= Etop; ok |= Etop;
typechecklist(n->list, Erv); typechecklist(n->list, Erv);
goto ret; goto ret;
case OPANIC:
ok |= Etop;
if(onearg(n) < 0)
goto error;
typecheck(&n->left, Erv);
defaultlit(&n->left, types[TINTER]);
if(n->left->type == T)
goto error;
goto ret;
case ORECOVER:
ok |= Erv|Etop;
if(n->list != nil) {
yyerror("too many arguments to recover");
goto error;
}
n->type = types[TINTER];
goto ret;
case OCLOSURE: case OCLOSURE:
ok |= Erv; ok |= Erv;
typecheckclosure(n); typecheckclosure(n);
......
...@@ -425,7 +425,6 @@ walkstmt(Node **np) ...@@ -425,7 +425,6 @@ walkstmt(Node **np)
switch(n->left->op) { switch(n->left->op) {
case OPRINT: case OPRINT:
case OPRINTN: case OPRINTN:
case OPANIC:
walkexprlist(n->left->list, &n->ninit); walkexprlist(n->left->list, &n->ninit);
n->left = walkprint(n->left, &n->ninit, 1); n->left = walkprint(n->left, &n->ninit, 1);
break; break;
...@@ -623,11 +622,18 @@ walkexpr(Node **np, NodeList **init) ...@@ -623,11 +622,18 @@ walkexpr(Node **np, NodeList **init)
case OPRINT: case OPRINT:
case OPRINTN: case OPRINTN:
case OPANIC:
walkexprlist(n->list, init); walkexprlist(n->list, init);
n = walkprint(n, init, 0); n = walkprint(n, init, 0);
goto ret; goto ret;
case OPANIC:
n = mkcall("panic", T, init, n->left);
goto ret;
case ORECOVER:
n = mkcall("recover", n->type, init);
goto ret;
case OLITERAL: case OLITERAL:
n->addable = 1; n->addable = 1;
goto ret; goto ret;
......
...@@ -369,6 +369,19 @@ TEXT stackcheck(SB), 7, $0 ...@@ -369,6 +369,19 @@ TEXT stackcheck(SB), 7, $0
INT $3 INT $3
RET RET
// callString(f, arg, out)
// call Go f(arg), which returns a string, and store in out
TEXT callString(SB), 7, $24
MOVL arg+4(FP), BX
MOVL f+0(FP), CX
MOVL BX, 0(SP)
CALL *CX
MOVL out+8(FP), DI
LEAL 4(SP), SI
MOVSL
MOVSL
MOVSL
RET
GLOBL m0(SB), $1024 GLOBL m0(SB), $1024
GLOBL g0(SB), $1024 GLOBL g0(SB), $1024
......
...@@ -311,3 +311,16 @@ TEXT stackcheck(SB), 7, $0 ...@@ -311,3 +311,16 @@ TEXT stackcheck(SB), 7, $0
INT $3 INT $3
RET RET
// callString(f, arg, out)
// call Go f(arg), which returns a string, and store in out
TEXT callString(SB), 7, $24
MOVQ arg+8(FP), BX
MOVQ f+0(FP), CX
MOVQ BX, 0(SP)
CALL *CX
MOVQ out+16(FP), DI
LEAQ 8(SP), SI
MOVSQ
MOVSQ
RET
...@@ -264,3 +264,18 @@ TEXT abort(SB),7,$0 ...@@ -264,3 +264,18 @@ TEXT abort(SB),7,$0
MOVW $0, R0 MOVW $0, R0
MOVW (R0), R1 MOVW (R0), R1
// callString(f, arg, out)
// call Go f(arg), which returns a string, and store in out
TEXT callString(SB), 7, $24
MOVW arg+4(FP), R1
MOVW f+0(FP), R0
MOVW R1, 0(SP)
BL R0
MOVW 4(SP), R1
MOVW 8(SP), R2
MOVW 12(SP), R3
MOVW out+8(FP), R0
MOVW R1, 0(R0)
MOVW R2, 4(R0)
MOVW R3, 8(R0)
RET
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
#include "runtime.h" #include "runtime.h"
#include "type.h"
//static Lock debuglock; //static Lock debuglock;
...@@ -150,7 +151,7 @@ vprintf(int8 *s, byte *arg) ...@@ -150,7 +151,7 @@ vprintf(int8 *s, byte *arg)
·printhex(*(uint64*)arg); ·printhex(*(uint64*)arg);
break; break;
case '!': case '!':
·panicl(-1); panic(-1);
} }
arg = narg; arg = narg;
lp = p+1; lp = p+1;
...@@ -347,3 +348,68 @@ void ...@@ -347,3 +348,68 @@ void
{ {
write(fd, "\n", 1); write(fd, "\n", 1);
} }
// print an empty interface, for use by panic.
// this could be arbitrarily complex in general,
// so we pick off only a few important cases:
// int, string, and values with a String() string method.
void
printany(Eface e)
{
int32 i;
FuncType *ft;
Method *m;
String s;
Type *rt;
UncommonType *x;
if(e.type == nil) {
write(fd, "nil", 3);
return;
}
if((x=e.type->x) != nil) {
for(i=0; i<x->mhdr.len; i++) {
// Look for String() string method.
m = &x->m[i];
if(m->name->len == 6 &&
mcmp(m->name->str, (byte*)"String", 6) == 0 &&
// Found String; check method signature for func() string.
m->mtyp->kind == KindFunc &&
(ft = (FuncType*)m->mtyp)->in.len == 0 &&
ft->out.len == 1 &&
// Found single output. Is it string?
// Only base types have name != nil but pkgPath == nil.
(rt = *(Type**)ft->out.array)->kind == KindString &&
rt->x != nil &&
rt->x->name != nil && rt->x->pkgPath == nil) {
// Found the method!
// Have to use assembly to call it
// and save the return value.
callString(m->ifn, e.data, &s);
·printstring(s);
return;
}
}
}
switch(e.type->kind & ~KindNoPointers) {
case KindInt:
mcpy((byte*)&i, (byte*)&e.data, sizeof(i));
·printint(i);
break;
case KindString:
·printstring(*(String*)e.data);
break;
default:
// Could print the other numeric types,
// but that's overkill: good panics have
// a string method anyway.
·printstring(*e.type->string);
write(fd, "(???)", 5);
break;
}
}
...@@ -20,7 +20,7 @@ gotraceback(void) ...@@ -20,7 +20,7 @@ gotraceback(void)
} }
void void
·panicl(int32 lno) panic(int32 unused)
{ {
uint8 *sp; uint8 *sp;
...@@ -31,16 +31,25 @@ void ...@@ -31,16 +31,25 @@ void
} }
panicking++; panicking++;
printf("\npanic PC=%X\n", (uint64)(uintptr)&lno); printf("\npanic PC=%X\n", (uint64)(uintptr)&unused);
sp = (uint8*)&lno; sp = (uint8*)&unused;
if(gotraceback()){ if(gotraceback()){
traceback(·getcallerpc(&lno), sp, g); traceback(·getcallerpc(&unused), sp, g);
tracebackothers(g); tracebackothers(g);
} }
breakpoint(); // so we can grab it in a debugger breakpoint(); // so we can grab it in a debugger
exit(2); exit(2);
} }
void
·panic(Eface e)
{
fd = 2;
printf("panic: ");
printany(e);
panic(0);
}
void void
·throwindex(void) ·throwindex(void)
{ {
...@@ -70,7 +79,7 @@ throw(int8 *s) ...@@ -70,7 +79,7 @@ throw(int8 *s)
{ {
fd = 2; fd = 2;
printf("throw: %s\n", s); printf("throw: %s\n", s);
·panicl(-1); panic(-1);
*(int32*)0 = 0; // not reached *(int32*)0 = 0; // not reached
exit(1); // even more not reached exit(1); // even more not reached
} }
......
...@@ -344,6 +344,7 @@ int32 charntorune(int32*, uint8*, int32); ...@@ -344,6 +344,7 @@ int32 charntorune(int32*, uint8*, int32);
/* /*
* very low level c-called * very low level c-called
*/ */
void callString(void(*fn)(void), void *arg, String *out);
void gogo(Gobuf*, uintptr); void gogo(Gobuf*, uintptr);
void gogocall(Gobuf*, void(*)(void)); void gogocall(Gobuf*, void(*)(void));
uintptr gosave(Gobuf*); uintptr gosave(Gobuf*);
...@@ -354,6 +355,7 @@ void* getu(void); ...@@ -354,6 +355,7 @@ void* getu(void);
void throw(int8*); void throw(int8*);
uint32 rnd(uint32, uint32); uint32 rnd(uint32, uint32);
void prints(int8*); void prints(int8*);
void printany(Eface);
void printf(int8*, ...); void printf(int8*, ...);
byte* mchr(byte*, byte, byte*); byte* mchr(byte*, byte, byte*);
void mcpy(byte*, byte*, uint32); void mcpy(byte*, byte*, uint32);
...@@ -510,7 +512,7 @@ void runtime_printuint(uint64); ...@@ -510,7 +512,7 @@ void runtime_printuint(uint64);
void runtime_printhex(uint64); void runtime_printhex(uint64);
void runtime_printslice(Slice); void runtime_printslice(Slice);
void runtime_printcomplex(Complex128); void runtime_printcomplex(Complex128);
void ·panicl(int32); void panic(int32);
void reflect·call(byte*, byte*, uint32); void reflect·call(byte*, byte*, uint32);
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment