#define noreturn __attribute__((noreturn))
+#ifdef __WINE__
+#define PCVOID LPCVOID
+#define __VALIST __ms_va_list
+#endif
return strcpy(s, buf);
}
-static void sprint_pp(const struct parsed_proto *pp, char *buf,
- size_t buf_size)
-{
- size_t l;
- int i;
-
- snprintf(buf, buf_size, "%s %s(", pp->ret_type.name, pp->name);
- l = strlen(buf);
-
- for (i = 0; i < pp->argc_reg; i++) {
- snprintf(buf + l, buf_size - l, "%s%s",
- i == 0 ? "" : ", ", pp->arg[i].reg);
- l = strlen(buf);
- }
- if (pp->argc_stack > 0) {
- snprintf(buf + l, buf_size - l, "%s{%d stack}",
- i == 0 ? "" : ", ", pp->argc_stack);
- l = strlen(buf);
- }
- snprintf(buf + l, buf_size - l, ")");
-}
-
static void sprint_pp_short(const struct parsed_proto *pp, char *buf,
size_t buf_size)
{
if (!pp->is_func && !pp->is_fptr)
return NULL;
- sprint_pp(pp, fp_var, sizeof(fp_var));
+ pp_print(fp_var, sizeof(fp_var), pp);
if (pp->argc_reg == 0)
goto check_sym;
}
if (bad) {
- sprint_pp(pp_sym, fp_sym, sizeof(fp_sym));
+ pp_print(fp_sym, sizeof(fp_sym), pp_sym);
anote("var: %s\n", fp_var);
anote("sym: %s\n", fp_sym);
awarn("^ mismatch\n");
return pp;
}
+static inline void pp_print(char *buf, size_t buf_size,
+ const struct parsed_proto *pp)
+{
+ size_t l;
+ int i;
+
+ snprintf(buf, buf_size, "%s %s(", pp->ret_type.name, pp->name);
+ l = strlen(buf);
+
+ for (i = 0; i < pp->argc_reg; i++) {
+ snprintf(buf + l, buf_size - l, "%s%s",
+ i == 0 ? "" : ", ", pp->arg[i].reg);
+ l = strlen(buf);
+ }
+ if (pp->argc_stack > 0) {
+ snprintf(buf + l, buf_size - l, "%s{%d stack}",
+ i == 0 ? "" : ", ", pp->argc_stack);
+ l = strlen(buf);
+ }
+ snprintf(buf + l, buf_size - l, ")");
+}
+
static inline void proto_release(struct parsed_proto *pp)
{
int i;
static void check_func_pp(struct parsed_op *po,
const struct parsed_proto *pp, const char *pfx)
{
+ char buf[256];
+
if (pp->argc_reg != 0) {
- if (!g_allow_regfunc && !pp->is_fastcall)
- ferr(po, "%s: reg arg in arg-call unhandled yet\n", pfx);
+ if (/*!g_allow_regfunc &&*/ !pp->is_fastcall) {
+ pp_print(buf, sizeof(buf), pp);
+ ferr(po, "%s: unexpected reg arg in icall: %s\n", pfx, buf);
+ }
if (pp->argc_stack > 0 && pp->argc_reg != 2)
ferr(po, "%s: %d reg arg(s) with %d stack arg(s)\n",
pfx, pp->argc_reg, pp->argc_stack);
if (pp->is_unresolved) {
int regmask_stack = 0;
- collect_call_args(po, i, pp, ®mask_stack, &save_arg_vars,
+ collect_call_args(po, i, pp, ®mask, &save_arg_vars,
i + opcnt * 2);
+ // this is pretty rough guess:
+ // see ecx and edx were pushed (and not their saved versions)
+ for (arg = 0; arg < pp->argc; arg++) {
+ if (pp->arg[arg].reg != NULL)
+ continue;
+
+ tmp_op = pp->arg[arg].datap;
+ if (tmp_op == NULL)
+ ferr(po, "parsed_op missing for arg%d\n", arg);
+ if (tmp_op->argnum == 0 && tmp_op->operand[0].type == OPT_REG)
+ regmask_stack |= 1 << tmp_op->operand[0].reg;
+ }
+
if (!((regmask_stack & (1 << xCX))
&& (regmask_stack & (1 << xDX))))
{
regmask |= 1 << xDX;
}
}
- regmask |= regmask_stack;
// note: __cdecl doesn't fall into is_unresolved category
if (pp->argc_stack > 0)