From: Brendan Hansen Date: Wed, 3 Feb 2021 21:20:52 +0000 (-0600) Subject: added bulk-memory intrinsics; bug fix X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=c27d600e024f6ad7397974a1889d1a3024962e73;p=onyx.git added bulk-memory intrinsics; bug fix --- diff --git a/bin/onyx b/bin/onyx index d7b1484a..732de5b6 100755 Binary files a/bin/onyx and b/bin/onyx differ diff --git a/core/intrinsics/wasm.onyx b/core/intrinsics/wasm.onyx index db95e792..0d2d115d 100644 --- a/core/intrinsics/wasm.onyx +++ b/core/intrinsics/wasm.onyx @@ -2,6 +2,8 @@ package core.intrinsics.wasm memory_size :: () -> i32 #intrinsic --- memory_grow :: (val: i32) -> i32 #intrinsic --- +memory_copy :: (dst: rawptr, src: rawptr, count: i32) -> void #intrinsic --- +memory_fill :: (dst: rawptr, byte: u8, count: i32) -> void #intrinsic --- clz_i32 :: (val: i32) -> i32 #intrinsic --- ctz_i32 :: (val: i32) -> i32 #intrinsic --- diff --git a/core/memory.onyx b/core/memory.onyx index 838acb58..ed6e2d94 100644 --- a/core/memory.onyx +++ b/core/memory.onyx @@ -8,14 +8,26 @@ package core.memory // However, it might be worth switching to an intrinsic completely // and having the intrinsic know whether or not to output the instruction // or an inlined version of this procedure. -copy :: (dst_: rawptr, src_: rawptr, len: u32) { +use package core.intrinsics.wasm { memory_copy, memory_fill } + +// Even though I thought this would work, this method of aliases functions +// does not currently work. There needs to be a second level of indirection +// on entities to allow for this case to work, which may not be hard to change +// but still needs to happen. +// copy :: memory_copy +// set :: memory_fill + +copy :: (dest: rawptr, src: rawptr, count: i32) do memory_copy(dest, src, count); +set :: (dest: rawptr, byte: u8, count: i32) do memory_fill(dest, byte, count); + +// Old and slow copy and set +copy_ :: (dst_: rawptr, src_: rawptr, len: u32) { dst := cast(^u8) dst_; src := cast(^u8) src_; for i: 0 .. len do dst[i] = src[i]; } -// The same thing goes for this procedure too. -set :: (start: rawptr, length: u32, value: u8) { +set_ :: (start: rawptr, value: u8, length: u32) { s := cast(^u8) start; for i: 0 .. length do s[i] = value; } diff --git a/include/onyxastnodes.h b/include/onyxastnodes.h index 7ca3b8f1..32fec4ec 100644 --- a/include/onyxastnodes.h +++ b/include/onyxastnodes.h @@ -276,6 +276,7 @@ typedef enum OnyxIntrinsic { ONYX_INTRINSIC_UNDEFINED, ONYX_INTRINSIC_MEMORY_SIZE, ONYX_INTRINSIC_MEMORY_GROW, + ONYX_INTRINSIC_MEMORY_COPY, ONYX_INTRINSIC_MEMORY_FILL, ONYX_INTRINSIC_I32_CLZ, ONYX_INTRINSIC_I32_CTZ, ONYX_INTRINSIC_I32_POPCNT, ONYX_INTRINSIC_I32_AND, ONYX_INTRINSIC_I32_OR, ONYX_INTRINSIC_I32_XOR, diff --git a/include/onyxwasm.h b/include/onyxwasm.h index 3d966549..2bd9816b 100644 --- a/include/onyxwasm.h +++ b/include/onyxwasm.h @@ -17,6 +17,7 @@ typedef struct WasmFuncType { } WasmFuncType; #define SIMD_INSTR_MASK 0x10000 +#define EXT_INSTR_MASK 0x20000 typedef enum WasmInstructionType { WI_UNREACHABLE = 0x00, @@ -410,6 +411,10 @@ typedef enum WasmInstructionType { WI_I32X4_TRUNC_SAT_F32X4_U = SIMD_INSTR_MASK | 249, WI_F32X4_CONVERT_I32X4_S = SIMD_INSTR_MASK | 250, WI_F32X4_CONVERT_I32X4_U = SIMD_INSTR_MASK | 251, + + + WI_MEMORY_COPY = EXT_INSTR_MASK | 0x0a, + WI_MEMORY_FILL = EXT_INSTR_MASK | 0x0b, } WasmInstructionType; typedef union { diff --git a/onyx.exe b/onyx.exe index 1506e5e5..1c6e8452 100644 Binary files a/onyx.exe and b/onyx.exe differ diff --git a/src/onyxbuiltins.c b/src/onyxbuiltins.c index a978e86c..4ce2a256 100644 --- a/src/onyxbuiltins.c +++ b/src/onyxbuiltins.c @@ -84,6 +84,8 @@ bh_table(OnyxIntrinsic) intrinsic_table; static IntrinsicMap builtin_intrinsics[] = { { "memory_size", ONYX_INTRINSIC_MEMORY_SIZE }, { "memory_grow", ONYX_INTRINSIC_MEMORY_GROW }, + { "memory_copy", ONYX_INTRINSIC_MEMORY_COPY }, + { "memory_fill", ONYX_INTRINSIC_MEMORY_FILL }, { "clz_i32", ONYX_INTRINSIC_I32_CLZ }, { "ctz_i32", ONYX_INTRINSIC_I32_CTZ }, diff --git a/src/onyxparser.c b/src/onyxparser.c index 7e834a3d..fe7a86a0 100644 --- a/src/onyxparser.c +++ b/src/onyxparser.c @@ -618,7 +618,7 @@ static AstTyped* parse_factor(OnyxParser* parser) { case Token_Type_Right_Arrow: { AstBinaryOp* method_call = make_node(AstBinaryOp, Ast_Kind_Method_Call); - method_call->token = expect_token(parser, Token_Type_Right_Arrow); + method_call->token = expect_token(parser, Token_Type_Right_Arrow); method_call->left = retval; method_call->right = parse_factor(parser); @@ -829,7 +829,7 @@ static AstIfWhile* parse_if_stmt(OnyxParser* parser) { AstIfWhile* root_if = if_node; // CLEANUP: All of the control blocks use this same kind of logic, and it - // is underpowered for what I think should be possible. Factor it out and + // is underpowered for what I think should be possible. Factor it out and // make it better? if (peek_token(1)->type == ':') { OnyxToken* local_sym = expect_token(parser, Token_Type_Symbol); @@ -1265,7 +1265,7 @@ static AstNode* parse_statement(OnyxParser* parser) { retval = parse_jump_stmt(parser, Token_Type_Keyword_Break, Jump_Type_Break); break; - case Token_Type_Keyword_Continue: + case Token_Type_Keyword_Continue: retval = parse_jump_stmt(parser, Token_Type_Keyword_Continue, Jump_Type_Continue); break; @@ -1640,7 +1640,7 @@ static AstStructType* parse_struct(OnyxParser* parser) { bh_arr_push(poly_params, ((AstPolyStructParam) { .token = sym_token, .type_node = param_type, - .type = NULL, + .type = NULL, })); if (parser->curr->type != ')') @@ -1742,7 +1742,7 @@ static AstStructType* parse_struct(OnyxParser* parser) { } bh_arr_each(OnyxToken *, member_name, member_list_temp) { - AstStructMember* mem = make_node(AstStructMember, Ast_Kind_Struct_Member); + AstStructMember* mem = make_node(AstStructMember, Ast_Kind_Struct_Member); mem->token = *member_name; mem->type_node = member_type; mem->initial_value = initial_value; @@ -1833,7 +1833,7 @@ static void parse_function_params(OnyxParser* parser, AstFunction* func) { curr_param.default_value = parse_expression(parser, 0); if (param_is_baked) { - param_is_baked = 0; + param_is_baked = 0; bh_arr(AstPolyParam) pv = *parser->polymorph_context.poly_params; bh_arr_push(pv, ((AstPolyParam) { @@ -2171,7 +2171,7 @@ static AstBinding* parse_top_level_binding(OnyxParser* parser, OnyxToken* symbol // HACK: This should maybe be entered elsewhere? ENTITY_SUBMIT(node); } - + AstBinding* binding = make_node(AstBinding, Ast_Kind_Binding); binding->token = symbol; binding->node = (AstNode *) node; diff --git a/src/onyxutils.c b/src/onyxutils.c index f0949321..b04cf5d3 100644 --- a/src/onyxutils.c +++ b/src/onyxutils.c @@ -123,10 +123,6 @@ AstNode* symbol_raw_resolve(Scope* start_scope, char* sym) { if (res == NULL) return NULL; - if (res->kind == Ast_Kind_Symbol) { - return symbol_resolve(start_scope, res->token); - } - return res; } diff --git a/src/onyxwasm.c b/src/onyxwasm.c index a0d90f42..18e384a9 100644 --- a/src/onyxwasm.c +++ b/src/onyxwasm.c @@ -1398,6 +1398,8 @@ EMIT_FUNC(intrinsic_call, AstCall* call) { switch (call->intrinsic) { case ONYX_INTRINSIC_MEMORY_SIZE: WID(WI_MEMORY_SIZE, 0x00); break; case ONYX_INTRINSIC_MEMORY_GROW: WID(WI_MEMORY_GROW, 0x00); break; + case ONYX_INTRINSIC_MEMORY_COPY: WIL(WI_MEMORY_COPY, 0x00); break; + case ONYX_INTRINSIC_MEMORY_FILL: WID(WI_MEMORY_FILL, 0x00); break; case ONYX_INTRINSIC_I32_CLZ: WI(WI_I32_CLZ); break; case ONYX_INTRINSIC_I32_CTZ: WI(WI_I32_CTZ); break; @@ -3502,6 +3504,11 @@ static void output_instruction(WasmFunc* func, WasmInstruction* instr, bh_buffer bh_buffer_write_byte(buff, 0xFD); leb = uint_to_uleb128((u64) (instr->type &~ SIMD_INSTR_MASK), &leb_len); bh_buffer_append(buff, leb, leb_len); + + } else if (instr->type & EXT_INSTR_MASK) { + bh_buffer_write_byte(buff, 0xFC); + leb = uint_to_uleb128((u64) (instr->type &~ EXT_INSTR_MASK), &leb_len); + bh_buffer_append(buff, leb, leb_len); } else { bh_buffer_write_byte(buff, (u8) instr->type); @@ -3527,9 +3534,18 @@ static void output_instruction(WasmFunc* func, WasmInstruction* instr, bh_buffer case WI_IF_START: case WI_MEMORY_SIZE: case WI_MEMORY_GROW: + case WI_MEMORY_FILL: leb = uint_to_uleb128((u64) instr->data.i1, &leb_len); bh_buffer_append(buff, leb, leb_len); break; + + case WI_MEMORY_COPY: + leb = uint_to_uleb128((u64) instr->data.i1, &leb_len); + bh_buffer_append(buff, leb, leb_len); + + leb = uint_to_uleb128((u64) instr->data.i2, &leb_len); + bh_buffer_append(buff, leb, leb_len); + break; case WI_JUMP_TABLE: { BranchTable* bt = (BranchTable *) instr->data.p; diff --git a/tests/aoc-2020/day19.onyx b/tests/aoc-2020/day19.onyx index d503098b..2dd97c4e 100644 --- a/tests/aoc-2020/day19.onyx +++ b/tests/aoc-2020/day19.onyx @@ -84,7 +84,7 @@ cyk_algorithm :: proc (use grammar: ^Grammar, input: str) -> bool { mem_size := sizeof bool * input.count * input.count * max_terminal; T := cast(^bool) calloc(mem_size); defer cfree(T); - memory.set(T, mem_size, ~~false); + memory.set(T, ~~false, mem_size); for s: 0 .. input.count { for ^term: terminate_rules { diff --git a/tests/aoc-2020/day20.onyx b/tests/aoc-2020/day20.onyx index b4fca178..a7fe3278 100644 --- a/tests/aoc-2020/day20.onyx +++ b/tests/aoc-2020/day20.onyx @@ -327,7 +327,7 @@ main :: proc (args: [] cstr) { printf("Corner product: %l\n", prod); grid : [12 * 12] u32; - memory.set(^grid, sizeof [12 * 12] u32, 0); + memory.set(^grid, 0, sizeof [12 * 12] u32); to_process : [..] tile_pos_state; array.init(^to_process);