<commit_before>#include <u.h>
#include <ds/ds.h>
#include <cc/cc.h>
#include <gc/gc.h>

static void expr(Node *);
static void stmt(Node *);
static void store(CTy *);

char    *intargregs[] = {"rdi", "rsi", "rdx", "rcx", "r8", "r9"};
int      stackoffset;
StkSlot *memretptr;

static FILE *o;

void
emitinit(FILE *out)
{
	o = out;
}

static void
out(char *fmt, ...)
{
	va_list va;

	va_start(va, fmt);
	if(vfprintf(o, fmt, va) < 0)
		errorf("Error printing\n");
	va_end(va);
}

static void
outi(char *fmt, ...)
{
	va_list va;

	va_start(va, fmt);
	fprintf(o, "  ");
	if(vfprintf(o, fmt, va) < 0)
		errorf("Error printing\n");
	va_end(va);
}

static void
block(Node *n)
{
	Vec *v;
	int  i;

	v = n->Block.stmts;
	for(i = 0; i < v->len ; i++) {
		stmt(vecget(v, i));
	}
}

static void
calcslotoffsets(Node *f)
{
	int i, tsz, curoffset;
	StkSlot *s;

	curoffset = 0;
	for(i = 0; i < f->Func.stkslots->len; i++) {
		s = vecget(f->Func.stkslots, i);
		tsz = s->size;
		/* This allows us to just copy params which have had the size rounded up. */
		if(tsz < 8)
			tsz = 8;
		else if(tsz < 16)
			tsz = 16;
		curoffset += tsz;
		if(curoffset % s->align)
			curoffset = (curoffset - (curoffset % s->align) + s->align);
		s->offset = -curoffset;
	}
	if(curoffset % 16)
		curoffset = (curoffset - (curoffset % 16) + 16);
	f->Func.localsz = curoffset;
}

static void
pushq(char *reg)
{
	stackoffset += 8;
	outi("pushq %%%s\n", reg);
}

static void
popq(char *reg)
{
	stackoffset -= 8;
	outi("popq %%%s\n", reg);
}

static void
func(Node *f)
{
	Vec *v;
	Sym *sym;
	int  i;
	
	calcslotoffsets(f);
	out("\n");
	out(".text\n");
	out(".globl %s\n", f->Func.name);
	out("%s:\n", f->Func.name);
	outi("pushq %%rbp\n");
	outi("movq %%rsp, %%rbp\n");
	if (f->Func.localsz)
		outi("sub $%d, %%rsp\n", f->Func.localsz);
	v = f->Func.params;
	for(i = 0; i < v->len; i++) {
		sym = vecget(v, i);
		if(!isitype(sym->type) && !isptr(sym->type))
			errorposf(&f->pos, "unimplemented arg type");
		if(i < 6) {
			outi("movq %%%s, %d(%%rbp)\n", intargregs[i], sym->Local.slot->offset);
		} else {
			outi("movq %d(%%rbp), %%rcx\n", 16 + 8 * (i - 6));
			outi("leaq %d(%%rbp), %%rax\n", sym->Local.slot->offset);
			store(sym->type);
		}
	}
	block(f->Func.body);
	outi("leave\n");
	outi("ret\n");
}


static void
call(Node *n)
{
	int i, nargs, nintargs, cleanup;
	Vec  *args;
	Node *arg;

	args = n->Call.args;
	i = nargs = args->len;
	/* Push args in reverse order */
	while(i-- != 0) {
		arg = vecget(args, i);
		if(!isitype(arg->type) && !isptr(arg->type))
			errorf("unimplemented arg type.");
		expr(arg);
		outi("pushq %%rax\n");
	}
	nintargs = nargs;
	if(nintargs > 6)
		nintargs = 6;
	for(i = 0; i < nintargs; i++)
		out("popq %%%s\n", intargregs[i]);
	expr(n->Call.funclike);
	outi("call *%%rax\n");
	cleanup = 8 * (nargs - nintargs);
	if(cleanup)
		outi("add $%d, %%rsp\n", cleanup);
}

