cresize :: (ptr: rawptr, size: u32) -> rawptr do return raw_resize(context.allocator, ptr, size);
cfree :: (ptr: rawptr) do raw_free(context.allocator, ptr);
-new :: ($T: type_expr, allocator := context.allocator) -> ^T {
- res := cast(^T) calloc(sizeof T);
-
- // At some point, it would be nice to initialize the resulting memory, i.e.
- // *res = T.{};
-
- return res;
+use package build_opts as build_opts
+#if build_opts.Runtime != build_opts.Runtime_Custom {
+ use package core.intrinsics.wasm { __initialize }
+
+ new :: ($T: type_expr, allocator := context.allocator, initialize := true) -> ^T {
+ res := cast(^T) calloc(sizeof T);
+
+ // @Robustness: This should be a '#if' when those are added in procedures because
+ // otherwise the __initialize intrinsic is going to be generated no matter what.
+ // This could be a problem if the type is not something that can be initialized.
+ if initialize do __initialize(res);
+
+ return res;
+ }
}
memory_copy :: (dst: rawptr, src: rawptr, count: i32) -> void #intrinsic ---
memory_fill :: (dst: rawptr, byte: u8, count: i32) -> void #intrinsic ---
+__initialize :: (val: ^$T) -> void #intrinsic ---
+
clz_i32 :: (val: i32) -> i32 #intrinsic ---
ctz_i32 :: (val: i32) -> i32 #intrinsic ---
popcnt_i32 :: (val: i32) -> i32 #intrinsic ---
enum { Foo, Bar, Baz };
enum { Foo; Bar; Baz };
+[ ] Using a package in the middle of a procedures removes all remaining statements in the procedure.
+ This is mostly likely due to the changes made with use package statements being treated as entities now.
+
+ use_package_breaking :: () {
+ println("Test 1");
+
+ use package foo
+
+ println("Test 2");
+ }
+
[ ] Aliasing in many cases does not work. For example:
SomeNamespace :: struct {
ONYX_INTRINSIC_MEMORY_SIZE, ONYX_INTRINSIC_MEMORY_GROW,
ONYX_INTRINSIC_MEMORY_COPY, ONYX_INTRINSIC_MEMORY_FILL,
+ ONYX_INTRINSIC_INITIALIZE,
+
ONYX_INTRINSIC_I32_CLZ, ONYX_INTRINSIC_I32_CTZ, ONYX_INTRINSIC_I32_POPCNT,
ONYX_INTRINSIC_I32_AND, ONYX_INTRINSIC_I32_OR, ONYX_INTRINSIC_I32_XOR,
ONYX_INTRINSIC_I32_SHL, ONYX_INTRINSIC_I32_SLR, ONYX_INTRINSIC_I32_SAR,
}
Type* resolve_expression_type(AstTyped* node) {
+ if (node == NULL) return NULL;
+
if (node->kind == Ast_Kind_Compound) {
bh_arr_each(AstTyped *, expr, ((AstCompound *) node)->exprs) {
resolve_expression_type(*expr);
{ "memory_copy", ONYX_INTRINSIC_MEMORY_COPY },
{ "memory_fill", ONYX_INTRINSIC_MEMORY_FILL },
+ { "__initialize", ONYX_INTRINSIC_INITIALIZE },
+
{ "clz_i32", ONYX_INTRINSIC_I32_CLZ },
{ "ctz_i32", ONYX_INTRINSIC_I32_CTZ },
{ "popcnt_i32", ONYX_INTRINSIC_I32_POPCNT },
AstNumLit* runtime_type = make_int_literal(a, context.options->runtime);
symbol_builtin_introduce(p->scope, "Runtime", (AstNode *) runtime_type);
-}
\ No newline at end of file
+}
CheckStatus check_struct(AstStructType* s_node) {
bh_arr_each(AstStructMember *, smem, s_node->members) {
if ((*smem)->type_node == NULL && (*smem)->initial_value != NULL) {
- check_expression(&(*smem)->initial_value);
+ CHECK(expression, &(*smem)->initial_value);
fill_in_type((*smem)->initial_value);
(*smem)->type = resolve_expression_type((*smem)->initial_value);
+
+ if ((*smem)->type == NULL) {
+ onyx_report_error((*smem)->initial_value->token->pos, "Unable to deduce type of initial value. This is probably a compiler bug.");
+ return Check_Error;
+ }
}
}
return Check_Success;
}
+CheckStatus check_struct_defaults(AstStructType* s_node) {
+ bh_arr_each(StructMember *, smem, s_node->stcache->Struct.memarr) {
+ if ((*smem)->initial_value && *(*smem)->initial_value) {
+ CHECK(expression, (*smem)->initial_value);
+
+ if (!type_check_or_auto_cast((*smem)->initial_value, (*smem)->type)) {
+ onyx_report_error((*(*smem)->initial_value)->token->pos,
+ "Mismatched type for initial value, expected '%s', got '%s'.",
+ type_get_name((*smem)->type),
+ type_get_name((*(*smem)->initial_value)->type));
+ return Check_Error;
+ }
+
+ resolve_expression_type(*(*smem)->initial_value);
+ }
+ }
+
+ return Check_Success;
+}
+
CheckStatus check_function_header(AstFunction* func) {
b32 expect_default_param = 0;
b32 has_had_varargs = 0;
cs = check_type(ent->type_alias);
break;
+ case Entity_Type_Struct_Member_Default:
+ cs = check_struct_defaults((AstStructType *) ent->type_alias);
+ break;
+
case Entity_Type_Memory_Reservation_Type:
cs = check_memres_type(ent->mem_res);
break;
EMIT_FUNC(return, AstReturn* ret);
EMIT_FUNC(stack_enter, u64 stacksize);
EMIT_FUNC(stack_leave, u32 unused);
+EMIT_FUNC(zero_value, WasmType wt);
EMIT_FUNC(enter_structured_block, StructuredBlockType sbt);
EMIT_FUNC_NO_ARGS(leave_structured_block);
}
break;
+ case ONYX_INTRINSIC_INITIALIZE: {
+ Type* type_to_initialize = ((AstArgument *) call->args.values[0])->value->type->Pointer.elem;
+ emit_initialize_type(mod, &code, type_to_initialize, call->token);
+ break;
+ }
+
case ONYX_INTRINSIC_I32_CLZ: WI(WI_I32_CLZ); break;
case ONYX_INTRINSIC_I32_CTZ: WI(WI_I32_CTZ); break;
case ONYX_INTRINSIC_I32_POPCNT: WI(WI_I32_POPCNT); break;
*pcode = code;
}
+EMIT_FUNC(zero_value, WasmType wt) {
+ bh_arr(WasmInstruction) code = *pcode;
+
+ switch (wt) {
+ case WASM_TYPE_INT32: WIL(WI_I32_CONST, 0); break;
+ case WASM_TYPE_INT64: WIL(WI_I64_CONST, 0); break;
+ case WASM_TYPE_FLOAT32: WIL(WI_F32_CONST, 0); break;
+ case WASM_TYPE_FLOAT64: WIL(WI_F64_CONST, 0); break;
+ case WASM_TYPE_VAR128: {
+ static u8 zero_v128[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+ WIP(WI_V128_CONST, &zero_v128);
+ break;
+ }
+ }
+
+ *pcode = code;
+}
+
static i32 generate_type_idx(OnyxWasmModule* mod, Type* ft) {
if (ft->kind != Type_Kind_Function) return -1;
}
}
- {
- WasmFuncType* ft = mod->types[type_idx];
- switch (ft->return_type) {
- case WASM_TYPE_INT32: bh_arr_push(wasm_func.code, ((WasmInstruction){ WI_I32_CONST, 0x00 })); break;
- case WASM_TYPE_INT64: bh_arr_push(wasm_func.code, ((WasmInstruction){ WI_I64_CONST, 0x00 })); break;
- case WASM_TYPE_FLOAT32: bh_arr_push(wasm_func.code, ((WasmInstruction){ WI_F32_CONST, 0x00 })); break;
- case WASM_TYPE_FLOAT64: bh_arr_push(wasm_func.code, ((WasmInstruction){ WI_F64_CONST, 0x00 })); break;
- case WASM_TYPE_VAR128: {
- static u8 zero_v128[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
- bh_arr_push(wasm_func.code, ((WasmInstruction){ WI_V128_CONST, { .p = &zero_v128 } }));
- break;
- }
- }
- }
+ WasmFuncType* ft = mod->types[type_idx];
+ emit_zero_value(mod, &wasm_func.code, ft->return_type);
bh_arr_push(wasm_func.code, ((WasmInstruction){ WI_BLOCK_END, 0x00 }));
*pcode = code;
}
+
+EMIT_FUNC(initialize_type, Type* type, OnyxToken* where) {
+ bh_arr(WasmInstruction) code = *pcode;
+
+ switch (type->kind) {
+ case Type_Kind_Pointer:
+ case Type_Kind_Basic: {
+ WasmType basic_type = onyx_type_to_wasm_type(type);
+ emit_zero_value(mod, &code, basic_type);
+ emit_store_instruction(mod, &code, type, 0);
+ break;
+ }
+
+ case Type_Kind_Struct: {
+ u64 value_ptr = local_raw_allocate(mod->local_alloc, WASM_TYPE_PTR);
+ WIL(WI_LOCAL_SET, value_ptr);
+
+ bh_arr_each(StructMember *, psmem, type->Struct.memarr) {
+ StructMember* smem = *psmem;
+ if (smem->initial_value == NULL || *smem->initial_value == NULL) continue;
+
+ WIL(WI_LOCAL_GET, value_ptr);
+ emit_expression(mod, &code, *smem->initial_value);
+ emit_store_instruction(mod, &code, smem->type, smem->offset);
+ }
+
+ local_raw_free(mod->local_alloc, WASM_TYPE_PTR);
+ break;
+ }
+
+ default:
+ onyx_report_error(where->pos,
+ "Unable to initialize type, '%s'. The reason for this is largely due to the compiler not knowing what the initial value should be.",
+ type_get_name(type));
+ break;
+ }
+
+ *pcode = code;
+}
test_overload :: proc {
proc (x: $T, y: T) -> T { return x; },
proc (x: $T, y: $R) -> R { return y; },
-}
\ No newline at end of file
+}