diff options
| author | rajdakin <rajdakin@gmail.com> | 2024-09-20 12:40:06 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-09-20 12:40:06 +0200 |
| commit | 550b72200d098607c5be999682b912903c98657a (patch) | |
| tree | f164c1298066035a374a54fc09972c4ab609f902 /wrapperhelper/src/parse.c | |
| parent | cd9d19a2bb0bbc411c3e32f9ec6b46df0ce5bfb1 (diff) | |
| download | box64-550b72200d098607c5be999682b912903c98657a.tar.gz box64-550b72200d098607c5be999682b912903c98657a.zip | |
Improve the wrapper helper (#1844)
* [WRAPPERHELPER] Fixed some issues, added better macros * [WRAPPERHELPER] Fixed type_t_equal_lax
Diffstat (limited to 'wrapperhelper/src/parse.c')
| -rw-r--r-- | wrapperhelper/src/parse.c | 261 |
1 files changed, 197 insertions, 64 deletions
diff --git a/wrapperhelper/src/parse.c b/wrapperhelper/src/parse.c index b1f9ed90..2470d8ce 100644 --- a/wrapperhelper/src/parse.c +++ b/wrapperhelper/src/parse.c @@ -47,15 +47,26 @@ void dump_preproc(machine_t *target, const char *filename, FILE *file) { } enum decl_storage { - STORAGE_NONE, - STORAGE_TYPEDEF, - STORAGE_EXTERN, - STORAGE_STATIC, - STORAGE_TLS, - STORAGE_TLS_EXTERN, - STORAGE_TLS_STATIC, - STORAGE_AUTO, - STORAGE_REG, + TMPSTO_NONE, + TMPSTO_TYPEDEF, + TMPSTO_EXTERN, + TMPSTO_STATIC, + TMPSTO_TLS, + TMPSTO_TLS_EXTERN, + TMPSTO_TLS_STATIC, + TMPSTO_AUTO, + TMPSTO_REG, +}; +const enum decl_storage_e tmpsto2sto[] = { + [TMPSTO_NONE] = STORAGE_NONE, + [TMPSTO_TYPEDEF] = STORAGE_NONE, + [TMPSTO_EXTERN] = STORAGE_EXTERN, + [TMPSTO_STATIC] = STORAGE_STATIC, + [TMPSTO_TLS] = STORAGE_TLS, + [TMPSTO_TLS_EXTERN] = STORAGE_TLS_EXTERN, + [TMPSTO_TLS_STATIC] = STORAGE_TLS_STATIC, + [TMPSTO_AUTO] = STORAGE_AUTO, + [TMPSTO_REG] = STORAGE_REG, }; enum decl_spec { SPEC_NONE, @@ -84,7 +95,7 @@ static int validate_storage_type(machine_t *target, enum decl_storage storage, // We may still do adjustments here if (!validate_type(target, typ)) return 0; if (typ->typ == TYPE_FUNCTION) { - if ((storage == STORAGE_TLS) || (storage == STORAGE_TLS_EXTERN) || (storage == STORAGE_TLS_STATIC)) { + if ((storage == TMPSTO_TLS) || (storage == TMPSTO_TLS_EXTERN) || (storage == TMPSTO_TLS_STATIC)) { printf("Error: functions cannot be thread local\n"); return 0; } @@ -94,7 +105,7 @@ static int validate_storage_type(machine_t *target, enum decl_storage storage, return VALIDATION_FUN; } } else { - if ((sym == SYM_COMMA) || (sym == SYM_RPAREN) || (sym == SYM_SEMICOLON) || ((storage != STORAGE_TYPEDEF) && (sym == SYM_EQ))) { + if ((sym == SYM_COMMA) || (sym == SYM_RPAREN) || (sym == SYM_SEMICOLON) || ((storage != TMPSTO_TYPEDEF) && (sym == SYM_EQ))) { return (sym == SYM_SEMICOLON) ? VALIDATION_LAST_DECL : VALIDATION_DECL; } } @@ -436,7 +447,7 @@ static int parse_type_name(machine_t *target, khash_t(struct_map) *struct_map, k dest2.argt.type_set = type_set; dest2.argt.builtins = builtins; dest2.argt.const_map = const_map; - if (!parse_declarator(target, &dest2, prep, tok, STORAGE_NONE, FSPEC_NONE, *typ, 0, 0, 0, 1)) { + if (!parse_declarator(target, &dest2, prep, tok, TMPSTO_NONE, FSPEC_NONE, *typ, 0, 0, 0, 1)) { // Token is deleted type_del(*typ); goto failed; @@ -1260,6 +1271,7 @@ static int eval_expression(expr_t *e, khash_t(const_map) *const_map, num_constan if (e->val.cast.typ->typ == TYPE_BUILTIN) { switch (e->val.cast.typ->val.builtin) { case BTT_UCHAR: + case BTT_U8: switch (dest->typ) { case NCT_FLOAT: dest->val.u32 = (uint8_t)dest->val.f; break; case NCT_DOUBLE: dest->val.u32 = (uint8_t)dest->val.d; break; @@ -1272,6 +1284,8 @@ static int eval_expression(expr_t *e, khash_t(const_map) *const_map, num_constan dest->typ = NCT_UINT32; return 1; case BTT_INT: + case BTT_SINT: + case BTT_S32: switch (dest->typ) { case NCT_FLOAT: dest->val.i32 = (int32_t)dest->val.f; break; case NCT_DOUBLE: dest->val.i32 = (int32_t)dest->val.d; break; @@ -1283,8 +1297,23 @@ static int eval_expression(expr_t *e, khash_t(const_map) *const_map, num_constan } dest->typ = NCT_INT32; return 1; + case BTT_UINT: + case BTT_U32: + switch (dest->typ) { + case NCT_FLOAT: dest->val.u32 = (uint32_t)dest->val.f; break; + case NCT_DOUBLE: dest->val.u32 = (uint32_t)dest->val.d; break; + case NCT_LDOUBLE: dest->val.u32 = (uint32_t)dest->val.l; break; + case NCT_INT32: dest->val.u32 = (uint32_t)dest->val.i32; break; + case NCT_UINT32: break; + case NCT_INT64: dest->val.u32 = (uint32_t)dest->val.i64; break; + case NCT_UINT64: dest->val.u32 = (uint32_t)dest->val.u64; break; + } + dest->typ = NCT_UINT32; + return 1; case BTT_ULONG: // Warning: assuming sizeof(long) == 8 on the current target + // TODO: use machine to select between U32 and U64 + case BTT_U64: switch (dest->typ) { case NCT_FLOAT: dest->val.u64 = (uint64_t)dest->val.f; break; case NCT_DOUBLE: dest->val.u64 = (uint64_t)dest->val.d; break; @@ -1296,18 +1325,6 @@ static int eval_expression(expr_t *e, khash_t(const_map) *const_map, num_constan } dest->typ = NCT_UINT64; return 1; - case BTT_U32: - switch (dest->typ) { - case NCT_FLOAT: dest->val.u32 = (uint32_t)dest->val.f; break; - case NCT_DOUBLE: dest->val.u32 = (uint32_t)dest->val.d; break; - case NCT_LDOUBLE: dest->val.u32 = (uint32_t)dest->val.l; break; - case NCT_INT32: dest->val.u32 = (uint32_t)dest->val.i32; break; - case NCT_UINT32: break; - case NCT_INT64: dest->val.u32 = (uint32_t)dest->val.i64; break; - case NCT_UINT64: dest->val.u32 = (uint32_t)dest->val.u64; break; - } - dest->typ = NCT_UINT32; - return 1; case BTT_VOID: case BTT_BOOL: case BTT_CHAR: @@ -1315,8 +1332,6 @@ static int eval_expression(expr_t *e, khash_t(const_map) *const_map, num_constan case BTT_SHORT: case BTT_SSHORT: case BTT_USHORT: - case BTT_SINT: - case BTT_UINT: case BTT_LONG: case BTT_SLONG: case BTT_LONGLONG: @@ -1326,12 +1341,9 @@ static int eval_expression(expr_t *e, khash_t(const_map) *const_map, num_constan case BTT_SINT128: case BTT_UINT128: case BTT_S8: - case BTT_U8: case BTT_S16: case BTT_U16: - case BTT_S32: case BTT_S64: - case BTT_U64: case BTT_FLOAT: case BTT_CFLOAT: case BTT_IFLOAT: @@ -1442,7 +1454,7 @@ parse_cur_token_decl: } // Storage if (storage && (tok->tokt == PTOK_KEYWORD) && (tok->tokv.kw == KW_AUTO)) { - if (*storage == STORAGE_NONE) *storage = STORAGE_AUTO; + if (*storage == TMPSTO_NONE) *storage = TMPSTO_AUTO; else { printf("Error: unexpected storage class specifier '%s' in declaration\n", kw2str[tok->tokv.kw]); goto failed; @@ -1450,8 +1462,8 @@ parse_cur_token_decl: *tok = proc_next_token(prep); goto parse_cur_token_decl; } else if (storage && (tok->tokt == PTOK_KEYWORD) && (tok->tokv.kw == KW_EXTERN)) { - if (*storage == STORAGE_NONE) *storage = STORAGE_EXTERN; - else if (*storage == STORAGE_TLS) *storage = STORAGE_TLS_EXTERN; + if (*storage == TMPSTO_NONE) *storage = TMPSTO_EXTERN; + else if (*storage == TMPSTO_TLS) *storage = TMPSTO_TLS_EXTERN; else { printf("Error: unexpected storage class specifier '%s' in declaration\n", kw2str[tok->tokv.kw]); goto failed; @@ -1459,7 +1471,7 @@ parse_cur_token_decl: *tok = proc_next_token(prep); goto parse_cur_token_decl; } else if (storage && (tok->tokt == PTOK_KEYWORD) && (tok->tokv.kw == KW_REGISTER)) { - if (*storage == STORAGE_NONE) *storage = STORAGE_REG; + if (*storage == TMPSTO_NONE) *storage = TMPSTO_REG; else { printf("Error: unexpected storage class specifier '%s' in declaration\n", kw2str[tok->tokv.kw]); goto failed; @@ -1467,8 +1479,8 @@ parse_cur_token_decl: *tok = proc_next_token(prep); goto parse_cur_token_decl; } else if (storage && (tok->tokt == PTOK_KEYWORD) && (tok->tokv.kw == KW_STATIC)) { - if (*storage == STORAGE_NONE) *storage = STORAGE_STATIC; - else if (*storage == STORAGE_TLS) *storage = STORAGE_TLS_STATIC; + if (*storage == TMPSTO_NONE) *storage = TMPSTO_STATIC; + else if (*storage == TMPSTO_TLS) *storage = TMPSTO_TLS_STATIC; else { printf("Error: unexpected storage class specifier '%s' in declaration\n", kw2str[tok->tokv.kw]); goto failed; @@ -1476,9 +1488,9 @@ parse_cur_token_decl: *tok = proc_next_token(prep); goto parse_cur_token_decl; } else if (storage && (tok->tokt == PTOK_KEYWORD) && (tok->tokv.kw == KW_THREAD_LOCAL)) { - if (*storage == STORAGE_NONE) *storage = STORAGE_TLS; - else if (*storage == STORAGE_EXTERN) *storage = STORAGE_TLS_EXTERN; - else if (*storage == STORAGE_STATIC) *storage = STORAGE_TLS_STATIC; + if (*storage == TMPSTO_NONE) *storage = TMPSTO_TLS; + else if (*storage == TMPSTO_EXTERN) *storage = TMPSTO_TLS_EXTERN; + else if (*storage == TMPSTO_STATIC) *storage = TMPSTO_TLS_STATIC; else { printf("Error: unexpected storage class specifier '%s' in declaration\n", kw2str[tok->tokv.kw]); goto failed; @@ -1486,7 +1498,7 @@ parse_cur_token_decl: *tok = proc_next_token(prep); goto parse_cur_token_decl; } else if (storage && (tok->tokt == PTOK_KEYWORD) && (tok->tokv.kw == KW_TYPEDEF)) { - if (*storage == STORAGE_NONE) *storage = STORAGE_TYPEDEF; + if (*storage == TMPSTO_NONE) *storage = TMPSTO_TYPEDEF; else { printf("Error: unexpected storage class specifier '%s' in declaration\n", kw2str[tok->tokv.kw]); goto failed; @@ -1775,7 +1787,7 @@ parse_cur_token_decl: "Current state:\n" " storage: %p/%u\n" " spec: %u\n" - " type: ", string_content(tok->tokv.str), storage, storage ? *storage : STORAGE_NONE, *spec); + " type: ", string_content(tok->tokv.str), storage, storage ? *storage : TMPSTO_NONE, *spec); type_print(typ); printf("\n"); string_del(tok->tokv.str); @@ -1848,7 +1860,7 @@ parse_cur_token_decl: "Current state:\n" " storage: %p/%u\n" " spec: %u\n" - " type: ", storage, storage ? *storage : STORAGE_NONE, *spec); + " type: ", storage, storage ? *storage : TMPSTO_NONE, *spec); type_print(typ); printf("\n"); goto failed; @@ -1916,7 +1928,7 @@ parse_cur_token_decl: dest2.structms.builtins = builtins; dest2.structms.const_map = const_map; dest2.structms.dest = members; - if (!parse_declarator(target, &dest2, prep, tok, STORAGE_NONE, FSPEC_NONE, typ2, 0, 1, 1, 1)) { + if (!parse_declarator(target, &dest2, prep, tok, TMPSTO_NONE, FSPEC_NONE, typ2, 0, 1, 1, 1)) { printf("Error parsing struct-declarator-list\n"); vector_del(st_members, members); type_del(typ2); @@ -2215,7 +2227,7 @@ invalid_token: "Current state:\n" " storage: %p/%u\n" " spec: %u\n" - " type: ", storage, storage ? *storage : STORAGE_NONE, *spec); + " type: ", storage, storage ? *storage : TMPSTO_NONE, *spec); type_print(typ); printf("\n"); proc_token_print(tok); @@ -2334,7 +2346,7 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d vector_del(types, args); goto failed; } - enum decl_storage storage2 = STORAGE_NONE; + enum decl_storage storage2 = TMPSTO_NONE; enum decl_spec spec2 = SPEC_NONE; if (!parse_declaration_specifier(target, PDECL_STRUCT_MAP, PDECL_TYPE_MAP, PDECL_ENUM_MAP, PDECL_BUILTINS, PDECL_CONST_MAP, PDECL_TYPE_SET, prep, tok, &storage2, NULL, &spec2, typ2)) { @@ -2383,6 +2395,27 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d break; } else if ((tok->tokt == PTOK_SYM) && (tok->tokv.sym == SYM_COMMA)) { // Unnamed argument + if (typ2->typ == TYPE_ARRAY) { + // Need to convert type to a pointer + type_t *typ3 = type_new(); + if (!typ3) { + printf("Error: failed to allocate new type\n"); + type_del(typ2); + // Empty destructor + goto failed; + } + if (!type_copy_into(typ3, typ2)) { + printf("Error: failed to duplicate array type to temporary type\n"); + type_del(typ3); + type_del(typ2); + // Empty destructor + goto failed; + } + type_del(typ2); + typ3->typ = TYPE_PTR; + typ3->val.typ = typ3->val.array.typ; + typ2 = type_try_merge(typ3, PDECL_TYPE_SET); + } if (!vector_push(types, args, typ2)) { printf("Error: failed to add argument to argument vector\n"); vector_del(types, args); @@ -2403,7 +2436,7 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d dest2.argt.type_set = PDECL_TYPE_SET; dest2.argt.builtins = PDECL_BUILTINS; dest2.argt.const_map = PDECL_CONST_MAP; - if (!parse_declarator(target, &dest2, prep, tok, STORAGE_NONE, FSPEC_NONE, typ2, 0, 0, 1, 1)) { + if (!parse_declarator(target, &dest2, prep, tok, TMPSTO_NONE, FSPEC_NONE, typ2, 0, 0, 1, 1)) { // Token is deleted vector_del(types, args); type_del(typ2); @@ -2726,22 +2759,39 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d // whereas no argument in function declaration means the function takes an unspecified number of arguments if (typ->val.fun.nargs == (size_t)-1) typ->val.fun.nargs = 0; + declaration_t *decl = malloc(sizeof *decl); + if (!decl) { + printf("Failed to create new declaration\n"); + // Empty destructor + goto failed; + } + decl->storage = tmpsto2sto[storage]; + decl->defined = 1; + decl->typ = typ; + int iret; char *cident = string_steal(cur_ident); cur_ident = NULL; - khiter_t it = kh_put(type_map, dest->f->decl_map, cident, &iret); + khiter_t it = kh_put(decl_map, dest->f->decl_map, cident, &iret); if (iret < 0) { printf("Failed to add function '%s' to the declaration map\n", cident); free(cident); + free(decl); // Empty destructor goto failed; } else if (iret == 0) { - printf("Error: function '%s' is already in the declaration map\n", cident); - free(cident); - // Empty destructor - goto failed; + free(decl); + if (kh_val(dest->f->decl_map, it)->defined) { + printf("Error: function '%s' is already in the declaration map\n", cident); + free(cident); + // Empty destructor + goto failed; + } else { + free(cident); + decl = kh_val(dest->f->decl_map, it); + } } - kh_val(dest->f->decl_map, it) = typ; + kh_val(dest->f->decl_map, it) = decl; // Skip the function body int nlbraces = 0; @@ -2757,13 +2807,14 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d printf("Error: unexpected token in function body\n"); goto failed; } - if (fspec != FSPEC_NONE) { + if ((fspec != FSPEC_NONE) && (typ->typ != TYPE_FUNCTION)) { printf("Error: unexpected function specifier\n"); // Empty destructor goto failed; } - if (storage == STORAGE_TYPEDEF) { + declaration_t *decl = NULL; + if (storage == TMPSTO_TYPEDEF) { if (!is_init || !is_list) { // We are not at the top-level (note that storage is set to NONE in function arguments) printf("Error: invalid function definition\n"); @@ -2793,31 +2844,46 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d } else { kh_val(dest->f->type_map, it) = typ; } - } else if ((storage != STORAGE_STATIC) && (storage != STORAGE_TLS_STATIC)) { + } else { if (is_init && is_list) { - // static variables/functions are not exposed + decl = malloc(sizeof *decl); + if (!decl) { + printf("Failed to create new declaration\n"); + // Empty destructor + goto failed; + } + if ((typ->typ == TYPE_FUNCTION) && (storage == TMPSTO_NONE)) + storage = TMPSTO_EXTERN; + decl->storage = tmpsto2sto[storage]; + decl->defined = 0; + decl->typ = typ; + int iret; char *cident = string_steal(cur_ident); cur_ident = NULL; - khiter_t it = kh_put(type_map, dest->f->decl_map, cident, &iret); + khiter_t it = kh_put(decl_map, dest->f->decl_map, cident, &iret); if (iret < 0) { printf("Failed to add '%s' to the declaration map\n", cident); free(cident); + free(decl); // Empty destructor goto failed; } else if (iret == 0) { - /* if ((storage == STORAGE_NONE) || !type_t_equal(typ, kh_val(dest->f->decl_map, it))) { + if (!type_t_equal(typ, kh_val(dest->f->decl_map, it)->typ) + || ((storage == TMPSTO_NONE) && (kh_val(dest->f->decl_map, it)->storage == STORAGE_NONE))) { printf("Error: '%s' is already in the declaration map (storage=%u)\n", cident, storage); free(cident); + free(decl); type_del(typ); // Empty destructor goto failed; - } else */ { - printf("Warning: '%s' is already in the declaration map with the same type\n", cident); + } else { + // OK, this is allowed free(cident); + free(decl); type_del(typ); } } else { - kh_val(dest->f->decl_map, it) = typ; + kh_val(dest->f->decl_map, it) = decl; } } else if (!is_init && !is_list) { if (allow_decl) { @@ -2868,6 +2934,13 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d printf("Error: unexpected initializer\n"); goto failed; } + if (decl) { + if (decl->defined) { + printf("Error: invalid declaration initializer: variable was already declared\n"); + goto failed; + } + decl->defined = 1; + } *tok = proc_next_token(prep); if ((tok->tokt == PTOK_SYM) && (tok->tokv.sym == SYM_LBRACKET)) { // { ... } @@ -2920,7 +2993,7 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d // Try to free some redundant types typ = type_try_merge(typ, PDECL_TYPE_SET); - // storage == STORAGE_NONE + // storage == TMPSTO_NONE *tok = proc_next_token(prep); expr_t *e = parse_expression(target, dest->structms.struct_map, dest->structms.type_map, dest->structms.enum_map, dest->structms.builtins, dest->structms.const_map, dest->structms.type_set, @@ -2955,7 +3028,7 @@ static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *d // Empty destructor goto failed; } - if (fspec != FSPEC_NONE) { + if ((fspec != FSPEC_NONE) && (typ->typ != TYPE_FUNCTION)) { printf("Error: unexpected function specifier\n"); // Empty destructor goto failed; @@ -3158,6 +3231,32 @@ file_t *parse_file(machine_t *target, const char *filename, FILE *file) { } } break; } + case PRAGMA_SIMPLE_SU: { + string_t *sutag = tok.tokv.pragma.val; + struct_t *su; + khiter_t it = kh_get(struct_map, ret->struct_map, string_content(sutag)); + if (it != kh_end(ret->struct_map)) { + su = kh_val(ret->struct_map, it); + } else { + it = kh_get(type_map, ret->type_map, string_content(sutag)); + if (it != kh_end(ret->struct_map)) { + type_t *typ2 = kh_val(ret->type_map, it); + if (typ2->typ != TYPE_STRUCT_UNION) { + printf("Error: failed to find struct/union named %s\n", string_content(sutag)); + string_del(sutag); + goto failed; + } + su = typ2->val.st; + } else { + printf("Error: failed to find struct/union named %s\n", string_content(sutag)); + string_del(sutag); + goto failed; + } + } + string_del(sutag); + su->is_simple = 1; + // Empty destructor + break; } case PRAGMA_EXPLICIT_CONV: { string_t *converted = tok.tokv.pragma.val; type_t *typ2 = type_new(); @@ -3173,9 +3272,43 @@ file_t *parse_file(machine_t *target, const char *filename, FILE *file) { string_del(converted); goto failed; } + int iret; + khiter_t it = kh_put(conv_map, ret->relaxed_type_conversion, typ2, &iret); + if (iret < 0) { + printf("Error: failed to add relaxed conversion to type map\n"); + string_del(converted); + type_del(typ2); + // Empty destructor + goto failed; + } else if (iret == 0) { + printf("Error: type already has a relaxed conversion\n"); + string_del(converted); + type_del(typ2); + // Empty destructor + goto failed; + } + string_trim(converted); + kh_val(ret->relaxed_type_conversion, it) = converted; + // Empty destructor + break; } + case PRAGMA_EXPLICIT_CONV_STRICT: { + string_t *converted = tok.tokv.pragma.val; + type_t *typ2 = type_new(); + if (!typ2) { + printf("Error: failed to create new type info structure\n"); + string_del(converted); + type_del(typ2); + goto failed; + } + tok = proc_next_token(prep); + if (!parse_type_name(target, ret->struct_map, ret->type_map, ret->enum_map, &ret->builtins, ret->const_map, ret->type_set, + prep, &tok, SYM_SEMICOLON, &typ2)) { + string_del(converted); + goto failed; + } type_del(typ2); // typ2 is in the type set, so it is already used if (typ2->converted) { - printf("Error: type already has a conversion\n"); + printf("Error: type already has a strict conversion\n"); string_del(converted); // Empty destructor goto failed; @@ -3190,7 +3323,7 @@ file_t *parse_file(machine_t *target, const char *filename, FILE *file) { proc_token_del(&tok); goto failed; } else { - enum decl_storage storage = STORAGE_NONE; + enum decl_storage storage = TMPSTO_NONE; enum fun_spec fspec = FSPEC_NONE; enum decl_spec spec = SPEC_NONE; if (!parse_declaration_specifier(target, ret->struct_map, ret->type_map, ret->enum_map, &ret->builtins, ret->const_map, |