Add remaining shims

This commit is contained in:
Michal Moskal 2016-04-02 11:22:36 -07:00
parent feb17c5e45
commit 241da7fbed

View File

@ -67,6 +67,9 @@ namespace BooleanMethods {
return (StringData*)(void*)sFalse;
}
}
//%
bool bang(bool v) { return !v; }
}
namespace String {
@ -83,6 +86,19 @@ namespace String {
int toNumber(StringData *s) {
return atoi(s->data);
}
//%
StringData *mkEmpty()
{
return ManagedString::EmptyString.leakData();
}
// The proper StringData* representation is already laid out in memory by the code generator.
//%
uint32_t mkLiteral(uint32_t lit)
{
return (uint32_t)getstr(lit);
}
}
namespace NumberMethods {
@ -96,6 +112,30 @@ namespace NumberMethods {
}
}
namespace NumberImpl {
// +, - and friends are handled directly by assembly instructions
// The comparisons are here as they are more code-size efficient
//%
bool lt(int x, int y) { return x < y; }
//%
bool le(int x, int y) { return x <= y; }
//%
bool neq(int x, int y) { return x != y; }
//%
bool eq(int x, int y) { return x == y; }
//%
bool gt(int x, int y) { return x > y; }
//%
bool ge(int x, int y) { return x >= y; }
// These in fact call into C runtime on Cortex-M0
//%
int div(int x, int y) { return x / y; }
//%
int mod(int x, int y) { return x % y; }
}
namespace Math {
/**
* Returns the value of a base expression taken to a specified power.
@ -231,3 +271,182 @@ namespace ArrayImpl {
}
}
namespace ActionImpl {
//%
Action mk(int reflen, int totallen, int startptr)
{
check(0 <= reflen && reflen <= totallen, ERR_SIZE, 1);
check(reflen <= totallen && totallen <= 255, ERR_SIZE, 2);
check(bytecode[startptr] == 0xffff, ERR_INVALID_BINARY_HEADER, 3);
check(bytecode[startptr + 1] == 0, ERR_INVALID_BINARY_HEADER, 4);
uint32_t tmp = (uint32_t)&bytecode[startptr];
if (totallen == 0) {
return tmp; // no closure needed
}
void *ptr = ::operator new(sizeof(RefAction) + totallen * sizeof(uint32_t));
RefAction *r = new (ptr) RefAction();
r->len = totallen;
r->reflen = reflen;
r->func = (ActionCB)((tmp + 4) | 1);
memset(r->fields, 0, r->len * sizeof(uint32_t));
return (Action)r;
}
//%
uint32_t mkLiteral(uint32_t lit)
{
return (uint32_t)getstr(lit);
}
//%
void run1(Action a, int arg)
{
if (hasVTable(a))
((RefAction*)a)->run(arg);
else {
check(*(uint16_t*)a == 0xffff, ERR_INVALID_BINARY_HEADER, 4);
((ActionCB)((a + 4) | 1))(NULL, NULL, arg);
}
}
//%
void run(Action a)
{
ActionImpl::run1(a, 0);
}
}
namespace RecordImpl {
//%
RefRecord* mk(int reflen, int totallen)
{
check(0 <= reflen && reflen <= totallen, ERR_SIZE, 1);
check(reflen <= totallen && totallen <= 255, ERR_SIZE, 2);
void *ptr = ::operator new(sizeof(RefRecord) + totallen * sizeof(uint32_t));
RefRecord *r = new (ptr) RefRecord();
r->len = totallen;
r->reflen = reflen;
memset(r->fields, 0, r->len * sizeof(uint32_t));
return r;
}
}
namespace ksrt {
//%
uint32_t ldloc(RefLocal *r) {
return r->v;
}
//%
uint32_t ldlocRef(RefRefLocal *r) {
uint32_t tmp = r->v;
incr(tmp);
return tmp;
}
//%
void stloc(RefLocal *r, uint32_t v) {
r->v = v;
}
//%
void stlocRef(RefRefLocal *r, uint32_t v) {
decr(r->v);
r->v = v;
}
//%
RefLocal *mkloc() {
return new RefLocal();
}
//%
RefRefLocal *mklocRef() {
return new RefRefLocal();
}
// All of the functions below unref() self. This is for performance reasons -
// the code emitter will not emit the unrefs for them.
//%
uint32_t ldfld(RefRecord *r, int idx) {
auto tmp = r->ld(idx);
r->unref();
return tmp;
}
//%
uint32_t ldfldRef(RefRecord *r, int idx) {
auto tmp = r->ldref(idx);
r->unref();
return tmp;
}
//%
void stfld(RefRecord *r, int idx, uint32_t val) {
r->st(idx, val);
r->unref();
}
//%
void stfldRef(RefRecord *r, int idx, uint32_t val) {
r->stref(idx, val);
r->unref();
}
//%
uint32_t ldglb(int idx) {
check(0 <= idx && idx < numGlobals, ERR_OUT_OF_BOUNDS, 7);
return globals[idx];
}
//%
uint32_t ldglbRef(int idx) {
check(0 <= idx && idx < numGlobals, ERR_OUT_OF_BOUNDS, 7);
uint32_t tmp = globals[idx];
incr(tmp);
return tmp;
}
// note the idx comes last - it's more convenient that way in the emitter
//%
void stglb(uint32_t v, int idx)
{
check(0 <= idx && idx < numGlobals, ERR_OUT_OF_BOUNDS, 7);
globals[idx] = v;
}
//%
void stglbRef(uint32_t v, int idx)
{
check(0 <= idx && idx < numGlobals, ERR_OUT_OF_BOUNDS, 7);
decr(globals[idx]);
globals[idx] = v;
}
// Store a captured local in a closure. It returns the action, so it can be chained.
//%
RefAction *stclo(RefAction *a, int idx, uint32_t v)
{
//DBG("STCLO "); a->print(); DBG("@%d = %p\n", idx, (void*)v);
a->st(idx, v);
return a;
}
//%
uint32_t incr(uint32_t ptr) {
bitvm::incr(ptr);
return ptr;
}
//%
void decr(uint32_t ptr) {
bitvm::decr(ptr);
}
}