From: yu.dongliang <18588496441@163.com> Date: Mon, 24 Aug 2026 07:47:03 +0000 (+0800) Subject: support char array[] inited by const string like "hello", support base 8/16 const... X-Git-Url: http://baseworks.info/?a=commitdiff_plain;h=33baaea06584ca63d05441dbaa10243c85034773;p=scf.git support char array[] inited by const string like "hello", support base 8/16 const char in string. --- diff --git a/core/scf_optimizer_basic_block.c b/core/scf_optimizer_basic_block.c index bf8ac62..7ede6e8 100644 --- a/core/scf_optimizer_basic_block.c +++ b/core/scf_optimizer_basic_block.c @@ -76,11 +76,10 @@ static void __optimize_dn_free(scf_dag_node_t* dn) static int _bb_dag_update(scf_basic_block_t* bb) { - scf_dag_node_t* dn; - scf_dag_node_t* dn_bb; - scf_dag_node_t* dn_func; - scf_dag_node_t* base; - scf_list_t* l; + scf_dag_node_t* dn; + scf_dag_node_t* dn_bb; + scf_dag_node_t* dn_func; + scf_list_t* l; while (1) { int updated = 0; @@ -102,6 +101,13 @@ static int _bb_dag_update(scf_basic_block_t* bb) if (scf_type_is_assign_pointer(dn->type)) continue; + if (SCF_OP_ASSIGN == dn->type && dn->childs && 2 == dn->childs->size) { + dn_bb = dn->childs->data[0]; + + if (scf_variable_char_array(dn_bb->var)) + continue; + } + if (scf_type_is_assign(dn->type) || SCF_OP_INC == dn->type || SCF_OP_DEC == dn->type || SCF_OP_3AC_INC == dn->type || SCF_OP_3AC_DEC == dn->type diff --git a/core/scf_variable.h b/core/scf_variable.h index 4e3d2e9..c908bac 100644 --- a/core/scf_variable.h +++ b/core/scf_variable.h @@ -190,6 +190,13 @@ static inline int scf_variable_is_array(scf_variable_t* v) return v->nb_dimentions > 0; } +static inline int scf_variable_char_array(scf_variable_t* v) +{ + return 1 == v->nb_dimentions + && 0 == v->nb_pointers + && (SCF_VAR_CHAR == v->type || SCF_VAR_I8 == v->type || SCF_VAR_U8 == v->type); +} + static inline int scf_variable_may_malloced(scf_variable_t* v) { if (v->nb_dimentions > 0) diff --git a/examples/char_array_cstr.c b/examples/char_array_cstr.c new file mode 100644 index 0000000..b04de9d --- /dev/null +++ b/examples/char_array_cstr.c @@ -0,0 +1,9 @@ +int printf(const char* fmt, ...); + +int main() +{ + char p[] = "hello\n"; + + printf(p); + return 0; +} diff --git a/lex/scf_lex.c b/lex/scf_lex.c index d42f565..2647478 100644 --- a/lex/scf_lex.c +++ b/lex/scf_lex.c @@ -502,114 +502,112 @@ static int _lex_identity(scf_lex_t* lex, scf_lex_word_t** pword, scf_char_t* c0) return -1; } -static int _lex_char_base8(scf_lex_t* lex, scf_string_t* s, int* num) +static int _lex_number_char(scf_lex_t* lex, scf_string_t* s, int base, int* num) { - int tmp = -1; int n = 0; int v = 0; + if ('0' <= base && base <= '7') + v = base - '0'; + else + assert('x' == base); + while (1) { scf_char_t* c = _lex_pop_char(lex); if (!c) return -ENOMEM; - tmp = c->c; - - int ret = scf_string_cat_cstr_len(s, c->utf8, c->len); - - lex->pos += c->len; - free(c); - c = NULL; - - if (ret < 0) - return ret; - - if (tmp < '0' || tmp > '7') - break; + int tmp = c->c; - v = (v << 3) + tmp - '0'; - n++; - } + if ('x' == base) { + if ('0' <= tmp && tmp <= '9') + tmp -= '0'; - if (tmp < 0) { - scf_loge("%s:%d:%d, un-expected char '%d' found\n", lex->file->data, lex->nb_lines, lex->pos, tmp); - return tmp; - } + else if ('a' <= tmp && tmp <= 'f') + tmp += 10 - 'a'; - switch (tmp) { - case '8': - case '9': - scf_loge("%s:%d:%d, un-expected char '%c' found\n", lex->file->data, lex->nb_lines, lex->pos, tmp); - return -1; - break; + else if ('A' <= tmp && tmp <= 'F') + tmp += 10 - 'A'; + else { + if (n <= 0) { + scf_loge("%s:%d:%d, '%c:%d' NOT const char of base 16\n", lex->file->data, lex->nb_lines, lex->pos, tmp, tmp); - case '\'': - if (n > 3) { - scf_loge("%s:%d:%d, const base8 char should NOT more than 3 bits, real '%d bits'.\n", - lex->file->data, lex->nb_lines, lex->pos, n); - return -1; - } - break; + free(c); + return -1; + } - default: - if (n > 1) { - scf_loge("%s:%d:%d, un-expected char '%c' found\n", lex->file->data, lex->nb_lines, lex->pos, tmp); - return -1; + _lex_push_char(lex, c); + break; } - break; - }; - *num = v; - return tmp; -} + v = (v << 4) + tmp; -static int _lex_char_base16(scf_lex_t* lex, scf_string_t* s, int* num) -{ - int tmp = -1; - int n = 0; - int v = 0; + } else if ('0' <= tmp && tmp <= '7') { - while (1) { - scf_char_t* c = _lex_pop_char(lex); - if (!c) - return -ENOMEM; - - tmp = c->c; + v = (v << 3) + tmp - '0'; + } else { + _lex_push_char(lex, c); + break; + } - int ret = scf_string_cat_cstr_len(s, c->utf8, c->len); + int ret = scf_string_cat_cstr_len(s, c->utf8, 1); + lex->pos++; - lex->pos += c->len; free(c); c = NULL; if (ret < 0) return ret; - if (tmp >= '0' && tmp <= '9') - tmp -= '0'; + n++; + } - else if (tmp >= 'a' && tmp <= 'f') - tmp += 10 - 'a'; + *num = v; + return n; +} - else if (tmp >= 'A' && tmp <= 'F') - tmp += 10 - 'A'; - else +static int _lex_escape_char(scf_lex_t* lex, scf_string_t* s, int base, int* num) +{ + int ret; + int v; + + switch (base) { + case 'x': + return _lex_number_char(lex, s, base, num); break; - v = (v << 4) + tmp; - } + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + v = 0; + ret = _lex_number_char(lex, s, base, &v); + + if (ret > 3) { + scf_loge("%s:%d:%d, base 8 const char should NOT more than 3 bits (real %d bits)\n", + lex->file->data, lex->nb_lines, lex->pos, ret); + return -1; + } - if (tmp < 0) { - scf_loge("%s:%d:%d, un-expected char '%d' found\n", lex->file->data, lex->nb_lines, lex->pos, tmp); - return tmp; - } + *num = v; + return ret; + break; - if ('\'' != tmp) { - scf_loge("%s:%d:%d, const char lost right '\n", lex->file->data, lex->nb_lines, lex->pos); - return -1; - } + case '8': + case '9': + scf_loge("%s:%d:%d, un-expected char '%c' found\n", lex->file->data, lex->nb_lines, lex->pos, base); + return -1; + break; - *num = v; - return tmp; + default: + *num = _find_escape_char(base); + break; + }; + + return 0; } static int _lex_char(scf_lex_t* lex, scf_lex_word_t** pword, scf_string_t* s, scf_char_t* c0) @@ -643,6 +641,14 @@ static int _lex_char(scf_lex_t* lex, scf_lex_word_t** pword, scf_string_t* s, sc return -ENOMEM; } + if ('\'' == c1->c) { + scf_loge("%s:%d:%d, const char should NOT empty\n", lex->file->data, lex->nb_lines, lex->pos); + + scf_string_free(s); + free(c1); + return -EINVAL; + } + int num = 0; int tmp = c1->c; @@ -658,60 +664,57 @@ static int _lex_char(scf_lex_t* lex, scf_lex_word_t** pword, scf_string_t* s, sc } if ('\\' == tmp) { - ret = _lex_char_base8(lex, s, &num); - if (ret < 0) { + c1 = _lex_pop_char(lex); + + if (!c1) { scf_string_free(s); - return ret; + return -ENOMEM; } - switch (ret) { - case 'x': // base 16 const char - num = 0; - ret = _lex_char_base16(lex, s, &num); - if (ret < 0) { - scf_string_free(s); - return ret; - } - break; + tmp = c1->c; - case '\'': // base 8 const char - break; + ret = scf_string_cat_cstr_len(s, c1->utf8, c1->len); - default: // other char - num = _find_escape_char(ret); - break; - }; - - tmp = ret; - } else - num = tmp; + lex->pos += c1->len; + free(c1); + c1 = NULL; - if ('\'' != tmp) { - c2 = _lex_pop_char(lex); - if (!c2) { + if (ret < 0) { scf_string_free(s); - return -ENOMEM; + return ret; } - tmp = c2->c; - - ret = scf_string_cat_cstr_len(s, c2->utf8, c2->len); - - lex->pos += c2->len; - free(c2); - c2 = NULL; - + ret = _lex_escape_char(lex, s, tmp, &num); if (ret < 0) { scf_string_free(s); return ret; } + } else + num = tmp; + + c2 = _lex_pop_char(lex); + if (!c2) { + scf_string_free(s); + return -ENOMEM; } - if ('\'' == tmp) - w = scf_lex_word_alloc(lex->file, lex->nb_lines, pos, SCF_LEX_WORD_CONST_CHAR); - else - scf_loge("%s:%d:%d, const char lost right '\n", lex->file->data, lex->nb_lines, lex->pos); + if ('\'' == c2->c) + ret = scf_string_cat_cstr_len(s, c2->utf8, c2->len); + else { + scf_loge("%s:%d:%d, un-expected char '%c', ascii: %d\n", lex->file->data, lex->nb_lines, lex->pos, c2->c, c2->c); + ret = -EINVAL; + } + + lex->pos += c2->len; + free(c2); + c2 = NULL; + + if (ret < 0) { + scf_string_free(s); + return ret; + } + w = scf_lex_word_alloc(lex->file, lex->nb_lines, pos, SCF_LEX_WORD_CONST_CHAR); if (!w) { scf_string_free(s); return -1; @@ -748,77 +751,123 @@ static int _lex_string(scf_lex_t* lex, scf_lex_word_t** pword, scf_char_t* c0) { scf_lex_word_t* w = NULL; scf_string_t* s = scf_string_cstr_len(c0->utf8, 1); - scf_string_t* d = scf_string_alloc(); + scf_string_t* d = NULL; - int pos = lex->pos; + int pos = lex->pos++; + + free(c0); + c0 = NULL; + if (!s) + return -ENOMEM; + + d = scf_string_alloc(); + if (!d) { + scf_string_free(s); + return -ENOMEM; + } while (1) { scf_char_t* c1 = _lex_pop_char(lex); + if (!c1) { + scf_string_free(s); + scf_string_free(d); + return -ENOMEM; + } + + if (EOF == c1->c || '\n' == c1->c) { + scf_loge("%s:%d:%d, const string lost 2nd \"\n", lex->file->data, lex->nb_lines, lex->pos); + + free(c1); + return -1; + } + + int ret = scf_string_cat_cstr_len(s, c1->utf8, c1->len); + if (ret < 0) { + scf_string_free(s); + scf_string_free(d); + free(c1); + return ret; + } + + lex->pos += c1->len; if ('\"' == c1->c) { - scf_string_cat_cstr_len(s, c1->utf8, 1); + free(c1); + c1 = NULL; w = scf_lex_word_alloc(lex->file, lex->nb_lines, pos, SCF_LEX_WORD_CONST_STRING); + if (!w) { + scf_string_free(s); + scf_string_free(d); + return -ENOMEM; + } + w->data.s = d; w->text = s; d = NULL; s = NULL; - lex->pos++; *pword = w; + return 0; + + } else if ('\\' != c1->c) { + + ret = scf_string_cat_cstr_len(d, c1->utf8, c1->len); free(c1); c1 = NULL; - return 0; - } else if ('\\' == c1->c) { - scf_char_t* c2 = _lex_pop_char(lex); + if (ret < 0) { + scf_string_free(s); + scf_string_free(d); + return ret; + } - int ch2 = _find_escape_char(c2->c); + continue; + } - scf_string_cat_cstr_len(s, c1->utf8, 1); - scf_string_cat_cstr_len(s, c2->utf8, c2->len); - lex->pos += 1 + c2->len; + // for escape char + scf_char_t* c2 = _lex_pop_char(lex); + if (!c2) { + scf_string_free(s); + scf_string_free(d); + return -ENOMEM; + } - free(c2); - free(c1); - c2 = NULL; - c1 = NULL; + int tmp = c2->c; - if (0 == ch2) { - while (1) { - c1 = _lex_pop_char(lex); + ret = scf_string_cat_cstr_len(s, c2->utf8, c2->len); + lex->pos += c2->len; - if ('0' <= c1->c && c1->c <= '7') { - ch2 <<= 3; - ch2 += c1->c - '0'; + free(c2); + c2 = NULL; - scf_string_cat_cstr_len(s, c1->utf8, 1); - lex->pos++; + if (ret < 0) { + scf_string_free(s); + scf_string_free(d); + return ret; + } - free(c1); - c1 = NULL; - } else { - _lex_push_char(lex, c1); - break; - } - } + int num = 0; - scf_string_cat_cstr_len(d, (char*)&ch2, 1); - } else - scf_string_cat_cstr_len(d, (char*)&ch2, 1); + ret = _lex_escape_char(lex, s, tmp, &num); - } else if (EOF == c1->c) { - scf_loge("const string lost 2nd \" in file: %s, line: %d\n", lex->file->data, lex->nb_lines); - return -1; + if (num > 255) { + scf_loge("%s:%d:%d, char '%d' out of 0-255\n", lex->file->data, lex->nb_lines, lex->pos, num); + ret = -1; + } - } else { - scf_string_cat_cstr_len(s, c1->utf8, c1->len); - scf_string_cat_cstr_len(d, c1->utf8, c1->len); - lex->pos += c1->len; + if (ret < 0) { + scf_string_free(s); + scf_string_free(d); + return ret; + } - free(c1); - c1 = NULL; + ret = scf_string_cat_cstr_len(d, (char*)&num, 1); + if (ret < 0) { + scf_string_free(s); + scf_string_free(d); + return ret; } } } diff --git a/native/x64/scf_x64_inst_common.c b/native/x64/scf_x64_inst_common.c index a4d573b..8740d2c 100644 --- a/native/x64/scf_x64_inst_common.c +++ b/native/x64/scf_x64_inst_common.c @@ -155,6 +155,45 @@ static int _x64_inst_op2_imm(int OpCode_type, scf_dag_node_t* dst, scf_dag_node_ return 0; } +int x64_init_char_array(scf_dag_node_t* dst, scf_dag_node_t* src, scf_3ac_code_t* c, scf_function_t* f) +{ + scf_instruction_t* inst; + scf_x64_OpCode_t* mov; + scf_variable_t* v = src->var; + scf_register_t* rd = NULL; + + X64_SELECT_REG_CHECK(&rd, dst, c, f, 1); + + rd->used = 1; + + int n = v->data.s->len + 1; + int i; + + for (i = 0; i < (n & ~0x3); i += 4) { + + mov = x64_find_OpCode(SCF_X64_MOV, 4, 4, SCF_X64_I2E); + inst = x64_make_inst_I2P(mov, rd, i, v->data.s->data + i, 4); + + X64_INST_ADD_CHECK(c, inst, NULL); + } + + for (; i < (n & ~0x1); i += 2) { + mov = x64_find_OpCode(SCF_X64_MOV, 2, 2, SCF_X64_I2E); + inst = x64_make_inst_I2P(mov, rd, i, v->data.s->data + i, 2); + + X64_INST_ADD_CHECK(c, inst, NULL); + } + + for (; i < n; i++) { + mov = x64_find_OpCode(SCF_X64_MOV, 1, 1, SCF_X64_I2E); + inst = x64_make_inst_I2P(mov, rd, i, v->data.s->data + i, 1); + + X64_INST_ADD_CHECK(c, inst, 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); @@ -166,9 +205,15 @@ 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; + + if (scf_variable_char_array(dst->var)) + return x64_init_char_array(dst, src, c, f); + X64_SELECT_REG_CHECK(&rd, dst, c, f, 0); return x64_load_const(rd, src, c, f); diff --git a/parse/scf_dfa_var.c b/parse/scf_dfa_var.c index a93a3b9..2ed0120 100644 --- a/parse/scf_dfa_var.c +++ b/parse/scf_dfa_var.c @@ -434,7 +434,20 @@ static int _var_action_assign(scf_dfa_t* dfa, scf_vector_t* words, void* data) if (d->current_var->nb_dimentions > 0) { scf_logi("var array '%s' init, nb_dimentions: %d\n", d->current_var->w->text->data, d->current_var->nb_dimentions); - return SCF_DFA_NEXT_WORD; + + if (scf_variable_char_array(d->current_var)) { + + w = dfa->ops->pop_word(dfa); + if (!w) + return SCF_DFA_ERROR; + dfa->ops->push_word(dfa, w); + + if (SCF_LEX_WORD_CONST_STRING == w->type) + d->current_var->dimentions[0].num = w->data.s->len + 1; + else + return SCF_DFA_NEXT_WORD; + } else + return SCF_DFA_NEXT_WORD; } scf_operator_t* op = scf_find_base_operator_by_type(SCF_OP_ASSIGN); diff --git a/parse/scf_operator_handler_semantic.c b/parse/scf_operator_handler_semantic.c index d786287..dcc43b9 100644 --- a/parse/scf_operator_handler_semantic.c +++ b/parse/scf_operator_handler_semantic.c @@ -77,27 +77,33 @@ static int _semantic_add_address_of(scf_ast_t* ast, scf_node_t** pp, scf_node_t* static int _semantic_add_type_cast(scf_ast_t* ast, scf_node_t** pp, scf_variable_t* v_dst, scf_node_t* src) { - scf_node_t* parent = src->parent; - scf_type_t* t = v_dst->t; - - assert(t); - scf_operator_t* op = scf_find_base_operator_by_type(SCF_OP_TYPE_CAST); if (!op) return -EINVAL; - scf_variable_t* v_src = _scf_operand_get(src); - scf_variable_t* v = SCF_VAR_ALLOC_BY_TYPE(NULL, t, v_src->const_flag, v_dst->nb_pointers, v_dst->func_ptr); + scf_node_t* parent = src->parent; + scf_variable_t* v_src = _scf_operand_get(src); + scf_variable_t* v; + scf_node_t* dst; + scf_node_t* cast; + scf_type_t* t = v_dst->t; + + assert(t); + + int const_flag = v_src->const_flag; + int nb_pointers = v_dst->nb_pointers + v_dst->nb_dimentions; + + v = SCF_VAR_ALLOC_BY_TYPE(NULL, t, const_flag, nb_pointers, v_dst->func_ptr); if (!v) return -ENOMEM; - scf_node_t* dst = scf_node_alloc(NULL, v->type, v); + dst = scf_node_alloc(NULL, v->type, v); scf_variable_free(v); v = NULL; if (!dst) return -ENOMEM; - scf_node_t* cast = scf_node_alloc(NULL, SCF_OP_TYPE_CAST, NULL); + cast = scf_node_alloc(NULL, SCF_OP_TYPE_CAST, NULL); if (!cast) { scf_node_free(dst); return -ENOMEM; @@ -2621,8 +2627,11 @@ static int _scf_op_semantic_assign(scf_ast_t* ast, scf_node_t** nodes, int nb_no if (v0->const_literal_flag || v0->nb_dimentions > 0) { - scf_loge("const var '%s' can't be assigned\n", v0->w->text->data); - return -1; + if (!scf_variable_char_array(v0) || !scf_variable_const_string(v1)) { + + scf_loge("const var '%s' can't be assigned\n", v0->w->text->data); + return -1; + } } else if (v0->const_flag) { scf_logw("const var '%s' can't be assigned\n", v0->w->text->data); @@ -2696,23 +2705,26 @@ static int _scf_op_semantic_assign(scf_ast_t* ast, scf_node_t** nodes, int nb_no } } - scf_logd("v0: v_%d_%d/%s\n", v0->w->line, v0->w->pos, v0->w->text->data); + if (!scf_variable_char_array(v0) || !scf_variable_const_string(v1)) { - if (scf_type_cast_check(ast, v0, v1) < 0) { - scf_loge("\n"); - return -1; - } + scf_logd("v0: v_%d_%d/%s\n", v0->w->line, v0->w->pos, v0->w->text->data); - int ret = _semantic_add_type_cast(ast, &nodes[1], v0, nodes[1]); - if (ret < 0) { - scf_loge("add type cast failed\n"); - return ret; + if (scf_type_cast_check(ast, v0, v1) < 0) { + scf_loge("\n"); + return -1; + } + + int ret = _semantic_add_type_cast(ast, &nodes[1], v0, nodes[1]); + if (ret < 0) { + scf_loge("add type cast failed\n"); + return ret; + } } } scf_type_t* t = v0->t; scf_lex_word_t* w = parent->w; - scf_variable_t* r = SCF_VAR_ALLOC_BY_TYPE(w, t, v0->const_flag, v0->nb_pointers, v0->func_ptr); + scf_variable_t* r = SCF_VAR_ALLOC_BY_TYPE(w, t, v0->const_flag, v0->nb_pointers + v0->nb_dimentions, v0->func_ptr); if (!r) { scf_loge("var alloc failed\n"); return -1;