From ae15dd5490fcf3e5185f5966da33dc061a1f67e7 Mon Sep 17 00:00:00 2001 From: "yu.dongliang" <18588496441@163.com> Date: Thu, 18 Jun 2026 20:02:24 +0800 Subject: [PATCH] 1, css: support counter, 2, js: support setTimeout() with variable args, 3, fix: some BUGS in native/x64. --- examples/{js2.html => js_func.html} | 0 examples/js_obj_func.html | 22 + examples/js_setTimeout.html | 21 + examples/{js.html => js_switch.html} | 0 html/Makefile | 3 +- html/abc_css.c | 20 +- html/abc_css_counter.c | 234 +++++++++-- html/abc_html.c | 36 +- html/abc_html.h | 28 +- html/abc_obj.c | 4 +- html/abc_obj.h | 21 +- html/main.c | 4 +- js/Makefile | 4 + js/abc_libjs.c | 81 ++++ js/abc_libjs.so | Bin 64528 -> 136824 bytes js/abc_libjs_asm.S | 67 +++ js/core/scf_3ac.c | 6 +- js/core/scf_3ac.h | 4 +- js/core/scf_ast.c | 42 +- js/core/scf_basic_block.c | 2 +- js/core/scf_block.h | 3 +- js/core/scf_calculate.c | 33 +- js/core/scf_calculate.h | 1 - js/core/scf_calculate_i32.c | 1 - js/core/scf_calculate_i64.c | 1 - js/core/scf_calculate_u32.c | 1 - js/core/scf_calculate_u64.c | 65 +++ js/core/scf_expr.c | 3 +- js/core/scf_function.c | 21 +- js/core/scf_function.h | 8 +- js/core/scf_label.c | 4 - js/core/scf_node.c | 31 +- js/core/scf_node.h | 17 +- js/core/scf_operator_handler_3ac.c | 48 +-- js/core/scf_optimizer_inline.c | 21 +- js/core/scf_optimizer_js_array.c | 4 +- js/core/scf_optimizer_js_array2.c | 75 ++-- js/core/scf_optimizer_js_teq.c | 2 +- js/core/scf_optimizer_js_unary_op.c | 4 +- js/core/scf_scope.c | 76 +--- js/core/scf_scope.h | 41 +- js/core/scf_type.c | 13 +- js/core/scf_type.h | 12 +- js/core/scf_variable.c | 2 +- js/doc.c | 70 +++- js/elf/scf_dwarf.c | 31 ++ js/elf/scf_dwarf.h | 4 + js/lex/scf_lex_util.c | 496 +++++++++++++++-------- js/lib/scf_rbtree.c | 4 +- js/native/x64/scf_x64.c | 70 ++-- js/native/x64/scf_x64_inst.c | 6 +- js/native/x64/scf_x64_inst_common.c | 78 ++-- js/native/x64/scf_x64_peephole.c | 153 +++---- js/native/x64/scf_x64_reg.c | 100 +++-- js/native/x64/scf_x64_reg.h | 4 +- js/parse/scf_dfa_call.c | 50 ++- js/parse/scf_dfa_class.c | 2 +- js/parse/scf_dfa_container.c | 2 +- js/parse/scf_dfa_expr.c | 9 +- js/parse/scf_dfa_function.c | 4 +- js/parse/scf_dfa_function_js.c | 2 +- js/parse/scf_dfa_goto.c | 6 +- js/parse/scf_dfa_include.c | 4 +- js/parse/scf_dfa_init_data.c | 12 +- js/parse/scf_dfa_label.c | 3 +- js/parse/scf_dfa_new.c | 6 +- js/parse/scf_dfa_type.c | 2 +- js/parse/scf_dfa_va_arg.c | 2 +- js/parse/scf_dfa_var.c | 12 +- js/parse/scf_operator_handler_const.c | 2 +- js/parse/scf_operator_handler_semantic.c | 38 +- js/parse/scf_parse.c | 247 ++++------- js/parse/scf_struct_array.c | 29 +- js/parse/scf_symtab.c | 100 +++++ js/parse/scf_symtab.h | 37 ++ js/util/scf_string.c | 2 +- js/util/scf_string.h | 2 +- ui/Makefile | 2 + ui/abc_layout.c | 7 +- ui/abc_layout_text.c | 7 +- ui/main.c | 77 ++-- 81 files changed, 1751 insertions(+), 1017 deletions(-) rename examples/{js2.html => js_func.html} (100%) create mode 100644 examples/js_obj_func.html create mode 100644 examples/js_setTimeout.html rename examples/{js.html => js_switch.html} (100%) create mode 100644 js/abc_libjs_asm.S create mode 100644 js/core/scf_calculate_u64.c create mode 100644 js/parse/scf_symtab.c create mode 100644 js/parse/scf_symtab.h diff --git a/examples/js2.html b/examples/js_func.html similarity index 100% rename from examples/js2.html rename to examples/js_func.html diff --git a/examples/js_obj_func.html b/examples/js_obj_func.html new file mode 100644 index 0000000..0c3cb9b --- /dev/null +++ b/examples/js_obj_func.html @@ -0,0 +1,22 @@ + + + + +

含有javascript的页面

+ +

含有js的页面

+ + + + + diff --git a/examples/js_setTimeout.html b/examples/js_setTimeout.html new file mode 100644 index 0000000..83b1ea6 --- /dev/null +++ b/examples/js_setTimeout.html @@ -0,0 +1,21 @@ + + + + +菜鸟教程(runoob.com) + + + +

回调函数等待 3 秒后执行。

+

