#include "assembler.h" #include #include #include #include #include #include #include #include #include struct constpool_assembler_scope { struct assembler_scope s_base; b_dict *s_strings; }; static enum ivy_status init_scope( struct ivy_assembler *as, struct assembler_scope *scope, const ivy_assembler_attrib_table attrib) { struct ivy_bin_constpool header = {0}; assembler_write_data(as, &header, sizeof header); struct constpool_assembler_scope *c = (struct constpool_assembler_scope *)scope; c->s_strings = b_dict_create(); return IVY_OK; } static ivy_extended_data_key get_cached_string( struct constpool_assembler_scope *scope, const char *s) { b_number *key = B_NUMBER(b_dict_at(scope->s_strings, s)); if (!key) { return IVY_EX_DATA_KEY_NULL; } return (ivy_extended_data_key)b_number_get_int32(key); } static void put_cached_string( struct constpool_assembler_scope *scope, const char *s, ivy_extended_data_key key) { b_dict_put(scope->s_strings, s, B_RV_INT32(key)); } static ivy_extended_data_key write_string(struct ivy_assembler *as, const char *s) { struct constpool_assembler_scope *scope = (struct constpool_assembler_scope *)assembler_get_scope(as); ivy_extended_data_key key = get_cached_string(scope, s); if (key != IVY_EX_DATA_KEY_NULL) { return key; } size_t len = strlen(s); struct ivy_bin_string str = {0}; str.s_hash = b_i32_htob((uint32_t)b_hash_string(s)); str.s_len = b_i32_htob((uint32_t)len); key = assembler_write_extended_data(as, &str, sizeof str); assembler_write_extended_data(as, s, len); put_cached_string(scope, s, key); return key; } static ivy_extended_data_key write_selector( struct ivy_assembler *as, const struct ivy_selector *sel) { struct ivy_bin_selector dat = {0}; switch (sel->sel_recipient) { case IVY_SEL_CLASS: dat.sel_flags = IVY_BIN_SELECTOR_CLASS; break; case IVY_SEL_OBJECT: dat.sel_flags = IVY_BIN_SELECTOR_OBJECT; break; default: return IVY_EX_DATA_KEY_NULL; } if (sel->sel_name) { dat.sel_name = b_i32_htob(write_string(as, sel->sel_name)); } size_t i = 0; size_t nr_args = b_queue_length(&sel->sel_args); dat.sel_nr_args = (uint8_t)nr_args; /* TODO hash. */ ivy_extended_data_key *arg_handles = calloc(nr_args, sizeof(ivy_extended_data_key)); b_queue_iterator it = {0}; b_queue_foreach (&it, &sel->sel_args) { struct ivy_selector_arg *arg = b_unbox(struct ivy_selector_arg, it.entry, arg_entry); arg_handles[i++] = write_string(as, arg->arg_label); } ivy_extended_data_key selector_handle = assembler_write_extended_data(as, &dat, sizeof dat); for (i = 0; i < nr_args; i++) { b_i32 arg_handle = b_i32_htob(arg_handles[i]); assembler_write_extended_data(as, &arg_handle, sizeof arg_handle); } free(arg_handles); return selector_handle; } static ivy_extended_data_key write_ident( struct ivy_assembler *as, const struct ivy_ident *id) { struct ivy_bin_ident dat = {0}; /* TODO hash. */ size_t nr_parts = b_queue_length(&id->id_parts); size_t i = 0; ivy_extended_data_key *part_handles = calloc(nr_parts, sizeof(ivy_extended_data_key)); b_queue_iterator it = {0}; b_queue_foreach (&it, &id->id_parts) { struct ivy_ident_part *arg = b_unbox(struct ivy_ident_part, it.entry, p_entry); part_handles[i++] = write_string(as, arg->p_str); } dat.id_nr_parts = (uint8_t)nr_parts; ivy_extended_data_key ident_handle = assembler_write_extended_data(as, &dat, sizeof dat); for (i = 0; i < nr_parts; i++) { b_i32 part_handle = b_i32_htob(part_handles[i]); assembler_write_extended_data(as, &part_handle, sizeof part_handle); } free(part_handles); return ident_handle; } static enum ivy_status put_pval( struct ivy_assembler *as, struct assembler_scope *scope, enum ivy_assembler_pval_type type, const void *val, ivy_extended_data_key *key) { struct ivy_bin_constpool_table_entry entry = {0}; uintptr_t i = *(uintptr_t *)val; ivy_extended_data_key k = IVY_EX_DATA_KEY_NULL; switch (type) { case IVY_ASM_PVAL_STRING: entry.e_type = b_i32_htob(IVY_CONSTPOOL_TABLE_STRING); k = write_string(as, val); entry.e_ex_handle = b_i32_htob(k); break; case IVY_ASM_PVAL_IDENT: entry.e_type = b_i32_htob(IVY_CONSTPOOL_TABLE_IDENT); k = write_ident(as, val); entry.e_ex_handle = b_i32_htob(k); break; case IVY_ASM_PVAL_ATOM: entry.e_type = b_i32_htob(IVY_CONSTPOOL_TABLE_ATOM); k = write_string(as, val); entry.e_ex_handle = b_i32_htob(k); break; case IVY_ASM_PVAL_SINT: entry.e_type = b_i32_htob(IVY_CONSTPOOL_TABLE_INT); entry.e_int = b_i32_htob((uint32_t)i); break; case IVY_ASM_PVAL_UINT: entry.e_type = b_i32_htob(IVY_CONSTPOOL_TABLE_UINT); entry.e_int = b_i32_htob((uint32_t)i); break; case IVY_ASM_PVAL_SELECTOR: entry.e_type = b_i32_htob(IVY_CONSTPOOL_TABLE_SELECTOR); k = write_selector(as, val); entry.e_ex_handle = b_i32_htob(k); break; default: return IVY_ERR_NOT_SUPPORTED; } if (key) { *key = k; } assembler_write_data(as, &entry, sizeof entry); return IVY_OK; } const struct assembler_scope_type constpool_scope_type = { .s_scope_size = sizeof(struct constpool_assembler_scope), .s_init_scope = init_scope, .s_put_pval = put_pval, };