-Subproject commit 310aab6d18d29f3bcb06fa1b5b12f2e7d2e79555
+Subproject commit f6c9ae7feb355a64345da5c99c479a32a310df11
ANN m_bool ensure_emit(const Emitter, const Type);
ANN m_bool emit_ensure_func(const Emitter emit, const Func f);
+ANN m_bool get_emit_var(const Emitter emit, const Type t, bool is_var);
#endif
tflag_union = 1 << 21,
tflag_enum = 1 << 22,
tflag_ref = 1 << 23,
+ tflag_packed = 1 << 24,
} __attribute__((packed));
struct Type_ {
const restrict m_str name);
ANN Type gwi_typedef_end(const Gwi gwi, const ae_flag flag);
ANN void ck_clean_tdef(MemPool, ImportCK *);
+
+ANN Type mk_primitive(const Env env, const m_str name, const m_uint size);
+//ANN Type gwi_primitive(const Gwi gwi, const m_str name, const m_uint size, const ae_flag flag);
+ANN m_bool gwi_primitive(const Gwi gwi, const m_str name, const m_uint size, const ae_flag flag);
#endif
if (b->traits) clean_id_list(a, b->traits);
if (b->body) clean_ast(a, b->body);
}
+ANN static void clean_prim_def(Clean *a NUSED, Prim_Def b NUSED) {}
DECL_SECTION_FUNC(clean, void, Clean *);
}
ANN static m_bool emit_exp_array(const Emitter emit, const Exp_Array *array) {
- CHECK_BB(emit_exp(emit, array->base));
const Exp e = exp_self(array);
- struct ArrayAccessInfo info = {*array->array, e->type, exp_getvar(e)};
+ exp_setvar(array->base, get_emit_var(emit, array->base->type, exp_getvar(e)));
+ CHECK_BB(emit_exp(emit, array->base));
+ struct ArrayAccessInfo info = {
+ .array = *array->array,
+ .type = e->type,
+ .is_var = exp_getvar(e)};
return emit_array_access(emit, &info);
}
}
ANN static inline int struct_ctor(const Value v) {
- return tflag(v->type, tflag_struct) && v->type->nspc->pre_ctor;
+ return tflag(v->type, tflag_struct) && v->type->nspc && v->type->nspc->pre_ctor;
+// return tflag(v->type, tflag_struct) && v->type->nspc->pre_ctor;
}
ANN static void decl_expand(const Emitter emit, const Type t) {
#define emit_fptr_def dummy_func
#define emit_trait_def dummy_func
#define emit_extend_def dummy_func
+#define emit_prim_def dummy_func
HANDLE_SECTION_FUNC(emit, m_bool, Emitter);
const Nspc global = a->nspc->parent;
if(!a->error) // this is quite a hack
nspc_remref(a->nspc, gwion);
- if(a->error) nspc_remref(global, gwion);
+// if(a->error) // this is quite a hack
+ if(a->global) // this is quite a hack
+ nspc_remref(global, gwion);
free_mstr(gwion->mp, a->name);
ast_cleaner(gwion, a->tree);
mp_free(gwion->mp, Context, a);
--- /dev/null
+#include <limits.h>
+#include "gwion_util.h"
+#include "gwion_ast.h"
+#include "gwion_env.h"
+#include "vm.h"
+#include "instr.h"
+#include "emit.h"
+#include "gwion.h"
+#include "object.h"
+#include "operator.h"
+#include "import.h"
+#include "gwi.h"
+#include "array.h"
+#include "gack.h"
+
+static GACK(gack_prim) {
+ for(m_uint i = 0; i < t->actual_size; i++) {
+ const m_bit *value = VALUE + i;
+ for(unsigned char mask = 1U << (CHAR_BIT-1); mask; mask >>= 1)
+ INTERP_PRINTF("%c", *(uint8_t*)value & mask ? '1' : '0');
+ if(i < t->actual_size - 1)
+ INTERP_PRINTF(" ");
+ }
+}
+
+static INSTR(bit_set) {
+ POP_REG(shred, SZ_INT);
+ const m_int offset = *(m_int*)REG(0);
+ const m_uint byte = offset / CHAR_BIT;
+ const m_uint idx = offset % CHAR_BIT;
+ uint8_t *val = *(uint8_t**)REG(-SZ_INT);
+ val += byte;
+ const m_int key = *(m_int*)REG(-SZ_INT*2);
+ if(key) *val = ((1 << idx) | (*val));
+ else **(m_bit**)REG(-SZ_INT) = ((*val) & (~(1 << (idx))));
+ *(m_bit**)REG(-SZ_INT) = REG(0);
+}
+
+static INSTR(bit_set_fast) {
+ uint8_t *val = *(uint8_t**)REG(-SZ_INT);
+ val += instr->m_val;
+ const m_uint idx = instr->m_val2;
+ const m_int key = *(m_int*)REG(-SZ_INT*2);
+ if(key) *val = ((1 << idx) | (*val));
+ else **(m_bit**)REG(-SZ_INT) = ((*val) & (~(1 << (idx))));
+ *(m_bit**)REG(-SZ_INT) = REG(0);
+}
+
+static INSTR(bit_check) {
+ const m_int offset = *(m_int*)REG(-SZ_INT);
+ if(offset < 0 || offset >= (m_int)instr->m_val)
+ handle(shred, "OutOfBoundByteAccess");
+}
+
+ANN static bool _bit_get(const uint8_t val, const m_uint idx) {
+ const int mask = 1 << idx;
+ const int masked_n = val & mask;
+ return masked_n >> idx;
+}
+
+static INSTR(bit_get) {
+ POP_REG(shred, instr->m_val);
+ const m_int offset = *(m_int*)REG(0);
+ const m_uint byte = offset / CHAR_BIT;
+ const uint8_t val = *(uint8_t*)REG(byte - SZ_INT);
+ *(m_int*)REG(-SZ_INT) = _bit_get(val, offset % CHAR_BIT);
+}
+
+static INSTR(bit_get_fast) {
+ const uint8_t val = *(uint8_t*)REG((int16_t)instr->udata.two);
+ *(m_int*)REG(-instr->m_val) = _bit_get(val, instr->udata.one);
+}
+
+static OP_EMIT(opem_bit_access) {
+ struct ArrayAccessInfo *const info = (struct ArrayAccessInfo *)data;
+ if(!is_prim_int(info->array.exp)) {
+ CHECK_BB(emit_exp(emit, info->array.exp));
+ const Instr check = emit_add_instr(emit, bit_check);
+ check->m_val = info->array.type->actual_size * CHAR_BIT;
+ if(!info->is_var) {
+ const Instr instr = emit_add_instr(emit, bit_get);
+ instr->m_val = info->array.type->size;
+ } else emit_add_instr(emit, bit_set);
+ } else {
+ const m_uint offset = info->array.exp->d.prim.d.num;
+ if(!info->is_var) {
+ const Instr instr = emit_add_instr(emit, bit_get_fast);
+ instr->m_val = info->type->size;
+ instr->udata.one = offset % CHAR_BIT;
+ instr->udata.two = (m_int)((offset / CHAR_BIT) - SZ_INT);
+ } else {
+ const Instr instr = emit_add_instr(emit, bit_set_fast);
+ const m_uint offset = info->array.exp->d.prim.d.num;
+ instr->m_val2 = offset % CHAR_BIT;
+ instr->m_val = (offset / CHAR_BIT);
+ }
+ }
+ return GW_OK;
+}
+
+static OP_EMIT(opem_bit_exp) {
+ bool *var = data;
+ var[1] = var[0];
+ return GW_OK;
+}
+
+static OP_CHECK(opck_bit_access) {
+ Array_Sub array = data;
+ const Exp e = array->exp;
+ if(e->next) ERR_N(e->next->pos, "too many expressions for bit access");
+ if(is_prim_int(e)) {
+ m_int idx = e->d.prim.d.num;
+ if(idx < 0 || idx >= (m_int)array->type->size * CHAR_BIT)
+ ERR_N(e->pos, "bit access out of bound");
+ }
+ return env->gwion->type[et_bool];
+}
+
+ANN static void scan_prim_op(const Env env, const Type t){
+ struct Op_Func opfunc = { .ck = opck_bit_access, .em = opem_bit_access };
+ struct Op_Import opi = {
+ .op = insert_symbol(env->gwion->st, "@array"),
+ .lhs = env->gwion->type[et_int],
+ .rhs = t,
+ .func = &opfunc
+ };
+ add_op(env->gwion, &opi);
+}
+
+ANN static void scan_prim_op2(const Env env, const Type t){
+ struct Op_Func opfunc = {.em = opem_bit_exp };
+ struct Op_Import opi = {
+ .op = insert_symbol(env->gwion->st, "@array_init"),
+ .lhs = t,
+ .ret = env->gwion->type[et_bool],
+ .func = &opfunc
+ };
+ add_op(env->gwion, &opi);
+}
+
+static INSTR(bitset) {
+ POP_REG(shred, SZ_INT);
+ memcpy(*(uint8_t**)REG(0), REG(-SZ_INT), instr->m_val);
+}
+
+static OP_EMIT(opem_bitset) {
+ Exp_Binary *bin = data;
+ const Instr instr = emit_add_instr(emit, bitset);
+ const Type t = isa(bin->rhs->type, emit->gwion->type[et_int]) > 0
+ ? bin->lhs->type
+ : bin->rhs->type;
+ instr->m_val = t->actual_size;
+ return GW_OK;
+}
+
+static INSTR(bitcast) {
+ memset(REG((m_int)instr->m_val), 0, instr->m_val2);
+}
+
+static OP_EMIT(opem_bitcast) {
+ Exp_Cast *cast = data;
+ const Type t = isa(cast->exp->type, emit->gwion->type[et_int]) > 0
+ ? known_type(emit->env, cast->td)
+ : cast->exp->type;
+ const Instr instr = emit_add_instr(emit, bitcast);
+ instr->m_val = -SZ_INT + t->actual_size;
+ instr->m_val2 = SZ_INT - t->actual_size;
+ return GW_OK;
+}
+
+ANN2(1,2,3,5) static void prim_op(const Env env, const Type t, const m_str op, const opck ck, const opem em){
+ struct Op_Func opfunc = { .ck = ck, .em = em };
+ struct Op_Import opi = {
+ .op = insert_symbol(env->gwion->st, op),
+ .lhs = env->gwion->type[et_int],
+ .rhs = t,
+ .ret = t,
+ .func = &opfunc
+ };
+ add_op(env->gwion, &opi);
+ opi.lhs = t;
+ opi.rhs = opi.ret = env->gwion->type[et_int];
+ add_op(env->gwion, &opi);
+}
+
+ANN static void prim_implicit(const Env env, const Type t){
+ struct Op_Import opi = {
+ .op = insert_symbol(env->gwion->st, "@implicit"),
+ .lhs = t,
+ .rhs = env->gwion->type[et_int],
+ .ret = env->gwion->type[et_int],
+ };
+ add_op(env->gwion, &opi);
+}
+
+ANN Type mk_primitive(const Env env, const m_str name, const m_uint size) {
+ m_uint sz = SZ_INT;
+ while(sz < size) sz += SZ_INT;
+ const Type t = new_type(env->gwion->mp, name, NULL);
+ t->size = sz;
+ t->actual_size = size;
+ scan_prim_op(env, t);
+ scan_prim_op2(env, t);
+ if(size < SZ_INT) {
+ prim_op(env, t, ":=>", opck_rassign, opem_bitset);
+ prim_op(env, t, "$", NULL, opem_bitcast);
+ prim_implicit(env, t);
+ } else if(size == SZ_INT) {
+ prim_op(env, t, ":=>", opck_rassign, (opem)dummy_func);
+ prim_op(env, t, "$", NULL, (opem)dummy_func);
+ prim_implicit(env, t);
+ } // else provide function to get slices
+ CHECK_BO(mk_gack(env->gwion->mp, t, gack_prim));
+ return t;
+}
+
+// actually we should make a Prim_Def
+// and either execute and free it already
+// or add it to the current ast
+
+ANN m_bool scan0_prim_def(const Env env, const Prim_Def pdef);
+
+//ANN Type gwi_primitive(const Gwi gwi, const m_str name, const m_uint size, const ae_flag flag) {
+ANN m_bool gwi_primitive(const Gwi gwi, const m_str name, const m_uint size, const ae_flag flag) {
+ const Env env = gwi->gwion->env;
+ const Prim_Def pdef = new_prim_def(gwi->gwion->mp, insert_symbol(gwi->gwion->st, name), size, gwi->loc, flag);
+ if(!env->class_def || !tflag(env->class_def, tflag_tmpl)) {
+ const m_bool ret = scan0_prim_def(gwi->gwion->env, pdef);
+ free_prim_def(gwi->gwion->mp, pdef);
+ return ret;
+ }
+ Section section = MK_SECTION(primitive, prim_def, pdef);
+ gwi_body(gwi, §ion);
+ return GW_OK;
+}
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
#include "gwion_util.h"
#include "gwion_ast.h"
#include "gwion_env.h"
#include "operator.h"
#include "import.h"
#include "gwi.h"
-#include "mpool.h"
-#include "specialid.h"
ANN m_int gwi_typedef_ini(const Gwi gwi, const restrict m_str type,
const restrict m_str name) {
return GW_OK;
}
+ANN m_bool get_emit_var(const Emitter emit, const Type t, bool is_var) {
+ const Env env = emit->env;
+ bool vars[2] = { is_var };
+ struct Op_Import opi = {.op = insert_symbol("@array_init"),
+ .lhs = t,
+ .data = (uintptr_t)vars};
+ CHECK_BB(op_emit(emit, &opi));
+ return vars[1];
+}
+
ANN static inline Exp emit_n_exp(const Emitter emit,
struct ArrayAccessInfo *const info) {
const Exp e = take_exp(info->array.exp, info->array.depth);
e->next = NULL;
struct Array_Sub_ partial = {info->array.exp, info->array.type,
info->array.depth};
- const m_bool ret = array_do(emit, &partial, 0);
+ const bool is_var = get_emit_var(emit, array_base(info->array.type), info->is_var);
+ const m_bool ret = array_do(emit, &partial, is_var);
e->next = next;
return ret > 0 ? next : NULL;
}
GWI_BB(gwi_oper_ini(gwi, "Array", NULL, NULL))
GWI_BB(gwi_oper_add(gwi, opck_array_scan))
GWI_BB(gwi_oper_end(gwi, "@scan", NULL))
+
+ GWI_BB(gwi_oper_ini(gwi, (m_str)OP_ANY_TYPE, NULL, "bool"))
+ GWI_BB(gwi_oper_end(gwi, "@array_init", NoOp))
+
gwi_register_freearg(gwi, ArrayAlloc, freearg_array);
return GW_OK;
}
+#include <limits.h>
#include "gwion_util.h"
#include "gwion_ast.h"
#include "gwion_env.h"
#define CHECK_OP(op, check, func) _CHECK_OP(op, check, int_##func)
-static inline bool is_prim(const Exp e) { return e->exp_type == ae_exp_primary; }
-
-static inline bool is_prim_int(const Exp e) {
- return (is_prim(e) && e->d.prim.prim_type == ae_prim_num);
-}
-
-static inline bool is_prim_float(const Exp e) {
- return (is_prim(e) && e->d.prim.prim_type == ae_prim_float);
-}
-
#define POWEROF2_OPT(name, OP) \
if (is_prim_int(bin->rhs) && pot(bin->rhs->d.prim.d.num)) { \
bin->op = insert_symbol(#OP); \
return GW_OK;
}
-static GACK(gack_u8) {
- INTERP_PRINTF("%u", *(uint8_t*)VALUE);
-}
-
-static GACK(gack_u16) {
- INTERP_PRINTF("%u", *(uint16_t*)VALUE);
-}
-
-static GACK(gack_u32) {
- INTERP_PRINTF("%u", *(uint32_t*)VALUE);
+ANN static m_bool import_ux(const Gwi gwi) {
+ char c[8] = { 'u' };
+ const Env env = gwi->gwion->env;
+ for(uint i = 1; i <= SZ_INT; i *= 2) {
+ sprintf(c+1, "%u", i * CHAR_BIT);
+ const Symbol s = insert_symbol(c);
+ GWI_OB(gwi_primitive(gwi, s_name(s), i, ae_flag_none));
+ }
+ return GW_OK;
}
GWION_IMPORT(prim) {
- GWI_BB(import_int(gwi)) // const folded + imm optimized
- const Type t_u8 = gwi_mk_type(gwi, "u8", SZ_INT, "int");
- t_u8->actual_size = 1;
- gwi_gack(gwi, t_u8, gack_u8);
- gwi_add_type(gwi, t_u8);
- GWI_BB(gwi_oper_ini(gwi, "int", "u8", "u8"))
- GWI_BB(gwi_oper_end(gwi, "@implicit", NoOp))
- const Type t_u16 = gwi_mk_type(gwi, "u16", SZ_INT, "int");
- t_u16->actual_size = 2;
- gwi_gack(gwi, t_u16, gack_u16);
- gwi_add_type(gwi, t_u16);
- GWI_BB(gwi_oper_ini(gwi, "int", "u16", "u16"))
- GWI_BB(gwi_oper_end(gwi, "@implicit", NoOp))
- const Type t_u32 = gwi_mk_type(gwi, "u32", SZ_INT, "int");
- t_u32->actual_size = 4;
- gwi_gack(gwi, t_u32, gack_u32);
- gwi_add_type(gwi, t_u32);
- GWI_BB(gwi_oper_ini(gwi, "int", "u32", "u32"))
- GWI_BB(gwi_oper_end(gwi, "@implicit", NoOp))
+ GWI_BB(import_int(gwi))
+ GWI_BB(import_ux(gwi));
GWI_BB(import_float(gwi)) // const folded
GWI_BB(import_intfloat(gwi)) // const folded
GWI_BB(import_floatint(gwi)) // const folded
return GW_OK;
}
+ANN static m_uint get_decl_size(const Env env, const Value v) {
+ if(safe_tflag(env->class_def, tflag_packed) && v->type->actual_size)
+ return v->type->actual_size;
+ return v->type->size;
+
+}
+
#define describe_check_decl(a, b, flag) \
ANN static inline void decl_##a(const Env env, const Value v) { \
const Nspc nspc = env->curr; \
flag; \
v->from->offset = nspc->b; \
- nspc->b += v->type->size; \
+ nspc->b += get_decl_size(env, v); \
}
describe_check_decl(member, offset, v->vflag |= vflag_member);
return ret;
}
+#define check_prim_def dummy_func
HANDLE_SECTION_FUNC(check, m_bool, Env)
ANN static m_bool check_parent(const Env env, const Class_Def cdef) {
return GW_OK;
}
+ANN m_bool scan0_prim_def(const Env env, const Prim_Def pdef) {
+ const loc_t loc = pdef->loc;
+ CHECK_BB(env_access(env, pdef->flag, loc));
+ CHECK_BB(scan0_defined(env, pdef->name, loc));
+ const bool global = GET_FLAG(pdef, global);
+ if(global) {
+ context_global(env);
+ env_push_global(env);
+ }
+ const Type t = mk_primitive(env, s_name(pdef->name), pdef->size);
+ add_type(env, env->curr, t);
+ mk_class(env, t, pdef->loc);
+ t->flag = pdef->flag;
+ if(global) env_pop(env, 0);
+ return GW_OK;
+}
+
HANDLE_SECTION_FUNC(scan0, m_bool, Env)
ANN static m_bool scan0_class_def_inner(const Env env, const Class_Def cdef) {
ANN static m_bool scan1_stmt_pp(const Env env, const Stmt_PP stmt) {
if (stmt->pp_type == ae_pp_include) env->name = stmt->data;
+ if (stmt->pp_type == ae_pp_pragma && !strcmp(stmt->data, "packed")) {
+ if(env->class_def && !tflag(env->class_def, tflag_union)) set_tflag(env->class_def, tflag_packed);
+ else ERR_B(stmt_self(stmt)->pos, "`packed` pragma outside of {G+}class{0} or {G+}struct{0} declaration");
+ }
return GW_OK;
}
const Value v = nspc_lookup_value1(env->curr, fdef->base->xid);
if (!v) return GW_OK;
if (is_func(env->gwion, actual_type(env->gwion, v->type))) return GW_OK; // is_callable
+ if(fdef->builtin) return GW_OK;
if ((!env->class_def || !GET_FLAG(env->class_def, final)) &&
!nspc_lookup_value0(env->curr, fdef->base->xid))
ERR_B(fdef->base->pos,
return ret;
}
-
ANN m_bool scan1_func_def(const Env env, const Func_Def fdef) {
const uint16_t depth = env->scope->depth;
env->scope->depth = 0;
#define scan1_trait_def dummy_func
#define scan1_extend_def dummy_func
+#define scan1_prim_def dummy_func
HANDLE_SECTION_FUNC(scan1, m_bool, Env)
ANN static Type scan1_get_parent(const Env env, const Type_Def tdef) {
#define scan2_enum_def dummy_func
#define scan2_trait_def dummy_func
#define scan2_extend_def dummy_func
+#define scan2_prim_def dummy_func
HANDLE_SECTION_FUNC(scan2, m_bool, Env)
ANN static m_bool scan2_parent(const Env env, const Class_Def cdef) {
--- /dev/null
+#! [contains] true
+var u8 u;
+true :=> u[2];
+<<< u[2] >>>;
--- /dev/null
+#! [contains] true
+var u8 u;
+2 :=> var int i;
+true :=> u[i];
+<<< u >>>;
+<<< u[i] >>>;
--- /dev/null
+#! [contains] OutOfBoundByteAccess
+9 :=> var int i;
+var u8 u;
+u[i];
--- /dev/null
+#! [contains] out of bound
+var u8 u;
+u[-3];
--- /dev/null
+#! [contains] too many expressions
+var u8 u;
+u[1][2];