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)
/* types used in front end */
// types[TNIL] got set early in lexinit
types[TIDEAL] = typ(TIDEAL);
types[TINTER] = typ(TINTER);
/* simple aliases */
simtype[TMAP] = tptr;
......
......@@ -4,7 +4,8 @@ char *runtimeimport =
"func \"\".throwindex ()\n"
"func \"\".throwreturn ()\n"
"func \"\".throwinit ()\n"
"func \"\".panicl ()\n"
"func \"\".panic (? interface { })\n"
"func \"\".recover () interface { }\n"
"func \"\".printbool (? bool)\n"
"func \"\".printfloat (? float64)\n"
"func \"\".printint (? int64)\n"
......
......@@ -379,6 +379,7 @@ enum
OPANIC, OPRINT, OPRINTN,
OSEND, OSENDNB,
OSLICE, OSLICEARR, OSLICESTR,
ORECOVER,
ORECV,
ORUNESTR,
OSELRECV,
......
......@@ -1309,6 +1309,7 @@ static struct
"print", LNAME, Txxx, OPRINT,
"println", LNAME, Txxx, OPRINTN,
"real", LNAME, Txxx, OREAL,
"recover", LNAME, Txxx, ORECOVER,
"notwithstanding", LIGNORE, Txxx, OXXX,
"thetruthofthematter", LIGNORE, Txxx, OXXX,
......
......@@ -14,7 +14,9 @@ func mal(int32) *any
func throwindex()
func throwreturn()
func throwinit()
func panicl()
func panic(interface{})
func recover() interface{}
func printbool(bool)
func printfloat(float64)
......
......@@ -1012,13 +1012,31 @@ reswitch:
n->type = ptrto(t);
goto ret;
case OPANIC:
case OPRINT:
case OPRINTN:
ok |= Etop;
typechecklist(n->list, Erv);
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:
ok |= Erv;
typecheckclosure(n);
......
......@@ -425,7 +425,6 @@ walkstmt(Node **np)
switch(n->left->op) {
case OPRINT:
case OPRINTN:
case OPANIC:
walkexprlist(n->left->list, &n->ninit);
n->left = walkprint(n->left, &n->ninit, 1);
break;
......@@ -623,11 +622,18 @@ walkexpr(Node **np, NodeList **init)
case OPRINT:
case OPRINTN:
case OPANIC:
walkexprlist(n->list, init);
n = walkprint(n, init, 0);
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:
n->addable = 1;
goto ret;
......
......@@ -360,15 +360,28 @@ TEXT runcgo(SB),7,$16
// check that SP is in range [g->stackbase, g->stackguard)
TEXT stackcheck(SB), 7, $0
get_tls(CX)
MOVL g(CX), AX
CMPL g_stackbase(AX), SP
JHI 2(PC)
INT $3
CMPL SP, g_stackguard(AX)
JHI 2(PC)
INT $3
MOVL g(CX), AX
CMPL g_stackbase(AX), SP
JHI 2(PC)
INT $3
CMPL SP, g_stackguard(AX)
JHI 2(PC)
INT $3
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 g0(SB), $1024
......
......@@ -303,11 +303,24 @@ TEXT runcgo(SB),7,$32
// check that SP is in range [g->stackbase, g->stackguard)
TEXT stackcheck(SB), 7, $0
CMPQ g_stackbase(g), SP
JHI 2(PC)
INT $3
CMPQ SP, g_stackguard(g)
JHI 2(PC)
INT $3
CMPQ g_stackbase(g), SP
JHI 2(PC)
INT $3
CMPQ SP, g_stackguard(g)
JHI 2(PC)
INT $3
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
MOVW $0, R0
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 @@
// license that can be found in the LICENSE file.
#include "runtime.h"
#include "type.h"
//static Lock debuglock;
......@@ -150,7 +151,7 @@ vprintf(int8 *s, byte *arg)
·printhex(*(uint64*)arg);
break;
case '!':
·panicl(-1);
panic(-1);
}
arg = narg;
lp = p+1;
......@@ -347,3 +348,68 @@ void
{
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)
}
void
·panicl(int32 lno)
panic(int32 unused)
{
uint8 *sp;
......@@ -31,16 +31,25 @@ void
}
panicking++;
printf("\npanic PC=%X\n", (uint64)(uintptr)&lno);
sp = (uint8*)&lno;
printf("\npanic PC=%X\n", (uint64)(uintptr)&unused);
sp = (uint8*)&unused;
if(gotraceback()){
traceback(·getcallerpc(&lno), sp, g);
traceback(·getcallerpc(&unused), sp, g);
tracebackothers(g);
}
breakpoint(); // so we can grab it in a debugger
exit(2);
}
void
·panic(Eface e)
{
fd = 2;
printf("panic: ");
printany(e);
panic(0);
}
void
·throwindex(void)
{
......@@ -70,7 +79,7 @@ throw(int8 *s)
{
fd = 2;
printf("throw: %s\n", s);
·panicl(-1);
panic(-1);
*(int32*)0 = 0; // not reached
exit(1); // even more not reached
}
......
......@@ -344,6 +344,7 @@ int32 charntorune(int32*, uint8*, int32);
/*
* very low level c-called
*/
void callString(void(*fn)(void), void *arg, String *out);
void gogo(Gobuf*, uintptr);
void gogocall(Gobuf*, void(*)(void));
uintptr gosave(Gobuf*);
......@@ -354,6 +355,7 @@ void* getu(void);
void throw(int8*);
uint32 rnd(uint32, uint32);
void prints(int8*);
void printany(Eface);
void printf(int8*, ...);
byte* mchr(byte*, byte, byte*);
void mcpy(byte*, byte*, uint32);
......@@ -510,7 +512,7 @@ void runtime_printuint(uint64);
void runtime_printhex(uint64);
void runtime_printslice(Slice);
void runtime_printcomplex(Complex128);
void ·panicl(int32);
void panic(int32);
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