add compile script
This commit is contained in:
154
qbe_rt.c
Normal file
154
qbe_rt.c
Normal file
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* qbe_rt.c - Runtime support for QBE-compiled ƿit modules
|
||||
*
|
||||
* Provides non-inline versions of static-inline quickjs functions
|
||||
* (which QBE-generated code calls as external symbols) and stub
|
||||
* implementations of cell_rt_* helper functions.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
typedef uint64_t JSValue;
|
||||
typedef struct JSContext JSContext;
|
||||
|
||||
#define JS_TAG_SHORT_FLOAT 5
|
||||
#define JS_TAG_NULL 7
|
||||
#define JS_VAL_NULL 7
|
||||
|
||||
/* ============================================================
|
||||
Non-inline wrappers for static-inline quickjs functions
|
||||
============================================================ */
|
||||
|
||||
/*
|
||||
* __JS_NewFloat64 — encode double as tagged JSValue
|
||||
* Short float: [sign:1][exp:8][mantissa:52][tag:3]
|
||||
* Returns tagged int if value is an exact integer in int32 range
|
||||
*/
|
||||
JSValue __JS_NewFloat64(JSContext *ctx, double d) {
|
||||
union { double d; uint64_t u; } u;
|
||||
u.d = d;
|
||||
|
||||
uint64_t sign = u.u >> 63;
|
||||
int exp = (u.u >> 52) & 0x7FF;
|
||||
uint64_t mantissa = u.u & ((1ULL << 52) - 1);
|
||||
|
||||
/* Zero */
|
||||
if (exp == 0 && mantissa == 0)
|
||||
return JS_TAG_SHORT_FLOAT;
|
||||
/* NaN/Inf → null */
|
||||
if (exp == 0x7FF)
|
||||
return JS_VAL_NULL;
|
||||
/* Subnormals → zero */
|
||||
if (exp == 0)
|
||||
return (sign << 63) | JS_TAG_SHORT_FLOAT;
|
||||
|
||||
int short_exp = exp - 1023 + 127;
|
||||
if (short_exp < 1 || short_exp > 254)
|
||||
return JS_VAL_NULL;
|
||||
|
||||
/* Prefer integer if exact */
|
||||
if (d >= (double)(-2147483647 - 1) && d <= (double)2147483647) {
|
||||
int32_t i = (int32_t)d;
|
||||
if ((double)i == d)
|
||||
return (uint64_t)(uint32_t)i << 1;
|
||||
}
|
||||
|
||||
return (sign << 63)
|
||||
| ((uint64_t)short_exp << 55)
|
||||
| (mantissa << 3)
|
||||
| JS_TAG_SHORT_FLOAT;
|
||||
}
|
||||
|
||||
/*
|
||||
* JS_IsNumber — check if value is tagged int or short float
|
||||
*/
|
||||
int JS_IsNumber(JSValue v) {
|
||||
int is_int = (v & 1) == 0;
|
||||
int is_float = (v & 7) == JS_TAG_SHORT_FLOAT;
|
||||
return is_int || is_float;
|
||||
}
|
||||
|
||||
/*
|
||||
* JS_NewString — create string from C string (wraps JS_NewStringLen)
|
||||
*/
|
||||
extern JSValue JS_NewStringLen(JSContext *ctx, const char *str, size_t len);
|
||||
|
||||
JSValue JS_NewString(JSContext *ctx, const char *str) {
|
||||
return JS_NewStringLen(ctx, str, strlen(str));
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
cell_rt_* stubs — error/fallback paths for QBE-compiled code
|
||||
These are called from type-mismatch branches that should not
|
||||
be reached in pure numeric code.
|
||||
============================================================ */
|
||||
|
||||
extern JSValue JS_ThrowTypeError(JSContext *ctx, const char *fmt, ...);
|
||||
|
||||
void cell_rt_disrupt(JSContext *ctx) {
|
||||
JS_ThrowTypeError(ctx, "type error in native code");
|
||||
}
|
||||
|
||||
JSValue cell_rt_lt_text(JSContext *ctx, JSValue a, JSValue b) {
|
||||
return JS_VAL_NULL;
|
||||
}
|
||||
JSValue cell_rt_gt_text(JSContext *ctx, JSValue a, JSValue b) {
|
||||
return JS_VAL_NULL;
|
||||
}
|
||||
JSValue cell_rt_le_text(JSContext *ctx, JSValue a, JSValue b) {
|
||||
return JS_VAL_NULL;
|
||||
}
|
||||
JSValue cell_rt_ge_text(JSContext *ctx, JSValue a, JSValue b) {
|
||||
return JS_VAL_NULL;
|
||||
}
|
||||
JSValue cell_rt_eq_tol(JSContext *ctx, JSValue a, JSValue b) {
|
||||
return JS_VAL_NULL;
|
||||
}
|
||||
JSValue cell_rt_ne_tol(JSContext *ctx, JSValue a, JSValue b) {
|
||||
return JS_VAL_NULL;
|
||||
}
|
||||
|
||||
JSValue cell_rt_get_intrinsic(JSContext *ctx, const char *name) {
|
||||
return JS_VAL_NULL;
|
||||
}
|
||||
JSValue cell_rt_load_field(JSContext *ctx, JSValue obj, const char *name) {
|
||||
return JS_VAL_NULL;
|
||||
}
|
||||
JSValue cell_rt_load_dynamic(JSContext *ctx, JSValue obj, JSValue key) {
|
||||
return JS_VAL_NULL;
|
||||
}
|
||||
JSValue cell_rt_load_index(JSContext *ctx, JSValue arr, JSValue idx) {
|
||||
return JS_VAL_NULL;
|
||||
}
|
||||
void cell_rt_store_field(JSContext *ctx, JSValue val, JSValue obj,
|
||||
const char *name) {}
|
||||
void cell_rt_store_dynamic(JSContext *ctx, JSValue val, JSValue obj,
|
||||
JSValue key) {}
|
||||
void cell_rt_store_index(JSContext *ctx, JSValue val, JSValue arr,
|
||||
JSValue idx) {}
|
||||
JSValue cell_rt_get_closure(JSContext *ctx, void *fp, int64_t depth,
|
||||
int64_t index) {
|
||||
return JS_VAL_NULL;
|
||||
}
|
||||
void cell_rt_put_closure(JSContext *ctx, void *fp, JSValue val, int64_t depth,
|
||||
int64_t index) {}
|
||||
JSValue cell_rt_frame(JSContext *ctx, JSValue fn, int64_t nargs) {
|
||||
return JS_VAL_NULL;
|
||||
}
|
||||
void cell_rt_setarg(JSValue frame, int64_t idx, JSValue val) {}
|
||||
JSValue cell_rt_invoke(JSContext *ctx, JSValue frame) { return JS_VAL_NULL; }
|
||||
JSValue cell_rt_goframe(JSContext *ctx, JSValue fn, int64_t nargs) {
|
||||
return JS_VAL_NULL;
|
||||
}
|
||||
void cell_rt_goinvoke(JSContext *ctx, JSValue frame) {}
|
||||
JSValue cell_rt_make_function(JSContext *ctx, int64_t fn_idx) {
|
||||
return JS_VAL_NULL;
|
||||
}
|
||||
void cell_rt_push(JSContext *ctx, JSValue arr, JSValue val) {}
|
||||
JSValue cell_rt_pop(JSContext *ctx, JSValue arr) { return JS_VAL_NULL; }
|
||||
JSValue cell_rt_delete(JSContext *ctx, JSValue obj, JSValue key) {
|
||||
return JS_VAL_NULL;
|
||||
}
|
||||
JSValue cell_rt_typeof(JSContext *ctx, JSValue val) { return JS_VAL_NULL; }
|
||||
Reference in New Issue
Block a user