static void
ereturn(Node *r)
{
	CTy *ty;
	
	ty = r->Return.expr->type;<commit_msg>track stack more accurately<commit_after>#include <u.h>
#include <ds/ds.h>
#include <cc/cc.h>
#include <gc/gc.h>

static void expr(Node *);
static void stmt(Node *);
static void store(CTy *);

char    *intargregs[] = {"rdi", "rsi", "rdx", "rcx", "r8", "r9"};
int      stackoffset;
StkSlot *memretptr;

static FILE *o;

void
emitinit(FILE *out)
{
	o = out;
}

static void
out(char *fmt, ...)
{
	va_list va;

	va_start(va, fmt);
	if(vfprintf(o, fmt, va) < 0)
		errorf("Error printing\n");
	va_end(va);
}

static void
outi(char *fmt, ...)
{
	va_list va;

	va_start(va, fmt);
	fprintf(o, "  ");
	if(vfprintf(o, fmt, va) < 0)
		errorf("Error printing\n");
	va_end(va);
}

static void
block(Node *n)
{
	Vec *v;
	int  i;

	v = n->Block.stmts;
	for(i = 0; i < v->len ; i++) {
		stmt(vecget(v, i));
	}
}

static void
calcslotoffsets(Node *f)
{
	int i, tsz, curoffset;
	StkSlot *s;

	curoffset = 0;
	for(i = 0; i < f->Func.stkslots->len; i++) {
		s = vecget(f->Func.stkslots, i);
		tsz = s->size;
		/* This allows us to just copy params which have had the size rounded up. */
		if(tsz < 8)
			tsz = 8;
		else if(tsz < 16)
			tsz = 16;
		curoffset += tsz;
		if(curoffset % s->align)
			curoffset = (curoffset - (curoffset % s->align) + s->align);
		s->offset = -curoffset;
	}
	if(curoffset % 16)
		curoffset = (curoffset - (curoffset % 16) + 16);
	f->Func.localsz = curoffset;
}

static void
pushq(char *reg)
{
	stackoffset += 8;
	outi("pushq %%%s\n", reg);
}

static void
popq(char *reg)
{
	stackoffset -= 8;
	outi("popq %%%s\n", reg);
}

static void
func(Node *f)
{
	Vec *v;
	Sym *sym;
	int  i;
	
	calcslotoffsets(f);
	out("\n");
	out(".text\n");
	out(".globl %s\n", f->Func.name);
	out("%s:\n", f->Func.name);
	pushq("rbp");
	outi("movq %%rsp, %%rbp\n");
	if (f->Func.localsz) {
		outi("sub $%d, %%rsp\n", f->Func.localsz);
		stackoffset += f->Func.localsz;
	}
	v = f->Func.params;
	for(i = 0; i < v->len; i++) {
		sym = vecget(v, i);
		if(!isitype(sym->type) && !isptr(sym->type))
			errorposf(&f->pos, "unimplemented arg type");
		if(i < 6) {
			outi("movq %%%s, %d(%%rbp)\n", intargregs[i], sym->Local.slot->offset);
		} else {
			outi("movq %d(%%rbp), %%rcx\n", 16 + 8 * (i - 6));
			outi("leaq %d(%%rbp), %%rax\n", sym->Local.slot->offset);
			store(sym->type);
		}
	}
	block(f->Func.body);
	outi("leave\n");
	outi("ret\n");
}


static void
call(Node *n)
{
	int i, nargs, nintargs, cleanup;
	Vec  *args;
	Node *arg;

	args = n->Call.args;
	i = nargs = args->len;
	/* Push args in reverse order */
	while(i-- != 0) {
		arg = vecget(args, i);
		if(!isitype(arg->type) && !isptr(arg->type))
			errorf("unimplemented arg type.");
		expr(arg);
		pushq("rax");
	}
	nintargs = nargs;
	if(nintargs > 6)
		nintargs = 6;
	for(i = 0; i < nintargs; i++)
		popq(intargregs[i]);
	expr(n->Call.funclike);
	outi("call *%%rax\n");
	cleanup = 8 * (nargs - nintargs);
	if(cleanup) {
		outi("add $%d, %%rsp\n", cleanup);
		stackoffset -= cleanup;
	}
}

static void
ereturn(Node *r)
{
	CTy *ty;
	
	ty = r->Return.expr->type;
{'fraction_non_alphanumeric': 0.22663080026899798, 'fraction_numerical': 0.010759919300605245, 'mean_word_length': 3.3742647058823527, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 80, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1828391', 'n_tokens_mistral': 2973, 'n_tokens_neox': 2771, 'n_words': 614}