diff --git a/asm/assembler/assembler.c b/asm/assembler/assembler.c index f0ed9ad..6e5525c 100644 --- a/asm/assembler/assembler.c +++ b/asm/assembler/assembler.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -7,24 +8,29 @@ #include "assembler.h" extern struct assembler_scope_type class_scope_type; -extern struct assembler_scope_type lambda_scope_type; -extern struct assembler_scope_type msgh_scope_type; -extern struct assembler_scope_type constpool_scope_type; static const struct assembler_scope_type *scope_types[] = { [IVY_ASM_SCOPE_CLASS] = &class_scope_type, - [IVY_ASM_SCOPE_LAMBDA] = &lambda_scope_type, - [IVY_ASM_SCOPE_MSGH] = &msgh_scope_type, - [IVY_ASM_SCOPE_CONSTPOOL] = &constpool_scope_type, }; static const size_t nr_scope_types = sizeof scope_types / sizeof scope_types[0]; -struct ivy_assembler { - FILE *as_fp; - struct assembler_scope *as_scope; +struct asm_table_entry { + b_queue_entry e_entry; + struct ivy_bin_table_entry e_data; }; -enum ivy_static ivy_assembler_create(FILE *fp, struct ivy_assembler **as) +struct ivy_assembler { + struct assembler_scope *as_scope; + b_queue as_table; + + FILE *as_data; + size_t as_data_offset; + + FILE *as_xdat; + extended_data_key as_next_xdata_key; +}; + +enum ivy_status ivy_assembler_create(FILE *fp, struct ivy_assembler **as) { struct ivy_assembler *out = malloc(sizeof *out); @@ -34,19 +40,122 @@ enum ivy_static ivy_assembler_create(FILE *fp, struct ivy_assembler **as) memset(out, 0x0, sizeof *out); - out->as_fp = fp; + out->as_data = fp; + out->as_xdat = tmpfile(); + + struct ivy_bin_header header = {0}; + + fseek(fp, 0, SEEK_SET); + fwrite(&header, sizeof header, 1, fp); *as = out; return IVY_OK; } -void ivy_assembler_destroy(struct ivy_assembler *as) +static void pad(struct ivy_assembler *as, unsigned int boundary) { + while ((as->as_data_offset % boundary) != 0) { + fputc(0, as->as_data); + as->as_data_offset++; + } +} + +enum ivy_status ivy_assembler_finish(struct ivy_assembler *as) +{ + const size_t buf_len = 4096; + size_t xdat_len = as->as_next_xdata_key; + + fseek(as->as_xdat, 0, SEEK_SET); + char *buf = malloc(buf_len); + + if (!buf) { + return IVY_ERR_NO_MEMORY; + } + + pad(as, 16); + + struct ivy_bin_table_entry xdat = {0}; + xdat.e_offset = b_i64_htob(as->as_data_offset); + xdat.e_size = b_i32_htob(xdat_len); + xdat.e_type = b_i32_htob(IVY_TABLE_XDAT); + + while (1) { + size_t r = fread(buf, 1, buf_len, as->as_xdat); + fwrite(buf, 1, r, as->as_xdat); + as->as_data_offset += r; + + if (r == buf_len) { + continue; + } + + if (ferror(as->as_xdat)) { + free(buf); + return IVY_ERR_IO_FAILURE; + } + + break; + } + + free(buf); + + unsigned int nr_table_entries = 0; + + struct ivy_bin_header header = {0}; + header.h_table_offset = b_i64_htob(as->as_data_offset); + header.h_table_len = b_i16_htob(0); + header.h_magic = b_i32_htob(IVY_BIN_MAGIC); + + pad(as, 16); + + b_queue_iterator it = {0}; + b_queue_foreach (&it, &as->as_table) { + struct asm_table_entry *e = b_unbox(struct asm_table_entry, it.entry, e_entry); + size_t w = fwrite(&e->e_data, 1, sizeof e->e_data, as->as_data); + + if (w < sizeof e->e_data) { + return IVY_ERR_IO_FAILURE; + } + + nr_table_entries++; + } + + fwrite(&xdat, 1, sizeof xdat, as->as_data); + nr_table_entries++; + + header.h_table_len = b_i16_htob(nr_table_entries * sizeof(struct ivy_bin_table_entry)); + + fseek(as->as_data, 0, SEEK_SET); + fwrite(&header, 1, sizeof header, as->as_data); + + fclose(as->as_xdat); free(as); + + return IVY_OK; +} + +size_t assembler_write_data(struct ivy_assembler *as, const void *p, size_t len) +{ + size_t offset = as->as_data_offset; + + fwrite(p, 1, len, as->as_data); + + as->as_data_offset += len; + return offset; +} + +extended_data_key assembler_write_extended_data(struct ivy_assembler *as, const void *p, size_t len) +{ + extended_data_key key = as->as_next_xdata_key; + + fwrite(p, 1, len, as->as_xdat); + + as->as_next_xdata_key += len; + return key; } enum ivy_status ivy_assembler_begin_scope( - struct ivy_assembler *as, enum ivy_assembler_scope_type type) + struct ivy_assembler *as, enum ivy_assembler_scope_type type, + ivy_assembler_attrib_table attrib) { if (type < 0 || type >= nr_scope_types) { return IVY_ERR_NOT_SUPPORTED; @@ -66,11 +175,18 @@ enum ivy_status ivy_assembler_begin_scope( return IVY_ERR_NO_MEMORY; } + while ((as->as_data_offset % 16) != 0) { + fputc(0, as->as_data); + as->as_data_offset++; + } + + scope->s_ops = type_info; scope->s_type = type; + scope->s_start_offset = as->as_data_offset; as->as_scope = scope; if (type_info->s_init_scope) { - type_info->s_init_scope(as, scope); + type_info->s_init_scope(as, scope, attrib); } return IVY_OK; @@ -91,14 +207,47 @@ enum ivy_status ivy_assembler_end_scope(struct ivy_assembler *as) type_info->s_finish_scope(as, as->as_scope); } + struct asm_table_entry *entry = malloc(sizeof *entry); + if (!entry) { + return IVY_ERR_NO_MEMORY; + } + + memset(entry, 0x0, sizeof *entry); + + entry->e_data.e_offset = b_i64_htob(as->as_scope->s_start_offset); + entry->e_data.e_size = b_i32_htob(as->as_data_offset - as->as_scope->s_start_offset); + + switch (as->as_scope->s_type) { + case IVY_ASM_SCOPE_CLASS: + entry->e_data.e_type = b_i32_htob(IVY_TABLE_CLASS); + break; + case IVY_ASM_SCOPE_LAMBDA: + entry->e_data.e_type = b_i32_htob(IVY_TABLE_LAMBDA); + break; + case IVY_ASM_SCOPE_MSGH: + entry->e_data.e_type = b_i32_htob(IVY_TABLE_MSGH); + break; + case IVY_ASM_SCOPE_CONSTPOOL: + entry->e_data.e_type = b_i32_htob(IVY_TABLE_POOL); + break; + case IVY_ASM_SCOPE_IMPORT: + entry->e_data.e_type = b_i32_htob(IVY_TABLE_IMPORT); + break; + default: + break; + } + + b_queue_push_back(&as->as_table, &entry->e_entry); + free(as->as_scope); as->as_scope = NULL; return IVY_OK; } -enum ivy_status ivy_assembler_put_string( - struct ivy_assembler *as, int index, const char *s) +enum ivy_status ivy_assembler_put_pval( + struct ivy_assembler *as, enum ivy_assembler_pval_type type, + unsigned long index, const void *val) { struct assembler_scope *scope = as->as_scope; @@ -107,15 +256,16 @@ enum ivy_status ivy_assembler_put_string( } const struct assembler_scope_type *type_info = scope->s_ops; - if (!type_info || !type_info->s_put_string) { + if (!type_info || !type_info->s_put_pval) { return IVY_ERR_NOT_SUPPORTED; } - return type_info->s_put_string(as, scope, index, s); + return type_info->s_put_pval(as, scope, type, index, val); } -enum ivy_status ivy_assembler_put_ident( - struct ivy_assembler *as, int index, const char *s) +enum ivy_status ivy_assembler_put_xval( + struct ivy_assembler *as, enum ivy_assembler_xval_type type, + const ivy_assembler_attrib_table attrib) { struct assembler_scope *scope = as->as_scope; @@ -124,62 +274,11 @@ enum ivy_status ivy_assembler_put_ident( } const struct assembler_scope_type *type_info = scope->s_ops; - if (!type_info || !type_info->s_put_string) { + if (!type_info || !type_info->s_put_xval) { return IVY_ERR_NOT_SUPPORTED; } - return type_info->s_put_string(as, scope, index, s); -} - -enum ivy_status ivy_assembler_put_atom( - struct ivy_assembler *as, int index, const char *s) -{ - struct assembler_scope *scope = as->as_scope; - - if (!scope) { - return IVY_ERR_NOT_SUPPORTED; - } - - const struct assembler_scope_type *type_info = scope->s_ops; - if (!type_info || !type_info->s_put_atom) { - return IVY_ERR_NOT_SUPPORTED; - } - - return type_info->s_put_atom(as, scope, index, s); -} - -enum ivy_status ivy_assembler_put_selector( - struct ivy_assembler *as, int index, struct ivy_selector *sel) -{ - struct assembler_scope *scope = as->as_scope; - - if (!scope) { - return IVY_ERR_NOT_SUPPORTED; - } - - const struct assembler_scope_type *type_info = scope->s_ops; - if (!type_info || !type_info->s_put_selector) { - return IVY_ERR_NOT_SUPPORTED; - } - - return type_info->s_put_selector(as, scope, index, sel); -} - -enum ivy_status ivy_assembler_put_mvar( - struct ivy_assembler *as, int index, const char *name) -{ - struct assembler_scope *scope = as->as_scope; - - if (!scope) { - return IVY_ERR_NOT_SUPPORTED; - } - - const struct assembler_scope_type *type_info = scope->s_ops; - if (!type_info || !type_info->s_put_mvar) { - return IVY_ERR_NOT_SUPPORTED; - } - - return type_info->s_put_mvar(as, scope, index, name); + return type_info->s_put_xval(as, scope, type, attrib); } enum ivy_status ivy_assembler_put_instr( diff --git a/asm/assembler/assembler.h b/asm/assembler/assembler.h index f110e53..a852db0 100644 --- a/asm/assembler/assembler.h +++ b/asm/assembler/assembler.h @@ -6,23 +6,46 @@ struct assembler_scope_type; +typedef size_t extended_data_key; + struct assembler_scope { enum ivy_assembler_scope_type s_type; + unsigned long s_attrib[__IVY_ASM_ATTRIB_COUNT]; struct assembler_scope_type *s_ops; + size_t s_start_offset; }; struct assembler_scope_type { size_t s_scope_size; - enum ivy_status(*s_init_scope)(struct ivy_assembler *, struct assembler_scope *); - enum ivy_status(*s_finish_scope)(struct ivy_assembler *, struct assembler_scope *); + enum ivy_status(*s_init_scope)( + struct ivy_assembler *, + struct assembler_scope *, + const ivy_assembler_attrib_table); - enum ivy_status(*s_put_string)(struct ivy_assembler *, struct assembler_scope *, long, const char *); - enum ivy_status(*s_put_ident)(struct ivy_assembler *, struct assembler_scope *, long, const char *); - enum ivy_status(*s_put_atom)(struct ivy_assembler *, struct assembler_scope *, long, const char *); - enum ivy_status(*s_put_selector)(struct ivy_assembler *, struct assembler_scope *, long, const struct ivy_selector *); - enum ivy_status(*s_put_mvar)(struct ivy_assembler *, struct assembler_scope *, long, const char *); - enum ivy_status(*s_put_instr)(struct ivy_assembler *, struct assembler_scope *, const struct ivy_instr *); + enum ivy_status(*s_finish_scope)( + struct ivy_assembler *, + struct assembler_scope *); + + enum ivy_status(*s_put_pval)(struct ivy_assembler *, + struct assembler_scope *, + enum ivy_assembler_pval_type, + unsigned long, + const void *); + + enum ivy_status(*s_put_xval)( + struct ivy_assembler *, + struct assembler_scope *, + enum ivy_assembler_xval_type, + const ivy_assembler_attrib_table); + + enum ivy_status(*s_put_instr)( + struct ivy_assembler *, + struct assembler_scope *, + const struct ivy_instr *); }; +extern size_t assembler_write_data(struct ivy_assembler *as, const void *p, size_t len); +extern extended_data_key assembler_write_extended_data(struct ivy_assembler *as, const void *p, size_t len); + #endif \ No newline at end of file diff --git a/asm/assembler/class.c b/asm/assembler/class.c index d22f0fe..dd54a8c 100644 --- a/asm/assembler/class.c +++ b/asm/assembler/class.c @@ -1,9 +1,47 @@ #include "assembler.h" +#include -struct class_scope { +static enum ivy_status init_scope(struct ivy_assembler *as, struct assembler_scope *scope, + const ivy_assembler_attrib_table attrib) +{ + struct ivy_bin_class header = {0}; + + header.c_ident = b_i32_htob(attrib[IVY_ASM_ATTRIB_IDENT]); -}; + assembler_write_data(as, &header, sizeof header); + + return IVY_OK; +} + +static enum ivy_status put_xval( + struct ivy_assembler *as, + struct assembler_scope *scope, + enum ivy_assembler_xval_type type, + ivy_assembler_attrib_table attrib) +{ + struct ivy_bin_class_table_entry entry = {0}; + switch (type) { + case IVY_ASM_XVAL_PROPERTY: + entry.e_type = b_i32_htob(IVY_CLASS_TABLE_PROP); + entry.e_property.p_ident = b_i32_htob(attrib[IVY_ASM_ATTRIB_IDENT]); + entry.e_property.p_get = b_i32_htob(attrib[IVY_ASM_ATTRIB_GET]); + entry.e_property.p_set = b_i32_htob(attrib[IVY_ASM_ATTRIB_SET]); + break; + case IVY_ASM_XVAL_MEMBER_VAR: + entry.e_type = b_i32_htob(IVY_CLASS_TABLE_MVAR); + entry.e_mvar.m_ident = b_i32_htob(attrib[IVY_ASM_ATTRIB_IDENT]); + entry.e_mvar.m_index = b_i32_htob(attrib[IVY_ASM_ATTRIB_INDEX]); + break; + default: + return IVY_ERR_NOT_SUPPORTED; + } + + assembler_write_data(as, &entry, sizeof entry); + return IVY_OK; +} const struct assembler_scope_type class_scope_type = { - .s_scope_size = sizeof(struct class_scope), + .s_scope_size = sizeof(struct assembler_scope), + .s_init_scope = init_scope, + .s_put_xval = put_xval, }; \ No newline at end of file diff --git a/asm/include/ivy/asm/assembler.h b/asm/include/ivy/asm/assembler.h index c2c086d..5a76a0f 100644 --- a/asm/include/ivy/asm/assembler.h +++ b/asm/include/ivy/asm/assembler.h @@ -1,6 +1,7 @@ #ifndef IVY_ASM_ASSEMBLER_H_ #define IVY_ASM_ASSEMBLER_H_ +#include #include #include #include @@ -12,31 +13,60 @@ struct ivy_instr; struct ivy_assembler; +enum ivy_assembler_attrib { + IVY_ASM_ATTRIB_NONE = 0, + IVY_ASM_ATTRIB_IDENT, + IVY_ASM_ATTRIB_INDEX, + IVY_ASM_ATTRIB_RECIPIENT, + IVY_ASM_ATTRIB_SELECTOR, + IVY_ASM_ATTRIB_GET, + IVY_ASM_ATTRIB_SET, + IVY_ASM_ATTRIB_PACKAGE, + __IVY_ASM_ATTRIB_COUNT, +}; + +enum ivy_assembler_pval_type { + IVY_ASM_PVAL_NONE = 0, + IVY_ASM_PVAL_STRING, + IVY_ASM_PVAL_IDENT, + IVY_ASM_PVAL_ATOM, + IVY_ASM_PVAL_SINT, + IVY_ASM_PVAL_UINT, + IVY_ASM_PVAL_SELECTOR, +}; + +enum ivy_assembler_xval_type { + IVY_ASM_XVAL_NONE = 0, + IVY_ASM_XVAL_PROPERTY, + IVY_ASM_XVAL_MEMBER_VAR, + IVY_ASM_XVAL_PACKAGE_REF, +}; + enum ivy_assembler_scope_type { IVY_ASM_SCOPE_NONE = 0, IVY_ASM_SCOPE_CLASS, IVY_ASM_SCOPE_LAMBDA, IVY_ASM_SCOPE_MSGH, IVY_ASM_SCOPE_CONSTPOOL, + IVY_ASM_SCOPE_IMPORT, }; +typedef unsigned int ivy_assembler_attrib_table[__IVY_ASM_ATTRIB_COUNT]; + IVY_API enum ivy_static ivy_assembler_create(FILE *out, struct ivy_assembler **as); -IVY_API void ivy_assembler_destroy(struct ivy_assembler *as); +IVY_API enum ivy_status ivy_assembler_finish(struct ivy_assembler *as); IVY_API enum ivy_status ivy_assembler_begin_scope( - struct ivy_assembler *as, enum ivy_assembler_scope_type type); + struct ivy_assembler *as, enum ivy_assembler_scope_type type, + const ivy_assembler_attrib_table attrib); IVY_API enum ivy_status ivy_assembler_end_scope(struct ivy_assembler *as); -IVY_API enum ivy_status ivy_assembler_put_string( - struct ivy_assembler *as, int index, const char *s); -IVY_API enum ivy_status ivy_assembler_put_ident( - struct ivy_assembler *as, int index, const char *s); -IVY_API enum ivy_status ivy_assembler_put_atom( - struct ivy_assembler *as, int index, const char *s); -IVY_API enum ivy_status ivy_assembler_put_selector( - struct ivy_assembler *as, int index, struct ivy_selector *sel); -IVY_API enum ivy_status ivy_assembler_put_mvar( - struct ivy_assembler *as, int index, const char *name); +IVY_API enum ivy_status ivy_assembler_put_pval( + struct ivy_assembler *as, enum ivy_assembler_pval_type type, + unsigned long index, const void *val); +IVY_API enum ivy_status ivy_assembler_put_xval( + struct ivy_assembler *as, enum ivy_assembler_xval_type type, + const ivy_assembler_attrib_table attrib); IVY_API enum ivy_status ivy_assembler_put_instr( struct ivy_assembler *as, const struct ivy_instr *i); diff --git a/asm/include/ivy/asm/bin.h b/asm/include/ivy/asm/bin.h index ca5820b..d09d66d 100644 --- a/asm/include/ivy/asm/bin.h +++ b/asm/include/ivy/asm/bin.h @@ -1,6 +1,7 @@ #ifndef IVY_ASM_BIN_H_ #define IVY_ASM_BIN_H_ +#include #include #define IVY_BIN_MAGIC 0x2E495659u @@ -10,7 +11,7 @@ #define IVY_TABLE_LAMBDA 0x4C424441u #define IVY_TABLE_MSGH 0x4D534748u #define IVY_TABLE_POOL 0x504F4F4Cu -#define IVY_TABLE_XDAT 0x53544142u +#define IVY_TABLE_XDAT 0x58444154u #define IVY_CLASS_TABLE_MVAR 0x4D564152u #define IVY_CLASS_TABLE_PROP 0x50524F50u @@ -31,61 +32,61 @@ typedef uint32_t ivy_bin_data_handle; struct ivy_bin_header { - uint32_t h_magic; - uint16_t h_table_len; + b_i32 h_magic; + b_i16 h_table_len; uint8_t h_reserved[2]; - uint64_t h_table_offset; + b_i64 h_table_offset; }; struct ivy_bin_table_entry { - uint32_t e_type; - uint32_t e_size; - uint64_t e_offset; + b_i32 e_type; + b_i32 e_size; + b_i64 e_offset; }; struct ivy_bin_class_table_entry { - uint32_t e_type; + b_i32 e_type; union { struct { - ivy_bin_data_handle p_ident; - ivy_bin_data_handle p_get; - ivy_bin_data_handle p_set; - uint32_t p_reserved; + b_i32 p_ident; + b_i32 p_get; + b_i32 p_set; + b_i32 p_reserved; } e_property; struct { - uint32_t m_index; - ivy_bin_data_handle m_ident; - uint8_t m_reserved[16]; + b_i32 m_index; + b_i32 m_ident; + uint8_t m_reserved[8]; } e_mvar; }; }; struct ivy_bin_class { - uint32_t c_ident; + b_i32 c_ident; struct ivy_bin_class_table_entry c_table[]; }; struct ivy_bin_lambda { ivy_bin_data_handle l_ident; - uint32_t l_instr[]; + b_i32 l_instr[]; }; struct ivy_bin_msgh { - ivy_bin_data_handle msg_recipient; - ivy_bin_data_handle msg_selector; - uint32_t msg_instr[]; + b_i32 msg_recipient; + b_i32 msg_selector; + b_i32 msg_instr[]; }; struct ivy_bin_constpool_header { - uint32_t c_nr_table_entries; + b_i32 c_nr_table_entries; uint8_t c_reserved[4]; - uint64_t c_table_offset; + b_i64 c_table_offset; }; struct ivy_bin_string { - uint32_t s_hash; - uint32_t s_len; + b_i32 s_hash; + b_i32 s_len; char s_chars[]; }; @@ -93,26 +94,25 @@ struct ivy_bin_selector { uint8_t sel_flags; uint8_t sel_nr_args; uint8_t sel_reserved[2]; - uint32_t sel_hash; + b_i32 sel_hash; ivy_bin_data_handle sel_name; ivy_bin_data_handle sel_args[]; }; struct ivy_bin_ident { - uint32_t id_hash; + b_i32 id_hash; uint8_t id_nr_parts; uint8_t id_reserved[3]; ivy_bin_data_handle id_parts[]; }; struct ivy_bin_constpool_table_entry { - uint32_t e_type; - uint32_t e_reserved; + b_i32 e_type; + b_i32 e_reserved; union { - ivy_bin_data_handle e_handle; - int64_t e_sint; - uint64_t e_uint; + b_i32 e_handle; + b_i64 e_int; }; };