diff options
| author | rajdakin <rajdakin@gmail.com> | 2024-09-08 22:26:35 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-09-08 22:26:35 +0200 |
| commit | 26b7a49d8279984a01ea5dc19b05cefff0693e35 (patch) | |
| tree | 3ff9f05a2fb11b0e21ad7cf1829c5a9992ce7728 /wrapperhelper/src | |
| parent | fa8a5a20336a64e5b53ea9a151c23941073381c4 (diff) | |
| download | box64-26b7a49d8279984a01ea5dc19b05cefff0693e35.tar.gz box64-26b7a49d8279984a01ea5dc19b05cefff0693e35.zip | |
[WRAPPERHELPER] Fixed preprocessor logic, moved type validation to machine (#1808)
Diffstat (limited to 'wrapperhelper/src')
| -rw-r--r-- | wrapperhelper/src/generator.c | 3 | ||||
| -rw-r--r-- | wrapperhelper/src/lang.c | 98 | ||||
| -rw-r--r-- | wrapperhelper/src/lang.h | 8 | ||||
| -rw-r--r-- | wrapperhelper/src/machine.c | 214 | ||||
| -rw-r--r-- | wrapperhelper/src/machine.h | 4 | ||||
| -rw-r--r-- | wrapperhelper/src/parse.c | 244 | ||||
| -rw-r--r-- | wrapperhelper/src/preproc.c | 29 |
7 files changed, 302 insertions, 298 deletions
diff --git a/wrapperhelper/src/generator.c b/wrapperhelper/src/generator.c index e162d0e4..63102f48 100644 --- a/wrapperhelper/src/generator.c +++ b/wrapperhelper/src/generator.c @@ -626,7 +626,8 @@ VECTOR(references) *references_from_file(const char *filename, FILE *f) { tok = pre_next_token(prep, 0); if (tok.tokt == PPTOK_NUM) { num_constant_t cst; - if (!num_constant_convert(tok.tokv.str, &cst)) { + // Assume target is 64 bits (box64) + if (!num_constant_convert(tok.tokv.str, &cst, 0)) { printf("Error: invalid reference file: invalid DATA line %d (num conversion)\n", lineno); string_del(req.obj_name); preproc_token_del(&tok); diff --git a/wrapperhelper/src/lang.c b/wrapperhelper/src/lang.c index ddc711fe..78cc66c1 100644 --- a/wrapperhelper/src/lang.c +++ b/wrapperhelper/src/lang.c @@ -394,7 +394,8 @@ void del_str2kw(void) { kh_destroy(str2kw, str2kw); } -int num_constant_convert(string_t *str, num_constant_t *cst) { +// ptr_is_32bits is actially long_is_32bits +int num_constant_convert(string_t *str, num_constant_t *cst, int ptr_is_32bits) { if (string_len(str) == 0) return 0; // Should never happen #define contains(c) strchr(string_content(str), c) if (contains('.') @@ -486,10 +487,10 @@ int num_constant_convert(string_t *str, num_constant_t *cst) { // If base == 10, keep the signness; in any case, try 32 bits if available else use 64 bits cst->typ = ((suffix_type & SUFFIX_SGN) == SUFFIX_U) ? - ((suffix_type & SUFFIX_SZ) == SUFFIX_L) ? LONG_IS_32BITS ? NCT_UINT32 : NCT_UINT64 : + ((suffix_type & SUFFIX_SZ) == SUFFIX_L) ? ptr_is_32bits ? NCT_UINT32 : NCT_UINT64 : ((suffix_type & SUFFIX_SZ) == SUFFIX_LL) ? NCT_UINT64 : NCT_UINT32 : - ((suffix_type & SUFFIX_SZ) == SUFFIX_L) ? LONG_IS_32BITS ? NCT_INT32 : NCT_INT64 : + ((suffix_type & SUFFIX_SZ) == SUFFIX_L) ? ptr_is_32bits ? NCT_INT32 : NCT_INT64 : ((suffix_type & SUFFIX_SZ) == SUFFIX_LL) ? NCT_INT64 : NCT_INT32; if (cst->typ == NCT_INT32) { @@ -795,7 +796,6 @@ struct_t *struct_new(int is_struct, string_t *tag) { return ret; } -_Static_assert(sizeof(type_t*) == sizeof(khint64_t), "Not a 64-bits machine"); khint_t type_t_hash(type_t *typ) { switch (typ->typ) { case TYPE_BUILTIN: return kh_int_hash_func(typ->val.builtin); @@ -1043,49 +1043,7 @@ void struct_print(const struct_t *st) { } } -// TODO: per-arch array -size_t sizeof_btt[LAST_BUILTIN + 1] = { - [BTT_VOID] = 0, - [BTT_BOOL] = 1, - [BTT_CHAR] = 1, - [BTT_SCHAR] = 1, - [BTT_UCHAR] = 1, - [BTT_SHORT] = 2, - [BTT_SSHORT] = 2, - [BTT_USHORT] = 2, - [BTT_INT] = 4, - [BTT_SINT] = 4, - [BTT_UINT] = 4, - [BTT_LONG] = LONG_IS_32BITS ? 4 : 8, - [BTT_SLONG] = LONG_IS_32BITS ? 4 : 8, - [BTT_ULONG] = LONG_IS_32BITS ? 4 : 8, - [BTT_LONGLONG] = 8, - [BTT_SLONGLONG] = 8, - [BTT_ULONGLONG] = 8, - [BTT_INT128] = 16, - [BTT_SINT128] = 16, - [BTT_UINT128] = 16, - [BTT_S8] = 1, - [BTT_U8] = 1, - [BTT_S16] = 2, - [BTT_U16] = 2, - [BTT_S32] = 4, - [BTT_U32] = 4, - [BTT_S64] = 8, - [BTT_U64] = 8, - [BTT_FLOAT] = 4, - [BTT_CFLOAT] = 8, - [BTT_IFLOAT] = 4, - [BTT_DOUBLE] = 8, - [BTT_CDOUBLE] = 16, - [BTT_IDOUBLE] = 8, - [BTT_LONGDOUBLE] = 16, - [BTT_CLONGDOUBLE] = 32, - [BTT_ILONGDOUBLE] = 16, - [BTT_VA_LIST] = LONG_IS_32BITS ? 0 : 24, // TODO -}; -// The following assumes sizeof(unsigned long) == sizeof(void*) -file_t *file_new(void) { +file_t *file_new(machine_t *target) { file_t *ret = malloc(sizeof *ret); if (!ret) { printf("Failed to create a new translation unit structure (init)\n"); @@ -1140,7 +1098,7 @@ file_t *file_new(void) { // Now fill in the builtin types int iret; khiter_t it; for (enum type_builtin_e i = 0; i < LAST_BUILTIN + 1; ++i) { - type_t *t = malloc(sizeof *t); + type_t *t = type_new(); if (!t) { printf("Failed to create a new translation unit structure (builtin type)\n"); for (; i--;) { @@ -1155,14 +1113,11 @@ file_t *file_new(void) { free(ret); return NULL; } - t->is_atomic = t->is_const = t->is_restrict = t->is_volatile = t->_internal_use = 0; t->is_incomplete = (i == BTT_VOID); - t->converted = NULL; // Maybe should be something else? - t->is_validated = 1; t->nrefs = 2; t->typ = TYPE_BUILTIN; t->val.builtin = i; - t->szinfo.align = t->szinfo.size = sizeof_btt[i]; + validate_type(target, t); ret->builtins[i] = t; kh_put(type_set, ret->type_set, t, &iret); if (iret < 0) { @@ -1196,26 +1151,25 @@ file_t *file_new(void) { char *sdup; #define ADD_TYPEDEF(name, btt) \ sdup = strdup(#name); \ - if (!sdup) { \ - printf("Failed to create a new translation unit structure (" #name " name)\n"); \ - file_del(ret); \ - return NULL; \ - } \ - it = kh_put(type_map, ret->type_map, sdup, &iret); \ - if (iret < 0) { \ - printf("Failed to create a new translation unit structure (add " #name " typedef)\n"); \ - free(sdup); \ - file_del(ret); \ - return NULL; \ - } else if (iret == 0) { \ - printf("Failed to create a new translation unit structure (" #name " is already a typedef)\n"); \ - free(sdup); \ - file_del(ret); \ - return NULL; \ - } \ - kh_val(ret->type_map, it) = ret->builtins[BTT_ ## btt]; \ - ++ret->builtins[BTT_ ## btt]->nrefs; - + if (!sdup) { \ + printf("Failed to create a new translation unit structure (" #name " name)\n"); \ + file_del(ret); \ + return NULL; \ + } \ + it = kh_put(type_map, ret->type_map, sdup, &iret); \ + if (iret < 0) { \ + printf("Failed to create a new translation unit structure (add " #name " typedef)\n"); \ + free(sdup); \ + file_del(ret); \ + return NULL; \ + } else if (iret == 0) { \ + printf("Failed to create a new translation unit structure (" #name " is already a typedef)\n"); \ + free(sdup); \ + file_del(ret); \ + return NULL; \ + } \ + kh_val(ret->type_map, it) = ret->builtins[BTT_ ## btt]; \ + ++ret->builtins[BTT_ ## btt]->nrefs; ADD_TYPEDEF(__builtin_va_list, VA_LIST) ADD_TYPEDEF(__int128_t, INT128) ADD_TYPEDEF(__uint128_t, UINT128) diff --git a/wrapperhelper/src/lang.h b/wrapperhelper/src/lang.h index 682bbdda..f5807f97 100644 --- a/wrapperhelper/src/lang.h +++ b/wrapperhelper/src/lang.h @@ -5,10 +5,9 @@ #include "cstring.h" #include "khash.h" +#include "machine.h" #include "vector.h" -#define LONG_IS_32BITS 0 - enum token_sym_type_e { SYM_LBRACKET, SYM_RBRACKET, @@ -191,7 +190,7 @@ typedef struct num_constant_s { uint64_t u64; } val; } num_constant_t; -int num_constant_convert(string_t *str, num_constant_t *cst); +int num_constant_convert(string_t *str, num_constant_t *cst, int ptr_is_32bits); KHASH_MAP_DECLARE_STR(const_map, num_constant_t) typedef struct expr_s { @@ -381,6 +380,7 @@ typedef struct st_member_s { type_t *typ; _Bool is_bitfield; size_t bitfield_width; + // TODO: add byte_offset then check in generator against both archs for every named members } st_member_t; typedef struct struct_s { string_t *tag; @@ -421,7 +421,7 @@ typedef struct file_s { khash_t(const_map) *const_map; khash_t(type_set) *type_set; } file_t; -file_t *file_new(void); +file_t *file_new(machine_t *target); void file_del(file_t *f); extern const char *sym2str[LAST_SYM + 1]; diff --git a/wrapperhelper/src/machine.c b/wrapperhelper/src/machine.c index 7637a5d3..d20c3e1f 100644 --- a/wrapperhelper/src/machine.c +++ b/wrapperhelper/src/machine.c @@ -102,6 +102,8 @@ int init_machines(size_t npaths, const char *const *extra_include_path) { #pragma GCC diagnostic ignored "-Wanalyzer-malloc-leak" #define CUR_MACHINE x86_64 machine_x86_64.size_long = 8; + machine_x86_64.align_valist = 8; + machine_x86_64.size_valist = 24; INIT_PATHS #define DO_PATH INCR_NPATHS #include "machine.gen" @@ -182,3 +184,215 @@ static void machine_del(machine_t *m) { void del_machines(void) { machine_del(&machine_x86_64); } + +int validate_type(machine_t *target, type_t *typ) { + if (typ->is_validated) return 1; + typ->is_validated = 1; + if (typ->is_restrict) { + if (typ->typ != TYPE_PTR) { + printf("Error: only pointers to object types may be restrict-qualified\n"); + return 0; + } + if (typ->val.typ->typ == TYPE_FUNCTION) { + printf("Error: only pointers to object types may be restrict-qualified\n"); + return 0; + } + } + if (typ->is_atomic) { + if ((typ->typ == TYPE_ARRAY) || (typ->typ == TYPE_FUNCTION)) { + printf("Error: array types and function types may not be atomic-qualified\n"); + return 0; + } + } + switch (typ->typ) { + case TYPE_BUILTIN: + switch (typ->val.builtin) { + case BTT_VOID: typ->szinfo.align = typ->szinfo.size = 0; break; + case BTT_BOOL: typ->szinfo.align = typ->szinfo.size = 1; break; + case BTT_CHAR: typ->szinfo.align = typ->szinfo.size = 1; break; + case BTT_SCHAR: typ->szinfo.align = typ->szinfo.size = 1; break; + case BTT_UCHAR: typ->szinfo.align = typ->szinfo.size = 1; break; + case BTT_SHORT: typ->szinfo.align = typ->szinfo.size = 2; break; + case BTT_SSHORT: typ->szinfo.align = typ->szinfo.size = 2; break; + case BTT_USHORT: typ->szinfo.align = typ->szinfo.size = 2; break; + case BTT_INT: typ->szinfo.align = typ->szinfo.size = 4; break; + case BTT_SINT: typ->szinfo.align = typ->szinfo.size = 4; break; + case BTT_UINT: typ->szinfo.align = typ->szinfo.size = 4; break; + case BTT_LONG: typ->szinfo.align = typ->szinfo.size = target->size_long; break; + case BTT_SLONG: typ->szinfo.align = typ->szinfo.size = target->size_long; break; + case BTT_ULONG: typ->szinfo.align = typ->szinfo.size = target->size_long; break; + case BTT_LONGLONG: typ->szinfo.align = typ->szinfo.size = 8; break; + case BTT_SLONGLONG: typ->szinfo.align = typ->szinfo.size = 8; break; + case BTT_ULONGLONG: typ->szinfo.align = typ->szinfo.size = 8; break; + case BTT_INT128: typ->szinfo.align = typ->szinfo.size = 16; break; + case BTT_SINT128: typ->szinfo.align = typ->szinfo.size = 16; break; + case BTT_UINT128: typ->szinfo.align = typ->szinfo.size = 16; break; + case BTT_S8: typ->szinfo.align = typ->szinfo.size = 1; break; + case BTT_U8: typ->szinfo.align = typ->szinfo.size = 1; break; + case BTT_S16: typ->szinfo.align = typ->szinfo.size = 2; break; + case BTT_U16: typ->szinfo.align = typ->szinfo.size = 2; break; + case BTT_S32: typ->szinfo.align = typ->szinfo.size = 4; break; + case BTT_U32: typ->szinfo.align = typ->szinfo.size = 4; break; + case BTT_S64: typ->szinfo.align = typ->szinfo.size = 8; break; + case BTT_U64: typ->szinfo.align = typ->szinfo.size = 8; break; + case BTT_FLOAT: typ->szinfo.align = typ->szinfo.size = 4; break; + case BTT_CFLOAT: typ->szinfo.align = typ->szinfo.size = 8; break; + case BTT_IFLOAT: typ->szinfo.align = typ->szinfo.size = 4; break; + case BTT_DOUBLE: typ->szinfo.align = typ->szinfo.size = 8; break; + case BTT_CDOUBLE: typ->szinfo.align = typ->szinfo.size = 16; break; + case BTT_IDOUBLE: typ->szinfo.align = typ->szinfo.size = 8; break; + case BTT_LONGDOUBLE: typ->szinfo.align = typ->szinfo.size = 16; break; + case BTT_CLONGDOUBLE: typ->szinfo.align = typ->szinfo.size = 32; break; + case BTT_ILONGDOUBLE: typ->szinfo.align = typ->szinfo.size = 16; break; + case BTT_VA_LIST: typ->szinfo.align = target->align_valist; typ->szinfo.size = target->size_valist; break; + default: + printf("Unknown builtin %u, cannot fill size info\n", typ->val.builtin); + return 0; + } + return 1; + case TYPE_ARRAY: + if (typ->val.array.typ->is_incomplete || (typ->val.array.typ->typ == TYPE_FUNCTION)) { + printf("Error: array types must point to complete object types\n"); + return 0; + } + if ((typ->val.array.typ->typ == TYPE_STRUCT_UNION) && typ->val.array.typ->val.st->has_incomplete) { + printf("Error: array types may not (inductively) point to structures which last element is incomplete\n"); + return 0; + } + if ((typ->is_atomic) || (typ->is_const) || (typ->is_restrict) || (typ->is_volatile)) { + // qualifier-type-list in array declaration is only allowed in function argument declaration under certain circumstances + printf("Error: array types may not be qualified\n"); + return 0; + } + if (!validate_type(target, typ->val.array.typ)) return 0; + if (typ->val.array.array_sz == (size_t)-1) { + typ->szinfo.size = 0; + typ->szinfo.align = (typ->val.array.typ->szinfo.align < 16) ? 16 : typ->val.array.typ->szinfo.align; + } else { + typ->szinfo.size = typ->val.array.array_sz * typ->val.array.typ->szinfo.size; + typ->szinfo.align = + ((typ->szinfo.size >= 16) && (typ->val.array.typ->szinfo.align < 16)) ? + 16 : + typ->val.array.typ->szinfo.align; + } + return 1; + case TYPE_PTR: + typ->szinfo.size = target->size_long; + typ->szinfo.align = target->size_long; + return validate_type(target, typ->val.typ); + case TYPE_FUNCTION: + if ((typ->val.fun.ret->typ == TYPE_FUNCTION) || (typ->val.fun.ret->typ == TYPE_ARRAY)) { + printf("Error: function types may not return function or array types\n"); + return 0; + } + if (typ->val.fun.nargs != (size_t)-1) { + for (size_t i = 0; i < typ->val.fun.nargs; ++i) { + // Adjust the argument if necessary + if (typ->val.fun.args[i]->typ == TYPE_ARRAY) { + // Adjustment to pointer + typ->val.fun.args[i]->typ = TYPE_PTR; + typ->val.fun.args[i]->val.typ = typ->val.fun.args[i]->val.array.typ; + } else if (typ->val.fun.args[i]->typ == TYPE_FUNCTION) { + // Adjustment to pointer + type_t *t2 = type_new_ptr(typ->val.fun.args[i]); + if (!t2) { + printf("Error: failed to adjust type of argument from function to pointer\n"); + return 0; + } + typ->val.fun.args[i] = t2; + } + if (!validate_type(target, typ->val.fun.args[i])) return 0; + } + } + typ->szinfo.size = 0; + typ->szinfo.align = 0; + return validate_type(target, typ->val.fun.ret); + case TYPE_STRUCT_UNION: { + if (!typ->val.st->is_defined) return typ->is_incomplete; + size_t max_align = 1, cur_sz = 0, cur_bit = 0; + for (size_t i = 0; i < typ->val.st->nmembers; ++i) { + // Adjust the argument if necessary + st_member_t *mem = &typ->val.st->members[i]; + if (mem->typ->typ == TYPE_FUNCTION) { + printf("Error: structures may not contain function members\n"); + return 0; + } + if (mem->typ->is_incomplete) { + if ((i != typ->val.st->nmembers - 1) || !typ->val.st->is_struct || (mem->typ->typ != TYPE_ARRAY)) { + // The last element of a structure may be a VLA + printf("Error: structures may not contain incomplete members\n"); + return 0; + } + typ->val.st->has_incomplete = 1; + } + if (!validate_type(target, mem->typ)) return 0; + if (!typ->val.st->is_struct && (mem->typ->typ == TYPE_STRUCT_UNION)) { + typ->val.st->has_incomplete |= mem->typ->val.st->has_incomplete; + } + if (mem->is_bitfield) { + if (!typ->val.st->is_struct) { + printf("Error: TODO: bitfield in union\n"); + return 0; + } + if (mem->typ->is_atomic) { + printf("Error: atomic bitfields are not supported\n"); + return 0; + } + if (mem->typ->typ != TYPE_BUILTIN) { + printf("Error: bitfields can only have a specific subset of types\n"); + return 0; + } + if ((mem->typ->val.builtin != BTT_BOOL) && (mem->typ->val.builtin != BTT_INT) + && (mem->typ->val.builtin != BTT_SINT) && (mem->typ->val.builtin != BTT_UINT)) { + printf("Error: bitfields can only have a specific subset of types\n"); + return 0; + } + if (!mem->name && (mem->typ->szinfo.align > max_align)) { + printf("Error: TODO: unnamed bitfield member with greater alignment (width=%zu)\n", mem->bitfield_width); + return 0; + } + if (mem->bitfield_width) { + if (mem->name && (max_align < mem->typ->szinfo.align)) max_align = mem->typ->szinfo.align; + size_t cur_block = cur_sz / mem->typ->szinfo.align; + size_t end_block = (cur_sz + (cur_bit + mem->bitfield_width - 1) / 8) / mem->typ->szinfo.align; + if (cur_block == end_block) { + cur_bit += mem->bitfield_width; + cur_sz += cur_bit / 8; + cur_bit %= 8; + } else { + cur_sz = ((cur_sz + mem->typ->szinfo.align - 1) & ~(mem->typ->szinfo.align - 1)) + (mem->bitfield_width / 8); + cur_bit = mem->bitfield_width % 8; + } + } else { + if (max_align < mem->typ->szinfo.align) max_align = mem->typ->szinfo.align; + cur_sz = ((cur_sz + mem->typ->szinfo.align - 1) & ~(mem->typ->szinfo.align - 1)) + mem->typ->szinfo.size; + printf("Error: TODO: unnamed zero-width bitfield member\n"); + return 0; + } + } else { + if (max_align < mem->typ->szinfo.align) max_align = mem->typ->szinfo.align; + if (typ->val.st->is_struct) { + if (cur_bit) { + cur_bit = 0; + ++cur_sz; + } + cur_sz = ((cur_sz + mem->typ->szinfo.align - 1) & ~(mem->typ->szinfo.align - 1)) + mem->typ->szinfo.size; + } else { + if (cur_sz < mem->typ->szinfo.size) cur_sz = mem->typ->szinfo.size; + } + } + } + if (cur_bit) { + cur_bit = 0; + ++cur_sz; + } + typ->szinfo.align = max_align; + typ->szinfo.size = (cur_sz + max_align - 1) & ~(max_align - 1); + return 1; } + case TYPE_ENUM: + if (typ->val.typ->typ != TYPE_BUILTIN) return 0; + typ->szinfo = typ->val.typ->szinfo; + return 1; + } + return 0; +} diff --git a/wrapperhelper/src/machine.h b/wrapperhelper/src/machine.h index 0f850fef..5570a4af 100644 --- a/wrapperhelper/src/machine.h +++ b/wrapperhelper/src/machine.h @@ -8,6 +8,7 @@ #include "vector.h" struct macro_s; // preproc_private.h +struct type_s; // lang.h typedef struct machine_s { // Preprocessor @@ -20,6 +21,7 @@ typedef struct machine_s { // Parsing size_t size_long; + size_t align_valist, size_valist; // TODO: also have info on unnamed bitfields, etc } machine_t; @@ -30,4 +32,6 @@ extern machine_t machine_x86_64; int init_machines(size_t npaths, const char *const *extra_include_path); void del_machines(void); +int validate_type(machine_t *target, struct type_s *typ); + #endif // MACHINE_H diff --git a/wrapperhelper/src/parse.c b/wrapperhelper/src/parse.c index 379df988..8b56cb15 100644 --- a/wrapperhelper/src/parse.c +++ b/wrapperhelper/src/parse.c @@ -79,179 +79,10 @@ VECTOR_IMPL_STATIC(size_t, (void)) #define VALIDATION_DECL 1 #define VALIDATION_LAST_DECL 2 #define VALIDATION_FUN 3 -// Assumes sizeof(void*) == sizeof(unsigned long) -static int validate_type(type_t *typ, type_t *(*builtins)[LAST_BUILTIN + 1]) { - if (typ->is_validated) return 1; - typ->is_validated = 1; - if (typ->is_restrict) { - if (typ->typ != TYPE_PTR) { - printf("Error: only pointers to object types may be restrict-qualified\n"); - return 0; - } - if (typ->val.typ->typ == TYPE_FUNCTION) { - printf("Error: only pointers to object types may be restrict-qualified\n"); - return 0; - } - } - if (typ->is_atomic) { - if ((typ->typ == TYPE_ARRAY) || (typ->typ == TYPE_FUNCTION)) { - printf("Error: array types and function types may not be atomic-qualified\n"); - return 0; - } - } - switch (typ->typ) { - case TYPE_BUILTIN: - typ->szinfo = (*builtins)[typ->val.builtin]->szinfo; - return 1; - case TYPE_ARRAY: - if (typ->val.array.typ->is_incomplete || (typ->val.array.typ->typ == TYPE_FUNCTION)) { - printf("Error: array types must point to complete object types\n"); - return 0; - } - if ((typ->val.array.typ->typ == TYPE_STRUCT_UNION) && typ->val.array.typ->val.st->has_incomplete) { - printf("Error: array types may not (inductively) point to structures which last element is incomplete\n"); - return 0; - } - if ((typ->is_atomic) || (typ->is_const) || (typ->is_restrict) || (typ->is_volatile)) { - // qualifier-type-list in array declaration is only allowed in function argument declaration under certain circumstances - printf("Error: array types may not be qualified\n"); - return 0; - } - if (!validate_type(typ->val.array.typ, builtins)) return 0; - if (typ->val.array.array_sz == (size_t)-1) { - typ->szinfo.size = 0; - typ->szinfo.align = (typ->val.array.typ->szinfo.align < 16) ? 16 : typ->val.array.typ->szinfo.align; - } else { - typ->szinfo.size = typ->val.array.array_sz * typ->val.array.typ->szinfo.size; - typ->szinfo.align = - ((typ->szinfo.size >= 16) && (typ->val.array.typ->szinfo.align < 16)) ? - 16 : - typ->val.array.typ->szinfo.align; - } - return 1; - case TYPE_PTR: - typ->szinfo.size = LONG_IS_32BITS ? 4 : 8; - typ->szinfo.align = LONG_IS_32BITS ? 4 : 8; - return validate_type(typ->val.typ, builtins); - case TYPE_FUNCTION: - if ((typ->val.fun.ret->typ == TYPE_FUNCTION) || (typ->val.fun.ret->typ == TYPE_ARRAY)) { - printf("Error: function types may not return function or array types\n"); - return 0; - } - if (typ->val.fun.nargs != (size_t)-1) { - for (size_t i = 0; i < typ->val.fun.nargs; ++i) { - // Adjust the argument if necessary - if (typ->val.fun.args[i]->typ == TYPE_ARRAY) { - // Adjustment to pointer - typ->val.fun.args[i]->typ = TYPE_PTR; - typ->val.fun.args[i]->val.typ = typ->val.fun.args[i]->val.array.typ; - } else if (typ->val.fun.args[i]->typ == TYPE_FUNCTION) { - // Adjustment to pointer - type_t *t2 = type_new_ptr(typ->val.fun.args[i]); - if (!t2) { - printf("Error: failed to adjust type of argument from function to pointer\n"); - return 0; - } - typ->val.fun.args[i] = t2; - } - if (!validate_type(typ->val.fun.args[i], builtins)) return 0; - } - } - typ->szinfo.size = 0; - typ->szinfo.align = 0; - return validate_type(typ->val.fun.ret, builtins); - case TYPE_STRUCT_UNION: { - if (!typ->val.st->is_defined) return typ->is_incomplete; - size_t max_align = 1, cur_sz = 0, cur_bit = 0; - for (size_t i = 0; i < typ->val.st->nmembers; ++i) { - // Adjust the argument if necessary - st_member_t *mem = &typ->val.st->members[i]; - if (mem->typ->typ == TYPE_FUNCTION) { - printf("Error: structures may not contain function members\n"); - return 0; - } - if (mem->typ->is_incomplete) { - if ((i != typ->val.st->nmembers - 1) || !typ->val.st->is_struct || (mem->typ->typ != TYPE_ARRAY)) { - // The last element of a structure may be a VLA - printf("Error: structures may not contain incomplete members\n"); - return 0; - } - typ->val.st->has_incomplete = 1; - } - if (!validate_type(mem->typ, builtins)) return 0; - if (!typ->val.st->is_struct && (mem->typ->typ == TYPE_STRUCT_UNION)) { - typ->val.st->has_incomplete |= mem->typ->val.st->has_incomplete; - } - if (mem->is_bitfield) { - if (!typ->val.st->is_struct) { - printf("Error: TODO: bitfield in union\n"); - return 0; - } - if (mem->typ->is_atomic) { - printf("Error: atomic bitfields are not supported\n"); - return 0; - } - if (mem->typ->typ != TYPE_BUILTIN) { - printf("Error: bitfields can only have a specific subset of types\n"); - return 0; - } - if ((mem->typ->val.builtin != BTT_BOOL) && (mem->typ->val.builtin != BTT_INT) - && (mem->typ->val.builtin != BTT_SINT) && (mem->typ->val.builtin != BTT_UINT)) { - printf("Error: bitfields can only have a specific subset of types\n"); - return 0; - } - if (!mem->name && (mem->typ->szinfo.align > max_align)) { - printf("Error: TODO: unnamed bitfield member with greater alignment (width=%zu)\n", mem->bitfield_width); - return 0; - } - if (mem->bitfield_width) { - if (mem->name && (max_align < mem->typ->szinfo.align)) max_align = mem->typ->szinfo.align; - size_t cur_block = cur_sz / mem->typ->szinfo.align; - size_t end_block = (cur_sz + (cur_bit + mem->bitfield_width - 1) / 8) / mem->typ->szinfo.align; - if (cur_block == end_block) { - cur_bit += mem->bitfield_width; - cur_sz += cur_bit / 8; - cur_bit %= 8; - } else { - cur_sz = ((cur_sz + mem->typ->szinfo.align - 1) & ~(mem->typ->szinfo.align - 1)) + (mem->bitfield_width / 8); - cur_bit = mem->bitfield_width % 8; - } - } else { - if (max_align < mem->typ->szinfo.align) max_align = mem->typ->szinfo.align; - cur_sz = ((cur_sz + mem->typ->szinfo.align - 1) & ~(mem->typ->szinfo.align - 1)) + mem->typ->szinfo.size; - printf("Error: TODO: unnamed zero-width bitfield member\n"); - return 0; - } - } else { - if (max_align < mem->typ->szinfo.align) max_align = mem->typ->szinfo.align; - if (typ->val.st->is_struct) { - if (cur_bit) { - cur_bit = 0; - ++cur_sz; - } - cur_sz = ((cur_sz + mem->typ->szinfo.align - 1) & ~(mem->typ->szinfo.align - 1)) + mem->typ->szinfo.size; - } else { - if (cur_sz < mem->typ->szinfo.size) cur_sz = mem->typ->szinfo.size; - } - } - } - if (cur_bit) { - cur_bit = 0; - ++cur_sz; - } - typ->szinfo.align = max_align; - typ->szinfo.size = (cur_sz + max_align - 1) & ~(max_align - 1); - return 1; } - case TYPE_ENUM: - if (typ->val.typ->typ != TYPE_BUILTIN) return 0; - typ->szinfo = typ->val.typ->szinfo; - return 1; - } - return 0; -} -static int validate_storage_type(enum decl_storage storage, type_t *(*builtins)[LAST_BUILTIN + 1], type_t *typ, enum token_sym_type_e sym) { +static int validate_storage_type(machine_t *target, enum decl_storage storage, + type_t *typ, enum token_sym_type_e sym) { // We may still do adjustments here - if (!validate_type(typ, builtins)) return 0; + if (!validate_type(target, typ)) return 0; if (typ->typ == TYPE_FUNCTION) { if ((storage == STORAGE_TLS) || (storage == STORAGE_TLS_EXTERN) || (storage == STORAGE_TLS_STATIC)) { printf("Error: functions cannot be thread local\n"); @@ -459,12 +290,12 @@ struct parse_declarator_dest_s { #define PDECL_TYPE_SET ((is_init && is_list) ? dest->f->type_set : (!is_init && is_list) ? dest->structms.type_set : dest->argt.type_set) #define PDECL_BUILTINS ((is_init && is_list) ? &dest->f->builtins : (!is_init && is_list) ? dest->structms.builtins : dest->argt.builtins) #define PDECL_CONST_MAP ((is_init && is_list) ? dest->f->const_map : (!is_init && is_list) ? dest->structms.const_map : dest->argt.const_map) -static int parse_declarator(struct parse_declarator_dest_s *dest, preproc_t *prep, proc_token_t *tok, enum decl_storage storage, enum fun_spec fspec, - type_t *base_type, int is_init, int is_list, int allow_decl, int allow_abstract); +static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *dest, preproc_t *prep, proc_token_t *tok, enum decl_storage storage, + enum fun_spec fspec, type_t *base_type, int is_init, int is_list, int allow_decl, int allow_abstract); // declaration-specifier with storage != NULL // specifier-qualifier-list + static_assert-declaration with storage == NULL -static int parse_declaration_specifier(khash_t(struct_map) *struct_map, khash_t(type_map) *type_map, khash_t(type_map) *enum_map, +static int parse_declaration_specifier(machine_t *target, khash_t(struct_map) *struct_map, khash_t(type_map) *type_map, khash_t(type_map) *enum_map, type_t *(*builtins)[LAST_BUILTIN + 1], khash_t(const_map) *const_map, khash_t(type_set) *type_set, preproc_t *prep, proc_token_t *tok, enum decl_storage *storage, enum fun_spec *fspec, enum decl_spec *spec, type_t *typ); @@ -584,17 +415,17 @@ static int is_type_spec_qual_kw(enum token_keyword_type_e kw) { #define IS_BEGIN_TYPE_NAME \ (((tok->tokt == PTOK_KEYWORD) && is_type_spec_qual_kw(tok->tokv.kw)) || \ ((tok->tokt == PTOK_IDENT) && ((it = kh_get(type_map, type_map, string_content(tok->tokv.str))) != kh_end(type_map)))) -static int parse_type_name(khash_t(struct_map) *struct_map, khash_t(type_map) *type_map, khash_t(type_map) *enum_map, +static int parse_type_name(machine_t *target, khash_t(struct_map) *struct_map, khash_t(type_map) *type_map, khash_t(type_map) *enum_map, type_t *(*builtins)[LAST_BUILTIN + 1], khash_t(const_map) *const_map, khash_t(type_set) *type_set, preproc_t *prep, proc_token_t *tok, enum token_sym_type_e end_sym, type_t **typ) { enum decl_spec spec = SPEC_NONE; - if (!parse_declaration_specifier(struct_map, type_map, enum_map, builtins, const_map, type_set, prep, tok, NULL, NULL, &spec, *typ)) { + if (!parse_declaration_specifier(target, struct_map, type_map, enum_map, builtins, const_map, type_set, prep, tok, NULL, NULL, &spec, *typ)) { type_del(*typ); goto failed; } *typ = type_try_merge(*typ, type_set); if ((tok->tokt == PTOK_SYM) && (tok->tokv.sym == end_sym)) { - return validate_type(*typ, builtins); + return validate_type(target, *typ); } struct parse_declarator_dest_s dest2; dest2.argt.dest = NULL; @@ -604,7 +435,7 @@ static int parse_type_name(khash_t(struct_map) *struct_map, khash_t(type_map) *t dest2.argt.type_set = type_set; dest2.argt.builtins = builtins; dest2.argt.const_map = const_map; - if (!parse_declarator(&dest2, prep, tok, STORAGE_NONE, FSPEC_NONE, *typ, 0, 0, 0, 1)) { + if (!parse_declarator(target, &dest2, prep, tok, STORAGE_NONE, FSPEC_NONE, *typ, 0, 0, 0, 1)) { // Token is deleted type_del(*typ); goto failed; @@ -622,13 +453,13 @@ static int parse_type_name(khash_t(struct_map) *struct_map, khash_t(type_map) *t } *typ = dest2.argt.dest; *typ = type_try_merge(*typ, type_set); - return validate_type(*typ, builtins); + return validate_type(target, *typ); failed: return 0; } -static expr_t *parse_expression(khash_t(struct_map) *struct_map, khash_t(type_map) *type_map, khash_t(type_map) *enum_map, +static expr_t *parse_expression(machine_t *target, khash_t(struct_map) *struct_map, khash_t(type_map) *type_map, khash_t(type_map) *enum_map, type_t *(*builtins)[LAST_BUILTIN + 1], khash_t(const_map) *const_map, khash_t(type_set) *type_set, preproc_t *prep, proc_token_t *tok, int expr_level) { // Note that expr_level >= 1; expr_level = 0 doesn't appear in the grammar @@ -684,7 +515,7 @@ expr_new_token: goto failed; } e->typ = ETY_CONST; - if (!num_constant_convert(tok->tokv.str, &e->val.cst)) { + if (!num_constant_convert(tok->tokv.str, &e->val.cst, target->size_long == 4)) { string_del(tok->tokv.str); goto failed; } @@ -919,7 +750,7 @@ expr_new_token: proc_token_del(tok); goto failed; } - if (!parse_type_name(struct_map, type_map, enum_map, builtins, const_map, type_set, prep, tok, SYM_RPAREN, &typ)) { + if (!parse_type_name(target, struct_map, type_map, enum_map, builtins, const_map, type_set, prep, tok, SYM_RPAREN, &typ)) { goto failed; } if (!typ->is_validated || typ->is_incomplete) { @@ -1032,7 +863,7 @@ expr_new_token: proc_token_del(tok); goto failed; } - if (!parse_type_name(struct_map, type_map, enum_map, builtins, const_map, type_set, prep, tok, SYM_RPAREN, &typ)) { + if (!parse_type_name(target, struct_map, type_map, enum_map, builtins, const_map, type_set, prep, tok, SYM_RPAREN, &typ)) { type_del(typ); proc_token_del(tok); goto failed; @@ -1525,7 +1356,7 @@ static int eval_expression(expr_t *e, khash_t(const_map) *const_map, num_constan // declaration-specifier with storage != NULL // specifier-qualifier-list + static_assert-declaration with storage == NULL -static int parse_declaration_specifier(khash_t(struct_map) *struct_map, khash_t(type_map) *type_map, khash_t(type_map) *enum_map, +static int parse_declaration_specifier(machine_t *target, khash_t(struct_map) *struct_map, khash_t(type_map) *type_map, khash_t(type_map) *enum_map, type_t *(*builtins)[LAST_BUILTIN + 1], khash_t(const_map) *const_map, khash_t(type_set) *type_set, preproc_t *prep, proc_token_t *tok, enum decl_storage *storage, enum fun_spec *fspec, enum decl_spec *spec, type_t *typ) { @@ -1540,7 +1371,7 @@ static int parse_declaration_specifier(khash_t(struct_map) *struct_map, khash_t( } // Empty destructor *tok = proc_next_token(prep); - expr_t *e = parse_expression(struct_map, type_map, enum_map, builtins, const_map, type_set, prep, tok, 14); + expr_t *e = parse_expression(target, struct_map, type_map, enum_map, builtins, const_map, type_set, prep, tok, 14); if (!e) { goto failed; } @@ -2010,7 +1841,8 @@ parse_cur_token_decl: *tok = proc_next_token(prep); while (!proc_token_isend(tok) && ((tok->tokt != PTOK_SYM) || (tok->tokv.sym != SYM_RBRACKET))) { enum decl_spec spec2 = SPEC_NONE; - if (!parse_declaration_specifier(struct_map, type_map, enum_map, builtins, const_map, type_set, prep, tok, NULL, NULL, &spec2, typ2)) { + if (!parse_declaration_specifier(target, struct_map, type_map, enum_map, builtins, + const_map, type_set, prep, tok, NULL, NULL, &spec2, typ2)) { vector_del(st_members, members); type_del(typ2); goto failed; @@ -2057,7 +1889,7 @@ parse_cur_token_decl: dest2.structms.builtins = builtins; dest2.structms.const_map = const_map; dest2.structms.dest = members; - if (!parse_declarator(&dest2, prep, tok, STORAGE_NONE, FSPEC_NONE, typ2, 0, 1, 1, 1)) { + if (!parse_declarator(target, &dest2, prep, tok, STORAGE_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 +2047,7 @@ parse_cur_token_decl: } else if ((tok->tokt == PTOK_SYM) && (tok->tokv.sym == SYM_EQ)) { // Empty destructor *tok = proc_next_token(prep); - expr_t *e = parse_expression(struct_map, type_map, enum_map, builtins, const_map, type_set, prep, tok, 14); + expr_t *e = parse_expression(target, struct_map, type_map, enum_map, builtins, const_map, type_set, prep, tok, 14); if (!e) { goto failed; } @@ -2330,7 +2162,7 @@ parse_cur_token_decl: typ->val.typ = new_typ->val.typ = (*builtins)[btt]; typ->val.typ->nrefs += 2; new_typ = type_try_merge(new_typ, type_set); - validate_type(new_typ, builtins); // Assume it returns 1 + validate_type(target, new_typ); // Assume it returns 1 kh_val(enum_map, it) = new_typ; } else { typ->typ = TYPE_ENUM; @@ -2366,8 +2198,8 @@ failed: return 0; } -static int parse_declarator(struct parse_declarator_dest_s *dest, preproc_t *prep, proc_token_t *tok, enum decl_storage storage, enum fun_spec fspec, - type_t *base_type, int is_init, int is_list, int allow_decl, int allow_abstract) { +static int parse_declarator(machine_t *target, struct parse_declarator_dest_s *dest, preproc_t *prep, proc_token_t *tok, enum decl_storage storage, + enum fun_spec fspec, type_t *base_type, int is_init, int is_list, int allow_decl, int allow_abstract) { int has_list = 0, has_ident = 0; // TODO: allow_abstract and 'direct-abstract-declarator(opt) ( parameter-type-list(opt) )' @@ -2476,8 +2308,8 @@ static int parse_declarator(struct parse_declarator_dest_s *dest, preproc_t *pre } enum decl_storage storage2 = STORAGE_NONE; enum decl_spec spec2 = SPEC_NONE; - if (!parse_declaration_specifier(PDECL_STRUCT_MAP, PDECL_TYPE_MAP, PDECL_ENUM_MAP, PDECL_BUILTINS, - PDECL_CONST_MAP, PDECL_TYPE_SET, prep, tok, &storage2, NULL, &spec2, typ2)) { + 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)) { // Token is deleted vector_del(types, args); type_del(typ2); @@ -2522,7 +2354,7 @@ static int parse_declarator(struct parse_declarator_dest_s *dest, preproc_t *pre dest2.argt.type_set = PDECL_TYPE_SET; dest2.argt.builtins = PDECL_BUILTINS; dest2.argt.const_map = PDECL_CONST_MAP; - if (!parse_declarator(&dest2, prep, tok, STORAGE_NONE, FSPEC_NONE, typ2, 0, 0, 1, 1)) { + if (!parse_declarator(target, &dest2, prep, tok, STORAGE_NONE, FSPEC_NONE, typ2, 0, 0, 1, 1)) { // Token is deleted vector_del(types, args); type_del(typ2); @@ -2644,7 +2476,8 @@ static int parse_declarator(struct parse_declarator_dest_s *dest, preproc_t *pre } else { // Constant expression, followed by ']' is_incomplete = 0; - expr_t *e = parse_expression(PDECL_STRUCT_MAP, PDECL_TYPE_MAP, PDECL_ENUM_MAP, PDECL_BUILTINS, PDECL_CONST_MAP, PDECL_TYPE_SET, prep, tok, 15); + expr_t *e = parse_expression(target, PDECL_STRUCT_MAP, PDECL_TYPE_MAP, PDECL_ENUM_MAP, PDECL_BUILTINS, + PDECL_CONST_MAP, PDECL_TYPE_SET, prep, tok, 15); if (!e) { goto failed; } @@ -2767,7 +2600,7 @@ static int parse_declarator(struct parse_declarator_dest_s *dest, preproc_t *pre // Try to free some redundant types typ = type_try_merge(typ, PDECL_TYPE_SET); - int validation = validate_storage_type(storage, PDECL_BUILTINS, typ, tok->tokv.sym); + int validation = validate_storage_type(target, storage, typ, tok->tokv.sym); if (!validation) { // Empty destructor goto failed; @@ -2921,7 +2754,8 @@ static int parse_declarator(struct parse_declarator_dest_s *dest, preproc_t *pre goto failed; } } else { - expr_t *e = parse_expression(PDECL_STRUCT_MAP, PDECL_TYPE_MAP, PDECL_ENUM_MAP, PDECL_BUILTINS, PDECL_CONST_MAP, PDECL_TYPE_SET, prep, tok, 15); + expr_t *e = parse_expression(target, PDECL_STRUCT_MAP, PDECL_TYPE_MAP, PDECL_ENUM_MAP, PDECL_BUILTINS, + PDECL_CONST_MAP, PDECL_TYPE_SET, prep, tok, 15); if (!e) { printf("Error: invalid declaration initializer\n"); goto failed; @@ -2955,7 +2789,7 @@ static int parse_declarator(struct parse_declarator_dest_s *dest, preproc_t *pre // storage == STORAGE_NONE *tok = proc_next_token(prep); - expr_t *e = parse_expression(dest->structms.struct_map, dest->structms.type_map, dest->structms.enum_map, + 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, prep, tok, 14); if (!e) { @@ -2975,7 +2809,7 @@ static int parse_declarator(struct parse_declarator_dest_s *dest, preproc_t *pre } expr_del(e); - int validation = validate_storage_type(storage, PDECL_BUILTINS, typ, tok->tokv.sym); + int validation = validate_storage_type(target, storage, typ, tok->tokv.sym); if (!validation) { // Empty destructor goto failed; @@ -3146,7 +2980,7 @@ file_t *parse_file(machine_t *target, const char *filename, FILE *file) { if (dirname) free(dirname); return NULL; } - file_t *ret = file_new(); + file_t *ret = file_new(target); if (!ret) { printf("Failed to create the file structure\n"); preproc_del(prep); @@ -3201,7 +3035,7 @@ file_t *parse_file(machine_t *target, const char *filename, FILE *file) { goto failed; } tok = proc_next_token(prep); - if (!parse_type_name(ret->struct_map, ret->type_map, ret->enum_map, &ret->builtins, ret->const_map, ret->type_set, + 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; @@ -3226,16 +3060,16 @@ file_t *parse_file(machine_t *target, const char *filename, FILE *file) { enum decl_storage storage = STORAGE_NONE; enum fun_spec fspec = FSPEC_NONE; enum decl_spec spec = SPEC_NONE; - if (!parse_declaration_specifier(ret->struct_map, ret->type_map, ret->enum_map, &ret->builtins, ret->const_map, + if (!parse_declaration_specifier(target, ret->struct_map, ret->type_map, ret->enum_map, &ret->builtins, ret->const_map, ret->type_set, prep, &tok, &storage, &fspec, &spec, typ)) { goto failed; } if (spec == SPEC_NONE) continue; // Declaration was an assert, typ is unchanged typ = type_try_merge(typ, ret->type_set); if ((tok.tokt != PTOK_SYM) || (tok.tokv.sym != SYM_SEMICOLON)) { - if (!parse_declarator(&(struct parse_declarator_dest_s){.f = ret}, prep, &tok, storage, fspec, typ, 1, 1, 1, 0)) goto failed; + if (!parse_declarator(target, &(struct parse_declarator_dest_s){.f = ret}, prep, &tok, storage, fspec, typ, 1, 1, 1, 0)) goto failed; } else { - if (validate_storage_type(storage, &ret->builtins, typ, tok.tokv.sym) != VALIDATION_LAST_DECL) goto failed; + if (validate_storage_type(target, storage, typ, tok.tokv.sym) != VALIDATION_LAST_DECL) goto failed; if (fspec != FSPEC_NONE) { printf("Error: unexpected function specifier\n"); // Empty destructor diff --git a/wrapperhelper/src/preproc.c b/wrapperhelper/src/preproc.c index 00b34e4d..f402d82a 100644 --- a/wrapperhelper/src/preproc.c +++ b/wrapperhelper/src/preproc.c @@ -1063,7 +1063,7 @@ typedef struct preproc_eval_aux_s { } preproc_eval_aux_t; VECTOR_DECLARE_STATIC(ppeaux, preproc_eval_aux_t) VECTOR_IMPL_STATIC(ppeaux, (void)) -static int64_t preproc_eval(const VECTOR(preproc) *cond, int *aux_ret) { +static int64_t preproc_eval(const VECTOR(preproc) *cond, int *aux_ret, int ptr_is_32bits) { VECTOR(ppeaux) *stack = vector_new_cap(ppeaux, 1); if (!stack) { printf("Failed to allocate #if evaluation stack vector\n"); @@ -1083,7 +1083,7 @@ static int64_t preproc_eval(const VECTOR(preproc) *cond, int *aux_ret) { // Evaluate token as an integer if st0 == 0, error otherwise if (vector_last(ppeaux, stack).st0 == 0) { num_constant_t cst; - if (!num_constant_convert(tok->tokv.str, &cst)) { + if (!num_constant_convert(tok->tokv.str, &cst, ptr_is_32bits)) { goto eval_fail; } switch (cst.typ) { @@ -1106,7 +1106,6 @@ static int64_t preproc_eval(const VECTOR(preproc) *cond, int *aux_ret) { } else if ((tok->tokt == PPTOK_IDENT) || (tok->tokt == PPTOK_IDENT_UNEXP)) { // Evaluate token as 0 if st0 == 0, error otherwise if (vector_last(ppeaux, stack).st0 == 0) { - is_unsigned = 0; acc = 0; goto push_acc_to_st0; } else { @@ -2021,7 +2020,7 @@ check_if_depth: // Now we need to compute what is pointed by expanded, and increase cond_depth and ok_depth as needed int st; - int64_t res = preproc_eval(expanded, &st); + int64_t res = preproc_eval(expanded, &st, src->target->size_long == 4); vector_del(preproc, expanded); if (!st) { printf("Error: failed to evaluate #elif condition in (%s)\n", src->cur_file); @@ -2029,7 +2028,6 @@ check_if_depth: return (proc_token_t){ .tokt = PTOK_INVALID, .tokv = {.c = '\0'} }; } if (res) { - vector_last(ppsource, src->prep).srcv.prep.entered_next_ok_cond = 1; ++vector_last(ppsource, src->prep).srcv.prep.ok_depth; if (tok.tokt == PPTOK_NEWLINE) { src->st = PPST_NL; @@ -2064,8 +2062,8 @@ check_if_depth: // We may enter the following block, check it khiter_t it = kh_get(macros_map, src->macros_map, string_content(tok.tokv.str)); if (it != kh_end(src->macros_map)) { - ppsrc->srcv.prep.entered_next_ok_cond = 1; ++ppsrc->srcv.prep.ok_depth; + goto preproc_ignore_remaining_goto; } goto preproc_ignore_remaining; } @@ -2080,13 +2078,14 @@ check_if_depth: // We may enter the following block, check it khiter_t it = kh_get(macros_map, src->macros_map, string_content(tok.tokv.str)); if (it == kh_end(src->macros_map)) { - ppsrc->srcv.prep.entered_next_ok_cond = 1; ++ppsrc->srcv.prep.ok_depth; + goto preproc_ignore_remaining_goto; } goto preproc_ignore_remaining; } } else if (!strcmp(string_content(tok.tokv.str), "else")) { // Maybe increase ok_depth if ok_depth = cond_depth - 1; also goto check_if_depth + // Also, we only need to goto check_if_depth if we actually update ok_depth // Note that this (very naive) approach allows code such as: /* #ifdef M * ... // Not preprocessed *** Preprocessed @@ -2098,10 +2097,8 @@ check_if_depth: * ... // Preprocessed *** Not preprocessed * #endif */ - // Forbidding this code would require another 64-bits bitfield, which is redundant, thus not implemented. - // Also, we only need to goto check_if_depth if we actually update ok_depth + // Forbidding this code would require a 256-bits bitfield, which is big, thus not implemented. if ((ppsrc->srcv.prep.ok_depth == ppsrc->srcv.prep.cond_depth - 1) && !ppsrc->srcv.prep.entered_next_ok_cond) { - vector_last(ppsource, src->prep).srcv.prep.entered_next_ok_cond = 1; ++ppsrc->srcv.prep.ok_depth; goto preproc_ignore_remaining_goto; } else goto preproc_ignore_remaining; @@ -2852,11 +2849,10 @@ start_cur_token: printf("Invalid pragma wrappers explicit_simple directive, skipping until EOL\n"); goto preproc_hash_err; } - string_t *id = tok.tokv.str; src->st = PPST_PRAGMA_EXPLICIT; ret.tokt = PTOK_PRAGMA; ret.tokv.pragma.typ = PRAGMA_EXPLICIT_CONV; - ret.tokv.pragma.val = id; + ret.tokv.pragma.val = tok.tokv.str; return ret; } else { printf("Unknown pragma wrappers directive '%s', skipping until EOL\n", string_content(tok.tokv.str)); @@ -2919,7 +2915,7 @@ start_cur_token: // Now we need to compute what is pointed by expanded, and increase cond_depth and ok_depth as needed int st; - int64_t res = preproc_eval(expanded, &st); + int64_t res = preproc_eval(expanded, &st, src->target->size_long == 4); vector_del(preproc, expanded); if (!st) { printf("Error: failed to evaluate #if condition (%s)\n", src->cur_file); @@ -2930,7 +2926,6 @@ start_cur_token: } ++vector_last(ppsource, src->prep).srcv.prep.cond_depth; if (res) { - vector_last(ppsource, src->prep).srcv.prep.entered_next_ok_cond = 1; ++vector_last(ppsource, src->prep).srcv.prep.ok_depth; if (tok.tokt == PPTOK_NEWLINE) goto check_next_token; else goto start_cur_token; @@ -2963,7 +2958,6 @@ start_cur_token: // TODO: check iret, error if needed ++vector_last(ppsource, src->prep).srcv.prep.cond_depth; if (it != kh_end(src->macros_map)) { - vector_last(ppsource, src->prep).srcv.prep.entered_next_ok_cond = 1; ++vector_last(ppsource, src->prep).srcv.prep.ok_depth; goto preproc_hash_err; } else { @@ -2994,7 +2988,6 @@ start_cur_token: // TODO: check iret, error if needed ++vector_last(ppsource, src->prep).srcv.prep.cond_depth; if (it == kh_end(src->macros_map)) { - vector_last(ppsource, src->prep).srcv.prep.entered_next_ok_cond = 1; ++vector_last(ppsource, src->prep).srcv.prep.ok_depth; goto preproc_hash_err; } else { @@ -3008,6 +3001,7 @@ start_cur_token: goto preproc_hash_err; } if (vector_last(ppsource, src->prep).srcv.prep.ok_depth) { + vector_last(ppsource, src->prep).srcv.prep.entered_next_ok_cond = 1; --vector_last(ppsource, src->prep).srcv.prep.ok_depth; goto preproc_hash_err_goto; } else { @@ -3033,6 +3027,7 @@ start_cur_token: // We don't care about iret(?) // TODO: check iret, error if needed if (vector_last(ppsource, src->prep).srcv.prep.ok_depth) { + vector_last(ppsource, src->prep).srcv.prep.entered_next_ok_cond = 1; --vector_last(ppsource, src->prep).srcv.prep.ok_depth; goto preproc_hash_err_goto; } else { @@ -3058,6 +3053,7 @@ start_cur_token: // We don't care about iret(?) // TODO: check iret, error if needed if (vector_last(ppsource, src->prep).srcv.prep.ok_depth) { + vector_last(ppsource, src->prep).srcv.prep.entered_next_ok_cond = 1; --vector_last(ppsource, src->prep).srcv.prep.ok_depth; goto preproc_hash_err_goto; } else { @@ -3071,6 +3067,7 @@ start_cur_token: goto preproc_hash_err; } if (vector_last(ppsource, src->prep).srcv.prep.ok_depth) { + // We can safely ignore setting entered_next_ok since two #else is illegal (though this parser doesn't actually detect this) --vector_last(ppsource, src->prep).srcv.prep.ok_depth; goto preproc_hash_err_goto; } else { |