aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sysdeps/linux-gnu/ia64/fetch.c48
-rw-r--r--type.c36
-rw-r--r--type.h11
3 files changed, 55 insertions, 40 deletions
diff --git a/sysdeps/linux-gnu/ia64/fetch.c b/sysdeps/linux-gnu/ia64/fetch.c
index e90dbed..171c7a2 100644
--- a/sysdeps/linux-gnu/ia64/fetch.c
+++ b/sysdeps/linux-gnu/ia64/fetch.c
@@ -1,6 +1,6 @@
/*
* This file is part of ltrace.
- * Copyright (C) 2012 Petr Machata, Red Hat Inc.
+ * Copyright (C) 2012,2013 Petr Machata, Red Hat Inc.
* Copyright (C) 2008,2009 Juan Cespedes
* Copyright (C) 2006 Steve Fink
* Copyright (C) 2006 Ian Wienand
@@ -249,37 +249,6 @@ allocate_float(struct fetch_context *ctx, struct process *proc,
return 0;
}
-static enum arg_type
-get_hfa_type(struct arg_type_info *info, size_t *countp)
-{
- size_t n = type_aggregate_size(info);
- if (n == (size_t)-1)
- return ARGTYPE_VOID;
-
- enum arg_type type = ARGTYPE_VOID;
- *countp = 0;
-
- while (n-- > 0) {
- struct arg_type_info *emt = type_element(info, n);
-
- enum arg_type emt_type = emt->type;
- size_t emt_count = 1;
- if (emt_type == ARGTYPE_STRUCT || emt_type == ARGTYPE_ARRAY)
- emt_type = get_hfa_type(emt, &emt_count);
-
- if (type == ARGTYPE_VOID) {
- if (emt_type != ARGTYPE_FLOAT
- && emt_type != ARGTYPE_DOUBLE)
- return ARGTYPE_VOID;
- type = emt_type;
- }
- if (emt_type != type)
- return ARGTYPE_VOID;
- *countp += emt_count;
- }
- return type;
-}
-
static int
allocate_hfa(struct fetch_context *ctx, struct process *proc,
struct arg_type_info *info, struct value *valuep,
@@ -380,10 +349,11 @@ allocate_ret(struct fetch_context *ctx, struct process *proc,
* floating-point registers, beginning with f8. */
if (info->type == ARGTYPE_STRUCT || info->type == ARGTYPE_ARRAY) {
size_t hfa_size;
- enum arg_type hfa_type = get_hfa_type(info, &hfa_size);
- if (hfa_type != ARGTYPE_VOID && hfa_size <= 8)
+ struct arg_type_info *hfa_info
+ = type_get_hfa_type(info, &hfa_size);
+ if (hfa_info != NULL && hfa_size <= 8)
return allocate_hfa(ctx, proc, info, valuep,
- hfa_type, hfa_size);
+ hfa_info->type, hfa_size);
}
/* Integers and pointers are passed in r8. 128-bit integers
@@ -409,7 +379,7 @@ arch_fetch_arg_next(struct fetch_context *ctx, enum tof type,
struct arg_type_info *info, struct value *valuep)
{
switch (info->type) {
- enum arg_type hfa_type;
+ struct arg_type_info *hfa_info;
size_t hfa_size;
case ARGTYPE_VOID:
@@ -421,10 +391,10 @@ arch_fetch_arg_next(struct fetch_context *ctx, enum tof type,
return allocate_float(ctx, proc, info, valuep, 1);
case ARGTYPE_STRUCT:
- hfa_type = get_hfa_type(info, &hfa_size);
- if (hfa_type != ARGTYPE_VOID)
+ hfa_info = type_get_hfa_type(info, &hfa_size);
+ if (hfa_info != NULL)
return allocate_hfa(ctx, proc, info, valuep,
- hfa_type, hfa_size);
+ hfa_info->type, hfa_size);
/* Fall through. */
case ARGTYPE_CHAR:
case ARGTYPE_SHORT:
diff --git a/type.c b/type.c
index 11b4ce1..d5bc98f 100644
--- a/type.c
+++ b/type.c
@@ -564,3 +564,39 @@ type_get_fp_equivalent(struct arg_type_info *info)
}
abort();
}
+
+struct arg_type_info *
+type_get_hfa_type(struct arg_type_info *info, size_t *countp)
+{
+ assert(info != NULL);
+ if (info->type != ARGTYPE_STRUCT
+ && info->type != ARGTYPE_ARRAY)
+ return NULL;
+
+ size_t n = type_aggregate_size(info);
+ if (n == (size_t)-1)
+ return NULL;
+
+ struct arg_type_info *ret = NULL;
+ *countp = 0;
+
+ while (n-- > 0) {
+ struct arg_type_info *emt = type_element(info, n);
+
+ size_t emt_count = 1;
+ if (emt->type == ARGTYPE_STRUCT || emt->type == ARGTYPE_ARRAY)
+ emt = type_get_hfa_type(emt, &emt_count);
+ if (emt == NULL)
+ return NULL;
+ if (ret == NULL) {
+ if (emt->type != ARGTYPE_FLOAT
+ && emt->type != ARGTYPE_DOUBLE)
+ return NULL;
+ ret = emt;
+ }
+ if (emt->type != ret->type)
+ return NULL;
+ *countp += emt_count;
+ }
+ return ret;
+}
diff --git a/type.h b/type.h
index b92c1af..3210677 100644
--- a/type.h
+++ b/type.h
@@ -1,6 +1,6 @@
/*
* This file is part of ltrace.
- * Copyright (C) 2011,2012 Petr Machata, Red Hat Inc.
+ * Copyright (C) 2011,2012,2013 Petr Machata, Red Hat Inc.
* Copyright (C) 1997-2009 Juan Cespedes
*
* This program is free software; you can redistribute it and/or
@@ -142,4 +142,13 @@ int type_is_signed(enum arg_type type);
* type. */
struct arg_type_info *type_get_fp_equivalent(struct arg_type_info *info);
+/* If INFO is homogeneous floating-point aggregate, return the
+ * corresponding floating point type, and set *COUNTP to number of
+ * fields of the structure. Otherwise return NULL. INFO is a HFA if
+ * it's an aggregate whose each field is either a HFA, or a
+ * floating-point type. */
+struct arg_type_info *type_get_hfa_type(struct arg_type_info *info,
+ size_t *countp);
+
+
#endif /* TYPE_H */