From ad547a6b5986815fda458221149728d9d9ab1d87 Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Thu, 25 Feb 2021 19:22:25 +0000 Subject: restore Build,TODO from r57911 git-svn-id: svn://tug.org/texlive/trunk@57915 c570f23f-e606-0410-a88d-b1316a301751 --- Build/source/utils/asymptote/coder.cc | 376 ++++++++++++++++++++++++++++++++++ 1 file changed, 376 insertions(+) create mode 100644 Build/source/utils/asymptote/coder.cc (limited to 'Build/source/utils/asymptote/coder.cc') diff --git a/Build/source/utils/asymptote/coder.cc b/Build/source/utils/asymptote/coder.cc new file mode 100644 index 00000000000..1beb3b58606 --- /dev/null +++ b/Build/source/utils/asymptote/coder.cc @@ -0,0 +1,376 @@ +/***** + * coder.cc + * Andy Hammerlindl 2004/11/06 + * + * Handles encoding of syntax into programs. It's methods are called by + * abstract syntax objects during translation to construct the virtual machine + * code. + *****/ + +#include + +#include "errormsg.h" +#include "coder.h" +#include "genv.h" +#include "entry.h" +#include "builtin.h" + +using namespace sym; +using namespace types; + +namespace trans { + +namespace { +function *inittype(); +function *bootuptype(); +} + +vm::lambda *newLambda(string name) { + assert(!name.empty()); + vm::lambda *l = new vm::lambda; +#ifdef DEBUG_FRAME + l->name = name; +#endif + return l; +} + + +// Used purely for global variables and static code blocks of file +// level modules. +coder::coder(position pos, string name, modifier sord) +#if SIMPLE_FRAME + : level(frame::indirect_frame(name)), +#else + : level(new frame(name, 0, 0)), +#endif + recordLevel(0), + recordType(0), + isCodelet(false), + l(newLambda(name)), + funtype(bootuptype()), + parent(0), + sord(sord), + perm(DEFAULT_PERM), + program(new vm::program), + curPos(pos) +{ + sord_stack.push(sord); +} + +// Defines a new function environment. +coder::coder(position pos, string name, function *t, coder *parent, + modifier sord, bool reframe) + : level(reframe ? new frame(name, + parent->getFrame(), + t->sig.getNumFormals()) : + parent->getFrame()), + recordLevel(parent->recordLevel), + recordType(parent->recordType), + isCodelet(!reframe), + l(newLambda(name)), + funtype(t), + parent(parent), + sord(sord), + perm(DEFAULT_PERM), + program(new vm::program), + curPos(pos) +{ + sord_stack.push(sord); +} + +// Start encoding the body of the record. The function being encoded +// is the record's initializer. +coder::coder(position pos, record *t, coder *parent, modifier sord) + : level(t->getLevel()), + recordLevel(t->getLevel()), + recordType(t), + isCodelet(false), + l(t->getInit()), + funtype(inittype()), + parent(parent), + sord(sord), + perm(DEFAULT_PERM), + program(new vm::program), + curPos(pos) +{ + sord_stack.push(sord); +} + +coder coder::newFunction(position pos, string name, function *t, modifier sord) +{ + return coder(pos, name, t, this, sord); +} + +coder coder::newCodelet(position pos) +{ + return coder(pos, "", new function(primVoid()), this, + DEFAULT_DYNAMIC, false); +} + +record *coder::newRecord(symbol id) +{ + frame *underlevel = getFrame(); + + frame *level = new frame(id, underlevel, 0); + + record *r = new record(id, level); + + return r; +} + +coder coder::newRecordInit(position pos, record *r, modifier sord) +{ + return coder(pos, r, this, sord); +} + +#ifdef DEBUG_BLTIN +void assertBltinLookup(inst::opcode op, item it) +{ + if (op == inst::builtin) { + string name=lookupBltin(vm::get(it)); + assert(!name.empty()); + } +} +#endif + + +void coder::encodePop() +{ + if (isStatic() && !isTopLevel()) { + assert(parent); + parent->encodePop(); + } + else { +#ifdef COMBO + vm::program::label end = program->end(); + --end; + inst& lastInst = *end; + if (lastInst.op == inst::varsave) { + lastInst.op = inst::varpop; + return; + } + if (lastInst.op == inst::fieldsave) { + lastInst.op = inst::fieldpop; + return; + } + // TODO: push+pop into no op. +#endif + + // No combo applicable. Just encode a usual pop. + encode(inst::pop); + } +} + + +bool coder::encode(frame *f) +{ + frame *toplevel = getFrame(); + + if (f == 0) { + encode(inst::constpush,(item)0); + return true; + } + else if (f == toplevel) { + encode(inst::pushclosure); + return true; + } + else { + encode(inst::varpush,toplevel->parentIndex()); + return encode(f, toplevel->getParent()); + } +} + +bool coder::encode(frame *dest, frame *top) +{ + if (dest == 0) { + // Change to encodePop? + encode(inst::pop); + encode(inst::constpush,(item)0); + } + else { + frame *level = top; + while (level != dest) { + if (level == 0) { + // Frame request was in an improper scope. + return false; + } + + encode(inst::fieldpush, level->parentIndex()); + + level = level->getParent(); + } + } + + //cerr << "succeeded\n"; + return true; +} + +vm::program::label coder::encodeEmptyJump(inst::opcode op) +{ + // Get the end position before encoding the label. Once encoded, this will + // point to the instruction. + vm::program::label pos = program->end(); + + encode(op); + + return pos; +} + +void replaceEmptyJump(vm::program::label from, vm::program::label to) +{ + from->ref = to; +} + +label coder::defNewLabel() +{ + if (isStatic()) + return parent->defNewLabel(); + + label l = new label_t(); + assert(!l->location.defined()); + assert(!l->firstUse.defined()); + return defLabel(l); +} + +label coder::defLabel(label label) +{ + if (isStatic()) + return parent->defLabel(label); + + //cout << "defining label " << label << endl; + + assert(!label->location.defined()); + //vm::program::label here = program->end(); + label->location = program->end(); + assert(label->location.defined()); + + if (label->firstUse.defined()) { + replaceEmptyJump(label->firstUse, program->end()); + //vm::printInst(cout, label->firstUse, program->begin()); + //cout << endl; + + if (label->moreUses) { + typedef label_t::useVector useVector; + useVector& v = *label->moreUses; + for (useVector::iterator p = v.begin(); p != v.end(); ++p) { + replaceEmptyJump(*p, program->end()); + } + } + } + + return label; +} + + +void coder::useLabel(inst::opcode op, label label) +{ + if (isStatic()) + return parent->useLabel(op,label); + + if (label->location.defined()) { + encode(op, label->location); + } else { + if (label->firstUse.defined()) { + // Store additional uses in the moreUses array. + if (!label->moreUses) + label->moreUses = new label_t::useVector; + label->moreUses->push_back(encodeEmptyJump(op)); + } + else { + label->firstUse = encodeEmptyJump(op); + assert(label->firstUse.defined()); + assert(!label->location.defined()); + } + } +} +label coder::fwdLabel() +{ + if (isStatic()) + return parent->fwdLabel(); + + // Create a new label without specifying its position. + label l = new label_t(); + assert(!l->location.defined()); + assert(!l->firstUse.defined()); + + //cout << "forward label " << l << endl; + + return l; +} + +bool coder::usesClosureSinceLabel(label l) +{ + assert(l->location.defined()); + for (vm::program::label i = l->location; i != program->end(); ++i) + if (i->op == inst::pushclosure) + return true; + return false; +} + +void coder::encodePatch(label from, label to) +{ + assert(from->location.defined()); + assert(to->location.defined()); + + assert(from->location->op == inst::nop); + + from->location->op = inst::jmp; + from->location->ref = to->location; +} + +void coder::markPos(position pos) +{ + curPos = pos; +} + +// When translating the function is finished, this ties up loose ends +// and returns the lambda. +vm::lambda *coder::close() { + // These steps must be done dynamically, not statically. + sord = EXPLICIT_DYNAMIC; + sord_stack.push(sord); + + // Add a return for void types; may be redundant. + if (funtype->result->kind == types::ty_void) + encode(inst::ret); + + l->code = program; + + l->parentIndex = level->parentIndex(); + + l->framesize = level->size(); + + sord_stack.pop(); + sord = sord_stack.top(); + + return l; +} + +void coder::closeRecord() +{ + // Put record into finished state. + encode(inst::pushclosure); + close(); +} + +bool coder::isRecord() +{ + return (funtype==inittype()); +} + +namespace { +function *inittype() +{ + static function t(types::primVoid()); + return &t; +} + +function *bootuptype() +{ + static function t(types::primVoid()); + return &t; +} +} // private + +} // namespace trans + -- cgit v1.2.3