aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien George2018-08-07 16:05:44 +1000
committerDamien George2018-08-07 16:19:38 +1000
commit17b512020b8d0d5ab6c32ecb4a5dc35865ac1593 (patch)
tree81f183528606f74a050c0ed4fa25cf2b99b9b997
parent652a58698edadfe9b587324197e6f922790cf05f (diff)
py/emitnative: Allocate space for local stack info as it's needed.
-rw-r--r--py/emitnative.c25
1 files changed, 17 insertions, 8 deletions
diff --git a/py/emitnative.c b/py/emitnative.c
index cb653cee4..37464a40a 100644
--- a/py/emitnative.c
+++ b/py/emitnative.c
@@ -148,6 +148,8 @@ struct _emit_t {
emit_t *EXPORT_FUN(new)(mp_obj_t *error_slot, mp_uint_t max_num_labels) {
emit_t *emit = m_new0(emit_t, 1);
emit->error_slot = error_slot;
+ emit->stack_info_alloc = 8;
+ emit->stack_info = m_new(stack_info_t, emit->stack_info_alloc);
emit->as = m_new0(ASM_T, 1);
mp_asm_base_init(&emit->as->base, max_num_labels);
return emit;
@@ -213,14 +215,6 @@ STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop
emit->local_vtype_alloc = scope->num_locals;
}
- // allocate memory for keeping track of the objects on the stack
- // XXX don't know stack size on entry, and it should be maximum over all scopes
- // XXX this is such a big hack and really needs to be fixed
- if (emit->stack_info == NULL) {
- emit->stack_info_alloc = scope->stack_size + 200;
- emit->stack_info = m_new(stack_info_t, emit->stack_info_alloc);
- }
-
// set default type for return
emit->return_vtype = VTYPE_PYOBJ;
@@ -455,8 +449,17 @@ STATIC bool emit_native_last_emit_was_return_value(emit_t *emit) {
return emit->last_emit_was_return_value;
}
+STATIC void ensure_extra_stack(emit_t *emit, size_t delta) {
+ if (emit->stack_size + delta > emit->stack_info_alloc) {
+ size_t new_alloc = (emit->stack_size + delta + 8) & ~3;
+ emit->stack_info = m_renew(stack_info_t, emit->stack_info, emit->stack_info_alloc, new_alloc);
+ emit->stack_info_alloc = new_alloc;
+ }
+}
+
STATIC void adjust_stack(emit_t *emit, mp_int_t stack_size_delta) {
assert((mp_int_t)emit->stack_size + stack_size_delta >= 0);
+ assert((mp_int_t)emit->stack_size + stack_size_delta <= (mp_int_t)emit->stack_info_alloc);
emit->stack_size += stack_size_delta;
if (emit->pass > MP_PASS_SCOPE && emit->stack_size > emit->scope->stack_size) {
emit->scope->stack_size = emit->stack_size;
@@ -473,6 +476,9 @@ STATIC void adjust_stack(emit_t *emit, mp_int_t stack_size_delta) {
STATIC void emit_native_adjust_stack_size(emit_t *emit, mp_int_t delta) {
DEBUG_printf("adjust_stack_size(" INT_FMT ")\n", delta);
+ if (delta > 0) {
+ ensure_extra_stack(emit, delta);
+ }
// If we are adjusting the stack in a positive direction (pushing) then we
// need to fill in values for the stack kind and vtype of the newly-pushed
// entries. These should be set to "value" (ie not reg or imm) because we
@@ -640,6 +646,7 @@ STATIC void emit_post_top_set_vtype(emit_t *emit, vtype_kind_t new_vtype) {
}
STATIC void emit_post_push_reg(emit_t *emit, vtype_kind_t vtype, int reg) {
+ ensure_extra_stack(emit, 1);
stack_info_t *si = &emit->stack_info[emit->stack_size];
si->vtype = vtype;
si->kind = STACK_REG;
@@ -648,6 +655,7 @@ STATIC void emit_post_push_reg(emit_t *emit, vtype_kind_t vtype, int reg) {
}
STATIC void emit_post_push_imm(emit_t *emit, vtype_kind_t vtype, mp_int_t imm) {
+ ensure_extra_stack(emit, 1);
stack_info_t *si = &emit->stack_info[emit->stack_size];
si->vtype = vtype;
si->kind = STACK_IMM;
@@ -769,6 +777,7 @@ STATIC void emit_get_stack_pointer_to_reg_for_pop(emit_t *emit, mp_uint_t reg_de
// vtype of all n_push objects is VTYPE_PYOBJ
STATIC void emit_get_stack_pointer_to_reg_for_push(emit_t *emit, mp_uint_t reg_dest, mp_uint_t n_push) {
need_reg_all(emit);
+ ensure_extra_stack(emit, n_push);
for (mp_uint_t i = 0; i < n_push; i++) {
emit->stack_info[emit->stack_size + i].kind = STACK_VALUE;
emit->stack_info[emit->stack_size + i].vtype = VTYPE_PYOBJ;