// Copyright 2009 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.

#include "runtime.h"

// TODO(rsc): Move this into portable code, with calls to a
// machine-dependent isclosure() function.

void
traceback(byte *pc0, byte *sp, G *g)
{
// 	Stktop *stk;
// 	uintptr pc;
// 	int32 i, n;
// 	Func *f;
// 	byte *p;

// 	pc = (uintptr)pc0;

// 	// If the PC is zero, it's likely a nil function call.
// 	// Start in the caller's frame.
// 	if(pc == 0) {
// 		pc = *(uintptr*)sp;
// 		sp += sizeof(uintptr);
// 	}

// 	stk = (Stktop*)g->stackbase;
// 	for(n=0; n<100; n++) {
// 		while(pc == (uintptr)retfromnewstack) {
// 			// pop to earlier stack block
// 			sp = stk->oldsp;
// 			stk = (Stktop*)stk->oldbase;
// 			pc = *(uintptr*)(sp+sizeof(uintptr));
// 			sp += 2*sizeof(uintptr);	// two irrelevant calls on stack: morestack plus its call
// 		}
// 		f = findfunc(pc);
// 		if(f == nil) {
// 			// dangerous, but poke around to see if it is a closure
// 			p = (byte*)pc;
// 			// ADDL $xxx, SP; RET
// 			if(p[0] == 0x81 && p[1] == 0xc4 && p[6] == 0xc3) {
// 				sp += *(uint32*)(p+2) + 8;
// 				pc = *(uintptr*)(sp - 8);
// 				if(pc <= 0x1000)
// 					return;
// 				continue;
// 			}
// 			printf("%p unknown pc\n", pc);
// 			return;
// 		}
// 		if(f->frame < sizeof(uintptr))	// assembly funcs say 0 but lie
// 			sp += sizeof(uintptr);
// 		else
// 			sp += f->frame;

// 		// print this frame
// 		//	main+0xf /home/rsc/go/src/runtime/x.go:23
// 		//		main(0x1, 0x2, 0x3)
// 		printf("%S", f->name);
// 		if(pc > f->entry)
// 			printf("+%p", (uintptr)(pc - f->entry));
// 		printf(" %S:%d\n", f->src, funcline(f, pc-1));	// -1 to get to CALL instr.
// 		printf("\t%S(", f->name);
// 		for(i = 0; i < f->args; i++) {
// 			if(i != 0)
// 				prints(", ");
// 			·printhex(((uint32*)sp)[i]);
// 			if(i >= 4) {
// 				prints(", ...");
// 				break;
// 			}
// 		}
// 		prints(")\n");

// 		pc = *(uintptr*)(sp-sizeof(uintptr));
// 		if(pc <= 0x1000)
// 			return;
// 	}
// 	prints("...\n");
}

// func caller(n int) (pc uintptr, file string, line int, ok bool)
void
·Caller(int32 n, uintptr retpc, String retfile, int32 retline, bool retbool)
{
// 	uintptr pc;
// 	byte *sp;
// 	byte *p;
// 	Stktop *stk;
// 	Func *f;

// 	// our caller's pc, sp.
// 	sp = (byte*)&n;
// 	pc = *((uintptr*)sp - 1);
// 	if((f = findfunc(pc)) == nil) {
// 	error:
// 		retpc = 0;
// 		retline = 0;
// 		retfile = emptystring;
// 		retbool = false;
// 		FLUSH(&retpc);
// 		FLUSH(&retfile);
// 		FLUSH(&retline);
// 		FLUSH(&retbool);
// 		return;
// 	}

// 	// now unwind n levels
// 	stk = (Stktop*)g->stackbase;
// 	while(n-- > 0) {
// 		while(pc == (uintptr)retfromnewstack) {
// 			sp = stk->oldsp;
// 			stk = (Stktop*)stk->oldbase;
// 			pc = *((uintptr*)sp + 1);
// 			sp += 2*sizeof(uintptr);
// 		}

// 		if(f->frame < sizeof(uintptr))	// assembly functions lie
// 			sp += sizeof(uintptr);
// 		else
// 			sp += f->frame;

// 	loop:
// 		pc = *((uintptr*)sp - 1);
// 		if(pc <= 0x1000 || (f = findfunc(pc)) == nil) {
// 			// dangerous, but let's try this.
// 			// see if it is a closure.
// 			p = (byte*)pc;
// 			// ADDL $xxx, SP; RET
// 			if(p[0] == 0x81 && p[1] == 0xc4 && p[6] == 0xc3) {
// 				sp += *(uint32*)(p+2) + sizeof(uintptr);
// 				goto loop;
// 			}
// 			goto error;
// 		}
// 	}

// 	retpc = pc;
// 	retfile = f->src;
// 	retline = funcline(f, pc-1);
// 	retbool = true;
// 	FLUSH(&retpc);
// 	FLUSH(&retfile);
// 	FLUSH(&retline);
// 	FLUSH(&retbool);
}
