hop_add_insel(hop, "stfs %H, %S(fp) ! %H", src, dest, dest);
break;
+ case burm_long_ATTR:
+ hop_add_insel(hop, "stw %0H, 4+%S(fp) ! %H", src, dest, dest);
+ hop_add_insel(hop, "stw %1H, 0+%S(fp) ! %H", src, dest, dest);
+ break;
+
case burm_double_ATTR:
hop_add_insel(hop, "stfd %H, %S(fp) ! %H", src, dest, dest);
break;
cost 16;
out:(long)reg = COPYD.L(in:(double)reg)
- emit "sfdu %in, -8(sp)"
+ emit "stfdu %in, -8(sp)"
emit "lwz %out.0, 4(sp)"
emit "lwz %out.1, 0(sp)"
emit "addi sp, sp, 8"
/* Stores */
+ STORE.D(addr:address, value:(double)reg)
+ emit "sfd %value, %addr"
+ cost 4;
+
STORE.L(addr:address, value:(long)reg)
emit "stw %value.0, 4+%addr"
emit "stw %value.1, 0+%addr"
- cost 4;
+ cost 8;
STORE.I(addr:address, value:(int)reg)
emit "stw %value, %addr"
emit "bl .fromf2l"
cost 4;
+ out:(long)reg = FROMSI.D(in:(double)reg)
+ with corrupted(volatile)
+ emit "bl .fromsi2d"
+ cost 4;
+
#if 0
/* byte conversions */
return copy;
}
-static void insert_copies(void)
+static void insert_copy(struct ir* ir, struct ir** child, char returntype, char childtype)
+{
+ if (*child)
+ {
+ char wanted;
+ char real;
+
+ if ((returntype == '?') && (childtype == '?'))
+ {
+ wanted = ir->type;
+ real = (*child)->type;
+ }
+ else
+ {
+ wanted = effective_type(ir, childtype);
+ real = (*child)->type;
+ }
+
+ if (wanted)
+ {
+ if (wanted != real)
+ {
+ struct ir* copy = new_copy(wanted, real, *child);
+ copy->root = ir->root;
+ *child = copy;
+ }
+ }
+ }
+}
+
+static void insert_ir_copies(void)
{
int i;
struct ir* ir = irs.item[i];
const struct ir_data* ird = &ir_data[ir->opcode];
- if (ir->left)
- {
- char wanted = effective_type(ir, ird->lefttype);
- char real = ir->left->type;
+ insert_copy(ir, &ir->left, ird->returntype, ird->lefttype);
+ insert_copy(ir, &ir->right, ird->returntype, ird->righttype);
+ }
+}
- if (wanted && (wanted != real))
- {
- struct ir* copy = new_copy(wanted, real, ir->left);
- copy->root = ir->root;
- ir->left = copy;
- }
- }
+static void insert_phi_copies(void)
+{
+ int i, j;
- if (ir->right)
- {
- char wanted = effective_type(ir, ird->righttype);
- char real = ir->right->type;
+ /* If the child of a phi isn't the same type as the phi itself, we need to
+ * insert the copy at the end of the block that exported the value. */
- if (wanted && (wanted != real))
- {
- struct ir* copy = new_copy(wanted, real, ir->right);
- copy->root = ir->root;
- ir->right = copy;
- }
- }
- }
+ for (i=0; i<irs.count; i++)
+ {
+ struct ir* ir = irs.item[i];
+
+ for (j=0; j<ir->u.phivalue.count; j++)
+ {
+ struct ir* childir = ir->u.phivalue.item[j].right;
+ int wanted = ir->type;
+ int real = childir->type;
+ if (wanted != real)
+ {
+ struct basicblock* childbb = ir->u.phivalue.item[j].left;
+ struct ir* copy = new_copy(wanted, real, childir);
+ copy->root = copy;
+
+ /* The copy gets inserted as the second last item of the child
+ * basic block. That way it'll happen before the final jump
+ * that exits the block. */
+
+ array_insert(&childbb->irs, copy, childbb->irs.count-1);
+
+ /* And replace the value in the phi with our copy. */
+
+ ir->u.phivalue.item[j].right = copy;
+ }
+ }
+ }
}
void pass_infer_types(void)
collect_irs();
propagate_types();
assign_fallback_types();
- insert_copies();
+ insert_ir_copies();
+ insert_phi_copies();
}
/* vim: set sw=4 ts=4 expandtab : */