int arch_fetch_arg_next(struct fetch_context *ctx, enum tof type, struct Process *proc, struct arg_type_info *info, struct value *valuep) { size_t sz = type_sizeof(proc, info); if (sz == (size_t)-1) return -1; switch (info->type) { case ARGTYPE_VOID: value_set_word(valuep, 0); return 0; case ARGTYPE_STRUCT: if (type_get_fp_equivalent(info) != NULL) /* fall through */ case ARGTYPE_FLOAT: case ARGTYPE_DOUBLE: return allocate_fpr(ctx, proc, info, valuep, sz); /* Structures<4 bytes on s390 and structures<8 bytes * on s390x are passed in register. On s390, long * long and structures<8 bytes are passed in two * consecutive registers (if two are available). */ if (sz <= (s390x(ctx) ? 8 : 4)) return allocate_gpr(ctx, proc, info, valuep, sz); else if (sz <= 8) return allocate_gpr_pair(ctx, proc, info, valuep, sz); /* fall through */ case ARGTYPE_ARRAY: if (value_pass_by_reference(valuep) < 0) return -1; /* fall through */ case ARGTYPE_INT: case ARGTYPE_UINT: case ARGTYPE_LONG: case ARGTYPE_ULONG: case ARGTYPE_CHAR: case ARGTYPE_SHORT: case ARGTYPE_USHORT: case ARGTYPE_POINTER: return allocate_gpr(ctx, proc, info, valuep, sz); default: assert(info->type != info->type); abort(); } return -1; }
static int zero_callback_max(struct value *ret_value, struct value *lhs, struct value_dict *arguments, size_t max, void *data) { size_t i; for (i = 0; i < max; ++i) { struct value element; if (value_init_element(&element, lhs, i) < 0) return -1; int zero = value_is_zero(&element, arguments); value_destroy(&element); if (zero) break; } struct arg_type_info *long_type = type_get_simple(ARGTYPE_LONG); value_init_detached(ret_value, NULL, long_type, 0); value_set_word(ret_value, i); return 0; }
static void copy_gpr(struct fetch_context *ctx, struct value *valuep, int regno) { value_set_word(valuep, ctx->regs.gprs[regno]); }
/* Syntax: * enum (keyname[=value],keyname[=value],... ) * enum<type> (keyname[=value],keyname[=value],... ) */ static int parse_enum(struct protolib *plib, struct locus *loc, char **str, struct arg_type_info **retp, int *ownp) { /* Optional type argument. */ eat_spaces(str); if (**str == '[') { parse_char(loc, str, '['); eat_spaces(str); *retp = parse_nonpointer_type(plib, loc, str, NULL, 0, ownp, 0); if (*retp == NULL) return -1; if (!type_is_integral((*retp)->type)) { report_error(loc->filename, loc->line_no, "integral type required as enum argument"); fail: if (*ownp) { /* This also releases associated lens * if any was set so far. */ type_destroy(*retp); free(*retp); } return -1; } eat_spaces(str); if (parse_char(loc, str, ']') < 0) goto fail; } else { *retp = type_get_simple(ARGTYPE_INT); *ownp = 0; } /* We'll need to set the lens, so unshare. */ if (unshare_type_info(loc, retp, ownp) < 0) goto fail; eat_spaces(str); if (parse_char(loc, str, '(') < 0) goto fail; struct enum_lens *lens = malloc(sizeof(*lens)); if (lens == NULL) { report_error(loc->filename, loc->line_no, "malloc enum lens: %s", strerror(errno)); return -1; } lens_init_enum(lens); (*retp)->lens = &lens->super; (*retp)->own_lens = 1; long last_val = 0; while (1) { eat_spaces(str); if (**str == 0 || **str == ')') { parse_char(loc, str, ')'); return 0; } /* Field delimiter. XXX should we support the C * syntax, where the enumeration can end in pending * comma? */ if (lens_enum_size(lens) > 0) parse_char(loc, str, ','); eat_spaces(str); char *key = parse_ident(loc, str); if (key == NULL) { err: free(key); goto fail; } if (**str == '=') { ++*str; eat_spaces(str); if (parse_int(loc, str, &last_val) < 0) goto err; } struct value *value = malloc(sizeof(*value)); if (value == NULL) goto err; value_init_detached(value, NULL, *retp, 0); value_set_word(value, last_val); if (lens_enum_add(lens, key, 1, value, 1) < 0) goto err; last_val++; } return 0; }