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)
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;
}
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;
{
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;
}
}
}
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);
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);
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;
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);
}
}
- 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;