From: Brendan Hansen Date: Wed, 11 May 2022 00:53:22 +0000 (-0500) Subject: added '#tag' to procedures; use runtime.info.tagged_procedures X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=1a2312cc6705f34439e96b16f379ae068c1f2fde;p=onyx.git added '#tag' to procedures; use runtime.info.tagged_procedures --- diff --git a/core/container/map.onyx b/core/container/map.onyx index 1ab17a08..b8db2fb8 100644 --- a/core/container/map.onyx +++ b/core/container/map.onyx @@ -21,9 +21,10 @@ package core.map } } +#tag conv.Custom_Format.{ + #solidify format_map {K=Key_Type, V=Value_Type} +} Map :: struct (Key_Type: type_expr, Value_Type: type_expr) where ValidKey(Key_Type) { - #struct_tag conv.Custom_Format.{ #solidify format_map {K=Key_Type, V=Value_Type} }; - allocator : Allocator; hashes : [] i32; diff --git a/core/runtime/info/proc_tags.onyx b/core/runtime/info/proc_tags.onyx new file mode 100644 index 00000000..0c8c4336 --- /dev/null +++ b/core/runtime/info/proc_tags.onyx @@ -0,0 +1,12 @@ + +package runtime.info + +tagged_procedures: [] ^Tagged_Procedure + +Tagged_Procedure :: struct { + // This should be cast to the correct function type. + // i.e. *cast(^(i32, i32) -> i32) ^tagged_procedures[0].func; + func: () -> void; + type: type_expr; + tags: [] any; +} diff --git a/core/std.onyx b/core/std.onyx index ec79d75b..28a22830 100644 --- a/core/std.onyx +++ b/core/std.onyx @@ -36,8 +36,6 @@ package core #load "./runtime/common" #load "./runtime/info/helper" -#load "./runtime/info/types" -#load "./runtime/info/foreign_blocks" #load "./arg_parse" diff --git a/include/astnodes.h b/include/astnodes.h index 740667e1..16acbc5f 100644 --- a/include/astnodes.h +++ b/include/astnodes.h @@ -1192,6 +1192,8 @@ struct AstFunction { ConstraintContext constraints; + bh_arr(AstTyped *) tags; + // Polymorphic procedures use the following fields Scope *parent_scope_of_poly_proc; bh_arr(AstPolyParam) poly_params; @@ -1589,6 +1591,7 @@ extern AstType *builtin_code_type; extern AstTyped *type_table_node; extern AstTyped *foreign_blocks_node; extern AstType *foreign_block_type; +extern AstTyped *tagged_procedures_node; extern AstFunction *builtin_initialize_data_segments; extern AstFunction *builtin_run_init_procedures; extern bh_arr(AstFunction *) init_procedures; @@ -1769,6 +1772,7 @@ static inline void convert_polyproc_to_function(AstFunction *func) { func->poly_scope = NULL; func->entity = NULL; func->type = NULL; + func->tags = NULL; } static inline void convert_function_to_polyproc(AstFunction *func) { diff --git a/include/parser.h b/include/parser.h index 70a35b96..054dd757 100644 --- a/include/parser.h +++ b/include/parser.h @@ -32,6 +32,8 @@ typedef struct OnyxParser { bh_arr(AstFlags) scope_flags; + bh_arr(AstTyped *) stored_tags; + b32 hit_unexpected_token : 1; b32 parse_calls : 1; diff --git a/include/wasm_emit.h b/include/wasm_emit.h index c9f10ab0..c1675308 100644 --- a/include/wasm_emit.h +++ b/include/wasm_emit.h @@ -648,6 +648,8 @@ typedef struct OnyxWasmModule { bh_arr(AstForeignBlock *) foreign_blocks; u32 next_foreign_block_idx; + bh_arr(AstFunction *) procedures_with_tags; + // NOTE: Used internally as a map from strings that represent function types, // 0x7f 0x7f : 0x7f ( (i32, i32) -> i32 ) // to the function type index if it has been created. diff --git a/src/builtins.c b/src/builtins.c index 3655d2d6..9e9b16c5 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -63,6 +63,7 @@ AstType *builtin_code_type; AstTyped *type_table_node = NULL; AstTyped *foreign_blocks_node = NULL; AstType *foreign_block_type = NULL; +AstTyped *tagged_procedures_node = NULL; AstFunction *builtin_initialize_data_segments = NULL; AstFunction *builtin_run_init_procedures = NULL; bh_arr(AstFunction *) init_procedures = NULL; @@ -462,6 +463,7 @@ void initialize_builtins(bh_allocator a) { type_table_node = (AstTyped *) symbol_raw_resolve(p->scope, "type_table"); foreign_blocks_node = (AstTyped *) symbol_raw_resolve(p->scope, "foreign_blocks"); foreign_block_type = (AstType *) symbol_raw_resolve(p->scope, "foreign_block"); + tagged_procedures_node = (AstTyped *) symbol_raw_resolve(p->scope, "tagged_procedures"); } fori (i, 0, Binary_Op_Count) { diff --git a/src/checker.c b/src/checker.c index 52b10f94..a9941989 100644 --- a/src/checker.c +++ b/src/checker.c @@ -2100,6 +2100,14 @@ CheckStatus check_function(AstFunction* func) { if (func->entity_header && func->entity_header->state < Entity_State_Code_Gen) YIELD(func->token->pos, "Waiting for procedure header to pass type-checking"); + bh_arr_each(AstTyped *, pexpr, func->tags) { + CHECK(expression, pexpr); + + if (((*pexpr)->flags & Ast_Flag_Comptime) == 0) { + ERROR((*pexpr)->token->pos, "#tag expressions should be compile time known."); + } + } + inside_for_iterator = 0; expected_return_type = &func->type->Function.return_type; if (func->body) { diff --git a/src/clone.c b/src/clone.c index 9c92cfda..b1a2a98d 100644 --- a/src/clone.c +++ b/src/clone.c @@ -452,7 +452,7 @@ AstNode* ast_clone(bh_allocator a, void* n) { captured_entities = NULL; df->params = NULL; - bh_arr_new(global_heap_allocator, df->params, bh_arr_length(sf->params)); + bh_arr_new(context.ast_alloc, df->params, bh_arr_length(sf->params)); bh_arr_each(AstParam, param, sf->params) { AstParam new_param = { 0 }; @@ -470,13 +470,20 @@ AstNode* ast_clone(bh_allocator a, void* n) { if (sf->constraints.constraints) { memset(&df->constraints, 0, sizeof(ConstraintContext)); - bh_arr_new(global_heap_allocator, df->constraints.constraints, bh_arr_length(sf->constraints.constraints)); + bh_arr_new(context.ast_alloc, df->constraints.constraints, bh_arr_length(sf->constraints.constraints)); bh_arr_each(AstConstraint *, constraint, sf->constraints.constraints) { bh_arr_push(df->constraints.constraints, (AstConstraint *) ast_clone(a, (AstNode *) *constraint)); } } + if (sf->tags) { + bh_arr_new(context.ast_alloc, df->tags, bh_arr_length(sf->tags)); + bh_arr_each(AstTyped *, pexpr, sf->tags) { + bh_arr_push(df->tags, (AstTyped *) ast_clone(a, (AstNode *) *pexpr)); + } + } + break; } diff --git a/src/onyx.c b/src/onyx.c index 9154d8a3..69dd81aa 100644 --- a/src/onyx.c +++ b/src/onyx.c @@ -270,6 +270,12 @@ static void context_init(CompileOptions* opts) { .package = NULL, .include = create_load(context.ast_alloc, "core/runtime/info/foreign_blocks"), })); + entity_heap_insert(&context.entities, ((Entity) { + .state = Entity_State_Parse_Builtin, + .type = Entity_Type_Load_File, + .package = NULL, + .include = create_load(context.ast_alloc, "core/runtime/info/proc_tags"), + })); entity_heap_insert(&context.entities, ((Entity) { .state = Entity_State_Parse_Builtin, diff --git a/src/parser.c b/src/parser.c index defe9802..8c7ad4ed 100644 --- a/src/parser.c +++ b/src/parser.c @@ -176,6 +176,36 @@ static b32 next_tokens_are(OnyxParser* parser, i32 n, ...) { } +static void expect_no_stored_tags_pos(OnyxParser *parser, OnyxFilePos pos) { + if (bh_arr_length(parser->stored_tags) > 0) { + onyx_report_error(pos, Error_Critical, "#tag is not allowed on this element."); + parser->hit_unexpected_token = 1; + } +} + +static void expect_no_stored_tags(OnyxParser *parser) { + expect_no_stored_tags_pos(parser, parser->curr->pos); +} + +static void flush_stored_tags(OnyxParser *parser, bh_arr(AstTyped *) *out_arr) { + if (bh_arr_length(parser->stored_tags) == 0) return; + + bh_arr(AstTyped *) arr = *out_arr; + + if (arr == NULL) { + bh_arr_new(parser->allocator, arr, bh_arr_length(parser->stored_tags)); + } + + bh_arr_each(AstTyped *, pexpr, parser->stored_tags) { + bh_arr_push(arr, *pexpr); + } + + bh_arr_clear(parser->stored_tags); + + *out_arr = arr; +} + + // TODO: Make parsing numeric literals not rely on the C standard libary. static AstNumLit* parse_int_literal(OnyxParser* parser) { AstNumLit* int_node = make_node(AstNumLit, Ast_Kind_NumLit); @@ -1921,6 +1951,8 @@ static AstStructType* parse_struct(OnyxParser* parser) { s_node = make_node(AstStructType, Ast_Kind_Struct_Type); s_node->token = s_token; + flush_stored_tags(parser, &s_node->meta_tags); + // Parse polymorphic parameters if (consume_token_if_next(parser, '(')) { bh_arr(AstPolyStructParam) poly_params = NULL; @@ -1987,8 +2019,6 @@ static AstStructType* parse_struct(OnyxParser* parser) { } } - bh_arr(AstTyped *) struct_meta_tags=NULL; - expect_token(parser, '{'); b32 member_is_used = 0; @@ -1998,15 +2028,6 @@ static AstStructType* parse_struct(OnyxParser* parser) { while (!consume_token_if_next(parser, '}')) { if (parser->hit_unexpected_token) return s_node; - if (parse_possible_directive(parser, "struct_tag")) { - if (struct_meta_tags == NULL) bh_arr_new(global_heap_allocator, struct_meta_tags, 1); - AstTyped* expr = parse_expression(parser, 0); - bh_arr_push(struct_meta_tags, expr); - - consume_token_if_next(parser, ';'); - continue; - } - if (parse_possible_directive(parser, "persist")) { struct_type_create_scope(parser, s_node); @@ -2095,7 +2116,6 @@ static AstStructType* parse_struct(OnyxParser* parser) { expect_token(parser, ';'); } - s_node->meta_tags = struct_meta_tags; if (s_node->scope) parser->current_scope = parser->current_scope->parent; bh_arr_free(member_list_temp); @@ -2360,6 +2380,8 @@ static AstFunction* parse_function_definition(OnyxParser* parser, OnyxToken* tok func_def->token = token; bh_arr_push(parser->current_function_stack, func_def); + flush_stored_tags(parser, &func_def->tags); + bh_arr_new(global_heap_allocator, func_def->params, 4); bh_arr(AstPolyParam) polymorphic_vars = NULL; @@ -2660,6 +2682,8 @@ static b32 parse_possible_quick_function_definition(OnyxParser* parser, AstTyped } static AstTyped* parse_global_declaration(OnyxParser* parser) { + expect_no_stored_tags(parser); + AstGlobal* global_node = make_node(AstGlobal, Ast_Kind_Global); global_node->token = expect_token(parser, Token_Type_Keyword_Global); @@ -2671,12 +2695,16 @@ static AstTyped* parse_global_declaration(OnyxParser* parser) { } static AstEnumType* parse_enum_declaration(OnyxParser* parser) { + expect_no_stored_tags(parser); + AstEnumType* enum_node = make_node(AstEnumType, Ast_Kind_Enum_Type); enum_node->token = expect_token(parser, Token_Type_Keyword_Enum); bh_arr_new(global_heap_allocator, enum_node->values, 4); while (parser->curr->type == '#') { + if (parser->hit_unexpected_token) return enum_node; + if (parse_possible_directive(parser, "flags")) { enum_node->is_flags = 1; } else { @@ -2720,6 +2748,8 @@ static AstEnumType* parse_enum_declaration(OnyxParser* parser) { } static AstIf* parse_static_if_stmt(OnyxParser* parser, b32 parse_block_as_statements) { + expect_no_stored_tags(parser); + AstIf* static_if_node = make_node(AstIf, Ast_Kind_Static_If); static_if_node->token = expect_token(parser, '#'); static_if_node->defined_in_scope = parser->current_scope; @@ -2769,6 +2799,8 @@ static AstIf* parse_static_if_stmt(OnyxParser* parser, b32 parse_block_as_statem static AstMemRes* parse_memory_reservation(OnyxParser* parser, OnyxToken* symbol, b32 threadlocal) { expect_token(parser, ':'); + expect_no_stored_tags(parser); + AstMemRes* memres = make_node(AstMemRes, Ast_Kind_Memres); memres->threadlocal = threadlocal; memres->token = symbol; @@ -2784,6 +2816,8 @@ static AstMemRes* parse_memory_reservation(OnyxParser* parser, OnyxToken* symbol } static AstMacro* parse_macro(OnyxParser* parser) { + expect_no_stored_tags(parser); + AstMacro* macro = make_node(AstMacro, Ast_Kind_Macro); macro->token = expect_token(parser, Token_Type_Keyword_Macro); @@ -2913,7 +2947,8 @@ static char* generate_name_within_scope(OnyxParser* parser, OnyxToken* symbol) { } static AstBinding* parse_top_level_binding(OnyxParser* parser, OnyxToken* symbol) { - expect_token(parser, ':'); + OnyxToken *after_second_colon = expect_token(parser, ':'); + if (after_second_colon) after_second_colon += 1; AstTyped* node = parse_top_level_expression(parser); if (parser->hit_unexpected_token || node == NULL) @@ -2978,6 +3013,7 @@ default_case: binding->token = symbol; binding->node = (AstNode *) node; + if (after_second_colon) expect_no_stored_tags_pos(parser, after_second_colon->pos); return binding; } @@ -3197,6 +3233,11 @@ static void parse_top_level_statement(OnyxParser* parser) { ENTITY_SUBMIT(library); return; } + else if (parse_possible_directive(parser, "tag")) { + AstTyped *expr = parse_expression(parser, 0); + bh_arr_push(parser->stored_tags, expr); + return; + } else { OnyxToken* directive_token = expect_token(parser, '#'); OnyxToken* symbol_token = expect_token(parser, Token_Type_Symbol); @@ -3339,6 +3380,7 @@ OnyxParser onyx_parser_create(bh_allocator alloc, OnyxTokenizer *tokenizer) { parser.current_symbol_stack = NULL; parser.current_function_stack = NULL; parser.scope_flags = NULL; + parser.stored_tags = NULL; parser.parse_calls = 1; parser.polymorph_context = (PolymorphicContext) { @@ -3349,6 +3391,7 @@ OnyxParser onyx_parser_create(bh_allocator alloc, OnyxTokenizer *tokenizer) { bh_arr_new(global_heap_allocator, parser.alternate_entity_placement_stack, 4); bh_arr_new(global_heap_allocator, parser.current_symbol_stack, 4); bh_arr_new(global_heap_allocator, parser.scope_flags, 4); + bh_arr_new(global_heap_allocator, parser.stored_tags, 4); return parser; } diff --git a/src/symres.c b/src/symres.c index b5edf7ac..01a86c16 100644 --- a/src/symres.c +++ b/src/symres.c @@ -1148,6 +1148,10 @@ SymresStatus symres_function(AstFunction* func) { } } + bh_arr_each(AstTyped *, pexpr, func->tags) { + SYMRES(expression, pexpr); + } + func->flags |= Ast_Flag_Has_Been_Symres; } diff --git a/src/wasm_emit.c b/src/wasm_emit.c index 9ddd934a..a20c7e7a 100644 --- a/src/wasm_emit.c +++ b/src/wasm_emit.c @@ -187,6 +187,24 @@ static u64 local_lookup_idx(LocalAllocator* la, u64 value) { } +static inline b32 should_emit_function(AstFunction* fd) { + // NOTE: Don't output intrinsic functions + if (fd->is_intrinsic) return 0; + + // NOTE: Don't output functions that are not used, only if + // they are also not exported. + if ((fd->flags & Ast_Flag_Function_Used) == 0) { + if (fd->is_exported || bh_arr_length(fd->tags) > 0) { + return 1; + } else { + return 0; + } + } + + return 1; +} + + typedef enum StructuredBlockType StructuredBlockType; enum StructuredBlockType { SBT_Basic_Block, // Cannot be targeted using jump @@ -3338,23 +3356,6 @@ static i32 get_element_idx(OnyxWasmModule* mod, AstFunction* func) { } } -static inline b32 should_emit_function(AstFunction* fd) { - // NOTE: Don't output intrinsic functions - if (fd->is_intrinsic) return 0; - - // NOTE: Don't output functions that are not used, only if - // they are also not exported. - if ((fd->flags & Ast_Flag_Function_Used) == 0) { - if (fd->is_exported) { - return 1; - } else { - return 0; - } - } - - return 1; -} - static void emit_function(OnyxWasmModule* mod, AstFunction* fd) { if (!should_emit_function(fd)) return; @@ -3734,6 +3735,13 @@ static void emit_memory_reservation(OnyxWasmModule* mod, AstMemRes* memres) { return; } + if (tagged_procedures_node != NULL && (AstMemRes *) tagged_procedures_node == memres) { + u64 tagged_procedures_location = build_tagged_procedures(mod); + memres->addr = tagged_procedures_location; + + return; + } + if (memres->threadlocal) { memres->addr = mod->next_tls_offset; bh_align(memres->addr, alignment); @@ -3876,6 +3884,8 @@ OnyxWasmModule onyx_wasm_module_create(bh_allocator alloc) { .foreign_blocks = NULL, .next_foreign_block_idx = 0, + + .procedures_with_tags = NULL }; bh_arena* eid = bh_alloc(global_heap_allocator, sizeof(bh_arena)); @@ -3909,6 +3919,7 @@ OnyxWasmModule onyx_wasm_module_create(bh_allocator alloc) { bh_arr_new(global_heap_allocator, module.local_allocations, 4); bh_arr_new(global_heap_allocator, module.stack_leave_patches, 4); bh_arr_new(global_heap_allocator, module.foreign_blocks, 4); + bh_arr_new(global_heap_allocator, module.procedures_with_tags, 4); if (context.options->use_multi_threading) { WasmImport mem_import = { @@ -3982,6 +3993,10 @@ void emit_entity(Entity* ent) { if (ent->function->flags & Ast_Flag_Proc_Is_Null) { if (module->null_proc_func_idx == -1) module->null_proc_func_idx = get_element_idx(module, ent->function); } + + if (ent->function->tags != NULL) { + bh_arr_push(module->procedures_with_tags, ent->function); + } break; case Entity_Type_Global_Header: diff --git a/src/wasm_type_table.h b/src/wasm_type_table.h index 80ed9df2..0b13fe77 100644 --- a/src/wasm_type_table.h +++ b/src/wasm_type_table.h @@ -8,7 +8,7 @@ typedef struct StructMethodData { u32 data_loc; } StructMethodData; -u64 build_type_table(OnyxWasmModule* module) { +static u64 build_type_table(OnyxWasmModule* module) { bh_arr(u32) base_patch_locations=NULL; bh_arr_new(global_heap_allocator, base_patch_locations, 256); @@ -603,7 +603,7 @@ u64 build_type_table(OnyxWasmModule* module) { -static b32 build_foreign_blocks(OnyxWasmModule* module) { +static u64 build_foreign_blocks(OnyxWasmModule* module) { bh_arr(u32) base_patch_locations=NULL; bh_arr_new(global_heap_allocator, base_patch_locations, 256); @@ -744,5 +744,153 @@ static b32 build_foreign_blocks(OnyxWasmModule* module) { return global_data_ptr; +#undef WRITE_SLICE +#undef WRITE_PTR #undef PATCH -} \ No newline at end of file +} + + + +static u64 build_tagged_procedures(OnyxWasmModule *module) { + bh_arr(u32) base_patch_locations=NULL; + bh_arr_new(global_heap_allocator, base_patch_locations, 256); + +#define PATCH (bh_arr_push(base_patch_locations, tag_proc_buffer.length)) +#define WRITE_PTR(val) \ + bh_buffer_align(&tag_proc_buffer, POINTER_SIZE); \ + PATCH; \ + if (POINTER_SIZE == 4) bh_buffer_write_u32(&tag_proc_buffer, val); \ + if (POINTER_SIZE == 8) bh_buffer_write_u64(&tag_proc_buffer, val); +#define WRITE_SLICE(ptr, count) \ + WRITE_PTR(ptr); \ + if (POINTER_SIZE == 4) bh_buffer_write_u32(&tag_proc_buffer, count); \ + if (POINTER_SIZE == 8) bh_buffer_write_u64(&tag_proc_buffer, count); + + #if (POINTER_SIZE == 4) + #define Tagged_Procedure_Type u32 + #else + #define Tagged_Procedure_Type u64 + #endif + u32 proc_count = bh_arr_length(module->procedures_with_tags); + Tagged_Procedure_Type* tag_proc_info = bh_alloc_array(global_heap_allocator, Tagged_Procedure_Type, proc_count); // HACK + memset(tag_proc_info, 0, proc_count * sizeof(Tagged_Procedure_Type)); + + bh_buffer tag_proc_buffer; + bh_buffer_init(&tag_proc_buffer, global_heap_allocator, 4096); + + // + // This is necessary because 0 is an invalid offset to store in this + // buffer, as 0 will map to NULL. This could be a single byte insertion, + // but 64 bytes keeps better alignment. + bh_buffer_write_u64(&tag_proc_buffer, 0); + + u32 index = 0; + bh_arr_each(AstFunction *, pfunc, module->procedures_with_tags) { + AstFunction *func = *pfunc; + if (!should_emit_function(func)) { + proc_count--; + continue; + } + + u32 tag_count = bh_arr_length(func->tags); + u32 *tag_data_offsets = bh_alloc_array(global_scratch_allocator, u32, tag_count); + u32 *tag_data_types = bh_alloc_array(global_scratch_allocator, u32, tag_count); + + u32 tag_index = 0; + bh_arr_each(AstTyped *, ptag, func->tags) { + AstTyped *tag = *ptag; + bh_buffer_align(&tag_proc_buffer, type_alignment_of(tag->type)); + + tag_data_offsets[tag_index ] = tag_proc_buffer.length; + tag_data_types [tag_index++] = tag->type->id; + + u32 size = type_size_of(tag->type); + bh_buffer_grow(&tag_proc_buffer, tag_proc_buffer.length + size); + u8* buffer = tag_proc_buffer.data + tag_proc_buffer.length; + emit_raw_data(module, buffer, tag); + tag_proc_buffer.length += size; + } + + bh_buffer_align(&tag_proc_buffer, 4); + u32 tag_array_base = tag_proc_buffer.length; + fori (i, 0, tag_count) { + PATCH; + bh_buffer_write_u32(&tag_proc_buffer, tag_data_offsets[i]); + bh_buffer_write_u32(&tag_proc_buffer, tag_data_types[i]); + } + + bh_buffer_align(&tag_proc_buffer, 4); + tag_proc_info[index++] = tag_proc_buffer.length; + + bh_buffer_write_u32(&tag_proc_buffer, get_element_idx(module, func)); + bh_buffer_write_u32(&tag_proc_buffer, func->type->id); + WRITE_SLICE(tag_array_base, tag_count); + } + + if (context.options->verbose_output == 1) { + bh_printf("Foreign blocks size: %d bytes.\n", tag_proc_buffer.length); + } + + u32 offset = module->next_datum_offset; + bh_align(offset, 8); + + u64 tagged_procedures_location = offset; + + WasmDatum tagged_procedures_data = { + .offset = offset, + .length = proc_count * POINTER_SIZE, + .data = tag_proc_info, + }; + bh_arr_push(module->data, tagged_procedures_data); + + offset += tagged_procedures_data.length; + + fori (i, 0, proc_count) { + tag_proc_info[i] += offset; + } + + bh_arr_each(u32, patch_loc, base_patch_locations) { + if (POINTER_SIZE == 4) { + u32* loc = bh_pointer_add(tag_proc_buffer.data, *patch_loc); + if (*loc == 0) continue; + + *loc += offset; + } + if (POINTER_SIZE == 8) { + u64* loc = bh_pointer_add(tag_proc_buffer.data, *patch_loc); + if (*loc == 0) continue; + + *loc += offset; + } + } + + WasmDatum tagged_procedures_info_data = { + .offset = offset, + .length = tag_proc_buffer.length, + .data = tag_proc_buffer.data, + }; + bh_arr_push(module->data, tagged_procedures_info_data); + offset += tagged_procedures_info_data.length; + + u64 global_data_ptr = offset; + + Tagged_Procedure_Type* tmp_data = bh_alloc(global_heap_allocator, 2 * POINTER_SIZE); + tmp_data[0] = tagged_procedures_location; + tmp_data[1] = proc_count; + WasmDatum tagged_procedures_global_data = { + .offset = offset, + .length = 2 * POINTER_SIZE, + .data = tmp_data, + }; + bh_arr_push(module->data, tagged_procedures_global_data); + offset += tagged_procedures_global_data.length; + + module->next_datum_offset = offset; + + return global_data_ptr; + +#undef WRITE_SLICE +#undef WRITE_PTR +#undef PATCH +} + diff --git a/tests/interfaces.onyx b/tests/interfaces.onyx index 69c1eb1a..f65fe987 100644 --- a/tests/interfaces.onyx +++ b/tests/interfaces.onyx @@ -53,10 +53,10 @@ BitField :: interface (t: $T) { { t ^ t } -> T; } +#tag conv.Custom_Format.{ Complex.format } Complex :: struct { x, y: f32; - #struct_tag conv.Custom_Format.{ format } format :: (output: ^conv.Format_Output, format: ^conv.Format, c: ^Complex) { conv.format(output, "{.2} + {.2}i", c.x, c.y); }