+ * generate the void type.
+ */
+static void gen_void_type(stabs_handle *h) {
+ fprintf(h->f, "\t.stabs\t\"void:t%u=%u\",%d,0,0,0\n", 0, 0, N_LSYM);
+} /* gen_void_type */
+
+typedef struct walker_env {
+ stabs_handle *h;
+ waitq *wq;
+} wenv_t;
+
+/* a type is not ready: put it on the wait queue */
+#define SET_TYPE_NOT_READY(wq, tp) \
+ do { \
+ set_type_link(tp, (void *)1); \
+ waitq_put(wq, tp); \
+ } while(0)
+
+/* a the is ready */
+#define SET_TYPE_READY(tp) set_type_link(tp, NULL)
+
+/* check whether a type is ready */
+#define IS_TYPE_READY(tp) (get_type_link(tp) == NULL)
+
+#ifdef EXPLICITE_PTR_TYPES
+#define SKIP_PTR(tp) tp
+#else
+#define SKIP_PTR(tp) (is_Pointer_type(tp) ? get_pointer_points_to_type(tp) : tp)
+#endif
+
+/**
+ * Generates a primitive type.
+ *
+ * @param h the stabs handle
+ * @param tp the type
+ */
+static void gen_primitive_type(stabs_handle *h, ir_type *tp)
+{
+ ir_mode *mode = get_type_mode(tp);
+ unsigned type_num;
+
+ SET_TYPE_READY(tp);
+ if (mode == mode_T) {
+ /* jack and FirmJC compiler use mode_T for the void type.
+ Ignore it here as it's name is remapped to "void". */
+ return;
+ } /* if */
+
+ if (0 && get_mode_size_bits(mode) & 7) {
+ /* this is a bitfield type, ignore it */
+ return;
+ } /* if */
+
+ type_num = get_type_number(h, tp);
+
+ if (mode_is_int(mode)) {
+ char buf[64];
+ fprintf(h->f, "\t.stabs\t\"%s:t%u=r%u;", get_type_name(tp), type_num, type_num);
+ tarval_snprintf(buf, sizeof(buf), get_mode_min(mode));
+ fprintf(h->f, "%s;", buf);
+ tarval_snprintf(buf, sizeof(buf), get_mode_max(mode));
+ fprintf(h->f, "%s;\",%d,0,0,0\n", buf, N_LSYM);
+ } else if (mode_is_float(mode)) {
+ int size = get_type_size_bytes(tp);
+ fprintf(h->f, "\t.stabs\t\"%s:t%u=r1;%d;0;\",%d,0,0,0\n", get_type_name(tp), type_num, size, N_LSYM);
+ }
+} /* gen_primitive_type */
+
+/**
+ * Generates an enum type
+ *
+ * @param h the stabs handle
+ * @param tp the type
+ */
+static void gen_enum_type(stabs_handle *h, ir_type *tp) {
+ unsigned type_num = get_type_number(h, tp);
+ int i, n;
+
+ SET_TYPE_READY(tp);
+ fprintf(h->f, "\t.stabs\t\"%s:T%u=e", get_type_name(tp), type_num);
+ for (i = 0, n = get_enumeration_n_enums(tp); i < n; ++i) {
+ ir_enum_const *ec = get_enumeration_const(tp, i);
+ char buf[64];
+
+ tarval_snprintf(buf, sizeof(buf), get_enumeration_value(ec));
+ fprintf(h->f, "%s:%s,", get_enumeration_name(ec), buf);
+ }
+ fprintf(h->f, ";\",%d,0,0,0\n", N_LSYM);
+} /* gen_enum_type */
+
+/**
+ * Generates a pointer type
+ *
+ * @param env the walker environment
+ * @param tp the type
+ */
+static void gen_pointer_type(wenv_t *env, ir_type *tp) {
+ stabs_handle *h = env->h;
+ unsigned type_num = get_type_number(h, tp);
+ ir_type *el_tp = get_pointer_points_to_type(tp);
+ unsigned el_num = get_type_number(h, el_tp);
+
+ SET_TYPE_READY(tp);
+ if (! IS_TYPE_READY(el_tp))
+ waitq_put(env->wq, el_tp);
+ fprintf(h->f, "\t.stabs\t\"%s:t%u=*%u\",%d,0,0,0\n",
+ get_type_name(tp), type_num, el_num, N_LSYM);
+} /* gen_pointer_type */
+
+/**
+ * Generates a struct/union type
+ *
+ * @param env the walker environment
+ * @param tp the type
+ */
+static void gen_struct_union_type(wenv_t *env, ir_type *tp) {
+ stabs_handle *h = env->h;
+ unsigned type_num = get_type_number(h, tp);
+ int i, n;
+ char desc = 's';
+
+ SET_TYPE_READY(tp);
+ if (is_Struct_type(tp)) {
+ desc = 's';
+ if (get_type_mode(tp) != NULL) {
+ /* this is a bitfield type, ignore it safely */
+ return;
+ }
+ }
+ else if (is_Union_type(tp))
+ desc = 'u';
+
+ fprintf(h->f, "\t.stabs\t\"%s:Tt%u=%c%d",
+ get_type_name(tp), type_num, desc, get_type_size_bytes(tp));
+
+ for (i = 0, n = get_compound_n_members(tp); i < n; ++i) {
+ entity *ent = get_compound_member(tp, i);
+ ir_type *mtp = get_entity_type(ent);
+ int ofs, size;
+
+ if (! IS_TYPE_READY(mtp))
+ waitq_put(env->wq, mtp);
+ ofs = get_entity_offset_bits(ent);
+ if (is_Struct_type(mtp) && get_type_mode(mtp) != NULL) {
+ /* this structure is a bitfield, skip */
+ int i, n;
+
+ for (i = 0, n = get_struct_n_members(mtp); i < n; ++i) {
+ entity *ent = get_struct_member(mtp, i);
+ ir_type *tp = get_entity_type(ent);
+ int bofs;
+
+ type_num = get_type_number(h, tp);
+ size = get_type_size_bits(tp);
+ bofs = ofs + get_entity_offset_bits(ent);
+
+ /* name:type, bit offset from the start of the struct', number of bits in the element. */
+ fprintf(h->f, "%s:%u,%d,%d;", get_entity_name(ent), type_num, bofs, size);
+ }
+ } else {
+ /* no bitfield */
+ type_num = get_type_number(h, mtp);
+ size = get_type_size_bits(mtp);
+
+ /* name:type, bit offset from the start of the struct', number of bits in the element. */
+ fprintf(h->f, "%s:%u,%d,%d;", get_entity_name(ent), type_num, ofs, size);
+ }
+ }
+ fprintf(h->f, ";\",%d,0,0,0\n", N_LSYM);
+} /* gen_struct_type */
+
+/**
+ * Generates an array type
+ *
+ * @param env the walker environment
+ * @param tp the type
+ */
+static void gen_array_type(wenv_t *env, ir_type *tp) {
+ stabs_handle *h = env->h;
+ unsigned type_num = get_type_number(h, tp);
+ int i, n = get_array_n_dimensions(tp);
+ ir_type *etp = get_array_element_type(tp);
+ int *perm;
+
+ SET_TYPE_READY(tp);
+ if (! IS_TYPE_READY(etp))
+ waitq_put(env->wq, etp);
+
+ NEW_ARR_A(int, perm, n);
+ for (i = 0; i < n; ++i) {
+ perm[i] = get_array_order(tp, i);
+ }
+ fprintf(h->f, "\t.stabs\t\"%s:t%u=a", get_type_name(tp), type_num);
+
+ for (i = 0; i < n; ++i) {
+ int dim = perm[i];
+ long min = get_array_lower_bound_int(tp, dim);
+ long max = get_array_upper_bound_int(tp, dim);
+
+ /* FIXME r1 must be integer type, but seems to work for now */
+ fprintf(h->f, "r1;%ld;%ld;", min, max-1);
+ }
+
+ type_num = get_type_number(h, etp);
+ fprintf(h->f, "%d\",%d,0,0,0\n", type_num, N_LSYM);
+} /* gen_array_type */
+
+/**
+ * Generates a method type
+ *
+ * @param env the walker environment
+ * @param tp the type