From ef2ed442f553f2666e2483808690e4dc0fed4c9d Mon Sep 17 00:00:00 2001 From: "yu.dongliang" <18588496441@163.com> Date: Wed, 2 Oct 2024 17:07:57 +0800 Subject: [PATCH] optimize switch-case for "const literal string" --- core/scf_3ac.c | 1 - core/scf_expr.c | 2 +- core/scf_node.c | 59 ++++++++++++--------------- core/scf_operator_handler_3ac.c | 16 +++++--- examples/switch_string.c | 5 ++- parse/scf_operator_handler_semantic.c | 8 ++++ 6 files changed, 49 insertions(+), 42 deletions(-) diff --git a/core/scf_3ac.c b/core/scf_3ac.c index 3a13aff..4fbaf37 100644 --- a/core/scf_3ac.c +++ b/core/scf_3ac.c @@ -437,7 +437,6 @@ scf_3ac_code_t* scf_3ac_jmp_code(int type, scf_label_t* l, scf_node_t* err) } if (scf_vector_add(c->dsts, dst) < 0) { - scf_3ac_operand_free(dst); scf_3ac_code_free(c); return NULL; diff --git a/core/scf_expr.c b/core/scf_expr.c index b2377c3..35c8eb1 100644 --- a/core/scf_expr.c +++ b/core/scf_expr.c @@ -19,8 +19,8 @@ scf_expr_t* scf_expr_alloc() int scf_expr_copy(scf_node_t* e2, scf_node_t* e) { scf_node_t* node; - int i; + for (i = 0; i < e->nb_nodes; i++) { node = scf_node_clone(e->nodes[i]); diff --git a/core/scf_node.c b/core/scf_node.c index 03de08d..89d68ad 100644 --- a/core/scf_node.c +++ b/core/scf_node.c @@ -66,52 +66,47 @@ _failed: scf_node_t* scf_node_clone(scf_node_t* node) { - scf_node_t* node2 = calloc(1, sizeof(scf_node_t)); - if (!node2) + scf_node_t* dst = calloc(1, sizeof(scf_node_t)); + if (!dst) return NULL; if (scf_type_is_var(node->type)) { - node2->var = scf_variable_ref(node->var); - if (!node2->var) - goto _failed; - - } else if (SCF_LABEL == node->type) { - node2->label = node->label; + dst->var = scf_variable_ref(node->var); + if (!dst->var) + goto failed; - } else { + } else if (SCF_LABEL == node->type) + dst->label = node->label; + else { if (node->w) { - node2->w = scf_lex_word_clone(node->w); - if (!node2->w) - goto _failed; - - } else - node2->w = NULL; + dst->w = scf_lex_word_clone(node->w); + if (!dst->w) + goto failed; + } } if (node->debug_w) { - node2->debug_w = scf_lex_word_clone(node->debug_w); + dst ->debug_w = scf_lex_word_clone(node->debug_w); - if (!node2->debug_w) - goto _failed; + if (!dst->debug_w) + goto failed; } - node2->type = node->type; + dst->type = node->type; - node2->root_flag = node->root_flag; - node2->file_flag = node->file_flag; - node2->class_flag = node->class_flag; - node2->union_flag = node->union_flag; - node2->define_flag = node->define_flag; - node2->const_flag = node->const_flag; - node2->split_flag = node->split_flag; - node2->semi_flag = node->semi_flag; - - scf_logd("node: %p, node->type: %d\n", node, node->type); - return node; + dst->root_flag = node->root_flag; + dst->file_flag = node->file_flag; + dst->class_flag = node->class_flag; + dst->union_flag = node->union_flag; + dst->define_flag = node->define_flag; + dst->const_flag = node->const_flag; + dst->split_flag = node->split_flag; + dst->semi_flag = node->semi_flag; + return dst; -_failed: - scf_node_free(node); +failed: + scf_node_free(dst); return NULL; } diff --git a/core/scf_operator_handler_3ac.c b/core/scf_operator_handler_3ac.c index e5c3897..6aa7db5 100644 --- a/core/scf_operator_handler_3ac.c +++ b/core/scf_operator_handler_3ac.c @@ -1135,22 +1135,26 @@ static int _scf_op_switch(scf_ast_t* ast, scf_node_t** nodes, int nb_nodes, void while (e2 && SCF_OP_EXPR == e2->type) e2 = e2->nodes[0]; + if (SCF_OP_CALL == e2->type) { + assert(3 == e2->nb_nodes); + e2->nodes[1]->_3ac_done = 1; + } + if (_scf_expr_calculate_internal(ast, e2, d) < 0) { scf_loge("\n"); return -1; } - 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}; + scf_node_t* srcs[2] = {e, e2}; + if (SCF_OP_CALL != e2->type) cmp = scf_3ac_code_NN(SCF_OP_3AC_CMP, NULL, 0, srcs, 2); - } - scf_list_add_tail(d->_3ac_list_head, &cmp->list); + else + cmp = scf_3ac_code_NN(SCF_OP_3AC_TEQ, NULL, 0, &e2, 1); 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/examples/switch_string.c b/examples/switch_string.c index 7c5844a..343b05c 100644 --- a/examples/switch_string.c +++ b/examples/switch_string.c @@ -3,9 +3,10 @@ int strcmp(const char* s1, const char* s2); int main() { - const char* s = "123"; + char* argv[2] = {"hello", "123"}; + + switch (argv[1]) { - switch (s) { case "456": printf("0\n"); case "123": diff --git a/parse/scf_operator_handler_semantic.c b/parse/scf_operator_handler_semantic.c index f37493c..87eb380 100644 --- a/parse/scf_operator_handler_semantic.c +++ b/parse/scf_operator_handler_semantic.c @@ -1287,6 +1287,7 @@ static int _scf_op_semantic_while(scf_ast_t* ast, scf_node_t** nodes, int nb_nod 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) { scf_function_t* f = NULL; + scf_variable_t* v = NULL; scf_expr_t* e2; scf_expr_t* e3; scf_expr_t* e4; @@ -1305,6 +1306,13 @@ static int __switch_for_string(scf_ast_t* ast, scf_node_t* parent, scf_node_t* c if (!e1) return -ENOMEM; + if (_scf_expr_calculate(ast, e2, &v) < 0) { + scf_expr_free(e2); + return -1; + } + scf_variable_free(v); + v = NULL; + e3 = scf_expr_alloc(); if (!e3) { scf_expr_free(e2); -- 2.25.1