+ + + + + diff --git a/examples/js.html b/examples/js_switch.html similarity index 100% rename from examples/js.html rename to examples/js_switch.html diff --git a/html/Makefile b/html/Makefile index bbb8c73..b11e664 100644 --- a/html/Makefile +++ b/html/Makefile @@ -20,8 +20,9 @@ CFILES += ../js/lex/scf_lex.c CFILES += ../js/lex/scf_lex_util.c CFILES += ../js/parse/main.c -CFILES += ../js/parse/scf_parse_util.c CFILES += ../js/parse/scf_parse.c +CFILES += ../js/parse/scf_parse_util.c +CFILES += ../js/parse/scf_symtab.c CFILES += ../js/parse/scf_operator_handler_semantic.c CFILES += ../js/parse/scf_operator_handler_expr.c CFILES += ../js/parse/scf_operator_handler_const.c diff --git a/html/abc_css.c b/html/abc_css.c index 16112df..8e25c92 100644 --- a/html/abc_css.c +++ b/html/abc_css.c @@ -1683,24 +1683,30 @@ int abc_css_clear(abc_obj_t* obj, int pse_start, int pse_end) { abc_attr_t* attr; int i; + int n = 0; for (i = pse_start; i <= pse_end; i++) { attr = abc_obj_get_attr(obj, i); - if (attr) + if (!attr) + continue; + + if (attr->flags & ABC_CSS_FLAG_ON) { attr->flags &= ~ABC_CSS_FLAG_ON; + n++; + } } - return 0; + return n; } int abc_css_active(abc_obj_t* obj, int pse) { abc_attr_t* attr = abc_obj_get_attr(obj, pse); - if (attr) { - attr->flags |= ABC_CSS_FLAG_ON; - return 1; - } - return 0; + if (!attr || (attr->flags & ABC_CSS_FLAG_ON)) + return 0; + + attr->flags |= ABC_CSS_FLAG_ON; + return 1; } diff --git a/html/abc_css_counter.c b/html/abc_css_counter.c index a91985a..67431a0 100644 --- a/html/abc_css_counter.c +++ b/html/abc_css_counter.c @@ -1,11 +1,48 @@ #include"abc_html.h" +static int __cmp_ref_counter(const void* counter, const void* ref) +{ + const ref_count_t* r = ref; + + if (r->counter == counter) + return 0; + return -1; +} + +static int __sort_ref_counter(const void* v0, const void* v1) +{ + const ref_count_t* r0 = *(const ref_count_t**)v0; + const ref_count_t* r1 = *(const ref_count_t**)v1; + + if (r0->layer < r1->layer) + return -1; + + else if (r0->layer > r1->layer) + return 1; + return 0; +} + +css_count_t* css_count_alloc(const char* name, size_t len) +{ + css_count_t* cnt = calloc(1, sizeof(css_count_t)); + if (!cnt) + return NULL; + + cnt->name = scf_string_cstr_len(name, len); + if (!cnt->name) { + free(cnt); + return NULL; + } + + return cnt; +} + int abc_css_counter_reset(abc_obj_t* obj, abc_attr_t* attr) { if (!obj || !attr || !attr->value || 0 == attr->value->len) return -EINVAL; - css_count_t* cnt = obj->counter_list; + css_count_t* cnt = obj->reset_counters; while (cnt) { if (!scf_string_cmp(cnt->name, attr->value)) break; @@ -13,26 +50,100 @@ int abc_css_counter_reset(abc_obj_t* obj, abc_attr_t* attr) } if (!cnt) { - cnt = calloc(1, sizeof(css_count_t)); + cnt = css_count_alloc(attr->value->data, attr->value->len); if (!cnt) return -ENOMEM; - cnt->name = scf_string_clone(attr->value); - if (!cnt->name) { - free(cnt); - return -ENOMEM; + cnt->next = obj->reset_counters; + obj->reset_counters = cnt; + + } else if (cnt->objs) { + abc_obj_t* tmp; + int i; + + for (i = 0; i < cnt->objs->size; i++) { + tmp = cnt->objs->data[i]; + + if (tmp->content) { + scf_string_free(tmp->content); + tmp->content = NULL; + } + + ref_count_t* r = scf_vector_find_cmp(tmp->used_counters, cnt, __cmp_ref_counter); + if (r) + assert(0 == scf_vector_del(tmp->used_counters, r)); + + tmp->css_used = 0; + + scf_logw("cnt: %p, i: %d, obj: %p, css_used: %u\n", cnt, i, tmp, tmp->css_used); } - cnt->next = obj->counter_list; - obj->counter_list = cnt; + scf_vector_free(cnt->objs); + cnt->objs = NULL; } cnt->value = 0; - scf_logd("cnt->name: %s, value: %ld\n", cnt->name->data, cnt->value); + scf_logd("cnt->name: %s, value: %d\n", cnt->name->data, cnt->value); return 0; } +static int __css_ref_counter(abc_obj_t* obj, css_count_t* cnt, int layer) +{ + if (!obj->used_counters) { + obj ->used_counters = scf_vector_alloc(); + + if (!obj->used_counters) + return -ENOMEM; + } + + ref_count_t* r = scf_vector_find_cmp(obj->used_counters, cnt, __cmp_ref_counter); + + if (!r) { + r = calloc(1, sizeof(ref_count_t)); + if (!r) + return -ENOMEM; + + int ret = scf_vector_add(obj->used_counters, r); + if (ret < 0) { + free(r); + return ret; + } + + r->counter = cnt; + r->value = cnt->value; + } + + r->layer = layer; + + scf_logi("#0 r: %p, cnt: %p, value: %d, layer: %d, obj: %p\n", r, cnt, cnt->value, layer, obj); + return 0; +} + +static int __css_inc_counter(abc_obj_t* obj, css_count_t* cnt) +{ + if (!cnt->objs) { + cnt ->objs = scf_vector_alloc(); + + if (!cnt->objs) + return -ENOMEM; + } + + if (scf_vector_find(cnt->objs, obj)) + return 0; + + int ret = scf_vector_add(cnt->objs, obj); + if (ret < 0) + return ret; + + cnt->value++; + + printf("\n"); + scf_logw("## cnt: %p, value: %d, obj: %p\n", cnt, cnt->value, obj); + + return __css_ref_counter(obj, cnt, 0); +} + int abc_css_counter_inc(abc_obj_t* obj, abc_attr_t* attr) { if (!obj || !attr || !attr->value || 0 == attr->value->len) @@ -43,52 +154,44 @@ int abc_css_counter_inc(abc_obj_t* obj, abc_attr_t* attr) for (parent = obj->parent; parent; parent = parent->parent) { - for (cnt = parent->counter_list; cnt; cnt = cnt->next) + for (cnt = parent->reset_counters; cnt; cnt = cnt->next) { - if (!scf_string_cmp(cnt->name, attr->value)) { - cnt->value++; - return 0; - } + if (scf_string_cmp(cnt->name, attr->value)) + continue; + + return __css_inc_counter(obj, cnt); } } return -EINVAL; } -static int __css_recursive_counter(scf_string_t* content, abc_obj_t* parent, const char* name, int len, const char* split, int split_len, int all_flag) +static int __css_use_counter(abc_obj_t* obj, css_count_t* cnt, int layer) { - if (all_flag && parent->parent) { + if (!cnt->objs) { + cnt ->objs = scf_vector_alloc(); - int ret = __css_recursive_counter(content, parent->parent, name, len, split, split_len, all_flag); - if (ret < 0) - return ret; + if (!cnt->objs) + return -ENOMEM; } - css_count_t* cnt; + ref_count_t* r; - for (cnt = parent->counter_list; cnt; cnt = cnt->next) { + if (scf_vector_find(cnt->objs, obj)) { + r = scf_vector_find_cmp(obj->used_counters, cnt, __cmp_ref_counter); + assert(r); - if (cnt->name->len == len && !memcmp(cnt->name->data, name, len)) { - uint8_t buf[128]; + r->layer = layer; - int n = snprintf(buf, sizeof(buf) - 1, "%ld", cnt->value); - - int ret = scf_string_cat_cstr_len(content, buf, n); - if (ret < 0) - return ret; - - if (split && split_len > 0) { - - ret = scf_string_cat_cstr_len(content, split, split_len); - if (ret < 0) - return ret; - } - - break; - } + scf_logi("#1 r: %p, cnt: %p, value: %d, layer: %d, obj: %p\n", r, r->counter, r->value, r->layer, obj); + return 0; } - return 0; + int ret = scf_vector_add(cnt->objs, obj); + if (ret < 0) + return ret; + + return __css_ref_counter(obj, cnt, layer); } static int __css_counter(abc_obj_t* obj, abc_attr_t* attr, int lp, int comma, int rp, int all_flag) @@ -115,9 +218,58 @@ static int __css_counter(abc_obj_t* obj, abc_attr_t* attr, int lp, int comma, in } } - int split_len = (int)(split2 - split); + abc_obj_t* parent; + css_count_t* cnt; + ref_count_t* r; + + int layer = 0; + int ret; + + for (parent = obj->parent; parent; parent = parent->parent) { + + for (cnt = parent->reset_counters; cnt; cnt = cnt->next) { + + if (cnt->name->len == len && !memcmp(cnt->name->data, name, len)) { + + ret = __css_use_counter(obj, cnt, layer); + if (ret < 0) + return ret; + + if (!all_flag) + goto found; + + layer++; + break; + } + } + } + +found: + if (!obj->used_counters) + return 0; + + scf_vector_qsort(obj->used_counters, __sort_ref_counter); - return __css_recursive_counter(obj->content, obj->parent, name, len, split, split_len, all_flag); + for (i = obj->used_counters->size - 1; i >= 0; i--) { + r = obj->used_counters->data[i]; + + scf_logi("#2 i: %d, r: %p, cnt: %p, value: %d, layer: %d, obj: %p\n", i, r, r->counter, r->value, r->layer, obj); + + uint8_t buf[128]; + int n = snprintf(buf, sizeof(buf) - 1, "%d", r->value); + + ret = scf_string_cat_cstr_len(obj->content, buf, n); + if (ret < 0) + return ret; + + if (split && split2 > split) { + ret = scf_string_cat_cstr_len(obj->content, split, (size_t)(split2 - split)); + if (ret < 0) + return ret; + } + } + + return 0; } int abc_css_content(abc_obj_t* obj, abc_attr_t* attr) diff --git a/html/abc_html.c b/html/abc_html.c index 37946b0..47ed2d1 100644 --- a/html/abc_html.c +++ b/html/abc_html.c @@ -902,6 +902,8 @@ int abc_html_open(abc_html_t** pp, const char* path) if (!html) return -ENOMEM; + scf_rbtree_init(&html->timers); + html->io.proto = io->proto; html->io.priv = NULL; html->io.open = io->open; @@ -1381,10 +1383,6 @@ static int __html_run_js(abc_html_t* html, abc_obj_t* obj) if (ret < 0) return ret; - ret = __html_js_path(&obj->js_entry, obj, NULL, NULL, 0); - if (ret < 0) - return ret; - if (!html->js) { ret = scf_parse_open(&html->js); if (ret < 0) @@ -1422,12 +1420,13 @@ static int __html_run_js(abc_html_t* html, abc_obj_t* obj) #if 1 assert(!html->io.tmp_list_js); - void* so = dlopen(obj->js_so->data, RTLD_LAZY); - void (*f)() = dlsym(so, "__js_main"); + obj->js_so_handle = dlopen(obj->js_so->data, RTLD_LAZY); + void (*f)(void*) = dlsym (obj->js_so_handle, "__js_main"); + + html->js_auto_freep = dlsym(obj->js_so_handle, "scf__auto_freep_array"); + html->js_release = dlsym(obj->js_so_handle, "Object___release_Object1"); f(html); - dlclose(so); - so = NULL; #endif abc_char_t* c; while ( html->io.tmp_list_js) { @@ -1560,11 +1559,13 @@ static int __html_parse_obj(abc_html_t* html, abc_char_t* c) } else ret = __html_parse_text(html, obj); + int err; switch (obj->type) { case ABC_HTML_SCRIPT: - if (__html_run_js(html, obj) < 0) - return -1; + err = __html_run_js(html, obj); + if (err < 0) + return err; break; case ABC_HTML_LINK: @@ -1576,19 +1577,22 @@ static int __html_parse_obj(abc_html_t* html, abc_char_t* c) break; case ABC_HTML_STYLE: - if (abc_css_parse(obj) < 0) - return -1; + err = abc_css_parse(obj); + if (err < 0) + return err; - if (abc_css_merge(html, obj) < 0) - return -1; + err = abc_css_merge(html, obj); + if (err < 0) + return err; break; case ABC_HTML_VIDEO: html->has_video = 1; case ABC_HTML_AUDIO: - if (__html_add_controls(obj) < 0) - return -1; + err = __html_add_controls(obj); + if (err < 0) + return err; default: break; }; diff --git a/html/abc_html.h b/html/abc_html.h index ff5a675..e41dae9 100644 --- a/html/abc_html.h +++ b/html/abc_html.h @@ -4,8 +4,10 @@ #include"abc_io.h" #include"abc_obj.h" #include"scf_parse.h" +#include"scf_rbtree.h" -typedef struct abc_html_s abc_html_t; +typedef struct abc_html_s abc_html_t; +typedef struct abc_timer_s abc_timer_t; typedef struct { abc_str_t* names; @@ -30,10 +32,23 @@ typedef struct { #define abc_number_of(__array) (sizeof(__array) / sizeof(__array[0])) +struct abc_timer_s +{ + scf_rbtree_node_t node; + int64_t usec; + + void (*func)(int argc, void* argv[]); + + int argc; + void* argv[0]; +}; + struct abc_html_s { scf_list_t list; + scf_rbtree_t timers; + abc_obj_t* root; abc_obj_t* current; @@ -46,6 +61,8 @@ struct abc_html_s int pos; scf_parse_t* js; + void (*js_auto_freep)(void** pp, int n_pointers, void (*js_release)(void* jobj)); + void (*js_release )(void* jobj); uint8_t has_video:1; }; @@ -90,4 +107,13 @@ int abc_css_counter_reset(abc_obj_t* obj, abc_attr_t* attr); int abc_css_counter_inc (abc_obj_t* obj, abc_attr_t* attr); int abc_css_content (abc_obj_t* obj, abc_attr_t* attr); + +static inline int abc_timer_cmp(scf_rbtree_node_t* node0, void* data) +{ + abc_timer_t* t0 = (abc_timer_t*)node0; + abc_timer_t* t1 = (abc_timer_t*)data; + + return t0->usec - t1->usec; +} + #endif diff --git a/html/abc_obj.c b/html/abc_obj.c index 60ca2e1..e93a111 100644 --- a/html/abc_obj.c +++ b/html/abc_obj.c @@ -44,8 +44,8 @@ void abc_obj_free(abc_obj_t* obj) if (obj->js_so) scf_string_free(obj->js_so); - if (obj->js_entry) - scf_string_free(obj->js_entry); + if (obj->js_so_handle) + dlclose(obj->js_so_handle); #ifndef ABC_HTML_TEST if (obj->av_filter) diff --git a/html/abc_obj.h b/html/abc_obj.h index a493295..e947a40 100644 --- a/html/abc_obj.h +++ b/html/abc_obj.h @@ -9,11 +9,12 @@ typedef struct abc_obj_s abc_obj_t; typedef struct abc_attr_s abc_attr_t; typedef struct abc_text_s abc_text_t; - typedef struct abc_css_s abc_css_t; + typedef struct css_rule_s css_rule_t; typedef struct css_hash_s css_hash_t; typedef struct css_count_s css_count_t; +typedef struct ref_count_s ref_count_t; enum abc_objs { @@ -266,7 +267,16 @@ struct css_count_s css_count_t* next; scf_string_t* name; - intptr_t value; + int value; + + scf_vector_t* objs; +}; + +struct ref_count_s +{ + css_count_t* counter; + int value; + int layer; }; #define ABC_HTML_FLAG_OPEN 0 @@ -368,7 +378,8 @@ struct abc_obj_s abc_text_t* text_splits; // for layout, split a long text to multi-lines and save every-line here abc_io_t io; - css_count_t* counter_list; + css_count_t* reset_counters; + scf_vector_t* used_counters; scf_string_t* content; int border_top; @@ -438,12 +449,12 @@ struct abc_obj_s scf_string_t* js_path; scf_string_t* js_obj; scf_string_t* js_so; - scf_string_t* js_entry; + void* js_so_handle; uint32_t clicked:1; uint32_t visited:1; - uint32_t css_use:1; + uint32_t css_used:1; uint32_t w_set:1; uint32_t h_set:1; diff --git a/html/main.c b/html/main.c index 561c805..35e3788 100644 --- a/html/main.c +++ b/html/main.c @@ -10,8 +10,8 @@ void abc_css_recursive_use(abc_html_t* html, abc_obj_t* obj) if (!obj) return; - if (!obj->css_use && ABC_CORE_TEXT != obj->type) { - obj->css_use = 1; + if (!obj->css_used && ABC_CORE_TEXT != obj->type) { + obj->css_used = 1; abc_css_use(html, obj); } diff --git a/js/Makefile b/js/Makefile index b4d00fb..b8c56f8 100644 --- a/js/Makefile +++ b/js/Makefile @@ -1,4 +1,8 @@ CFILES += abc_libjs.c +CFILES += abc_libjs_asm.S +CFILES += ../js/util/scf_string.c +CFILES += ../js/util/scf_rbtree.c +CFILES += ../js/lib/x64/scf_atomic.o CFLAGS += -g -DABC_HTML_TEST -D_GNU_SOURCE CFLAGS += -I../ffmpeg diff --git a/js/abc_libjs.c b/js/abc_libjs.c index f8a1312..3e28fdc 100644 --- a/js/abc_libjs.c +++ b/js/abc_libjs.c @@ -2,6 +2,9 @@ #define PCRE2_CODE_UNIT_WIDTH 8 #include +void asm_Object_ref(void* obj); +void asm_timer_func(int argc, void* argv[]); + static char* js_days[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; @@ -415,3 +418,81 @@ int abc_pcre2_match(int** __ovector, const char* __subject, const char* __patter *__ovector = outs; return n_outs; } + +static abc_obj_t* __html_getElementById(abc_obj_t* root, const char* id) +{ + if (!root) + return NULL; + + scf_list_t* l; + abc_obj_t* child; + abc_obj_t* obj; + abc_attr_t* attr = abc_obj_get_attr(root, ABC_CSS_ID); + + if (attr && attr->value && attr->value->len > 0 && !strcmp(attr->value->data, id)) + return root; + + for (l = scf_list_head(&root->childs); l != scf_list_sentinel(&root->childs); l = scf_list_next(l)) { + child = scf_list_data(l, abc_obj_t, list); + + obj = __html_getElementById(child, id); + if (obj) + return obj; + } + + return NULL; +} + +abc_obj_t* abc_html_getElementById(abc_html_t* html, const char* id) +{ + if (!html || !html->root) + return NULL; + + return __html_getElementById(html->root, id); +} + +void abc_html_inner(abc_obj_t* obj, const char* s) +{ + printf("obj: %p, s: %s\n", obj, s); + + scf_string_t* text = scf_string_cstr(s); + if (text) { + if (obj->text) + scf_string_free(obj->text); + + obj->text = text; + } +} + +void abc_html_setTimeout(abc_html_t* html, int argc, void (*func)(abc_html_t* html), int msec, void** argv) +{ + printf("html: %p, func: %p, argc: %d, msec: %d, argv: %p\n", html, func, argc, msec, argv); + + int n = argc; + if (n < 5) + n = 5; + + n = (n + 1) & ~0x1; + + abc_timer_t* timer = calloc(1, sizeof(abc_timer_t) + sizeof(void*) * (2 + n)); + if (!timer) + return; + + timer->usec = gettime() + msec * 1000ll; + timer->func = asm_timer_func; + timer->argc = 2 + n; + timer->argv[0] = func; + timer->argv[1] = html; + + int i; + for (i = 0; i < argc; i++) { + asm_Object_ref(argv[i]); + + printf("argv[%d]: %p\n", i, argv[i]); + + timer->argv[2 + i] = argv[i]; + } + +// timer->func(timer->argc, timer->argv); + scf_rbtree_insert(&html->timers, (scf_rbtree_node_t*)timer, abc_timer_cmp); +} diff --git a/js/abc_libjs.so b/js/abc_libjs.so index b5d7e51efae8bd855a2bd95d04bf4c0060ff4aea..e9b31a886e3576a056b32783adc71d35b296fc91 100755 GIT binary patch literal 136824 zcmeFa30zgx`aitaJ{&jn*>sf0L$Gs_i+9X{F&2^Zxv059ZX=w)IKo{Lr1+-Mn7w0}&jI8VB=9~-c4OcW* zsaX|H9cF?yo^aUY*zO);i$Z&PW zu#>%JJIl?gzUAKbWu4(HS7}jfjbiwhYPhXq+1IG&Dp{9D#+Qy9!j9DvJ*Qk~$a9sh zb~Dk=M>Y9FXQO-CEJI&sez6$(T&2-n*|$(=GU0FXj5*q%nQt#Re)^+Nc7OSoul^kK z>*#<54RT~+!MEX$cG5S`YiZ*xWmP@)^b6<{{3l;)*~C44_ogffaBjKlPTev=*6odY zo<|=bloRhs^neo#I2q+Y10IBO2>yoSFBN|y@HYy7WAHZ)f0yEq#{^Zl&yxU6#-H7w zOhp+!`lgp2{rb-DzWZS1?{(oJAAi^UWpwJ=w}{ndf30|b|F9P>9p$ra{lw3XZ2RnkQ*ZP)-|L9%^_b(dw#nD)AKyLls$cSx z_pE&U?po{!Erv9+tIko!@bum0aUk+Z3j`mLSNmvlnk*9racPUv$wp+D4#AKpVi zpRZqGozSOuBB!YnKitv@9c0ahzmCUyoyb3eis!R)LnrcI>4e^`6Z%J;(C2kRPl7$R zj>ZE|>7;&cC-i-t(7ijMbH2u$N3XXWuK+FInBXgoI-j5n)&ev$lLd~gs?ffd@&mMo zm?Utx=Kl!k{{Ss#w4yVlUuE=nU>C)oZqyH+ zsqm{*p`9`Geze#i7=_)?d+kI;NH*keFy!nt1ne~GZ!zjm<^bVXZPc$a>W^Ni=y?YH zW262^!(rDbwzklyzoLVkHAemWjDfNnav}}?9~iF$xQ6GiM*VQ3{!NDb`3C*rbVXQZ z(7!k64;uE!#SFYXhCTN$QWahHe`n}@%oz9Q4LNBp`)4S^QNzxsjrv{F6x|gMDTdzQ ziHh#BCmZz{4?(UDDYmxRpoev!uL7Ur-t!VwvDB#ltU*5;rwE&&k4F{$SpQa|{&Ls2 z76tmXCAmxUS2=P^W>23`P*j*ZJ8MZnuHv1albO9XD>E;@FsmT{+FWgEuEUYPBDW|n zCu^OSN!i)gWM(hBCNnQ9zd*}clAXDHRc20>BUj5VC<4o<@5#w@6kXvc$uC^0p+;5# z#buUgs|t%jbL7dI%N#2TGS`&kL(Gb-0#xfj&CKse$dQEN?2_C;nJcm!*~_$5j*^1h zLQRpfi&hlp7vyH98aT|#%q=M?D#=`tyJ}U|(l(B4%pPQALKr%dnO9P@BC|Nl0iPAR z1*mE+aUPBGN^;wTWf$eJy$6Mgi&p1mJD|F_2p!HXq0CapD#J3DqWr?VBDXfSlEaw2 zEQ|GFnDh$Tk;1-auPAQw3F@a8Y_igJx~X?|g0E^24zK^jLOGaIERPFvf= ztjcxF=3tjPGz^p+hE*#vIbbE3d8LII6`+?dS&r^xmgMG1K_yEZ>~DVIs@xKXW-!|X z8Px}7=4a*=4lV&~x12qIDFTUDQD}aM}2L70;EL;FZEi^sI{5+G;p|^IH>?I-6T>lAh z&A?c)o+{6Wd2;^m!n91lnlLlh0Cnu#al1F~JVYC`(ENPth`h7}1OJoco3tSYUfMn1 zm;DFUwgU>-_wDv85@kf9q3*LeP0K<#h@SPKo2nJ z)g9Onv1K_BKpuk)aH^`M{dpoe(S>pkeazvns{_9%${ ziFFZCHt$gg>0t_#=axMRA$`08)!E1cq<8b6TRiB-En~^Gde9?0>PL9cZ60)+2c7r+ zTt}P-J<>%)nc_irrE;=UJ?Oj#=sMCo=qWBDO1lTWhX*~wgC6BUpYK8M=|NxYLGR^3 zzX)FRz(o&S^uR?AT=c+24_x%X|CR^-9n|X=d-)lQz0&;FCTwFWsvUZ3oxS{J%S%#4 z>(I|ZZjC*Kb5L{|AmYo&Ypid@5&I!=LA*}l$BFY2qp@1zuMsy9-zV|I#CeI(xJTj# ziJOUUm-v&!xy5fRllUXVxm|25miYa|xutJhEb%*ub1UDNA@N&@a|_>?Ch?nybL-xi zBJmrDbIaanllZm7xm9npO1y+Px8jYO#FrE27QC_fcMxKi5a-srv0mZ}h;wV*SSRsW z#CgfrSS|6X#JR<8+$Zr%iF0e+xJTk6iF51RxLx9dh;wV)SSIlV;@lE97E3&aIJd%$ zizVKjIJdNo84?dB&P&L~G>Q8W=a#fFMdCVfZbchy68~i*aBe{xtrGv9IJcgSn#4~N zk0##y8~gt`aU1b^iGN7EH}N`&A159|yjtR~5$D#rai7Ew6X&IG;~t40B+g5U#_bY+ zl6XJjWfFgc_$9=PC4N8gIO2;XekbvG;u#W;*`R58+kwl&UNz=Qbl6^H=D65Lv^c^L z>YuDvq3+vS9~522iZ2-@>c`9aL+NLG{O@*Wv%Th!kGT~!HM{dmM}WO@Od#kDSHg=8IXE3L9|A5Gp>4bN zjcdT1gEp9$wj6tKeGX7oQ@6_WAF49mfq)i!_Hldp zVQ+io#5&8Om)ISnWkYTHSu^64T7vd#Tho7SimgmPTT^d#9!4n+2klS)Rn$4t&)Un= z8$?^RvJJm#rSGCjn>go&v*jDkhHUJDbI(ma2beyZ%+i*Ql|uhWr7MDVRtN2`?$~zr z`N?z7PcD?2)?C<}H5+}e-*EPN*eih>0F++P{=$t`qrn9PqeeL-IVgMc9~8-Y7Z3^0 z7D^LYPXZMLE@-Q^mIJcl!cu!mH}$!2C9A9ya^XssIs%|>o~)X6;i`YA(j+M_L`r^*`2T1tNq}c|GDCe2k&~>=BdQTLy0qetG#N@K4gupcISJ{ z8F#hNR<@lNKl6<}N7Exb+jgOGHNT9bf%$c1GX?U@Q6SFry_M+)^6RWv7%S7CzNUJ# zz@*>D>HcVC`lE^Id+ph1ar~91?%!drIc*b%Yku*sX^Dfy(rk zCsu7Oz-nH(==sX@YWr?`Rp=}9Arkb=b(%JwJ)Zdk_8 z8lN$5=J=W8ogYkhp0GRLvR8#|nv9yxTA4>02C<{%FQ>rE4W8-nm;cZKi(1+|4RL93 z^ic#ywWpVvZfn!)rFrEWs5cs{&M!uQ)o?BKFr3OaG;2YdzeE+-h(w(s zFljk02;N&QKZH!Dz5o!m}(CSW#Wt2p9%u6iXUIQAQ=ENJg=o08J^|o1(#_lxA5< z8Aj;VHk|sm9H4q!P?VlH0Gnu3yKPAc%=egs*PoGoavoa7y3S{~x$ig`D|eA_=c;=fvvXAdeojMP&% z!NU$lUc;00!1?T0M*}<9k=xOZdd8;nP%5_Ia0YkocIU1*6zBM)f>gV+qL@Wxg{oSy z-4m;A`0;yLXE&&|71MBrg<5UJL<4HF*vq8=gpw>VT}BUZoHj5>UyGWu76H~`DJPX9 zunikMp!B4H*%OsT&Wb_g&55QBW!`33^~o=ZJOu9!wD$!f~q?8%)4ZqovT&#bz? zy1ZqDqd!iYMwYiMb@-IG$}W~4wKyfv6s!nk$Gi-J*p8l`)2Gti zmAmL0d)1+3vZzXvop{FR3w=HQAN1iAXA5&sDF@qGv6r>V53$fnudb|+t*WY;fgj}K zIJ@%=RNk%nNy$hmRTX4UaaKFuI`|nR!Yj21Cgp*9#(VfDYIh7i}!SyXXK|St^ zfx~Ku_km`wtWw3U-4c6dyDSXz&RCYi>{rLjc`Q4@9!y|!WEW?}LR2n4#IqLUydD-Q zq_s5m;CITtOWgKN@U(AVGe#(}QVKve`?sq6iyTB|vlP$D<*1AX%JMK6|>>>Z>3h%4p~hJDzCOM1&%lz zwB;rm?MY@O={{aq?NSYcvD+}<^22Bv?0hf&JLhYlI#pP|m*!#19n@K6PBcuIs!VWo zs0Vrq6|Rm?gW+n7{cul1`4YRKntBrlDNyykjJ+>E#6l~LLu;3?H^^@j)(TYzkZoEU z58;MMZAAtf;Ak8!D4VG8+=ChYW=}o4?X0LrO^^CmyWIOWk2YH6E-CUjuOX`f-lZy+ zpTui$6L*!)iUtUSkt{H9mAl%6Bc(gPmxCFQ=HbBk-?Y>2+A(@)wt5&>6;PoRS4cOB zqfSq5C#IiMi8I+nz-y$`8qeS~}8WAkx(!yGC_2dH`;!?D;Nf7p>wP zYmDJ;Sk0M=*{o2dQjZ!&_w+W&DB5M0BGk<1O(aG|gY*ycRV*KNS5yb>!dhSLtXK?E zWd)m*w|F_axj>V{-vyf6U%Waia!|RpVm{7>6IH~gSuk*0K}9bVg#jWV_v9(<=OS?~ zRqRIXpv}Cqr{p05%NlplP18QayEW`7(6T$dXr@#P(^*sLDh0rHm@o*G}{2 zbZ5;obGkK^ zKIYc1L_)@#-U`z?^o_m^+P0dPb>}XVa#ieb!88OiJTBbI&!pfE4sHXL;@Q=P6I!XC z9N5MhIbG9FypT))e)y4oaN;_*d_#lgn1CzS2Hf$B;B&8GZUh(nB*c0UFwN&+^CB-K z?a+?BSZimWCd%zs1ukiAiJNbTkisQj+{Mv>-UrNUrrpJTqb{u?TAgFg8>q&eL z%*=?`-cD-@wK_{r;m+6z=k)q%&UCnELtSNQedY91a4|fY-Y~`a^LRXUk@ggL+H*PV zsZ2kGI}W(l=C#SEHoY0U0^Ij$#tbU2{~Zho>qvd&)wmDJUGtF_5sX?xIs3x9y>wg9 zW-Ex&TMf5yqVN$$JzC{g%Nw|YcXepKO_r5mhnCPS8F3I_m7$a9%t%o@*zC+mHDGu# zBds?52WZ6eE1d9P#WN41yWCyV#SOi`U~kUH#{HomWbgM3^%#wroz$0)eEj< z1w1x(o>{a=J!vXGV|{@SNtN@xVY=J-t}xAb0b4@tMb>Kg5(Z!pWDnFWO$Ie*VQCLV ztZmrw8S2!gx1hcnx+dItNN=f??{*V19&+KKnLD=SEax0yuu5@$2e7=gHXefzk}EU3 zWTA~XyfF^(|FraY&B5v9SDB{|;Q(-ATqU8}hF@t#`-Y`gC=un=)^=m9bgG>3wCtb} ze((TSQ0}~Fn4BmUC8LUWfYTe~&0nyJ6*2$(WSz0d5gdRj6x(DrG>ZVH9=e^HAG}y9TEh zgv+u09mcq)m0Y{lgVN5wDTo(ju+qAYHx}hGYOE-I`5Xih%gC>T$6+znDc<>&_mOKG z!lObs~Yc<@b4c=+XtB-};1fe-Li^D`%n z%<5sg@&lJ}8TaZ@kPM6whgbQ?yFX3i&cj=6JiKM>z+tX-=fuud7}jo#Jry?7%m0E^ zGA^bo8&u5MKyBA9%@rG1u8($%kG6<7YD7exiU_%#Ky=7>JH|2W5EyGa>QQr?k7i}Q z?v0{eb96Uc%4{O{IrYpDOf5zZ|FYdo-^BENXaEPO=HM2xs?0C3h(=^zFg6e733AQObYOt?848|S@1ZMsw;IDDC1=6W{RP07B$td2QVmdgusy_ z1Xb?YJxp041J&KwHM`qvL(VXgyGQi=FAU1FAD%lXUx3zb@XraFC)mn~?AI=6e*LIJ zyZ?)W*`JpTat<+V%fZy-nAIHon;OjjB)JCDjNLrLxJdTHon+M*$i16uT#aFJ4FrY= z+pnq&v(m)zkVD)Joj~v!L+q!nZ|`=8mwS{sU>1)7!@}Uz*`Px>-vg*zX_Ql-`#T0B z_FKc+3}>jImfb__Q5dNbJs6()xbkp^d7h|f8!fr?b750C6?4Z2k=xA3<<6%m2CQa! z@3Rx<8_(-L=rEoaj5jV4d?AXLKyq$MWp!?4i5?5bh0?^2(AqIg%!GaIBC*BBSWFLYN;2*2zRi56=OPY=farM^h)Z4Ci)|b=dcEOXz zwai)i4wo|L^g3L5R+n#hN8@{Nb=oFlMd^oLRi?k=Oh1Et4zDJ0{fr0UDoGsty}f(r zh(=!N)u!VjiN0w7qBXuOopP$9jnXNn$~T;nPLXWs6po&BN`rFB3A<=>${(o)r<{UQ znsMKFMEa>xylvBvD6fcN0n;^Ja8Moi1kc!<>3sc9TW5wBn?@o6Ix!P(@IlU~^fN)* zrl4O!S-0NTM~sF(eamk4j6D;3r2{0=bq8o3FUn}x=m zE~ueIJ}z`6CgY-WEyTbuih~mkx8!16jnG(Y2eG9x%?leXs8u$AcODBaR~Cfhh6im> z*W=P;CIGZhL9+ypI1z5=^b~tU+^*vl1+q2s4we!1&;}E*e8ZVdo4RoOFEh;(a#Ec! zUV-Xbo_i*mJlrVLrpkPGtZNy$sV^bpn&7dwFhArC2D#iAeH)S9vKo(U z*ikE;f;XJFBCS`VX1YbK@f5YhEvgdgk$CBcrhLvId9{H&VLal3tKnYbjisQP+%w)l z`EFABnWmw*JA@|cw(N~cVZBttUGWT0h2PZ~wm0=uX_k2%rmxwiOy@d=+Fr(AN|I+08O!cs1#Qxn}ao`iQ#HPf5Ih%F-ba z{*x40bC9p;0}XfU8f557hb}`pEOu+cXk17WC%?)yGS9fDIkad^DQIiVAGwG8%C$Uj z%J9(;T!&;N>+&8``{n3=B)au~K{SWt(>@HlVsIzhxZ}f`oXnC4(CrPrDMSWjzx zp<-5WOTfzxRpxl37c*2Z65PF*Euq?m`EM8tmTU9uGz_nj8$4Qo(K+l0GR(2ak#t?O zq2o|0u?Ac!fXNQ=DzVhqamtC%#Jg*fA*JDFeOEVu6*4SMl&@+?f)dQ20aLN0r1m%6 zZ0?v-KCqnE2Sa67YYrAFAN1?(8p&J<)i%t2-R%SFb?J2V$QXq-A8@!)N!2xOCI3I{ z14Gw^e9*Xs8B03Cs0|GN%kc}U;N)`qm}FPLv;^%>iyAGE8!(nf(xP0oJV3|+#$9Q> z6sf__^^N@J@Z2O7r=`4`ChN%OGwtSln%pu-?gd2CbfgiPC4w=P8~1gz+cn58yXBo* z4~ZV&dF^h>a@pt##tRsI%m3KuE6=*p0^Yi#V}mv?WlCbVq#L#NF`R}NR*O3}+j3VX z_h@x$r*xEea^)KNn(_m-aY&a=3N!91%5{Jv($bU;BBm3Wh!nYoPCu%g+4>f?KPsmv z0nKtb!O~Ifk>sTqDcO~jA5&tG-eiO~Lvo!0PZ$#(sGOpnI7hKgg^YZrhYrdSod|cH zdzZ%Mn#PT3x@SmnS*Q=Hi0BY!D$luwKLx57aY`FO&k*|OFYeLs40+B9jt*XPjzfDn z!wo!wc$+YKq`q;lGQqPRpMVm#81ZJbk$#7>WOrx&dOq#6HfVoF6a{RRg<-$uGQ|+t zp)alKmlF&lX;er%zc46ZPx>G8%d_qL;%@st^~-h@l+q7||6G2tUcfIyRZrM$YBVe- zdO^RqT;0JhP3`>xA4nH**<>ixE5m{||HYWgG_3s`OmWXad5?yB7u=RHCf=iTGq#lI zD$5pGa`LJ5u1@v`qkPkChPa_aBkrCW~fIsx}mxKtOeD*OrL;hWXok* zGE`=4k;}9qu!6Bndk`pC2He*4Z>6eH>2(hN4gg+}Jf#$vv71n-g1Et!CHCf?)1eNJ zy$mk{bU*eYY$d&H!?zkAnaLXtuGI1<=GwWbCB>Cm+OB{(y7JPOqMCAHtTCfx{*+4= zdWdUYIfq-{GA{LuWQe73VL@gV<&YJ}Kjk**M1 z89~UnFbjQ|*Pv$`ABBSq8ITEiZjUHAaR-Bx9Ftp4yr-OFFG)E~OQjKQmU3n|rW=+b z4%%DFw=Z0l#vKe-8t#*FIT>p4^Io^5%MA_c=aB8LeAdoL+`(J!qB8~IVxSvCA+I(K3%vn#7r5y_*jQBht6$L>o1ti7(tJx~kH7RjC3pgPz4?fi?&VdbV2K0GOwIvQ&D4USARB z;q~TfnTuW52vDacpk3*f=?)W5ZUc_Bi|9p4Zjf8UO&w^+M8+o8=U zTCGjQcLsRGu1d1SuCm3Z49c;^;(wGQ-6z}R>9Z4wrKGt08oMek9xZZ`Y(1_TJaC0g zes^SKkE>Ev*!Xz`TV8(2Du->!I!CT;O-WJVQd?}FwMn2BUL*Rdt zM@d)3<}CVe(qap8wAg~Bn(@UEsOX=t%1>KSl#`#ApIbuZQso8oWlWfrKFFp%u9D@* zFDkV0GcdV1wk(IONPa~Eb}K<`Qut+)k+vB{Hu)tAKlrm#|4iqXT=1O|?dC2&@ifv8SDqCR@Je!a9g+--Hm)Y`)N^JP9h|RGq*Or}C>?kdPgjJK_MIqFOyA6SAmybXv@O?@(U&Go}E58rXIY# z;hp~d2P|JTpwy9HFo2)kkGqZAX6z={$ixMr*9XzSN!U9k7yF9jj z{cI&gMGlF$DQmTLw%%iG{a6EogwF;c7*P{Hi7X3%L z;Am^>^C;)O+S+;&~IYD8ELz9_5H*Xpizol+UBg zdmZgj-iz`qO7Az&9zV7l{3hC?ybI+*ly9S4k8%p$HoP0fI2fl~)DDOjAhB656j_*PFGs&qzL`xNa_eo&A0_}6O#G3x^;@n}FE;@Vl7SZftM0(>mn@oc6qs8RS!dAPN8AL2<1v`z|) zm>T52#!{w@>pm)BaNigc}?ZqX-n@zyVc1|@qv z$ajE0%#*)TvZe03LH|4Wmy@6FYCp-{{&|o;0YBE0zp$fTifwBx%qp*k3`Ot-ywC&kL%)+Uk!f3 z3-||;+qM7H-M$|D@4>fw@|AdLAAeii{l(VS)t-EPg=}vF%?5rk`0_ihZvFQw2Y}B$ zPDGtiHLb1J0dAY;tKBy61KqcS&-vEI|Bsu$8T=AFU!L5Kf2o`Q0Qh%+-fq#uBUsn@}?fZhC5B{`v{0VORCW5~U z{O8;8pK|kaz#oWpYh^pWn&_0j8T=c-Pxa&%wb}Oo_;-T8%#*LHM8Nhhga0}B$(YaX z{+ar=^&k9i@!n8p?Y*#G4##@hnf|`uUk<+fCaueVrWJ1a6TyEF>+phh_RVbTKlq=5 ze^WdD^=|%V@TXwiwzso?oLl|_;IDkGwe`n#?a#Q|zYPAQe`0-Y*ZvB3`%~cGfOYb#5ng}iih>sapA@hJFlb;w6-;O1w!`NzO70spFY{8?`P8So#w z06)NjTn7HZcI}^Vw@(892JCmdJo}*k>gG=aKM(t$&iDo3PsRSI+OxgsS@$??1OGJk zP4e5g?*9Gamj5XDuVX)TJ@U4@|E9G%E6{((!0(UW7RqlqyV{%Ha?3vhegpPdJKOcI z(k(v#`>%!AZ^>^IyW1~vw@(89e(b|K<4*&>0sFI8+x4$nwx`OA$3+iZ^uR?AT=c+2 z4_x%XMGsu`z(o&S^uYf&JmC6nx$8US+~V^v1_FXpun4nwWhf_uO`aLFr=6S)7w z!ys#y85R8%S;OxV3At!&aI;YdDZ$zJaJ^(Ko>Fmf;ey>T@OoNtH;1{*MA6BP3$eD@OnsDUmq+ ztNuVnNhC#oF$KtIiKOaY@SSChMAGy{_{ZTaX%eyPGva`Zmq>>G-Xb8EN@Tu%HV??e zZZE>l#rkVE0htu~GLU7u-%=oUX?3xF4Q?V^rbxu0f3*O}RR1IB&RTs?36SZ*9Fa18 zlnuy?ASlpo&<|Y(P-}IWtZcqwq5VeZeJDt1vtC)X99sN zjQkqN9z6sevn-P4?A5;m$#S(Xqh+6dFTI!P2Ty1R^fGo~v9zsPUx+cbEU|o#+AjmR z0%PG58I9_fem)GG#K3@ELoi?m!8el}%;BO{T^SG{J_$G=95$IhA@n2+GB*H{6?H6| zvSNs4#t+#ve-gTIV0!@Yp>dj-V{TcB2=eP5QVxP;Fe>=<2zi+BCd9OVL^nA7)2u-j%WFXNe>(8YFED^yO`kCaNKn_)Y^M1>Y(qV(zvX*ZJ*(BI zSBJ2(hK1?qs6|V%bd54~!y^}cG@RPCSMYc#YYUv;HCiHGTD+xeq;D$f#6AxvckK}; z;eViqU2SH{=j?w3)84Wp3$)%+p6|mqLQU{s>naMr6munbXdl9wp1KXlFo{?+^JSn} zyn2B&+(g*-zV*0q9@5S73maa601JsQCfR;W#E?iUP4v=pdIIS#ITrn7IFKmG3D7eu zfY>C*s=pHiB*wQGZ9?^H;NOrw66vNtvjj-r(6vw#q51wDMx_K_ZOJx6>vGJP;Kh;S zz|!C;tcE(1B#Wf~dlcZw0Sp-xx`$kn zF3~K%!26+g(8#WC<4&DJt8Kzeu zAlm9R682AUtk6=!d@TD>OK-rW3iCAvWqKG8KZ$th4`LpK`5S|>V zBx2P?DUd*kgzAx)Bw;}kiO_TV0I^CWO1}#u6xLNDHvO{-AfdABar(2^5r>5Zah|4N z(eb)r0E5tL94x)$O_*rRSw3sBJPFO+qU7S@yAadK8veA!;)8CCSfy#<`_1p5lBQpK z8<1!Hx{#sy*Mla#(i6BGsV8c){0k~RGaU$p+9qB8?~OmpJ*ZhEEG4dRoFQ=(S#mi4bkLV-ETn zVe@;Q49)*rHsi?}1wz0xgCMFOATv+a6hic10Hlg{1_-M_#gwT3I z1%$Q}T21HyLS=*w5W0yFACy^l5~?S3FCiLi-AgEu(33dH;o?IjIb7FhN!Cbj-`{}i zHx0(qKpz=Kn(l|$6lsx&mp%*AEYerjLME~!4lHI&$4EaD1tmpv_x2r!WGp3g_wirB z$r6Z{1-0%Lf38v%DWSWsKWkYvvrPTFu~2mPGX;WVIWY@sh<6XZOXT}HU~3PHWiusC zL_+N0+l{cMk3{b2;U^K8!OE5^LvR)86Sa#CX8?|finhGVhO8UaJGhpYh=JK!R7~(K zG(=hz)mI_``hql6iVZ%7N>6xaZ1 zXN0~NaTb*#5t}}=H;_TW&5#zSXGQ@T9IRnJr|6jo@2H`{p+Hh~3#$za9u6c;i#!2! zKI3tU3OS61;%%&>n&^tfUx>;C~1RSG}+jPsAirBRpv;5kuRewW)4Qr+BLwF_aQNE5`{>- znixKbh6eSZp;O=tlL!pNA||>aX_&Qs4d^R7*E38UKvVGyqE8c_B2x$vkj6$20XB(& zfW1VP6^+DWID3nGk*R$&-z}FT26~OO)}wV`Vd)C3*C=0_q6Ow4T6>L_h?izzyOpBb0qcN76ZK^s0eCB zmqG-ISlk`kAyI%%$BC{Zump*fbMUr{a8A{gt32p^{0re4Sxp$;`Cl-ARGNhVkA=ZSG<6fcew&csy?a@ zkXw5e07=vQ*P>|`T0rK}bY=mt z=Y=%MYU10hwnHNP@0US{$#EmFw}j7~(=g40`0A_exCl6e1Z)dhfvUE*6&7d8LDI0D zP*PG%{O4wDpDGQhnty-TV5T8m*j4t>F!dGE7!3a*O`bSmRS?S{F`os;EYRD~xj0#E zXN8qsF_|%5wjO%eyy<9Q^23hL7Ol%pSWMHhf%Q>XfM))HS}2zul$s6o$u~Fv^?6Ynwn3-;^;hdv;}DPDo>5 zF1dk$xg23(7F!1}Fps4`i&zuHzya%)FPwwL4vb%j_zHm#D&EIAOe}z$ZsKl82p5eLFjgW1R!55TzR34t z0G!i9A#k^IRYa;PxbWqHg31^87SigFU_aPxhJaf6G^%41#5tZWWS=gM3 z14WwFPi#gMT_VoHO>tryCQZCJGKAA;8~U3lovUo{ro|8uh6FiOWWa^PL>&4xTs()7N)-<*;rUi%-BeMANjE|q zK!lAH!I&kZ#3S1^ZL}Bz`D4V;1Wg+&?z~ph#);!w5cQ&0C{mW#XTv3!_!4a=h+oil zqWA{V(#7{7c*#dRd5xw`7XL!uCySZzgI(;vESn-efPbcn=ir~qMBZ(9_Z;CTsRSO8RAil+D!2bJU>h9s6cRuVt8q`=mjs$5g)F`tHk2q4VpGjn2;dn zixjlFQj7y-fmjcXSBWV|FAGI@q^2zr-=o#l;xJleiiQYW8jH&j;8|i-s-`Uwi^?@E zTilGTSdMrKW0WiU+=y3XgpO8AMOg{1o<+$ zB0CS;De--QrWJ`?XekytELka@M}(A!El#{pE>4WlG>2#j!^_9wUPQ}k@f@OSjkrG$ zm)$~uvQB)HgjcA=1Xy*QXhr??;uXZn2J!7yeB)kN#&AYt2wa(qlb9{nixAYjL3}b1 zSLC7sH8+dUD>SV_gu{j{;&I5lQGAEqZ50lTsZ(5y5xhy9o{Ja6MH%|IP3&5#X;tFP zSWUZGSYhWa;iF& zKr~+d6Ijo+JB9yRyofFCMGV|6P9kpa5!KLsuZTl*{aO4Q8F7!81drV(j!na>I%4a5 zyr3;i@c#p10VofOym^}Tkk~d#(;gNNA#V4Ir~BdMba4uq?-3D-wto``Q2$Y}6TN#( z+=9q?T%3->i^$@0#OglrD|-5bxc^p7ds6HisA*3L0liO)LAjdtj3`8I*^h6ZXxg*l zml?R}Ag;nV{zDAip=k%j*WQ};oCt$gpBL%y>LKydVtfW!^tc^gXb~?WuBydu#72!c zhL}7oVzV{vB{2dvzbyJ)qG_*)KA1H}!~^I{tw=`ij*2l;HSJaLBxdMqA`zqWPw^2( z=a_Inu@d_7FlJ``7AE_@`SF$yQeNkr7gA|Vy8V2elKfltM0c%WW{EYq~l z#AOb=k|<)~&o9K`c)WtC`QLzW?Dy0z%yDFm-idkzrn?xAG0;Q{=7tb9jEXJ<;>;u# zAxgYNA!dkKEHX0-Uyt$j5kC%Q7M=-xzTz3^_7hPtJoD>x{^AhM0U{S(?k1)}Q#Y~h za^zO6pVvx5?L@sh=81UvYN{Q8;1|L_mTGTVh8)Cj2(d?cXDR~7r1h&?VpOcryL1CL0;8dc1Np4jfVk4d=~cA&YdFwLj4z|b zdl3WPqBpeqXpx&Swd7J9Gaw)wD^AI9CZ3Nm*qVrkkA>J@NikR1CJ^y z%;Q380~{@WLIBxBA58S#B4QU8(!UjRAw3Qk^%d7bORRWx85h!5;p9ui8o`A$cQF^z zEg0Jbkqyfe#c4PvDWVY$)bxlI15lVET4ti~ib#N{R&@VbjDWo4h$$L{?u+X;gDw2g z1tA=L+3~RmC6jmxYl4>+Iu=@OF(Jab3YCNMbF`RH5lY9aoncIv@FT~|bR6Lw(@pr> z!HQ6qt>s|I%akB3gmPlSg^4-`#n{DDC~e;&l49nG;4Blmup+Bii&-wZlcSm0Hk3cE ziHI34tiJ&>^)E#2(IS$grkS2XRK<)}yGE~|QZ42h;jez{7=OgA~l3B!WXyz+E+D08YxzsTdi84T34PSQ=8>$#(-`~h6yA7~a zSP*wzMI_F_A{dkqaRzNe#Tv8?6P8I#N|88+i>{CpA!1G3@L3R>-9YBoc;+KW5iS&S1%jLTr0z6c44;uS<_l6d_#Zuq(-a>Exsgd4uE0=VJ($69Xq!sc?rw;MJO7Jr3R zL&VN`-0;1Iz6=vBDctZK#L}KBa?sNe!oGr=yp70lqr~>b+~hqA504Qy^yDUQs~+ zGna|RE!^JigKg8r*BGxEVgbhJa#0U08KM$#FjFKWZf1$q1>D~KhWs&GEWVc8yMvkB z-c5n7d15a-IbSTu=JswTyuCnV;e3?{v~qj5@+NNY#=zRE#oO>(rr3%}yjc9Zmxk@# zR%l-$zJfj3;_vWAj(8ALFjth{!0p{#Xth*mG2Grc(U*Mj8{%@g*tU(^J6kxnca{Kd z?o)w}8=G7LlvxM6_bOPJE!VGTj`eW>F64%2&l_Cw1woNR=6srw(AeGy@g|PE4q8PFCfH>sj_UPc_Mq6E$L-y_Gq}AQ z2KbP$Vb;7LOc<9J#ZGv;S{#EXYs7hcAh5Ve`vkS~<6OC*Y+c;&1Rztq`-h zy=y=WyejUFQIk$IZaopb3qUP)3JTmX)WT83HXhqn6(|hKo$QSs%gIp@70=iR%H2W+HZm% zzWQBUcNv!7hzfWcTbARP5<*1m#mv)1gb6`q5)orVxCTVbOyMFBu@rvu77>plSbapq z2^831m2}}k5YZhL`-zCAJT3(hpP*j>BI5bmxEOei#Tl-RVo<@b&Pe6~MJy;Y8oJn9204sqB z0J;+Bfzb&juoLMsguu`$IFmpwfG`5n0dynq-qmm>fjO0MCV_-8a3+D52Ev&HCSzjt zAn+Cpiz09mvC)&jMs&Fsf%ptKlRzM%#YUh%9Mzk^ZrB_{;75#C9|E_-^L+`#jmI{D zz&Z%*N8lA0b_s#ikP}DXny%O~5C}$$B@l2xav}j61|^9=0-`0Ez`V`aK@b=Pr2_~| z!aPnPp!daAfzg#B@l<93?uOAXao|0xrl^t z0^4szAQAW+Yg8nGtatIkaBm(7_)Rz$WU=;$1Kpy5-Jb}nr2qXf|90U@9 zv6v}I1Zq$xnZQGn5J&{B9DzV0FtaNnfd!)nm_XpF`Pj@7IEE!4oxpaC=_CRZFmRIz{JIhwTLL|> z4o@NQ9EM;jf%mS%4wt}!P;7DuIN{9c1oAL&GYA~tiQO)NF92i^cw#a3yac|*ax{y; zJoNnv0zbg!*#xeR!~T~*>R@bv33#E-JOUrV^YaNj1NUA@;6Mzv!vvm)#g3T3t(bZX z36x=4Eh12PJGRCIzQ<5z65#Lf7ZbPxBbY@X8gaOUz*dZMHi6d*u~{bY&r#Sf6PSYO znMWYD47+9mJuoQC2plcI-kHE1aPM*gqo7nP2JmT$0elRBf|LR$<}!gRCSWcTcz6@$ zGJ!{K!CWRVd{<;DYK~Wwi~GL+SSzeOMfU5AHy@=;u{2sk9aJa;)8C2XYi(!8L4e*WGw^*5cVyC zeG&a;Sw%b~ z3k?GZN8XE(l}5+K_ey}JFL21k&DaD8@eQ)PE_Pf_qc1C^(JO5+27iZT^IY4}OBFy*253qiV396T2a>fttHrgNk)K??T z#1HSb4mrU~KQKCt`geU1@Igl*r!4&;53~qd(td^=TKy1ZdCy~+m>=Gbl5=qm)MnuJ5FOiA*kw73@ zBx2V$BiiF{l*lywGy*ApyXB$DEgr|-X_n{gOCE^ zAC3#ev|Xm3fV<=O#_?f7fo^8!{u;+y{KfhhoZ}yf;~i~>?%V?8?^5YnJ)BlQ9me~S zW%|RrfEWP0*B6sU~h`9KdB(g^zj@cOhPbuI5JpoRRKQ58Idii=F?@8oQ z&B6hSf8R6%k>Pt5NzIxt%Gw7BQXdNo6Gre=8BoyYOzLzn!X7J=n*N9{q&*f& zSd*D5;j_?IAQru%0-VpKxmG;`v6b+JVehOO;rEB%yv0^6t;=c<> znQ0l#(L~SzU|UUJVt^CO>NfRu(~M$Z0Sen``W~|>p{sh;VYlhqU|`)8w#PIV1E0`C z_}4?qUegc`OpI!`&-D6IU~xiPa=`Qol0-tXkX^1ey*3rtAcY;(%o_qRE|bngjF$qk z$-M<2y`$O^)6CbCK{0ex8^gy#@|~>0+VnyP(|m>?DrIF&enCEjv6nDdm>8{*r;+Ss z^d=5`7Ig6iG6o(e4QKQ^3K_lCmv|>(UIYS40MC?w)srU~<##dZ% zBbT#puweO%K1dG%;`!dNOI(5|4iwX`;Bxjk!oe!OPvvsf6$2S8{sA*W#Qqsv&hCf& zFfrVZ%h}bK>)~SQY%XViLQF@B4~K9$dlb5Qh<^>`a`r5=^wdIc!aR&i^cB{Cfv}Z} zPokgb#eIibrV{gBeC!SQ8!<5z&*p~`hYq|!GN^BAle7kJDiOD#zS;z!jCKt}c zA5}DOH5FumcUEEB>FuxO%6>pzuR5`F= z3VYhry%gA3g&i>cj+B--Nny{Mn3fZ#DXd!gae*HE8Tx+I`vC-Q;xawtJ75;!eIL;R zU3T6oytz0h7V6uvmC=qmcN6LYLu5z%HP_ z>+-$IV&VPwK0sR)x>k7aWGHAR$t@G!d$5;G6bjucy!pasVpo$4$nCNiVpMjgnm!dclE+V&G=3hZDcf}kCVT30}nM}Qa z_-mMMzPDsxz9v0o9SKBk8j_xtDPPn1zFX2W@^v?h<{u2cg_V=`n+W@lW9y=$=60^uJ-+Cw*WoL$wrr*$N;Z*KG|Dg5vGQzz%07#w9T{IhU9N_>lQ39ChmKZzgP7&(=VHW{h;(%_y9fm7lj0vUd;o`Y>Hqj zygrE>ne1bd+norR-IBvhGP~JK8|H%-ttLgB+}g#pBx5Vh zl!HJ^9%>5Zb?-!(Ta!mCnRdBKB#$+zY+%}SEox3yy!ob&5E#iBroi!-M~mg9M)FdV z+@l{gF_|S7nPf7nGX*1GCvQ;t-Z7oVxFqjXQcjre!%C2RkK)ziO?xalA#_#py(ZIQ zjL)Qi%@$KN)~Dn%N`HW9Ba%|`_X@L`?yCeA;+ zZKI7gFX_X+rU%M^U81l!x#lGgQdp8)^O8p^EJZW#Mpxtu+8ZE8<|308nu_%;B6+fx z^<}rcb}z%;9~d0dy$pM~o+i&!(gKw1ISR9C{T{?nuv^LVz5WeB;-PpT;YtdD%{3ZY^>M{qDimFFN`w$zC7!Q-CekJx`=vs@GyZj#^-DrDvxI?VO zy)Lt>FuK3SbkEPazsbdhJ(azgqRU*lB$RCRixf1!&*i3`6&lSv;9|`Ts=r@|yju*B zD)l9yyG`45M%#}Y88uq^6Jqol^f-ZdEc$^<%|c3IPc%$k(c>=vt1v;##uF}9UyJwD zML#vjWv0tX7f%;BRdB3}o^&NqEx#hwEc%%%k;Wj^u=tc=FH<$^oB z?SHs7tSd1(r2H4p0>vbq^Lu1DYCkM@QHIX_BT&c~j?l&!#;#iio2KJWAS+v?_oLu= z&9k%6Xh*%~88p^tM~i07463)uGPaq#D)lQu9XjcAP^nY5Yyw(s@*344LThx~KatlO zyRmN-Y?}7b(;y4XAYG|hZ##_b-EUBjqEm^Yn+;m0uEo}|=oUkBiy9#H`L^M6yHT_w z2JKSGImkO@>g`ic)d9U=(Eiw!E4EriFX=?uLmgB<$wJ=Crrr@X<5HkkO$&FbS%hBG zacM*J|M?tS-+yo-E@9t8JzQ#_BkZwQ)QWlxj1u;i zRKPU``i0F4)1?L`3Oki@uQf1L*x$bn@SuSi!v60o0FM|52Yo4&x#;@_!a?t)kvwi- zp|H=+1AN3D@ideL4th}s;7?5tg2H~a3Givty((cJB(;9g)U5%Nq%dz7SO0*qV zM{XV5cTC};WOsTTRAq~>*)z*BaF?*z85?QfK4CYupm4E)`-Ocy&C?1)>LB(uWZovY zd1@XJ_Ev0}it60M8!+GR5q4TK;52v0eYby3{hj6JgTF_FT}pc2>GoBFjg!KjnF847 z_RR%64W*;p?WXQ4!qPO~^#_;+ns%}yv!ERH7K;4UMJ7YICj*G8t+WFE6aABxCa+JE z&#KQ+-OpedwFGfZR#8V$>`j!^gZ@PrA629cjP( zMZ_oY%`Sa$ede10g_f@qKiZA@n)WW9UaaE&zzhCNNJgGrh0B&N z@|aul0ZPzg{%TEbB-f(F`$80eDu(3l;seGz^m$4pj#XR`r-c8Hi1FGU zI4wfzGOWY7{thrNMHgF02`8lceTf0g=@vn}vn1|3%yV+sV$7=#64I?$IgYD_cEg47HeqhTto0qCS^>IBL$ zj`L}C5@shbTCw)LptfU%1xgHhMIH14jW_5Gl?UH3P;b!NYR+1qMuXl_H$uS!vkf|< zelP$u-=O!^QwxDEGUy{!ehpBkK_9CY(&LrNOVa&Ry;lg-XE^(dip>VvV$eBNxE1I! zgTA!uiOODsEMb2@%p5Wh3(Eo0rtcc)2z$c_zeQ zELb|0-3a)1lUpb3am9fDG7wA0V;2D0#zAbv;z06^HgKk}yY>SnhTKPV0hS|>X<(bM z>6|MN+V3oY37-vE;2K7EFfTFZGl77M&u2P7Y725Fn7UhV07c4CZ{T)eH!lKgG;o)& ze@z{n?aHJ}sC%&{6XgpH<$dS^OmU#c6uws2bVVbu!9XlKbWJ0$&A=Ol{Q~Ap;1!o| z6(o63*p)OT{>$VZ5%!}!fWI^FP7K*hzz+?)2kUAy;2&J9vqzCjZ2Y%@$Ax_{iS9E~ z_#v!*q+)+J@DU8?b$~b}`6dSTgs^vC0q8dHBnE~08)M)pVb@_j55(%Y^I@F+Jb+^id>=}f0a$7%eM-f?->}B_6q94$A(muv}1+?eqmsZ zwCQ?GK-e*FfO4I*@5ACB2)UZOq zY6JI6`+y&Cih(yu`x=5X4Lm6A4_OIq-w61jN2Fayvbx0ftpmJA+H?Ui&}SMtE^WGm z7?5sm_aStU%xjE028%7;PF`qyy))9rwPq|; zrtU}5{)GlyZQ#cc9lVUd8sma}D%m3oY%=hiWFIqdnIUB2AOjCvGI^hO!$7raLV5MlhKUSm316>3S=eBv|OM>$E^w zQ3_mY@?Q!vP~FWz4#kKXU$YtvEIkTisiR>KHO+8+4)vmGeWta~)TQ%R9ESkwCUlYg z!R|;d$EYf~2X5L4HkD1(tt0)N5@XRqN%~v~(196n$E|C74 z!c@-EM2s_9A{iVzpNggDh6&J&86+@NrlXOgU#JVwyCG7JV@6hVvZ%KqCxLv9XCAFb%W_*3f0U)DF}UNty7g z#qMZ0#^UWFx@^}D)$xfnAQL5q<$)tXFF1%1?_Nlk?V3^EFaC+C7$??a+Qf@1aR8qn zj!eM#xmuvXXcOY(K*cM&Sk5t?4JuiJuE*O zf1G7yKP{4|vC-?TY`Eie#cTA^KBT`Qa;UncZ$g;3unlu5`vc)`ZUL8E@of0iz8|J4 z`(yLSy`%n?!zhJX@T>V=pg)_uRCNO}`Dc;NkLs(j*8%;_xZQb$dR%jm)d@j6?r~oU$7erF-ToM>vJ_)`gc;D(* zyRi5MUlEA~$V*jcV}V{3iDQAX)q8|q6LBQyLUr{@pf^m(p!zK_@C#ECCuxMitrn&kb6lIt~E+Rb=9D#9F4@dvE4m6B3|;xmkKJqqt4-5|u{~CByorzHElY5M*|G$A>k*t{ zwjNcy^$0eYtw#-C9}P}7_39K|#|t(}_7fX<+ZCK+sC1|scOma$nH~WDJ?drneZl1h z?YEqfeSkBvA3#Ta)Y~XZa4KOvgEO;FQUb-DrUOW5DR`9 z2m6yLZpj}70Jf$OaAf^jfXlK*1NdcK2f!XKmWp?l0PJOuZRv+VSpOV>Lxh7@sy7iY z4NesYP&51ae5Cb?*t-c_Nu#()#J*18Uxffyi9A{+viBDO91!_*WiFexd%tEtFKh-%_X--npzMa-R^;Isah z=AhF&kzO?Gi~LSDT6@D>qmw+1ew|9C{E}zNSq7y@9(oET@efZl~-kW(XfiCaB5?l^Il}O3HxnCn~=|({+l+=sUta0VNyN zv+!txx0-3vsGxI%am5}{eLCv81&1@uwo_axz2V;bGBqd3QbvalU_+b7uzd; z9FLrhT}B z*}>o;8GQ}FWegsP>BmW8$<7pdv))NLi@4sELNCWVEq4;>%Twt6cAt)0yKaM3vM1%? z`MA%Bmb;R@DKw&mcoE$?b|rT)$hMq=bAgg`mJ{h~5PziPDyJNk*x;00opJ(k ziw#c6HyAkbW++n0wJEcpHh#Hu62Nr~Ql;7oa6L;WTmEGoz&9Bb%Fi|d45W~w9h842 zAs%2*WfbB@9+EmE(QmQb8jVD6W-!x8^dN&)Bhgz}q6>^fzs(ZuFcSR^OLU(#wyGq{ zb2oM7CIltJQz&l9mJWdIlzV58oNieUki&HSvXaIlk6BKYF6vBvs54JfpGR;v3yp#n zaGju0&_V{~xYM={MCZaYD;cFojGE??mJm75*k2;a%>f%W9ydJ?g49nUhl|jNaS?d) zh&u6mz_KUH1z)$=L41o#E)vdXi($@a10t6QzMaNg29+0yc)D5FrJjPMWxI$kMvoo! zb3z>=UN6O%DNhh+sfZ^pI#pc_U6sp4ycc=d>fvQTD?~ia@Itkx6R2Cn$0D!Fz7bPE z_L_Rw8?P3Cmzd^H%N)9EbEP1g@q)}*zF`9%OC}=N2v<%(!8N8Jwz_EDl4}ioU)r(d zfa?v!&iC$dfPDsH=X(#q4Tc}=d;=tnjUt|A2DZABVRYms5#J5|u+=3SBsYtAlCWRp z^ses4g%Y~s3_IKB;it)MBK{v8)XkjUwRpst-pGc1Y-S;{c8GWjCD$qYl1l(D6Y-?_ zTa^7!4&YAH>s`ves1opU!{0t-(|c^?ZUe7X_66v_++*N=Wv5~+t~BtV zvU5rRuQKqEvhTw5llu%jqU`o0z^e_sQ`vus1H8t-dz3wYGvKub9>xB7D&Tbn9#?jH z0PuPPA5uB}YuDjnY8skHuxqE92Ta}xWzV6SHyC(Q*?Cm+Mgvc&oXtTzXH6APtDK%7 zp0=j=3o2&|9=4|FD=KFzp17vy8z_y(t||I93gg*pioT=lpWg_QhYiUy%D%S(@HPYA z#}Na@KprvhBV~KBJjy!^{8-t)A=UY=fuAb-cch(n8u%Aw+gAhLW#BnwZ^VvL-ecgG z%HB@!`vzJrdkw*R4RpEeW`g$_=(y~?m?-j?fl)4dfZ+WG`d#)(64C<(Cc5kw2_82v z)n$(v1NcJ&GhB8#!3Pb@cG(-J06t`3zRSL72H=kjEOglyqyau`;8>Ua)^NZ_3=F#L z4|)K9BI3zasB+mSsQZtZ+&Y)Ns|@gjfekMEPc?u~7})5t{iJ(8HTGbp%iewy;FCs; zTV3|w4gmhlzy&V*^lZSV4D4{(573-EWu{q=D=&7xg~!Rsu0=7;JL$hlR`dx^h$w;!~Y~f6} z2$j#(A#;w1&xcX6Y%dM<+z@)L{Oodi3&nWKx>H!?--Ks4U$g?AIV-L57h#hwG*Cpr zFg}NgC}XpxgKY6n5kDg3G~oN zA!#`dW&5*k1)0PzSCG8$4wd(bD7^?&`a~SrQ*&r0qeUF8Hh4E54MB{EBirCtWmsdS zU&N8AO|^yv0Qt~JCXksHUqFW}F%4yfxFZQg#fz8-N~~H)M@K8byB0Emj*emwx`y8lch+A&J9pB>m5%d7lBrGYz z#a|mB7D2vMj(7kIS*~~)VV<}%gC1adK93$?x;xdvt5#NJVm~A%rbEkxg(*=e9>m%? zN|dj`F_E}?I_`ZHzkoQ$hos0>7zId>5QFiJQ@{W^rpG9!(YV;w`*yv@IE$cAkpEiogKhMP;Y>(l zz37`nFJJi!q_IIvh79|~jA8Whm0hrJo5V#|)5}->1OvZCT-Zu4Ul|2W+a_K`uP+tL z(4+057~Jl#G}$~&(^b=L*ZSOiXzK8#P%wP?=oojCkwX|yhJ%a(Cl+vsyRRvgYy;y$ z4y8#Yx2bVF1Y96O$(ptm`aZPa{5AvXxYn8r`kPQ(hZ!9ad zN?%N%NuZl3k~^)^SNYYZ$=j^b*Al3w$s4TF z*V%4aPCpc+%+9z5O?W2HgBd7Ga^5D!$k>&o#BW#*3E-{AWvT3ro3|d9r7O?9O*~u@I54Ho0VQzvv7-dDAQzhqOc9a!!j(PH` zEWn__(j-q!opfG7kCiLuYVhK@@J3u@E01%cXtC%=@5>XD_jD1H^OFIRlH1nN_MDEg z%9E36_}59=Rg@2lrTxGbNyi!G>7mPjpGN~^C4UHuyPqF;EzjnhgOXlMTb{$&VB^fr1NnNWjU8|DMrT}CoQwQqgck2Lhlm86RD31`x<2tSKdW=&=K2vMscY9Zi;G6|4 zn~DMkOXRjWC|1bDI^@lmvK6BlbjlBQ0gPeLBma)Etteu!NG1qn#PZno;>CK6_l%DI-@5~c`v}4 zP|?WfXQ#aJG(1g=o;u~dkvMB+bn2A%x**U@Mn6C0-9mh}FnaowH)|WvEJn|q^5#gO z*^Ew~@-Bv^RLo)Y>?!YN%*KkjjGjB?y@vWXkJ0m|ylbWbwJ~}Df9~;46x1#%=bNbS zc@^=V%2vX0x4;uoZSqNmrVXstK35^ z=Oj~dB-Erho%D+FcLtiK!uE?@_q{|VC5)AN_j7bI#!NmdkpMhDd zj$*KdO=WdVBALov@`q{2@h8&o?w7l70ElC7Q2w$HAb~IHACWttIMs;^?vw!sAc?^} z@;=y;>J$b?<7Yc}4yn&O`NZ25-ne z!I!Dd;W}^2`&I+wah)@=Za=^X&iPbUVHB%JGB}s?4UA=VAp=V!Jx9!qV&sUVzruD` zk4anzh4qW1FB^fzCSDAbD#qdZY;|$sa)6{n41RSmu?O)&k@O~PUv&v{6ckBoAe!nj zMtGa_Udk(HR3(yrMW}*Njqpanhp8TyNbZ2;_1<(PP!%KLWusF)o{{vj(W#!mNO`@l z*Pvt#BbS#=N%cfV+UspgLS8K++v|P$0-!oZZm;*VjX?E`9Iv-~4A5jo9xof6>M4x8 zUY;J+4UBwV?=v*!(-=j0y|qMTI-_VW{@Dj}P9@~TL%Tc$h%XrLan_Kk(F!}>mrQD7 z$?6>d(QFm`atp*dK8ABr<+pbM#4;$9hhW~u`x#WpLU_#M;}|sJFO`;{our&?ARSeU zxDx}7$1U&IP{P0bNLYtKQ7JixC}An$&M~;kDmCXAB^*ZFd1Vw5(sQ4ngbA2%&R?Ox zDkJx0N_ZYihx5-FNXX1RLka)bjD)EpkdT%8XG&PP0o$ytGPEO9xl>^9M5>MciK7UG zcxFAiD&`lUiugk>?FdU|!C?`dJ+vcSzn6A|6UTt6Sf37YiGN%}JHqR_Xh%2)^E^s) zuc95{laN-7SO>|(if7A66(?<{9pQV}m&A)(_S25=MTja<* z3C4?mjiLSD_PMnGEBY4g|GMYV{;wB(uND6SS9Rk1kZrx#gx$spwgV+lS zQ^km#wEvsAl=go&4kvSXDY$JCCqT1VOhtT#c<2(^|Gn8k`@f%{U$ewn#Al2ASla(x z4j$%+4oC8g7$wESJD1&&o^lQ*N^d9C`RVHj zyG1@E-y_z;Jobw3L6VnS0k*T!*dkyhE z@oR(|#77AG#ZKthM$wISH;H6S%T1ygb7Zqf06&|>YOKmz#1ohpTg9Xqv=@AOB<%$! zAbq=-hH!_NgYYu3eha;b^LnhKyF|%l7GA_z&_?0*AkN{$MvUnm(H&2>YyKMc{|Z4@ zTd%|m*YE%U`5Q5ta3)^iu-h4MBxh(Tp4AR8&dwHL$U&s2&(RYh%hV^vYd8>{4XRz*EOhJai9J287{71ld2 z0(uo1jkhuS^yTg8zbyU3l}JoS0)4}YPa#p?j$o8inJUTsN#3-y&#D~8PEzt_t1`{( zRyD1}nhNL-&_zv)wBAX3JEd6r51tybB=dpK2zIN~X9a zH`D=)W&lqw4`6J_)4K)cVnPvvMCpdcObDHN4cE405HqZ1A_GUxwgKvsAMT^AH(frgnL-+7 z6~cGiVAV`beg-)~%lR=?O3I%HYM$>QURX2Mxt~arhgDOY%>SMf(~By>2v8OI>sa<;(Q)g!TPiZb<$#qoUTW}7uPO8#LWT81`kg|!p=O*<(l-^E-JY)Tyk%uBspLF zP@FYPmWEcNnoMd^Y)S+XQPM!G(T`z;rFgdrs}ZjHp{trkES}1d=)>nLBy0XN66!Rw zg1hVxb=Jc|Ote$!QlT?<7A$T?**T;q2B23xleP=zapD-0^+o6II%DcH3QD!g#mnzYZLD)mJx z(A5UjsduqPPx^*Ijq028fUY%ETGewz^E!hTsM{6+U2jl_-K*TD6%;G;*o(rP-*HmE=cG zw)Bk!$WEd`D&(0~o5LU|>7MA?yrd))tFoM0v|8)Snt?_=??UfS*G_SWwv4+R84W4? z?=NzE4#2b&GLnwma1Frp(52zs8lWj94OLR*S!hpfa|)ToY&jZ=Uppg(j%EtwTQ>o; zgf0!gJ^(PwTpE@?n*z|9@*(O}$=DkJ=5S7(d@TWB9usJkx4_w|ZDY_X?}bj(&QBq0 zvp}x87GOaNS+5THHdeFRMGSgmEf(V1B@EWdwIrR3_)`5A*<20K&N;i}RalE_I~eSf zuVUe>UB+O)jJh6RIfH}pupgk4!4cl^)pn(j(_E+7F|O@qRIk}-uI*toS+kp5+skN* z_FfD>p>`#s2F*t)wX6A%@F*Xp)UIK0oR3m!*D-jAk5X#aGk8S4T?Psp7@Uwbm{zs@ z3{K)UDu_Un`sk0L5c&*FpX(ryI=hhmxx#ZJxGk(papuwZ&b$a2!;;S+Zpl9pNK2*+ zn1~T@C+ggV?NlcL@$5RE^BC2kEqq;cs198qt&3&gNV+^)=V#!TH{AjdpG-Ftr^+1k zxGsS~n%o3|)+HuaAqTt7KQ{q+{Lg^2egOfSB4WtRfiXqQ(}h^NU7pN8BhPaH1W&t) zo$q1Nv3u_d@>O|U09}q!rSZd2%Fq3CmGjm6D%lPxxGEUb#n3f)*SPosn2g34T<>;O z$I}JxRzCl8P2lstgR&ng;;P{zzaxAY>zc^m&X`M3y*7R)|muL3? z)W?%?e#Cn}y6T$3rZT>0#FZ|$Ad29OIPeP znaTpArF$X;a2(Lm9gwk~5(8skq3cR{JG_kYIbaPWrMEQcQ^lH*h-rH(6=21zz*T*C zO7?zAp$5z!Wo0zq^raStFR4VmKQ|cvv&IpCd8AT>}GbK@AX&S`JZ(>KoL?cBrJ`8CCwR4J+xv`5- zdQcFiS>}+6So#KPd!Wz|qx26VH7RE4wNzj~T!3&FeDKPQ)Hy~y#yei9RAAU3uXR*v zux;)w-v~(kb5pLRFQ-adM?v5>i&&yV4xbTr<##b&Q^v^XwUor8p7D#Z*vfSZ9-FJe zC9AEByGl_s!;H&eN@tcbUZ>*QO!1SH%=c_k9yd{qXG~CW+HDEHLMDCPf1uzD0!yc1 zYWgWr-%85*0b&`4QFmI3A?VwVqF2xmQq0oy2gBp=H{qEwbr0EU;X-flvv}6FJbDPZx8Z6MX$l4)jRpnGI&A+jSPAUaTg+LOg0odteFlpPTwsOh{O})4KE*=ACP#3NYL7eBISms zMkaB$m}W@S<*ve&LJ>IecUf%>6#_FXK6aA3ND1x zbO(v`I?O!!lti0facJBw%gP*<0S4|!r??upXM5(8wCLYaN(`uhBil1y!+NRjXfpWV z_Vm6LmcBEFX094IxFhWiWZxA-6GIK0*`D?kYTq4#yLP0dM&a)r_^qI7VBe0k3of&) z@ADX|fj73NRiMp#L-6?av>bSO_l4kz?dcfvqakz>%`Ug}u@HP=d)lHpbTtHD*`D@V z0~SpmO-eQJ(Dt;8(9RD+@R99l6Cr{JqiLq7fw#A(rK86W#n8M(hj*kE_TY~q63JAc zzdO=?fT4aY+H~ln?P(w6Th>oQb@%U>(1Kbs!L~jzQF22pP(?m528>mJ({AEMM#{l z?8v2?VRVXle;vBA!0;)`;U|h=Xs2>zsyOTAIvYd>X2dV0fX8 zwR|;*$CDLZ8czI|6>Q70tZ$Pp(w{xhXP^1OWO!f~bdhb!w{vMap?jB=bXwmI(0y5I z;FZhL>0PnnwVlQ(rA6gji&SIt_Xr)f!T$^mQ1oU9m4B5wmzAw8_Gx>&MF!c$Ja^Gihpc zg#bpCWluC%5HXgI_|w#S@Igp2jXH6lfLN!)HS;SD&BVk7(`nhXj9_-|ETO*}O)H?% zYGCiqOg7kQ>S781;po$38SOXr4W;6cC=OXr2)p`F(351PP3oQG;> zhT6so$RBZN2ii`@>wR@XJS{XZZPu9YLHAs1dH?a=NK-ImF(L6^qC)1GJyfEc+$jhq zldgWc*49G+M1c5ltq(029mI~SFT8wMS^qo$uB*&a_e6*~tPOv#IDl{p-RX-Wxzv9- zu*%AMBMk{iikyRI#Z;ZXSKcm>=|FQ>0GukUA43>WngVn!eV~ zy^%Vj#F$7s!!dtUzNwS{wK~6v)X5j4B6aSsL!IHK4!!@KK7%r#fBiHv7%oOc>U_2u zb<#|omqLX@mJ0ou7O9gqq(6m|P$$XMxjR%RG=)%STcl2s$cwbo3PYm&rp~3II)ie% zKT^j(WPDE3nEFhed0%Vi-AEmu$d9yBn2tKOsgwJ){v=-!mVrG)21~FYDEt#M5&366 zi*1P9nj>|@V1LH^7}~GCq{V1>sLE{9b9DVqRDs)t0;7$Gvmh6@Yg&@mYRtMxrJ*Y0LRE5? zTT;p-q96xW;v!ELd>r{Vkxov|@AFKl$_V|Bh(5VRC^F8tNj-)1rYPV#)2mLa^-j0~ zB8{Jxxg|sbwuC?8PuE8f|#ACrc)EJ zm{}TpS~1tu;JE)n`dehGNi3oLd(p6X8u3iG-!&dRal2f*1C-^e1&aA$CgK?xb5J6A z3AD)XJQORiNv_74<@{K`gLEru+YJB@dlQj?cMN@mBtP+y56mkQ{_%(sVYhIR@V3=p zs2DLp0SqtF{sd|0$&^Ncnn`K7>yb8}(kM_Jls3N>X|$3F3RFL(ZGrc%FQYUH)ILi4 z&SIp|xu~E(9ip@+&=dIENTWa=6V!TCX9(qqUO$`bc0FM17+SrQGg5jGYzbT?^naa7ED)EIb}6h5x>y zl{iN4MUqz$nUqv-eYn2Y?fV|p&mtGr>-fkSceuXSF@6jA#lm3fkKINy;_Jnw+YsnTq-{GB??48h7x~HXP;J&D{5!lC@r1j;_#|e0Pm3Y( zhY%%k=vr!u7@s6YQ5^1FH0jnPF`kA6c9{DyNlZ7aH~PpSt`oLlzSFm9#d2H&_YZL0 z9!rqs2pd7da13K5H=7h{c1@(&PpR29WRIg5B;siWXfmSfh&~67E5$t1EUwZX}Z$ zA0mbIjz8kiHHOqkQ9Q`$NHNub4kk5H%r~SKSh+t3DQOwy{0*%b_$-O2$whAF%Mv3) zN)r7`^uiKFMw$&^6Bd~AuwC5AVz2}~$O;kFaa)$Sh}u#E$9F=bba)(=_*PqX7g1PqC`d}ihkVP0@mT7DYhrNdrt$v=lx2{*`~l~*;@ zyPc*fK8+F4RXZTPA!x~03qyJ;`2m$z%Z!$^CZ2;8YeFfHIv$=mxglQB5B}g{yZohR z7vglzWbt&NDm+~hElrI$uYikF%mqK9io)OE%8e zEJ7b{XC`7p)vF?XxIfIq?V(``_2KraNFR2g`psPZds9ulo=A22muHsm&127#@69#m z$@k_)8uW;KZyA*DM<9MV6W7s~$E)5gEJa4FgE}t+|K-Zvk+FXBL4>z}**Tb!YJ^T)c z_c8HbPBFX!!92=Bi@ZQ{-yDL?WflozKHpM%FupOCcxYa$wiuv0o+YF3>dEA_`1 z7SWhMmh+`hAHL*TWV7f$S*d(uFtkb)(0#z7vAPjOV3gQ!8oO{htoGAFt57^9GOCW)n-c;y|@HPg&8zo)6Divo9!9u(9TTl zLXNl!K{V~mRB8fsF8U%=Q^OLw5J&kq{^3oTHrp|6wqx3C$D(OF=E~q!;(0r!ANm*S zxM@44f2?0X+;Y=)Oh4>(K{+HgFi2vHLEAGgsUo&xlqe~|q3xK;LQGH~3n`7ZW2%(W zD3CRjM%ytpjnXKPt&~RFF|~-&D3G0$M%yv9hSDgITPTgTV`?|0QGh3_kw)7w^({)H z01qi6jkaUzUP_|?&-Ehhlch*|g3>6Emgvy+1?-q;ZyNQ6S@y;LvtVWgsRfkRvHZ0+m6E;a1HqS#Xu`v%3{qS%cTBZlQ+iqV4<@*V^{TC{!S(OPLm z)BP82yYM9>#q<3a?v%eG?xssf?qSK7V|BOObo+%nEtxVLE1GVgBH)XU$}is z5O>qv7w+g#6}tPv9m~LR=h3d;&%p1dyD!}F$+v=Vs+;blC_7XCS|bD{gx^~JZ>aNXPL(D09pEUMH+t`CAje{Sv<7yEIB>YxQq5O zS#lo90ednRU7pO6YiT6lQ8Q~J&u8sLX00yF8goTy%vGADsLi+paP@^?k<=_pfS`L~Xm3z?T#<0z6_X4btqIF<>(RSnkzu1TnO2DpMUvsUXZX7zl2bz@ zS$Lle*@nh_2kjp-Qh8~iDfP?9SS^PYV5uAvBTV~^3ENP7lA&K0y9NIx&&n?cI%2ot zFXcm^$48F+22}SbDMSz9C|rS;*wFJ&il7omrM@z9jvShlVH*R z7R5d4Q}}57;Tb_`EbC}X5xJz_g4^cZb4`)Krp7xV=`asb&<% zjX&o#MQPkr6rR0DJY_a|6(9NZVxR@|wea*#pbzT$d-!ySN+=L|x@t9i%Iq%SpnDM>|zG`1nLKPBJC_#r4 zTwD~hQRBjOj?7=2Y zRDq4;p>07iwCM@gm#J9cSqdmP%!N)(^7(RHO$p3fj!gv9%Bez*HiD!Y=}3uiPYD^t zqIMVy8&s)}HN&W8W~eD10V}& zk*JjukC6nYxgiE3eaPb~kusqH$PaTKDK{cSnmNL;8}~TJ9quw(;4T-?NKp?8(F5vf zgutj2ymikE9OaK@-a`2}=?(P{yoyCEbnK0adHl3#gGdGIafr+~UshoyFdd!w@AThf zwNPKFu~}X-KOxsRESj?;^jOeC#nw8gZG+7~)_6ONKLrJ2RZMye1O`5_T@G6~T+cjz z@+xC#T*lC8W3=qAPI33({B*)&Daj;!RTDi%6KT3arZl47umSWjQJ$rttf-;GL2`^n zZ5W#&wPOaylMHceSQ&7U${55!6B!W|t7+H@B@D6))%)7aNgS$tN#U|l;jS5FPi74; z6W`38l#q(#*wr~68n@KJ(fF!JhJ~q;z`m;dXW&Q5i*qT9QJDL3PrDnrMeJnIYoQ{Z)l>!pi3f>x(zMq>?&D%ubZiO)hB=K8DJ5dSq@!VLWi&BQ?pJhX$NB2|Ny8ksl#3D6Q$jTfNv9!obec-i>}D) zQ;6BmQ$WX0`V0ksLf}3}X)YA8=~TzgqJR#P^fU^VP_UAMZ3t|-RIdjppbPZQZ3x6s z3VuStDFpIG1fDl3_#FiwQt$}{f1`l@}L=-!0{ zJ1MrFf=dxZU5Oz21_X+3e2F+%1cJ^<{AC1d z3C={|ZbRTKrr2?C>h27uxiJVH8NT%f_m}O~@~rkbi8`TK=k@F1&00)!N%fX;7HEA; zr&-b^y0o`jr*6^-U0QrzqJ59)VViVPzm_%Hi+mN(e)`$16X^%_=%-nark@M-Sd+*I z4FHK6?dhdbif)%y zx9%){RLc*;nw8bB3z~JB^BG3nS?u&{_lH`_QHk2`1hp+o<8|~zom``Hy7Z_Tomrzx zi?v;&@v4;t+M~8~q0ES6?Wxi+_=CdnI>woyJrgwE^@3OSIX5^pI_9j_d$sqNcHge; zw{+|SI{H!VuF-an_Mx|;n}XZ0$;8hw9YsGUv~7@!e)i~u#To*NTc~}zH|n&%=;#PY z|Igq#9lao2$Mu|?p7@xKS**Q}YlXkBS*YFpTF-b)MUStZ8!lP->-dL z+J8W6XOf(cni*h3sXF?{l2}~!PuPD9yvM@S6B96Ku#Mx zHiTt*lYF{3@wSG7LE-wB}t>yS(S{-rj*Irqb zpkr^>Zs!P6C#PxqS?wB-BNDZeV-i2m-Vb!t?RuQEP|L#*-y*FBbo5!B2JogHev?jq zQ^((`lMn0R#S~Ya&K+mDR?O`vew$XeG4k9_^~=D!TBL*Yb6CgFkJGHP_%}hP)9-Fm z$T@6E9gUPylzW6{w~{4^JcJ;^W)Vc(lzo_`qnvD0EMN-l4i!3V3hfRR>ene$M{Ox) zql)1t>1CsXACQuJodj(^pydg4A_u}LKC0sv=z;+~uS++gqFkU$>8DGt!jEf#o<~14 zr?tHRAv7i)KaRaX$M)WaiIl4|4r}{O9SdbWtfQXO>1QGJMcVmX$2+wc#2jr8=!AgI z#SnUT>xvC#P1udB+!5MV9ywiT_p{pfyv{nRV~=Y0B%ME??V~ysAu6TLz)!#S&(Kja zH$nTJ)oDSE(H?$Udv@zMEGy0#o${u39n|i5+69`6X{<5KA86kPy6$!j3EE)EH9!(b zXLhr1qACfu>XgGeyO^u<7;}}p+jaD3sPegX-DZeDQr@?TPB}V{vBpJh8W%DLG}g2z zDM*$kAjX;tVXV0n`V=Zfb^>EPhJI+Q3n_9~DIoD`T`=dlw~I##gm|H7d&gUz}iZUlaGKV*#u(_ zEYzM&FhboWS|T&Wd0Xqxi9uL2*Fqir7cEZIBI{YK0D(lUySu5pt4lZc=n5FUX3(6W z6CTj{r*-C|I<97qPJ(gi+W46EJg#Lw?#~6o3ypxFjClm_k3b%9*c%eKLN?jJ| zqts7~Fqm0)$4LP@R6?`y@19)KJJDHOg zDt~rPATTi}cTrAGAeb{UCuh>c851YwOv<58AQ+sOlOqMF*W#F++S>V_+QQk9al{+& zOAdJ0`DW)j_A0b5*vaJ>dDD`-X+`d{BKO%v9dlXS5Y z8NTkXVuen`I)fDr;}*3EHY%GJp4}RP*NDb4#f@1;G0Sb@mq}|%H5!$8x zWP$c$+F{)RO&8kVODSS6R@EO}R->`R>bJs7o*v}Ui$xm@9@FYEYR5AXoI+Vy50kI} zaUC}z{W@Wx_Ct9G$P`li=mDL4zs~8`(aqX-RC^!??lwq9Z>Br$FF;Q2)hVQV;0Bk)&K?F5A3+wJg9m^^M9Sz%29-)4AA~1(oj0;F>NQ**(hZ_B-QqcFoF`m#g4mGCHe>t-x5X4I>Gb~Mmwun~YWzgv$iCQU&kshH=LlR(U49(}d= z2o!%*r=S!js&iW}N@2TjUMXJLm^Kt7t7|A#h$O~=MS-ze2zI-)52CnDC&N`{%ZGVR zJ~Q?%QT;Qtd-o(Rgbt=0(3z+NXJiuhW}=z*(P$eQ(%Y?*p4Hwitw9xqpVLv{ck|R4=tY@(4r}6(Ui1aN?I=^ zoggVbe&Gd@mr7nG!({O$6h`gEggB;PF#o@&N*kGmMbrwGYMe0G&DwK-90(jTV0Crl>|!pl zos5(jI;NkE?o8Ug$39NXJIxA;Y#)O|jt%9ILTNLoOCG29d}6Q%|CZPdA!69~gILs8 zhz(<68S1{B@SyUsA85w@>X#N&1LspSYB3ApUy-oQCeE0O;)8M;=&u z;}lj93`7h%hkXdk5^DtPH*Gt;fBipc9U5g?&kwa81@^zvI+mcXw2p}tYCT&0=`zTy z-|Swxcmsgm`EZ*gmX19%0z>Cj@{v8%F{A6`x`+k3$_RwlDbU5P`Uqxz52Zq^Hct_* zu<&itttg~z3Qdfdh0l^a!1K^);k`oZiVq86Cu2Rxrz^Ug%(~pBG!BU04r|VX^NZTaUPh zmbABsMW4*WDbJM^1oo1DpU!>eb*Fy*>~;OUYuD8G^)21n zfOr3{TDzt@n*(}`w0?g3l-Uhar?fXUw9lG7YpT`1VoQHJ{o_>q)YDq zqR_0ixwB`^qYAA}3)-i(w6#y3KDWHQeCAZ7HS}&+zO=9NJaR4d4d>yeY17)9W=?Lg zmakpCZta>CYx>*i-2?0TH?(i=Te_}&SufrVuwqSTdspAm)hnzGz1vo_uf`wY4P|j& z!-CTGhSn)9*3xCm+t>B2?I%u$^kI5wi?w=Ld*_Pfy&KT$^YU8f&YnA!dl2bz{rnQ{ z=#+W$+GjS+Yipm^wvap2-a4bLy`jFXzI|H#%$bwxr_5+?n~RVLhWo$pg8Aj8rL869 zlc!ppE0%5SZeP{AW`)(aV(BVwx3PX!`{dbeZL?e2r_F`@+UGV+Z)~$REbnSxx3q7= ziuQi19kI>|CK_(9zGZULR1}`yH1)!!S<~C6&YItZ+AT;szc*7_+UJ!*{OzqX>u1%^ zMdmaT+`Qh-6%9-Km$q$Px8f^A5uxR++Q=`rBz_nKT}l=v~tdF$@vvRVg>9HT z)4HU$tE(6Mgb4TbcK4h=3mPw&HVq?dEnT;6)zW&`)VZ&^S1Y~Nt5S=Npz2fbg> z8D=@6o-Iu+O;gUJSzkYIN?6oo^;0lsThGgHnLh;@J!C>4p)_2fH zw69vab?wIfa2^qBn>q(|r_7!SU7ylEy}qTTzO>ZZgfXXybbfl3Mf0^C>d@Y|baVTL zrK{Jig1*gfncC1)-`=*cbt*KtVe0Im1HGJ{kQp-8(68Xy&y} zo!Zbi$6B$8Ob_Y%25bGs6@6RLfi>MwiJ@Yf-_lTjK||AQA_;lSYn{>#+c95TEx6u(~nvAm6oQo%s;Q? zc~e?xE)SYzSiANMcrw(_pS-cFYek>6VdFATTD79RXT?&Q9{+b`-vT4qa+Y^&F2TUX zFJ#O^AE3?L%nj(=-kF}q-I?jR(=+=3DL9aXheYB) z5`LjK{1)1Vu9eDK%8tRFtT31Im}Kmu%uRhiM%dMy4eS7P=2?DMLcYE z8YIG`ADwZ1oE^+&NFP4G;9@>M$Z+&B7#OPgI5bvA%S(&P$%8vNwvNHwyjaDw+{F`H z!&Y}AZ}YZ;$;rv|sGX4FV6@8nqdt)rVuvc(*?I$;3;6sIHwf7;@V+F!m^tUzoqCH) zLSVJo(d=vh1~ko1ch06u;DM8)VrRBHEpGF+u;hl=@{$6$U1N#PF?+=>*eW)iDW<@9 z8Eb~w#vVCP_C7xcr%U-7SW3RKw9xZ`Z#B!eY3Hkrc7{EHWODy#w(}tAL2F~!=!3~` z>&{0;OD@~ebuC|)rCIs9QhvS7y=WI*y_n0`gqI{qHJ4>%!Y*H|_Z!V@a<)G&c4rq{ zb@8xZ?;MOejXqkOUmT@;uDh{>nPhe6$6VNpT*vvim3Nx?#qQy(aWp-~`^D9I3pP9D z@DG+3u!Boewc)7W&~+q|iH!c)^k_2AAi11Pid{+orgC?EF}0Lao`H zM^2ue9Xj0| zeBzW!mt;?g)?d9bY}B}Di`CWc7G$VMgsVtsn~l}+aF`D0c%7`doa7#az{BFTiwXHK zc2S5EE|5t7WzUdxfc-JZp{vRkDOC-yvzRm$x7+FHmXnlq*>AjGLxfk7W9RU34`d8t zB#%4^U779eanHfsVM&+51B=s9g1kWqC4N|~-}3dX#NSn(+R6KOG2Vmijat#`Vm=B;{n#%)N-{YE+*ylFr_P>QJK zc2w)FV(0Ak8vS95Qh8uR*})@K0p`Wd`QxN>+wGdr#tHd0wjt2Fd`(~P_G&L`Z_pj} zYiYl7Y7j+j=$)tR)7aof*gJeYJ+hT5I?@%aQ18y`Ti^rx*ckRtCPy5s-q~y)0(jEl z9=1%3ZlI@n3r~HGs|NdW4sofm=b>a9U7@0%iK^US^tAm4w|L~+EjSGY zWBi7+L9Pj@9@{V3YROMlTSKyOh-Rb+S5fq_F>>^lJ&F3ZAtI08Ld{b2nM%{0-bxNORupsSB%(ST zfr=oW9G;wBTCvS^GaC19rCb;VO;F$&!^Gmz)L|KH3VnsWtk&&P`Az28<=q~rI_%Yh z7F&zoggP=gCH19;P@)cmFL9#^vhl-70S!oRjN9Ty1ac5X+?Z&yJsPYV7X|15A$b01 zj!CaDthGU>=%^Nop~4~q9V*8NKZR>}N5RXMR@i~?#@nJl_zSnYYsKJRf0$H(f_GO~ zZBfU%j&C+5vBo)Y*;v-b(u(Q`;W0hbL4JN!AA7ZaW2qQno9+wAc<;t}-ji{SZrkDm zLj~$uL#P|rpCL)^?uud!Q6cVBt+`Gn7w3u^s`n*107|}|XS;@eq2t1QPIjf^LG!AY+xy}I_QKI1nU;I?PA%J+oKEf^9$nTC z*K1u6QRq`YtQnK=9>wgdr#i1w1*Z?I&vfkYCQ6(uTf!jXy3m*2g@p?78p7$t>3Mn8w%5C6Pp!u^`y8Nh_w`!&>Kw|E%q0V+P${WCRbS;uBSBFar zOAAJhqCm=&g^jw|&Vga=9GuOLCxE_oR8oXgMuih+;6O_f#OxSfp(2zpQX2qEQOk#o zwQe5@TSK}fv{`gV!`>)m6TLei1s?>$80ccOLytD@Zge*RB1LRzb5M-$<)V`UL7E)L z+calrv;nO~mbuStZB!S|A8j`SoYV>#51U2-5GM#ACG%6b%AcRgA^<+-J0SF|xHy42 zw5v;r8VgwTTFXJtm@cuct|g2`^)YY?0&F&X_LRJj4HMj`-cSzbXiqP1H-#}KM=5ygB^M%&|Utc_%7$EztgaC~}*?PX_% z4&e9$3Y|}<4+JP9>n_I&ppIyKf>f1rTdQxip>58fzn)C@LD}4t=NVLL@E_o@wtdL_ zk*AMJpkY)34I^;Mh%ECBZ2X)-xdZYauwAGZ^YdK{Ah5y1iK?K{ehPH&;@E&^Ujyw{ zHhm27Gj4iKh3GJljh?Lhh@3~sW+_T6p`T0YS-X*gPY{*lKpEsH)q%_iV4>g;d(5f7 z9hmJNA#Ze&R8Ct6(Rkgg2fd-})m>RmraKrZuVG83UXQz>`wJzVVQ(^>KY7XV@*bhYHWRVP9%iDJE6=E|4-R2Jd2FZGSX&B15{7tvyCcgr z6qJP788$QStA!x*(pdVK!6x(*0p0uA1yzZ7F0~y9W|s>|^?ks4$k~xDoE|v6&xkPH z80UC(NA?JxOh8K2S=UEy=bc<&h={!kW_*8ldP*cS!cHzusMWzX5?C|Db8POgDv34{ zz(DQ9~QhJR=$e6TT9h@H@5!;BU5DFUDVYqt}7wcF- zU?Y>WCsNZFHnz6@c2D4#)<$axR@oGS4$m5b4d(?^zFXd2PUsy!i7im@qchM` zv77DU{f}m12q;_V<=70A+4}s7m2eD|)I z=I7W-!5>QwY}iOxLo&t?CD*&sqtM0n9k6;>dkY|cMOEi-D1IL*=l#`MRy;hXP;r%b zIIbxiB7CFW-6ZyRZ{#v}5J3QF(QctqJI2Ozu)&UY2{1!ZyAZP&j8|u~`%|%+kyyz5HVG*U z$Agq77SHM9Q&`%fZ9x?-dGz72nXSvGD%QCguukLT;~YK(IdKD%9xicJ*@9s}Kiq}9 zG&$OzVY35)t7I5$?1SDql<1n+&5U8g$kFIJpYCC|xHy{*iK{%E99_VB0`3*@V(1Ma zQTtjPk~|V$wsd`_B15y) zroG0746m4);PP6d-7D@k+T+Nep2HwP389`($^LvIGIY?ea@wUPGQ&bR~;qWB(AOSg`>K+O+CEWsfbdM7}ssKMZp?~7HPCV)wo%Mq@WwO zSe+Duk6KS*#9AG&6A+;OP8T+^GXS?f`lX?%HX6VS2FByFLs&J=!NX1E{7kl~dxNnV>#1CY#iZ^v(2dT~z=;?$Ch9(PPWgQw-66{p1HZi@T^mLla0aNg znk^{Gdxvm2g5DNbG-bL++3{@m0xjU;^l>)W*=yXNnS+y$M5$(&+$QGNSIrA6vClnY9VV_FP7_ya>%&4vsMFM7Pp`>uzI?f40C90 zRKbRNv$rYYN1)(-dnswOPw$dIX0oEV%pm8)y{d0P3QQ%Yjqb3v4&%&Zeq40buteJ= zY@b41YqTT`F(Yf75YvWI9_;VcswZLx<@soM#i0UhOYNl5K2MK@I=1KKgk!%7Xd8U% z>^?+oUp(?w6wm<9)Ve0dMa!oLGaF^n1fGZKpeN=B?YncTdTT7USn&*iOA(!v#BU`Y zu3-hT)HS%3t|G!6-E=afXgL{qDU!t=rcjDfpt8QPr8sXSjf`$njIMDvtlPE=jh0qW zs-=J-2qR#>(4En|8=_Ggz_i(eKm#zIc;E%x_23YdbS{_eMW2!3AZ*j@qe-HyX`B!0 zFkFztqz`ut+Oqcmwc)wCkd>~TCdf(w;UrH}5OHZ?`8L;^$uqt*O|<~woYJ5N=QZ`s za`545B)$Xl8wNKalqUW5a2v!*u4P%`z|M42IH8|nJk|9<3m~;(K>$F^w(7m2zvOKp zE$>HgDI&F9A=r!G1Fm@sP(#UzVEmEEgiDJU;MfPR!Z9ZHAv9ch6>Pmp37~t*;?dnC zevDdFBKiU4eiXx83A7Lo=NAC@qDO+~gN5(R_NnqgVTxE@ztQfh6X;bh7oZH_!vo+c zs!-w4fwueId)fWePXMdA)V?D#g3PeELs30FpV0*H=m5L6&3xJDdR5l#3`9#=1m^%a zb5uO`FHihk=pWnb(lU|^pD+=wKVU&rcrOz?j8NVNw}2LO@c8`(-3@3g;+GKd$)13F zBF07YfL-2{qnv131j?(tiV9vye(20vmCON1TBIM=IZMv!C~R*u&t)OJ_X3 zTqOJpiNZ+%ghS$c&lh^_2iw+{WNlL&sDsVISmLJK~g(}wU@13p-jV?Mvn(VK5ixr#+#rITprI> zr<0B*3esJ7xJKt$Rm|LOVs@e#{JwB0X3>lA1Y~XB;)ZKuD6OZbvoiv83j9*xnET)Z zxNS7?Zv(z8>TLcfX@JWE%7`#;_aj+t0m(zHR=1`$4B6qux_2}s+3rq{&L@|efmb=5 zUoV$i^JT9A*S2!>h>lCB?$50^n)wLu2e*Re2r3yQ$O14q^rX|vOj3E!aJ>gbHhCtB zRN%PS3(`h1hKuPK(#ivGjbUq8Y3Satj}i)k>aN0Y13E6t{%z>cWt}UhGYY5eO57EY ztD-xLx6ByjQ;9LZeu!+Z{(CIDb^$}VZB_8@jd{GCh zk;Bxs1r`P=(iYEbPZdydP-<~1;w;>LK^74`ap<~h9_)N8>j1UK73#3yZg3>qO`Zm* z5sEpm%(x48@)~?WR|T>O^AZTT1zUEyO|GtiU?@Pb7+c7&OIZh;5!Ny;`{E2_d4!)3 zNB5LG0_^#Csj|rGR8XRI(}h~anN@sqo}g=QdoQ!Gq%HfyiGp)(2s- zxMZ||WD61pqPshV3D6-Wj-u0s2s8BtEHjMRAR=$Z8Q8xLrV?a83;&J*hd%oCt#Q6o zj1dz+*?Z^U;^cukbI0#EhETTUd;q>q#TEt=?|f8o&XOI{fLxLR{nCM~bi_&_!~|cV zg0@Uyj^&iqA+*ZuaM0GfEPWlL1_h6+n-^+qIty~88X+)z6j3zw!s3qdJhD`6F`4~La`62HioyZzM1 zhIEBJL6zb_HABQLSP%`7^+eTIS1Bb z!ZMKM(mtm?IXlRS(hw_Y6wLB!g2v%F0j^$H<${? zc-_ce66x5`r(JcCDfgFm!l=m3l%~-ZcTD9maebP~#U>KXO=plVBJzqcHL_oM{c*jQ zkHXT?H3RGh5r${5=+XM9=!1aj+zjwr+!39B$u>rR(s(^+h}ddhL&PX$1YaZdqm0%< z8sfg{cnR5*3fH*q32?zG+i!&cFERY??Y%Oor>9n-7x9?oE(}ljI0d0WbIV?ePn5gI=VSi?>f zQ{rZ@MHu3EZxDwciRO%Z>~UtrsE0m75sj2b^BBpmtD?Bk+8P z2*oq&nIgjkf;k#tk~VWdQScg^!$U}8Ba7w9j_RBR;B5FWM4X;8?CW3fPw=EZe6lK~ zz-#!B&>x6t=4BV2+Zf}i%43whl-^N%-$bYc2T_ZW2|!RhK=?F<(&y`Fx<`iH1DZHJ zPl8q<13;FAjkBUVy9#}H!kM|ONWh();LpCe*2jZ2gv(0QJ6QP`w zy_F9lvjtZlRM{Q2c7<-)flp2*VLkG=ARE?1?u96(`b~+la4(?iZ5gi=aW3UY>!b;G z-di*8BZMm>m>4S47?Wn08{lYP4!9#~YH+s&XhwW;25c-$=PD#Sc}_yhaO^-xFe-v! z#je+@^xB8!Y~I(1`b1#K1VIm{2i)5koI8c9sO{xtJT<{HiTTUu_mXsAyfK2YFTxCI zCV{{XduZIxA(;pDlZsE>us>>aB*JG&U9+76OaJ_2>%i0_3J-H{5Puj5Iek zd~g<^-vy!oLdT|Yj*IGKK(IH(-%;OFFQ=iuue-@bMI*2=Z(``51T0UN~sllhYq z`V^l45W9YH@(2&VETm*c!^WZwsYjMlEjt(+agJ0l&e&CleSh%pW7yX7`EFzKU z0T5Q8x#Mae^yQtfr;98?>);lg(gX$OCX)ELL_!g0nxG7O{&4B}EWWg4NPsWvo zTPeEM>8`eF?N%b1L+gWHf|2*-O;39^J(FpY+N0D?Pd`XizxU19fC8~+@Sxx6b!5a<@5@Ixm6TWcr96XPVnVkUyYZa7{XeIRMeGaO6@G zlUNloV>S}DY*kxQxcnI4K)}xBhd7%=?~Y}mVY^;tJD_MuCV2RS4953T`bPn$j4w^> zLllBYK~SETZgZ=N-4M?7BYM+MF3xAgzF7vZpg=fTVR+zoApn+B^gJbLy2xn%!bWTY zk}dIa?+Xi7{Ay&CM`BMWA7I1gwq%ZIWu^#{gaCOD!~74{Lw1Zv9vS3mg!Bd?YDx$| z>^>857mG*{97%)CA<4prR9?@g#mSUf7||z?k z5v&A+mFV`m%bXnIZUclC1`)CBi=?gaB41Fb4#Fk(T#wXDXF|C6ZI9_eC&F-#>DE_) z3H$k`ijv0!bqQkWi@V@j`mdc&kpM_MIZuxs0|=ZyV1^aNRoy92Q_O@>%bCmI6pjK6 zc81Zh&8Yg-ijca%%=j;}Q4)ZJ=vWWk3h5st>iQB{OAJK? zNaIEdq`)FjuEbqbk#gLnq%mPYi$DQR3itv8O?d)ym;fl?sL2bB@4@p(FgT$hT+`*F z!5DMQ_TJ&Xt^xItG{5wuk^XoIfP-%wlxeXLeVt&fuyWW?4ULnX2}ukN${R(!4q2qa zOb_6Yud5@Ti5$oTc2R$*+zWF_P?rkXt*~_kf;aRToVuMOKLqh|;kh(OpC<1^5Pkq> z5ofYV|A{9I0k^8pi8_vlzIFz^bZhS;I3;Pj#^g{O58HbM%`glxpa(MTNY!8-0>1gI zHPo(Knxx{EdMl!uA;X5mMumNvk(O~ic=+V1#nEw|8b4(Mv9u>W?T=TYS(O1M>|MZH z8NOTbTqv`Pp8-~D$|88Jx+;-*#8qU)ic^Akog@t+gb<3NxXe)GiH1uXUXWNz76%S# z#>xK%zSt%>-EoK2DS2@tdz*^9knU>Fav71IUP zQhIUCBy-sr3{r^+1?d_g`5+7p;~{twnWHNpvZ41Sf>blZg+X0ky0u(%RyBf$1CIqc z(nxY&TB6;6{;<&Jvy6+zOvtr^$tk*=y>|Zykpt7m)13>=fD}e%4Bu<|$t$j|5zG2L z$UHf+FkB@~i6JO&){;T!_g>C1pZa{;fZ?cfR}(NvI8aOnch@Rf7PJbq*E^e0?qSPe z90rR^oigc^QJ^@@LiM@?2Ib@aM$$19guF^jL<0ZuE@U7{$#;0NM~8ZX1#?ONB(6J> z0xRyU>L~O$h)c1A2kQ(;M}*HFa_dN^OMT-GlQbkZ)M>-&X_$#{3=u@c)D3g~8Rn3J zN&ETbrLh3txPzrY!nOpB-ZOuMN1nXTs7FM@2AJfhR9 zPW}$&55^A?#L=YfWNR>RV!C3egvMhVU|X zB0{v%?(`w;%uI(9_5di+P%X^q&|$FxjO`G>JU2t|+Jjl@&ykNuNp=nsIPvc6KNSL+ zAn2)sTx7-{=a0_d6(=qO97wfC2uss+5WxdA8X4Iv+*%?$NCF<=s$yBdR-d$_XVq!2 z*iA2{(236JCKLH{Qk_x!j(oNh8NvHI;7FP$4Hvu}SDM(EdhIMPaWyA`*EnxOZI7E% zra(g%TwcI)#D{{}9z0tWP%%!jHzUlD4SWVU*P_#bUbs1fS;p`_lZObu7DqSc8^fN- z2snuRnsI=^+79YQZv_riLF@)d7?8XK(;jYR`$x0;8ag+xcz-n8NHH0)-1=a4v&2;1aLHLT=~7PKG^Kh*_-X$A|PfkMeQlX%)N%4Hc`=HU-pgZy)(S5d- z0LEQ18Nea7-5m_t8pRQ4O=V#aTHJC;N%gxackc{dMp(!tnlUo*WjXFbM(5IpB<0C- znFeo9)87V}TZBEVQMGS|C1RVkDG%m>z||b3!Z0^9CoT%&m6rh2i68)?4r<iJD!XgzVSW=ERcv9DeN^>k!Gq$Ay7DTBeX!A5;X4(rJK5FydYT*)WhYP?TPzfROFM z{f2@72#ZdFF9>Oh`QJH~jt3(;nCwe3FgaOl*SfW}AaH_PLcYYB!E5<`s%}#Z_a+d* z$S>2{NT`+?hrBVi56O_qhOO)jJMC2bFlFe&%dLo{&UTRMf_{6Xx`&phg~g2dHX%TQ zri&R8#Fk6i8&WlqnrRR#k_T<)AzeVqvpb`$3VZ7;E>K9)O>amq?`Sr3y3D2=F;kVT z6IW@wid4J7ht)n zRvF)~mH~v>9IG?65jP%lm0CGi?;=?jb+;OU6bW>hivJ=kC9k9Nzv?@;@i=`V<9}|2(m}VF}qyy{sigl!Pg5n`8T%3>6j0mQPR^r-a zn%u!2`mQWe@jsDqOlfm#6A}b99F31f2ZPk0L68V6m+K*S2l3Web)NGPBDaC!;Kqym zoU`L&niu%CVb@GUfY_&5Ocx%`07p(}Mg8hiUgm2D@rBN51le{WULWmD zA0{xNYniHlAb&nG#%PX9i@g*+OK>L&$O%6Mb|}Y$R(so3$wta88tgfw3jtQ-IX{kp z3rSv)$l)O&zuIcu4poRJrwO${XsO&)Lm&EgbJYKg>f>d?TX>K9Shty|119TN_6p+VE0jTk_?<4UaR*L8?BA1QWa%p(GfqrNXg}{FcNoc5w8UqXYP{J-NgqK3H7VKPHdpPrLIoC zB)S90Bao}ias)psaJWo!FsnBq=Pe{7qckPYM2Z?QsMC(FlA)>;D=#9KE7U>cCzguo za1C*?#rPgb=srB_<&t-Iv<*}8_R3-^vf$W|nrJ(KmEZ;wJ*kpjl1hxC1%TQBy^D|* zrn?OVFPWdNItGRc$iyh~pKvXWjC+kgohdCzx$}C7}6fr7s1rw>! zJRs>ykObsuT#*zru-G8&I1J#(2vHOVh=Fm!hNV53hV`5%Y7~!SJ|NR0Sc%E4k1gV$7j8F~$VjH4QLC^`<8?!iCHgVO_6VN|;6f&N_;l z;q5f}1M{~D7{Wf9T;kDHD}1OAolpxAtOIfQ;c^PDZP1@&TX*^mHp~M4%;or8~jfpMLVLS&+HfJHfVWi6x>~1l?_xjO-)TK zER}mGe+n}#k1`Rhxe#zeE|rteYzCOsb`AK%^L_0xLmty|SwVwU6y%olZve;cczQdV z7HWq zC##q=?{#y3Ff|Jp6BTF-noTr*vbB`!>YVe4dpV1$RhxKSeLAfEF=K)rE-X^O&oDxCfX{Q&9p;>AQZ2&9BI1L3yT1?M&ctFR# zx^Yq6mhGsV$tF~vcmV3-)iOX8_9{D6ZhAl-dj=LA%n|7bfMjiNuqPEr(l3q=10c)1fe>=A(ju24r#=A%VV_}2ZPk>ZAt3v!q`tWt%QD$sB~EXLrc94` z^|Gxcl**nD(+R|kNqD_b1A;%>0gEF5i@XQSbjkdk)Rr!}B=-q|fNMD2#zV_32FGZC z%8?WTzGum}3*qrBp{x7^k-jGLF+u&0xz#ZkIk8 zbao1Zl?BHKjsG)vmtycjHC+jaYwh)@D$_n`WPUJ z+6?SrV%=}r;0q>qRLMJ;r2(RKd0YtwNp0^CG{P57Xj4So9u|24o{oJSbbeCGC|Xy< z6`WyIx^RR|kP$l68@O3AhH-VMDjfby*y z$SH_|NP_~>q1LO!W5L{@EgvV`2@J4F`jYN-wL0Ffx8AA^D*d6}5b>8Xaywnjgx559 z;tG6k6UR+#b`ium*r=zf@517erdA{4)}x9Td}pzDfqKBz04fb}3}Oq;E%A^bs#=9P z=4OO);NvYP6CxebP|g_CU2pI33@8+rjp9x=9Q7_jdFgxSPTJ9`?lg9pQUv3l!8 z(N7Y)^rHNn6zb@D*7DF^;oA^>Rm*QY7I-O~4B<^c9tVYEH3x}pV#!QPaUk$+ z!Yr%s)4j{XB$;`DS~wCylf7OJm{U0sl!aN6BT;-fF?1`%>Ne1t=soV}@P?OIzbEQx z5DX+`3=*v)HCYjh0vgwRjTjlJzgedPa+piFXfOT9ylZWJQK`rI*2yq~j zLHd$qRPJRaBPo4(=Aj9>sG)g;Jfzy^L9j_plgF(5j`4-*Mz9+>ge2=@7b|^`Z1YSv z?Gyv!FMaMFQW%<&V?m(c8E=eD2jiCfQKU=ctmP3@z?_9l!%y+i6DHz41f^))YxMRe z%j3D&>Ed%;1H&~Lk3{K6WV!i!=yD`~`_r6wgdY=h&`d3Hf;MEPLbENNAEwS;;3rJ_ zrekO1tf|$h*q`B$qR=f9CqlPsW)6%O0kWGjDx4l(%&wTt6rPvDrOC+?P+4lIQc?z6 z03jiaXf}{d64iLt9-U{6J_a}%lgAM-Oe2^hxNf;A(g-1FMVR{1B`n_A`dXZ}@DZ&N<{TN4`SlW-k0q((Z2zv#v$sC+e z&Ks2fLevALTN_LwE70Ajh`{*lXPf&(Tdo;@bx>K-^>MckFJO?DCzz8Z$xWj2iilVU zOSIw?qPa~?R6heU54aTIJdIZ6{>_BA5oL2r@uYDj64Ne@?%uzt{O(m^Z3 zIq}4(O3+bfGB78o43d^0J41%%^aYsDKz$P8nZprlSP5~*Vp$*SE+SYQ5t9M?<-z6m z=@CUZSVFI$u+bDzzUw-jb`o_5nYLKxk$!-0@RwKw6^$MG`9dYwF2Wx&NygnB3U6(;uPHYK#<^>J|}nFduQ>qAL~71gRt)-X}j z(263bjyIRqLL_WR+8?ADD;8|g`jd$LUdppnwsud}k5`7luj<}302>tBb2I>IyVIJ^ zE08^+ra3|7P%qoU^!s@{da{`S&JrP;99IO2Y844Xb{>Mf0KhKd>8!nLnZK_P2;osI zp}HZEAnLd7W0r*&8-`|y#`#e=ftk*wMs!dGLE`|$lg$feG%Rrw>`YSPnIF>gK*C6v zx^(+?wtxNrNFGvg0R{#4ou1(sLBNp#*9`SxqZVl1XF$YxZsFJ;=(z#zh_FkA{fH6< zTfHuJzfEL&+!l|~V4RwiRk<%WB5_6-Yy($C9$2FM3zVWEp-n9%cW9g>MB^SirHB2b z>X7jflP&!=rUczbSK@` zk=CI{FPi;h@yvxqsd$78dzw@iXU7F+XfnF6-g`)Bj;WLZ<50tSR}!&VfN^CrLi{eB z@8Z#kv5!)H1TEcx-v&~)0(mFOh)1f{+ZCgN;+^XGbN^J#UqL>PhMoy4ah6dy-E4q% zR4}bs4qJ4_DOKoq2^^`ig3un1fG#V#Vt{&TXpS?MNA;*6piVRaQNrU$Sd2P+nUzt3 zo-j(9o`X^2rO=UXAv}n)l!AreVWw9o3bzNAGpG$4#c~>PotJI};EiT_$ zEE;efkNZ)w2!sjXie~*1zC<*$!cRIP)Z;iHwU9<4j)2^0#;owJI6GD_#42$R+M@0g z(mZ>GSS7%uLwm+~DP`h<&@d9@$jO#obPl}ju;=wzJxGz5S8R_cxlFKCRSA-iqy#>g z9-ZP2QUoFW(ivBohac9!FcfeNto!-&H9jGXoE$_KuckZdG-(C_id+ht;3gj*j;<`| zi&N16U3-FE;$Q+W&Hcu4WVGz5d|6TeKbMNVYArBD9@iTO%jd|6bvF=Iy8a~p%@GG*=wnThGa3RkcmeamZKzi zpXATR*`hGlC9}EJgeArY3pvO?iKKcU(fF&vPnaJp9R%Day<@ihXc2N_t;ROf8xcvc zqgqr^DzYQoO^N-BEibN$1_fQav{jeOhZMni5_Gwt2bO%f z^7`vlLtAHnV`=GPOYBY)sDQ?3aDjK5@34`63#37Oxdim2)I3GXK~Q0Mj3$@2yvO2p zEIi)AZp-|1cm|KN!MdhXI0Z5DVsSA{vy$-<>SUYJcc(knLnOH>=>CX4gs(JJfh%D+ zyfHaX5B!-UbOn1y^dNHdOJ46CB&>cQi=c9^1U$-48(h4^ujM|X{SXqZIlCQi4aC@6 zM>=;LeR%wEK~k{88CW`2a&u8ZxK+m6LaW(yKBCYfp@N98M6N@A486~H2I?i&l4EsI zm|oO=NmH8uy-XpK^!MqOiUV0m7)LxF%8=DHNoJXLMG03dWC^vwUksvf0~&6^vt%Z{ z&*RZ{iU%N+zPquKJ=Cn3@}Syq)VHI{SCJwe+bT2f?!>u~)BzRenK9KSEoWe^*bM30 ziYB5(QD21$hN3V-4DLz9BJ@a;$!}a@EtEvyVF2GIcNzr#iUY0f=w`*9O{i~Ap1@0s z26YJmK|ZtT1(`nlEHuwT+zFi!$g1gB+~c`^@x0gj9ZDK{`bl_&W`A=e)9AP>rPX~& zP+GocIp=w=MtvA6esU8wSsWD%zPFQ%58wG|2kVf@=5k_dlO_zgFI7L0@!taleZ~d1 zF$V&IOnl_S_$5Kc2`$l(oOFp(#ub|s0+$rt8%Cuw=vS5%l+tmlu}Ogjd4EErLefm% zvM`5cn1YBkA`waxsup8`*9X2(2b(RN@n(BvIkK<`VFgtjl4biqVEQAC!HwjrnjQ^s zl{c=~!<2hLg5e=8oJKJ(GUOf+Bl;sItgR06j#mmQ+cA`h%~V#{L{>?;iCiQ^irAsY z>P9m?(IaQh&oo)F%J41--)YE+Pzo+a11D(@`n^%HI)Zhx&+cO}iv_eC@4-MeXg%w} z^ESBqphZ&FxQu$SlS;UMxZc2_b>sn*o@SzFm#YBU6*8g;Vj1p$Ls6AdU_HYojd63L z#aYpWd~BkSab;9Vv7*UO1MCqGd8Y;ECLYgLAO${7m_|n2IVWEHoWKzn|0S~+-_(Q$ zhRn4Hct?jYxx(xE_{Jc+c`!Sk-h6U#lQDO~N^SzXy9ro?Nmuj1wWS+4^Nm~`3LD)g z^h^O37?2_U6a^Rw(p_$s2hbGpO~99m9W;=XL7<*W0aM!|sOSXwijH?qHSv-?4V?I> z_$Ju0k~?RoPs--38)d)j)*Y`UP17Q_he3J(%_4dmL1Yx9k4n{GP^s$gAk9UU`JAlB z?#G4bgufEgHtW;l8sQo8CYKterK=ot=tEalOB<=&0SbX7&ZtP?? zZeTUsynqWkzY>MFB8dRLc`-k`iK;jEcXnHh=%OFVUH&d<(>2es6M9`g_At>Rx>Lm~0(d#2v|O0mr*>;Fbe?BJXo zYS!r}`R^U}i_1?mfB7iIrA+(j|QmoK7VI)5XXBR&)|!57_X zFp>C9PgQ(~-9~;YeS}&}Gb-hBlhzQ|3Vy{KD3#y`Uz09J%otYwv~L_e`wDjfIi}8j z5(2TWZs)Y0qVCyuNBZoi7~SkUU{U)9Ym#4QhHx)s20r^Pv}@m$q2PyLboeCw@Y?w< zmY9Cg>2Z!?`)Jdp>*SV_)%m&pq=q&;Rr1rP9^^y^gnMpZs+7>a!?#efDhj@#oSj zZ?y6^e`Q+!6;|G>l)s4b*JW?dUiuNO&*$;4hJUZi-kN1UBtOG{ui_h@``$`B52gNF zvOoO6P*uMCUHpGl|KE>tw)6egPS0-paV!5FE5BvsKWF8C?j2gtweo*s zR{p(}^8aP!KWpW0xB6d*7iWKdrBc3R<-b)a?^yZ&skHx!l|N@4S+w>qtbAbQUv1^z zY31K+<$ux2f56Irv{L^kt^C84_J6_3KW*jqk^QQbzvHX4VK4uLmA5M8pYwVhhZ8IJ z{=D7FzrRxdomTz}mGXC4`EOYH*Vuclq5O5(7iI5zzZTrK@~)MC+{$0E@=Ym!W7eB% z!JDl7zLmdX;U#}Iv+3LUF%0F!7pR)3wLiy{m zH)bC?*8=a)FIoM6_m{MM&FcTU)qk(m_kMoD%HLOM=k=eZ?f;aOzs=hDVwCf}ey61c z|J%yfz+qVaU+-waH(*}*=i~EHYv&8JIC}@$xoR9f{W;ps3$_q#ShGd%&xJNXzQe!Y zwCDbq)hA!z-BM z_5a2ot?%Ri`&OU)k$?Z#>VMZze}B;0|JPRD+0^pCih1In&sRo9hd*#e`TJF?|L$+l z-+R{1Cs9s1xn}jh(CUB6>i@_$ruCi9U$XjNX7zm@U$OGHSow3$=zP7Q(1L$!&*jHe z^ZWIv|GMnW+3jz&2BMFv>bIr+FUUUeN>mYF`_j%AW$$@^T3$%`7iMp$>=y?p&$2fm zN+GTP&DM_ZJAU=srTlGK_C7Ds&mTnj>$A_zvTJGi2T=Z2(EnTOT7F=c{{_n5jPn2d zN?QNdq<&h)U%&a3@;{RDXS2WelHT*2jq~Sywm$a{axH(LAK8~%d3Ao@h4O1wC;k{& z{X1hV{VZ#LU&`Z}`u$r_&i8to@g=YEerxCb>sqpI?fi_@e^aIYFIxR?s%!o0R{uXr zxwl$={+89R()k}frT$z0jE>KreW$iz%P;$KEC1~4TK*mOh?`b^yrBgjvi`hV%B@oL z(S1t!(NoG_eMKl#r2N_JV>RuJ?_a-UeW{dtFUrsBR)1pS-?mF%XXRgG1-{<VN91wSm6|zR$n;Q|f=`Q_4SJ?Y!rCz5lQ4NA^#jQvX9%{~uUCPp$rcv-0E0_0sHt)tN(4*{(rafAGZ3>`@*vFpG5gJ`yPLMNZN@@^!x8U zrTlX~Py6#9UP zK*HdqIo${BfZ#2-!2w0#shh}9jx%U9-|a3=8085Gk7=hu=nxK9zp-$24IqRkhp>w? zpFSKlklR4O1DrT^e9S0?=oj3j;A0wBjo~>UxYW5FH)6<*q(I7&bT-tn2_Mi=)Y6T_ zMQI|E_=;8r&RNDgUvW7;7vPG^ewavn$xg70i#!lPP!R8}Ti@b}76}o(lX;KFl_VKK zRKggrsR#Uc#Z@NgJ=i&=)`0On(48I5B#}EbI+($Rs}Hh#n7ZyMeSp z7Ud?Ca#hq6+g3~;G{_$gRUZMWkhS&C?_iajCV zGgmc2Z>>xAksB`(FfZZltE$|pAnsSR^1@}v91BKa|A5LTFg*vu9&CX84FQLdcnm)J zVLFhT@lr*H>Ej!sS^~7k*9tRqBBmB$jI!qOfZgcKaXT;=rLZ>@jdiY1A$1~-V@K#QN#Lb5_%zju zr5j5(UdRxQ1yuAbDdTH-tHDy`1^5gWn{+6Bgpf0I*b%m&922j?R)#cm#sh1q-(&)~ zT#B?8-TSZd^dT&%AuhrNpwN=V0^xS2_&SS`NE(+^+t3(9<|a8rWUj0KDr0ac9NpF55e?_ z(=(4x|FmjCRvcCv;xZ&JT4!S5`b;k62si?p9Z|R2No6**Rk16^ zqsGMhVX_ZlKRAO~{WHC`u-WJ-!BQE=4zLnjSwq8`EVg{HIEtezRhM#DW#-6NbLn<0 z33{-7h8YQ6Q5$G9u5MQJWuDrKQ-g9eP;np1l^Tz6`pCdK{5h$yx3pwO+$(O4B96Jn zR>J9p>9~-Vu$;KN^phzNkidvfb)3@(AH2tlDr+kc_NS>*L9e3yi0sYMKl>|wasqKpB&@RR(zhH>F0reJHgqlH(+MHAt6N9 z5&tZ|B!A(J-6towGm}p&X1U^_obitW*O+>Y746&U(Rp@5ww4?CdSicvpW<l_cCt^4p~J6NXa@g(MPG*MP>q3|>ECVp;-BxZ za{mC_mHgenuRr+or)PfuEB3`d&rNSL_0|ktWfRofKOg`6{*PKk|GdV|;g8Q{Q&30c z?~Cp8C4BN0zyA-R|M1U0?*e~{|ExQqh)&6&M|}TBp3`#w^!K&uq5od~ z?Uno8-szv8ThZ_Rx!&G)SMGN_+dmCH^6E0y;Rn8auiYPB^VF`|=WAhLwY>WLAE?~# zIJkd)LugpW2e*Z^*n6Gxl+l>7bu`AJ;&?{U>rd;SOGLVWje55>6o zs{0qXF!1-`AJR|%zgqX%r`-Q1i(2#FSLnBT|Cc`H{$KuDty%vPf3kj7@Bb>hzdC+z z8fnd+`2MT!_jcG#ey`sD^S`S#{+Sc5HRJdBXO1uaJ$}+_|5Hn!Hh*51wJIz^F1^q0 ze~F75e_w%r9sF~8^8J&;>$Hcj;qT+G(^lVO`>9{3_LbY!RrkO0tlodGazo{3_J0A- CPv#K- literal 64528 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 o_eW7y=psszop = scf_3ac_find_operator(type); - c->label = l; + c->label = label; - c->dsts = scf_vector_alloc(); + c->dsts = scf_vector_alloc(); if (!c->dsts) { scf_3ac_code_free(c); return NULL; diff --git a/js/core/scf_3ac.h b/js/core/scf_3ac.h index 947bff2..7f45cb6 100644 --- a/js/core/scf_3ac.h +++ b/js/core/scf_3ac.h @@ -32,7 +32,7 @@ struct scf_3ac_code_s { scf_vector_t* dsts; // dst operands, maybe only used for function return value scf_vector_t* srcs; // src operands, usually 2 - scf_label_t* label; // only for 'goto' to find the destination to go + scf_lex_word_t* label; // only for 'goto' to find the destination scf_3ac_code_t* origin; @@ -60,7 +60,7 @@ void scf_3ac_code_print(scf_3ac_code_t* c, scf_list_t* sentinel); void scf_3ac_list_print(scf_list_t* h); -scf_3ac_code_t* scf_3ac_jmp_code(int type, scf_label_t* l, scf_node_t* err); +scf_3ac_code_t* scf_3ac_jmp_code(int type, scf_lex_word_t* label); scf_3ac_operator_t* scf_3ac_find_operator(const int type); diff --git a/js/core/scf_ast.c b/js/core/scf_ast.c index aa22dff..daf19fd 100644 --- a/js/core/scf_ast.c +++ b/js/core/scf_ast.c @@ -158,7 +158,7 @@ static int _find_type_by_type(scf_node_t* node, void* arg, scf_vector_t* vec) scf_type_t* t = (scf_type_t*)node; - if (t->type == (intptr_t)arg) { + if (t->node.type == (intptr_t)arg) { int ret = scf_vector_add(vec, t); if (ret < 0) @@ -486,9 +486,11 @@ int scf_ast_add_const_var(scf_ast_t* ast, scf_node_t* parent, int type, const ui int scf_function_signature(scf_ast_t* ast, scf_function_t* f) { - scf_string_t* s; - scf_type_t* t = (scf_type_t*)f->node.parent; - + scf_string_t* s; + scf_type_t* t = (scf_type_t*)f->node.parent; + scf_type_t* tv; + scf_variable_t* v; + scf_operator_t* op; int ret; int i; @@ -509,8 +511,7 @@ int scf_function_signature(scf_ast_t* ast, scf_function_t* f) } if (f->op_type >= 0) { - scf_operator_t* op = scf_find_base_operator_by_type(f->op_type); - + op = scf_find_base_operator_by_type(f->op_type); if (!op->signature) goto error; @@ -532,12 +533,11 @@ int scf_function_signature(scf_ast_t* ast, scf_function_t* f) if (f->argv) { for (i = 0; i < f->argv->size; i++) { - scf_variable_t* v = f->argv->data[i]; - scf_type_t* t_v = NULL; + v = f->argv->data[i]; - t_v = scf_block_find_type_type((scf_block_t*)t, v->type); - if (!t_v) { - ret = scf_ast_find_global_type_type(&t_v, ast, v->type); + tv = scf_block_find_type_type((scf_block_t*)t, v->type); + if (!tv) { + ret = scf_ast_find_global_type_type(&tv, ast, v->type); if (ret < 0) goto error; } @@ -546,13 +546,11 @@ int scf_function_signature(scf_ast_t* ast, scf_function_t* f) if (ret < 0) goto error; - scf_logd("t_v: %p, v->type: %d, v->w->text->data: %s\n", t_v, v->type, v->w->text->data); - - const char* abbrev = scf_type_find_abbrev(t_v->name->data); + const char* abbrev = scf_type_find_abbrev(tv->name->data); if (abbrev) ret = scf_string_cat_cstr(s, abbrev); else - ret = scf_string_cat(s, t_v->name); + ret = scf_string_cat(s, tv->name); if (ret < 0) goto error; @@ -567,16 +565,15 @@ int scf_function_signature(scf_ast_t* ast, scf_function_t* f) } } - scf_logd("f signature: %s\n", s->data); - if (f->signature) scf_string_free(f->signature); + f->signature = s; return 0; error: scf_string_free(s); - return -1; + return ret; } int scf_ast_find_proper_function(scf_function_t** pf, scf_ast_t* ast, scf_vector_t* fvec, scf_vector_t* argv) @@ -584,7 +581,6 @@ int scf_ast_find_proper_function(scf_function_t** pf, scf_ast_t* ast, scf_vector scf_function_t* f; scf_variable_t* v0; scf_variable_t* v1; - int i; int j; @@ -593,9 +589,9 @@ int scf_ast_find_proper_function(scf_function_t** pf, scf_ast_t* ast, scf_vector f->score = 0; - for (j = 0; j < argv->size; j++) { - v0 = f->argv->data[j]; - v1 = argv->data[j]; + for (j = 0; j < f->argv->size; j++) { + v0 = f->argv->data[j]; + v1 = argv->data[j]; if (scf_variable_is_struct_pointer(v0)) continue; @@ -619,7 +615,7 @@ int scf_ast_find_proper_function(scf_function_t** pf, scf_ast_t* ast, scf_vector } } - if (j < argv->size) + if (j < f->argv->size) assert(0 == scf_vector_del(fvec, f)); // drop invalid function else i++; diff --git a/js/core/scf_basic_block.c b/js/core/scf_basic_block.c index 55a6426..0fc2e60 100644 --- a/js/core/scf_basic_block.c +++ b/js/core/scf_basic_block.c @@ -143,7 +143,7 @@ scf_basic_block_t* scf_basic_block_jcc(scf_basic_block_t* to, scf_function_t* f, if (!bb) return NULL; - c = scf_3ac_jmp_code(jcc, NULL, NULL); + c = scf_3ac_jmp_code(jcc, NULL); if (!c) { scf_basic_block_free(bb); return NULL; diff --git a/js/core/scf_block.h b/js/core/scf_block.h index f405d24..30d3fd0 100644 --- a/js/core/scf_block.h +++ b/js/core/scf_block.h @@ -9,6 +9,8 @@ struct scf_block_s { scf_scope_t* scope; scf_string_t* name; + + scf_lex_t* lex_list; }; @@ -29,4 +31,3 @@ scf_function_t* scf_block_find_function(scf_block_t* b, const char* name); scf_label_t* scf_block_find_label(scf_block_t* b, const char* name); #endif - diff --git a/js/core/scf_calculate.c b/js/core/scf_calculate.c index 2e429c1..6f068ad 100644 --- a/js/core/scf_calculate.c +++ b/js/core/scf_calculate.c @@ -3,6 +3,7 @@ #include"scf_calculate_i32.c" #include"scf_calculate_u32.c" #include"scf_calculate_i64.c" +#include"scf_calculate_u64.c" #include"scf_calculate_float.c" #include"scf_calculate_double.c" @@ -99,6 +100,37 @@ scf_calculate_t base_calculates[] = {"i64", SCF_OP_GE, SCF_VAR_I64, SCF_VAR_I64, SCF_VAR_I64, scf_i64_ge}, {"i64", SCF_OP_LE, SCF_VAR_I64, SCF_VAR_I64, SCF_VAR_I64, scf_i64_le}, + // u64 + {"u64", SCF_OP_ADD, SCF_VAR_U64, SCF_VAR_U64, SCF_VAR_U64, scf_u64_add}, + {"u64", SCF_OP_SUB, SCF_VAR_U64, SCF_VAR_U64, SCF_VAR_U64, scf_u64_sub}, + {"u64", SCF_OP_MUL, SCF_VAR_U64, SCF_VAR_U64, SCF_VAR_U64, scf_u64_mul}, + {"u64", SCF_OP_DIV, SCF_VAR_U64, SCF_VAR_U64, SCF_VAR_U64, scf_u64_div}, + {"u64", SCF_OP_MOD, SCF_VAR_U64, SCF_VAR_U64, SCF_VAR_U64, scf_u64_mod}, + + {"u64", SCF_OP_SHL, SCF_VAR_U64, SCF_VAR_U64, SCF_VAR_U64, scf_u64_shl}, + {"u64", SCF_OP_SHR, SCF_VAR_U64, SCF_VAR_U64, SCF_VAR_U64, scf_u64_shr}, + + {"u64", SCF_OP_INC, SCF_VAR_U64, SCF_VAR_U64, SCF_VAR_U64, scf_u64_inc}, + {"u64", SCF_OP_DEC, SCF_VAR_U64, SCF_VAR_U64, SCF_VAR_U64, scf_u64_dec}, + + {"u64", SCF_OP_NEG, SCF_VAR_U64, SCF_VAR_U64, SCF_VAR_U64, scf_u64_neg}, + + {"u64", SCF_OP_BIT_AND, SCF_VAR_U64, SCF_VAR_U64, SCF_VAR_U64, scf_u64_bit_and}, + {"u64", SCF_OP_BIT_OR, SCF_VAR_U64, SCF_VAR_U64, SCF_VAR_U64, scf_u64_bit_or}, + {"u64", SCF_OP_BIT_NOT, SCF_VAR_U64, SCF_VAR_U64, SCF_VAR_U64, scf_u64_bit_not}, + + {"u64", SCF_OP_LOGIC_AND, SCF_VAR_U64, SCF_VAR_U64, SCF_VAR_U64, scf_u64_logic_and}, + {"u64", SCF_OP_LOGIC_OR, SCF_VAR_U64, SCF_VAR_U64, SCF_VAR_U64, scf_u64_logic_or}, + {"u64", SCF_OP_LOGIC_NOT, SCF_VAR_U64, SCF_VAR_U64, SCF_VAR_U64, scf_u64_logic_not}, + + {"u64", SCF_OP_GT, SCF_VAR_U64, SCF_VAR_U64, SCF_VAR_U64, scf_u64_gt}, + {"u64", SCF_OP_LT, SCF_VAR_U64, SCF_VAR_U64, SCF_VAR_U64, scf_u64_lt}, + + {"u64", SCF_OP_EQ, SCF_VAR_U64, SCF_VAR_U64, SCF_VAR_U64, scf_u64_eq}, + {"u64", SCF_OP_NE, SCF_VAR_U64, SCF_VAR_U64, SCF_VAR_U64, scf_u64_ne}, + {"u64", SCF_OP_GE, SCF_VAR_U64, SCF_VAR_U64, SCF_VAR_U64, scf_u64_ge}, + {"u64", SCF_OP_LE, SCF_VAR_U64, SCF_VAR_U64, SCF_VAR_U64, scf_u64_le}, + {"float", SCF_OP_ADD, SCF_VAR_FLOAT, SCF_VAR_FLOAT, SCF_VAR_FLOAT, scf_float_add}, {"float", SCF_OP_SUB, SCF_VAR_FLOAT, SCF_VAR_FLOAT, SCF_VAR_FLOAT, scf_float_sub}, {"float", SCF_OP_MUL, SCF_VAR_FLOAT, SCF_VAR_FLOAT, SCF_VAR_FLOAT, scf_float_mul}, @@ -136,4 +168,3 @@ scf_calculate_t* scf_find_base_calculate(int op_type, int src0_type, int src1_ty return NULL; } - diff --git a/js/core/scf_calculate.h b/js/core/scf_calculate.h index 145e252..4d2b19a 100644 --- a/js/core/scf_calculate.h +++ b/js/core/scf_calculate.h @@ -19,4 +19,3 @@ typedef struct { scf_calculate_t* scf_find_base_calculate(int op_type, int src0_type, int src1_type); #endif - diff --git a/js/core/scf_calculate_i32.c b/js/core/scf_calculate_i32.c index 50fc79c..c01ad95 100644 --- a/js/core/scf_calculate_i32.c +++ b/js/core/scf_calculate_i32.c @@ -63,4 +63,3 @@ SCF_I32_BINARY_OP(eq, ==) SCF_I32_BINARY_OP(ne, !=) SCF_I32_BINARY_OP(ge, >=) SCF_I32_BINARY_OP(le, <=) - diff --git a/js/core/scf_calculate_i64.c b/js/core/scf_calculate_i64.c index 06aa716..ed2eee9 100644 --- a/js/core/scf_calculate_i64.c +++ b/js/core/scf_calculate_i64.c @@ -63,4 +63,3 @@ SCF_I64_BINARY_OP(eq, ==) SCF_I64_BINARY_OP(ne, !=) SCF_I64_BINARY_OP(ge, >=) SCF_I64_BINARY_OP(le, <=) - diff --git a/js/core/scf_calculate_u32.c b/js/core/scf_calculate_u32.c index 7ecb10f..fa982d2 100644 --- a/js/core/scf_calculate_u32.c +++ b/js/core/scf_calculate_u32.c @@ -63,4 +63,3 @@ SCF_U32_BINARY_OP(eq, ==) SCF_U32_BINARY_OP(ne, !=) SCF_U32_BINARY_OP(ge, >=) SCF_U32_BINARY_OP(le, <=) - diff --git a/js/core/scf_calculate_u64.c b/js/core/scf_calculate_u64.c new file mode 100644 index 0000000..36aaebd --- /dev/null +++ b/js/core/scf_calculate_u64.c @@ -0,0 +1,65 @@ +#include"scf_calculate.h" + +#define SCF_U64_BINARY_OP(name, op) \ +int scf_u64_##name(scf_ast_t* ast, scf_variable_t** pret, scf_variable_t* src0, scf_variable_t* src1) \ +{ \ + scf_type_t* t = scf_block_find_type_type(ast->current_block, SCF_VAR_U64); \ + scf_variable_t* r = SCF_VAR_ALLOC_BY_TYPE(NULL, t, 0, 0, NULL); \ + if (!r) \ + return -ENOMEM; \ + r->data.u64 = src0->data.u64 op src1->data.u64; \ + if (pret) \ + *pret = r; \ + return 0; \ +} + +#define SCF_U64_UNARY_OP(name, op) \ +int scf_u64_##name(scf_ast_t* ast, scf_variable_t** pret, scf_variable_t* src0, scf_variable_t* src1) \ +{ \ + scf_type_t* t = scf_block_find_type_type(ast->current_block, SCF_VAR_U64); \ + scf_variable_t* r = SCF_VAR_ALLOC_BY_TYPE(NULL, t, 0, 0, NULL); \ + if (!r) \ + return -ENOMEM; \ + r->data.u64 = op src0->data.u64; \ + if (pret) \ + *pret = r; \ + return 0; \ +} + +#define SCF_U64_UPDATE_OP(name, op) \ +int scf_u64_##name(scf_ast_t* ast, scf_variable_t** pret, scf_variable_t* src0, scf_variable_t* src1) \ +{ \ + op src0->data.u64; \ + if (pret) \ + *pret = scf_variable_ref(src0); \ + return 0; \ +} + +SCF_U64_BINARY_OP(add, +) +SCF_U64_BINARY_OP(sub, -) +SCF_U64_BINARY_OP(mul, *) +SCF_U64_BINARY_OP(div, /) +SCF_U64_BINARY_OP(mod, %) + +SCF_U64_BINARY_OP(shl, <<) +SCF_U64_BINARY_OP(shr, >>) + +SCF_U64_UPDATE_OP(inc, ++); +SCF_U64_UPDATE_OP(dec, --); + +SCF_U64_UNARY_OP(neg, -) + +SCF_U64_BINARY_OP(bit_and, &) +SCF_U64_BINARY_OP(bit_or, |) +SCF_U64_UNARY_OP(bit_not, ~) + +SCF_U64_BINARY_OP(logic_and, &&) +SCF_U64_BINARY_OP(logic_or, ||) +SCF_U64_UNARY_OP(logic_not, !) + +SCF_U64_BINARY_OP(gt, >) +SCF_U64_BINARY_OP(lt, <) +SCF_U64_BINARY_OP(eq, ==) +SCF_U64_BINARY_OP(ne, !=) +SCF_U64_BINARY_OP(ge, >=) +SCF_U64_BINARY_OP(le, <=) diff --git a/js/core/scf_expr.c b/js/core/scf_expr.c index 8a8b081..bb7b5da 100644 --- a/js/core/scf_expr.c +++ b/js/core/scf_expr.c @@ -156,7 +156,8 @@ void scf_expr_simplify(scf_expr_t** pe) e = *pp; *pp = NULL; - e->parent = (*pe)->parent; + e->parent = (*pe)->parent; + e->_3ac_done = (*pe)->_3ac_done; scf_expr_free(*pe); *pe = e; diff --git a/js/core/scf_function.c b/js/core/scf_function.c index a8d5e31..de7c2fe 100644 --- a/js/core/scf_function.c +++ b/js/core/scf_function.c @@ -173,19 +173,24 @@ int scf_function_same_argv(scf_vector_t* argv0, scf_vector_t* argv1) return 1; } -int scf_function_like_argv(scf_vector_t* argv0, scf_vector_t* argv1) +int scf_function_like_argv(scf_function_t* f, scf_vector_t* argv) { - if (argv0) { - if (!argv1) + if (f->argv) { + if (!argv) return 0; - if (argv0->size != argv1->size) + if (f->argv->size > argv->size) + return 0; + else if (f->argv->size < argv->size && !f->vargs_flag) return 0; + scf_variable_t* v0; + scf_variable_t* v1; int i; - for (i = 0; i < argv0->size; i++) { - scf_variable_t* v0 = argv0->data[i]; - scf_variable_t* v1 = argv1->data[i]; + + for (i = 0; i < f->argv->size; i++) { + v0 = f->argv->data[i]; + v1 = argv->data[i]; if (scf_variable_type_like(v0, v1)) continue; @@ -194,7 +199,7 @@ int scf_function_like_argv(scf_vector_t* argv0, scf_vector_t* argv1) return 0; } } else { - if (argv1) + if (argv) return 0; } diff --git a/js/core/scf_function.h b/js/core/scf_function.h index 9b0afd4..d423198 100644 --- a/js/core/scf_function.h +++ b/js/core/scf_function.h @@ -72,11 +72,11 @@ struct scf_function_s { }; scf_function_t* scf_function_alloc(scf_lex_word_t* w); -void scf_function_free(scf_function_t* f); +void scf_function_free (scf_function_t* f); -int scf_function_same(scf_function_t* f0, scf_function_t* f1); -int scf_function_same_type(scf_function_t* f0, scf_function_t* f1); +int scf_function_same (scf_function_t* f0, scf_function_t* f1); +int scf_function_same_type(scf_function_t* f0, scf_function_t* f1); +int scf_function_like_argv(scf_function_t* f, scf_vector_t* argv); int scf_function_same_argv(scf_vector_t* argv0, scf_vector_t* argv1); -int scf_function_like_argv(scf_vector_t* argv0, scf_vector_t* argv1); #endif diff --git a/js/core/scf_label.c b/js/core/scf_label.c index 63bdb9e..7bb478b 100644 --- a/js/core/scf_label.c +++ b/js/core/scf_label.c @@ -12,7 +12,6 @@ scf_label_t* scf_label_alloc(scf_lex_word_t* w) return NULL; } - l->refs = 1; l->type = SCF_LABEL; return l; } @@ -20,9 +19,6 @@ scf_label_t* scf_label_alloc(scf_lex_word_t* w) void scf_label_free(scf_label_t* l) { if (l) { - if (--l->refs > 0) - return; - if (l->w) { scf_lex_word_free(l->w); l->w = NULL; diff --git a/js/core/scf_node.c b/js/core/scf_node.c index 89d68ad..4027d40 100644 --- a/js/core/scf_node.c +++ b/js/core/scf_node.c @@ -2,6 +2,9 @@ scf_variable_t* _scf_operand_get(const scf_node_t* node) { + while (SCF_OP_EXPR == node->type && node->nb_nodes > 0) + node = node->nodes[0]; + if (scf_type_is_var(node->type)) return node->var; else if (scf_type_is_operator(node->type)) @@ -76,9 +79,7 @@ scf_node_t* scf_node_clone(scf_node_t* node) if (!dst->var) goto failed; - } else if (SCF_LABEL == node->type) - dst->label = node->label; - else { + } else { if (node->w) { dst->w = scf_lex_word_clone(node->w); if (!dst->w) @@ -110,19 +111,6 @@ failed: return NULL; } -scf_node_t* scf_node_alloc_label(scf_label_t* l) -{ - scf_node_t* node = calloc(1, sizeof(scf_node_t)); - if (!node) { - scf_loge("node alloc failed\n"); - return NULL; - } - - node->type = SCF_LABEL; - node->label = l; - return node; -} - int scf_node_add_child(scf_node_t* parent, scf_node_t* child) { if (!parent) @@ -168,11 +156,6 @@ void scf_node_free_data(scf_node_t* node) scf_variable_free(node->var); node->var = NULL; } - } else if (SCF_LABEL == node->type) { - if (node->label) { - scf_label_free(node->label); - node->label = NULL; - } } else { if (node->w) { scf_lex_word_free(node->w); @@ -277,11 +260,7 @@ void scf_node_print(scf_node_t* node) if (node) { scf_logw("node: %p, type: %d", node, node->type); - if (SCF_LABEL == node->type) { - if (node->label && node->label->w) - printf(", w: %s, line: %d", node->label->w->text->data, node->label->w->line); - - } else if (scf_type_is_var(node->type)) { + if (scf_type_is_var(node->type)) { if (node->var && node->var->w) printf(", w: %s, line: %d", node->var->w->text->data, node->var->w->line); diff --git a/js/core/scf_node.h b/js/core/scf_node.h index 946298c..b6f23c0 100644 --- a/js/core/scf_node.h +++ b/js/core/scf_node.h @@ -22,9 +22,8 @@ struct scf_node_s { scf_expr_t* js_new; // the expr which created this node, only for js! union { - scf_variable_t* var; - scf_lex_word_t* w; - scf_label_t* label; + scf_variable_t* var; + scf_lex_word_t* w; }; scf_lex_word_t* debug_w; @@ -52,30 +51,26 @@ struct scf_node_s { uint32_t semi_flag :1; // set when followed by a ';' }; -struct scf_label_s { +struct scf_label_s +{ scf_list_t list; // for variable scope - int refs; // reference count - int type; - scf_lex_word_t* w; scf_node_t* node; // the labeled node }; scf_node_t* scf_node_alloc(scf_lex_word_t* w, int type, scf_variable_t* var); -scf_node_t* scf_node_alloc_label(scf_label_t* l); - -scf_node_t* scf_node_clone(scf_node_t* node); int scf_node_add_child(scf_node_t* parent, scf_node_t* child); void scf_node_del_child(scf_node_t* parent, scf_node_t* child); -void scf_node_free(scf_node_t* node); +void scf_node_free (scf_node_t* node); void scf_node_free_data(scf_node_t* node); void scf_node_move_data(scf_node_t* dst, scf_node_t* src); +scf_node_t* scf_node_clone(scf_node_t* node); void scf_node_print(scf_node_t* node); scf_variable_t* _scf_operand_get(const scf_node_t* node); diff --git a/js/core/scf_operator_handler_3ac.c b/js/core/scf_operator_handler_3ac.c index 02b34ad..5bbf410 100644 --- a/js/core/scf_operator_handler_3ac.c +++ b/js/core/scf_operator_handler_3ac.c @@ -413,7 +413,6 @@ static int _scf_op_block(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, void* // for goto if (SCF_LABEL == node->type) { - scf_label_t* l = node->label; scf_list_t* tail = scf_list_tail(d->_3ac_list_head); scf_3ac_code_t* end = scf_list_data(tail, scf_3ac_code_t, list); scf_3ac_code_t* c; @@ -423,7 +422,7 @@ static int _scf_op_block(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, void* scf_loge("\n"); return -1; } - end->label = l; + end->label = node->w; int j; for (j = 0; j < d->branch_ops->_gotos->size; j++) { @@ -432,10 +431,7 @@ static int _scf_op_block(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, void* if (!c) continue; - assert(l->w); - assert(c->label->w); - - if (!strcmp(l->w->text->data, c->label->w->text->data)) { + if (!strcmp(node->w->text->data, c->label->text->data)) { dst = c->dsts->data[0]; dst->code = end; } @@ -486,7 +482,7 @@ static int _scf_op_return(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, void return -1; } - scf_3ac_code_t* end = scf_3ac_jmp_code(SCF_OP_GOTO, NULL, NULL); + scf_3ac_code_t* end = scf_3ac_jmp_code(SCF_OP_GOTO, NULL); scf_list_add_tail(d->_3ac_list_head, &end->list); @@ -510,7 +506,7 @@ static int _scf_op_break(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, void* return -1; } - scf_3ac_code_t* jmp = scf_3ac_jmp_code(SCF_OP_GOTO, NULL, NULL); + scf_3ac_code_t* jmp = scf_3ac_jmp_code(SCF_OP_GOTO, NULL); scf_list_add_tail(d->_3ac_list_head, &jmp->list); @@ -534,7 +530,7 @@ static int _scf_op_continue(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, vo return -1; } - scf_3ac_code_t* jmp = scf_3ac_jmp_code(SCF_OP_GOTO, NULL, NULL); + scf_3ac_code_t* jmp = scf_3ac_jmp_code(SCF_OP_GOTO, NULL); scf_list_add_tail(d->_3ac_list_head, &jmp->list); @@ -553,14 +549,12 @@ static int _scf_op_goto(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, void* scf_handler_data_t* d = data; scf_node_t* nl = nodes[0]; - scf_label_t* l = nl->label; assert(SCF_LABEL == nl->type); - assert(l->w); scf_3ac_operand_t* dst; scf_3ac_code_t* c; - scf_3ac_code_t* jmp = scf_3ac_jmp_code(SCF_OP_GOTO, l, NULL); + scf_3ac_code_t* jmp = scf_3ac_jmp_code(SCF_OP_GOTO, nl->w); scf_list_add_tail(d->_3ac_list_head, &jmp->list); @@ -568,7 +562,7 @@ static int _scf_op_goto(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, void* for (i = 0; i < d->branch_ops->_labels->size; i++) { c = d->branch_ops->_labels->data[i]; - if (!strcmp(l->w->text->data, c->label->w->text->data)) { + if (!strcmp(nl->w->text->data, c->label->text->data)) { dst = jmp->dsts->data[0]; dst->code = c; break; @@ -734,7 +728,7 @@ static int _scf_op_if(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, void* da } scf_3ac_operand_t* dst; - scf_3ac_code_t* jmp_else = scf_3ac_jmp_code(jmp_op, NULL, NULL); + scf_3ac_code_t* jmp_else = scf_3ac_jmp_code(jmp_op, NULL); scf_3ac_code_t* jmp_endif = NULL; scf_list_t* l; @@ -751,7 +745,7 @@ static int _scf_op_if(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, void* da if (1 == i) { if (3 == nb_nodes) { - jmp_endif = scf_3ac_jmp_code(SCF_OP_GOTO, NULL, NULL); + jmp_endif = scf_3ac_jmp_code(SCF_OP_GOTO, NULL); scf_list_add_tail(d->_3ac_list_head, &jmp_endif->list); } @@ -870,7 +864,7 @@ static int _scf_op_end_loop(scf_list_t* start_prev, scf_list_t* continue_prev, s }; // add loop when true - scf_3ac_code_t* loop = scf_3ac_jmp_code(jmp_op, NULL, NULL); + scf_3ac_code_t* loop = scf_3ac_jmp_code(jmp_op, NULL); scf_list_add_tail(d->_3ac_list_head, &loop->list); // should get the real start here, @@ -977,7 +971,7 @@ static int _scf_op_do(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, void* da scf_list_t* l; scf_3ac_code_t* c; - scf_3ac_code_t* jmp_end = scf_3ac_jmp_code(jmp_op, NULL, NULL); + scf_3ac_code_t* jmp_end = scf_3ac_jmp_code(jmp_op, NULL); scf_list_add_tail(d->_3ac_list_head, &jmp_end->list); @@ -1037,7 +1031,7 @@ static int _scf_op_while(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, void* return -1; } - scf_3ac_code_t* jmp_end = scf_3ac_jmp_code(jmp_op, NULL, NULL); + scf_3ac_code_t* jmp_end = scf_3ac_jmp_code(jmp_op, NULL); scf_list_add_tail(d->_3ac_list_head, &jmp_end->list); scf_branch_ops_t* local_branch_ops = scf_branch_ops_alloc(); @@ -1102,7 +1096,7 @@ static int _scf_op_vla_alloc(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, v if (!cmp) return -ENOMEM; - jgt = scf_3ac_jmp_code(SCF_OP_3AC_JGT, NULL, NULL); + jgt = scf_3ac_jmp_code(SCF_OP_3AC_JGT, NULL); if (!jgt) { scf_3ac_code_free(cmp); return -ENOMEM; @@ -1181,7 +1175,7 @@ static int _scf_op_switch(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, void if (SCF_OP_CASE == child->type || SCF_OP_DEFAULT == child->type) { if (jnot) { - jnext = scf_3ac_jmp_code(SCF_OP_GOTO, NULL, NULL); + jnext = scf_3ac_jmp_code(SCF_OP_GOTO, NULL); scf_list_add_tail(d->_3ac_list_head, &jnext->list); scf_vector_add(up_branch_ops->_breaks, jnext); @@ -1218,12 +1212,12 @@ static int _scf_op_switch(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, void scf_function_t* f = v->func_ptr; if (SCF_OP_EQ == f->op_type) - jnot = scf_3ac_jmp_code(SCF_OP_3AC_JZ, NULL, NULL); + jnot = scf_3ac_jmp_code(SCF_OP_3AC_JZ, NULL); else - jnot = scf_3ac_jmp_code(SCF_OP_3AC_JNZ, NULL, NULL); + jnot = scf_3ac_jmp_code(SCF_OP_3AC_JNZ, NULL); } else { cmp = scf_3ac_code_NN (SCF_OP_3AC_CMP, NULL, 0, srcs, 2); - jnot = scf_3ac_jmp_code(SCF_OP_3AC_JNZ, NULL, NULL); + jnot = scf_3ac_jmp_code(SCF_OP_3AC_JNZ, NULL); } scf_list_add_tail(d->_3ac_list_head, &cmp->list); @@ -1311,7 +1305,7 @@ static int _scf_op_for(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, void* d return -1; } - jmp_end = scf_3ac_jmp_code(jmp_op, NULL, NULL); + jmp_end = scf_3ac_jmp_code(jmp_op, NULL); scf_list_add_tail(d->_3ac_list_head, &jmp_end->list); } } @@ -1504,7 +1498,7 @@ static int _scf_op_new(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, void* d return ret; } - jz = scf_3ac_jmp_code(SCF_OP_3AC_JZ, NULL, NULL); + jz = scf_3ac_jmp_code(SCF_OP_3AC_JZ, NULL); scf_list_add_tail(d->_3ac_list_head, &jz->list); for (i = 3; i < nb_nodes; i++) { @@ -1528,7 +1522,7 @@ static int _scf_op_new(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, void* d return ret; } - jmp = scf_3ac_jmp_code(SCF_OP_GOTO, NULL, NULL); + jmp = scf_3ac_jmp_code(SCF_OP_GOTO, NULL); scf_list_add_tail(d->_3ac_list_head, &jmp->list); scf_vector_add(d->branch_ops->_breaks, jz); @@ -2373,7 +2367,7 @@ static int _scf_op_logic_##name(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes if (jmp_op < 0) \ return -1; \ \ - scf_3ac_code_t* jmp = scf_3ac_jmp_code(jmp_op, NULL, NULL); \ + scf_3ac_code_t* jmp = scf_3ac_jmp_code(jmp_op, NULL); \ if (!jmp) \ return -ENOMEM; \ \ diff --git a/js/core/scf_optimizer_inline.c b/js/core/scf_optimizer_inline.c index 6900ea9..32fbb9e 100644 --- a/js/core/scf_optimizer_inline.c +++ b/js/core/scf_optimizer_inline.c @@ -186,25 +186,6 @@ static int _copy_codes(scf_list_t* hbb, scf_vector_t* argv, scf_3ac_code_t* c, s return 0; } -static int _find_local_vars(scf_node_t* node, void* arg, scf_vector_t* results) -{ - scf_block_t* b = (scf_block_t*)node; - - if ((SCF_OP_BLOCK == b->node.type || SCF_FUNCTION == b->node.type) && b->scope) { - - int i; - for (i = 0; i < b->scope->vars->size; i++) { - - scf_variable_t* var = b->scope->vars->data[i]; - - int ret = scf_vector_add(results, var); - if (ret < 0) - return ret; - } - } - return 0; -} - static int _do_inline(scf_ast_t* ast, scf_3ac_code_t* c, scf_basic_block_t** pbb, scf_function_t* f, scf_function_t* f2) { scf_basic_block_t* bb = *pbb; @@ -254,7 +235,7 @@ static int _do_inline(scf_ast_t* ast, scf_3ac_code_t* c, scf_basic_block_t** pbb scf_vector_clear(argv, NULL); - int ret = scf_node_search_bfs((scf_node_t*)f2, NULL, argv, -1, _find_local_vars); + int ret = scf_node_search_bfs((scf_node_t*)f2, NULL, argv, -1, __find_local_vars); if (ret < 0) { scf_vector_free(argv); return -ENOMEM; diff --git a/js/core/scf_optimizer_js_array.c b/js/core/scf_optimizer_js_array.c index 2799637..f39e0a5 100644 --- a/js/core/scf_optimizer_js_array.c +++ b/js/core/scf_optimizer_js_array.c @@ -11,7 +11,7 @@ static int __js_array_realloc(scf_ast_t* ast, scf_3ac_code_t** pc, scf_node_t* a int ret; - if (v->type == Object->type) + if (v->type == Object->node.type) ret = scf_ast_find_global_function(&f, ast, "Object_array_realloc_obj"); else ret = scf_ast_find_global_function(&f, ast, "Object_array_realloc"); @@ -116,7 +116,7 @@ static int _optimize_js_array_bb(scf_ast_t* ast, scf_function_t* f, scf_basic_bl v = _scf_operand_get(array); - if (v->type != Object->type) + if (v->type != Object->node.type) continue; c2 = NULL; diff --git a/js/core/scf_optimizer_js_array2.c b/js/core/scf_optimizer_js_array2.c index 007b09b..b78138b 100644 --- a/js/core/scf_optimizer_js_array2.c +++ b/js/core/scf_optimizer_js_array2.c @@ -1,20 +1,22 @@ #include"scf_optimizer.h" #include"scf_pointer_alias.h" -static int __js_array_index(scf_ast_t* ast, scf_3ac_code_t* c, scf_dag_node_t* index, scf_type_t* Object) +static int __js_array_index(scf_ast_t* ast, scf_3ac_code_t* c, scf_dag_node_t* array, scf_dag_node_t* index, scf_type_t* Object) { - scf_3ac_operand_t* pf; - scf_variable_t* v; - scf_dag_node_t* dn; - scf_function_t* f = NULL; - scf_type_t* t = NULL; + scf_3ac_operand_t* pf; + scf_3ac_operand_t* src; + scf_3ac_operand_t* dst; + scf_variable_t* v; + scf_dag_node_t* dn; + scf_function_t* f = NULL; + scf_type_t* t = NULL; int ret; if (SCF_OP_3AC_ASSIGN_ARRAY_INDEX == c->op->type) ret = scf_ast_find_global_function(&f, ast, "Object_assign_array_index_obj"); else { - if (index->var->type == Object->type) + if (index->var->type == Object->node.type) ret = scf_ast_find_global_function(&f, ast, "Object_array_index_obj"); else if (index->var->type == SCF_VAR_DOUBLE) @@ -40,12 +42,17 @@ static int __js_array_index(scf_ast_t* ast, scf_3ac_code_t* c, scf_dag_node_t* i if (!dn) return -ENOMEM; - pf = c->srcs->data[2]; + // 2nd src operand is 'scale size' of array index (no-use after here), change it to 'const function pointer'. + pf = c->srcs->data[2]; + dst = c->dsts->data[0]; if (pf->node) scf_node_free(pf->node); if (pf->dag_node) { + scf_vector_del(dst->dag_node->childs, pf->dag_node); + scf_vector_del(pf ->dag_node->parents, dst->dag_node); + scf_list_del(&pf->dag_node->list); scf_dag_node_free(pf->dag_node); } @@ -56,11 +63,20 @@ static int __js_array_index(scf_ast_t* ast, scf_3ac_code_t* c, scf_dag_node_t* i SCF_XCHG(c->srcs->data[2], c->srcs->data[1]); SCF_XCHG(c->srcs->data[1], c->srcs->data[0]); + src = c->srcs->data[1]; + + scf_vector_del(dst->dag_node->childs, src->dag_node); + scf_vector_del(src->dag_node->parents, dst->dag_node); + assert (src->dag_node != array); + + src->dag_node = array; + src->node = array->node; + c->op = scf_3ac_find_operator(SCF_OP_CALL); return 0; } -static scf_3ac_code_t* __js_array_find_3ac(scf_dag_node_t* member, scf_3ac_code_t* c, scf_basic_block_t* cur_bb, scf_basic_block_t* bb, scf_list_t* l, scf_list_t* bb_list_head) +static scf_3ac_code_t* __js_array_find_pointer(scf_dag_node_t* members, scf_3ac_code_t* c, scf_basic_block_t* cur_bb, scf_basic_block_t* bb, scf_list_t* l, scf_list_t* bb_list_head) { scf_basic_block_t* bb2; scf_3ac_operand_t* dst; @@ -74,7 +90,7 @@ static scf_3ac_code_t* __js_array_find_3ac(scf_dag_node_t* member, scf_3ac_code_ if (SCF_OP_POINTER == c2->op->type) { dst = c2->dsts->data[0]; - if (dst->dag_node == member) + if (dst->dag_node == members) return c2; } } @@ -96,7 +112,7 @@ static scf_3ac_code_t* __js_array_find_3ac(scf_dag_node_t* member, scf_3ac_code_ if (SCF_OP_POINTER == c2->op->type) { dst = c2->dsts->data[0]; - if (dst->dag_node == member) + if (dst->dag_node == members) return c2; } } @@ -116,7 +132,7 @@ static int _optimize_js_array2_bb(scf_ast_t* ast, scf_function_t* f, scf_basic_b scf_3ac_code_t* c; scf_3ac_code_t* c2; scf_dag_node_t* array; - scf_dag_node_t* member; + scf_dag_node_t* members; scf_type_t* Object = NULL; scf_list_t* l; scf_list_t* l2; @@ -140,41 +156,40 @@ static int _optimize_js_array2_bb(scf_ast_t* ast, scf_function_t* f, scf_basic_b if (SCF_OP_ARRAY_INDEX != c->op->type && SCF_OP_3AC_ASSIGN_ARRAY_INDEX != c->op->type) continue; - base = c->srcs->data[0]; - index = c->srcs->data[1]; - member = base->dag_node; + base = c->srcs->data[0]; + index = c->srcs->data[1]; + members = base->dag_node; - array = member; + array = members; while (SCF_OP_EXPR == array->type || SCF_OP_POINTER == array->type) array = array->childs->data[0]; - if (array->var->type != Object->type) + if (array->var->type != Object->node.type) continue; - if (SCF_OP_3AC_ASSIGN_ARRAY_INDEX == c->op->type && index->dag_node->var->type != Object->type) + if (SCF_OP_3AC_ASSIGN_ARRAY_INDEX == c->op->type && index->dag_node->var->type != Object->node.type) continue; int op_type = c->op->type; - ret = __js_array_index(ast, c, index->dag_node, Object); + ret = __js_array_index(ast, c, array, index->dag_node, Object); if (ret < 0) return ret; - scf_vector_del(c->basic_block->dn_reloads, member); - - base = c->srcs->data[1]; - base->dag_node = array; - base->node = array->node; + scf_vector_del(c->basic_block->dn_reloads, members); #if 1 - c2 = __js_array_find_3ac(member, c, cur_bb, bb, l, bb_list_head); + c2 = __js_array_find_pointer(members, c, cur_bb, bb, l, bb_list_head); assert(c2); - scf_vector_del(c2->basic_block->dn_resaves, member); - scf_vector_del(c2->basic_block->exit_dn_actives, member); + if (!members->parents || members->parents->size <= 0) { - scf_list_del(&c2->list); - scf_3ac_code_free(c2); - c2 = NULL; + scf_vector_del(c2->basic_block->dn_resaves, members); + scf_vector_del(c2->basic_block->exit_dn_actives, members); + + scf_list_del(&c2->list); + scf_3ac_code_free(c2); + c2 = NULL; + } #endif if (scf_list_prev(&c->list) != scf_list_sentinel(&cur_bb->code_list_head)) { diff --git a/js/core/scf_optimizer_js_teq.c b/js/core/scf_optimizer_js_teq.c index 2d64d15..c48e2a5 100644 --- a/js/core/scf_optimizer_js_teq.c +++ b/js/core/scf_optimizer_js_teq.c @@ -90,7 +90,7 @@ static int _optimize_js_teq_bb(scf_ast_t* ast, scf_function_t* f, scf_basic_bloc v = _scf_operand_get(node); - if (v->type != Object->type) + if (v->type != Object->node.type) continue; if (SCF_OP_CALL == node->type) { diff --git a/js/core/scf_optimizer_js_unary_op.c b/js/core/scf_optimizer_js_unary_op.c index baad749..86ec2ad 100644 --- a/js/core/scf_optimizer_js_unary_op.c +++ b/js/core/scf_optimizer_js_unary_op.c @@ -168,7 +168,7 @@ static int _optimize_js_unary_op_bb(scf_ast_t* ast, scf_function_t* f, scf_basic v = _scf_operand_get(node); - if (v->type != Object->type) + if (v->type != Object->node.type) continue; ret = __js_unary_op(ast, c, node, Object); @@ -182,7 +182,7 @@ static int _optimize_js_unary_op_bb(scf_ast_t* ast, scf_function_t* f, scf_basic v = _scf_operand_get(node); - if (v->type != Object->type) + if (v->type != Object->node.type) continue; switch (dst->node->type) { diff --git a/js/core/scf_scope.c b/js/core/scf_scope.c index 424fb0f..7bc08ba 100644 --- a/js/core/scf_scope.c +++ b/js/core/scf_scope.c @@ -1,48 +1,27 @@ #include"scf_ast.h" -scf_scope_t* scf_scope_alloc(scf_lex_word_t* w, const char* name) +scf_scope_t* scf_scope_alloc() { scf_scope_t* scope = calloc(1, sizeof(scf_scope_t)); if (!scope) return NULL; - scope->name = scf_string_cstr(name); - if (!scope->name) { - free(scope); - return NULL; - } - scope->vars = scf_vector_alloc(); if (!scope->vars) { - scf_string_free(scope->name); free(scope); return NULL; } - if (w) { - scope->w = scf_lex_word_clone(w); - - if (!scope->w) { - scf_vector_free(scope->vars); - scf_string_free(scope->name); - free(scope); - return NULL; - } - } - scf_list_init(&scope->list); - scf_list_init(&scope->type_list_head); - scf_list_init(&scope->operator_list_head); - scf_list_init(&scope->function_list_head); - scf_list_init(&scope->label_list_head); + scf_list_init(&scope->types); + scf_list_init(&scope->operators); + scf_list_init(&scope->functions); + scf_list_init(&scope->labels); return scope; } void scf_scope_push_var(scf_scope_t* scope, scf_variable_t* var) { - assert(scope); - assert(var); - var->js_index = scope->vars->size; scf_vector_add(scope->vars, var); @@ -50,47 +29,32 @@ void scf_scope_push_var(scf_scope_t* scope, scf_variable_t* var) void scf_scope_push_type(scf_scope_t* scope, scf_type_t* t) { - assert(scope); - assert(t); - scf_list_add_front(&scope->type_list_head, &t->list); + scf_list_add_front(&scope->types, &t->list); } void scf_scope_push_operator(scf_scope_t* scope, scf_function_t* op) { - assert(scope); - assert(op); - scf_list_add_front(&scope->operator_list_head, &op->list); + scf_list_add_front(&scope->operators, &op->list); } void scf_scope_push_function(scf_scope_t* scope, scf_function_t* f) { - assert(scope); - assert(f); - scf_list_add_front(&scope->function_list_head, &f->list); + scf_list_add_front(&scope->functions, &f->list); } void scf_scope_push_label(scf_scope_t* scope, scf_label_t* l) { - assert(scope); - assert(l); - scf_list_add_front(&scope->label_list_head, &l->list); + scf_list_add_front(&scope->labels, &l->list); } void scf_scope_free(scf_scope_t* scope) { if (scope) { - scf_string_free(scope->name); - scope->name = NULL; - - if (scope->w) - scf_lex_word_free(scope->w); - scf_vector_clear(scope->vars, (void (*)(void*))scf_variable_free); scf_vector_free(scope->vars); scope->vars = NULL; - scf_list_clear(&scope->type_list_head, scf_type_t, list, scf_type_free); - scf_list_clear(&scope->function_list_head, scf_function_t, list, scf_function_free); + scf_list_clear(&scope->labels, scf_label_t, list, scf_label_free); free(scope); } @@ -101,7 +65,7 @@ scf_type_t* scf_scope_find_type(scf_scope_t* scope, const char* name) scf_type_t* t; scf_list_t* l; - for (l = scf_list_head(&scope->type_list_head); l != scf_list_sentinel(&scope->type_list_head); l = scf_list_next(l)) { + for (l = scf_list_head(&scope->types); l != scf_list_sentinel(&scope->types); l = scf_list_next(l)) { t = scf_list_data(l, scf_type_t, list); if (!strcmp(name, t->name->data)) { @@ -116,10 +80,10 @@ scf_type_t* scf_scope_find_type_type(scf_scope_t* scope, const int type) scf_type_t* t; scf_list_t* l; - for (l = scf_list_head(&scope->type_list_head); l != scf_list_sentinel(&scope->type_list_head); l = scf_list_next(l)) { + for (l = scf_list_head(&scope->types); l != scf_list_sentinel(&scope->types); l = scf_list_next(l)) { t = scf_list_data(l, scf_type_t, list); - if (type == t->type) + if (type == t->node.type) return t; } return NULL; @@ -144,7 +108,7 @@ scf_label_t* scf_scope_find_label(scf_scope_t* scope, const char* name) scf_label_t* label; scf_list_t* l; - for (l = scf_list_head(&scope->label_list_head); l != scf_list_sentinel(&scope->label_list_head); l = scf_list_next(l)) { + for (l = scf_list_head(&scope->labels); l != scf_list_sentinel(&scope->labels); l = scf_list_next(l)) { label = scf_list_data(l, scf_label_t, list); if (!strcmp(name, label->w->text->data)) @@ -158,7 +122,7 @@ scf_function_t* scf_scope_find_function(scf_scope_t* scope, const char* name) scf_function_t* f; scf_list_t* l; - for (l = scf_list_head(&scope->function_list_head); l != scf_list_sentinel(&scope->function_list_head); l = scf_list_next(l)) { + for (l = scf_list_head(&scope->functions); l != scf_list_sentinel(&scope->functions); l = scf_list_next(l)) { f = scf_list_data(l, scf_function_t, list); if (!strcmp(name, f->node.w->text->data)) @@ -172,7 +136,7 @@ scf_function_t* scf_scope_find_same_function(scf_scope_t* scope, scf_function_t* scf_function_t* f1; scf_list_t* l; - for (l = scf_list_head(&scope->function_list_head); l != scf_list_sentinel(&scope->function_list_head); l = scf_list_next(l)) { + for (l = scf_list_head(&scope->functions); l != scf_list_sentinel(&scope->functions); l = scf_list_next(l)) { f1 = scf_list_data(l, scf_function_t, list); if (scf_function_same(f0, f1)) @@ -191,13 +155,13 @@ int scf_scope_find_like_functions(scf_vector_t** pfunctions, scf_scope_t* scope, if (!vec) return -ENOMEM; - for (l = scf_list_head(&scope->function_list_head); l != scf_list_sentinel(&scope->function_list_head); l = scf_list_next(l)) { + for (l = scf_list_head(&scope->functions); l != scf_list_sentinel(&scope->functions); l = scf_list_next(l)) { f = scf_list_data(l, scf_function_t, list); if (strcmp(f->node.w->text->data, name)) continue; - if (!scf_function_like_argv(f->argv, argv)) + if (!scf_function_like_argv(f, argv)) continue; int ret = scf_vector_add(vec, f); @@ -226,13 +190,13 @@ int scf_scope_find_overloaded_functions(scf_vector_t** pfunctions, scf_scope_t* if (!vec) return -ENOMEM; - for (l = scf_list_head(&scope->operator_list_head); l != scf_list_sentinel(&scope->operator_list_head); l = scf_list_next(l)) { + for (l = scf_list_head(&scope->operators); l != scf_list_sentinel(&scope->operators); l = scf_list_next(l)) { f = scf_list_data(l, scf_function_t, list); if (op_type != f->op_type) continue; - if (!scf_function_like_argv(f->argv, argv)) + if (!scf_function_like_argv(f, argv)) continue; int ret = scf_vector_add(vec, f); diff --git a/js/core/scf_scope.h b/js/core/scf_scope.h index 53ef96a..ac823f1 100644 --- a/js/core/scf_scope.h +++ b/js/core/scf_scope.h @@ -6,37 +6,30 @@ #include"scf_lex_word.h" #include"scf_core_types.h" -struct scf_scope_s { - scf_list_t list; // scope list - scf_string_t* name; // scope name - - scf_lex_word_t* w; // scope name - - scf_vector_t* vars; // vars in this scope, should not have the same name - scf_list_t type_list_head; // type list in this scope, not define the same type - scf_list_t operator_list_head; // operator list in this scope - scf_list_t function_list_head; // function list in this scope - scf_list_t label_list_head; // label list in this scope +struct scf_scope_s +{ + scf_list_t list; // scope list + + scf_vector_t* vars; // vars in this scope, should not have the same name + scf_list_t types; // type list in this scope, not define the same type + scf_list_t operators; // operator list in this scope + scf_list_t functions; // function list in this scope + scf_list_t labels; // label list in this scope }; -scf_scope_t* scf_scope_alloc(scf_lex_word_t* w, const char* name); -void scf_scope_free( scf_scope_t* scope); +scf_scope_t* scf_scope_alloc(); +void scf_scope_free(scf_scope_t* scope); -void scf_scope_push_var(scf_scope_t* scope, scf_variable_t* var); - -void scf_scope_push_type(scf_scope_t* scope, scf_type_t* t); +void scf_scope_push_var (scf_scope_t* scope, scf_variable_t* var); +void scf_scope_push_type(scf_scope_t* scope, scf_type_t* t); void scf_scope_push_operator(scf_scope_t* scope, scf_function_t* op); - void scf_scope_push_function(scf_scope_t* scope, scf_function_t* f); -scf_type_t* scf_scope_find_type(scf_scope_t* scope, const char* name); - -scf_type_t* scf_scope_find_type_type(scf_scope_t* scope, const int type); - -scf_variable_t* scf_scope_find_variable(scf_scope_t* scope, const char* name); - -scf_function_t* scf_scope_find_function(scf_scope_t* scope, const char* name); +scf_type_t* scf_scope_find_type (scf_scope_t* scope, const char* name); +scf_type_t* scf_scope_find_type_type(scf_scope_t* scope, const int type); +scf_variable_t* scf_scope_find_variable (scf_scope_t* scope, const char* name); +scf_function_t* scf_scope_find_function (scf_scope_t* scope, const char* name); scf_function_t* scf_scope_find_same_function(scf_scope_t* scope, scf_function_t* f0); diff --git a/js/core/scf_type.c b/js/core/scf_type.c index a964018..94455a5 100644 --- a/js/core/scf_type.c +++ b/js/core/scf_type.c @@ -7,7 +7,6 @@ scf_type_t* scf_type_alloc(scf_lex_word_t* w, const char* name, int type, int si if (!t) return NULL; - t->type = type; t->node.type = type; t->name = scf_string_cstr(name); @@ -17,8 +16,8 @@ scf_type_t* scf_type_alloc(scf_lex_word_t* w, const char* name, int type, int si } if (w) { - t->w = scf_lex_word_clone(w); - if (!t->w) { + t->node.w = scf_lex_word_clone(w); + if (!t->node.w) { scf_string_free(t->name); free(t); return NULL; @@ -35,18 +34,12 @@ void scf_type_free(scf_type_t* t) scf_string_free(t->name); t->name = NULL; - if (t->w) { - scf_lex_word_free(t->w); - t->w = NULL; - } - if (t->scope) { scf_scope_free(t->scope); t->scope = NULL; } - free(t); - t = NULL; + scf_node_free((scf_node_t*)t); } } diff --git a/js/core/scf_type.h b/js/core/scf_type.h index 82aa8a9..3ece46b 100644 --- a/js/core/scf_type.h +++ b/js/core/scf_type.h @@ -4,8 +4,8 @@ #include"scf_node.h" typedef struct { - int type; const char* name; + int type; int size; } scf_base_type_t; @@ -14,20 +14,16 @@ typedef struct { const char* abbrev; } scf_type_abbrev_t; -struct scf_type_s { +struct scf_type_s +{ // same as block, only used for class type scf_node_t node; - scf_scope_t* scope; - scf_string_t* name; // list for scope's type_list_head scf_list_t list; - int type; - scf_lex_word_t* w; - int nb_pointers; // int array_capacity; @@ -36,7 +32,6 @@ struct scf_type_s { int size; int offset; // only used for member var of struct or class - scf_type_t* super; // pointed to super type extended by this scf_type_t* parent; // pointed to parent type includes this }; @@ -46,4 +41,3 @@ void scf_type_free(scf_type_t* t); const char* scf_type_find_abbrev(const char* name); #endif - diff --git a/js/core/scf_variable.c b/js/core/scf_variable.c index 469e896..cc8935f 100644 --- a/js/core/scf_variable.c +++ b/js/core/scf_variable.c @@ -98,7 +98,7 @@ scf_variable_t* scf_variable_alloc(scf_lex_word_t* w, scf_type_t* t) return NULL; v->refs = 1; - v->type = t->type; + v->type = t->node.type; v->js_type = -1; v->js_index = -1; diff --git a/js/doc.c b/js/doc.c index ceeda44..f8ea145 100644 --- a/js/doc.c +++ b/js/doc.c @@ -2,9 +2,12 @@ struct Object; -int abc_html_write (Object* html, const char* s); -int abc_html_write_i(Object* html, int64_t i); -int abc_html_write_d(Object* html, double d); +void abc_html_inner (Object* obj, const char* s); +int abc_html_write (Object* html, const char* s); +int abc_html_write_i(Object* html, int64_t i); +int abc_html_write_d(Object* html, double d); + +void* abc_html_getElementById(Object* html, const char* id); int abc_pcre2_match(int** __ovector, const char* __subject, const char* __pattern); @@ -31,6 +34,7 @@ struct Object char* str; double d; int64_t i64; + Object* innerHTML; int __init(Object* this) { @@ -128,6 +132,42 @@ struct Object return 0; } + int __init(Object* this, const char* name, int length, const char* s) + { + printf("this: %p, name: %s\n", this, name); + int len = strlen(name); + + this->name = scf__auto_malloc(len + 1); + if (!this->name) + return -1; + memcpy(this->name, name, len + 1); + + this->length = length; + + if (length > 0) { + this->members = scf__auto_malloc(sizeof(Object*) * length); + if (!this->members) + return -1; + + this->type = JS_Object; + } else + this->type = JS_String; + + if (s) { + len = strlen(s); + + this->str = scf__auto_malloc(len + 1); + if (!this->str) + return -1; + + memcpy(this->str, s, len + 1); + + printf("this: %p, this->str: %s, s: %s\n\n", this, this->str, s); + } + + return 0; + } + Object* Boolean(Object* this) { Object* res = new Object(); @@ -581,6 +621,30 @@ struct Object { return this->match(pattern->str); } + + void operator=(Object* this, const char* s) + { + if (1ull & (uintptr_t)this) + abc_html_inner((uintptr_t)this & ~1ull, s); + } + + Object* getElementById(Object* this, const char* id) + { + void* html_obj = abc_html_getElementById(this, id); + if (!html_obj) + return NULL; + + Object* obj = new Object(); + if (!obj) + return NULL; + + obj->type = JS_Object; + *(uintptr_t*)&obj->innerHTML = 0x1 | (uintptr_t)html_obj; + return obj; + } + + // it's an ASM function, only declare here. + void setTimeout(Object* this, int argc, const funcptr* func, int msec, ...); }; const double Math_PI = 3.1415926; diff --git a/js/elf/scf_dwarf.c b/js/elf/scf_dwarf.c index c7d8771..a34bce1 100644 --- a/js/elf/scf_dwarf.c +++ b/js/elf/scf_dwarf.c @@ -435,6 +435,37 @@ scf_dwarf_t* scf_dwarf_debug_alloc() return debug; } +int _find_debug_file(const void* v0, const void* v1) +{ + const scf_string_t* s0 = v0; + const scf_string_t* s1 = v1; + + if (s0->len < s1->len) + return -1; + else if (s0->len > s1->len) + return 1; + + return strcmp(s0->data, s1->data); +} + +int scf_dwarf_add_file_name(scf_dwarf_t* debug, const scf_string_t* fname) +{ + if (scf_vector_find_cmp(debug->file_names, fname, _find_debug_file)) + return 0; + + scf_string_t* s = scf_string_clone(fname); + if (!s) + return -ENOMEM; + + int ret = scf_vector_add(debug->file_names, s); + if (ret < 0) { + scf_string_free(s); + return ret; + } + + return 0; +} + void scf_dwarf_debug_free (scf_dwarf_t* debug) { if (debug) { diff --git a/js/elf/scf_dwarf.h b/js/elf/scf_dwarf.h index 08675bc..c680663 100644 --- a/js/elf/scf_dwarf.h +++ b/js/elf/scf_dwarf.h @@ -441,4 +441,8 @@ const char* scf_dwarf_find_tag (const uint32_t type); const char* scf_dwarf_find_form(const uint32_t type); const char* scf_dwarf_find_attribute(const uint32_t type); +int scf_dwarf_add_file_name(scf_dwarf_t* debug, const scf_string_t* fname); + +int _find_debug_file(const void* v0, const void* v1); + #endif diff --git a/js/lex/scf_lex_util.c b/js/lex/scf_lex_util.c index 2fda3c0..b4d6c9c 100644 --- a/js/lex/scf_lex_util.c +++ b/js/lex/scf_lex_util.c @@ -1,5 +1,35 @@ #include"scf_lex.h" +int _find_key_word(const char* text); + +static scf_key_word_t number_postfix[] = +{ + {"l", SCF_LEX_WORD_CONST_INT}, + {"ll", SCF_LEX_WORD_CONST_I64}, + + {"u", SCF_LEX_WORD_CONST_U32}, + {"ul", SCF_LEX_WORD_CONST_U32}, + {"ull", SCF_LEX_WORD_CONST_U64}, + + {"f", SCF_LEX_WORD_CONST_FLOAT}, + {"lf", SCF_LEX_WORD_CONST_DOUBLE}, +}; + +static int _lex_number_postfix(const char* postfix, int n) +{ + scf_key_word_t* key; + int i; + + for (i = 0; i < sizeof(number_postfix) / sizeof(number_postfix[0]); i++) { + key = &number_postfix[i]; + + if (!strncmp(key->text, postfix, n)) + return key->type; + } + + return -EINVAL; +} + static int __lex_getc(scf_lex_t* lex) { if (lex->fp) @@ -78,7 +108,7 @@ scf_char_t* _lex_pop_char(scf_lex_t* lex) c->utf8[i] = ret; } else { - scf_loge("utf8 byte[%d] wrong %#x, file: %s, line: %d\n", i + 1, ret, lex->file->data, lex->nb_lines); + scf_loge("utf8 byte[%d] wrong %#x, file: %s, line: %d\n", i, ret, lex->file->data, lex->nb_lines); free(c); return NULL; } @@ -214,69 +244,93 @@ int _lex_op3_ll1(scf_lex_t* lex, scf_lex_word_t** pword, scf_char_t* c0, int _lex_number_base_10(scf_lex_t* lex, scf_lex_word_t** pword, scf_string_t* s) { - scf_char_t* c2; - scf_char_t* c3; - scf_lex_word_t* w; + scf_char_t* c2; + scf_char_t* c3; + scf_lex_word_t* w; + int type = -1; int dot = 0; int exp = 0; int neg = 0; uint64_t value = 0; uint64_t num; + char postfix[8]; + int n = 0; + while (1) { c2 = _lex_pop_char(lex); - if (c2->c >= '0' && c2->c <= '9') { - num = c2->c - '0'; - value *= 10; - value += num; + int tmp = c2->c; + if ('A' <= tmp && 'Z' >= tmp) + tmp |= 0x20; - } else if ('.' == c2->c) { + if ('a' <= tmp && 'z' >= tmp) { - c3 = _lex_pop_char(lex); + if (n > 0 || 'e' != tmp) { + if (n < sizeof(postfix) - 1) + postfix[n++] = tmp; - _lex_push_char(lex, c3); + goto next; + } + + } else if (n > 0) { + _lex_push_char(lex, c2); + c2 = NULL; + + postfix[n] = '\0'; + + type = _lex_number_postfix(postfix, n); + if (type < 0) { + scf_loge("postfix '%s' NOT found, file: %s, line: %d, pos: %d\n", postfix, lex->file->data, lex->nb_lines, lex->pos); + goto error; + } + + break; + } - if ('.' == c3->c) { - c3 = NULL; + if (tmp >= '0' && tmp <= '9') + value = value * 10 + tmp - '0'; + else if ('.' == tmp) { + c3 = _lex_pop_char(lex); + tmp = c3->c; + + _lex_push_char(lex, c3); + c3 = NULL; + + if ('.' == tmp) { _lex_push_char(lex, c2); c2 = NULL; break; } - c3 = NULL; - if (++dot > 1) { scf_loge("\n"); - return -EINVAL; + goto error; } - } else if ('e' == c2->c || 'E' == c2->c) { - exp++; - - if (exp > 1) { + } else if ('e' == tmp) { + if (++exp > 1) { scf_loge("\n"); - return -EINVAL; + goto error; } - } else if ('-' == c2->c) { - neg++; - - if (0 == exp || neg > 1) { + } else if ('-' == tmp) { + if (0 == exp || ++neg > 1) { scf_loge("\n"); - return -EINVAL; + goto error; } } else if ('_' == c2->c) { - + // only to split every 3-4 numbers, no other use. } else { _lex_push_char(lex, c2); c2 = NULL; break; } +next: assert(1 == c2->len); scf_string_cat_cstr_len(s, c2->utf8, 1); lex->pos++; @@ -286,10 +340,18 @@ int _lex_number_base_10(scf_lex_t* lex, scf_lex_word_t** pword, scf_string_t* s) } if (exp > 0 || dot > 0) { - w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_DOUBLE); - w->data.d = atof(s->data); + if (SCF_LEX_WORD_CONST_FLOAT == type) { + w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_FLOAT); + w->data.f = atof(s->data); + } else { + w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_DOUBLE); + w->data.d = atof(s->data); + } } else { - if (value & ~0xffffffffULL) + if (type > 0) + w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, type); + + else if (value & ~0xffffffffULL) w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_U64); else w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_U32); @@ -302,57 +364,66 @@ int _lex_number_base_10(scf_lex_t* lex, scf_lex_word_t** pword, scf_string_t* s) *pword = w; return 0; + +error: + free(c2); + return -EINVAL; } int _lex_number_base_16(scf_lex_t* lex, scf_lex_word_t** pword, scf_string_t* s) { - scf_char_t* c2; - scf_lex_word_t* w; + scf_char_t* c2; + scf_lex_word_t* w; + int type = -1; uint64_t value = 0; - uint64_t value2; + + char postfix[8]; + int n = 0; while (1) { c2 = _lex_pop_char(lex); - if (c2->c >= '0' && c2->c <= '9') - value2 = c2->c - '0'; - - else if ('a' <= c2->c && 'f' >= c2->c) - value2 = c2->c - 'a' + 10; - - else if ('A' <= c2->c && 'F' >= c2->c) - value2 = c2->c - 'A' + 10; + int tmp = c2->c; + if ('A' <= tmp && 'Z' >= tmp) + tmp |= 0x20; - else if ('_' == c2->c) { - assert(1 == c2->len); - scf_string_cat_cstr_len(s, c2->utf8, 1); - lex->pos++; + if ('g' <= tmp && 'z' >= tmp) { + if (n < sizeof(postfix) - 1) + postfix[n++] = tmp; - free(c2); - c2 = NULL; + goto next; - } else { + } else if (n > 0) { _lex_push_char(lex, c2); c2 = NULL; - if (value & ~0xffffffffULL) - w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_U64); - else - w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_U32); - - w->data.u64 = value; + postfix[n] = '\0'; - w->text = s; - s = NULL; + type = _lex_number_postfix(postfix, n); + if (type < 0) { + scf_loge("postfix '%s' NOT found, file: %s, line: %d, pos: %d\n", postfix, lex->file->data, lex->nb_lines, lex->pos); + goto error; + } - *pword = w; - return 0; + break; } - value <<= 4; - value += value2; + if (tmp >= '0' && tmp <= '9') + value = (value << 4) + tmp - '0'; + + else if ('a' <= tmp && 'f' >= tmp) + value = (value << 4) + tmp - 'a' + 10; + + else if ('_' == tmp) { + // only to split every 3-4 numbers, no other use. + } else { + _lex_push_char(lex, c2); + c2 = NULL; + break; + } +next: assert(1 == c2->len); scf_string_cat_cstr_len(s, c2->utf8, 1); lex->pos++; @@ -360,149 +431,266 @@ int _lex_number_base_16(scf_lex_t* lex, scf_lex_word_t** pword, scf_string_t* s) free(c2); c2 = NULL; } + + if (type > 0) + w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, type); + + else if (value & ~0xffffffffULL) + w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_U64); + else + w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_U32); + + w->data.u64 = value; + + w->text = s; + s = NULL; + + *pword = w; + return 0; + +error: + free(c2); + return -EINVAL; } int _lex_number_base_8(scf_lex_t* lex, scf_lex_word_t** pword, scf_string_t* s) { - scf_char_t* c2; - scf_lex_word_t* w; + scf_char_t* c2; + scf_lex_word_t* w; + int type = -1; uint64_t value = 0; + char postfix[8]; + int n = 0; + while (1) { c2 = _lex_pop_char(lex); - if (c2->c >= '0' && c2->c <= '7') { - scf_string_cat_cstr_len(s, c2->utf8, 1); - lex->pos++; + int tmp = c2->c; + if ('A' <= tmp && 'Z' >= tmp) + tmp |= 0x20; - value = (value << 3) + c2->c - '0'; + if ('a' <= tmp && 'z' >= tmp) { + if (n < sizeof(postfix) - 1) + postfix[n++] = tmp; - free(c2); + goto next; + + } else if (n > 0) { + _lex_push_char(lex, c2); c2 = NULL; - } else if ('8' == c2->c || '9' == c2->c) { - scf_loge("number must be 0-7 when base 8"); + postfix[n] = '\0'; - free(c2); - c2 = NULL; - return -1; + type = _lex_number_postfix(postfix, n); + if (type < 0) { + scf_loge("postfix '%s' NOT found, file: %s, line: %d, pos: %d\n", postfix, lex->file->data, lex->nb_lines, lex->pos); + goto error; + } - } else if ('_' == c2->c) { - scf_string_cat_cstr_len(s, c2->utf8, 1); - lex->pos++; + break; + } - free(c2); - c2 = NULL; + if (tmp >= '0' && tmp <= '7') + value = (value << 3) + tmp - '0'; + + else if ('8' == tmp || '9' == tmp) { + scf_loge("number must be 0-7 when base 8"); + goto error; + } else if ('_' == tmp) { + // only to split every 3-4 numbers, no other use. } else { _lex_push_char(lex, c2); c2 = NULL; + break; + } - if (value & ~0xffffffffULL) - w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_U64); - else - w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_U32); - w->data.u64 = value; - - w->text = s; - s = NULL; +next: + assert(1 == c2->len); + scf_string_cat_cstr_len(s, c2->utf8, 1); + lex->pos++; - *pword = w; - return 0; - } + free(c2); + c2 = NULL; } + + if (type > 0) + w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, type); + + else if (value & ~0xffffffffULL) + w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_U64); + else + w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_U32); + w->data.u64 = value; + + w->text = s; + s = NULL; + + *pword = w; + return 0; + +error: + free(c2); + return -EINVAL; } int _lex_number_base_2(scf_lex_t* lex, scf_lex_word_t** pword, scf_string_t* s) { - scf_char_t* c2; - scf_lex_word_t* w; + scf_char_t* c2; + scf_lex_word_t* w; + int type = -1; uint64_t value = 0; + char postfix[8]; + int n = 0; + while (1) { c2 = _lex_pop_char(lex); - if (c2->c >= '0' && c2->c <= '1') { - assert(1 == c2->len); - scf_string_cat_cstr_len(s, c2->utf8, 1); - lex->pos++; + int tmp = c2->c; + if ('A' <= tmp && 'Z' >= tmp) + tmp |= 0x20; - value = (value << 1) + c2->c - '0'; + if ('a' <= tmp && 'z' >= tmp) { + if (n < sizeof(postfix) - 1) + postfix[n++] = tmp; - free(c2); + goto next; + + } else if (n > 0) { + _lex_push_char(lex, c2); c2 = NULL; - } else if (c2->c >= '2' && c2->c <= '9') { - scf_loge("number must be 0-1 when base 2"); + postfix[n] = '\0'; - free(c2); - c2 = NULL; - return -1; + type = _lex_number_postfix(postfix, n); + if (type < 0) { + scf_loge("postfix '%s' NOT found, file: %s, line: %d, pos: %d\n", postfix, lex->file->data, lex->nb_lines, lex->pos); + goto error; + } - } else if ('_' == c2->c) { - assert(1 == c2->len); - scf_string_cat_cstr_len(s, c2->utf8, 1); - lex->pos++; + break; + } - free(c2); - c2 = NULL; + if (tmp >= '0' && tmp <= '1') + value = (value << 1) + tmp - '0'; + + else if (tmp >= '2' && tmp <= '9') { + scf_loge("number must be 0-1 when base 2"); + goto error; + } else if ('_' == tmp) { + // only to split every 3-4 numbers, no other use. } else { _lex_push_char(lex, c2); c2 = NULL; + break; + } - if (value & ~0xffffffffULL) - w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_U64); - else - w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_U32); - w->data.u64 = value; - - w->text = s; - s = NULL; +next: + assert(1 == c2->len); + scf_string_cat_cstr_len(s, c2->utf8, 1); + lex->pos++; - *pword = w; - return 0; - } + free(c2); + c2 = NULL; } + + if (type > 0) + w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, type); + + else if (value & ~0xffffffffULL) + w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_U64); + else + w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_U32); + w->data.u64 = value; + + w->text = s; + s = NULL; + + *pword = w; + return 0; + +error: + free(c2); + return -EINVAL; } int _lex_double(scf_lex_t* lex, scf_lex_word_t** pword, scf_string_t* s) { - scf_lex_word_t* w; - scf_char_t* c2; + scf_char_t* c2; + scf_lex_word_t* w; + + int type = -1; + char postfix[8]; + int n = 0; while (1) { c2 = _lex_pop_char(lex); - if (c2->c >= '0' && c2->c <= '9') { - scf_string_cat_cstr_len(s, c2->utf8, 1); - lex->pos++; + int tmp = c2->c; + if ('A' <= tmp && 'Z' >= tmp) + tmp |= 0x20; - free(c2); - c2 = NULL; + if ('a' <= tmp && 'z' >= tmp) { + if (n < sizeof(postfix) - 1) + postfix[n++] = tmp; - } else if ('.' == c2->c) { - scf_loge("too many '.' for number in file: %s, line: %d\n", lex->file->data, lex->nb_lines); + goto next; - free(c2); + } else if (n > 0) { + _lex_push_char(lex, c2); c2 = NULL; - return -1; + postfix[n] = '\0'; + + type = _lex_number_postfix(postfix, n); + if (type < 0) { + scf_loge("postfix '%s' NOT found, file: %s, line: %d, pos: %d\n", postfix, lex->file->data, lex->nb_lines, lex->pos); + goto error; + } + + break; + } + + if (tmp >= '0' && tmp <= '9') { + + } else if ('.' == tmp) { + scf_loge("too many '.' for number in file: %s, line: %d\n", lex->file->data, lex->nb_lines); + goto error; } else { _lex_push_char(lex, c2); c2 = NULL; break; } + +next: + assert(1 == c2->len); + scf_string_cat_cstr_len(s, c2->utf8, 1); + lex->pos++; + + free(c2); + c2 = NULL; } - w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_DOUBLE); - w->data.d = atof(s->data); + if (SCF_LEX_WORD_CONST_FLOAT == type) { + w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_FLOAT); + w->data.f = atof(s->data); + } else { + w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_CONST_DOUBLE); + w->data.d = atof(s->data); + } w->text = s; *pword = w; return 0; + +error: + free(c2); + return -EINVAL; } int _lex_dot(scf_lex_t* lex, scf_lex_word_t** pword, scf_char_t* c0) @@ -510,8 +698,6 @@ int _lex_dot(scf_lex_t* lex, scf_lex_word_t** pword, scf_char_t* c0) scf_char_t* c1 = _lex_pop_char(lex); scf_char_t* c2 = NULL; scf_lex_word_t* w = NULL; - scf_lex_word_t* w1 = NULL; - scf_lex_word_t* w2 = NULL; scf_string_t* s = scf_string_cstr_len(c0->utf8, c0->len); lex->pos += c0->len; @@ -548,48 +734,16 @@ int _lex_dot(scf_lex_t* lex, scf_lex_word_t** pword, scf_char_t* c0) } } else { - w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_DOT); - w->text = s; - s = NULL; - + int tmp = c1->c; _lex_push_char(lex, c1); c1 = NULL; - int ret = __lex_pop_word(lex, &w1); - if (ret < 0) { - scf_lex_word_free(w); - return ret; - } - - if (SCF_LEX_WORD_CONST_CHAR <= w1->type && w1->type <= SCF_LEX_WORD_CONST_U64) { + if ('0' <= tmp && '9' >= tmp) // for double / float .5, .618, etc. + return _lex_double(lex, pword, s); - ret = __lex_pop_word(lex, &w2); - if (ret < 0) { - scf_lex_word_free(w); - scf_lex_word_free(w1); - return ret; - } - - scf_lex_push_word(lex, w2); - - if (w2->type != SCF_LEX_WORD_ASSIGN && w2->type != SCF_LEX_WORD_DOT) { - w->type = SCF_LEX_WORD_CONST_DOUBLE; - - ret = scf_string_cat(w->text, w1->text); - scf_lex_word_free(w1); - w1 = NULL; - - if (ret < 0) { - scf_lex_word_free(w); - return ret; - } - - w->data.d = atof(w->text->data); - } - } - - if (w1) - scf_lex_push_word(lex, w1); + w = scf_lex_word_alloc(lex->file, lex->nb_lines, lex->pos, SCF_LEX_WORD_DOT); + w->text = s; + s = NULL; } *pword = w; diff --git a/js/lib/scf_rbtree.c b/js/lib/scf_rbtree.c index ff08fcb..0723dff 100644 --- a/js/lib/scf_rbtree.c +++ b/js/lib/scf_rbtree.c @@ -471,9 +471,9 @@ int scf_rbtree_delete(scf_rbtree_t* tree, scf_rbtree_node_t* z) if (&tree->sentinel == y->parent) { tree->root = x; } else if (y->parent->left == y) { - y->parent->left = x; + y->parent->left = x; } else { - y->parent->right = x; + y->parent->right = x; } uint8_t color = y->color; diff --git a/js/native/x64/scf_x64.c b/js/native/x64/scf_x64.c index 7ec69c3..300b9dc 100644 --- a/js/native/x64/scf_x64.c +++ b/js/native/x64/scf_x64.c @@ -52,7 +52,6 @@ static void _x64_argv_rabi(scf_function_t* f) int size = x64_variable_size(v); if (is_float) { - if (f->args_float < X64_ABI_FLOAT_NB) { v->rabi = x64_find_register_type_id_bytes(is_float, x64_abi_float_regs[f->args_float], size); @@ -61,6 +60,7 @@ static void _x64_argv_rabi(scf_function_t* f) f->args_float++; continue; } + } else if (f->args_int < X64_ABI_NB) { v->rabi = x64_find_register_type_id_bytes(is_float, x64_abi_regs[f->args_int], size); @@ -79,12 +79,12 @@ static void _x64_argv_rabi(scf_function_t* f) static int _x64_function_init(scf_function_t* f, scf_vector_t* local_vars) { scf_variable_t* v; + int i; int ret = x64_registers_init(); if (ret < 0) return ret; - int i; for (i = 0; i < local_vars->size; i++) { v = local_vars->data[i]; @@ -109,11 +109,13 @@ static int _x64_function_init(scf_function_t* f, scf_vector_t* local_vars) local_vars_size += size; - if (local_vars_size & 0x7) - local_vars_size = (local_vars_size + 7) >> 3 << 3; + if (v->nb_dimentions > 0) + local_vars_size = (local_vars_size + 0xf) & ~0xf; + else + local_vars_size = (local_vars_size + 0x7) & ~0x7; - v->bp_offset = -local_vars_size; - v->local_flag = 1; + v->bp_offset = -local_vars_size; + v->local_flag = 1; } return local_vars_size; @@ -136,9 +138,12 @@ static int _x64_save_rabi(scf_function_t* f) scf_register_t* xmm1; scf_register_t* xmm2; scf_register_t* xmm3; + scf_register_t* xmm4; + scf_register_t* xmm5; + scf_register_t* xmm6; + scf_register_t* xmm7; if (f->vargs_flag) { - inst = NULL; mov = x64_find_OpCode(SCF_X64_MOV, 8,8, SCF_X64_G2E); @@ -171,11 +176,19 @@ static int _x64_save_rabi(scf_function_t* f) xmm1 = x64_find_register("xmm1"); xmm2 = x64_find_register("xmm2"); xmm3 = x64_find_register("xmm3"); - - X64_SAVE_RABI(-56, xmm0); - X64_SAVE_RABI(-64, xmm1); - X64_SAVE_RABI(-72, xmm2); - X64_SAVE_RABI(-80, xmm3); + xmm4 = x64_find_register("xmm4"); + xmm5 = x64_find_register("xmm5"); + xmm6 = x64_find_register("xmm6"); + xmm7 = x64_find_register("xmm7"); + + X64_SAVE_RABI(-56, xmm0); + X64_SAVE_RABI(-64, xmm1); + X64_SAVE_RABI(-72, xmm2); + X64_SAVE_RABI(-80, xmm3); + X64_SAVE_RABI(-88, xmm4); + X64_SAVE_RABI(-96, xmm5); + X64_SAVE_RABI(-104, xmm6); + X64_SAVE_RABI(-112, xmm7); } return 0; @@ -217,6 +230,10 @@ static int _x64_function_finish(scf_function_t* f) l = scf_list_tail(&bb->code_list_head); end = scf_list_data(l, scf_3ac_code_t, list); + int err = x64_pop_callee_regs(end, f); + if (err < 0) + return err; + if (f->bp_used_flag || f->vla_flag || f->call_flag) { inst = x64_make_inst_G2E(mov, rsp, rbp); @@ -230,16 +247,8 @@ static int _x64_function_finish(scf_function_t* f) bb ->code_bytes += inst->len; } - int err = x64_pop_callee_regs(end, f); - if (err < 0) - return err; - f->init_code_bytes = 0; - err = x64_push_callee_regs(f->init_code, f); - if (err < 0) - return err; - uint32_t local = f->bp_used_flag ? f->local_vars_size : 0; if (f->bp_used_flag || f->vla_flag || f->call_flag) { @@ -252,13 +261,8 @@ static int _x64_function_finish(scf_function_t* f) X64_INST_ADD_CHECK(f->init_code->instructions, inst, NULL); f->init_code_bytes += inst->len; - if (f->callee_saved_size & 0xf) { - if (!(local & 0xf)) - local += 8; - } else { - if ((local & 0xf)) - local += 8; - } + if ((f->callee_saved_size + local) & 0xf) + local += 8; scf_logd("### local: %#x, local_vars_size: %#x, callee_saved_size: %#x\n", local, f->local_vars_size, f->callee_saved_size); @@ -267,11 +271,15 @@ static int _x64_function_finish(scf_function_t* f) X64_INST_ADD_CHECK(f->init_code->instructions, inst, NULL); f->init_code_bytes += inst->len; - int err = _x64_save_rabi(f); + err = _x64_save_rabi(f); if (err < 0) return err; } + err = x64_push_callee_regs(f->init_code, f); + if (err < 0) + return err; + inst = x64_make_inst(ret, 8); X64_INST_ADD_CHECK(end->instructions, inst, NULL); end->inst_bytes += inst->len; @@ -1120,11 +1128,13 @@ int scf_x64_select_inst(scf_native_t* ctx, scf_function_t* f) scf_logi("---------- %s() ------------\n", f->node.w->text->data); + scf_variable_t* v; int i; + for (i = 0; i < local_vars->size; i++) { - scf_variable_t* v = local_vars->data[i]; - assert(v->w); + v = local_vars->data[i]; + assert(v->w); scf_logd("v: %p, name: %s_%d_%d, size: %d, bp_offset: %d, arg_flag: %d\n", v, v->w->text->data, v->w->line, v->w->pos, scf_variable_size(v), v->bp_offset, v->arg_flag); diff --git a/js/native/x64/scf_x64_inst.c b/js/native/x64/scf_x64_inst.c index 51c6b9b..9921814 100644 --- a/js/native/x64/scf_x64_inst.c +++ b/js/native/x64/scf_x64_inst.c @@ -528,8 +528,10 @@ static int _x64_inst_call_handler(scf_native_t* ctx, scf_3ac_code_t* c) X64_INST_ADD_CHECK(c->instructions, inst, NULL); scf_register_t* saved_regs[X64_ABI_CALLER_SAVES_NB]; + scf_register_t* drop_regs [X64_ABI_CALLER_SAVES_NB]; + int n_drops = 0; - int save_size = x64_caller_save_regs(c, x64_abi_caller_saves, X64_ABI_CALLER_SAVES_NB, stack_size, saved_regs); + int save_size = x64_caller_save_regs(c, x64_abi_caller_saves, X64_ABI_CALLER_SAVES_NB, stack_size, saved_regs, drop_regs, &n_drops); if (save_size < 0) { scf_loge("\n"); return save_size; @@ -593,6 +595,8 @@ static int _x64_inst_call_handler(scf_native_t* ctx, scf_3ac_code_t* c) X64_INST_ADD_CHECK(c->instructions, inst, NULL); } + x64_drop_regs(drop_regs, n_drops); + int nb_updated = 0; scf_register_t* updated_regs[X64_ABI_RET_NB * 2]; diff --git a/js/native/x64/scf_x64_inst_common.c b/js/native/x64/scf_x64_inst_common.c index cdd4fbd..1d9eba7 100644 --- a/js/native/x64/scf_x64_inst_common.c +++ b/js/native/x64/scf_x64_inst_common.c @@ -86,18 +86,21 @@ static int _x64_inst_op2_imm(int OpCode_type, scf_dag_node_t* dst, scf_dag_node_ else X64_SELECT_REG_CHECK(&rd, dst, c, f, 1); - OpCode = x64_find_OpCode(OpCode_type, src_size, dst_size, SCF_X64_I2G); - if (OpCode) { - inst = x64_make_inst_I2G(OpCode, rd, (uint8_t*)&src->var->data, src_size); - X64_INST_ADD_CHECK(c->instructions, inst, NULL); - return 0; - } + if (scf_variable_const_integer(src->var)) { - OpCode = x64_find_OpCode(OpCode_type, src_size, dst_size, SCF_X64_I2E); - if (OpCode) { - inst = x64_make_inst_I2E(OpCode, rd, (uint8_t*)&src->var->data, src_size); - X64_INST_ADD_CHECK(c->instructions, inst, NULL); - return 0; + OpCode = x64_find_OpCode(OpCode_type, src_size, dst_size, SCF_X64_I2G); + if (OpCode) { + inst = x64_make_inst_I2G(OpCode, rd, (uint8_t*)&src->var->data, src_size); + X64_INST_ADD_CHECK(c->instructions, inst, NULL); + return 0; + } + + OpCode = x64_find_OpCode(OpCode_type, src_size, dst_size, SCF_X64_I2E); + if (OpCode) { + inst = x64_make_inst_I2E(OpCode, rd, (uint8_t*)&src->var->data, src_size); + X64_INST_ADD_CHECK(c->instructions, inst, NULL); + return 0; + } } OpCode = x64_find_OpCode(OpCode_type, src_size, dst_size, SCF_X64_G2E); @@ -120,12 +123,15 @@ static int _x64_inst_op2_imm(int OpCode_type, scf_dag_node_t* dst, scf_dag_node_ return 0; } - OpCode = x64_find_OpCode(OpCode_type, src_size, dst_size, SCF_X64_I2E); - if (OpCode) { - inst = x64_make_inst_I2M(&rela, OpCode, dst->var, NULL, (uint8_t*)&src->var->data, src_size); - X64_INST_ADD_CHECK(c->instructions, inst, rela); - X64_RELA_ADD_CHECK(f->data_relas, rela, c, dst->var, NULL); - return 0; + if (scf_variable_const_integer(src->var)) { + + OpCode = x64_find_OpCode(OpCode_type, src_size, dst_size, SCF_X64_I2E); + if (OpCode) { + inst = x64_make_inst_I2M(&rela, OpCode, dst->var, NULL, (uint8_t*)&src->var->data, src_size); + X64_INST_ADD_CHECK(c->instructions, inst, rela); + X64_RELA_ADD_CHECK(f->data_relas, rela, c, dst->var, NULL); + return 0; + } } OpCode = x64_find_OpCode(OpCode_type, src_size, dst_size, SCF_X64_G2E); @@ -149,36 +155,6 @@ static int _x64_inst_op2_imm(int OpCode_type, scf_dag_node_t* dst, scf_dag_node_ return 0; } -static int _x64_inst_op2_imm_str(int OpCode_type, scf_dag_node_t* dst, scf_dag_node_t* src, scf_3ac_code_t* c, scf_function_t* f) -{ - if (SCF_X64_MOV != OpCode_type) { - scf_loge("\n"); - return -EINVAL; - } - - scf_register_t* rd = NULL; - scf_instruction_t* inst = NULL; - scf_x64_OpCode_t* lea = x64_find_OpCode(SCF_X64_LEA, 8, 8, SCF_X64_E2G); - scf_rela_t* rela = NULL; - - int size0 = x64_variable_size(dst->var); - int size1 = x64_variable_size(src->var); - - assert(8 == size0); - assert(8 == size1); - - X64_SELECT_REG_CHECK(&rd, dst, c, f, 0); - - src->var->global_flag = 1; - src->var->local_flag = 0; - src->var->tmp_flag = 0; - - inst = x64_make_inst_M2G(&rela, lea, rd, NULL, src->var); - X64_INST_ADD_CHECK(c->instructions, inst, rela); - X64_RELA_ADD_CHECK(f->data_relas, rela, c, src->var, NULL); - return 0; -} - int x64_inst_op2(int OpCode_type, scf_dag_node_t* dst, scf_dag_node_t* src, scf_3ac_code_t* c, scf_function_t* f) { assert(0 != dst->color); @@ -190,9 +166,13 @@ int x64_inst_op2(int OpCode_type, scf_dag_node_t* dst, scf_dag_node_t* src, scf_ scf_rela_t* rela = NULL; if (0 == src->color) { + if (scf_variable_const_string(src->var)) { + if (SCF_X64_MOV != OpCode_type) + return -EINVAL; + X64_SELECT_REG_CHECK(&rd, dst, c, f, 0); - if (scf_variable_const_string(src->var)) - return _x64_inst_op2_imm_str(OpCode_type, dst, src, c, f); + return x64_load_const(rd, src, c, f); + } if (!scf_variable_float(src->var)) return _x64_inst_op2_imm(OpCode_type, dst, src, c, f); diff --git a/js/native/x64/scf_x64_peephole.c b/js/native/x64/scf_x64_peephole.c index 57f906c..147a303 100644 --- a/js/native/x64/scf_x64_peephole.c +++ b/js/native/x64/scf_x64_peephole.c @@ -3,18 +3,20 @@ #include"scf_basic_block.h" #include"scf_3ac.h" -static int _x64_peephole_mov(scf_vector_t* std_insts, scf_instruction_t* inst) +static int _x64_peephole_mov(scf_vector_t* save_insts, scf_vector_t* peep_insts, scf_instruction_t* inst) { - scf_3ac_code_t* c = inst->c; - scf_basic_block_t* bb = c->basic_block; + scf_3ac_code_t* c = inst->c; + scf_basic_block_t* bb = c->basic_block; - scf_instruction_t* inst2; - scf_instruction_t* std; - scf_x64_OpCode_t* OpCode; + scf_register_t* r0; + scf_register_t* r1; + scf_x64_OpCode_t* OpCode; + scf_instruction_t* inst2; + scf_instruction_t* std; int j; - for (j = std_insts->size - 1; j >= 0; j--) { - std = std_insts->data[j]; + for (j = peep_insts->size - 1; j >= 0; j--) { + std = peep_insts->data[j]; #if 0 scf_loge("std j: %d\n", j); scf_3ac_code_print(std->c, NULL); @@ -67,12 +69,13 @@ static int _x64_peephole_mov(scf_vector_t* std_insts, scf_instruction_t* inst) return X64_PEEPHOLE_DEL; } - assert(0 == scf_vector_del(std_insts, std)); + assert(0 == scf_vector_del(peep_insts, std)); if (std->nb_used > 0) continue; assert(0 == scf_vector_del(std->c->instructions, std)); + assert(0 == scf_vector_del(save_insts, std)); free(std); std = NULL; @@ -175,20 +178,16 @@ static int _x64_peephole_mov(scf_vector_t* std_insts, scf_instruction_t* inst) } } else if (scf_inst_data_same(&std->src, &inst->dst)) { - assert(0 == scf_vector_del(std_insts, std)); + assert(0 == scf_vector_del(peep_insts, std)); } else if (x64_inst_data_is_reg(&std->src)) { - scf_register_t* r0; - scf_register_t* r1; - if (x64_inst_data_is_reg(&inst->dst)) { - r0 = std ->src.base; r1 = inst->dst.base; if (X64_COLOR_CONFLICT(r0->color, r1->color)) - assert(0 == scf_vector_del(std_insts, std)); + assert(0 == scf_vector_del(peep_insts, std)); } } else if (x64_inst_data_is_reg(&std->dst)) { @@ -201,33 +200,41 @@ static int _x64_peephole_mov(scf_vector_t* std_insts, scf_instruction_t* inst) } } - assert(0 == scf_vector_add_unique(std_insts, inst)); + if (x64_inst_data_is_reg(&inst->dst)) { + r1 = inst->dst.base; + + for (j = peep_insts->size - 1; j >= 0; j--) { + std = peep_insts->data[j]; + + if ((std->src.flag && (std->src.base == r1 || std->src.index == r1)) + || (std->dst.flag && (std->dst.base == r1 || std->dst.index == r1))) + assert(0 == scf_vector_del(peep_insts, std)); + } + } + + assert(0 == scf_vector_add_unique(peep_insts, inst)); return 0; } -static int _x64_peephole_cmp(scf_vector_t* std_insts, scf_instruction_t* inst) +static int _x64_peephole_cmp(scf_vector_t* save_insts, scf_vector_t* peep_insts, scf_instruction_t* inst) { - scf_3ac_code_t* c = inst->c; - scf_basic_block_t* bb = c->basic_block; - - scf_instruction_t* inst2; - scf_instruction_t* std; + scf_3ac_code_t* c = inst->c; + scf_basic_block_t* bb = c->basic_block; + scf_instruction_t* inst2; + scf_instruction_t* std; int j; - for (j = std_insts->size - 1; j >= 0; j--) { - std = std_insts->data[j]; + for (j = peep_insts->size - 1; j >= 0; j--) { + std = peep_insts->data[j]; if (SCF_X64_LEA == std->OpCode->type) break; if (inst->src.flag) { - if (scf_inst_data_same(&inst->src, &std->src)) - inst->src.base = std->dst.base; else if (scf_inst_data_same(&inst->src, &std->dst)) - inst->src.base = std->src.base; else goto check; @@ -244,11 +251,9 @@ static int _x64_peephole_cmp(scf_vector_t* std_insts, scf_instruction_t* inst) } else if (inst->dst.flag) { if (scf_inst_data_same(&inst->dst, &std->src)) - inst->dst.base = std->dst.base; else if (scf_inst_data_same(&inst->dst, &std->dst)) - inst->dst.base = std->src.base; else goto check; @@ -295,42 +300,6 @@ check: return 0; } -static int _x64_peephole_movx(scf_vector_t* std_insts, scf_instruction_t* inst) -{ - if (!x64_inst_data_is_reg(&inst->src) || !x64_inst_data_is_reg(&inst->dst)) { - scf_vector_clear(std_insts, NULL); - return 0; - } - - scf_3ac_code_t* c = inst->c; - scf_basic_block_t* bb = c->basic_block; - scf_instruction_t* std; - scf_x64_OpCode_t* OpCode; - int j; - - for (j = std_insts->size - 1; j >= 0; j--) { - std = std_insts->data[j]; - - if (scf_inst_data_same(&std->dst, &inst->src)) { - std->nb_used++; - - if (std->OpCode == inst->OpCode - && scf_inst_data_same(&std->src, &inst->src) - && scf_inst_data_same(&std->dst, &inst->dst)) { - - assert(0 == scf_vector_del(inst->c->instructions, inst)); - - free(inst); - inst = NULL; - return X64_PEEPHOLE_DEL; - } - } - } - - assert(0 == scf_vector_add_unique(std_insts, inst)); - return 0; -} - static int x64_inst_is_useful(scf_instruction_t* inst, scf_instruction_t* std) { if (scf_inst_data_same(&inst->dst, &std->src)) @@ -478,15 +447,15 @@ static int __x64_inst_useful_bb_next(scf_basic_block_t* bb, void* data, scf_vect return 0; } -static int _x64_peephole_function(scf_vector_t* tmp_insts, scf_function_t* f) +static int _x64_peephole_function(scf_vector_t* save_insts, scf_function_t* f) { scf_instruction_t* inst; scf_basic_block_t* bb; scf_3ac_code_t* c; int i; - for (i = tmp_insts->size - 1; i >= 0; i--) { - inst = tmp_insts->data[i]; + for (i = save_insts->size - 1; i >= 0; i--) { + inst = save_insts->data[i]; if (SCF_X64_MOV != inst->OpCode->type) continue; @@ -510,7 +479,7 @@ static int _x64_peephole_function(scf_vector_t* tmp_insts, scf_function_t* f) continue; assert(0 == scf_vector_del(c->instructions, inst)); - assert(0 == scf_vector_del(tmp_insts, inst)); + assert(0 == scf_vector_del(save_insts, inst)); free(inst); inst = NULL; @@ -518,8 +487,8 @@ static int _x64_peephole_function(scf_vector_t* tmp_insts, scf_function_t* f) int n_locals = 0; - for (i = 0; i < tmp_insts->size; i++) { - inst = tmp_insts->data[i]; + for (i = 0; i < save_insts->size; i++) { + inst = save_insts->data[i]; if (x64_inst_data_is_local(&inst->src) || x64_inst_data_is_local(&inst->dst)) n_locals++; @@ -536,7 +505,6 @@ static int _x64_peephole_function(scf_vector_t* tmp_insts, scf_function_t* f) int x64_optimize_peephole(scf_native_t* ctx, scf_function_t* f) { - scf_instruction_t* std; scf_instruction_t* inst; scf_basic_block_t* bb; scf_3ac_operand_t* dst; @@ -544,16 +512,16 @@ int x64_optimize_peephole(scf_native_t* ctx, scf_function_t* f) scf_list_t* l; scf_list_t* l2; - scf_vector_t* std_insts; - scf_vector_t* tmp_insts; // instructions for register or local variable + scf_vector_t* peep_insts; + scf_vector_t* save_insts; - std_insts = scf_vector_alloc(); - if (!std_insts) + peep_insts = scf_vector_alloc(); + if (!peep_insts) return -ENOMEM; - tmp_insts = scf_vector_alloc(); - if (!tmp_insts) { - scf_vector_free(tmp_insts); + save_insts = scf_vector_alloc(); + if (!save_insts) { + scf_vector_free(save_insts); return -ENOMEM; } @@ -569,7 +537,7 @@ int x64_optimize_peephole(scf_native_t* ctx, scf_function_t* f) bb = scf_list_data(l, scf_basic_block_t, list); if (bb->jmp_flag) { - scf_vector_clear(std_insts, NULL); + scf_vector_clear(peep_insts, NULL); l2 = scf_list_head(&bb->code_list_head); c = scf_list_data(l2, scf_3ac_code_t, list); @@ -582,9 +550,8 @@ int x64_optimize_peephole(scf_native_t* ctx, scf_function_t* f) continue; } - if (bb->jmp_dst_flag) { - scf_vector_clear(std_insts, NULL); - } + if (bb->jmp_dst_flag) + scf_vector_clear(peep_insts, NULL); for (l2 = scf_list_head(&bb->code_list_head); l2 != scf_list_sentinel(&bb->code_list_head); l2 = scf_list_next(l2)) { @@ -603,26 +570,26 @@ int x64_optimize_peephole(scf_native_t* ctx, scf_function_t* f) // scf_instruction_print(inst); ret = 0; - switch (inst->OpCode->type) { - + switch (inst->OpCode->type) + { case SCF_X64_CMP: case SCF_X64_TEST: - ret = _x64_peephole_cmp(std_insts, inst); + ret = _x64_peephole_cmp(save_insts, peep_insts, inst); break; case SCF_X64_MOV: - ret = _x64_peephole_mov(std_insts, inst); + ret = _x64_peephole_mov(save_insts, peep_insts, inst); break; case SCF_X64_LEA: - ret = scf_vector_add_unique(std_insts, inst); + ret = scf_vector_add_unique(peep_insts, inst); break; case SCF_X64_MOVSS: case SCF_X64_MOVSD: break; default: - scf_vector_clear(std_insts, NULL); + scf_vector_clear(peep_insts, NULL); break; }; @@ -632,7 +599,7 @@ int x64_optimize_peephole(scf_native_t* ctx, scf_function_t* f) if (X64_PEEPHOLE_DEL == ret) continue; - ret = scf_vector_add(tmp_insts, inst); + ret = scf_vector_add(save_insts, inst); if (ret < 0) goto error; i++; @@ -640,9 +607,9 @@ int x64_optimize_peephole(scf_native_t* ctx, scf_function_t* f) } } - ret = _x64_peephole_function(tmp_insts, f); + ret = _x64_peephole_function(save_insts, f); error: - scf_vector_free(tmp_insts); - scf_vector_free(std_insts); + scf_vector_free(save_insts); + scf_vector_free(peep_insts); return ret; } diff --git a/js/native/x64/scf_x64_reg.c b/js/native/x64/scf_x64_reg.c index efcc9aa..9374eed 100644 --- a/js/native/x64/scf_x64_reg.c +++ b/js/native/x64/scf_x64_reg.c @@ -95,7 +95,7 @@ void x64_registers_print() } } -int x64_caller_save_regs(scf_3ac_code_t* c, const char* regs[], int nb_regs, int stack_size, scf_register_t** saved_regs) +int x64_caller_save_regs(scf_3ac_code_t* c, const char* regs[], int nb_regs, int stack_size, scf_register_t** saved_regs, scf_register_t** drop_regs, int* n_drops) { scf_basic_block_t* bb = c->basic_block; scf_dag_node_t* dn; @@ -119,6 +119,8 @@ int x64_caller_save_regs(scf_3ac_code_t* c, const char* regs[], int nb_regs, int for (j = 0; j < nb_regs; j++) { r2 = x64_find_register(regs[j]); + int drop_flag = 0; + for (i = 0; i < sizeof(x64_registers) / sizeof(x64_registers[0]); i++) { r = &(x64_registers[i]); @@ -148,11 +150,15 @@ int x64_caller_save_regs(scf_3ac_code_t* c, const char* regs[], int nb_regs, int if (k < r->dag_nodes->size) break; + drop_flag = 1; } } - if (i == sizeof(x64_registers) / sizeof(x64_registers[0])) + if (i == sizeof(x64_registers) / sizeof(x64_registers[0])) { + if (drop_flag) + drop_regs[(*n_drops)++] = r2; continue; + } if (X64_COLOR_TYPE(r2->color)) { if (stack_size > 0) @@ -693,6 +699,7 @@ int x64_load_const(scf_register_t* r, scf_dag_node_t* dn, scf_3ac_code_t* c, scf scf_instruction_t* inst; scf_x64_OpCode_t* lea; scf_x64_OpCode_t* mov; + scf_x64_OpCode_t* xor; scf_variable_t* v; v = dn->var; @@ -701,34 +708,9 @@ int x64_load_const(scf_register_t* r, scf_dag_node_t* dn, scf_3ac_code_t* c, scf int size = x64_variable_size(v); int is_float = scf_variable_float(v); - if (SCF_FUNCTION_PTR == v->type) { - - if (v->func_ptr) { - assert(v->const_literal_flag); - - v->global_flag = 1; - v->local_flag = 0; - v->tmp_flag = 0; - - scf_rela_t* rela = NULL; - - lea = x64_find_OpCode(SCF_X64_LEA, size, size, SCF_X64_E2G); - inst = x64_make_inst_M2G(&rela, lea, r, NULL, v); - X64_INST_ADD_CHECK(c->instructions, inst, rela); - X64_RELA_ADD_CHECK(f->text_relas, rela, c, NULL, v->func_ptr); - - } else { - scf_x64_OpCode_t* xor; - - xor = x64_find_OpCode(SCF_X64_XOR, size, size, SCF_X64_G2E); - inst = x64_make_inst_G2E(xor, r, r); - X64_INST_ADD_CHECK(c->instructions, inst, NULL); - } - - } else if (scf_variable_const_string(v)) { - - scf_rela_t* rela = NULL; + scf_rela_t* rela = NULL; + if (scf_variable_const_string(v)) { v->global_flag = 1; v->local_flag = 0; v->tmp_flag = 0; @@ -742,14 +724,29 @@ int x64_load_const(scf_register_t* r, scf_dag_node_t* dn, scf_3ac_code_t* c, scf } else if (v->nb_dimentions > 0) { assert(v->const_literal_flag); - scf_rela_t* rela = NULL; - lea = x64_find_OpCode(SCF_X64_LEA, size, size, SCF_X64_E2G); inst = x64_make_inst_M2G(&rela, lea, r, NULL, v); X64_INST_ADD_CHECK(c->instructions, inst, rela); X64_RELA_ADD_CHECK(f->data_relas, rela, c, v, NULL); + } else if (SCF_FUNCTION_PTR == v->type) { + if (v->func_ptr) { + assert(v->const_literal_flag); + + v->global_flag = 1; + v->local_flag = 0; + v->tmp_flag = 0; + + lea = x64_find_OpCode(SCF_X64_LEA, size, size, SCF_X64_E2G); + inst = x64_make_inst_M2G(&rela, lea, r, NULL, v); + X64_INST_ADD_CHECK(c->instructions, inst, rela); + X64_RELA_ADD_CHECK(f->text_relas, rela, c, NULL, v->func_ptr); + } else { + xor = x64_find_OpCode(SCF_X64_XOR, size, size, SCF_X64_G2E); + inst = x64_make_inst_G2E(xor, r, r); + X64_INST_ADD_CHECK(c->instructions, inst, NULL); + } } else { mov = x64_find_OpCode(SCF_X64_MOV, size, size, SCF_X64_I2G); inst = x64_make_inst_I2G(mov, r, (uint8_t*)&v->data, size); @@ -1181,6 +1178,46 @@ void x64_call_rabi(int* p_nints, int* p_nfloats, scf_3ac_code_t* c) *p_nfloats = nfloats; } +int x64_drop_regs(scf_register_t** drop_regs, int n_drops) +{ + scf_register_t* r2; + scf_register_t* r; + scf_dag_node_t* dn; + scf_variable_t* v; + + int N = sizeof(x64_registers) / sizeof(x64_registers[0]); + int i; + int j; + + for (j = 0; j < N; j++) { + r2 = &(x64_registers[j]); + + if (!r2->dag_nodes || r2->dag_nodes->size <= 0) + continue; + + for (i = 0; i < n_drops; i++) { + r = drop_regs[i]; + + if (X64_COLOR_CONFLICT(r2->color, r->color)) + break; + } + + if (i >= n_drops) + continue; + + for (i = 0; i < r2->dag_nodes->size; i++) { + dn = r2->dag_nodes->data[i]; + + dn->color = -1; + dn->loaded = 0; + } + + r2->dag_nodes->size = 0; + } + + return 0; +} + int x64_push_callee_regs(scf_3ac_code_t* c, scf_function_t* f) { scf_x64_OpCode_t* push = x64_find_OpCode(SCF_X64_PUSH, 8,8, SCF_X64_G); @@ -1217,7 +1254,6 @@ int x64_push_callee_regs(scf_3ac_code_t* c, scf_function_t* f) int x64_pop_callee_regs(scf_3ac_code_t* c, scf_function_t* f) { scf_x64_OpCode_t* pop = x64_find_OpCode(SCF_X64_POP, 8, 8, SCF_X64_G); - scf_basic_block_t* bb = c->basic_block; scf_instruction_t* inst; diff --git a/js/native/x64/scf_x64_reg.h b/js/native/x64/scf_x64_reg.h index 0e59579..9be5f65 100644 --- a/js/native/x64/scf_x64_reg.h +++ b/js/native/x64/scf_x64_reg.h @@ -112,7 +112,9 @@ int x64_save_var2(scf_dag_node_t* dn, scf_register_t* r, scf_3ac int x64_push_regs(scf_vector_t* instructions, uint32_t* regs, int nb_regs); int x64_pop_regs (scf_vector_t* instructions, scf_register_t** regs, int nb_regs, scf_register_t** updated_regs, int nb_updated); -int x64_caller_save_regs(scf_3ac_code_t* c, const char* regs[], int nb_regs, int stack_size, scf_register_t** saved_regs); +int x64_caller_save_regs(scf_3ac_code_t* c, const char* regs[], int nb_regs, int stack_size, scf_register_t** saved_regs, scf_register_t** drop_regs, int* n_drops); + +int x64_drop_regs(scf_register_t** drop_regs, int n_drops); int x64_push_callee_regs(scf_3ac_code_t* c, scf_function_t* f); int x64_pop_callee_regs (scf_3ac_code_t* c, scf_function_t* f); diff --git a/js/parse/scf_dfa_call.c b/js/parse/scf_dfa_call.c index 7197a1b..47b0754 100644 --- a/js/parse/scf_dfa_call.c +++ b/js/parse/scf_dfa_call.c @@ -108,7 +108,7 @@ static int _call_action_lp(scf_dfa_t* dfa, scf_vector_t* words, void* data) return SCF_DFA_ERROR; } } else { - if (Object->type != var_pf->type) { + if (Object->node.type != var_pf->type) { scf_loge("invalid function ptr\n"); return SCF_DFA_ERROR; } @@ -228,7 +228,7 @@ static int _call_add_arguments(scf_ast_t* ast, scf_lex_word_t* w, int n_members, } // add construct() for obj - v = SCF_VAR_ALLOC_BY_TYPE(Object->w, pt, 1, 1, NULL); + v = SCF_VAR_ALLOC_BY_TYPE(Object->node.w, pt, 1, 1, NULL); if (!v) { scf_node_free(assign); return -ENOMEM; @@ -251,7 +251,7 @@ static int _call_add_arguments(scf_ast_t* ast, scf_lex_word_t* w, int n_members, } // add obj name - ret = scf_ast_add_const_str(ast, new, Object->w); + ret = scf_ast_add_const_str(ast, new, Object->node.w); if (ret < 0) { scf_node_free(assign); return ret; @@ -293,7 +293,7 @@ static int _call_add_arguments(scf_ast_t* ast, scf_lex_word_t* w, int n_members, return ret; } - e->js_new = e2; + e->js_new = assign; return 0; } @@ -309,7 +309,7 @@ int _call_add_obj(scf_ast_t* ast, scf_lex_word_t* w, scf_node_t* call, scf_expr_ if (ret < 0) return ret; - if (v->type == Object->type) { + if (v->type == Object->node.type) { scf_variable_free(v); return 0; } @@ -444,22 +444,28 @@ static int _call_action_rp(scf_dfa_t* dfa, scf_vector_t* words, void* data) if (ret < 0) return ret; - int js_flag = 1; + int js_flag = 1; + int timer_flag = 0; + if (SCF_FUNCTION_PTR == pf->type) { f = pf->var->func_ptr; js_flag = f->js_flag; - scf_logw("f: %s, f->js_flag: %d\n", f->node.w->text->data, f->js_flag); + if (!strcmp(f->node.w->text->data, "setTimeout")) + timer_flag = 1; + + scf_logd("f: %s, f->js_flag: %d, timer_flag: %d\n", f->node.w->text->data, f->js_flag, timer_flag); } else - assert(Object->type == pf->type); + assert(Object->node.type == pf->type); + int i = 0; if (cd->argv) { - int i; - for (i = 0; i < cd->argv->size; i++) { - e = cd->argv->data[i]; + for ( ; i < cd->argv->size; i++) { + e = cd->argv->data[i]; - if (js_flag) { + if (js_flag || (timer_flag && i > 1)) + { ret = _call_add_obj(ast, w, cd->call, e, Object); if (ret < 0) return ret; @@ -474,7 +480,8 @@ static int _call_action_rp(scf_dfa_t* dfa, scf_vector_t* words, void* data) // the last arg if (d->expr) { - if (js_flag) { + if (js_flag || (timer_flag && i > 1)) + { ret = _call_add_obj(ast, w, cd->call, d->expr, Object); if (ret < 0) return ret; @@ -484,16 +491,25 @@ static int _call_action_rp(scf_dfa_t* dfa, scf_vector_t* words, void* data) d->expr = NULL; } - if (js_flag) { + if (js_flag || timer_flag) { e = scf_expr_alloc(); if (!e) return -ENOMEM; - ret = _call_add_arguments(ast, w, cd->call->nb_nodes - 1, e, Object); - if (ret < 0) + if (js_flag) + ret = _call_add_arguments(ast, w, cd->call->nb_nodes - 1, e, Object); + else + ret = scf_ast_add_const_var(ast, e, SCF_VAR_INT, cd->call->nb_nodes - 3); + if (ret < 0) { + scf_expr_free(e); return ret; + } - scf_node_add_child(cd->call, e); + ret = scf_node_add_child(cd->call, e); + if (ret < 0) { + scf_expr_free(e); + return ret; + } int i; for (i = cd->call->nb_nodes - 2; i >= 1; i--) diff --git a/js/parse/scf_dfa_class.c b/js/parse/scf_dfa_class.c index 5429e61..dc9fb5c 100644 --- a/js/parse/scf_dfa_class.c +++ b/js/parse/scf_dfa_class.c @@ -54,7 +54,7 @@ static int _class_action_identity(scf_dfa_t* dfa, scf_vector_t* words, void* dat md->parent_block = parse->ast->current_block; SCF_DFA_PUSH_HOOK(scf_dfa_find_node(dfa, "class_end"), SCF_DFA_HOOK_END); - scf_logi("\033[31m t: %p, t->type: %d\033[0m\n", t, t->type); + scf_logi("\033[31m t: %p, t->type: %d\033[0m\n", t, t->node.type); return SCF_DFA_NEXT_WORD; } diff --git a/js/parse/scf_dfa_container.c b/js/parse/scf_dfa_container.c index 5a2ac2b..03d1bbb 100644 --- a/js/parse/scf_dfa_container.c +++ b/js/parse/scf_dfa_container.c @@ -120,7 +120,7 @@ static int _container_action_comma(scf_dfa_t* dfa, scf_vector_t* words, void* da return SCF_DFA_ERROR; } - if (id->type->type < SCF_STRUCT) { + if (id->type->node.type < SCF_STRUCT) { scf_loge("'%s' is not a class or struct\n", w->text->data); free(id); return SCF_DFA_ERROR; diff --git a/js/parse/scf_dfa_expr.c b/js/parse/scf_dfa_expr.c index 75337c1..5b4d206 100644 --- a/js/parse/scf_dfa_expr.c +++ b/js/parse/scf_dfa_expr.c @@ -152,9 +152,9 @@ int _expr_add_var(scf_parse_t* parse, dfa_data_t* d) scf_scope_push_type(b->scope, t); scf_node_add_child((scf_node_t*)b, (scf_node_t*)t); - md->current_var->js_type = t->type; + md->current_var->js_type = t->node.type; - scf_logi("md->current_var->js_type: %d, %s\n", t->type, t->name->data); + scf_logi("md->current_var->js_type: %d, %s\n", t->node.type, t->name->data); } t2 = NULL; @@ -187,7 +187,8 @@ int _expr_add_var(scf_parse_t* parse, dfa_data_t* d) if (md->current_var && md->current_var->js_type >= 0 && var->member_flag - && strcmp(var->w->text->data, "length")) { + && strcmp(var->w->text->data, "length") + && strcmp(var->w->text->data, "innerHTML")) { scf_logi("md->current_var: %s, var: %s, member_flag: %d, line: %d, pos: %d\n", md->current_var->w->text->data, var->w->text->data, var->member_flag, var->w->line, var->w->pos); @@ -850,7 +851,7 @@ int _expr_multi_rets(scf_expr_t* e) scf_variable_t* v_pf = _scf_operand_get(n_pf); scf_function_t* f = v_pf->func_ptr; - if (f->rets->size <= 1) + if (!f || f->rets->size <= 1) return 0; nb_rets = f->rets->size; diff --git a/js/parse/scf_dfa_function.c b/js/parse/scf_dfa_function.c index fe0748e..3a14de6 100644 --- a/js/parse/scf_dfa_function.c +++ b/js/parse/scf_dfa_function.c @@ -59,7 +59,7 @@ int _function_add_function(scf_dfa_t* dfa, dfa_data_t* d) return SCF_DFA_ERROR; } - if (SCF_VAR_VOID == id->type->type && 0 == id->nb_pointers) + if (SCF_VAR_VOID == id->type->node.type && 0 == id->nb_pointers) void_flag = 1; f->extern_flag |= id->extern_flag; @@ -152,7 +152,7 @@ int _function_add_arg(scf_dfa_t* dfa, dfa_data_t* d) if (v && v->identity) w = v->identity; - if (SCF_VAR_VOID == t->type->type && 0 == t->nb_pointers) { + if (SCF_VAR_VOID == t->type->node.type && 0 == t->nb_pointers) { scf_loge("\n"); return SCF_DFA_ERROR; } diff --git a/js/parse/scf_dfa_function_js.c b/js/parse/scf_dfa_function_js.c index 97ff26b..61e733f 100644 --- a/js/parse/scf_dfa_function_js.c +++ b/js/parse/scf_dfa_function_js.c @@ -84,7 +84,7 @@ int _function_js_add_arg(scf_ast_t* ast, scf_lex_word_t* w, dfa_data_t* d) arg = SCF_VAR_ALLOC_BY_TYPE(w, t, 0, 1, NULL); if (!arg) return SCF_DFA_ERROR; - arg->js_type = t->type; + arg->js_type = t->node.type; scf_scope_push_var(d->current_function->scope, arg); diff --git a/js/parse/scf_dfa_goto.c b/js/parse/scf_dfa_goto.c index b3ea503..2c035d5 100644 --- a/js/parse/scf_dfa_goto.c +++ b/js/parse/scf_dfa_goto.c @@ -31,11 +31,9 @@ static int _goto_action_identity(scf_dfa_t* dfa, scf_vector_t* words, void* data scf_parse_t* parse = dfa->priv; dfa_data_t* d = data; scf_lex_word_t* w = words->data[words->size - 1]; + scf_node_t* node = scf_node_alloc(w, SCF_LABEL, NULL); - scf_label_t* l = scf_label_alloc(w); - scf_node_t* n = scf_node_alloc_label(l); - - scf_node_add_child(d->current_goto, n); + scf_node_add_child(d->current_goto, node); return SCF_DFA_NEXT_WORD; } diff --git a/js/parse/scf_dfa_include.c b/js/parse/scf_dfa_include.c index cd0c333..fb4bb60 100644 --- a/js/parse/scf_dfa_include.c +++ b/js/parse/scf_dfa_include.c @@ -25,7 +25,7 @@ static int _include_action_path(scf_dfa_t* dfa, scf_vector_t* words, void* data) scf_logd("include '%s', line %d\n", w->data.s->data, w->line); parse->lex = NULL; - parse->ast->current_block = parse->ast->root_block; +// parse->ast->current_block = parse->ast->root_block; int ret = scf_parse_file(parse, w->data.s->data, NULL); if (ret < 0) { @@ -33,7 +33,7 @@ static int _include_action_path(scf_dfa_t* dfa, scf_vector_t* words, void* data) goto error; } - if (parse->lex != lex && parse->lex->macros) { // copy macros + if (parse->lex && parse->lex != lex && parse->lex->macros) { // copy macros if (!lex->macros) { lex->macros = scf_vector_clone(parse->lex->macros); diff --git a/js/parse/scf_dfa_init_data.c b/js/parse/scf_dfa_init_data.c index 2eb7808..8d61fbe 100644 --- a/js/parse/scf_dfa_init_data.c +++ b/js/parse/scf_dfa_init_data.c @@ -92,8 +92,8 @@ static int _add_struct_member(scf_ast_t* ast, dfa_data_t* d, scf_variable_t* r) scf_scope_push_type(ast->current_block->scope, s); scf_node_add_child((scf_node_t*)ast->current_block, (scf_node_t*)s); - obj->type = s->type; - obj->js_type = s->type; + obj->type = s->node.type; + obj->js_type = s->node.type; scf_logi("obj->w: %s\n", obj->w->text->data); } else { int ret = scf_ast_find_type_type(&s, ast, obj->type); @@ -437,14 +437,14 @@ static int _data_action_lb(scf_dfa_t* dfa, scf_vector_t* words, void* data) scf_node_add_child((scf_node_t*)md->parent_block, (scf_node_t*)s); if (ast->current_block == md->parent_block) - d->current_var->js_type = s->type; + d->current_var->js_type = s->node.type; ast->current_block = (scf_block_t*)s; - obj->type = s->type; - obj->js_type = s->type; + obj->type = s->node.type; + obj->js_type = s->node.type; - scf_loge("s: %p, js_type: %d, obj: %p, obj->w: %s, md->nb_lbs: %d\n", s, s->type, obj, obj->w->text->data, md->nb_lbs); + scf_loge("s: %p, js_type: %d, obj: %p, obj->w: %s, md->nb_lbs: %d\n", s, s->node.type, obj, obj->w->text->data, md->nb_lbs); SCF_DFA_PUSH_HOOK(scf_dfa_find_node(dfa, "init_data_comma"), SCF_DFA_HOOK_POST); diff --git a/js/parse/scf_dfa_label.c b/js/parse/scf_dfa_label.c index a017cf7..f8679fa 100644 --- a/js/parse/scf_dfa_label.c +++ b/js/parse/scf_dfa_label.c @@ -16,7 +16,7 @@ static int _label_action_colon(scf_dfa_t* dfa, scf_vector_t* words, void* data) } scf_label_t* l = scf_label_alloc(id->identity); - scf_node_t* n = scf_node_alloc_label(l); + scf_node_t* n = scf_node_alloc(l->w, SCF_LABEL, NULL); scf_stack_pop(d->current_identities); free(id); @@ -24,6 +24,7 @@ static int _label_action_colon(scf_dfa_t* dfa, scf_vector_t* words, void* data) scf_node_add_child((scf_node_t*)parse->ast->current_block, n); + l->node = n; scf_scope_push_label(parse->ast->current_block->scope, l); return SCF_DFA_OK; diff --git a/js/parse/scf_dfa_new.c b/js/parse/scf_dfa_new.c index 4598774..cab7bcf 100644 --- a/js/parse/scf_dfa_new.c +++ b/js/parse/scf_dfa_new.c @@ -104,7 +104,7 @@ static int __js_init_func(scf_ast_t* ast, scf_function_t* f) } // add 'Object()' - pf = SCF_VAR_ALLOC_BY_TYPE(Object->w, pt, 1, 1, NULL); + pf = SCF_VAR_ALLOC_BY_TYPE(Object->node.w, pt, 1, 1, NULL); if (!pf) { scf_node_free(assign); return -ENOMEM; @@ -242,9 +242,9 @@ static int _new_action_identity(scf_dfa_t* dfa, scf_vector_t* words, void* data) } if (d->current_var && strcmp(t->name->data, "Object")) { - d->current_var->js_type = t->type; + d->current_var->js_type = t->node.type; scf_logw("type '%s', t->type: %d, d->current_var: %s, type: %d, js_type: %d\n", - t->name->data, t->type, d->current_var->w->text->data, d->current_var->type, d->current_var->js_type); + t->name->data, t->node.type, d->current_var->w->text->data, d->current_var->type, d->current_var->js_type); } if (scf_ast_find_type_type(&pt, parse->ast, SCF_FUNCTION_PTR) < 0) diff --git a/js/parse/scf_dfa_type.c b/js/parse/scf_dfa_type.c index 5ef9055..7e72383 100644 --- a/js/parse/scf_dfa_type.c +++ b/js/parse/scf_dfa_type.c @@ -132,7 +132,7 @@ int _type_find_type(scf_dfa_t* dfa, dfa_identity_t* id) } } - if (SCF_FUNCTION_PTR == id->type->type) { + if (SCF_FUNCTION_PTR == id->type->node.type) { id->func_ptr = _type_find_function(parse->ast->current_block, id->identity->text->data); diff --git a/js/parse/scf_dfa_va_arg.c b/js/parse/scf_dfa_va_arg.c index 0a4dc98..918690c 100644 --- a/js/parse/scf_dfa_va_arg.c +++ b/js/parse/scf_dfa_va_arg.c @@ -120,7 +120,7 @@ static int _va_arg_action_ap(scf_dfa_t* dfa, scf_vector_t* words, void* data) } assert(t); - if (t->type != ap->type || 0 != ap->nb_dimentions) { + if (t->node.type != ap->type || 0 != ap->nb_dimentions) { scf_loge("variable %s is not va_list type\n", w->text->data); return SCF_DFA_ERROR; } diff --git a/js/parse/scf_dfa_var.c b/js/parse/scf_dfa_var.c index 33506f7..5dd4249 100644 --- a/js/parse/scf_dfa_var.c +++ b/js/parse/scf_dfa_var.c @@ -8,7 +8,7 @@ int _expr_multi_rets(scf_expr_t* e); int _check_recursive(scf_type_t* parent, scf_type_t* child, scf_lex_word_t* w) { - if (child->type == parent->type) { + if (child->node.type == parent->node.type) { scf_loge("recursive define '%s' type member var '%s' in type '%s', line: %d\n", child->name->data, w->text->data, parent->name->data, w->line); @@ -17,7 +17,7 @@ int _check_recursive(scf_type_t* parent, scf_type_t* child, scf_lex_word_t* w) } if (child->scope) { - assert(child->type >= SCF_STRUCT); + assert(child->node.type >= SCF_STRUCT); scf_variable_t* v = NULL; scf_type_t* type_v = NULL; @@ -85,7 +85,7 @@ static int _var_add_var(scf_dfa_t* dfa, dfa_data_t* d) global_flag = 0; member_flag = 1; - if (0 == id0->nb_pointers && id0->type->type >= SCF_STRUCT) { + if (0 == id0->nb_pointers && id0->type->node.type >= SCF_STRUCT) { // if not pointer var, check if define recursive struct/union/class var if (_check_recursive((scf_type_t*)b, id0->type, id->identity) < 0) { @@ -97,7 +97,7 @@ static int _var_add_var(scf_dfa_t* dfa, dfa_data_t* d) } } - if (SCF_FUNCTION_PTR == id0->type->type + if (SCF_FUNCTION_PTR == id0->type->node.type && (!id0->func_ptr || 0 == id0->nb_pointers)) { scf_loge("invalid func ptr\n"); return SCF_DFA_ERROR; @@ -116,12 +116,12 @@ static int _var_add_var(scf_dfa_t* dfa, dfa_data_t* d) } } - if (SCF_VAR_VOID == id0->type->type && 0 == id0->nb_pointers) { + if (SCF_VAR_VOID == id0->type->node.type && 0 == id0->nb_pointers) { scf_loge("void var must be a pointer, like void*\n"); return SCF_DFA_ERROR; } - if (SCF_VAR_VAR == id0->type->type) { + if (SCF_VAR_VAR == id0->type->node.type) { id0->nb_pointers = 1; if (scf_ast_find_type(&id0->type, parse->ast, "Object") < 0) diff --git a/js/parse/scf_operator_handler_const.c b/js/parse/scf_operator_handler_const.c index 35ebbae..656b792 100644 --- a/js/parse/scf_operator_handler_const.c +++ b/js/parse/scf_operator_handler_const.c @@ -620,7 +620,7 @@ static int _scf_op_const_unary(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, scf_calculate_t* cal = scf_find_base_calculate(parent->type, v0->type, v0->type); if (!cal) { - scf_loge("type %d not support\n", v0->type); + scf_loge("type %d not support, SCF_VAR_U64: %d\n", v0->type, SCF_VAR_U64); return -EINVAL; } diff --git a/js/parse/scf_operator_handler_semantic.c b/js/parse/scf_operator_handler_semantic.c index f3eacb6..5742ece 100644 --- a/js/parse/scf_operator_handler_semantic.c +++ b/js/parse/scf_operator_handler_semantic.c @@ -150,7 +150,7 @@ static int _semantic_do_type_cast(scf_ast_t* ast, scf_node_t** nodes, int nb_nod if (!v_std) return -ENOMEM; - if (t->type != v0->type) { + if (t->node.type != v0->type) { ret = _semantic_add_type_cast(ast, &nodes[0], v_std, nodes[0]); if (ret < 0) { scf_loge("add type cast failed\n"); @@ -158,7 +158,7 @@ static int _semantic_do_type_cast(scf_ast_t* ast, scf_node_t** nodes, int nb_nod } } - if (t->type != v1->type) { + if (t->node.type != v1->type) { ret = _semantic_add_type_cast(ast, &nodes[1], v_std, nodes[1]); if (ret < 0) { scf_loge("add type cast failed\n"); @@ -467,12 +467,12 @@ static int _semantic_do_new(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, sc if (!new) return -ENOMEM; - v_pf = SCF_VAR_ALLOC_BY_TYPE(t->w, pt, 1, 1, NULL); + v_pf = SCF_VAR_ALLOC_BY_TYPE(t->node.w, pt, 1, 1, NULL); if (!v_pf) return -ENOMEM; v_pf->const_literal_flag = 1; - node_pf = scf_node_alloc(t->w, v_pf->type, v_pf); + node_pf = scf_node_alloc(t->node.w, v_pf->type, v_pf); if (!node_pf) return -ENOMEM; @@ -727,7 +727,7 @@ static int _scf_op_semantic_new(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes if (!argv) return -ENOMEM; - ret = _semantic_add_var(&nthis, ast, NULL, v0->w, class->type, 0, 1, NULL); + ret = _semantic_add_var(&nthis, ast, NULL, v0->w, class->node.type, 0, 1, NULL); if (ret < 0) { scf_vector_free(argv); return ret; @@ -1149,11 +1149,8 @@ static int _scf_op_semantic_goto(scf_ast_t* ast, scf_node_t** nodes, int nb_node scf_node_t* nl = nodes[0]; assert(SCF_LABEL == nl->type); - scf_label_t* l = nl->label; - assert(l->w); - - scf_label_t* l2 = scf_block_find_label(ast->current_block, l->w->text->data); - if (!l2) { + scf_label_t* l = scf_block_find_label(ast->current_block, nl->w->text->data); + if (!l) { scf_loge("label '%s' not found\n", l->w->text->data); return -1; } @@ -1507,7 +1504,7 @@ static int _scf_op_semantic_switch(scf_ast_t* ast, scf_node_t** nodes, int nb_no goto error; } - if (v0->type == Object->type) { + if (v0->type == Object->node.type) { ret = __switch_for_Object(ast, Object, parent, child, e, e1, d, v0, v1); if (ret < 0) goto error; @@ -1735,7 +1732,7 @@ static int _scf_op_semantic_call(scf_ast_t* ast, scf_node_t** nodes, int nb_node if (ret < 0) return ret; - if (v0->type != Object->type) { + if (v0->type != Object->node.type) { scf_loge("\n"); return -1; } @@ -2688,7 +2685,7 @@ static int _scf_op_semantic_binary(scf_ast_t* ast, scf_node_t** nodes, int nb_no if (ret < 0) return ret; - if (t->type != v0->type) + if (t->node.type != v0->type) ret = _semantic_add_type_cast(ast, &nodes[0], v1, nodes[0]); else ret = _semantic_add_type_cast(ast, &nodes[1], v0, nodes[1]); @@ -3121,6 +3118,21 @@ static int _scf_op_semantic_assign(scf_ast_t* ast, scf_node_t** nodes, int nb_no v1 = _scf_operand_get(nodes[1]); } + scf_expr_t* e = nodes[0]; + + while (SCF_OP_EXPR == e->type) + e = e->nodes[0]; + + if (scf_type_is_operator(e->type)) { + + ret = _semantic_do_overloaded(ast, nodes, nb_nodes, d); + if (ret < 0) + scf_loge("overloaded function NOT found for operator '%s', file: %s, line: %d\n", + parent->w->text->data, parent->w->file->data, parent->w->line); + + return ret; + } + if (scf_scope_find_function(t->scope, "__init")) { ret = _semantic_do_new(ast, nodes, nb_nodes, d); diff --git a/js/parse/scf_parse.c b/js/parse/scf_parse.c index 852afbd..1d08abb 100644 --- a/js/parse/scf_parse.c +++ b/js/parse/scf_parse.c @@ -5,43 +5,34 @@ #include"scf_dfa.h" #include"scf_basic_block.h" #include"scf_optimizer.h" +#include"scf_symtab.h" #include"scf_elf.h" #include"scf_leb128.h" -#define ADD_SECTION_SYMBOL(sh_index, sh_name) \ - do { \ - int ret = _scf_parse_add_sym(parse, sh_name, 0, 0, sh_index, ELF64_ST_INFO(STB_LOCAL, STT_SECTION)); \ - if (ret < 0) { \ - scf_loge("\n"); \ - return ret; \ - } \ - } while (0) - scf_base_type_t base_types[] = { - {SCF_VAR_CHAR, "char", 1}, - - {SCF_VAR_VOID, "void", 1}, - {SCF_VAR_VAR, "var", 1}, - {SCF_VAR_BOOL, "bool", 1}, - - {SCF_VAR_INT, "int", 4}, - {SCF_VAR_FLOAT, "float", 4}, - {SCF_VAR_DOUBLE, "double", 8}, - - {SCF_VAR_I8, "int8_t", 1}, - {SCF_VAR_I16, "int16_t", 2}, - {SCF_VAR_I32, "int32_t", 4}, - {SCF_VAR_I64, "int64_t", 8}, - - {SCF_VAR_U8, "uint8_t", 1}, - {SCF_VAR_U16, "uint16_t", 2}, - {SCF_VAR_U32, "uint32_t", 4}, - {SCF_VAR_U64, "uint64_t", 8}, - - {SCF_VAR_INTPTR, "intptr_t", sizeof(void*)}, - {SCF_VAR_UINTPTR, "uintptr_t", sizeof(void*)}, - {SCF_FUNCTION_PTR, "funcptr", sizeof(void*)}, + {"char", SCF_VAR_CHAR, 1}, + {"void", SCF_VAR_VOID, 1}, + {"var", SCF_VAR_VAR, 1}, + {"bool", SCF_VAR_BOOL, 1}, + + {"int", SCF_VAR_INT, 4}, + {"float", SCF_VAR_FLOAT, 4}, + {"double", SCF_VAR_DOUBLE, 8}, + + {"int8_t", SCF_VAR_I8, 1}, + {"int16_t", SCF_VAR_I16, 2}, + {"int32_t", SCF_VAR_I32, 4}, + {"int64_t", SCF_VAR_I64, 8}, + + {"uint8_t", SCF_VAR_U8, 1}, + {"uint16_t", SCF_VAR_U16, 2}, + {"uint32_t", SCF_VAR_U32, 4}, + {"uint64_t", SCF_VAR_U64, 8}, + + {"intptr_t", SCF_VAR_INTPTR, sizeof(void*)}, + {"uintptr_t", SCF_VAR_UINTPTR, sizeof(void*)}, + {"funcptr", SCF_FUNCTION_PTR, sizeof(void*)}, }; int scf_parse_open(scf_parse_t** pparse) @@ -100,58 +91,6 @@ int scf_parse_close(scf_parse_t* parse) return 0; } -static int _find_sym(const void* v0, const void* v1) -{ - const char* name = v0; - const scf_elf_sym_t* sym = v1; - - if (!sym->name) - return -1; - - return strcmp(name, sym->name); -} - -static int _scf_parse_add_sym(scf_parse_t* parse, const char* name, - uint64_t st_size, Elf64_Addr st_value, - uint16_t st_shndx, uint8_t st_info) -{ - scf_elf_sym_t* sym = NULL; - scf_elf_sym_t* sym2 = NULL; - - if (name) - sym = scf_vector_find_cmp(parse->symtab, name, _find_sym); - - if (!sym) { - sym = calloc(1, sizeof(scf_elf_sym_t)); - if (!sym) - return -ENOMEM; - - if (name) { - sym->name = strdup(name); - if (!sym->name) { - free(sym); - return -ENOMEM; - } - } - - sym->st_size = st_size; - sym->st_value = st_value; - sym->st_shndx = st_shndx; - sym->st_info = st_info; - - int ret = scf_vector_add(parse->symtab, sym); - if (ret < 0) { - if (sym->name) - free(sym->name); - free(sym); - scf_loge("\n"); - return ret; - } - } - - return 0; -} - int scf_parse_file(scf_parse_t* parse, const char* path, scf_string_t* text) { if (!parse || !path) @@ -247,7 +186,7 @@ static scf_dwarf_info_entry_t* _debug_find_type(scf_parse_t* parse, scf_type_t* tag = DW_TAG_pointer_type; types = parse->debug->base_types; - } else if (t->type < SCF_STRUCT) { + } else if (t->node.type < SCF_STRUCT) { tag = DW_TAG_base_type; types = parse->debug->base_types; @@ -271,7 +210,7 @@ static scf_dwarf_info_entry_t* _debug_find_type(scf_parse_t* parse, scf_type_t* assert(ie->attributes->size == d->attributes->size); - if (ie->type == t->type && ie->nb_pointers == nb_pointers) + if (ie->type == t->node.type && ie->nb_pointers == nb_pointers) return ie; #if 0 for (j = 0; j < d ->attributes->size; j++) { @@ -319,7 +258,7 @@ static int __debug_add_type(scf_dwarf_info_entry_t** pie, scf_dwarf_abbrev_decla types = parse->debug->base_types; - } else if (t->type < SCF_STRUCT) { + } else if (t->node.type < SCF_STRUCT) { d = scf_vector_find_cmp(parse->debug->abbrevs, (void*)DW_TAG_base_type, _debug_abbrev_find_by_tag); if (!d) { @@ -357,7 +296,7 @@ static int __debug_add_type(scf_dwarf_info_entry_t** pie, scf_dwarf_abbrev_decla return -ENOMEM; ie->code = d->code; - ie->type = t->type; + ie->type = t->node.type; ie->nb_pointers = nb_pointers; ret = scf_vector_add(types, ie); @@ -400,19 +339,19 @@ static int __debug_add_type(scf_dwarf_info_entry_t** pie, scf_dwarf_abbrev_decla uint8_t ate; - if (SCF_VAR_CHAR == t->type || SCF_VAR_I8 == t->type) + if (SCF_VAR_CHAR == t->node.type || SCF_VAR_I8 == t->node.type) ate = DW_ATE_signed_char; - else if (scf_type_is_signed(t->type)) + else if (scf_type_is_signed(t->node.type)) ate = DW_ATE_signed; - else if (SCF_VAR_U8 == t->type) + else if (SCF_VAR_U8 == t->node.type) ate = DW_ATE_unsigned_char; - else if (scf_type_is_unsigned(t->type)) + else if (scf_type_is_unsigned(t->node.type)) ate = DW_ATE_unsigned; - else if (scf_type_is_float(t->type)) + else if (scf_type_is_float(t->node.type)) ate = DW_ATE_float; else { scf_loge("\n"); @@ -439,7 +378,7 @@ static int __debug_add_type(scf_dwarf_info_entry_t** pie, scf_dwarf_abbrev_decla } else if (DW_AT_decl_line == iattr->name) { - ret = scf_dwarf_info_fill_attr(iattr, (uint8_t*)&t->w->line, sizeof(t->w->line)); + ret = scf_dwarf_info_fill_attr(iattr, (uint8_t*)&t->node.w->line, sizeof(t->node.w->line)); if (ret < 0) return ret; @@ -689,7 +628,7 @@ static int _debug_add_struct_type(scf_dwarf_info_entry_t** pie, scf_dwarf_abbrev v_member = t->scope->vars->data[i]; - if (v_member->type != t->type) + if (v_member->type != t->node.type) continue; if (v_member->nb_pointers != j) @@ -731,8 +670,7 @@ static int _debug_add_type(scf_dwarf_info_entry_t** pie, scf_parse_t* parse, scf ie = _debug_find_type(parse, t, 0); if (!ie) { - - if (t->type < SCF_STRUCT) { + if (t->node.type < SCF_STRUCT) { ret = __debug_add_type(&ie, &d, parse, t, 0, NULL); if (ret < 0) return ret; @@ -1376,52 +1314,6 @@ static int _fill_function_inst(scf_string_t* code, scf_function_t* f, int64_t of return 0; } -static int _scf_parse_add_rela(scf_vector_t* relas, scf_parse_t* parse, scf_rela_t* r, const char* name, uint16_t st_shndx) -{ - scf_elf_rela_t* rela; - - int ret; - int i; - - for (i = 0; i < parse->symtab->size; i++) { - scf_elf_sym_t* sym = parse->symtab->data[i]; - - if (!sym->name) - continue; - - if (!strcmp(name, sym->name)) - break; - } - - if (i == parse->symtab->size) { - ret = _scf_parse_add_sym(parse, name, 0, 0, st_shndx, ELF64_ST_INFO(STB_GLOBAL, STT_NOTYPE)); - if (ret < 0) { - scf_loge("\n"); - return ret; - } - } - - scf_logd("rela: %s, offset: %ld\n", name, r->text_offset); - - rela = calloc(1, sizeof(scf_elf_rela_t)); - if (!rela) - return -ENOMEM; - - rela->name = (char*)name; - rela->r_offset = r->text_offset; - rela->r_info = ELF64_R_INFO(i + 1, r->type); - rela->r_addend = r->addend; - - ret = scf_vector_add(relas, rela); - if (ret < 0) { - scf_loge("\n"); - free(rela); - return ret; - } - - return 0; -} - static int _fill_data(scf_parse_t* parse, scf_variable_t* v, scf_string_t* data, uint32_t shndx) { char* name; @@ -1472,7 +1364,7 @@ static int _fill_data(scf_parse_t* parse, scf_variable_t* v, scf_string_t* data, else stb = STB_GLOBAL; - ret = _scf_parse_add_sym(parse, name, size, data->len, shndx, ELF64_ST_INFO(stb, STT_OBJECT)); + ret = scf_symtab_add_sym(parse->symtab, name, size, data->len, shndx, ELF64_ST_INFO(stb, STT_OBJECT)); if (ret < 0) return ret; @@ -1602,7 +1494,7 @@ static int _scf_parse_add_data_relas(scf_parse_t* parse, scf_elf_context_t* elf) } if (j == parse->symtab->size) { - ret = _scf_parse_add_sym(parse, name, 0, 0, 0, ELF64_ST_INFO(STB_GLOBAL, STT_NOTYPE)); + ret = scf_symtab_add_sym(parse->symtab, name, 0, 0, 0, ELF64_ST_INFO(STB_GLOBAL, STT_NOTYPE)); if (ret < 0) { scf_loge("\n"); return ret; @@ -1847,11 +1739,10 @@ static int _add_debug_sections(scf_parse_t* parse, scf_elf_context_t* elf) if (str < 0) return str; - ADD_SECTION_SYMBOL(abbrev, ".debug_abbrev"); - ADD_SECTION_SYMBOL(info, ".debug_info"); - ADD_SECTION_SYMBOL(line, ".debug_line"); - ADD_SECTION_SYMBOL(str, ".debug_str"); - + ADD_SECTION_SYMBOL(parse->symtab, abbrev, ".debug_abbrev"); + ADD_SECTION_SYMBOL(parse->symtab, info, ".debug_info"); + ADD_SECTION_SYMBOL(parse->symtab, line, ".debug_line"); + ADD_SECTION_SYMBOL(parse->symtab, str, ".debug_str"); return 0; } @@ -1939,9 +1830,9 @@ static int _scf_parse_add_text_relas(scf_parse_t* parse, scf_elf_context_t* elf, } if (r->func->node.define_flag) - ret = _scf_parse_add_rela(relas, parse, r, r->func->signature->data, SCF_SHNDX_TEXT); + ret = scf_symtab_add_rela(relas, parse->symtab, r, r->func->signature->data, SCF_SHNDX_TEXT); else - ret = _scf_parse_add_rela(relas, parse, r, r->func->signature->data, 0); + ret = scf_symtab_add_rela(relas, parse->symtab, r, r->func->signature->data, 0); if (ret < 0) { scf_loge("\n"); @@ -1958,7 +1849,7 @@ static int _scf_parse_add_text_relas(scf_parse_t* parse, scf_elf_context_t* elf, else name = r->var->signature->data; - ret = _scf_parse_add_rela(relas, parse, r, name, 2); + ret = scf_symtab_add_rela(relas, parse->symtab, r, name, 2); if (ret < 0) { scf_loge("\n"); goto error; @@ -2015,7 +1906,8 @@ static int _sym_cmp(const void* v0, const void* v1) static int _add_debug_file_names(scf_parse_t* parse) { scf_block_t* root = parse->ast->root_block; - scf_block_t* b = NULL; + scf_block_t* b; + scf_lex_t* lex; int ret; int i; @@ -2026,20 +1918,23 @@ static int _add_debug_file_names(scf_parse_t* parse) if (SCF_OP_BLOCK != b->node.type) continue; - ret = _scf_parse_add_sym(parse, b->name->data, 0, 0, SHN_ABS, ELF64_ST_INFO(STB_LOCAL, STT_FILE)); - if (ret < 0) { - scf_loge("\n"); + ret = scf_symtab_add_sym(parse->symtab, b->name->data, 0, 0, SHN_ABS, ELF64_ST_INFO(STB_LOCAL, STT_FILE)); + if (ret < 0) return ret; - } - - scf_string_t* file_str = scf_string_clone(b->name); - if (!file_str) - return -ENOMEM; - ret = scf_vector_add(parse->debug->file_names, file_str); - if (ret < 0) { - scf_string_free(file_str); + ret = scf_dwarf_add_file_name(parse->debug, b->name); + if (ret < 0) return ret; + + for (lex = b->lex_list; lex; lex = lex->next) + { + ret = scf_symtab_add_sym(parse->symtab, lex->file->data, 0, 0, SHN_ABS, ELF64_ST_INFO(STB_LOCAL, STT_FILE)); + if (ret < 0) + return ret; + + ret = scf_dwarf_add_file_name(parse->debug, lex->file); + if (ret < 0) + return ret; } } @@ -2138,16 +2033,9 @@ int scf_parse_write_elf(scf_parse_t* parse, scf_vector_t* functions, scf_vector_ goto error; } - scf_elf_sym_t* sym; - int i; - - for (i = 0; i < parse->symtab->size; i++) { - sym = parse->symtab->data[i]; - - ret = scf_elf_add_sym(elf, sym, ".symtab"); - if (ret < 0) - goto error; - } + ret = scf_elf_add_syms(elf, parse->symtab, ".symtab"); + if (ret < 0) + goto error; ret = scf_elf_write_rel(elf); error: @@ -2184,7 +2072,7 @@ int64_t scf_parse_fill_code2(scf_parse_t* parse, scf_vector_t* functions, scf_ve if (ret < 0) return ret; - ret = _scf_parse_add_sym(parse, f->signature->data, f->code_bytes, offset, SCF_SHNDX_TEXT, ELF64_ST_INFO(STB_GLOBAL, STT_FUNC)); + ret = scf_symtab_add_sym(parse->symtab, f->signature->data, f->code_bytes, offset, SCF_SHNDX_TEXT, ELF64_ST_INFO(STB_GLOBAL, STT_FUNC)); if (ret < 0) return ret; @@ -2232,9 +2120,9 @@ int scf_parse_fill_code(scf_parse_t* parse, scf_vector_t* functions, scf_vector_ scf_string_t* file_name = parse->debug->file_names->data[0]; const char* path = file_name->data; - ADD_SECTION_SYMBOL(SCF_SHNDX_TEXT, ".text"); - ADD_SECTION_SYMBOL(SCF_SHNDX_RODATA, ".rodata"); - ADD_SECTION_SYMBOL(SCF_SHNDX_DATA, ".data"); + ADD_SECTION_SYMBOL(parse->symtab, SCF_SHNDX_TEXT, ".text"); + ADD_SECTION_SYMBOL(parse->symtab, SCF_SHNDX_RODATA, ".rodata"); + ADD_SECTION_SYMBOL(parse->symtab, SCF_SHNDX_DATA, ".data"); scf_dwarf_info_entry_t* cu = NULL; scf_dwarf_line_result_t* r = NULL; @@ -2334,6 +2222,7 @@ int scf_parse_compile(scf_parse_t* parse, const char* arch) switch (e->type) { case SCF_OP_EXPR: + case SCF_OP_CALL: case SCF_OP_SWITCH: case SCF_OP_IF: case SCF_OP_FOR: diff --git a/js/parse/scf_struct_array.c b/js/parse/scf_struct_array.c index b27d10d..b204298 100644 --- a/js/parse/scf_struct_array.c +++ b/js/parse/scf_struct_array.c @@ -37,7 +37,7 @@ static int __object_new(scf_expr_t* e, scf_ast_t* ast, scf_lex_word_t* w, scf_va return -ENOMEM; // add construct() for obj - v = SCF_VAR_ALLOC_BY_TYPE(Object->w, pt, 1, 1, NULL); + v = SCF_VAR_ALLOC_BY_TYPE(Object->node.w, pt, 1, 1, NULL); if (!v) { scf_node_free(new); return -ENOMEM; @@ -99,7 +99,7 @@ static int __object_new(scf_expr_t* e, scf_ast_t* ast, scf_lex_word_t* w, scf_va if (j >= init_pos->size) { assert(ie->expr); - scf_logi("var: %s\n", var->w->text->data); + scf_logd("var: %s:%p, var->func_ptr: %p, ie->expr: %p\n", var->w->text->data, var, var->func_ptr, ie->expr); ret = scf_node_add_child(new, ie->expr); if (ret < 0) { @@ -156,13 +156,13 @@ static int __object_init(scf_ast_t* ast, scf_expr_t* e, scf_lex_word_t* w, scf_v } if (array_dim < obj->nb_dimentions) { - scf_logi("var: %s, array_dim: %d, nb_dimentions: %d, num: %d\n", + scf_logd("var: %s, array_dim: %d, nb_dimentions: %d, num: %d\n", var->w->text->data, array_dim, obj->nb_dimentions, obj->dimentions[array_dim].num); ret = __object_new(e, ast, w, var, obj->dimentions[array_dim].num, Object, NULL, NULL); - } else if (t->type >= SCF_STRUCT) { + } else if (t->node.type >= SCF_STRUCT) { scf_logd("var: %s\n", var->w->text->data); ret = __object_new(e, ast, w, var, t->scope->vars->size, Object, NULL, NULL); } else { @@ -185,7 +185,7 @@ static int __object_init(scf_ast_t* ast, scf_expr_t* e, scf_lex_word_t* w, scf_v scf_logi("-----------------\n"); - if (t->type >= SCF_STRUCT || array_dim < obj->nb_dimentions) { + if (t->node.type >= SCF_STRUCT || array_dim < obj->nb_dimentions) { // add -> node = scf_node_alloc(w, SCF_OP_POINTER, NULL); if (!node) { @@ -202,6 +202,7 @@ static int __object_init(scf_ast_t* ast, scf_expr_t* e, scf_lex_word_t* w, scf_v } OBJ_EXPR_ADD_NODE(e2, node); + scf_variable_t* v; int i; int n; if (array_dim < obj->nb_dimentions) @@ -210,6 +211,15 @@ static int __object_init(scf_ast_t* ast, scf_expr_t* e, scf_lex_word_t* w, scf_v n = t->scope->vars->size; for (i = 0; i < n; i++) { + v = NULL; + + if (array_dim >= obj->nb_dimentions) { + v = t->scope->vars->data[i]; + + if (v->const_flag && v->func_ptr) + continue; + } + e3 = scf_expr_clone(e2); if (!e3) { scf_expr_free(e2); @@ -231,14 +241,9 @@ static int __object_init(scf_ast_t* ast, scf_expr_t* e, scf_lex_word_t* w, scf_v return ret; } - scf_variable_t* v = NULL; + int js_index = v ? v->js_index : i; - if (array_dim < obj->nb_dimentions) - ret = scf_ast_add_const_var(ast, node, SCF_VAR_INT, i); - else { - v = t->scope->vars->data[i]; - ret = scf_ast_add_const_var(ast, node, SCF_VAR_INT, v->js_index); - } + ret = scf_ast_add_const_var(ast, node, SCF_VAR_INT, js_index); if (ret < 0) { scf_expr_free(e3); scf_expr_free(e2); diff --git a/js/parse/scf_symtab.c b/js/parse/scf_symtab.c new file mode 100644 index 0000000..76f9a93 --- /dev/null +++ b/js/parse/scf_symtab.c @@ -0,0 +1,100 @@ +#include"scf_symtab.h" + +static int _find_sym(const void* v0, const void* v1) +{ + const char* name = v0; + const scf_elf_sym_t* sym = v1; + + if (!sym->name) + return -1; + + return strcmp(name, sym->name); +} + +int scf_symtab_add_sym(scf_vector_t* symtab, const char* name, + uint64_t st_size, + Elf64_Addr st_value, + uint16_t st_shndx, + uint8_t st_info) +{ + scf_elf_sym_t* sym = NULL; + + if (name) + sym = scf_vector_find_cmp(symtab, name, _find_sym); + + if (!sym) { + sym = calloc(1, sizeof(scf_elf_sym_t)); + if (!sym) + return -ENOMEM; + + if (name) { + sym->name = strdup(name); + if (!sym->name) { + free(sym); + return -ENOMEM; + } + } + + sym->st_size = st_size; + sym->st_value = st_value; + sym->st_shndx = st_shndx; + sym->st_info = st_info; + + int ret = scf_vector_add(symtab, sym); + if (ret < 0) { + if (sym->name) + free(sym->name); + free(sym); + scf_loge("\n"); + return ret; + } + } + + return 0; +} + +int scf_symtab_add_rela(scf_vector_t* relas, scf_vector_t* symtab, scf_rela_t* r, const char* name, uint16_t st_shndx) +{ + scf_elf_rela_t* rela; + scf_elf_sym_t* sym; + + int ret; + int i; + + for (i = 0; i < symtab->size; i++) { + sym = symtab->data[i]; + + if (!sym->name) + continue; + + if (!strcmp(name, sym->name)) + break; + } + + if (i == symtab->size) { + ret = scf_symtab_add_sym(symtab, name, 0, 0, st_shndx, ELF64_ST_INFO(STB_GLOBAL, STT_NOTYPE)); + if (ret < 0) { + scf_loge("\n"); + return ret; + } + } + + scf_logd("rela: %s, offset: %ld\n", name, r->text_offset); + + rela = calloc(1, sizeof(scf_elf_rela_t)); + if (!rela) + return -ENOMEM; + + rela->name = (char*)name; + rela->r_offset = r->text_offset; + rela->r_info = ELF64_R_INFO(i + 1, r->type); + rela->r_addend = r->addend; + + ret = scf_vector_add(relas, rela); + if (ret < 0) { + free(rela); + return ret; + } + + return 0; +} diff --git a/js/parse/scf_symtab.h b/js/parse/scf_symtab.h new file mode 100644 index 0000000..dcab871 --- /dev/null +++ b/js/parse/scf_symtab.h @@ -0,0 +1,37 @@ +#ifndef SCF_SYMTAB_H +#define SCF_SYMTAB_H + +#include"scf_elf.h" +#include"scf_instruction.h" + +int scf_symtab_add_sym(scf_vector_t* symtab, const char* name, + uint64_t st_size, + Elf64_Addr st_value, + uint16_t st_shndx, + uint8_t st_info); + +int scf_symtab_add_rela(scf_vector_t* relas, scf_vector_t* symtab, scf_rela_t* r, const char* name, uint16_t st_shndx); + +#define ADD_SECTION_SYMBOL(symtab, sh_index, sh_name) \ + do { \ + int ret = scf_symtab_add_sym(symtab, sh_name, 0, 0, sh_index, ELF64_ST_INFO(STB_LOCAL, STT_SECTION)); \ + if (ret < 0) { \ + scf_loge("\n"); \ + return ret; \ + } \ + } while (0) + +static int __symtab_sort_cmp(const void* v0, const void* v1) +{ + const scf_elf_sym_t* sym0 = *(const scf_elf_sym_t**)v0; + const scf_elf_sym_t* sym1 = *(const scf_elf_sym_t**)v1; + + if (STB_LOCAL == ELF64_ST_BIND(sym0->st_info)) { + if (STB_GLOBAL == ELF64_ST_BIND(sym1->st_info)) + return -1; + } else if (STB_LOCAL == ELF64_ST_BIND(sym1->st_info)) + return 1; + return 0; +} + +#endif diff --git a/js/util/scf_string.c b/js/util/scf_string.c index c73f9a2..83c8197 100644 --- a/js/util/scf_string.c +++ b/js/util/scf_string.c @@ -20,7 +20,7 @@ scf_string_t* scf_string_alloc() return s; } -scf_string_t* scf_string_clone(scf_string_t* s) +scf_string_t* scf_string_clone(const scf_string_t* s) { if (!s) return NULL; diff --git a/js/util/scf_string.h b/js/util/scf_string.h index 082d2b5..16b07a8 100644 --- a/js/util/scf_string.h +++ b/js/util/scf_string.h @@ -12,7 +12,7 @@ typedef struct { scf_string_t* scf_string_alloc(); -scf_string_t* scf_string_clone(scf_string_t* s); +scf_string_t* scf_string_clone(const scf_string_t* s); scf_string_t* scf_string_cstr(const char* str); diff --git a/ui/Makefile b/ui/Makefile index 36893bd..a56faec 100644 --- a/ui/Makefile +++ b/ui/Makefile @@ -69,6 +69,7 @@ CFILES += ../ffmpeg/abc_avio.c CFILES += ../ffmpeg/abc_filter.c CFILES += ../js/util/scf_string.c +CFILES += ../js/util/scf_rbtree.c CFILES += ../js/util/scf_graph.c CFILES += ../js/lex/scf_lex.c CFILES += ../js/lex/scf_lex_util.c @@ -76,6 +77,7 @@ CFILES += ../js/lex/scf_lex_util.c CFILES += ../js/parse/main.c CFILES += ../js/parse/scf_parse_util.c CFILES += ../js/parse/scf_parse.c +CFILES += ../js/parse/scf_symtab.c CFILES += ../js/parse/scf_operator_handler_semantic.c CFILES += ../js/parse/scf_operator_handler_expr.c CFILES += ../js/parse/scf_operator_handler_const.c diff --git a/ui/abc_layout.c b/ui/abc_layout.c index 28689e0..f7773e0 100644 --- a/ui/abc_layout.c +++ b/ui/abc_layout.c @@ -249,12 +249,13 @@ int abc_layout_root(abc_ctx_t* ctx, abc_obj_t* root, int width, int height) || ABC_HTML_LINK == root->type) return 0; - if (!root->css_use && ABC_CORE_TEXT != root->type) { - root->css_use = 1; - + if (!root->css_used && ABC_CORE_TEXT != root->type) + { int ret = abc_css_use(ctx->current, root); if (ret < 0) return ret; + + root->css_used = 1; } abc_attr_t* attr; diff --git a/ui/abc_layout_text.c b/ui/abc_layout_text.c index 1a4e299..540e5c0 100644 --- a/ui/abc_layout_text.c +++ b/ui/abc_layout_text.c @@ -211,13 +211,8 @@ int abc_layout_text(abc_ctx_t* ctx, abc_obj_t* obj, int width, int height) return 0; if (parent->content && !parent->text) { - if (obj->content) { - int ret = scf_string_cat(parent->content, obj->content); - if (ret < 0) - return ret; - + if (obj->content) scf_string_free(obj->content); - } obj->content = parent->content; parent->content = NULL; diff --git a/ui/main.c b/ui/main.c index 50a81fa..0c49f4c 100644 --- a/ui/main.c +++ b/ui/main.c @@ -99,8 +99,8 @@ static int __do_button_move(abc_ctx_t* ctx, int x, int y) prev->mouse_move_x = -1; prev->mouse_move_y = -1; - prev->css_use = 0; - prev->clicked = 0; + prev->css_used = 0; + prev->clicked = 0; ret = 1; } @@ -158,7 +158,7 @@ static int __do_button_move(abc_ctx_t* ctx, int x, int y) ret |= abc_css_active(obj, ABC_CSS_HOVER); ctx->current->current = obj; - obj->css_use = 0; + obj->css_used = 0; } return ret; @@ -216,7 +216,7 @@ static int __do_button_release(abc_ctx_t* ctx, int x, int y) abc_css_clear (obj, ABC_CSS_LINK, ABC_CSS_ACTIVE); abc_css_active(obj, ABC_CSS_VISITED); - obj->css_use = 0; + obj->css_used = 0; scf_logd("obj: %s, x: %d, y: %d, w: %d, h: %d, event x: %d, y: %d\n", obj->keys[0], obj->x, obj->y, obj->w, obj->h, x, y); @@ -386,7 +386,7 @@ static gboolean button_press_event(GtkWidget* self, GdkEventButton* event, gpoin abc_css_clear (obj, ABC_CSS_LINK, ABC_CSS_ACTIVE); abc_css_active(obj, ABC_CSS_ACTIVE); - obj->css_use = 0; + obj->css_used = 0; gtk_gl_area_queue_render(ctx->gl_area); } @@ -448,12 +448,13 @@ static gboolean key_press_event(GtkWidget* self, GdkEventKey* event, gpointer us static gboolean button_move_event(GtkWidget* self, GdkEventMotion* event, gpointer user_data) { - abc_ctx_t* ctx = user_data; - abc_obj_t* obj; + abc_ctx_t* ctx = user_data; + abc_html_t* html = ctx->current; + abc_obj_t* obj; - if (ctx->current->io.download && ctx->current->root) + if (html->io.download && html->root) { - obj = abc_obj_find(ctx->current->root, event->x, event->y); + obj = abc_obj_find(html->root, event->x, event->y); if (obj) { obj->mouse_move_x = event->x; obj->mouse_move_y = event->y; @@ -469,37 +470,67 @@ static gboolean button_move_event(GtkWidget* self, GdkEventMotion* event, gpoint static gboolean timer_handler(gpointer user_data) { - abc_ctx_t* ctx = user_data; - abc_obj_t* obj; + abc_ctx_t* ctx = user_data; + abc_html_t* html = ctx->current; + abc_obj_t* obj; - if (ctx->current) { - if (!ctx->current->io.download) + if (html) { + if (!html->io.download) return TRUE; - if (!ctx->current->root) { - int ret = abc_html_parse(ctx->current); + int render_flag = 0; + + if (!html->root) { + int ret = abc_html_parse(html); if (ret < 0) { - abc_obj_free(ctx->current->root); - ctx->current->root = NULL; + abc_obj_free(html->root); + html->root = NULL; return TRUE; } - ctx->current->root->gtk_builder = ctx->builder; - ctx->current->current = ctx->current->root; + html->root->gtk_builder = ctx->builder; + html->current = html->root; gtk_widget_set_sensitive(GTK_WIDGET(ctx->back), TRUE); - gtk_gl_area_queue_render(ctx->gl_area); + render_flag = 1; + } + + while (1) { + abc_timer_t* timer = (abc_timer_t*) scf_rbtree_min(&html->timers, html->timers.root); + if (!timer || timer->usec > gettime()) + break; + + scf_rbtree_delete(&html->timers, (scf_rbtree_node_t*)timer); + + if (timer->func) { + timer->func(timer->argc, timer->argv); + render_flag = 1; + } + + if (html->js_auto_freep && html->js_release) { + int i; + for (i = 2; i < timer->argc; i++) { + if (timer->argv[i]) + html->js_auto_freep(&(timer->argv[i]), 1, html->js_release); + } + } + + free(timer); + timer = NULL; } - obj = ctx->current->current; + obj = html->current; if (obj) { obj->jiffies++; if (ABC_HTML_INPUT == obj->type && 0 == obj->jiffies % 64) - gtk_gl_area_queue_render(ctx->gl_area); + render_flag = 1; } - if (ctx->current->has_video) + if (html->has_video) + render_flag = 1; + + if (render_flag) gtk_gl_area_queue_render(ctx->gl_area); } -- 2.25.1