diff options
| author | rajdakin <rajdakin@gmail.com> | 2024-09-30 12:31:45 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-09-30 12:31:45 +0200 |
| commit | 4715ef2633534a0427a1e92006a09fde5c3faf44 (patch) | |
| tree | b3fe587555e1979d48df6666533f11496161b859 /wrapperhelper/src/machine.c | |
| parent | 703d19b256bc533d73cf4f206e5c443579aaf4c1 (diff) | |
| download | box64-4715ef2633534a0427a1e92006a09fde5c3faf44.tar.gz box64-4715ef2633534a0427a1e92006a09fde5c3faf44.zip | |
[WRAPPERHELPER] Added box32 and line number support in the wrapperhelper (#1890)
Diffstat (limited to 'wrapperhelper/src/machine.c')
| -rw-r--r-- | wrapperhelper/src/machine.c | 267 |
1 files changed, 177 insertions, 90 deletions
diff --git a/wrapperhelper/src/machine.c b/wrapperhelper/src/machine.c index b89a64ae..499bcb2f 100644 --- a/wrapperhelper/src/machine.c +++ b/wrapperhelper/src/machine.c @@ -5,7 +5,7 @@ #include "lang.h" machine_t machine_x86_64; -// machine_t machine_x86; +machine_t machine_x86; machine_t machine_aarch64; #define PASTE2(a, b) a ## b @@ -17,23 +17,23 @@ machine_t machine_aarch64; #define PATHS_OFFSET_PRE 2 // There are two paths that are always included before any other #define ADD_PATH(path) \ - if (!(MACHINE_VAL.include_path[failure_id] = strdup(path))) { \ - printf("Failed to add include path to " MACHINE_STR " platform\n"); \ - goto PASTE(failed_, PASTE(CUR_MACHINE, _paths)); \ - } \ + if (!(MACHINE_VAL.include_path[failure_id] = strdup(path))) { \ + log_memory("failed to add include path to " MACHINE_STR " platform\n"); \ + goto PASTE(failed_, PASTE(CUR_MACHINE, _paths)); \ + } \ ++failure_id; #define INIT_PATHS \ - MACHINE_VAL.npaths = PATHS_OFFSET_PRE + npaths + paths_offset_post; \ - if (!(MACHINE_VAL.include_path = \ - malloc(MACHINE_VAL.npaths * sizeof *MACHINE_VAL.include_path))) { \ - printf("Failed to add include path to " MACHINE_STR " platform\n"); \ - goto PASTE(failed_, PASTE(CUR_MACHINE, _nopath)); \ - } \ - failure_id = 0; \ - ADD_PATH("include-override/" MACHINE_STR) \ - ADD_PATH("include-override/common") \ - while (failure_id < PATHS_OFFSET_PRE + npaths) { \ - ADD_PATH(extra_include_path[failure_id - PATHS_OFFSET_PRE]) \ + MACHINE_VAL.npaths = PATHS_OFFSET_PRE + npaths + paths_offset_post; \ + if (!(MACHINE_VAL.include_path = \ + malloc(MACHINE_VAL.npaths * sizeof *MACHINE_VAL.include_path))) { \ + log_memory("failed to add include path to " MACHINE_STR " platform\n"); \ + goto PASTE(failed_, PASTE(CUR_MACHINE, _nopath)); \ + } \ + failure_id = 0; \ + ADD_PATH("include-override/" MACHINE_STR) \ + ADD_PATH("include-override/common") \ + while (failure_id < PATHS_OFFSET_PRE + npaths) { \ + ADD_PATH(extra_include_path[failure_id - PATHS_OFFSET_PRE]) \ } int init_machines(size_t npaths, const char *const *extra_include_path) { @@ -48,24 +48,45 @@ 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_longdouble = 16; + machine_x86_64.size_longdouble = 16; machine_x86_64.align_valist = 8; machine_x86_64.size_valist = 24; - machine_x86_64.unsigned_char = 1; + machine_x86_64.max_align = 8; + machine_x86_64.has_int128 = 1; + machine_x86_64.unsigned_char = 0; machine_x86_64.unnamed_bitfield_aligns = 0; INIT_PATHS #define DO_PATH ADD_PATH #include "machine.gen" #undef DO_PATH #undef CUR_MACHINE -#pragma GCC diagnostic pop -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wanalyzer-malloc-leak" +#define CUR_MACHINE x86 + machine_x86.size_long = 4; + machine_x86.align_longdouble = 4; + machine_x86.size_longdouble = 12; + machine_x86.align_valist = 4; + machine_x86.size_valist = 4; + machine_x86.max_align = 4; + machine_x86.has_int128 = 0; + machine_x86.unsigned_char = 0; + machine_x86.unnamed_bitfield_aligns = 0; + INIT_PATHS +#define DO_PATH ADD_PATH +#include "machine.gen" +#undef DO_PATH +#undef CUR_MACHINE + #define CUR_MACHINE aarch64 machine_aarch64.size_long = 8; + machine_aarch64.align_longdouble = 16; + machine_aarch64.size_longdouble = 16; machine_aarch64.align_valist = 8; machine_aarch64.size_valist = 32; - machine_aarch64.unsigned_char = 0; + machine_aarch64.max_align = 8; + machine_aarch64.has_int128 = 1; + machine_aarch64.unsigned_char = 1; machine_aarch64.unnamed_bitfield_aligns = 1; INIT_PATHS #define DO_PATH ADD_PATH @@ -82,6 +103,13 @@ failed_aarch64_paths: } free(machine_aarch64.include_path); failed_aarch64_nopath: + failure_id = machine_x86.npaths; +failed_x86_paths: + while (failure_id--) { + free(machine_x86.include_path[failure_id]); + } + free(machine_x86.include_path); +failed_x86_nopath: failure_id = machine_x86_64.npaths; failed_x86_64_paths: while (failure_id--) { @@ -100,100 +128,143 @@ static void machine_del(machine_t *m) { } void del_machines(void) { machine_del(&machine_x86_64); + machine_del(&machine_x86); machine_del(&machine_aarch64); } machine_t *convert_machine_name(const char *archname) { if (!strcmp(archname, "x86_64")) return &machine_x86_64; + if (!strcmp(archname, "x86")) + return &machine_x86; if (!strcmp(archname, "aarch64")) return &machine_aarch64; return NULL; } -int validate_type(machine_t *target, type_t *typ) { +void fill_self_recursion(type_t *typ, struct_t *st) { + if (typ->_internal_use) return; // Recursion, but not self recursion + typ->_internal_use = 1; + switch (typ->typ) { + case TYPE_BUILTIN: break; + case TYPE_ARRAY: + fill_self_recursion(typ->val.array.typ, st); + break; + case TYPE_PTR: + fill_self_recursion(typ->val.typ, st); + break; + case TYPE_FUNCTION: + if (typ->val.fun.nargs != (size_t)-1) { + for (size_t i = 0; (i < typ->val.fun.nargs) && !st->has_self_recursion; ++i) { + fill_self_recursion(typ->val.fun.args[i], st); + } + } + if (!st->has_self_recursion) fill_self_recursion(typ->val.fun.ret, st); + break; + case TYPE_STRUCT_UNION: + if (typ->val.st == st) { + st->has_self_recursion = 1; + break; + } + if (!typ->val.st->is_defined) break; + for (size_t i = 0; (i < typ->val.st->nmembers) && !st->has_self_recursion; ++i) { + fill_self_recursion(typ->val.st->members[i].typ, st); + } + break; + case TYPE_ENUM: + fill_self_recursion(typ->val.typ, st); + break; + } + typ->_internal_use = 0; +} + +int validate_type(loginfo_t *loginfo, 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"); + log_error(loginfo, "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"); + log_error(loginfo, "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"); + log_error(loginfo, "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 = 16; typ->szinfo.size = 32; break; - case BTT_ILONGDOUBLE: typ->szinfo.align = typ->szinfo.size = 16; break; - case BTT_FLOAT128: typ->szinfo.align = typ->szinfo.size = 16; break; - case BTT_CFLOAT128: typ->szinfo.align = 16; typ->szinfo.size = 32; break; - case BTT_IFLOAT128: 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; + case BTT_VOID: typ->szinfo.align = typ->szinfo.size = 0; return 1; + case BTT_BOOL: + case BTT_CHAR: + case BTT_SCHAR: + case BTT_UCHAR: + case BTT_S8: + case BTT_U8: typ->szinfo.align = typ->szinfo.size = 1; return 1; + case BTT_SHORT: + case BTT_SSHORT: + case BTT_USHORT: + case BTT_S16: + case BTT_U16: typ->szinfo.align = typ->szinfo.size = 2; return 1; + case BTT_INT: + case BTT_SINT: + case BTT_UINT: + case BTT_S32: + case BTT_U32: typ->szinfo.align = typ->szinfo.size = 4; return 1; + case BTT_LONGLONG: + case BTT_SLONGLONG: + case BTT_ULONGLONG: + case BTT_S64: + case BTT_U64: typ->szinfo.align = target->max_align; typ->szinfo.size = 8; return 1; + case BTT_LONG: + case BTT_SLONG: + case BTT_ULONG: typ->szinfo.align = typ->szinfo.size = target->size_long; return 1; + case BTT_FLOAT: + case BTT_IFLOAT: typ->szinfo.align = typ->szinfo.size = 4; return 1; + case BTT_CFLOAT: + case BTT_DOUBLE: + case BTT_IDOUBLE: typ->szinfo.align = target->max_align; typ->szinfo.size = 8; return 1; + case BTT_CDOUBLE: typ->szinfo.align = target->max_align; typ->szinfo.size = 16; return 1; + case BTT_LONGDOUBLE: + case BTT_ILONGDOUBLE: typ->szinfo.align = target->align_longdouble; typ->szinfo.size = target->size_longdouble; return 1; + case BTT_CLONGDOUBLE: typ->szinfo.align = target->align_longdouble; typ->szinfo.size = 2*target->size_longdouble; return 1; + case BTT_INT128: + case BTT_SINT128: + case BTT_UINT128: + if (!target->has_int128) { + if (loginfo->filename) log_error(loginfo, "target does not have type __int128\n"); + typ->szinfo.align = typ->szinfo.size = 0; return 0; + } + /* FALLTHROUGH */ + case BTT_FLOAT128: + case BTT_IFLOAT128: typ->szinfo.align = typ->szinfo.size = 16; return 1; + case BTT_CFLOAT128: typ->szinfo.align = 16; typ->szinfo.size = 32; return 1; + case BTT_VA_LIST: typ->szinfo.align = target->align_valist; typ->szinfo.size = target->size_valist; return 1; default: - printf("Unknown builtin %u, cannot fill size info\n", typ->val.builtin); + log_error(loginfo, "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"); + log_error(loginfo, "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"); + log_error(loginfo, "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"); + log_error(loginfo, "array types may not be qualified\n"); return 0; } - if (!validate_type(target, typ->val.array.typ)) return 0; + if (!validate_type(loginfo, 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; @@ -208,10 +279,10 @@ int validate_type(machine_t *target, type_t *typ) { case TYPE_PTR: typ->szinfo.size = target->size_long; typ->szinfo.align = target->size_long; - return validate_type(target, typ->val.typ); + return validate_type(loginfo, 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"); + log_error(loginfo, "function types may not return function or array types\n"); return 0; } if (typ->val.fun.nargs != (size_t)-1) { @@ -219,57 +290,72 @@ int validate_type(machine_t *target, type_t *typ) { // Adjust the argument if necessary // Assume arrays are already converted if (typ->val.fun.args[i]->typ == TYPE_ARRAY) { - printf("Error: function argument %zu is an array\n", i + 1); + log_error(loginfo, "function argument %zu is an array\n", i + 1); return 0; } 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"); + log_error(loginfo, "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; + if (!validate_type(loginfo, target, typ->val.fun.args[i])) return 0; } } typ->szinfo.size = 0; typ->szinfo.align = 0; - return validate_type(target, typ->val.fun.ret); + return validate_type(loginfo, 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; + size_t max_align = 1, cur_sz = 0; unsigned char 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"); + log_error(loginfo, "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"); + log_error(loginfo, "structures may not contain incomplete members\n"); return 0; } typ->val.st->has_incomplete = 1; } - if (!validate_type(target, mem->typ)) return 0; + if (!validate_type(loginfo, target, mem->typ)) return 0; + if (!typ->val.st->has_self_recursion) fill_self_recursion(mem->typ, typ->val.st); if (!typ->val.st->is_struct && (mem->typ->typ == TYPE_STRUCT_UNION)) { typ->val.st->has_incomplete |= mem->typ->val.st->has_incomplete; + } else if ((mem->typ->typ == TYPE_STRUCT_UNION) && mem->typ->val.st->has_incomplete) { + log_error(loginfo, "structures may not (inductively) contain structures which last element is incomplete\n"); + return 0; + } else if (typ->val.st->is_struct) { + if (mem->typ->is_incomplete) { + if (i && (i == typ->val.st->nmembers - 1) && (mem->typ->typ == TYPE_ARRAY)) { + typ->val.st->has_incomplete |= mem->typ->val.st->has_incomplete; + } else { + log_error(loginfo, "structures may not have any incomplete element, except that the last, but not first, element may be an incomplete array\n"); + return 0; + } + } } + mem->byte_offset = cur_sz; + mem->bit_offset = cur_bit; if (mem->is_bitfield) { if (!typ->val.st->is_struct) { - printf("Error: TODO: bitfield in union\n"); + log_error(loginfo, "TODO: bitfield in union\n"); return 0; } if (mem->typ->is_atomic) { - printf("Error: atomic bitfields are not supported\n"); + log_error(loginfo, "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"); + log_error(loginfo, "bitfields can only have a specific subset of types\n"); return 0; } if ((mem->typ->val.builtin != BTT_BOOL) && (mem->typ->val.builtin != BTT_CHAR) @@ -285,11 +371,11 @@ int validate_type(machine_t *target, type_t *typ) { && (mem->typ->val.builtin != BTT_S64) && (mem->typ->val.builtin != BTT_U64)) { // C standard: allow _Bool, (s/u)int // Implementation: also allow (u/s)char, (u/s)short, (u/s)long, (u/s)long long, [u]intx_t - printf("Error: bitfields can only have a specific subset of types\n"); + log_error(loginfo, "bitfields can only have a specific subset of types\n"); return 0; } if (mem->typ->szinfo.size < mem->bitfield_width / 8) { - printf("Error: bitfield member %c%s%c has width (%zu) greater than its container size (%zu * 8)\n", + log_error(loginfo, "bitfield member %c%s%c has width (%zu) greater than its container size (%zu * 8)\n", mem->name ? '\'' : '<', mem->name ? string_content(mem->name) : "unnamed", mem->name ? '\'' : '>', @@ -302,7 +388,8 @@ int validate_type(machine_t *target, type_t *typ) { 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 += mem->bitfield_width / 8; + cur_bit += mem->bitfield_width % 8; cur_sz += cur_bit / 8; cur_bit %= 8; } else { @@ -312,7 +399,7 @@ int validate_type(machine_t *target, type_t *typ) { } 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"); + log_error(loginfo, "TODO: unnamed zero-width bitfield member\n"); return 0; } } else { @@ -337,7 +424,7 @@ int validate_type(machine_t *target, type_t *typ) { return 1; } case TYPE_ENUM: if (typ->val.typ->typ != TYPE_BUILTIN) { - printf("Error: the underlying type of an enum is not a builtin type\n"); + log_error(loginfo, "the underlying type of an enum is not a builtin type\n"); return 0; } typ->szinfo = typ->val.typ->szinfo; |