#include <u.h>
#include <libc.h>
#include "dat.h"
#include "fns.h"
Inst
mkInst(char *op, int ne, ...)
{
int i;
va_list arg;
Inst inst;
zero(inst);
inst.op = op;
inst.ne = ne;
va_start(arg, ne);
for(i=0; i<ne; i++)
inst.e[i] = va_arg(arg, Expr);
va_end(arg);
return inst;
}
Expr
mkExprReg8(Reg8 r8)
{
Expr e;
zero(e);
e.ty = ExReg8;
e.r8 = r8;
return e;
}
Expr
mkExprReg32(Reg32 r32)
{
Expr e;
zero(e);
e.ty = ExReg32;
e.r32 = r32;
return e;
}
Expr
mkExprConst(u32int i)
{
Expr e;
zero(e);
e.ty = ExConst;
e.i = i;
return e;
}
Expr
mkExprMem(Mem m)
{
Expr e;
zero(e);
e.ty = ExMem;
e.m = m;
return e;
}
Mem
mkMem(Reg32 base, u32int disp, Reg32 index, u32int scale)
{
Mem m;
zero(m);
m.disp = disp;
m.base = base;
m.index = index;
m.scale = scale;
return m;
}
/*
* Custom allocators to avoid malloc overheads on small objects.
* We never free these. (See below.)
*/
typedef struct Stringtab Stringtab;
struct Stringtab {
Stringtab *link;
char *str;
};
static Stringtab*
taballoc(void)
{
static Stringtab *t;
static uint nt;
if(nt == 0){
t = malloc(64*sizeof(Stringtab));
if(t == 0)
sysfatal("out of memory");
nt = 64;
}
nt--;
return t++;
}
static char*
xstrdup(char *s)
{
char *r;
int len;
static char *t;
static int nt;
len = strlen(s)+1;
if(len >= 8192)
sysfatal("strdup big string");
if(nt < len){
t = malloc(8192);
if(t == 0)
sysfatal("out of memory");
nt = 8192;
}
r = t;
t += len;
nt -= len;
strcpy(r, s);
return r;
}
/*
* Return a uniquely allocated copy of a string.
* Don't free these -- they stay in the table for the
* next caller who wants that particular string.
* String comparison can be done with pointer comparison
* if you know both strings are atoms.
*/
static Stringtab *stab[1024];
static uint
hash(char *s)
{
uint h;
uchar *p;
h = 0;
for(p=(uchar*)s; *p; p++)
h = h*37 + *p;
return h;
}
char*
atom(char *str)
{
uint h;
Stringtab *tab;
h = hash(str) % nelem(stab);
for(tab=stab[h]; tab; tab=tab->link)
if(strcmp(str, tab->str) == 0)
return tab->str;
tab = taballoc();
tab->str = xstrdup(str);
tab->link = stab[h];
stab[h] = tab;
return tab->str;
}
|