added __zero_value intrinsic to quickly make a zeroed value
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 16 Apr 2021 16:11:19 +0000 (11:11 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 16 Apr 2021 16:11:19 +0000 (11:11 -0500)
core/intrinsics/onyx.onyx
include/onyxastnodes.h
include/onyxtypes.h
src/onyxbuiltins.c
src/onyxchecker.c
src/onyxtypes.c
src/onyxwasm.c

index e77a2ddd5e85ae6c9e71f899725f78a11bbac32d..6df73adf18554a6410c7a197e3f3bef31f8d6112 100644 (file)
@@ -1,3 +1,4 @@
 package core.intrinsics.onyx
 
-__initialize :: (val: ^$T) -> void #intrinsic ---
+__initialize :: (val: ^$T)      -> void #intrinsic ---
+__zero_value :: ($T: type_expr) -> T    #intrinsic ---
index c44353f6832009c9d835dea9e0b8e2968419a8b7..cfd7572494aa1c516fe76f65a2237a3037efc4ba 100644 (file)
@@ -290,7 +290,7 @@ typedef enum OnyxIntrinsic {
     ONYX_INTRINSIC_MEMORY_SIZE, ONYX_INTRINSIC_MEMORY_GROW,
     ONYX_INTRINSIC_MEMORY_COPY, ONYX_INTRINSIC_MEMORY_FILL,
 
-    ONYX_INTRINSIC_INITIALIZE,
+    ONYX_INTRINSIC_INITIALIZE, ONYX_INTRINSIC_ZERO_VALUE,
 
     ONYX_INTRINSIC_I32_CLZ,   ONYX_INTRINSIC_I32_CTZ, ONYX_INTRINSIC_I32_POPCNT,
     ONYX_INTRINSIC_I32_AND,   ONYX_INTRINSIC_I32_OR,  ONYX_INTRINSIC_I32_XOR,
@@ -533,6 +533,7 @@ struct AstRangeLiteral {
 struct AstCall {
     AstTyped_base;
 
+    Arguments original_args;
     Arguments args;
 
     union {
index b0d22e27cad61607aeb5a607c49d3c1584b7b342..950434e6021da21ccff3c89548ee7e3cdd8d3f95 100644 (file)
@@ -97,6 +97,7 @@ struct TypeWithOffset {
         bh_arr(StructMember *) memarr;                            \
         bh_arr(struct AstPolySolution) poly_sln;                  \
         bh_arr(TypeWithOffset) linear_members;                    \
+        struct AstType *constructed_from;                         \
     })                                                            \
     TYPE_KIND(Compound, struct {                                  \
         u32 count;                                                \
@@ -202,5 +203,6 @@ b32 type_is_structlike_strict(Type* type);
 u32 type_structlike_mem_count(Type* type);
 u32 type_structlike_is_simple(Type* type);
 b32 type_is_sl_constructable(Type* type);
+b32 type_struct_constructed_from_poly_struct(Type* struct_type, struct AstType* from);
 
 #endif // #ifndef ONYX_TYPES
index 37471aefe850830894e1086131c8a4a8eeff6f9f..e9fe9f094f8317d3808bad885596ccd6d1afa044 100644 (file)
@@ -88,6 +88,7 @@ static IntrinsicMap builtin_intrinsics[] = {
     { "memory_fill",  ONYX_INTRINSIC_MEMORY_FILL },
 
     { "__initialize", ONYX_INTRINSIC_INITIALIZE },
+    { "__zero_value", ONYX_INTRINSIC_ZERO_VALUE },
 
     { "clz_i32",      ONYX_INTRINSIC_I32_CLZ },
     { "ctz_i32",      ONYX_INTRINSIC_I32_CTZ },
index 32e91e7daf86a528351300f723c586fe85d9dc2b..b98e05531239a935359762283cc6f36c4287bbc2 100644 (file)
@@ -365,6 +365,10 @@ CheckStatus check_call(AstCall* call) {
     CHECK(expression, &call->callee);
     check_arguments(&call->args);
 
+    // SPEED CLEANUP: Keeping an original copy for basically no reason except that sometimes you
+    // need to know the baked argument values in code generation.
+    arguments_clone(&call->original_args, &call->args);
+
     if (call->callee->kind == Ast_Kind_Overloaded_Function) {
         call->callee = find_matching_overload_by_arguments(((AstOverloadedFunction *) call->callee)->overloads, &call->args);
         if (call->callee == NULL) {
index 7310b6f61214128599b1dbc513611375a9d3886a..22b410726d546b2f5c6606dc8552e883519fa5a3 100644 (file)
@@ -474,7 +474,9 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) {
             bh_arr_free(slns);
 
             if (!concrete) return NULL;
-            return type_build_from_ast(alloc, (AstType *) concrete);
+            Type* struct_type = type_build_from_ast(alloc, (AstType *) concrete);
+            struct_type->Struct.constructed_from = (AstType *) ps_type;
+            return struct_type;
         }
 
         case Ast_Kind_Type_Compound: {
@@ -1024,3 +1026,10 @@ b32 type_is_sl_constructable(Type* type) {
         default: return 0;
     }
 }
+
+b32 type_struct_constructed_from_poly_struct(Type* struct_type, struct AstType* from) {
+    DEBUG_HERE;
+    if (struct_type->kind != Type_Kind_Struct) return 0;
+
+    return struct_type->Struct.constructed_from == from;
+}
index 8c2365fdc4b296472a12faccf7403ed523953a0a..d427298a97b7b5a27e9b13f28050d15152927024 100644 (file)
@@ -240,6 +240,7 @@ 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(zero_value_for_type,           Type* type);
 
 EMIT_FUNC(enter_structured_block,        StructuredBlockType sbt);
 EMIT_FUNC_NO_ARGS(leave_structured_block);
@@ -1393,6 +1394,13 @@ EMIT_FUNC(intrinsic_call, AstCall* call) {
             break;
         }
 
+        case ONYX_INTRINSIC_ZERO_VALUE: {
+            // NOTE: This probably will not have to make an allocation.
+            Type* zero_type = type_build_from_ast(context.ast_alloc, (AstType *) ((AstArgument *) call->args.values[0])->value);
+            emit_zero_value_for_type(mod, &code, zero_type);
+            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;
@@ -2450,6 +2458,26 @@ EMIT_FUNC(zero_value, WasmType wt) {
     *pcode = code;
 }
 
+EMIT_FUNC(zero_value_for_type, Type* type) {
+    bh_arr(WasmInstruction) code = *pcode;
+    
+    if (type_is_structlike_strict(type)) {
+        i32 mem_count = type_linear_member_count(type);
+        TypeWithOffset two;
+
+        fori (i, 0, mem_count) {
+            type_linear_member_lookup(type, i, &two);
+            emit_zero_value_for_type(mod, &code, two.type);
+        }
+
+    } else {
+        WasmType wt = onyx_type_to_wasm_type(type);
+        emit_zero_value(mod, &code, wt);
+    }
+
+    *pcode = code;
+}
+
 static i32 generate_type_idx(OnyxWasmModule* mod, Type* ft) {
     if (ft->kind != Type_Kind_Function) return -1;