From: yu.dongliang <18588496441@163.com> Date: Wed, 2 Oct 2024 04:30:07 +0000 (+0800) Subject: support "const literal string" in 'case' for 'switch' X-Git-Url: http://baseworks.info/?a=commitdiff_plain;h=6c90ed24c758e6ba85ebed2f6cdc13c84233bdc5;p=scf.git support "const literal string" in 'case' for 'switch' --- diff --git a/core/scf_3ac.c b/core/scf_3ac.c index 9d82a62..3a13aff 100644 --- a/core/scf_3ac.c +++ b/core/scf_3ac.c @@ -450,16 +450,16 @@ static void _3ac_print_node(scf_node_t* node) { if (scf_type_is_var(node->type)) { if (node->var->w) { - printf("v_%d_%d/%s", - node->var->w->line, node->var->w->pos, node->var->w->text->data); + printf("v_%d_%d/%s/%#lx", + node->var->w->line, node->var->w->pos, node->var->w->text->data, 0xffff & (uintptr_t)node->var); } else { printf("v_%#lx", 0xffff & (uintptr_t)node->var); } } else if (scf_type_is_operator(node->type)) { if (node->result) { if (node->result->w) { - printf("v_%d_%d/%s", - node->result->w->line, node->result->w->pos, node->result->w->text->data); + printf("v_%d_%d/%s/%#lx", + node->result->w->line, node->result->w->pos, node->result->w->text->data, 0xffff & (uintptr_t)node->result); } else printf("v/%#lx", 0xffff & (uintptr_t)node->result); } diff --git a/core/scf_basic_block.c b/core/scf_basic_block.c index 786e3b8..8e39c9b 100644 --- a/core/scf_basic_block.c +++ b/core/scf_basic_block.c @@ -194,10 +194,10 @@ void scf_basic_block_print(scf_basic_block_t* bb, scf_list_t* sentinel) if (bb) { #define SCF_BB_PRINT(h) \ do { \ - scf_list_t* l; \ - for (l = scf_list_head(&bb->h); l != scf_list_sentinel(&bb->h); \ - l = scf_list_next(l)) { \ - scf_3ac_code_t* c = scf_list_data(l, scf_3ac_code_t, list); \ + scf_3ac_code_t* c; \ + scf_list_t* l; \ + for (l = scf_list_head(&bb->h); l != scf_list_sentinel(&bb->h); l = scf_list_next(l)) { \ + c = scf_list_data(l, scf_3ac_code_t, list); \ scf_3ac_code_print(c, sentinel); \ } \ } while (0) @@ -259,7 +259,7 @@ void scf_basic_block_print_list(scf_list_t* h) for (l = scf_list_head(h); l != scf_list_sentinel(h); l = scf_list_next(l)) { bb = scf_list_data(l, scf_basic_block_t, list); - printf("\033[33mbasic_block: %p, index: %d, dfo: %d, cmp_flag: %d, call_flag: %d, group: %d, loop: %d, dereference_flag: %d, ret_flag: %d\033[0m\n", + printf("\033[34mbasic_block: %p, index: %d, dfo: %d, cmp_flag: %d, call_flag: %d, group: %d, loop: %d, dereference_flag: %d, ret_flag: %d\033[0m\n", bb, bb->index, bb->dfo, bb->cmp_flag, bb->call_flag, bb->group_flag, bb->loop_flag, bb->dereference_flag, bb->ret_flag); scf_basic_block_print(bb, sentinel); @@ -280,12 +280,7 @@ void scf_basic_block_print_list(scf_list_t* h) printf("next : %p, index: %d\n", bb2, bb2->index); } } -#if 0 - if (bb->dominators_normal) { - for (i = 0; i < bb->dominators_normal->size; i++) - printf("dominator: %p\n", bb->dominators_normal->data[i]); - } -#endif + if (bb->dn_status_initeds) { printf("inited: \n"); for (i = 0; i < bb->dn_status_initeds->size; i++) { @@ -295,7 +290,7 @@ void scf_basic_block_print_list(scf_list_t* h) } printf("\n"); } -#if 1 + if (bb->ds_malloced) { printf("auto gc: \n"); for (i = 0; i < bb->ds_malloced->size; i++) { @@ -307,7 +302,7 @@ void scf_basic_block_print_list(scf_list_t* h) } printf("\n"); } -#endif + if (bb->entry_dn_actives) { for (i = 0; i < bb->entry_dn_actives->size; i++) { dn = bb->entry_dn_actives->data[i]; diff --git a/core/scf_expr.c b/core/scf_expr.c index c3c94ac..b2377c3 100644 --- a/core/scf_expr.c +++ b/core/scf_expr.c @@ -3,17 +3,12 @@ scf_expr_t* scf_expr_alloc() { scf_expr_t* e = calloc(1, sizeof(scf_expr_t)); - if (!e) { - scf_loge("expr alloc failed"); + if (!e) return NULL; - } e->nodes = calloc(1, sizeof(scf_node_t*)); if (!e->nodes) { - scf_loge("expr nodes alloc failed"); - free(e); - e = NULL; return NULL; } @@ -29,7 +24,6 @@ int scf_expr_copy(scf_node_t* e2, scf_node_t* e) for (i = 0; i < e->nb_nodes; i++) { node = scf_node_clone(e->nodes[i]); - if (!node) return -ENOMEM; @@ -66,7 +60,7 @@ void scf_expr_free(scf_expr_t* e) } } -static int _scf_expr_node_add_node(scf_node_t** pparent, scf_node_t* child) +static int __expr_node_add_node(scf_node_t** pparent, scf_node_t* child) { scf_node_t* parent = *pparent; if (!parent) { @@ -79,10 +73,10 @@ static int _scf_expr_node_add_node(scf_node_t** pparent, scf_node_t* child) if (parent->op->nb_operands > parent->nb_nodes) return scf_node_add_child(parent, child); - else { - assert(parent->nb_nodes >= 1); - return _scf_expr_node_add_node(&(parent->nodes[parent->nb_nodes - 1]), child); - } + + assert(parent->nb_nodes >= 1); + return __expr_node_add_node(&(parent->nodes[parent->nb_nodes - 1]), child); + } else if (parent->priority < child->priority) { assert(child->op); @@ -90,37 +84,34 @@ static int _scf_expr_node_add_node(scf_node_t** pparent, scf_node_t* child) assert(child->op->nb_operands > child->nb_nodes); child->parent = parent->parent; - if (scf_node_add_child(child, parent) < 0) { - scf_loge("expr nodes alloc failed"); + if (scf_node_add_child(child, parent) < 0) return -1; - } + *pparent = child; return 0; - } else { - // parent->priority == child->priority - assert(parent->op); - assert(child->op); + } - if (SCF_OP_ASSOCIATIVITY_LEFT == child->op->associativity) { - if (child->op->nb_operands > 0) - assert(child->op->nb_operands > child->nb_nodes); - - child->parent = parent->parent; - scf_node_add_child(child, parent); // add parent to child's child node - *pparent = child; // child is the new parent node - return 0; - } else { - if (parent->op->nb_operands > parent->nb_nodes) - return scf_node_add_child(parent, child); - else { - assert(parent->nb_nodes >= 1); - return _scf_expr_node_add_node(&(parent->nodes[parent->nb_nodes - 1]), child); - } - } + // parent->priority == child->priority + assert(parent->op); + assert(child->op); + + if (SCF_OP_ASSOCIATIVITY_LEFT == child->op->associativity) { + if (child->op->nb_operands > 0) + assert(child->op->nb_operands > child->nb_nodes); + + child->parent = parent->parent; + + scf_node_add_child(child, parent); // add parent to child's child node + + *pparent = child; // child is the new parent node + return 0; } - scf_loge("\n"); - return -1; + if (parent->op->nb_operands > parent->nb_nodes) + return scf_node_add_child(parent, child); + + assert(parent->nb_nodes >= 1); + return __expr_node_add_node(&(parent->nodes[parent->nb_nodes - 1]), child); } int scf_expr_add_node(scf_expr_t* e, scf_node_t* node) @@ -128,10 +119,10 @@ int scf_expr_add_node(scf_expr_t* e, scf_node_t* node) assert(e); assert(node); - if (scf_type_is_var(node->type)) { + if (scf_type_is_var(node->type)) node->priority = -1; - } else if (scf_type_is_operator(node->type)) { + else if (scf_type_is_operator(node->type)) { node->op = scf_find_base_operator_by_type(node->type); if (!node->op) { @@ -144,13 +135,31 @@ int scf_expr_add_node(scf_expr_t* e, scf_node_t* node) return -1; } - if (_scf_expr_node_add_node(&(e->nodes[0]), node) < 0) { - scf_loge("\n"); + if (__expr_node_add_node(&(e->nodes[0]), node) < 0) return -1; - } e->nodes[0]->parent = e; e->nb_nodes = 1; return 0; } +void scf_expr_simplify(scf_expr_t** pe) +{ + scf_expr_t** pp = pe; + scf_expr_t* e; + + while (SCF_OP_EXPR == (*pp)->type) { + e = *pp; + pp = &(e->nodes[0]); + } + + if (pp != pe) { + e = *pp; + *pp = NULL; + + e->parent = (*pe)->parent; + + scf_expr_free(*pe); + *pe = e; + } +} diff --git a/core/scf_expr.h b/core/scf_expr.h index 7029b68..de8ca60 100644 --- a/core/scf_expr.h +++ b/core/scf_expr.h @@ -3,12 +3,13 @@ #include"scf_node.h" -typedef scf_node_t scf_expr_t; // expr is a node +typedef scf_node_t scf_expr_t; // expr is a node -scf_expr_t* scf_expr_alloc(); -scf_expr_t* scf_expr_clone(scf_expr_t* e); -void scf_expr_free(scf_expr_t* expr); -int scf_expr_add_node(scf_expr_t* expr, scf_node_t* node); +scf_expr_t* scf_expr_alloc(); +scf_expr_t* scf_expr_clone(scf_expr_t* e); +void scf_expr_free (scf_expr_t* e); -#endif +int scf_expr_add_node(scf_expr_t* e, scf_node_t* node); +void scf_expr_simplify(scf_expr_t** pe); +#endif diff --git a/core/scf_node.c b/core/scf_node.c index dd111da..03de08d 100644 --- a/core/scf_node.c +++ b/core/scf_node.c @@ -134,10 +134,8 @@ int scf_node_add_child(scf_node_t* parent, scf_node_t* child) return -EINVAL; void* p = realloc(parent->nodes, sizeof(scf_node_t*) * (parent->nb_nodes + 1)); - if (!p) { - scf_loge("realloc failed\n"); + if (!p) return -ENOMEM; - } parent->nodes = p; parent->nodes[parent->nb_nodes++] = child; diff --git a/core/scf_operator_handler_3ac.c b/core/scf_operator_handler_3ac.c index 5dcd74b..e5c3897 100644 --- a/core/scf_operator_handler_3ac.c +++ b/core/scf_operator_handler_3ac.c @@ -1140,12 +1140,17 @@ static int _scf_op_switch(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, void return -1; } - scf_node_t* srcs[2] = {e, e2}; + if (SCF_OP_CALL == e2->type) + cmp = scf_3ac_code_NN(SCF_OP_3AC_TEQ, NULL, 0, &e2, 1); + else { + scf_node_t* srcs[2] = {e, e2}; + + cmp = scf_3ac_code_NN(SCF_OP_3AC_CMP, NULL, 0, srcs, 2); + } + scf_list_add_tail(d->_3ac_list_head, &cmp->list); - cmp = scf_3ac_code_NN(SCF_OP_3AC_CMP, NULL, 0, srcs, 2); jnot = scf_3ac_jmp_code(SCF_OP_3AC_JNZ, NULL, NULL); - scf_list_add_tail(d->_3ac_list_head, &cmp->list); scf_list_add_tail(d->_3ac_list_head, &jnot->list); scf_vector_add(up_branch_ops->_breaks, jnot); diff --git a/core/scf_optimizer.c b/core/scf_optimizer.c index ad0dbfd..6b89c9f 100644 --- a/core/scf_optimizer.c +++ b/core/scf_optimizer.c @@ -161,6 +161,7 @@ int scf_optimize(scf_ast_t* ast, scf_vector_t* functions) if (!f->node.define_flag) continue; + printf("\n"); scf_logi("------- %s() ------\n", f->node.w->text->data); scf_basic_block_print_list(&f->basic_block_list_head); diff --git a/core/scf_type_cast.c b/core/scf_type_cast.c index be31fb6..15e0c73 100644 --- a/core/scf_type_cast.c +++ b/core/scf_type_cast.c @@ -156,11 +156,9 @@ int scf_type_cast_check(scf_ast_t* ast, scf_variable_t* dst, scf_variable_t* src if (scf_type_is_integer(dst->type)) { - if (dst->size < src->size) { - scf_logw("type cast %s -> %s discard bits\n", - src->w->text->data, dst->w->text->data); - } - + if (dst->size < src->size) + scf_logw("type cast %s -> %s discard bits, file: %s, line: %d\n", + src->w->text->data, dst->w->text->data, src->w->file->data, src->w->line); return 0; } } @@ -178,9 +176,9 @@ failed: dst_type = scf_variable_type_name(ast, dst); src_type = scf_variable_type_name(ast, src); - scf_loge("type cast '%s -> %s' with different type: from '%s' to '%s'\n", + scf_loge("type cast '%s -> %s' with different type: from '%s' to '%s', file: %s, line: %d\n", src->w->text->data, dst->w->text->data, - src_type->data, dst_type->data); + src_type->data, dst_type->data, src->w->file->data, src->w->line); scf_string_free(dst_type); scf_string_free(src_type); diff --git a/core/scf_variable.h b/core/scf_variable.h index 564ab14..7d0360d 100644 --- a/core/scf_variable.h +++ b/core/scf_variable.h @@ -128,6 +128,11 @@ static inline int scf_variable_const_string(scf_variable_t* v) && 0 == v->nb_dimentions; } +static inline int scf_variable_string(scf_variable_t* v) +{ + return SCF_VAR_CHAR == v->type && 1 == v->nb_pointers + v->nb_dimentions; +} + static inline int scf_variable_float(scf_variable_t* v) { return scf_type_is_float(v->type) && 0 == v->nb_pointers && 0 == v->nb_dimentions; diff --git a/examples/switch_string.c b/examples/switch_string.c new file mode 100644 index 0000000..7c5844a --- /dev/null +++ b/examples/switch_string.c @@ -0,0 +1,20 @@ +int printf(const char* fmt, ...); +int strcmp(const char* s1, const char* s2); + +int main() +{ + const char* s = "123"; + + switch (s) { + case "456": + printf("0\n"); + case "123": + printf("1\n"); + break; + default: + printf("default\n"); + break; + }; + + return 0; +} diff --git a/native/x64/scf_x64.c b/native/x64/scf_x64.c index 8ff7f3c..c7d2964 100644 --- a/native/x64/scf_x64.c +++ b/native/x64/scf_x64.c @@ -250,7 +250,7 @@ static int _x64_function_finish(scf_function_t* f) local += 8; } - scf_logw("### local: %#x, local_vars_size: %#x, callee_saved_size: %#x\n", + scf_logd("### local: %#x, local_vars_size: %#x, callee_saved_size: %#x\n", local, f->local_vars_size, f->callee_saved_size); inst = x64_make_inst_I2E(sub, rsp, (uint8_t*)&local, 4); @@ -1165,6 +1165,7 @@ int scf_x64_select_inst(scf_native_t* ctx, scf_function_t* f) for (i = 0; i < local_vars->size; i++) { scf_variable_t* 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); @@ -1194,4 +1195,3 @@ scf_native_ops_t native_ops_x64 = { .select_inst = scf_x64_select_inst, }; - diff --git a/parse/scf_dfa_for.c b/parse/scf_dfa_for.c index 0258ced..9a7eeb2 100644 --- a/parse/scf_dfa_for.c +++ b/parse/scf_dfa_for.c @@ -280,7 +280,7 @@ static int _for_action_end(scf_dfa_t* dfa, scf_vector_t* words, void* data) d->current_node = fd->parent_node; - scf_logi("\033[31m for: %d, fd: %p, s->size: %d\033[0m\n", fd->_for->w->line, fd, s->size); + scf_logi("for: %d, fd: %p, s->size: %d\n", fd->_for->w->line, fd, s->size); free(fd); fd = NULL; diff --git a/parse/scf_dfa_if.c b/parse/scf_dfa_if.c index cd2f75b..ad3666e 100644 --- a/parse/scf_dfa_if.c +++ b/parse/scf_dfa_if.c @@ -195,7 +195,7 @@ static int _if_action_end(scf_dfa_t* dfa, scf_vector_t* words, void* data) d->current_node = ifd->parent_node; - scf_logi("\033[31m if: %d, ifd: %p, s->size: %d\033[0m\n", ifd->_if->w->line, ifd, s->size); + scf_logi("if: %d, ifd: %p, s->size: %d\n", ifd->_if->w->line, ifd, s->size); free(ifd); ifd = NULL; diff --git a/parse/scf_dfa_switch.c b/parse/scf_dfa_switch.c index e95de06..fa22c3a 100644 --- a/parse/scf_dfa_switch.c +++ b/parse/scf_dfa_switch.c @@ -30,16 +30,12 @@ static int _switch_action_switch(scf_dfa_t* dfa, scf_vector_t* words, void* data scf_stack_t* s = d->module_datas[dfa_module_switch.index]; scf_node_t* _switch = scf_node_alloc(w, SCF_OP_SWITCH, NULL); - if (!_switch) { - scf_loge("node alloc failed\n"); - return SCF_DFA_ERROR; - } + if (!_switch) + return -ENOMEM; dfa_switch_data_t* sd = calloc(1, sizeof(dfa_switch_data_t)); - if (!sd) { - scf_loge("module data alloc failed\n"); - return SCF_DFA_ERROR; - } + if (!sd) + return -ENOMEM; if (d->current_node) scf_node_add_child(d->current_node, _switch); @@ -192,7 +188,7 @@ static int _switch_action_end(scf_dfa_t* dfa, scf_vector_t* words, void* data) d->current_node = sd->parent_node; - scf_logi("\033[31m switch: %d, sd: %p, s->size: %d\033[0m\n", sd->_switch->w->line, sd, s->size); + scf_logi("switch: %d, sd: %p, s->size: %d\n", sd->_switch->w->line, sd, s->size); free(sd); sd = NULL; diff --git a/parse/scf_dfa_while.c b/parse/scf_dfa_while.c index 77aa343..1098618 100644 --- a/parse/scf_dfa_while.c +++ b/parse/scf_dfa_while.c @@ -132,7 +132,7 @@ static int _while_action_end(scf_dfa_t* dfa, scf_vector_t* words, void* data) d->current_node = wd->parent_node; - scf_logi("\033[31m while: %d, wd: %p, s->size: %d\033[0m\n", wd->_while->w->line, wd, s->size); + scf_logi("while: %d, wd: %p, s->size: %d\n", wd->_while->w->line, wd, s->size); free(wd); wd = NULL; diff --git a/parse/scf_operator_handler_const.c b/parse/scf_operator_handler_const.c index 7039425..0d53b21 100644 --- a/parse/scf_operator_handler_const.c +++ b/parse/scf_operator_handler_const.c @@ -40,13 +40,13 @@ static int _scf_expr_calculate_internal(scf_ast_t* ast, scf_node_t* node, void* return __scf_op_const_call(ast, (scf_function_t*)node, data); if (0 == node->nb_nodes) { + + if (scf_type_is_var(node->type) && node->var->w) + scf_logd("w: %s\n", node->var->w->text->data); + assert(scf_type_is_var(node->type) || SCF_LABEL == node->type || node->split_flag); - - if (scf_type_is_var(node->type) && node->var->w) { - scf_logd("w: %s\n", node->var->w->text->data); - } return 0; } @@ -327,30 +327,40 @@ static int _scf_op_const_switch(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes scf_handler_data_t* d = data; scf_variable_t* r = NULL; scf_expr_t* e = nodes[0]; + scf_expr_t* e2; + scf_node_t* b = nodes[1]; + scf_node_t* child; assert(SCF_OP_EXPR == e->type); if (_scf_expr_calculate_internal(ast, e, &r) < 0) return -1; - if (_scf_op_const_node(ast, nodes[1], d) < 0) - return -1; + int i; + for (i = 0; i < b->nb_nodes; i++) { + child = b->nodes[i]; + + if (SCF_OP_CASE == child->type) { + assert(1 == child->nb_nodes); + + e = child->nodes[0]; + + assert(SCF_OP_EXPR == e->type); + + if (_scf_expr_calculate_internal(ast, e, &r) < 0) + return -1; + + } else { + if (_scf_op_const_node(ast, child, d) < 0) + return -1; + } + } return 0; } static int _scf_op_const_case(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, void* data) { - assert(1 == nb_nodes); - - scf_handler_data_t* d = data; - scf_variable_t* r = NULL; - scf_expr_t* e = nodes[0]; - - assert(SCF_OP_EXPR == e->type); - - if (_scf_expr_calculate_internal(ast, e, &r) < 0) - return -1; return 0; } @@ -453,20 +463,14 @@ static int _scf_op_const_expr(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, { assert(1 == nb_nodes); - scf_handler_data_t* d = data; - - scf_node_t* n = nodes[0]; scf_node_t* parent = nodes[0]->parent; + scf_node_t* node; - while (SCF_OP_EXPR == n->type) - n = n->nodes[0]; + scf_expr_simplify(&nodes[0]); - n->parent->nodes[0] = NULL; - scf_node_free(nodes[0]); - nodes[0] = n; - n->parent = parent; + node = nodes[0]; - int ret = _scf_expr_calculate_internal(ast, n, d); + int ret = _scf_expr_calculate_internal(ast, node, data); if (ret < 0) { scf_loge("\n"); return -1; @@ -475,8 +479,7 @@ static int _scf_op_const_expr(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, if (parent->result) scf_variable_free(parent->result); - scf_variable_t* v = _scf_operand_get(n); - + scf_variable_t* v = _scf_operand_get(node); if (v) parent->result = scf_variable_ref(v); else diff --git a/parse/scf_operator_handler_semantic.c b/parse/scf_operator_handler_semantic.c index 856030f..f37493c 100644 --- a/parse/scf_operator_handler_semantic.c +++ b/parse/scf_operator_handler_semantic.c @@ -1045,7 +1045,6 @@ static int _scf_op_semantic_block(scf_ast_t* ast, scf_node_t** nodes, int nb_nod ret = _scf_op_semantic_node(ast, node, d); if (ret < 0) { - scf_loge("\n"); ast->current_block = up; return -1; } @@ -1285,59 +1284,173 @@ static int _scf_op_semantic_while(scf_ast_t* ast, scf_node_t** nodes, int nb_nod return 0; } -static int _scf_op_semantic_switch(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, void* data) +static int __switch_for_string(scf_ast_t* ast, scf_node_t* parent, scf_node_t* child, scf_expr_t* e, scf_expr_t* e1, scf_handler_data_t* d) { - assert(2 == nb_nodes); - - scf_handler_data_t* d = data; - scf_variable_t* r = NULL; - scf_expr_t* e = nodes[0]; + scf_function_t* f = NULL; + scf_expr_t* e2; + scf_expr_t* e3; + scf_expr_t* e4; - assert(SCF_OP_EXPR == e->type); + int ret = scf_ast_find_function(&f, ast, "strcmp"); + if (ret < 0) + return ret; - if (_scf_expr_calculate(ast, e, &r) < 0) { - scf_loge("\n"); + if (!f) { + scf_loge("can't find function 'strcmp()' for compare const string, file: %s, line: %d\n", + parent->w->file->data, parent->w->line); return -1; } - if (!r || !scf_variable_integer(r)) { - scf_loge("\n"); - return -1; + e2 = scf_expr_clone(e); + if (!e1) + return -ENOMEM; + + e3 = scf_expr_alloc(); + if (!e3) { + scf_expr_free(e2); + return -ENOMEM; } - scf_variable_free(r); - r = NULL; - int ret = _scf_op_semantic_node(ast, nodes[1], d); + ret = scf_node_add_child(e3, e2); if (ret < 0) { - scf_loge("\n"); - return -1; + scf_expr_free(e2); + scf_expr_free(e3); + return ret; } + e2 = NULL; - return 0; + ret = scf_node_add_child(e3, e1); + if (ret < 0) { + scf_expr_free(e3); + return ret; + } + child->nodes[0] = NULL; + + e4 = scf_expr_alloc(); + if (!e4) { + scf_expr_free(e3); + return -ENOMEM; + } + + ret = scf_node_add_child(e4, e3); + if (ret < 0) { + scf_expr_free(e3); + scf_expr_free(e4); + return ret; + } + + child->nodes[0] = e4; + e4->parent = child; + + d->pret = &e3->result; + + return _semantic_add_call(ast, e3->nodes, e3->nb_nodes, d, f); } -static int _scf_op_semantic_case(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, void* data) +static int _scf_op_semantic_switch(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, void* data) { - assert(1 == nb_nodes); + assert(2 == nb_nodes); - scf_handler_data_t* d = data; - scf_variable_t* r = NULL; - scf_expr_t* e = nodes[0]; + scf_handler_data_t* d = data; + scf_variable_t** pret = d->pret; + scf_variable_t* v0 = NULL; + scf_variable_t* v1 = NULL; + scf_block_t* tmp = ast->current_block; + scf_expr_t* e = nodes[0]; + scf_node_t* b = nodes[1]; + scf_node_t* parent = nodes[0]->parent; + scf_node_t* child; + scf_expr_t* e1; - assert(SCF_OP_EXPR == e->type); + assert(SCF_OP_EXPR == e->type); + assert(SCF_OP_BLOCK == b->type); - if (_scf_expr_calculate(ast, e, &r) < 0) { - scf_loge("\n"); + if (_scf_expr_calculate(ast, e, &v0) < 0) return -1; - } - if (!r || !scf_variable_integer(r)) { - scf_loge("\n"); + if (!scf_variable_integer(v0) && !scf_variable_string(v0)) { + scf_loge("result of switch expr should be an integer or string, file: %s, line: %d\n", parent->w->file->data, parent->w->line); + scf_variable_free(v0); return -1; } - scf_variable_free(r); + ast->current_block = (scf_block_t*)b; + + int ret = -1; + int i; + + for (i = 0; i < b->nb_nodes; i++) { + child = b->nodes[i]; + + if (SCF_OP_CASE == child->type) { + assert(1 == child->nb_nodes); + + e1 = child->nodes[0]; + + assert(SCF_OP_EXPR == e1->type); + + ret = _scf_expr_calculate(ast, e1, &v1); + if (ret < 0) { + scf_variable_free(v0); + return ret; + } + + if (!scf_variable_const_integer(v1) && !scf_variable_const_string(v1)) { + ret = -1; + scf_loge("result of case expr should be const integer or const string, file: %s, line: %d\n", child->w->file->data, child->w->line); + goto error; + } + + if (!scf_variable_type_like(v0, v1)) { + + if (scf_type_cast_check(ast, v0, v1) < 0) { + ret = -1; + scf_loge("type of switch's expr is NOT same to the case's, file: %s, line: %d\n", child->w->file->data, child->w->line); + goto error; + } + + ret = _semantic_add_type_cast(ast, &(e1->nodes[0]), v0, e1->nodes[0]); + if (ret < 0) + goto error; + } + + if (scf_variable_const_string(v1)) { + + ret = __switch_for_string(ast, parent, child, e, e1, d); + if (ret < 0) + goto error; + } + + scf_variable_free(v1); + v1 = NULL; + + } else { + ret = _scf_op_semantic_node(ast, child, d); + if (ret < 0) { + scf_variable_free(v0); + return -1; + } + } + } + + ast->current_block = tmp; + + scf_variable_free(v0); + + d->pret = pret; return 0; + +error: + scf_variable_free(v0); + scf_variable_free(v1); + d->pret = pret; + return ret; +} + +static int _scf_op_semantic_case(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, void* data) +{ + scf_loge("\n"); + return -1; } static int _scf_op_semantic_default(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, void* data) @@ -1404,10 +1517,8 @@ static int __scf_op_semantic_call(scf_ast_t* ast, scf_function_t* f, void* data) // change the current block ast->current_block = (scf_block_t*)f; - if (_scf_op_semantic_block(ast, f->node.nodes, f->node.nb_nodes, d) < 0) { - scf_loge("\n"); + if (_scf_op_semantic_block(ast, f->node.nodes, f->node.nb_nodes, d) < 0) return -1; - } ast->current_block = tmp; return 0; diff --git a/parse/scf_parse.c b/parse/scf_parse.c index e0f889d..4fbda8e 100644 --- a/parse/scf_parse.c +++ b/parse/scf_parse.c @@ -1860,12 +1860,12 @@ static int _add_debug_sections(scf_parse_t* parse, scf_elf_context_t* elf) int scf_parse_compile_functions(scf_parse_t* parse, scf_vector_t* functions) { scf_function_t* f; - int i; + for (i = 0; i < functions->size; i++) { f = functions->data[i]; - scf_logi("i: %d, fname: %s, f->argv->size: %d, f->node.define_flag: %d, inline_flag: %d\n", + printf("%d, %s(), argv->size: %d, define_flag: %d, inline_flag: %d\n", i, f->node.w->text->data, f->argv->size, f->node.define_flag, f->inline_flag); if (!f->node.define_flag)