Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

1279 lines (1186 sloc) 33.802 kb
#! winxed
// pirado.winxed
// Tests towards HLL-based pasm/pir compilers.
const int DEBUG = 0;
//**********************************************************************
const int PARROT_ARG_I = 0x00;
const int PARROT_ARG_S = 0x01;
const int PARROT_ARG_P = 0x02;
const int PARROT_ARG_N = 0x03;
const int PARROT_ARG_TYPE_MASK = 0x0F;
const int PARROT_ARG_CONSTANT = 0x10;
const int PARROT_ARG_IC = PARROT_ARG_I | PARROT_ARG_CONSTANT;
const int PARROT_ARG_SC = PARROT_ARG_S | PARROT_ARG_CONSTANT;
const int PARROT_ARG_PC = PARROT_ARG_P | PARROT_ARG_CONSTANT;
const int PARROT_ARG_NC = PARROT_ARG_N | PARROT_ARG_CONSTANT;
// Care to not collide with valid parrot values.
const int PARROT_ARG_UNKNOWN = 0x80000;
const int PARROT_JUMP_RELATIVE = 1;
const int FIXUP_TYPE_SUB = 1;
function typearg(string rtype)
{
switch (rtype) {
case 'I': return PARROT_ARG_I;
case 'S': return PARROT_ARG_S;
case 'N': return PARROT_ARG_N;
case 'P': return PARROT_ARG_P;
default: return -1;
}
}
function pirtype(string nametype)
{
switch (nametype) {
case 'int': return PARROT_ARG_I;
case 'string': return PARROT_ARG_S;
case 'num': return PARROT_ARG_N;
case 'pmc': return PARROT_ARG_P;
default: return -1;
}
}
//**********************************************************************
function iswhitespace(string c)
{
return indexof(" \t\n", c) > -1;
}
function isdigit(string c)
{
return indexof('0123456789', c) > -1;
}
function isidentstart(string c)
{
return indexof(
'abcdefghijklmnopqrstuvwxyz' +
'ABCDEFGHIJKLMNOPQRSTUVWXYZ' + '_',
c) > -1;
}
function isident(string c)
{
return indexof(
'abcdefghijklmnopqrstuvwxyz' +
'ABCDEFGHIJKLMNOPQRSTUVWXYZ' + '_' +
'0123456789',
c) > -1;
}
function auxgetchar(string l)
{
yield length(l);
for (string c in l)
yield c;
for (;;)
yield '';
}
//**********************************************************************
class Token
{
var strval;
var filename;
var line;
var pos;
function isop(string opstr) { return 0; }
function setstrval(var filepos, string val)
{
self.strval = val;
self.filename = filepos[0];
int line = filepos[1];
self.line = line;
int pos = filepos[2];
self.pos = pos;
}
function debdump() {
string s = self.strval;
s = string(self.filename) + ':' + string(self.line) + ':' + string(self.pos) + ':' + s;
return s;
}
}
class TokenComment : Token
{
function setcomment(var filepos)
{
self.setstrval(filepos, '# comment');
return self;
}
}
class TokenIdentifier : Token
{
function setid(var filepos, string str)
{
self.setstrval(filepos, str);
return self;
}
function getid() { return self.strval; }
}
class TokenInteger : Token
{
function setint(var filepos, string str)
{
self.setstrval(filepos, str);
return self;
}
function getint() { return int(self.strval); }
}
class TokenSingleQuoted : Token
{
function setsquoted(var filepos, string str)
{
self.setstrval(filepos, str);
return self;
}
function getstr() { return string(self.strval); }
}
class TokenRegister : Token
{
var type;
var num;
function setregister(var filepos, string type, int num)
{
self.setstrval(filepos, '$' + type + string(num));
self.type = type;
self.num = num;
return self;
}
function regtype() { return self.type; }
function regnum() { return self.num; }
}
class TokenOperator : Token
{
function setopname(var filepos, string str)
{
self.setstrval(filepos, str);
return self;
}
function isop(string opstr)
{
return opstr == self.strval;
}
}
//**********************************************************************
function ErrorAt(string msg, var token)
{
throw Error(msg + ' at ' + string(token.debdump()));
}
//**********************************************************************
class Line
{
var getchar_fun;
var filename;
var linenum;
var pos;
var pending;
function getchar()
{
string c;
var pending = self.pending;
if (pending == null)
throw Error('Line reader not initialized');
if (elements(pending) > 0) {
c = pending.pop();
}
else {
var get = self.getchar_fun;
if (get == null)
throw Error('Line reader not initialized');
c = get();
if (c != '')
self.pos++;
}
return c;
}
function ungetchar(string c)
{
if (length(c) > 0)
self.pending.push(c);
}
function scancomment(var filepos)
{
string c;
while ((c = self.getchar()) != "\n") ;
return new TokenComment().setcomment(filepos);
}
function scannum(var filepos, string c)
{
string n = c;
while (isdigit(c = self.getchar()))
n += c;
self.ungetchar(c);
return new TokenInteger().setint(filepos, n);
}
function scanident(var filepos, string c)
{
string id = c;
while (isident(c = self.getchar()))
id += c;
self.ungetchar(c);
return new TokenIdentifier().setid(filepos, id);
}
function scanregister(var filepos)
{
string c = self.getchar();
if (indexof("INSP", c) < 0)
throw Error("Invalid register");
string type = c;
string strnum = '';
while (isdigit(c = self.getchar()))
strnum += c;
if (strnum == '')
throw Error("Invalid register number");
int regnum = strnum;
self.ungetchar(c);
return new TokenRegister().setregister(filepos, type, regnum);
}
function scansinglequoted(var filepos)
{
string s;
string c;
while ((c = self.getchar()) != '' && c != "'")
s += c;
return new TokenSingleQuoted().setsquoted(filepos, s);
}
function scan()
{
var c;
var tokenlist = [];
while ((c = self.getchar()) != '') {
if (iswhitespace(c)) continue;
var filepos = [ self.filename, int(self.linenum), int(self.pos) ];
switch (c) {
case '#':
tokenlist.push(self.scancomment(filepos));
break;
case "'":
tokenlist.push(self.scansinglequoted(filepos));
break;
case '$':
tokenlist.push(self.scanregister(filepos));
break;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
tokenlist.push(self.scannum(filepos, c));
break;
default:
if (isidentstart(c))
tokenlist.push(self.scanident(filepos, c));
else
tokenlist.push(new TokenOperator().setopname(filepos, c));
}
}
return tokenlist;
}
function scanline(int linenum, string line)
{
using auxgetchar;
var getchar_f = clone(auxgetchar);
int n = getchar_f(line);
var tokenlist;
if (n) {
self.getchar_fun = getchar_f;
self.pending = [];
self.linenum = linenum;
self.pos = 0;
tokenlist = self.scan();
self.pending = null;
self.getchar_fun = null;
}
return tokenlist;
}
function setfilename(string filename)
{
self.filename = filename;
}
}
//**********************************************************************
class Arg
{
}
class ArgRegister
{
var regtype;
var regnum;
function type()
{
int regtype = self.regtype;
return regtype;
}
function initreg(int regtype, int regnum)
{
self.regtype = regtype;
self.regnum = regnum;
return self;
}
function num() { return int(self.regnum); }
function code() { return int(self.regnum); }
}
class ArgConstant
{
var regtype;
var cstindex;
function type()
{
int regtype = self.regtype;
return regtype | PARROT_ARG_CONSTANT;
}
function initconst(int regtype, int cstindex)
{
self.regtype = regtype;
self.cstindex = cstindex;
return self;
}
function index() { return self.cstindex; }
function code() { return int(self.cstindex); }
}
class ArgConstString
{
var value;
var cstindex;
function type() { return PARROT_ARG_SC; }
function initconststring(string value)
{
self.value = value;
self.cstindex = -1;
return self;
}
function put(var store)
{
int cstindex = store.pushconststring(self.value);
self.cstindex = cstindex;
}
function code()
{
int cstindex = self.cstindex;
if (cstindex == -1)
throw Error('Premature use of constant string');
return cstindex;
}
}
class ArgIdentifier
{
var idstr;
function type() { return PARROT_ARG_UNKNOWN; }
function initid(string name)
{
self.idstr = name;
return self;
}
function name() { return self.idstr; }
}
//**********************************************************************
function find_opcode(var inst, var args)
{
string opname = inst.getid();
int nargs = elements(args);
var oplib = new 'OpLib';
var ops = oplib.op_family(opname);
if (ops == null)
throw Error('No such op: ' + opname);
int numops = ops;
int iop;
for (iop = 0; iop < numops; ++iop) {
var op = ops[iop];
if (nargs != elements(op) )
continue;
int i;
for (i = 0; i < nargs; ++i) {
var arg = args[i];
int ptype = op[i];
int atype = arg.type();
if (atype != ptype) {
if (atype != PARROT_ARG_UNKNOWN || ! (arg instanceof ArgIdentifier))
break;
}
}
if (i == nargs)
break;
}
if (iop >= numops)
ErrorAt('No op with that args', inst);
var op = ops[iop];
return op;
}
//**********************************************************************
class GenItem
{
var codepos;
}
//**********************************************************************
class GenMark : GenItem
{
function bytelength() { return 0; }
function adjust(int codepos)
{
self.codepos = codepos;
}
function gencode(var dest) { }
}
//**********************************************************************
class GenOp : GenItem
{
var context;
var args;
var op;
function build(var context, var tokenlist)
{
self.context = context;
int ntokens = elements(tokenlist);
var args = [];
for (int i = 1; i < ntokens; ++i) {
var arg = tokenlist[i];
if ((i %% 2) == 0 && (arg.isop(',')) )
continue;
var argnew;
if (arg instanceof TokenRegister) {
int argt = typearg(arg.regtype());
argnew = new ArgRegister().initreg(argt, arg.regnum());
}
else if (arg instanceof TokenSingleQuoted) {
string argstr = arg.getstr();
argnew = new ArgConstString().initconststring(argstr);
}
else if (arg instanceof TokenInteger) {
int argint = arg.getint();
argnew = new ArgConstant().initconst(PARROT_ARG_I, argint);
}
else if (arg instanceof TokenIdentifier) {
string argname = arg.getid();
var local = context.getlocal(argname);
if (local != null) {
argnew = new ArgRegister().initreg(local['type'], local['regnum']);
}
else
argnew = new ArgIdentifier().initid(argname);
}
else
ErrorAt('Invalid arg', arg);
args.push(argnew);
}
self.args = args;
self.op = find_opcode(tokenlist[0], args);
}
function getargs() { return self.args; }
function bytelength()
{
return elements(self.op) + 1;
}
function adjust(int codepos)
{
self.codepos = codepos;
int jump = self.op.jump();
if (jump & PARROT_JUMP_RELATIVE) {
var args = self.args;
int nargs = elements(args);
if (nargs > 0) {
var last = args[nargs - 1];
if (last instanceof ArgIdentifier) {
int dest = self.context.getlabel(last.name());
if (DEBUG) say('relative at ', codepos, ' is ', dest - codepos);
var newarg = new ArgConstant().initconst(PARROT_ARG_I, dest - codepos);
args[nargs - 1] = newarg;
}
}
}
}
function gencode(var dest)
{
int opnum = self.op;
dest.pushop(opnum);
var args = self.args;
int nargs = elements(args);
for (int i = 0; i < nargs; ++i) {
var arg = args[i];
if (arg instanceof ArgConstString)
arg.put(dest);
dest.pushop(arg.code());
}
}
}
class GenLabel
{
var context;
var label;
function build(var context, var tokenlist)
{
self.context = context;
int ntokens = elements(tokenlist);
var ltoken = tokenlist[0];
if (! (tokenlist[0] instanceof TokenIdentifier))
ErrorAt('Bad label', ltoken);
self.label = ltoken.getid();
return self;
}
function bytelength() { return 0; }
function set(int pos)
{
if (DEBUG) say(self.label, ' set to ', pos);
self.context.setlabel(self.label, pos);
}
function adjust(int codepos) {}
function gencode(var dest) {}
}
// Base for call and return instructions
class WithArgs
{
var context;
var args;
function parseargs(var tokenlist)
{
var oper = tokenlist.shift();
if (!oper.isop('('))
ErrorAt('Unexpected operation', oper);
oper = tokenlist[0];
self.args = [];
if (oper.isop(')'))
oper = tokenlist.shift();
else {
do {
var arg = tokenlist.shift();
if (arg instanceof TokenInteger || arg instanceof TokenSingleQuoted) {
self.args.push(arg);
}
else
ErrorAt('Invalid argument list', arg);
} while ((oper = tokenlist.shift()).isop(','));
if (!oper.isop(')'))
ErrorAt('Invalid argument list', oper);
}
}
function argsbytelength()
{
return elements(self.args);
}
function genargspc(var dest)
{
int arglistv;
int n = elements(self.args);
if (n == 0)
arglistv = self.context.getzeroargs();
else {
var arglist = new 'FixedIntegerArray';
arglist =: n;
for (int i= 0; i < n; ++i) {
int type;
var arg = self.args[i];
if (arg instanceof TokenInteger)
type = PARROT_ARG_I;
else if (arg instanceof TokenSingleQuoted)
type = PARROT_ARG_S;
type = type | PARROT_ARG_CONSTANT;
arglist[i] = type;
}
arglistv = dest.pushconstpmc(arglist);
}
return arglistv;
}
function genargs(var dest)
{
int n = elements(self.args);
for (int i= 0; i < n; ++i) {
var arg = self.args[i];
int ival;
if (arg instanceof TokenInteger)
ival = arg.getint();
else if (arg instanceof TokenSingleQuoted) {
string strval = arg.getstr();
ival = self.context.pushconststring(strval);
}
dest.pushop(ival);
}
}
}
class GenReturn : WithArgs
{
function build(var context, var tokenlist)
{
self.context = context;
self.parseargs(tokenlist);
return self;
}
function bytelength()
{
int n = self.argsbytelength();
return 3 + n;
}
function adjust(int codepos) {}
function gencode(var dest)
{
var oplib = new 'OpLib';
var op = oplib['set_returns_pc'];
int opnum = op;
dest.pushop(opnum);
int arglistv = self.genargspc(dest);
dest.pushop(arglistv);
self.genargs(dest);
op = oplib['returncc'];
opnum = op;
dest.pushop(opnum);
}
}
class GenCallSub : WithArgs
{
var name;
var owner;
function build(var context, var tokenlist)
{
self.context = context;
self.owner = context.current_sub;
var subitem = tokenlist.shift();
string name;
if (subitem instanceof TokenIdentifier)
name = subitem.getid();
else if (subitem instanceof TokenSingleQuoted)
name = subitem.getstr();
else
ErrorAt('Invalid call', subitem);
self.name = name;
self.parseargs(tokenlist);
return self;
}
function bytelength()
{
int n = self.argsbytelength();
return 7 + n;
}
function adjust(int codepos)
{}
function gencode(var dest)
{
var oplib = new 'OpLib';
var op = oplib['set_args_pc'];
int opnum = op;
dest.pushop(opnum);
int arglistv = self.genargspc(dest);
dest.pushop(arglistv);
self.genargs(dest);
op = oplib['find_sub_not_null_p_sc'];
opnum = op;
dest.pushop(opnum);
int tempreg = self.owner.tempcaller();
dest.pushop(tempreg);
int nameindex = self.context.pushconststring(self.name);
dest.pushop(nameindex);
/*
op = oplib['get_results_pc'];
opnum = op;
dest.pushop(opnum);
dest.pushop(zeroargs);
*/
op = oplib['invokecc_p'];
opnum = op;
dest.pushop(opnum);
dest.pushop(tempreg);
}
}
function gen_item(var context, var tokenlist)
{
int ntokens = elements(tokenlist);
var item;
if (ntokens > 1 && tokenlist[1].isop(':'))
item = new GenLabel().build(context, tokenlist);
else if (ntokens > 1 && tokenlist[1].isop('(')) {
item = new GenCallSub().build(context, tokenlist);
}
else {
var inst = tokenlist[0];
switch (inst.getid()) {
case 'goto':
item = new GenOp();
item.context = context;
item.op = new 'OpLib'()['branch_ic'];
var args = [];
args.push(new ArgIdentifier().initid(tokenlist[1].getid()));
item.args = args;
break;
default:
item = new GenOp();
item.build(context, tokenlist);
}
}
return item;
}
//**********************************************************************
class BlockSub : GenItem
{
var name;
var args;
var locals;
var registers;
var regtempcall;
var startgen;
var endgen;
var main_flag;
function init(string subname, int startgen)
{
if (DEBUG) say(subname, ' ', startgen);
self.name = subname;
self.args = [];
self.locals = [];
self.startgen = startgen;
self.endgen = 0;
self.main_flag = 0;
int registers[] = [ 0, 0, 0, 0];
self.registers = registers;
}
function set_main()
{
self.main_flag =: 1;
}
function tempcaller()
{
int newreg;
if (self.regtempcall != null)
newreg = self.regtempcall;
else {
var registers = self.registers;
newreg = registers[PARROT_ARG_P];
self.regtempcall = newreg;
registers[PARROT_ARG_P] = newreg + 1;
}
if (DEBUG) say('tempcaller: ', newreg);
return newreg;
}
function addparam(string name, int type)
{
var registers = self.registers;
int newreg = registers[type];
registers[type] = newreg + 1;
var argdesc = { 'name': name, 'type': type, 'regnum': newreg };
self.args.push(argdesc);
}
function addlocal(string name, int type)
{
var registers = self.registers;
int newreg = registers[type];
registers[type] = newreg + 1;
var argdesc = { 'name': name, 'type': type, 'regnum': newreg };
self.locals.push(argdesc);
}
function getlocal(string name)
{
for (var arg in self.args)
if (arg['name'] == name)
return arg;
for (var local in self.locals)
if (local['name'] == name)
return local;
return null;
}
function bytelength()
{
var args = self.args;
int nargs = elements(args);
if (args == 0)
return 0;
else
return 2 + args;
}
function adjust(int codepos)
{
self.codepos = codepos;
}
function gencode(var dest)
{
var args = self.args;
int nargs = elements(args);
if (nargs > 0) {
var oplib = new 'OpLib';
var op = oplib['get_params_pc'];
int opnum = op;
var arglist = new 'FixedIntegerArray';
arglist =: nargs;
for (int i = 0; i < args; ++i) {
arglist[i] = args[i]['type'];
}
int arglistv = dest.pushconstpmc(arglist);
dest.pushop(opnum);
dest.pushop(arglistv);
for (int i = 0; i < args; ++i) {
int regnum = args[i]['regnum'];
dest.pushop(regnum);
}
}
}
}
//**********************************************************************
const int FLAG_PASM_MODE = 1;
class Generator
{
var flags;
var current_sub;
var sub_list;
var segname;
var packfile;
var dir;
var constseg;
var zeroargs;
var byteseg;
var nextconst;
var nextcode;
var labels;
var opgenlist;
function init[vtable]()
{
self.flags = 0;
self.sub_list = [];
}
function modepasm()
{
int flags = int(self.flags) | FLAG_PASM_MODE;
self.flags =: flags;
}
function checkpirmode(var inst)
{
if (int(self.flags) & FLAG_PASM_MODE)
throw ErrorAt('Invalid in PASM mode', inst);
}
function initialize(string segname)
{
var packfile = new 'Packfile';
var dir = packfile.get_directory();
var constseg = new 'PackfileConstantTable';
int cstindex = 0;
constseg[cstindex++] = getinterp();
dir['CONSTANT_' + segname] = constseg;
var byteseg = new 'PackfileRawSegment';
self.segname = segname;
self.packfile = packfile;
self.dir = dir;
self.constseg = constseg;
self.byteseg = byteseg;
self.nextconst = cstindex;
self.nextcode = 0;
self.labels = {};
self.opgenlist = [];
}
function setlabel(string labelstr, int pos)
{
if (DEBUG) say('set label ', labelstr, ' to ', pos);
// if (self.labels[labelstr] == null)
// throw Error('Label already exists');
self.labels[labelstr] = pos;
}
function getlabel(string labelstr)
{
int pos = self.labels[labelstr];
return pos;
}
function tempcaller()
{
if (self.current_sub != null)
return self.current_sub.tempcaller();
return -1;
}
function getlocal(string name)
{
if (self.current_sub != null)
return self.current_sub.getlocal(name);
return null;
}
function pushop(int opnum)
{
int nextcode = self.nextcode;
self.byteseg[nextcode++] = opnum;
self.nextcode =: nextcode;
}
function pushconststring(string value)
{
int nextconst = self.nextconst;
int result = nextconst;
self.constseg[nextconst++] = value;
self.nextconst =: nextconst;
return result;
}
function pushconstpmc(var value)
{
int nextconst = self.nextconst;
int result = nextconst;
self.constseg[nextconst++] = value;
self.nextconst =: nextconst;
return result;
}
function getzeroargs()
{
int zeroargsindex;
var zeroargs = self.zeroargs;
if (zeroargs == null) {
var zeroargspmc = new 'FixedIntegerArray';
zeroargsindex = self.pushconstpmc(zeroargspmc);
zeroargs = zeroargsindex;
self.zeroargs = zeroargs;
}
else
zeroargsindex = zeroargs;
return zeroargsindex;
}
function parsesub(var inst, var tokenlist)
{
self.checkpirmode(inst);
if (self.current_sub != null)
throw ErrorAt('.sub cannot nest', inst);
var subitem = tokenlist.shift();
string subname;
if (subitem instanceof TokenIdentifier)
subname = subitem.getid();
else if (subitem instanceof TokenSingleQuoted)
subname = subitem.getstr();
int is_main = 0;
while (elements(tokenlist) > 0) {
var item = tokenlist.shift();
if (item.isop(':')) {
var flag = tokenlist.shift();
var flagname = flag.getid();
switch (flagname) {
case 'main':
is_main = 1;
break;
default:
ErrorAt('Invalid flag', flag);
}
}
else
ErrorAt('Invalid sub flag', item);
}
var blocksub = new BlockSub();
int startgen = elements(self.opgenlist);
blocksub.init(subname, startgen);
self.opgenlist.push(blocksub);
if (is_main)
blocksub.set_main();
self.current_sub = blocksub;
}
function parseparam(var inst, var tokenlist)
{
var typetok = tokenlist.shift();
if (! (typetok instanceof TokenIdentifier))
ErrorAt("Invalid param type", typetok);
string nametype = typetok.getid();
if (DEBUG) say(nametype);
int type = pirtype(nametype);
if (type < 0)
ErrorAt('Invalid params type', typetok);
var cursub = self.current_sub;
if (cursub == null)
ErrorAt('param out of sub', inst);
if (cursub.startgen + 1 != elements(self.opgenlist))
ErrorAt('param after code', inst);
var nametok = tokenlist.shift();
string name = nametok.getid();
cursub.addparam(name, type);
}
function parselocal(var inst, var tokenlist)
{
var typetok = tokenlist.shift();
if (! (typetok instanceof TokenIdentifier))
ErrorAt("Invalid param type", typetok);
string nametype = typetok.getid();
if (DEBUG) say(nametype);
int type = pirtype(nametype);
if (type < 0)
ErrorAt('Invalid params type', typetok);
var cursub = self.current_sub;
if (cursub == null)
ErrorAt('param out of sub', inst);
if (cursub.startgen + 1 != elements(self.opgenlist))
ErrorAt('param after code', inst);
var nametok = tokenlist.shift();
string name = nametok.getid();
cursub.addlocal(name, type);
}
function parseend(var inst, var tokenlist)
{
self.checkpirmode(inst);
self.current_sub.endgen = elements(self.opgenlist);
self.opgenlist.push(new GenMark());
self.sub_list.push(self.current_sub);
self.current_sub = null;
}
function parse(var tokenlist)
{
var inst = tokenlist[0];
int ntokens = elements(tokenlist);
int curpos = self.nextcode;
if (inst.isop('.')) {
tokenlist.shift();
inst = tokenlist.shift();
if (! (inst instanceof TokenIdentifier))
throw ErrorAt('No directive', inst);
switch (inst.getid()) {
case 'sub':
self.parsesub(inst, tokenlist);
break;
case 'end':
if (self.current_sub == null)
throw ErrorAt('.end outside sub', inst);
self.parseend(inst, tokenlist);
break;
case 'return':
var opgen = new GenReturn().build(self, tokenlist);
self.opgenlist.push(opgen);
break;
case 'param':
self.parseparam(inst, tokenlist);
break;
case 'local':
self.parselocal(inst, tokenlist);
break;
default:
ErrorAt('No such directive', inst);
}
}
else if (inst instanceof TokenIdentifier) {
var opgen = gen_item(self, tokenlist);
self.opgenlist.push(opgen);
}
else if (inst instanceof TokenSingleQuoted && ntokens > 1 && tokenlist[1].isop('(')) {
var opgen = new GenCallSub().build(self, tokenlist);
self.opgenlist.push(opgen);
}
else
throw ErrorAt('No instruction', inst);
}
function writefile(string filename)
{
string segname = self.segname;
var dir = self.dir;
dir['BYTECODE_' + segname] = self.byteseg;
// Generate sub fixups.
var fixups = new 'PackfileFixupTable';
dir['FIXUP_' + segname] = fixups;
int nsubs = elements(self.sub_list);
int fixuppos = 0;
if (nsubs > 0) {
for (var blocksub in self.sub_list) {
string name = blocksub.name;
if (DEBUG) say(name);
int startgen = blocksub.startgen;
int startpos = self.opgenlist[startgen].codepos;
if (DEBUG) say(startpos);
int endgen = blocksub.endgen;
int endpos = self.opgenlist[endgen].codepos;
if (DEBUG) say(endpos);
var registers = blocksub.registers;
int registers_used[4];
for (int i = 0; i < 4; ++i) {
int r = registers[i];
if (r < 2) r = 2;
registers_used[i] = r;
}
var subpmc = new 'Sub'({
"name" : name,
"subid" : name,
"ns_entry_name" : name,
"vtable_index" : -1,
"start_offs" : startpos,
"end_offs" : endpos,
// Set registers used to a number reasonable for little
// tests, for a now.
"n_regs_used": registers_used
});
int subconst = self.pushconstpmc(subpmc);
if (blocksub.main_flag)
self.constseg.set_main(subconst);
var fixupsub = new 'PackfileFixupEntry';
fixupsub =: name;
fixupsub =: subconst;
fixupsub.set_type(FIXUP_TYPE_SUB);
fixups[fixuppos++] = fixupsub;
}
}
else {
// Temporary
// Create a fake main sub for tests of PASM mode.
string fakename = 'fakemain';
var fakesub = new 'Sub'({
"name" : fakename,
"subid" : fakename,
"ns_entry_name" : fakename,
"start_offs" : 0,
"end_offs" : self.nextcode,
"n_regs_used": [ 8, 8, 8, 8 ]
});
int fakeconst = self.pushconstpmc(fakesub);
var fixupfake = new 'PackfileFixupEntry';
fixupfake =: fakename;
fixupfake =: fakeconst;
fixupfake.set_type(2);
fixups[fixuppos++] = fixupfake;
}
dir['BYTECODE_' + segname + '_ANN'] = new 'PackfileAnnotations';
var packfile = self.packfile;
string rawdata = packfile;
if (DEBUG) say('About to write');
var handle = new 'FileHandle'.open(filename, 'wb');
if (DEBUG) say('Writing');
handle.print(rawdata);
handle.close();
if (DEBUG) say('Done');
}
function generate()
{
int nitems = elements(self.opgenlist);
int codepos = 0;
for (int i = 0; i < nitems; ++i) {
var item = self.opgenlist[i];
if (item instanceof GenLabel)
item.set(codepos);
int l = item.bytelength();
codepos += l;
}
if (DEBUG) say('codesize: ', codepos);
codepos = 0;
for (int i = 0; i < nitems; ++i) {
var item = self.opgenlist[i];
item.adjust(codepos);
int l = item.bytelength();
codepos += l;
}
if (DEBUG) say('codesize: ', codepos);
codepos = 0;
for (int i = 0; i < nitems; ++i) {
var item = self.opgenlist[i];
item.gencode(self);
}
}
}
//**********************************************************************
function main(argv)
{
string filename = argv[1];
var l = new Line();
l.setfilename(filename);
var file = open(filename);
var line;
int numline = 0;
int is_pasm = 0;
string pbcfilename = filename;
{
int l = length(filename);
if (l > 4 && substr(filename, l - 5) == '.pasm') {
is_pasm = 1;
pbcfilename = substr(pbcfilename, 0, l - 5);
}
else if (l > 3 && substr(filename, l - 4) == '.pir')
pbcfilename = substr(pbcfilename, 0, l - 4);
pbcfilename += '.pbc';
}
var gen = new Generator();
if (is_pasm)
gen.modepasm();
gen.initialize(filename);
while ((line = file.readline()) != '') {
++numline;
var tokenlist = l.scanline(numline, line);
if (tokenlist != null && elements(tokenlist) > 0) {
if (DEBUG) {
for (var token in tokenlist)
print(token.debdump());
say();
}
if (tokenlist[0] instanceof TokenComment)
continue;
gen.parse(tokenlist);
}
}
int nopgen = gen.opgenlist;
if (DEBUG) say('Items: ', nopgen);
gen.generate();
if (DEBUG) say(pbcfilename);
gen.writefile(pbcfilename);
}
// End
Jump to Line
Something went wrong with that request. Please try again.