mirror of
https://github.com/golang/go
synced 2024-11-25 05:57:57 -07:00
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
This commit is contained in:
parent
c7122a3c58
commit
01eaf780a8
@ -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 =
|
|||||||
"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
|
|||||||
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
|
|||||||
"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
|
|||||||
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:
|
|||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
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;
|
||||||
|
@ -360,15 +360,28 @@ TEXT runcgo(SB),7,$16
|
|||||||
// check that SP is in range [g->stackbase, g->stackguard)
|
// check that SP is in range [g->stackbase, g->stackguard)
|
||||||
TEXT stackcheck(SB), 7, $0
|
TEXT stackcheck(SB), 7, $0
|
||||||
get_tls(CX)
|
get_tls(CX)
|
||||||
MOVL g(CX), AX
|
MOVL g(CX), AX
|
||||||
CMPL g_stackbase(AX), SP
|
CMPL g_stackbase(AX), SP
|
||||||
JHI 2(PC)
|
JHI 2(PC)
|
||||||
INT $3
|
INT $3
|
||||||
CMPL SP, g_stackguard(AX)
|
CMPL SP, g_stackguard(AX)
|
||||||
JHI 2(PC)
|
JHI 2(PC)
|
||||||
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
|
||||||
|
@ -303,11 +303,24 @@ TEXT runcgo(SB),7,$32
|
|||||||
|
|
||||||
// check that SP is in range [g->stackbase, g->stackguard)
|
// check that SP is in range [g->stackbase, g->stackguard)
|
||||||
TEXT stackcheck(SB), 7, $0
|
TEXT stackcheck(SB), 7, $0
|
||||||
CMPQ g_stackbase(g), SP
|
CMPQ g_stackbase(g), SP
|
||||||
JHI 2(PC)
|
JHI 2(PC)
|
||||||
INT $3
|
INT $3
|
||||||
CMPQ SP, g_stackguard(g)
|
CMPQ SP, g_stackguard(g)
|
||||||
JHI 2(PC)
|
JHI 2(PC)
|
||||||
INT $3
|
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
|
RET
|
||||||
|
|
||||||
|
@ -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 @@
|
|||||||
// 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)
|
|||||||
·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
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
·panicl(int32 lno)
|
panic(int32 unused)
|
||||||
{
|
{
|
||||||
uint8 *sp;
|
uint8 *sp;
|
||||||
|
|
||||||
@ -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)
|
|||||||
{
|
{
|
||||||
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);
|
|||||||
/*
|
/*
|
||||||
* 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);
|
|||||||
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);
|
|||||||
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);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user