+ size_t i, a;
+ bool retval = true;
+ size_t pos;
+
+ ir_value *slot;
+ const ir_value *v;
+
+ function_allocator alloc;
+
+ if (!self->locals_count)
+ return true;
+
+ MEM_VECTOR_INIT(&alloc, locals);
+ MEM_VECTOR_INIT(&alloc, sizes);
+ MEM_VECTOR_INIT(&alloc, positions);
+
+ for (i = 0; i < self->locals_count; ++i)
+ {
+ if (!function_allocator_alloc(&alloc, self->locals[i]))
+ goto error;
+ }
+
+ /* Allocate a slot for any value that still exists */
+ for (i = 0; i < self->values_count; ++i)
+ {
+ v = self->values[i];
+
+ if (!v->life_count)
+ continue;
+
+ for (a = 0; a < alloc.locals_count; ++a)
+ {
+ slot = alloc.locals[a];
+
+ if (ir_values_overlap(v, slot))
+ continue;
+
+ if (!ir_value_life_merge_into(slot, v))
+ goto error;
+
+ /* adjust size for this slot */
+ if (alloc.sizes[a] < type_sizeof[v->vtype])
+ alloc.sizes[a] = type_sizeof[v->vtype];
+
+ self->values[i]->code.local = a;
+ break;
+ }
+ if (a >= alloc.locals_count) {
+ self->values[i]->code.local = alloc.locals_count;
+ if (!function_allocator_alloc(&alloc, v))
+ goto error;
+ }
+ }
+
+ /* Adjust slot positions based on sizes */
+ if (!function_allocator_positions_add(&alloc, 0))
+ goto error;
+
+ if (alloc.sizes_count)
+ pos = alloc.positions[0] + alloc.sizes[0];
+ else
+ pos = 0;
+ for (i = 1; i < alloc.sizes_count; ++i)
+ {
+ pos = alloc.positions[i-1] + alloc.sizes[i-1];
+ if (!function_allocator_positions_add(&alloc, pos))
+ goto error;
+ }
+
+ self->allocated_locals = pos + alloc.sizes[alloc.sizes_count-1];
+
+ /* Take over the actual slot positions */
+ for (i = 0; i < self->values_count; ++i)
+ self->values[i]->code.local = alloc.positions[self->values[i]->code.local];
+
+ goto cleanup;
+
+error:
+ retval = false;
+cleanup:
+ for (i = 0; i < alloc.locals_count; ++i)
+ ir_value_delete(alloc.locals[i]);
+ MEM_VECTOR_CLEAR(&alloc, locals);
+ MEM_VECTOR_CLEAR(&alloc, sizes);
+ MEM_VECTOR_CLEAR(&alloc, positions);
+ return retval;