From a652aa9f7b2c4ddd5fac0c960e9de8f4e821827b Mon Sep 17 00:00:00 2001 From: notaz Date: Tue, 31 Dec 2013 02:50:15 +0200 Subject: [PATCH] funcarg fixes, struct arg handling of some sorts.. --- stdc.hlist | 16 ++++++++++- tools/protoparse.h | 68 ++++++++++++++++++++++++++++++++++------------ tools/translate.c | 31 +++++++++++---------- 3 files changed, 82 insertions(+), 33 deletions(-) diff --git a/stdc.hlist b/stdc.hlist index b294913..a3fe144 100644 --- a/stdc.hlist +++ b/stdc.hlist @@ -31,7 +31,6 @@ char* __cdecl strerror (int); double __cdecl atof (const char*); int __cdecl atoi (const char*); long __cdecl atol (const char*); - size_t __cdecl strlen (const char*) ; char* __cdecl strncat (char*, const char*, size_t); int __cdecl strncmp (const char*, const char*, size_t) ; @@ -43,6 +42,21 @@ char* __cdecl strstr (const char*, const char*) ; char* __cdecl strtok (char*, const char*); size_t __cdecl strxfrm (char*, const char*, size_t); +char* __cdecl _strerror (const char *); +void* __cdecl _memccpy (void*, const void*, int, size_t); +int __cdecl _memicmp (const void*, const void*, size_t); +char* __cdecl _strdup (const char*); +int __cdecl _strcmpi (const char*, const char*); +int __cdecl _stricmp (const char*, const char*); +int __cdecl _stricoll (const char*, const char*); +char* __cdecl _strlwr (char*); +int __cdecl _strnicmp (const char*, const char*, size_t); +char* __cdecl _strnset (char*, int, size_t); +char* __cdecl _strrev (char*); +char* __cdecl _strset (char*, int); +char* __cdecl _strupr (char*); +void __cdecl _swab (const char*, char*, size_t); + int __cdecl isalnum(int); int __cdecl isalpha(int); int __cdecl iscntrl(int); diff --git a/tools/protoparse.h b/tools/protoparse.h index 673fcb7..ec9d4ad 100644 --- a/tools/protoparse.h +++ b/tools/protoparse.h @@ -5,6 +5,7 @@ struct parsed_type { char *name; unsigned int is_array:1; unsigned int is_ptr:1; + unsigned int is_struct:1; // split for args }; struct parsed_proto_arg { @@ -29,11 +30,15 @@ struct parsed_proto { unsigned int is_vararg:1; unsigned int is_fptr:1; unsigned int is_noreturn:1; + unsigned int has_structarg:1; }; static const char *hdrfn; static int hdrfline = 0; +static void pp_copy_arg(struct parsed_proto_arg *d, + const struct parsed_proto_arg *s); + static int b_pp_c_handler(char *proto, const char *fname); static int do_protostrs(FILE *fhdr, const char *fname) @@ -127,6 +132,7 @@ static const char *known_ptr_types[] = { "HBITMAP", "HCURSOR", "HDC", + "HFONT", "HGDIOBJ", "HGLOBAL", "HINSTANCE", @@ -205,7 +211,7 @@ static int check_type(const char *name, struct parsed_type *type) break; } - if (n[0] == 'L' && n[1] == 'P') + if (n[0] == 'L' && n[1] == 'P' && strncmp(n, "LPARAM", 6)) type->is_ptr = 1; // assume single word @@ -248,6 +254,14 @@ static const char *map_reg(const char *reg) return reg; } +static int check_struct_arg(struct parsed_proto_arg *arg) +{ + if (IS(arg->type.name, "POINT")) + return 2 - 1; + + return 0; +} + static int parse_protostr(char *protostr, struct parsed_proto *pp) { struct parsed_proto_arg *arg; @@ -454,7 +468,7 @@ static int parse_protostr(char *protostr, struct parsed_proto *pp) return -1; } // we'll treat it as void * for non-calls - arg->type.name = "void *"; + arg->type.name = strdup("void *"); arg->type.is_ptr = 1; p = p1 + ret; @@ -478,6 +492,18 @@ static int parse_protostr(char *protostr, struct parsed_proto *pp) arg->reg = strdup(map_reg(regparm)); } + + ret = check_struct_arg(arg); + if (ret > 0) { + pp->has_structarg = 1; + arg->type.is_struct = 1; + free(arg->type.name); + arg->type.name = strdup("int"); + for (l = 0; l < ret; l++) { + pp_copy_arg(&pp->arg[xarg], arg); + xarg++; + } + } } if (xarg > 0 && (IS(cconv, "__fastcall") || IS(cconv, "__thiscall"))) { @@ -578,6 +604,26 @@ static const struct parsed_proto *proto_parse(FILE *fhdr, const char *sym) return pp_ret; } +static void pp_copy_arg(struct parsed_proto_arg *d, + const struct parsed_proto_arg *s) +{ + memcpy(d, s, sizeof(*d)); + + if (s->reg != NULL) { + d->reg = strdup(s->reg); + my_assert_not(d->reg, NULL); + } + if (s->type.name != NULL) { + d->type.name = strdup(s->type.name); + my_assert_not(d->type.name, NULL); + } + if (s->fptr != NULL) { + d->fptr = malloc(sizeof(*d->fptr)); + my_assert_not(d->fptr, NULL); + memcpy(d->fptr, s->fptr, sizeof(*d->fptr)); + } +} + struct parsed_proto *proto_clone(const struct parsed_proto *pp_c) { struct parsed_proto *pp; @@ -588,22 +634,8 @@ struct parsed_proto *proto_clone(const struct parsed_proto *pp_c) memcpy(pp, pp_c, sizeof(*pp)); // lazy.. // do the actual deep copy.. - for (i = 0; i < pp_c->argc; i++) { - if (pp_c->arg[i].reg != NULL) { - pp->arg[i].reg = strdup(pp_c->arg[i].reg); - my_assert_not(pp->arg[i].reg, NULL); - } - if (pp_c->arg[i].type.name != NULL) { - pp->arg[i].type.name = strdup(pp_c->arg[i].type.name); - my_assert_not(pp->arg[i].type.name, NULL); - } - if (pp_c->arg[i].fptr != NULL) { - pp->arg[i].fptr = malloc(sizeof(*pp->arg[i].fptr)); - my_assert_not(pp->arg[i].fptr, NULL); - memcpy(pp->arg[i].fptr, pp_c->arg[i].fptr, - sizeof(*pp->arg[i].fptr)); - } - } + for (i = 0; i < pp_c->argc; i++) + pp_copy_arg(&pp->arg[i], &pp_c->arg[i]); if (pp_c->ret_type.name != NULL) pp->ret_type.name = strdup(pp_c->ret_type.name); diff --git a/tools/translate.c b/tools/translate.c index 7cbf8b7..ef38d73 100644 --- a/tools/translate.c +++ b/tools/translate.c @@ -691,8 +691,8 @@ static int parse_operand(struct parsed_opr *opr, if (tmplmod < opr->lmod) opr->size_lt = 1; } + opr->is_ptr = pp->type.is_ptr; } - opr->is_ptr = pp->type.is_ptr; opr->is_array = pp->type.is_array; } @@ -2035,7 +2035,7 @@ static int scan_for_esp_adjust(int i, int opcnt, int *adj) static int collect_call_args(struct parsed_op *po, int i, struct parsed_proto *pp, int *save_arg_vars, int arg, - int need_op_saving, int branched) + int need_op_saving, int may_reuse) { struct parsed_proto *pp_tmp; struct label_ref *lr; @@ -2053,14 +2053,18 @@ static int collect_call_args(struct parsed_op *po, int i, for (j = i; j >= 0 && arg < pp->argc; ) { if (g_labels[j][0] != 0) { - branched = 1; lr = &g_label_refs[j]; if (lr->next != NULL) need_op_saving = 1; - for (; lr->next; lr = lr->next) + for (; lr->next; lr = lr->next) { + if ((ops[lr->i].flags & (OPF_JMP|OPF_CC)) != OPF_JMP) + may_reuse = 1; ret |= collect_call_args(po, lr->i, pp, save_arg_vars, - arg, need_op_saving, branched); + arg, need_op_saving, may_reuse); + } + if ((ops[lr->i].flags & (OPF_JMP|OPF_CC)) != OPF_JMP) + may_reuse = 1; if (j > 0 && LAST_OP(j - 1)) { // follow last branch in reverse j = lr->i; @@ -2068,7 +2072,7 @@ static int collect_call_args(struct parsed_op *po, int i, } need_op_saving = 1; ret |= collect_call_args(po, lr->i, pp, save_arg_vars, - arg, need_op_saving, branched); + arg, need_op_saving, may_reuse); } j--; @@ -2077,7 +2081,7 @@ static int collect_call_args(struct parsed_op *po, int i, pp_tmp = ops[j].datap; if (pp_tmp == NULL) ferr(po, "arg collect hit unparsed call\n"); - if (branched && pp_tmp->argc_stack > 0) + if (may_reuse && pp_tmp->argc_stack > 0) ferr(po, "arg collect %d/%d hit '%s' with %d stack args\n", arg, pp->argc, opr_name(&ops[j], 0), pp_tmp->argc_stack); } @@ -2088,12 +2092,9 @@ static int collect_call_args(struct parsed_op *po, int i, else if (ops[j].op == OP_POP) { ferr(po, "arg collect %d/%d hit pop\n", arg, pp->argc); } - else if (LAST_OP(j)) { - break; - } else if ((ops[j].flags & (OPF_JMP|OPF_CC)) == (OPF_JMP|OPF_CC)) { - branched = 1; + may_reuse = 1; } else if (ops[j].op == OP_PUSH && !(ops[j].flags & OPF_FARG)) { @@ -2117,10 +2118,10 @@ static int collect_call_args(struct parsed_op *po, int i, else if (ops[j].argnum == 0) ops[j].flags |= OPF_RMD; - // some PUSHes are reused by calls on multiple branches, + // some PUSHes are reused by different calls on other branches, // but that can't happen if we didn't branch, so they // can be removed from future searches (handles nested calls) - if (!branched) + if (!may_reuse) ops[j].flags |= OPF_FARG; // next arg @@ -2149,6 +2150,7 @@ static void add_label_ref(struct label_ref *lr, int op_i) lr_new = calloc(1, sizeof(*lr_new)); lr_new->i = op_i; + lr_new->next = lr->next; lr->next = lr_new; } @@ -3108,7 +3110,8 @@ static void gen_func(FILE *fout, FILE *fhdr, const char *funcn, int opcnt) else { if (pp->name[0] == 0) ferr(po, "missing pp->name\n"); - fprintf(fout, "%s(", pp->name); + fprintf(fout, "%s%s(", pp->name, + pp->has_structarg ? "_sa" : ""); } for (arg = 0; arg < pp->argc; arg++) { -- 2.39.5