// 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 <u.h>
#include <libc.h>
#include "go.h"

/*
 * architecture-independent object file output
 */

static	void	dumpglobls(void);

enum
{
	ArhdrSize = 60
};

static void
formathdr(char *arhdr, char *name, vlong size)
{
	snprint(arhdr, ArhdrSize, "%-16s%-12d%-6d%-6d%-8o%-10lld`",
		name, 0, 0, 0, 0644, size);
	arhdr[ArhdrSize-1] = '\n'; // overwrite \0 written by snprint
}

void
dumpobj(void)
{
	NodeList *externs, *tmp;
	char arhdr[ArhdrSize];
	vlong startobj, size;
	Sym *zero;

	bout = Bopen(outfile, OWRITE);
	if(bout == nil) {
		flusherrors();
		print("can't create %s: %r\n", outfile);
		errorexit();
	}

	startobj = 0;
	if(writearchive) {
		Bwrite(bout, "!<arch>\n", 8);
		memset(arhdr, 0, sizeof arhdr);
		Bwrite(bout, arhdr, sizeof arhdr);
		startobj = Boffset(bout);
	}
	Bprint(bout, "go object %s %s %s %s\n", getgoos(), getgoarch(), getgoversion(), expstring());
	dumpexport();
	
	if(writearchive) {
		Bflush(bout);
		size = Boffset(bout) - startobj;
		if(size&1)
			Bputc(bout, 0);
		Bseek(bout, startobj - ArhdrSize, 0);
		formathdr(arhdr, "__.PKGDEF", size);
		Bwrite(bout, arhdr, ArhdrSize);
		Bflush(bout);

		Bseek(bout, startobj + size + (size&1), 0);
		memset(arhdr, 0, ArhdrSize);
		Bwrite(bout, arhdr, ArhdrSize);
		startobj = Boffset(bout);
		Bprint(bout, "go object %s %s %s %s\n", getgoos(), getgoarch(), getgoversion(), expstring());
	}

	Bprint(bout, "\n!\n");

	externs = nil;
	if(externdcl != nil)
		externs = externdcl->end;

	dumpglobls();
	dumptypestructs();

	// Dump extra globals.
	tmp = externdcl;
	if(externs != nil)
		externdcl = externs->next;
	dumpglobls();
	externdcl = tmp;

	zero = pkglookup("zerovalue", runtimepkg);
	ggloblsym(zero, zerosize, 1, 1);

	dumpdata();
	linkwriteobj(ctxt, bout);

	if(writearchive) {
		Bflush(bout);
		size = Boffset(bout) - startobj;
		if(size&1)
			Bputc(bout, 0);
		Bseek(bout, startobj - ArhdrSize, 0);
		snprint(namebuf, sizeof namebuf, "_go_.%c", thechar);
		formathdr(arhdr, namebuf, size);
		Bwrite(bout, arhdr, ArhdrSize);
	}
	Bterm(bout);
}

static void
dumpglobls(void)
{
	Node *n;
	NodeList *l;

	// add globals
	for(l=externdcl; l; l=l->next) {
		n = l->n;
		if(n->op != ONAME)
			continue;

		if(n->type == T)
			fatal("external %N nil type\n", n);
		if(n->class == PFUNC)
			continue;
		if(n->sym->pkg != localpkg)
			continue;
		dowidth(n->type);

		ggloblnod(n);
	}
	
	for(l=funcsyms; l; l=l->next) {
		n = l->n;
		dsymptr(n->sym, 0, n->sym->def->shortname->sym, 0);
		ggloblsym(n->sym, widthptr, 1, 1);
	}
	
	// Do not reprocess funcsyms on next dumpglobls call.
	funcsyms = nil;
}

void
Bputname(Biobuf *b, LSym *s)
{
	Bwrite(b, s->name, strlen(s->name)+1);
}

LSym*
linksym(Sym *s)
{
	char *p;

	if(s == nil)
		return nil;
	if(s->lsym != nil)
		return s->lsym;
	if(isblanksym(s))
		s->lsym = linklookup(ctxt, "_", 0);
	else {
		p = smprint("%s.%s", s->pkg->prefix, s->name);
		s->lsym = linklookup(ctxt, p, 0);
		free(p);
	}
	return s->lsym;	
}

int
duintxx(Sym *s, int off, uint64 v, int wid)
{
	// Update symbol data directly instead of generating a
	// DATA instruction that liblink will have to interpret later.
	// This reduces compilation time and memory usage.
	off = rnd(off, wid);
	return setuintxx(ctxt, linksym(s), off, v, wid);
}

int
duint8(Sym *s, int off, uint8 v)
{
	return duintxx(s, off, v, 1);
}

int
duint16(Sym *s, int off, uint16 v)
{
	return duintxx(s, off, v, 2);
}

int
duint32(Sym *s, int off, uint32 v)
{
	return duintxx(s, off, v, 4);
}

int
duint64(Sym *s, int off, uint64 v)
{
	return duintxx(s, off, v, 8);
}

int
duintptr(Sym *s, int off, uint64 v)
{
	return duintxx(s, off, v, widthptr);
}

Sym*
stringsym(char *s, int len)
{
	static int gen;
	Sym *sym;
	int off, n, m;
	struct {
		Strlit lit;
		char buf[110];
	} tmp;
	Pkg *pkg;

	if(len > 100) {
		// huge strings are made static to avoid long names
		snprint(namebuf, sizeof(namebuf), ".gostring.%d", ++gen);
		pkg = localpkg;
	} else {
		// small strings get named by their contents,
		// so that multiple modules using the same string
		// can share it.
		tmp.lit.len = len;
		memmove(tmp.lit.s, s, len);
		tmp.lit.s[len] = '\0';
		snprint(namebuf, sizeof(namebuf), "\"%Z\"", &tmp.lit);
		pkg = gostringpkg;
	}
	sym = pkglookup(namebuf, pkg);
	
	// SymUniq flag indicates that data is generated already
	if(sym->flags & SymUniq)
		return sym;
	sym->flags |= SymUniq;
	sym->def = newname(sym);

	off = 0;
	
	// string header
	off = dsymptr(sym, off, sym, widthptr+widthint);
	off = duintxx(sym, off, len, widthint);
	
	// string data
	for(n=0; n<len; n+=m) {
		m = 8;
		if(m > len-n)
			m = len-n;
		off = dsname(sym, off, s+n, m);
	}
	off = duint8(sym, off, 0);  // terminating NUL for runtime
	off = (off+widthptr-1)&~(widthptr-1);  // round to pointer alignment
	ggloblsym(sym, off, 1, 1);

	return sym;	
}

void
slicebytes(Node *nam, char *s, int len)
{
	int off, n, m;
	static int gen;
	Sym *sym;

	snprint(namebuf, sizeof(namebuf), ".gobytes.%d", ++gen);
	sym = pkglookup(namebuf, localpkg);
	sym->def = newname(sym);

	off = 0;
	for(n=0; n<len; n+=m) {
		m = 8;
		if(m > len-n)
			m = len-n;
		off = dsname(sym, off, s+n, m);
	}
	ggloblsym(sym, off, 0, 0);
	
	if(nam->op != ONAME)
		fatal("slicebytes %N", nam);
	off = nam->xoffset;
	off = dsymptr(nam->sym, off, sym, 0);
	off = duintxx(nam->sym, off, len, widthint);
	duintxx(nam->sym, off, len, widthint);
}
