Add remaining shims
This commit is contained in:
parent
feb17c5e45
commit
241da7fbed
@ -67,6 +67,9 @@ namespace BooleanMethods {
|
|||||||
return (StringData*)(void*)sFalse;
|
return (StringData*)(void*)sFalse;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//%
|
||||||
|
bool bang(bool v) { return !v; }
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace String {
|
namespace String {
|
||||||
@ -83,6 +86,19 @@ namespace String {
|
|||||||
int toNumber(StringData *s) {
|
int toNumber(StringData *s) {
|
||||||
return atoi(s->data);
|
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 {
|
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 {
|
namespace Math {
|
||||||
/**
|
/**
|
||||||
* Returns the value of a base expression taken to a specified power.
|
* 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user