diff --git a/extmod/modmachine.c b/extmod/modmachine.c
index 5e54b2272252636031f8edfdb30cb4399c464050..675a32086355c6f4369f8578fe3b858bd20053b0 100644
--- a/extmod/modmachine.c
+++ b/extmod/modmachine.c
@@ -77,13 +77,13 @@ typedef struct _machine_mem_obj_t {
 
 STATIC void machine_mem_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
     (void)kind;
-    machine_mem_obj_t *self = self_in;
+    machine_mem_obj_t *self = MP_OBJ_TO_PTR(self_in);
     mp_printf(print, "<%u-bit memory>", 8 * self->elem_size);
 }
 
 STATIC mp_obj_t machine_mem_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
     // TODO support slice index to read/write multiple values at once
-    machine_mem_obj_t *self = self_in;
+    machine_mem_obj_t *self = MP_OBJ_TO_PTR(self_in);
     if (value == MP_OBJ_NULL) {
         // delete
         return MP_OBJ_NULL; // op not supported
diff --git a/extmod/moductypes.c b/extmod/moductypes.c
index 9dcaf44694bb5c41d2d706c6bc35036f09153576..559339a7a81c15647d3b80cde0829ee0cdcf7456 100644
--- a/extmod/moductypes.c
+++ b/extmod/moductypes.c
@@ -124,24 +124,24 @@ STATIC NORETURN void syntax_error(void) {
 STATIC mp_obj_t uctypes_struct_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
     mp_arg_check_num(n_args, n_kw, 2, 3, false);
     mp_obj_uctypes_struct_t *o = m_new_obj(mp_obj_uctypes_struct_t);
-    o->base.type = type_in;
-    o->addr = (void*)mp_obj_get_int(args[0]);
+    o->base.type = MP_OBJ_TO_PTR(type_in);
+    o->addr = (void*)(uintptr_t)mp_obj_get_int(args[0]);
     o->desc = args[1];
     o->flags = LAYOUT_NATIVE;
     if (n_args == 3) {
         o->flags = mp_obj_get_int(args[2]);
     }
-    return o;
+    return MP_OBJ_FROM_PTR(o);
 }
 
 STATIC void uctypes_struct_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
     (void)kind;
-    mp_obj_uctypes_struct_t *self = self_in;
+    mp_obj_uctypes_struct_t *self = MP_OBJ_TO_PTR(self_in);
     const char *typen = "unk";
     if (MP_OBJ_IS_TYPE(self->desc, &mp_type_dict)) {
         typen = "STRUCT";
     } else if (MP_OBJ_IS_TYPE(self->desc, &mp_type_tuple)) {
-        mp_obj_tuple_t *t = (mp_obj_tuple_t*)self->desc;
+        mp_obj_tuple_t *t = MP_OBJ_TO_PTR(self->desc);
         mp_int_t offset = MP_OBJ_SMALL_INT_VALUE(t->items[0]);
         uint agg_type = GET_TYPE(offset, AGG_TYPE_BITS);
         switch (agg_type) {
@@ -207,12 +207,9 @@ STATIC mp_uint_t uctypes_struct_agg_size(mp_obj_tuple_t *t, mp_uint_t *max_field
 }
 
 STATIC mp_uint_t uctypes_struct_size(mp_obj_t desc_in, mp_uint_t *max_field_size) {
-    mp_obj_dict_t *d = desc_in;
-    mp_uint_t total_size = 0;
-
     if (!MP_OBJ_IS_TYPE(desc_in, &mp_type_dict)) {
         if (MP_OBJ_IS_TYPE(desc_in, &mp_type_tuple)) {
-            return uctypes_struct_agg_size((mp_obj_tuple_t*)desc_in, max_field_size);
+            return uctypes_struct_agg_size((mp_obj_tuple_t*)MP_OBJ_TO_PTR(desc_in), max_field_size);
         } else if (MP_OBJ_IS_SMALL_INT(desc_in)) {
             // We allow sizeof on both type definitions and structures/structure fields,
             // but scalar structure field is lowered into native Python int, so all
@@ -223,6 +220,9 @@ STATIC mp_uint_t uctypes_struct_size(mp_obj_t desc_in, mp_uint_t *max_field_size
         syntax_error();
     }
 
+    mp_obj_dict_t *d = MP_OBJ_TO_PTR(desc_in);
+    mp_uint_t total_size = 0;
+
     for (mp_uint_t i = 0; i < d->map.alloc; i++) {
         if (MP_MAP_SLOT_IS_FILLED(&d->map, i)) {
             mp_obj_t v = d->map.table[i].value;
@@ -241,7 +241,7 @@ STATIC mp_uint_t uctypes_struct_size(mp_obj_t desc_in, mp_uint_t *max_field_size
                 if (!MP_OBJ_IS_TYPE(v, &mp_type_tuple)) {
                     syntax_error();
                 }
-                mp_obj_tuple_t *t = (mp_obj_tuple_t*)v;
+                mp_obj_tuple_t *t = MP_OBJ_TO_PTR(v);
                 mp_int_t offset = MP_OBJ_SMALL_INT_VALUE(t->items[0]);
                 offset &= VALUE_MASK(AGG_TYPE_BITS);
                 mp_uint_t s = uctypes_struct_agg_size(t, max_field_size);
@@ -266,7 +266,7 @@ STATIC mp_obj_t uctypes_struct_sizeof(mp_obj_t obj_in) {
     // or to instantiated structure
     if (MP_OBJ_IS_TYPE(obj_in, &uctypes_struct_type)) {
         // Extract structure definition
-        mp_obj_uctypes_struct_t *obj = obj_in;
+        mp_obj_uctypes_struct_t *obj = MP_OBJ_TO_PTR(obj_in);
         obj_in = obj->desc;
     }
     mp_uint_t size = uctypes_struct_size(obj_in, &max_field_size);
@@ -365,7 +365,7 @@ STATIC void set_aligned(uint val_type, void *p, mp_int_t index, mp_obj_t val) {
 }
 
 STATIC mp_obj_t uctypes_struct_attr_op(mp_obj_t self_in, qstr attr, mp_obj_t set_val) {
-    mp_obj_uctypes_struct_t *self = self_in;
+    mp_obj_uctypes_struct_t *self = MP_OBJ_TO_PTR(self_in);
 
     // TODO: Support at least OrderedDict in addition
     if (!MP_OBJ_IS_TYPE(self->desc, &mp_type_dict)) {
@@ -443,7 +443,7 @@ STATIC mp_obj_t uctypes_struct_attr_op(mp_obj_t self_in, qstr attr, mp_obj_t set
         syntax_error();
     }
 
-    mp_obj_tuple_t *sub = (mp_obj_tuple_t*)deref;
+    mp_obj_tuple_t *sub = MP_OBJ_TO_PTR(deref);
     mp_int_t offset = MP_OBJ_SMALL_INT_VALUE(sub->items[0]);
     mp_uint_t agg_type = GET_TYPE(offset, AGG_TYPE_BITS);
     offset &= VALUE_MASK(AGG_TYPE_BITS);
@@ -456,7 +456,7 @@ STATIC mp_obj_t uctypes_struct_attr_op(mp_obj_t self_in, qstr attr, mp_obj_t set
             o->desc = sub->items[1];
             o->addr = self->addr + offset;
             o->flags = self->flags;
-            return o;
+            return MP_OBJ_FROM_PTR(o);
         }
         case ARRAY: {
             mp_uint_t dummy;
@@ -468,11 +468,11 @@ STATIC mp_obj_t uctypes_struct_attr_op(mp_obj_t self_in, qstr attr, mp_obj_t set
         case PTR: {
             mp_obj_uctypes_struct_t *o = m_new_obj(mp_obj_uctypes_struct_t);
             o->base.type = &uctypes_struct_type;
-            o->desc = sub;
+            o->desc = MP_OBJ_FROM_PTR(sub);
             o->addr = self->addr + offset;
             o->flags = self->flags;
 //printf("PTR/ARR base addr=%p\n", o->addr);
-            return o;
+            return MP_OBJ_FROM_PTR(o);
         }
     }
 
@@ -494,7 +494,7 @@ STATIC void uctypes_struct_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
 }
 
 STATIC mp_obj_t uctypes_struct_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value) {
-    mp_obj_uctypes_struct_t *self = self_in;
+    mp_obj_uctypes_struct_t *self = MP_OBJ_TO_PTR(self_in);
 
     if (value == MP_OBJ_NULL) {
         // delete
@@ -505,7 +505,7 @@ STATIC mp_obj_t uctypes_struct_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_ob
             nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "struct: cannot index"));
         }
 
-        mp_obj_tuple_t *t = (mp_obj_tuple_t*)self->desc;
+        mp_obj_tuple_t *t = MP_OBJ_TO_PTR(self->desc);
         mp_int_t offset = MP_OBJ_SMALL_INT_VALUE(t->items[0]);
         uint agg_type = GET_TYPE(offset, AGG_TYPE_BITS);
 
@@ -530,7 +530,7 @@ STATIC mp_obj_t uctypes_struct_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_ob
                 o->desc = t->items[2];
                 o->addr = self->addr + size * index;
                 o->flags = self->flags;
-                return o;
+                return MP_OBJ_FROM_PTR(o);
             }
         } else if (agg_type == PTR) {
             byte *p = *(void**)self->addr;
@@ -545,7 +545,7 @@ STATIC mp_obj_t uctypes_struct_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_ob
                 o->desc = t->items[1];
                 o->addr = p + size * index;
                 o->flags = self->flags;
-                return o;
+                return MP_OBJ_FROM_PTR(o);
             }
         }
 
@@ -559,7 +559,7 @@ STATIC mp_obj_t uctypes_struct_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_ob
 
 STATIC mp_int_t uctypes_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) {
     (void)flags;
-    mp_obj_uctypes_struct_t *self = self_in;
+    mp_obj_uctypes_struct_t *self = MP_OBJ_TO_PTR(self_in);
     mp_uint_t max_field_size = 0;
     mp_uint_t size = uctypes_struct_size(self->desc, &max_field_size);
 
@@ -575,7 +575,7 @@ STATIC mp_int_t uctypes_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo,
 STATIC mp_obj_t uctypes_struct_addressof(mp_obj_t buf) {
     mp_buffer_info_t bufinfo;
     mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ);
-    return mp_obj_new_int((mp_int_t)bufinfo.buf);
+    return mp_obj_new_int((mp_int_t)(uintptr_t)bufinfo.buf);
 }
 MP_DEFINE_CONST_FUN_OBJ_1(uctypes_struct_addressof_obj, uctypes_struct_addressof);
 
@@ -584,7 +584,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(uctypes_struct_addressof_obj, uctypes_struct_addressof
 /// captured by reference (and thus memory pointed by bytearray may change
 /// or become invalid at later time). Use bytes_at() to capture by value.
 STATIC mp_obj_t uctypes_struct_bytearray_at(mp_obj_t ptr, mp_obj_t size) {
-    return mp_obj_new_bytearray_by_ref(mp_obj_int_get_truncated(size), (void*)mp_obj_int_get_truncated(ptr));
+    return mp_obj_new_bytearray_by_ref(mp_obj_int_get_truncated(size), (void*)(uintptr_t)mp_obj_int_get_truncated(ptr));
 }
 MP_DEFINE_CONST_FUN_OBJ_2(uctypes_struct_bytearray_at_obj, uctypes_struct_bytearray_at);
 
@@ -593,7 +593,7 @@ MP_DEFINE_CONST_FUN_OBJ_2(uctypes_struct_bytearray_at_obj, uctypes_struct_bytear
 /// captured by value, i.e. copied. Use bytearray_at() to capture by reference
 /// ("zero copy").
 STATIC mp_obj_t uctypes_struct_bytes_at(mp_obj_t ptr, mp_obj_t size) {
-    return mp_obj_new_bytes((void*)mp_obj_int_get_truncated(ptr), mp_obj_int_get_truncated(size));
+    return mp_obj_new_bytes((void*)(uintptr_t)mp_obj_int_get_truncated(ptr), mp_obj_int_get_truncated(size));
 }
 MP_DEFINE_CONST_FUN_OBJ_2(uctypes_struct_bytes_at_obj, uctypes_struct_bytes_at);
 
diff --git a/extmod/moduhashlib.c b/extmod/moduhashlib.c
index 8df96be3c514d826c90630529da6503d21863162..7b0d25e80ba5fbe0ddb611efa44f440a0f4e8277 100644
--- a/extmod/moduhashlib.c
+++ b/extmod/moduhashlib.c
@@ -44,16 +44,16 @@ STATIC mp_obj_t hash_update(mp_obj_t self_in, mp_obj_t arg);
 STATIC mp_obj_t hash_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
     mp_arg_check_num(n_args, n_kw, 0, 1, false);
     mp_obj_hash_t *o = m_new_obj_var(mp_obj_hash_t, char, sizeof(SHA256_CTX));
-    o->base.type = type_in;
+    o->base.type = MP_OBJ_TO_PTR(type_in);
     sha256_init((SHA256_CTX*)o->state);
     if (n_args == 1) {
-        hash_update(o, args[0]);
+        hash_update(MP_OBJ_FROM_PTR(o), args[0]);
     }
-    return o;
+    return MP_OBJ_FROM_PTR(o);
 }
 
 STATIC mp_obj_t hash_update(mp_obj_t self_in, mp_obj_t arg) {
-    mp_obj_hash_t *self = self_in;
+    mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
     mp_buffer_info_t bufinfo;
     mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_READ);
     sha256_update((SHA256_CTX*)self->state, bufinfo.buf, bufinfo.len);
@@ -62,7 +62,7 @@ STATIC mp_obj_t hash_update(mp_obj_t self_in, mp_obj_t arg) {
 MP_DEFINE_CONST_FUN_OBJ_2(hash_update_obj, hash_update);
 
 STATIC mp_obj_t hash_digest(mp_obj_t self_in) {
-    mp_obj_hash_t *self = self_in;
+    mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
     vstr_t vstr;
     vstr_init_len(&vstr, SHA256_BLOCK_SIZE);
     sha256_final((SHA256_CTX*)self->state, (byte*)vstr.buf);
diff --git a/extmod/moduheapq.c b/extmod/moduheapq.c
index c0d3c6376ac6d425ec6d8d6a5ebeb6d57febc759..84ffe54f98775a8a2cfac4895412924f429700b8 100644
--- a/extmod/moduheapq.c
+++ b/extmod/moduheapq.c
@@ -37,7 +37,7 @@ STATIC mp_obj_list_t *get_heap(mp_obj_t heap_in) {
     if (!MP_OBJ_IS_TYPE(heap_in, &mp_type_list)) {
         nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "heap must be a list"));
     }
-    return heap_in;
+    return MP_OBJ_TO_PTR(heap_in);
 }
 
 STATIC void heap_siftdown(mp_obj_list_t *heap, mp_uint_t start_pos, mp_uint_t pos) {
@@ -74,7 +74,7 @@ STATIC void heap_siftup(mp_obj_list_t *heap, mp_uint_t pos) {
 
 STATIC mp_obj_t mod_uheapq_heappush(mp_obj_t heap_in, mp_obj_t item) {
     mp_obj_list_t *heap = get_heap(heap_in);
-    mp_obj_list_append(heap, item);
+    mp_obj_list_append(heap_in, item);
     heap_siftdown(heap, 0, heap->len - 1);
     return mp_const_none;
 }
diff --git a/extmod/modujson.c b/extmod/modujson.c
index 68ed264714b91298cd1db78aa5a6a83db49c88b0..4e080c975674cbd1dcfdc2d167c6e8d221ed1605 100644
--- a/extmod/modujson.c
+++ b/extmod/modujson.c
@@ -222,7 +222,7 @@ STATIC mp_obj_t mod_ujson_loads(mp_obj_t obj) {
                     mp_obj_list_init(&stack, 1);
                     stack.items[0] = stack_top;
                 } else {
-                    mp_obj_list_append(&stack, stack_top);
+                    mp_obj_list_append(MP_OBJ_FROM_PTR(&stack), stack_top);
                 }
                 stack_top = next;
                 stack_top_type = mp_obj_get_type(stack_top);
diff --git a/extmod/modure.c b/extmod/modure.c
index ef946ea9877ada9dbcfb981b6bd49ad3be2df483..5843569a50101d340c99ddd24ded2768d90e9320 100644
--- a/extmod/modure.c
+++ b/extmod/modure.c
@@ -53,12 +53,12 @@ typedef struct _mp_obj_match_t {
 
 STATIC void match_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
     (void)kind;
-    mp_obj_match_t *self = self_in;
+    mp_obj_match_t *self = MP_OBJ_TO_PTR(self_in);
     mp_printf(print, "<match num=%d>", self->num_matches);
 }
 
 STATIC mp_obj_t match_group(mp_obj_t self_in, mp_obj_t no_in) {
-    mp_obj_match_t *self = self_in;
+    mp_obj_match_t *self = MP_OBJ_TO_PTR(self_in);
     mp_int_t no = mp_obj_get_int(no_in);
     if (no < 0 || no >= self->num_matches) {
         nlr_raise(mp_obj_new_exception_arg1(&mp_type_IndexError, no_in));
@@ -83,18 +83,18 @@ STATIC const mp_obj_type_t match_type = {
     { &mp_type_type },
     .name = MP_QSTR_match,
     .print = match_print,
-    .locals_dict = (mp_obj_t)&match_locals_dict,
+    .locals_dict = (void*)&match_locals_dict,
 };
 
 STATIC void re_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
     (void)kind;
-    mp_obj_re_t *self = self_in;
+    mp_obj_re_t *self = MP_OBJ_TO_PTR(self_in);
     mp_printf(print, "<re %p>", self);
 }
 
 STATIC mp_obj_t re_exec(bool is_anchored, uint n_args, const mp_obj_t *args) {
     (void)n_args;
-    mp_obj_re_t *self = args[0];
+    mp_obj_re_t *self = MP_OBJ_TO_PTR(args[0]);
     Subject subj;
     mp_uint_t len;
     subj.begin = mp_obj_str_get_data(args[1], &len);
@@ -112,7 +112,7 @@ STATIC mp_obj_t re_exec(bool is_anchored, uint n_args, const mp_obj_t *args) {
     match->base.type = &match_type;
     match->num_matches = caps_num / 2; // caps_num counts start and end pointers
     match->str = args[1];
-    return match;
+    return MP_OBJ_FROM_PTR(match);
 }
 
 STATIC mp_obj_t re_match(mp_uint_t n_args, const mp_obj_t *args) {
@@ -126,7 +126,7 @@ STATIC mp_obj_t re_search(mp_uint_t n_args, const mp_obj_t *args) {
 MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(re_search_obj, 2, 4, re_search);
 
 STATIC mp_obj_t re_split(mp_uint_t n_args, const mp_obj_t *args) {
-    mp_obj_re_t *self = args[0];
+    mp_obj_re_t *self = MP_OBJ_TO_PTR(args[0]);
     Subject subj;
     mp_uint_t len;
     subj.begin = mp_obj_str_get_data(args[1], &len);
@@ -179,7 +179,7 @@ STATIC const mp_obj_type_t re_type = {
     { &mp_type_type },
     .name = MP_QSTR_ure,
     .print = re_print,
-    .locals_dict = (mp_obj_t)&re_locals_dict,
+    .locals_dict = (void*)&re_locals_dict,
 };
 
 STATIC mp_obj_t mod_re_compile(mp_uint_t n_args, const mp_obj_t *args) {
@@ -202,16 +202,16 @@ error:
     if (flags & FLAG_DEBUG) {
         re1_5_dumpcode(&o->re);
     }
-    return o;
+    return MP_OBJ_FROM_PTR(o);
 }
 MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_re_compile_obj, 1, 2, mod_re_compile);
 
 STATIC mp_obj_t mod_re_exec(bool is_anchored, uint n_args, const mp_obj_t *args) {
     (void)n_args;
-    mp_obj_re_t *self = mod_re_compile(1, args);
+    mp_obj_t self = mod_re_compile(1, args);
 
     const mp_obj_t args2[] = {self, args[1]};
-    mp_obj_match_t *match = re_exec(is_anchored, 2, args2);
+    mp_obj_t match = re_exec(is_anchored, 2, args2);
     return match;
 }
 
diff --git a/py/bc.c b/py/bc.c
index 909edb603baccf1769aaa3d493eaa81b7794146a..84dc3291a811b2e5caad5bc1862c6045f92cdf68 100644
--- a/py/bc.c
+++ b/py/bc.c
@@ -68,7 +68,7 @@ STATIC NORETURN void fun_pos_args_mismatch(mp_obj_fun_bc_t *f, mp_uint_t expecte
 #elif MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED
     nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
         "%q() takes %d positional arguments but %d were given",
-        mp_obj_fun_get_name(f), expected, given));
+        mp_obj_fun_get_name(MP_OBJ_FROM_PTR(f)), expected, given));
 #endif
 }
 
@@ -95,7 +95,7 @@ void mp_setup_code_state(mp_code_state *code_state, mp_obj_fun_bc_t *self, mp_ui
     mp_uint_t n_state = code_state->n_state;
 
     // ip comes in as an offset into bytecode, so turn it into a true pointer
-    code_state->ip = self->bytecode + (mp_uint_t)code_state->ip;
+    code_state->ip = self->bytecode + (size_t)code_state->ip;
 
     // store pointer to constant table
     code_state->const_table = self->const_table;
@@ -219,7 +219,7 @@ continue2:;
             if (code_state->state[n_state - 1 - n_pos_args - i] == MP_OBJ_NULL) {
                 mp_map_elem_t *elem = NULL;
                 if ((scope_flags & MP_SCOPE_FLAG_DEFKWARGS) != 0) {
-                    elem = mp_map_lookup(&((mp_obj_dict_t*)self->extra_args[n_def_pos_args])->map, arg_names[n_pos_args + i], MP_MAP_LOOKUP);
+                    elem = mp_map_lookup(&((mp_obj_dict_t*)MP_OBJ_TO_PTR(self->extra_args[n_def_pos_args]))->map, arg_names[n_pos_args + i], MP_MAP_LOOKUP);
                 }
                 if (elem != NULL) {
                     code_state->state[n_state - 1 - n_pos_args - i] = elem->value;
diff --git a/py/bc.h b/py/bc.h
index 04575cee5aeed33b6c01145feb760d4bf964eb8e..b660240c9ed2988680a68c8d3c654fe55d0bc2e8 100644
--- a/py/bc.h
+++ b/py/bc.h
@@ -66,7 +66,7 @@ typedef struct _mp_exc_stack {
     // bit 1 is whether the opcode was SETUP_WITH or SETUP_FINALLY
     mp_obj_t *val_sp;
     // Saved exception, valid if currently_in_except_block bit is 1
-    mp_obj_t prev_exc;
+    mp_obj_base_t *prev_exc;
 } mp_exc_stack_t;
 
 typedef struct _mp_code_state {
diff --git a/py/binary.c b/py/binary.c
index c9ce0585da3d6890322bc7d0cad3029dbfa545ff..699324bc6eae6582cde40a9f32feae12a820796c 100644
--- a/py/binary.c
+++ b/py/binary.c
@@ -147,7 +147,7 @@ mp_obj_t mp_binary_get_val_array(char typecode, void *p, mp_uint_t index) {
             return ((mp_obj_t*)p)[index];
         // Extension to CPython: array of pointers
         case 'P':
-            return mp_obj_new_int((mp_int_t)((void**)p)[index]);
+            return mp_obj_new_int((mp_int_t)(uintptr_t)((void**)p)[index]);
     }
     return MP_OBJ_NEW_SMALL_INT(val);
 }
@@ -199,7 +199,7 @@ mp_obj_t mp_binary_get_val(char struct_type, char val_type, byte **ptr) {
     if (val_type == 'O') {
         return (mp_obj_t)(mp_uint_t)val;
     } else if (val_type == 'S') {
-        const char *s_val = (const char*)(mp_uint_t)val;
+        const char *s_val = (const char*)(uintptr_t)(mp_uint_t)val;
         return mp_obj_new_str(s_val, strlen(s_val), false);
 #if MICROPY_PY_BUILTINS_FLOAT
     } else if (val_type == 'f') {
@@ -374,6 +374,6 @@ void mp_binary_set_val_array_from_int(char typecode, void *p, mp_uint_t index, m
 #endif
         // Extension to CPython: array of pointers
         case 'P':
-            ((void**)p)[index] = (void*)val;
+            ((void**)p)[index] = (void*)(uintptr_t)val;
     }
 }
diff --git a/py/builtinevex.c b/py/builtinevex.c
index 4cafc5ecfe7d01661e330dfe4583bcdf8ef99f4b..c14869e350a3a0bb9b7965fa75d6c1062154db63 100644
--- a/py/builtinevex.c
+++ b/py/builtinevex.c
@@ -44,7 +44,7 @@ STATIC const mp_obj_type_t mp_type_code = {
     .name = MP_QSTR_code,
 };
 
-STATIC mp_obj_t code_execute(mp_obj_code_t *self, mp_obj_t globals, mp_obj_t locals) {
+STATIC mp_obj_t code_execute(mp_obj_code_t *self, mp_obj_dict_t *globals, mp_obj_dict_t *locals) {
     // save context and set new context
     mp_obj_dict_t *old_globals = mp_globals_get();
     mp_obj_dict_t *old_locals = mp_locals_get();
@@ -54,7 +54,7 @@ STATIC mp_obj_t code_execute(mp_obj_code_t *self, mp_obj_t globals, mp_obj_t loc
     // a bit of a hack: fun_bc will re-set globals, so need to make sure it's
     // the correct one
     if (MP_OBJ_IS_TYPE(self->module_fun, &mp_type_fun_bc)) {
-        mp_obj_fun_bc_t *fun_bc = self->module_fun;
+        mp_obj_fun_bc_t *fun_bc = MP_OBJ_TO_PTR(self->module_fun);
         fun_bc->globals = globals;
     }
 
@@ -70,7 +70,7 @@ STATIC mp_obj_t code_execute(mp_obj_code_t *self, mp_obj_t globals, mp_obj_t loc
         // exception; restore context and re-raise same exception
         mp_globals_set(old_globals);
         mp_locals_set(old_locals);
-        nlr_raise(nlr.ret_val);
+        nlr_jump(nlr.ret_val);
     }
 }
 
@@ -101,7 +101,7 @@ STATIC mp_obj_t mp_builtin_compile(mp_uint_t n_args, const mp_obj_t *args) {
     mp_obj_code_t *code = m_new_obj(mp_obj_code_t);
     code->base.type = &mp_type_code;
     code->module_fun = mp_parse_compile_execute(lex, parse_input_kind, NULL, NULL);
-    return code;
+    return MP_OBJ_FROM_PTR(code);
 }
 MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_compile_obj, 3, 6, mp_builtin_compile);
 
@@ -112,9 +112,9 @@ STATIC mp_obj_t eval_exec_helper(mp_uint_t n_args, const mp_obj_t *args, mp_pars
     mp_obj_dict_t *globals = mp_globals_get();
     mp_obj_dict_t *locals = mp_locals_get();
     if (n_args > 1) {
-        globals = args[1];
+        globals = MP_OBJ_TO_PTR(args[1]);
         if (n_args > 2) {
-            locals = args[2];
+            locals = MP_OBJ_TO_PTR(args[2]);
         } else {
             locals = globals;
         }
@@ -122,7 +122,7 @@ STATIC mp_obj_t eval_exec_helper(mp_uint_t n_args, const mp_obj_t *args, mp_pars
 
     #if MICROPY_PY_BUILTINS_COMPILE
     if (MP_OBJ_IS_TYPE(args[0], &mp_type_code)) {
-        return code_execute(args[0], globals, locals);
+        return code_execute(MP_OBJ_TO_PTR(args[0]), globals, locals);
     }
     #endif
 
diff --git a/py/builtinimport.c b/py/builtinimport.c
index d50f4185902a6b81c208f225bb28e778eaaca7f0..a8d5f069680c3105f6551593d018d377b575d87a 100644
--- a/py/builtinimport.c
+++ b/py/builtinimport.c
@@ -174,7 +174,7 @@ STATIC void do_execute_raw_code(mp_obj_t module_obj, mp_raw_code_t *raw_code) {
         // exception; restore context and re-raise same exception
         mp_globals_set(old_globals);
         mp_locals_set(old_locals);
-        nlr_raise(nlr.ret_val);
+        nlr_jump(nlr.ret_val);
     }
 }
 #endif
@@ -237,15 +237,15 @@ mp_obj_t mp_builtin___import__(mp_uint_t n_args, const mp_obj_t *args) {
         // "Relative imports use a module's __name__ attribute to determine that
         // module's position in the package hierarchy."
         level--;
-        mp_obj_t this_name_q = mp_obj_dict_get(mp_globals_get(), MP_OBJ_NEW_QSTR(MP_QSTR___name__));
+        mp_obj_t this_name_q = mp_obj_dict_get(MP_OBJ_FROM_PTR(mp_globals_get()), MP_OBJ_NEW_QSTR(MP_QSTR___name__));
         assert(this_name_q != MP_OBJ_NULL);
         #if MICROPY_CPYTHON_COMPAT
         if (MP_OBJ_QSTR_VALUE(this_name_q) == MP_QSTR___main__) {
             // This is a module run by -m command-line switch, get its real name from backup attribute
-            this_name_q = mp_obj_dict_get(mp_globals_get(), MP_OBJ_NEW_QSTR(MP_QSTR___main__));
+            this_name_q = mp_obj_dict_get(MP_OBJ_FROM_PTR(mp_globals_get()), MP_OBJ_NEW_QSTR(MP_QSTR___main__));
         }
         #endif
-        mp_map_t *globals_map = mp_obj_dict_get_map(mp_globals_get());
+        mp_map_t *globals_map = &mp_globals_get()->map;
         mp_map_elem_t *elem = mp_map_lookup(globals_map, MP_OBJ_NEW_QSTR(MP_QSTR___path__), MP_MAP_LOOKUP);
         bool is_pkg = (elem != NULL);
 
@@ -338,8 +338,8 @@ mp_obj_t mp_builtin___import__(mp_uint_t n_args, const mp_obj_t *args) {
         // name to __main__ instead of real name).
         // TODO: Duplicated below too.
         if (fromtuple == mp_const_false) {
-            mp_obj_module_t *o = module_obj;
-            mp_obj_dict_store(o->globals, MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR___main__));
+            mp_obj_module_t *o = MP_OBJ_TO_PTR(module_obj);
+            mp_obj_dict_store(MP_OBJ_FROM_PTR(o->globals), MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR___main__));
         }
         do_load_from_lexer(module_obj, lex, mod_str);
         return module_obj;
@@ -409,11 +409,11 @@ mp_obj_t mp_builtin___import__(mp_uint_t n_args, const mp_obj_t *args) {
                 // this module for command-line "-m" option (set module's
                 // name to __main__ instead of real name).
                 if (i == mod_len && fromtuple == mp_const_false) {
-                    mp_obj_module_t *o = module_obj;
-                    mp_obj_dict_store(o->globals, MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR___main__));
+                    mp_obj_module_t *o = MP_OBJ_TO_PTR(module_obj);
+                    mp_obj_dict_store(MP_OBJ_FROM_PTR(o->globals), MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR___main__));
                     #if MICROPY_CPYTHON_COMPAT
                     // Store real name in "__main__" attribute. Choosen semi-randonly, to reuse existing qstr's.
-                    mp_obj_dict_store(o->globals, MP_OBJ_NEW_QSTR(MP_QSTR___main__), MP_OBJ_NEW_QSTR(mod_name));
+                    mp_obj_dict_store(MP_OBJ_FROM_PTR(o->globals), MP_OBJ_NEW_QSTR(MP_QSTR___main__), MP_OBJ_NEW_QSTR(mod_name));
                     #endif
                 }
 
diff --git a/py/emitbc.c b/py/emitbc.c
index 580ff165c00e9ce8fc3b5625779dfa7cc8ba68a1..c08501b3f813f556f51ce1b0e8a35c1e7388526a 100644
--- a/py/emitbc.c
+++ b/py/emitbc.c
@@ -38,6 +38,11 @@
 #define DUMMY_DATA_SIZE (BYTES_FOR_INT)
 
 struct _emit_t {
+    // Accessed as mp_obj_t, so must be aligned as such, and we rely on the
+    // memory allocator returning a suitably aligned pointer.
+    // Should work for cases when mp_obj_t is 64-bit on a 32-bit machine.
+    byte dummy_data[DUMMY_DATA_SIZE];
+
     pass_kind_t pass : 8;
     mp_uint_t last_emit_was_return_value : 8;
 
@@ -51,10 +56,10 @@ struct _emit_t {
     mp_uint_t max_num_labels;
     mp_uint_t *label_offsets;
 
-    mp_uint_t code_info_offset;
-    mp_uint_t code_info_size;
-    mp_uint_t bytecode_offset;
-    mp_uint_t bytecode_size;
+    size_t code_info_offset;
+    size_t code_info_size;
+    size_t bytecode_offset;
+    size_t bytecode_size;
     byte *code_base; // stores both byte code and code info
 
     #if MICROPY_PERSISTENT_CODE
@@ -63,9 +68,6 @@ struct _emit_t {
     uint16_t ct_cur_raw_code;
     #endif
     mp_uint_t *const_table;
-
-    // Accessed as mp_uint_t, so must be aligned as such
-    byte dummy_data[DUMMY_DATA_SIZE];
 };
 
 emit_t *emit_bc_new(void) {
@@ -224,16 +226,6 @@ STATIC void emit_write_bytecode_byte_const(emit_t *emit, byte b, mp_uint_t n, mp
     }
     emit_write_bytecode_byte_uint(emit, b, n);
 }
-#else
-STATIC void emit_write_bytecode_byte_ptr(emit_t *emit, byte b, void *ptr) {
-    // aligns the pointer so it is friendly to GC
-    emit_write_bytecode_byte(emit, b);
-    emit->bytecode_offset = (mp_uint_t)MP_ALIGN(emit->bytecode_offset, sizeof(mp_uint_t));
-    mp_uint_t *c = (mp_uint_t*)emit_get_cur_to_write_bytecode(emit, sizeof(mp_uint_t));
-    // Verify thar c is already uint-aligned
-    assert(c == MP_ALIGN(c, sizeof(mp_uint_t)));
-    *c = (mp_uint_t)ptr;
-}
 #endif
 
 STATIC void emit_write_bytecode_byte_qstr(emit_t* emit, byte b, qstr qst) {
@@ -248,13 +240,19 @@ STATIC void emit_write_bytecode_byte_qstr(emit_t* emit, byte b, qstr qst) {
     #endif
 }
 
-STATIC void emit_write_bytecode_byte_obj(emit_t *emit, byte b, void *ptr) {
+STATIC void emit_write_bytecode_byte_obj(emit_t *emit, byte b, mp_obj_t obj) {
     #if MICROPY_PERSISTENT_CODE
     emit_write_bytecode_byte_const(emit, b,
         emit->scope->num_pos_args + emit->scope->num_kwonly_args
-        + emit->ct_cur_obj++, (mp_uint_t)ptr);
+        + emit->ct_cur_obj++, (mp_uint_t)obj);
     #else
-    emit_write_bytecode_byte_ptr(emit, b, ptr);
+    // aligns the pointer so it is friendly to GC
+    emit_write_bytecode_byte(emit, b);
+    emit->bytecode_offset = (size_t)MP_ALIGN(emit->bytecode_offset, sizeof(mp_obj_t));
+    mp_obj_t *c = (mp_obj_t*)emit_get_cur_to_write_bytecode(emit, sizeof(mp_obj_t));
+    // Verify thar c is already uint-aligned
+    assert(c == MP_ALIGN(c, sizeof(mp_obj_t)));
+    *c = obj;
     #endif
 }
 
@@ -262,9 +260,15 @@ STATIC void emit_write_bytecode_byte_raw_code(emit_t *emit, byte b, mp_raw_code_
     #if MICROPY_PERSISTENT_CODE
     emit_write_bytecode_byte_const(emit, b,
         emit->scope->num_pos_args + emit->scope->num_kwonly_args
-        + emit->ct_num_obj + emit->ct_cur_raw_code++, (mp_uint_t)rc);
+        + emit->ct_num_obj + emit->ct_cur_raw_code++, (mp_uint_t)(uintptr_t)rc);
     #else
-    emit_write_bytecode_byte_ptr(emit, b, rc);
+    // aligns the pointer so it is friendly to GC
+    emit_write_bytecode_byte(emit, b);
+    emit->bytecode_offset = (size_t)MP_ALIGN(emit->bytecode_offset, sizeof(void*));
+    void **c = (void**)emit_get_cur_to_write_bytecode(emit, sizeof(void*));
+    // Verify thar c is already uint-aligned
+    assert(c == MP_ALIGN(c, sizeof(void*)));
+    *c = rc;
     #endif
 }
 
@@ -416,7 +420,7 @@ void mp_emit_bc_end_pass(emit_t *emit) {
     if (emit->pass == MP_PASS_CODE_SIZE) {
         #if !MICROPY_PERSISTENT_CODE
         // so bytecode is aligned
-        emit->code_info_offset = (mp_uint_t)MP_ALIGN(emit->code_info_offset, sizeof(mp_uint_t));
+        emit->code_info_offset = (size_t)MP_ALIGN(emit->code_info_offset, sizeof(mp_uint_t));
         #endif
 
         // calculate size of total code-info + bytecode, in bytes
@@ -523,7 +527,7 @@ void mp_emit_bc_load_const_tok(emit_t *emit, mp_token_kind_t tok) {
         case MP_TOKEN_KW_NONE: emit_write_bytecode_byte(emit, MP_BC_LOAD_CONST_NONE); break;
         case MP_TOKEN_KW_TRUE: emit_write_bytecode_byte(emit, MP_BC_LOAD_CONST_TRUE); break;
         no_other_choice:
-        case MP_TOKEN_ELLIPSIS: emit_write_bytecode_byte_obj(emit, MP_BC_LOAD_CONST_OBJ, (void*)&mp_const_ellipsis_obj); break;
+        case MP_TOKEN_ELLIPSIS: emit_write_bytecode_byte_obj(emit, MP_BC_LOAD_CONST_OBJ, MP_OBJ_FROM_PTR(&mp_const_ellipsis_obj)); break;
         default: assert(0); goto no_other_choice; // to help flow control analysis
     }
 }
diff --git a/py/emitglue.c b/py/emitglue.c
index 26fe3dec91d4a92ebd235872f7e6a41be24d9343..7ebd9c351847c6d6c525c74bc1c91c3214d4fe08 100644
--- a/py/emitglue.c
+++ b/py/emitglue.c
@@ -263,7 +263,7 @@ STATIC qstr load_qstr(mp_reader_t *reader) {
 STATIC mp_obj_t load_obj(mp_reader_t *reader) {
     byte obj_type = read_byte(reader);
     if (obj_type == 'e') {
-        return (mp_obj_t)&mp_const_ellipsis_obj;
+        return MP_OBJ_FROM_PTR(&mp_const_ellipsis_obj);
     } else {
         size_t len = read_uint(reader);
         vstr_t vstr;
@@ -324,7 +324,7 @@ STATIC mp_raw_code_t *load_raw_code(mp_reader_t *reader) {
         *ct++ = (mp_uint_t)load_obj(reader);
     }
     for (mp_uint_t i = 0; i < n_raw_code; ++i) {
-        *ct++ = (mp_uint_t)load_raw_code(reader);
+        *ct++ = (mp_uint_t)(uintptr_t)load_raw_code(reader);
     }
 
     // create raw_code and return it
@@ -511,7 +511,7 @@ STATIC void save_obj(mp_print_t *print, mp_obj_t o) {
         mp_print_bytes(print, &obj_type, 1);
         mp_print_uint(print, len);
         mp_print_bytes(print, (const byte*)str, len);
-    } else if (o == &mp_const_ellipsis_obj) {
+    } else if (MP_OBJ_TO_PTR(o) == &mp_const_ellipsis_obj) {
         byte obj_type = 'e';
         mp_print_bytes(print, &obj_type, 1);
     } else {
@@ -582,7 +582,7 @@ STATIC void save_raw_code(mp_print_t *print, mp_raw_code_t *rc) {
         save_obj(print, (mp_obj_t)*const_table++);
     }
     for (uint i = 0; i < rc->data.u_byte.n_raw_code; ++i) {
-        save_raw_code(print, (mp_raw_code_t*)*const_table++);
+        save_raw_code(print, (mp_raw_code_t*)(uintptr_t)*const_table++);
     }
 }
 
@@ -614,7 +614,7 @@ STATIC void fd_print_strn(void *env, const char *str, size_t len) {
 
 void mp_raw_code_save_file(mp_raw_code_t *rc, const char *filename) {
     int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644);
-    mp_print_t fd_print = {(void*)(mp_int_t)fd, fd_print_strn};
+    mp_print_t fd_print = {(void*)(intptr_t)fd, fd_print_strn};
     mp_raw_code_save(rc, &fd_print);
     close(fd);
 }
diff --git a/py/gc.c b/py/gc.c
index 2dad9d8a78738d7ae8a9c66f8cb23bd523c556bd..6de8a7a0261601badf7d6071558f98ad1e384090 100644
--- a/py/gc.c
+++ b/py/gc.c
@@ -203,7 +203,7 @@ STATIC void gc_drain_stack(void) {
         mp_obj_t *scan = (mp_obj_t*)PTR_FROM_BLOCK(block);
         for (mp_uint_t i = n_blocks * WORDS_PER_BLOCK; i > 0; i--, scan++) {
             mp_obj_t obj = *scan;
-            void *ptr2 = (void*)obj;
+            void *ptr2 = MP_OBJ_TO_PTR(obj);
             VERIFY_MARK_AND_PUSH(ptr2);
         }
     }
@@ -237,7 +237,7 @@ STATIC void gc_sweep(void) {
 #if MICROPY_ENABLE_FINALISER
                 if (FTB_GET(block)) {
                     mp_obj_t obj = (mp_obj_t)PTR_FROM_BLOCK(block);
-                    if (((mp_obj_base_t*)obj)->type != MP_OBJ_NULL) {
+                    if (((mp_obj_base_t*)MP_OBJ_TO_PTR(obj))->type != NULL) {
                         // if the object has a type then see if it has a __del__ method
                         mp_obj_t dest[2];
                         mp_load_method_maybe(obj, MP_QSTR___del__, dest);
diff --git a/py/misc.h b/py/misc.h
index 1a0c085ac344e7c7853b4c097912ea30688e0c7c..0ccb5261984e71504e6c851aea0a2b6cc3fe8f11 100644
--- a/py/misc.h
+++ b/py/misc.h
@@ -101,7 +101,7 @@ size_t m_get_peak_bytes_allocated(void);
 #define MP_ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
 
 // align ptr to the nearest multiple of "alignment"
-#define MP_ALIGN(ptr, alignment) (void*)(((mp_uint_t)(ptr) + ((alignment) - 1)) & ~((alignment) - 1))
+#define MP_ALIGN(ptr, alignment) (void*)(((uintptr_t)(ptr) + ((alignment) - 1)) & ~((alignment) - 1))
 
 /** unichar / UTF-8 *********************************************/
 
diff --git a/py/modbuiltins.c b/py/modbuiltins.c
index 768e1d9a96163977477ed3823bd68546e9bb9126..36a3d9b685931e15c4408f1dc72b81164802b8ff 100644
--- a/py/modbuiltins.c
+++ b/py/modbuiltins.c
@@ -53,7 +53,7 @@ STATIC mp_obj_t mp_builtin___build_class__(mp_uint_t n_args, const mp_obj_t *arg
     // set the new classes __locals__ object
     mp_obj_dict_t *old_locals = mp_locals_get();
     mp_obj_t class_locals = mp_obj_new_dict(0);
-    mp_locals_set(class_locals);
+    mp_locals_set(MP_OBJ_TO_PTR(class_locals));
 
     // call the class code
     mp_obj_t cell = mp_call_function_0(args[0]);
@@ -65,10 +65,10 @@ STATIC mp_obj_t mp_builtin___build_class__(mp_uint_t n_args, const mp_obj_t *arg
     mp_obj_t meta;
     if (n_args == 2) {
         // no explicit bases, so use 'type'
-        meta = (mp_obj_t)&mp_type_type;
+        meta = MP_OBJ_FROM_PTR(&mp_type_type);
     } else {
         // use type of first base object
-        meta = mp_obj_get_type(args[2]);
+        meta = MP_OBJ_FROM_PTR(mp_obj_get_type(args[2]));
     }
 
     // TODO do proper metaclass resolution for multiple base objects
@@ -206,11 +206,11 @@ STATIC mp_obj_t mp_builtin_dir(mp_uint_t n_args, const mp_obj_t *args) {
         } else {
             mp_obj_type_t *type;
             if (MP_OBJ_IS_TYPE(args[0], &mp_type_type)) {
-                type = args[0];
+                type = MP_OBJ_TO_PTR(args[0]);
             } else {
                 type = mp_obj_get_type(args[0]);
             }
-            if (type->locals_dict != MP_OBJ_NULL && MP_OBJ_IS_TYPE(type->locals_dict, &mp_type_dict)) {
+            if (type->locals_dict != NULL && type->locals_dict->base.type == &mp_type_dict) {
                 dict = type->locals_dict;
             }
         }
@@ -376,18 +376,18 @@ STATIC mp_obj_t mp_builtin_print(mp_uint_t n_args, const mp_obj_t *args, mp_map_
         end_data = mp_obj_str_get_data(end_elem->value, &end_len);
     }
     #if MICROPY_PY_IO
-    mp_obj_t stream_obj = &mp_sys_stdout_obj;
+    void *stream_obj = &mp_sys_stdout_obj;
     mp_map_elem_t *file_elem = mp_map_lookup(kwargs, MP_OBJ_NEW_QSTR(MP_QSTR_file), MP_MAP_LOOKUP);
     if (file_elem != NULL && file_elem->value != mp_const_none) {
-        stream_obj = file_elem->value;
+        stream_obj = MP_OBJ_TO_PTR(file_elem->value); // XXX may not be a concrete object
     }
 
-    mp_print_t print = {stream_obj, (mp_print_strn_t)mp_stream_write};
+    mp_print_t print = {stream_obj, mp_stream_write_adaptor};
     #endif
     for (mp_uint_t i = 0; i < n_args; i++) {
         if (i > 0) {
             #if MICROPY_PY_IO
-            mp_stream_write(stream_obj, sep_data, sep_len);
+            mp_stream_write_adaptor(stream_obj, sep_data, sep_len);
             #else
             mp_print_strn(&mp_plat_print, sep_data, sep_len, 0, 0, 0);
             #endif
@@ -399,7 +399,7 @@ STATIC mp_obj_t mp_builtin_print(mp_uint_t n_args, const mp_obj_t *args, mp_map_
         #endif
     }
     #if MICROPY_PY_IO
-    mp_stream_write(stream_obj, end_data, end_len);
+    mp_stream_write_adaptor(stream_obj, end_data, end_len);
     #else
     mp_print_strn(&mp_plat_print, end_data, end_len, 0, 0, 0);
     #endif
@@ -418,7 +418,7 @@ STATIC mp_obj_t mp_builtin___repl_print__(mp_obj_t o) {
         #endif
         #if MICROPY_CAN_OVERRIDE_BUILTINS
         mp_obj_t dest[2] = {MP_OBJ_SENTINEL, o};
-        mp_type_module.attr((mp_obj_t)&mp_module_builtins, MP_QSTR__, dest);
+        mp_type_module.attr(MP_OBJ_FROM_PTR(&mp_module_builtins), MP_QSTR__, dest);
         #endif
     }
     return mp_const_none;
@@ -490,7 +490,7 @@ STATIC mp_obj_t mp_builtin_sorted(mp_uint_t n_args, const mp_obj_t *args, mp_map
         nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
                                           "must use keyword argument for key function"));
     }
-    mp_obj_t self = mp_type_list.make_new((mp_obj_t)&mp_type_list, 1, 0, args);
+    mp_obj_t self = mp_type_list.make_new(MP_OBJ_FROM_PTR(&mp_type_list), 1, 0, args);
     mp_obj_list_sort(1, &self, kwargs);
 
     return self;
diff --git a/py/modstruct.c b/py/modstruct.c
index fb206bc35f15deb4044f25f393c799cac569e0de..a52c5070fe748702559a74ba5d9db91f36a20548 100644
--- a/py/modstruct.c
+++ b/py/modstruct.c
@@ -137,7 +137,7 @@ STATIC mp_obj_t struct_unpack(mp_obj_t fmt_in, mp_obj_t data_in) {
     const char *fmt = mp_obj_str_get_str(fmt_in);
     char fmt_type = get_fmt_type(&fmt);
     uint size = calcsize_items(fmt);
-    mp_obj_tuple_t *res = mp_obj_new_tuple(size, NULL);
+    mp_obj_tuple_t *res = MP_OBJ_TO_PTR(mp_obj_new_tuple(size, NULL));
     mp_buffer_info_t bufinfo;
     mp_get_buffer_raise(data_in, &bufinfo, MP_BUFFER_READ);
     byte *p = bufinfo.buf;
@@ -161,7 +161,7 @@ STATIC mp_obj_t struct_unpack(mp_obj_t fmt_in, mp_obj_t data_in) {
         }
         fmt++;
     }
-    return res;
+    return MP_OBJ_FROM_PTR(res);
 }
 MP_DEFINE_CONST_FUN_OBJ_2(struct_unpack_obj, struct_unpack);
 
diff --git a/py/modsys.c b/py/modsys.c
index 3aa1109b8d7cf5605d00c9c2b24b3005528fd9a0..57ac2bf058dd7e9fd86cfa22edce2be1f4e93561 100644
--- a/py/modsys.c
+++ b/py/modsys.c
@@ -45,7 +45,7 @@ extern struct _mp_dummy_t mp_sys_stdout_obj;
 extern struct _mp_dummy_t mp_sys_stderr_obj;
 
 #if MICROPY_PY_IO
-const mp_print_t mp_sys_stdout_print = {&mp_sys_stdout_obj, (mp_print_strn_t)mp_stream_write};
+const mp_print_t mp_sys_stdout_print = {&mp_sys_stdout_obj, mp_stream_write_adaptor};
 #endif
 
 /// \constant version - Python language version that this implementation conforms to, as a string
@@ -106,12 +106,12 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_sys_exit_obj, 0, 1, mp_sys_exit);
 
 STATIC mp_obj_t mp_sys_print_exception(mp_uint_t n_args, const mp_obj_t *args) {
     #if MICROPY_PY_IO
-    mp_obj_t stream_obj = &mp_sys_stdout_obj;
+    void *stream_obj = &mp_sys_stdout_obj;
     if (n_args > 1) {
-        stream_obj = args[1];
+        stream_obj = MP_OBJ_TO_PTR(args[1]); // XXX may fail
     }
 
-    mp_print_t print = {stream_obj, (mp_print_strn_t)mp_stream_write};
+    mp_print_t print = {stream_obj, mp_stream_write_adaptor};
     mp_obj_print_exception(&print, args[0]);
     #else
     (void)n_args;
@@ -124,20 +124,20 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_sys_print_exception_obj, 1, 2, mp_sys_pri
 
 #if MICROPY_PY_SYS_EXC_INFO
 STATIC mp_obj_t mp_sys_exc_info(void) {
-    mp_obj_t cur_exc = MP_STATE_VM(cur_exception);
-    mp_obj_tuple_t *t = mp_obj_new_tuple(3, NULL);
+    mp_obj_t cur_exc = MP_OBJ_FROM_PTR(MP_STATE_VM(cur_exception));
+    mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(3, NULL));
 
     if (cur_exc == MP_OBJ_NULL) {
         t->items[0] = mp_const_none;
         t->items[1] = mp_const_none;
         t->items[2] = mp_const_none;
-        return t;
+        return MP_OBJ_FROM_PTR(t);
     }
 
-    t->items[0] = mp_obj_get_type(cur_exc);
+    t->items[0] = MP_OBJ_FROM_PTR(mp_obj_get_type(cur_exc));
     t->items[1] = cur_exc;
     t->items[2] = mp_const_none;
-    return t;
+    return MP_OBJ_FROM_PTR(t);
 }
 MP_DEFINE_CONST_FUN_OBJ_0(mp_sys_exc_info_obj, mp_sys_exc_info);
 #endif
diff --git a/py/mpstate.h b/py/mpstate.h
index 78f497e60b9acdf7cdcd2270be303fa302070024..d0baad2b78f267ff97dcfd9abbeb7512752514c2 100644
--- a/py/mpstate.h
+++ b/py/mpstate.h
@@ -109,7 +109,7 @@ typedef struct _mp_state_vm_t {
 
     // current exception being handled, for sys.exc_info()
     #if MICROPY_PY_SYS_EXC_INFO
-    mp_obj_t cur_exception;
+    mp_obj_base_t *cur_exception;
     #endif
 
     // dictionary for the __main__ module
diff --git a/py/nlr.h b/py/nlr.h
index 16cab1c6678763729c86bc7ba6ecb69c25bc5317..aacac6a59ccf6dd29e1a81d043e201cd1164e0b0 100644
--- a/py/nlr.h
+++ b/py/nlr.h
@@ -39,7 +39,7 @@ typedef struct _nlr_buf_t nlr_buf_t;
 struct _nlr_buf_t {
     // the entries here must all be machine word size
     nlr_buf_t *prev;
-    void *ret_val;
+    void *ret_val; // always a concrete object (an exception instance)
 #if !defined(MICROPY_NLR_SETJMP) || !MICROPY_NLR_SETJMP
 #if defined(__i386__)
     void *regs[6];
@@ -86,16 +86,16 @@ void nlr_jump_fail(void *val);
 
 // use nlr_raise instead of nlr_jump so that debugging is easier
 #ifndef DEBUG
-#define nlr_raise(val) nlr_jump(val)
+#define nlr_raise(val) nlr_jump(MP_OBJ_TO_PTR(val))
 #else
 #include "mpstate.h"
 #define nlr_raise(val) \
     do { \
         /*printf("nlr_raise: nlr_top=%p\n", MP_STATE_VM(nlr_top)); \
         fflush(stdout);*/ \
-        void *_val = val; \
+        void *_val = MP_OBJ_TO_PTR(val); \
         assert(_val != NULL); \
-        assert(mp_obj_is_exception_instance(_val)); \
+        assert(mp_obj_is_exception_instance(val)); \
         nlr_jump(_val); \
     } while (0)
 
diff --git a/py/obj.c b/py/obj.c
index 42bf0c5009f1a6551af7c650d3be637befb18840..baac1f568a30a78a525ce6563d1d5d08bb9a8d73 100644
--- a/py/obj.c
+++ b/py/obj.c
@@ -41,16 +41,16 @@
 
 mp_obj_type_t *mp_obj_get_type(mp_const_obj_t o_in) {
     if (MP_OBJ_IS_SMALL_INT(o_in)) {
-        return (mp_obj_t)&mp_type_int;
+        return (mp_obj_type_t*)&mp_type_int;
     } else if (MP_OBJ_IS_QSTR(o_in)) {
-        return (mp_obj_t)&mp_type_str;
+        return (mp_obj_type_t*)&mp_type_str;
     #if MICROPY_PY_BUILTINS_FLOAT
     } else if (mp_obj_is_float(o_in)) {
-        return (mp_obj_t)&mp_type_float;
+        return (mp_obj_type_t*)&mp_type_float;
     #endif
     } else {
-        const mp_obj_base_t *o = o_in;
-        return (mp_obj_t)o->type;
+        const mp_obj_base_t *o = MP_OBJ_TO_PTR(o_in);
+        return (mp_obj_type_t*)o->type;
     }
 }
 
@@ -62,7 +62,7 @@ void mp_obj_print_helper(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t
     // There can be data structures nested too deep, or just recursive
     MP_STACK_CHECK();
 #ifndef NDEBUG
-    if (o_in == NULL) {
+    if (o_in == MP_OBJ_NULL) {
         mp_print_str(print, "(nil)");
         return;
     }
diff --git a/py/obj.h b/py/obj.h
index b969ed5fedbb3fb16497b262ef1345cdd4c56cf1..09c8eda64658536d26fe2049de60f42e1b374c10 100644
--- a/py/obj.h
+++ b/py/obj.h
@@ -58,13 +58,13 @@ typedef struct _mp_obj_base_t mp_obj_base_t;
 // as many as we can to MP_OBJ_NULL because it's cheaper to load/compare 0.
 
 #ifdef NDEBUG
-#define MP_OBJ_NULL             ((mp_obj_t)0)
-#define MP_OBJ_STOP_ITERATION   ((mp_obj_t)0)
-#define MP_OBJ_SENTINEL         ((mp_obj_t)4)
+#define MP_OBJ_NULL             (MP_OBJ_FROM_PTR((void*)0))
+#define MP_OBJ_STOP_ITERATION   (MP_OBJ_FROM_PTR((void*)0))
+#define MP_OBJ_SENTINEL         (MP_OBJ_FROM_PTR((void*)4))
 #else
-#define MP_OBJ_NULL             ((mp_obj_t)0)
-#define MP_OBJ_STOP_ITERATION   ((mp_obj_t)4)
-#define MP_OBJ_SENTINEL         ((mp_obj_t)8)
+#define MP_OBJ_NULL             (MP_OBJ_FROM_PTR((void*)0))
+#define MP_OBJ_STOP_ITERATION   (MP_OBJ_FROM_PTR((void*)4))
+#define MP_OBJ_SENTINEL         (MP_OBJ_FROM_PTR((void*)8))
 #endif
 
 // These macros/inline functions operate on objects and depend on the
@@ -166,13 +166,13 @@ static inline bool MP_OBJ_IS_OBJ(mp_const_obj_t o)
 // object representation and memory management.
 
 // Cast mp_obj_t to object pointer
-#ifndef MP_OBJ_CAST
-#define MP_OBJ_CAST(o) ((void*)o)
+#ifndef MP_OBJ_TO_PTR
+#define MP_OBJ_TO_PTR(o) ((void*)o)
 #endif
 
 // Cast object pointer to mp_obj_t
-#ifndef MP_OBJ_UNCAST
-#define MP_OBJ_UNCAST(p) ((mp_obj_t)p)
+#ifndef MP_OBJ_FROM_PTR
+#define MP_OBJ_FROM_PTR(p) ((mp_obj_t)p)
 #endif
 
 // Macros to create objects that are stored in ROM.
@@ -193,11 +193,11 @@ typedef struct _mp_rom_obj_t { mp_const_obj_t o; } mp_rom_obj_t;
 // The macros below are derived from the ones above and are used to
 // check for more specific object types.
 
-#define MP_OBJ_IS_TYPE(o, t) (MP_OBJ_IS_OBJ(o) && (((mp_obj_base_t*)(o))->type == (t))) // this does not work for checking int, str or fun; use below macros for that
+#define MP_OBJ_IS_TYPE(o, t) (MP_OBJ_IS_OBJ(o) && (((mp_obj_base_t*)MP_OBJ_TO_PTR(o))->type == (t))) // this does not work for checking int, str or fun; use below macros for that
 #define MP_OBJ_IS_INT(o) (MP_OBJ_IS_SMALL_INT(o) || MP_OBJ_IS_TYPE(o, &mp_type_int))
 #define MP_OBJ_IS_STR(o) (MP_OBJ_IS_QSTR(o) || MP_OBJ_IS_TYPE(o, &mp_type_str))
-#define MP_OBJ_IS_STR_OR_BYTES(o) (MP_OBJ_IS_QSTR(o) || (MP_OBJ_IS_OBJ(o) && ((mp_obj_base_t*)(o))->type->binary_op == mp_obj_str_binary_op))
-#define MP_OBJ_IS_FUN(o) (MP_OBJ_IS_OBJ(o) && (((mp_obj_base_t*)(o))->type->name == MP_QSTR_function))
+#define MP_OBJ_IS_STR_OR_BYTES(o) (MP_OBJ_IS_QSTR(o) || (MP_OBJ_IS_OBJ(o) && ((mp_obj_base_t*)MP_OBJ_TO_PTR(o))->type->binary_op == mp_obj_str_binary_op))
+#define MP_OBJ_IS_FUN(o) (MP_OBJ_IS_OBJ(o) && (((mp_obj_base_t*)MP_OBJ_TO_PTR(o))->type->name == MP_QSTR_function))
 
 // Note: inline functions sometimes use much more code space than the
 // equivalent macros, depending on the compiler.
@@ -382,7 +382,7 @@ typedef struct _mp_stream_p_t {
     // are implementation-dependent, but will be exposed to user, e.g. via exception).
     mp_uint_t (*read)(mp_obj_t obj, void *buf, mp_uint_t size, int *errcode);
     mp_uint_t (*write)(mp_obj_t obj, const void *buf, mp_uint_t size, int *errcode);
-    mp_uint_t (*ioctl)(mp_obj_t obj, mp_uint_t request, mp_uint_t arg, int *errcode);
+    mp_uint_t (*ioctl)(mp_obj_t obj, mp_uint_t request, uintptr_t arg, int *errcode);
     mp_uint_t is_text : 1; // default is bytes, set this for text stream
 } mp_stream_p_t;
 
@@ -431,8 +431,8 @@ struct _mp_obj_type_t {
     const mp_stream_p_t *stream_p;
 
     // these are for dynamically created types (classes)
-    mp_obj_t bases_tuple;
-    mp_obj_t locals_dict;
+    struct _mp_obj_tuple_t *bases_tuple;
+    struct _mp_obj_dict_t *locals_dict;
 
     /*
     What we might need to add here:
@@ -517,11 +517,11 @@ extern const mp_obj_type_t mp_type_ZeroDivisionError;
 
 // Constant objects, globally accessible
 // The macros are for convenience only
-#define mp_const_none ((mp_obj_t)&mp_const_none_obj)
-#define mp_const_false ((mp_obj_t)&mp_const_false_obj)
-#define mp_const_true ((mp_obj_t)&mp_const_true_obj)
-#define mp_const_empty_bytes ((mp_obj_t)&mp_const_empty_bytes_obj)
-#define mp_const_empty_tuple ((mp_obj_t)&mp_const_empty_tuple_obj)
+#define mp_const_none (MP_OBJ_FROM_PTR(&mp_const_none_obj))
+#define mp_const_false (MP_OBJ_FROM_PTR(&mp_const_false_obj))
+#define mp_const_true (MP_OBJ_FROM_PTR(&mp_const_true_obj))
+#define mp_const_empty_bytes (MP_OBJ_FROM_PTR(&mp_const_empty_bytes_obj))
+#define mp_const_empty_tuple (MP_OBJ_FROM_PTR(&mp_const_empty_tuple_obj))
 extern const struct _mp_obj_none_t mp_const_none_obj;
 extern const struct _mp_obj_bool_t mp_const_false_obj;
 extern const struct _mp_obj_bool_t mp_const_true_obj;
diff --git a/py/objarray.c b/py/objarray.c
index d65bb61faabe668e3bfd90e22ad6f77edb0e776c..3445bff82e597e23d0be2f540fade75c14033d74 100644
--- a/py/objarray.c
+++ b/py/objarray.c
@@ -78,7 +78,7 @@ STATIC mp_int_t array_get_buffer(mp_obj_t o_in, mp_buffer_info_t *bufinfo, mp_ui
 #if MICROPY_PY_BUILTINS_BYTEARRAY || MICROPY_PY_ARRAY
 STATIC void array_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
     (void)kind;
-    mp_obj_array_t *o = o_in;
+    mp_obj_array_t *o = MP_OBJ_TO_PTR(o_in);
     if (o->typecode == BYTEARRAY_TYPECODE) {
         mp_print_str(print, "bytearray(b");
         mp_str_print_quoted(print, o->items, o->len, true);
@@ -138,7 +138,7 @@ STATIC mp_obj_t array_construct(char typecode, mp_obj_t initializer) {
         mp_uint_t len = bufinfo.len / sz;
         mp_obj_array_t *o = array_new(typecode, len);
         memcpy(o->items, bufinfo.buf, len * sz);
-        return o;
+        return MP_OBJ_FROM_PTR(o);
     }
 
     mp_uint_t len;
@@ -157,13 +157,13 @@ STATIC mp_obj_t array_construct(char typecode, mp_obj_t initializer) {
     mp_uint_t i = 0;
     while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
         if (len == 0) {
-            array_append(array, item);
+            array_append(MP_OBJ_FROM_PTR(array), item);
         } else {
             mp_binary_set_val_array(typecode, array->items, i++, item);
         }
     }
 
-    return array;
+    return MP_OBJ_FROM_PTR(array);
 }
 #endif
 
@@ -178,7 +178,7 @@ STATIC mp_obj_t array_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_k
 
     if (n_args == 1) {
         // 1 arg: make an empty array
-        return array_new(*typecode, 0);
+        return MP_OBJ_FROM_PTR(array_new(*typecode, 0));
     } else {
         // 2 args: construct the array from the given object
         return array_construct(*typecode, args[1]);
@@ -193,13 +193,13 @@ STATIC mp_obj_t bytearray_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t
 
     if (n_args == 0) {
         // no args: construct an empty bytearray
-        return array_new(BYTEARRAY_TYPECODE, 0);
+        return MP_OBJ_FROM_PTR(array_new(BYTEARRAY_TYPECODE, 0));
     } else if (MP_OBJ_IS_INT(args[0])) {
         // 1 arg, an integer: construct a blank bytearray of that length
         mp_uint_t len = mp_obj_get_int(args[0]);
         mp_obj_array_t *o = array_new(BYTEARRAY_TYPECODE, len);
         memset(o->items, 0, len);
-        return o;
+        return MP_OBJ_FROM_PTR(o);
     } else {
         // 1 arg: construct the bytearray from that
         return array_construct(BYTEARRAY_TYPECODE, args[0]);
@@ -216,7 +216,7 @@ mp_obj_t mp_obj_new_memoryview(byte typecode, mp_uint_t nitems, void *items) {
     self->free = 0;
     self->len = nitems;
     self->items = items;
-    return self;
+    return MP_OBJ_FROM_PTR(self);
 }
 
 STATIC mp_obj_t memoryview_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
@@ -230,21 +230,21 @@ STATIC mp_obj_t memoryview_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_
     mp_buffer_info_t bufinfo;
     mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ);
 
-    mp_obj_array_t *self = mp_obj_new_memoryview(bufinfo.typecode,
+    mp_obj_array_t *self = MP_OBJ_TO_PTR(mp_obj_new_memoryview(bufinfo.typecode,
         bufinfo.len / mp_binary_get_size('@', bufinfo.typecode, NULL),
-        bufinfo.buf);
+        bufinfo.buf));
 
     // test if the object can be written to
     if (mp_get_buffer(args[0], &bufinfo, MP_BUFFER_RW)) {
         self->typecode |= 0x80; // used to indicate writable buffer
     }
 
-    return self;
+    return MP_OBJ_FROM_PTR(self);
 }
 #endif
 
 STATIC mp_obj_t array_unary_op(mp_uint_t op, mp_obj_t o_in) {
-    mp_obj_array_t *o = o_in;
+    mp_obj_array_t *o = MP_OBJ_TO_PTR(o_in);
     switch (op) {
         case MP_UNARY_OP_BOOL: return mp_obj_new_bool(o->len != 0);
         case MP_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT(o->len);
@@ -253,7 +253,7 @@ STATIC mp_obj_t array_unary_op(mp_uint_t op, mp_obj_t o_in) {
 }
 
 STATIC mp_obj_t array_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
-    mp_obj_array_t *lhs = lhs_in;
+    mp_obj_array_t *lhs = MP_OBJ_TO_PTR(lhs_in);
     switch (op) {
         case MP_BINARY_OP_ADD: {
             // allow to add anything that has the buffer protocol (extension to CPython)
@@ -270,7 +270,7 @@ STATIC mp_obj_t array_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in)
             // note: lhs->len is element count of lhs, lhs_bufinfo.len is byte count
             mp_obj_array_t *res = array_new(lhs_bufinfo.typecode, lhs->len + rhs_len);
             mp_seq_cat((byte*)res->items, lhs_bufinfo.buf, lhs_bufinfo.len, rhs_bufinfo.buf, rhs_len * sz, byte);
-            return res;
+            return MP_OBJ_FROM_PTR(res);
         }
 
         case MP_BINARY_OP_INPLACE_ADD: {
@@ -279,8 +279,8 @@ STATIC mp_obj_t array_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in)
                 return MP_OBJ_NULL; // op not supported
             }
             #endif
-            array_extend(lhs, rhs_in);
-            return lhs;
+            array_extend(lhs_in, rhs_in);
+            return lhs_in;
         }
 
         case MP_BINARY_OP_EQUAL: {
@@ -303,7 +303,7 @@ STATIC mp_obj_t array_append(mp_obj_t self_in, mp_obj_t arg) {
     // self is not a memoryview, so we don't need to use (& TYPECODE_MASK)
     assert((MICROPY_PY_BUILTINS_BYTEARRAY && MP_OBJ_IS_TYPE(self_in, &mp_type_bytearray))
         || (MICROPY_PY_ARRAY && MP_OBJ_IS_TYPE(self_in, &mp_type_array)));
-    mp_obj_array_t *self = self_in;
+    mp_obj_array_t *self = MP_OBJ_TO_PTR(self_in);
 
     if (self->free == 0) {
         size_t item_sz = mp_binary_get_size('@', self->typecode, NULL);
@@ -322,7 +322,7 @@ STATIC mp_obj_t array_extend(mp_obj_t self_in, mp_obj_t arg_in) {
     // self is not a memoryview, so we don't need to use (& TYPECODE_MASK)
     assert((MICROPY_PY_BUILTINS_BYTEARRAY && MP_OBJ_IS_TYPE(self_in, &mp_type_bytearray))
         || (MICROPY_PY_ARRAY && MP_OBJ_IS_TYPE(self_in, &mp_type_array)));
-    mp_obj_array_t *self = self_in;
+    mp_obj_array_t *self = MP_OBJ_TO_PTR(self_in);
 
     // allow to extend by anything that has the buffer protocol (extension to CPython)
     mp_buffer_info_t arg_bufinfo;
@@ -359,7 +359,7 @@ STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value
         // slice deletion
         return MP_OBJ_NULL; // op not supported
     } else {
-        mp_obj_array_t *o = self_in;
+        mp_obj_array_t *o = MP_OBJ_TO_PTR(self_in);
         if (0) {
 #if MICROPY_PY_BUILTINS_SLICE
         } else if (MP_OBJ_IS_TYPE(index_in, &mp_type_slice)) {
@@ -373,9 +373,9 @@ STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value
                 mp_uint_t src_len;
                 void *src_items;
                 size_t item_sz = mp_binary_get_size('@', o->typecode & TYPECODE_MASK, NULL);
-                if (MP_OBJ_IS_OBJ(value) && ((mp_obj_base_t*)value)->type->subscr == array_subscr) {
+                if (MP_OBJ_IS_OBJ(value) && ((mp_obj_base_t*)MP_OBJ_TO_PTR(value))->type->subscr == array_subscr) {
                     // value is array, bytearray or memoryview
-                    mp_obj_array_t *src_slice = value;
+                    mp_obj_array_t *src_slice = MP_OBJ_TO_PTR(value);
                     if (item_sz != mp_binary_get_size('@', src_slice->typecode & TYPECODE_MASK, NULL)) {
                     compat_error:
                         nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "lhs and rhs should be compatible"));
@@ -449,7 +449,7 @@ STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value
                 res = array_new(o->typecode, slice.stop - slice.start);
                 memcpy(res->items, (uint8_t*)o->items + slice.start * sz, (slice.stop - slice.start) * sz);
             }
-            return res;
+            return MP_OBJ_FROM_PTR(res);
 #endif
         } else {
             mp_uint_t index = mp_get_index(o->base.type, o->len, index_in, false);
@@ -475,7 +475,7 @@ STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value
 }
 
 STATIC mp_int_t array_get_buffer(mp_obj_t o_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) {
-    mp_obj_array_t *o = o_in;
+    mp_obj_array_t *o = MP_OBJ_TO_PTR(o_in);
     size_t sz = mp_binary_get_size('@', o->typecode & TYPECODE_MASK, NULL);
     bufinfo->buf = o->items;
     bufinfo->len = o->len * sz;
@@ -514,7 +514,7 @@ const mp_obj_type_t mp_type_array = {
     .binary_op = array_binary_op,
     .subscr = array_subscr,
     .buffer_p = { .get_buffer = array_get_buffer },
-    .locals_dict = (mp_obj_t)&array_locals_dict,
+    .locals_dict = (mp_obj_dict_t*)&array_locals_dict,
 };
 #endif
 
@@ -529,7 +529,7 @@ const mp_obj_type_t mp_type_bytearray = {
     .binary_op = array_binary_op,
     .subscr = array_subscr,
     .buffer_p = { .get_buffer = array_get_buffer },
-    .locals_dict = (mp_obj_t)&array_locals_dict,
+    .locals_dict = (mp_obj_dict_t*)&array_locals_dict,
 };
 #endif
 
@@ -556,7 +556,7 @@ mp_uint_t mp_obj_array_len(mp_obj_t self_in) {
 mp_obj_t mp_obj_new_bytearray(mp_uint_t n, void *items) {
     mp_obj_array_t *o = array_new(BYTEARRAY_TYPECODE, n);
     memcpy(o->items, items, n);
-    return o;
+    return MP_OBJ_FROM_PTR(o);
 }
 
 // Create bytearray which references specified memory area
@@ -567,7 +567,7 @@ mp_obj_t mp_obj_new_bytearray_by_ref(mp_uint_t n, void *items) {
     o->free = 0;
     o->len = n;
     o->items = items;
-    return o;
+    return MP_OBJ_FROM_PTR(o);
 }
 #endif
 
@@ -582,7 +582,7 @@ typedef struct _mp_obj_array_it_t {
 } mp_obj_array_it_t;
 
 STATIC mp_obj_t array_it_iternext(mp_obj_t self_in) {
-    mp_obj_array_it_t *self = self_in;
+    mp_obj_array_it_t *self = MP_OBJ_TO_PTR(self_in);
     if (self->cur < self->array->len) {
         return mp_binary_get_val_array(self->array->typecode & TYPECODE_MASK, self->array->items, self->offset + self->cur++);
     } else {
@@ -598,7 +598,7 @@ STATIC const mp_obj_type_t array_it_type = {
 };
 
 STATIC mp_obj_t array_iterator_new(mp_obj_t array_in) {
-    mp_obj_array_t *array = array_in;
+    mp_obj_array_t *array = MP_OBJ_TO_PTR(array_in);
     mp_obj_array_it_t *o = m_new0(mp_obj_array_it_t, 1);
     o->base.type = &array_it_type;
     o->array = array;
@@ -607,7 +607,7 @@ STATIC mp_obj_t array_iterator_new(mp_obj_t array_in) {
         o->offset = array->free;
     }
     #endif
-    return o;
+    return MP_OBJ_FROM_PTR(o);
 }
 
 #endif // MICROPY_PY_ARRAY || MICROPY_PY_BUILTINS_BYTEARRAY || MICROPY_PY_BUILTINS_MEMORYVIEW
diff --git a/py/objattrtuple.c b/py/objattrtuple.c
index 04c17a2c64e74f1c54648f4d8cd1f7170af0c639..c6dd3aeacfead4d9386b7769a644bae046a00d3e 100644
--- a/py/objattrtuple.c
+++ b/py/objattrtuple.c
@@ -50,17 +50,17 @@ void mp_obj_attrtuple_print_helper(const mp_print_t *print, const qstr *fields,
 
 STATIC void mp_obj_attrtuple_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
     (void)kind;
-    mp_obj_tuple_t *o = o_in;
-    const qstr *fields = (const qstr*)o->items[o->len];
+    mp_obj_tuple_t *o = MP_OBJ_TO_PTR(o_in);
+    const qstr *fields = (const qstr*)MP_OBJ_TO_PTR(o->items[o->len]);
     mp_obj_attrtuple_print_helper(print, fields, o);
 }
 
 STATIC void mp_obj_attrtuple_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
     if (dest[0] == MP_OBJ_NULL) {
         // load attribute
-        mp_obj_tuple_t *self = self_in;
+        mp_obj_tuple_t *self = MP_OBJ_TO_PTR(self_in);
         mp_uint_t len = self->len;
-        const qstr *fields = (const qstr*)self->items[len];
+        const qstr *fields = (const qstr*)MP_OBJ_TO_PTR(self->items[len]);
         for (mp_uint_t i = 0; i < len; i++) {
             if (fields[i] == attr) {
                 dest[0] = self->items[i];
@@ -77,8 +77,8 @@ mp_obj_t mp_obj_new_attrtuple(const qstr *fields, mp_uint_t n, const mp_obj_t *i
     for (mp_uint_t i = 0; i < n; i++) {
         o->items[i] = items[i];
     }
-    o->items[n] = (void*)fields;
-    return o;
+    o->items[n] = MP_OBJ_FROM_PTR(fields);
+    return MP_OBJ_FROM_PTR(o);
 }
 
 const mp_obj_type_t mp_type_attrtuple = {
diff --git a/py/objbool.c b/py/objbool.c
index e0640b42a38847afb4e9681fabfe6594a660cef7..622005657afd74d0f05fd06bee93315bdf896493 100644
--- a/py/objbool.c
+++ b/py/objbool.c
@@ -36,7 +36,7 @@ typedef struct _mp_obj_bool_t {
 } mp_obj_bool_t;
 
 STATIC void bool_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
-    mp_obj_bool_t *self = self_in;
+    mp_obj_bool_t *self = MP_OBJ_TO_PTR(self_in);
     if (MICROPY_PY_UJSON && kind == PRINT_JSON) {
         if (self->value) {
             mp_print_str(print, "true");
@@ -66,7 +66,7 @@ STATIC mp_obj_t bool_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw
 }
 
 STATIC mp_obj_t bool_unary_op(mp_uint_t op, mp_obj_t o_in) {
-    mp_int_t value = ((mp_obj_bool_t*)o_in)->value;
+    mp_int_t value = ((mp_obj_bool_t*)MP_OBJ_TO_PTR(o_in))->value;
     switch (op) {
         case MP_UNARY_OP_BOOL: return o_in;
         // needs to hash to the same value as if converting to an integer
@@ -88,7 +88,7 @@ STATIC mp_obj_t bool_unary_op(mp_uint_t op, mp_obj_t o_in) {
 }
 
 STATIC mp_obj_t bool_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
-    mp_obj_bool_t *self = lhs_in;
+    mp_obj_bool_t *self = MP_OBJ_TO_PTR(lhs_in);
     return mp_binary_op(op, MP_OBJ_NEW_SMALL_INT(self->value), rhs_in);
 }
 
diff --git a/py/objboundmeth.c b/py/objboundmeth.c
index b96159235934782894f55088f7505fc715189704..c19192397999e545d607f20e039742b7a6087544 100644
--- a/py/objboundmeth.c
+++ b/py/objboundmeth.c
@@ -38,7 +38,7 @@ typedef struct _mp_obj_bound_meth_t {
 #if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED
 STATIC void bound_meth_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
     (void)kind;
-    mp_obj_bound_meth_t *o = o_in;
+    mp_obj_bound_meth_t *o = MP_OBJ_TO_PTR(o_in);
     mp_printf(print, "<bound_method %p ", o);
     mp_obj_print_helper(print, o->self, PRINT_REPR);
     mp_print_str(print, ".");
@@ -48,7 +48,7 @@ STATIC void bound_meth_print(const mp_print_t *print, mp_obj_t o_in, mp_print_ki
 #endif
 
 STATIC mp_obj_t bound_meth_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
-    mp_obj_bound_meth_t *self = self_in;
+    mp_obj_bound_meth_t *self = MP_OBJ_TO_PTR(self_in);
 
     // need to insert self->self before all other args and then call self->meth
 
@@ -77,7 +77,7 @@ STATIC void bound_meth_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
         return;
     }
     if (attr == MP_QSTR___name__) {
-        mp_obj_bound_meth_t *o = self_in;
+        mp_obj_bound_meth_t *o = MP_OBJ_TO_PTR(self_in);
         dest[0] = MP_OBJ_NEW_QSTR(mp_obj_fun_get_name(o->meth));
     }
 }
@@ -100,5 +100,5 @@ mp_obj_t mp_obj_new_bound_meth(mp_obj_t meth, mp_obj_t self) {
     o->base.type = &mp_type_bound_meth;
     o->meth = meth;
     o->self = self;
-    return o;
+    return MP_OBJ_FROM_PTR(o);
 }
diff --git a/py/objcell.c b/py/objcell.c
index 97f1ecd63c2462fdb8684a07feb3646cb8b35adc..06a88b95474bd112d6d23f43e57a35cc63d3617d 100644
--- a/py/objcell.c
+++ b/py/objcell.c
@@ -32,19 +32,19 @@ typedef struct _mp_obj_cell_t {
 } mp_obj_cell_t;
 
 mp_obj_t mp_obj_cell_get(mp_obj_t self_in) {
-    mp_obj_cell_t *self = self_in;
+    mp_obj_cell_t *self = MP_OBJ_TO_PTR(self_in);
     return self->obj;
 }
 
 void mp_obj_cell_set(mp_obj_t self_in, mp_obj_t obj) {
-    mp_obj_cell_t *self = self_in;
+    mp_obj_cell_t *self = MP_OBJ_TO_PTR(self_in);
     self->obj = obj;
 }
 
 #if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED
 STATIC void cell_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
     (void)kind;
-    mp_obj_cell_t *o = o_in;
+    mp_obj_cell_t *o = MP_OBJ_TO_PTR(o_in);
     mp_printf(print, "<cell %p ", o->obj);
     if (o->obj == MP_OBJ_NULL) {
         mp_print_str(print, "(nil)");
@@ -67,5 +67,5 @@ mp_obj_t mp_obj_new_cell(mp_obj_t obj) {
     mp_obj_cell_t *o = m_new_obj(mp_obj_cell_t);
     o->base.type = &mp_type_cell;
     o->obj = obj;
-    return o;
+    return MP_OBJ_FROM_PTR(o);
 }
diff --git a/py/objclosure.c b/py/objclosure.c
index a4000e5ddbd4aa08edd34e79c458b1f5b403d950..e331a659bb35bcdd75d0c25d65403529d3b0a305 100644
--- a/py/objclosure.c
+++ b/py/objclosure.c
@@ -37,7 +37,7 @@ typedef struct _mp_obj_closure_t {
 } mp_obj_closure_t;
 
 STATIC mp_obj_t closure_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
-    mp_obj_closure_t *self = self_in;
+    mp_obj_closure_t *self = MP_OBJ_TO_PTR(self_in);
 
     // need to concatenate closed-over-vars and args
 
@@ -62,7 +62,7 @@ STATIC mp_obj_t closure_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw,
 #if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_DETAILED
 STATIC void closure_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
     (void)kind;
-    mp_obj_closure_t *o = o_in;
+    mp_obj_closure_t *o = MP_OBJ_TO_PTR(o_in);
     mp_print_str(print, "<closure ");
     mp_obj_print_helper(print, o->fun, PRINT_REPR);
     mp_printf(print, " at %p, n_closed=%u ", o, o->n_closed);
@@ -93,5 +93,5 @@ mp_obj_t mp_obj_new_closure(mp_obj_t fun, mp_uint_t n_closed_over, const mp_obj_
     o->fun = fun;
     o->n_closed = n_closed_over;
     memcpy(o->closed, closed, n_closed_over * sizeof(mp_obj_t));
-    return o;
+    return MP_OBJ_FROM_PTR(o);
 }
diff --git a/py/objcomplex.c b/py/objcomplex.c
index 231ccf7689d9e5729b8f478953532d2973d8f92b..e9a15d254767d98043d917d961ddf7c9cfb936d9 100644
--- a/py/objcomplex.c
+++ b/py/objcomplex.c
@@ -47,7 +47,7 @@ typedef struct _mp_obj_complex_t {
 
 STATIC void complex_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
     (void)kind;
-    mp_obj_complex_t *o = o_in;
+    mp_obj_complex_t *o = MP_OBJ_TO_PTR(o_in);
 #if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
     char buf[16];
     const int precision = 7;
@@ -114,7 +114,7 @@ STATIC mp_obj_t complex_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n
 }
 
 STATIC mp_obj_t complex_unary_op(mp_uint_t op, mp_obj_t o_in) {
-    mp_obj_complex_t *o = o_in;
+    mp_obj_complex_t *o = MP_OBJ_TO_PTR(o_in);
     switch (op) {
         case MP_UNARY_OP_BOOL: return mp_obj_new_bool(o->real != 0 || o->imag != 0);
         case MP_UNARY_OP_POSITIVE: return o_in;
@@ -124,7 +124,7 @@ STATIC mp_obj_t complex_unary_op(mp_uint_t op, mp_obj_t o_in) {
 }
 
 STATIC mp_obj_t complex_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
-    mp_obj_complex_t *lhs = lhs_in;
+    mp_obj_complex_t *lhs = MP_OBJ_TO_PTR(lhs_in);
     return mp_obj_complex_binary_op(op, lhs->real, lhs->imag, rhs_in);
 }
 
@@ -133,7 +133,7 @@ STATIC void complex_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
         // not load attribute
         return;
     }
-    mp_obj_complex_t *self = self_in;
+    mp_obj_complex_t *self = MP_OBJ_TO_PTR(self_in);
     if (attr == MP_QSTR_real) {
         dest[0] = mp_obj_new_float(self->real);
     } else if (attr == MP_QSTR_imag) {
@@ -156,12 +156,12 @@ mp_obj_t mp_obj_new_complex(mp_float_t real, mp_float_t imag) {
     o->base.type = &mp_type_complex;
     o->real = real;
     o->imag = imag;
-    return o;
+    return MP_OBJ_FROM_PTR(o);
 }
 
 void mp_obj_complex_get(mp_obj_t self_in, mp_float_t *real, mp_float_t *imag) {
     assert(MP_OBJ_IS_TYPE(self_in, &mp_type_complex));
-    mp_obj_complex_t *self = self_in;
+    mp_obj_complex_t *self = MP_OBJ_TO_PTR(self_in);
     *real = self->real;
     *imag = self->imag;
 }
diff --git a/py/objdict.c b/py/objdict.c
index c07de78c05e77866e0a03bd641938e9a2d900576..43e1bfe6816236dd5ec9358eb5f9569087ec0521 100644
--- a/py/objdict.c
+++ b/py/objdict.c
@@ -34,7 +34,7 @@
 #include "py/builtin.h"
 #include "py/objtype.h"
 
-#define MP_OBJ_IS_DICT_TYPE(o) (MP_OBJ_IS_OBJ(o) && ((mp_obj_base_t*)o)->type->make_new == dict_make_new)
+#define MP_OBJ_IS_DICT_TYPE(o) (MP_OBJ_IS_OBJ(o) && ((mp_obj_base_t*)MP_OBJ_TO_PTR(o))->type->make_new == dict_make_new)
 
 STATIC mp_obj_t dict_update(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kwargs);
 
@@ -56,7 +56,7 @@ STATIC mp_map_elem_t *dict_iter_next(mp_obj_dict_t *dict, mp_uint_t *cur) {
 }
 
 STATIC void dict_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
-    mp_obj_dict_t *self = MP_OBJ_CAST(self_in);
+    mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in);
     bool first = true;
     if (!(MICROPY_PY_UJSON && kind == PRINT_JSON)) {
         kind = PRINT_REPR;
@@ -84,10 +84,10 @@ STATIC void dict_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_
 
 STATIC mp_obj_t dict_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
     mp_obj_t dict_out = mp_obj_new_dict(0);
-    mp_obj_dict_t *dict = MP_OBJ_CAST(dict_out);
-    dict->base.type = MP_OBJ_CAST(type_in);
+    mp_obj_dict_t *dict = MP_OBJ_TO_PTR(dict_out);
+    dict->base.type = MP_OBJ_TO_PTR(type_in);
     #if MICROPY_PY_COLLECTIONS_ORDEREDDICT
-    if (MP_OBJ_CAST(type_in) == &mp_type_ordereddict) {
+    if (MP_OBJ_TO_PTR(type_in) == &mp_type_ordereddict) {
         dict->map.is_ordered = 1;
     }
     #endif
@@ -101,7 +101,7 @@ STATIC mp_obj_t dict_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw
 }
 
 STATIC mp_obj_t dict_unary_op(mp_uint_t op, mp_obj_t self_in) {
-    mp_obj_dict_t *self = MP_OBJ_CAST(self_in);
+    mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in);
     switch (op) {
         case MP_UNARY_OP_BOOL: return mp_obj_new_bool(self->map.used != 0);
         case MP_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT(self->map.used);
@@ -110,7 +110,7 @@ STATIC mp_obj_t dict_unary_op(mp_uint_t op, mp_obj_t self_in) {
 }
 
 STATIC mp_obj_t dict_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
-    mp_obj_dict_t *o = MP_OBJ_CAST(lhs_in);
+    mp_obj_dict_t *o = MP_OBJ_TO_PTR(lhs_in);
     switch (op) {
         case MP_BINARY_OP_IN: {
             mp_map_elem_t *elem = mp_map_lookup(&o->map, rhs_in, MP_MAP_LOOKUP);
@@ -124,7 +124,7 @@ STATIC mp_obj_t dict_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
             } else
             #endif
             if (MP_OBJ_IS_TYPE(rhs_in, &mp_type_dict)) {
-                mp_obj_dict_t *rhs = MP_OBJ_CAST(rhs_in);
+                mp_obj_dict_t *rhs = MP_OBJ_TO_PTR(rhs_in);
                 if (o->map.used != rhs->map.used) {
                     return mp_const_false;
                 }
@@ -151,7 +151,7 @@ STATIC mp_obj_t dict_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
 
 // TODO: Make sure this is inlined in dict_subscr() below.
 mp_obj_t mp_obj_dict_get(mp_obj_t self_in, mp_obj_t index) {
-    mp_obj_dict_t *self = MP_OBJ_CAST(self_in);
+    mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in);
     mp_map_elem_t *elem = mp_map_lookup(&self->map, index, MP_MAP_LOOKUP);
     if (elem == NULL) {
         nlr_raise(mp_obj_new_exception_msg(&mp_type_KeyError, "<value>"));
@@ -167,7 +167,7 @@ STATIC mp_obj_t dict_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
         return mp_const_none;
     } else if (value == MP_OBJ_SENTINEL) {
         // load
-        mp_obj_dict_t *self = MP_OBJ_CAST(self_in);
+        mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in);
         mp_map_elem_t *elem = mp_map_lookup(&self->map, index, MP_MAP_LOOKUP);
         if (elem == NULL) {
             nlr_raise(mp_obj_new_exception_msg(&mp_type_KeyError, "<value>"));
@@ -191,8 +191,8 @@ typedef struct _mp_obj_dict_it_t {
 } mp_obj_dict_it_t;
 
 STATIC mp_obj_t dict_it_iternext(mp_obj_t self_in) {
-    mp_obj_dict_it_t *self = MP_OBJ_CAST(self_in);
-    mp_map_elem_t *next = dict_iter_next(MP_OBJ_CAST(self->dict), &self->cur);
+    mp_obj_dict_it_t *self = MP_OBJ_TO_PTR(self_in);
+    mp_map_elem_t *next = dict_iter_next(MP_OBJ_TO_PTR(self->dict), &self->cur);
 
     if (next == NULL) {
         return MP_OBJ_STOP_ITERATION;
@@ -209,12 +209,11 @@ STATIC const mp_obj_type_t mp_type_dict_it = {
 };
 
 STATIC mp_obj_t dict_getiter(mp_obj_t self_in) {
-    mp_obj_t o_out = m_new_obj(mp_obj_dict_it_t);
-    mp_obj_dict_it_t *o = MP_OBJ_CAST(o_out);
+    mp_obj_dict_it_t *o = m_new_obj(mp_obj_dict_it_t);
     o->base.type = &mp_type_dict_it;
     o->dict = self_in;
     o->cur = 0;
-    return o_out;
+    return MP_OBJ_FROM_PTR(o);
 }
 
 /******************************************************************************/
@@ -222,7 +221,7 @@ STATIC mp_obj_t dict_getiter(mp_obj_t self_in) {
 
 STATIC mp_obj_t dict_clear(mp_obj_t self_in) {
     assert(MP_OBJ_IS_DICT_TYPE(self_in));
-    mp_obj_dict_t *self = MP_OBJ_CAST(self_in);
+    mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in);
 
     mp_map_clear(&self->map);
 
@@ -232,9 +231,9 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(dict_clear_obj, dict_clear);
 
 STATIC mp_obj_t dict_copy(mp_obj_t self_in) {
     assert(MP_OBJ_IS_DICT_TYPE(self_in));
-    mp_obj_dict_t *self = MP_OBJ_CAST(self_in);
+    mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in);
     mp_obj_t other_out = mp_obj_new_dict(self->map.alloc);
-    mp_obj_dict_t *other = MP_OBJ_CAST(other_out);
+    mp_obj_dict_t *other = MP_OBJ_TO_PTR(other_out);
     other->base.type = self->base.type;
     other->map.used = self->map.used;
     other->map.all_keys_are_qstrs = self->map.all_keys_are_qstrs;
@@ -265,7 +264,7 @@ STATIC mp_obj_t dict_fromkeys(mp_uint_t n_args, const mp_obj_t *args) {
         self_out = mp_obj_new_dict(MP_OBJ_SMALL_INT_VALUE(len));
     }
 
-    mp_obj_dict_t *self = MP_OBJ_CAST(self_out);
+    mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_out);
     while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) {
         mp_map_lookup(&self->map, next, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value;
     }
@@ -303,8 +302,9 @@ STATIC mp_obj_t dict_get_helper(mp_map_t *self, mp_obj_t key, mp_obj_t deflt, mp
 STATIC mp_obj_t dict_get(mp_uint_t n_args, const mp_obj_t *args) {
     assert(2 <= n_args && n_args <= 3);
     assert(MP_OBJ_IS_DICT_TYPE(args[0]));
+    mp_obj_dict_t *self = MP_OBJ_TO_PTR(args[0]);
 
-    return dict_get_helper(&((mp_obj_dict_t *)args[0])->map,
+    return dict_get_helper(&self->map,
                            args[1],
                            n_args == 3 ? args[2] : MP_OBJ_NULL,
                            MP_MAP_LOOKUP);
@@ -314,8 +314,9 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(dict_get_obj, 2, 3, dict_get);
 STATIC mp_obj_t dict_pop(mp_uint_t n_args, const mp_obj_t *args) {
     assert(2 <= n_args && n_args <= 3);
     assert(MP_OBJ_IS_DICT_TYPE(args[0]));
+    mp_obj_dict_t *self = MP_OBJ_TO_PTR(args[0]);
 
-    return dict_get_helper(&((mp_obj_dict_t *)args[0])->map,
+    return dict_get_helper(&self->map,
                            args[1],
                            n_args == 3 ? args[2] : MP_OBJ_NULL,
                            MP_MAP_LOOKUP_REMOVE_IF_FOUND);
@@ -326,8 +327,9 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(dict_pop_obj, 2, 3, dict_pop);
 STATIC mp_obj_t dict_setdefault(mp_uint_t n_args, const mp_obj_t *args) {
     assert(2 <= n_args && n_args <= 3);
     assert(MP_OBJ_IS_DICT_TYPE(args[0]));
+    mp_obj_dict_t *self = MP_OBJ_TO_PTR(args[0]);
 
-    return dict_get_helper(&((mp_obj_dict_t *)args[0])->map,
+    return dict_get_helper(&self->map,
                            args[1],
                            n_args == 3 ? args[2] : MP_OBJ_NULL,
                            MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
@@ -337,7 +339,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(dict_setdefault_obj, 2, 3, dict_setde
 
 STATIC mp_obj_t dict_popitem(mp_obj_t self_in) {
     assert(MP_OBJ_IS_DICT_TYPE(self_in));
-    mp_obj_dict_t *self = MP_OBJ_CAST(self_in);
+    mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in);
     mp_uint_t cur = 0;
     mp_map_elem_t *next = dict_iter_next(self, &cur);
     if (next == NULL) {
@@ -355,7 +357,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(dict_popitem_obj, dict_popitem);
 
 STATIC mp_obj_t dict_update(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kwargs) {
     assert(MP_OBJ_IS_DICT_TYPE(args[0]));
-    mp_obj_dict_t *self = MP_OBJ_CAST(args[0]);
+    mp_obj_dict_t *self = MP_OBJ_TO_PTR(args[0]);
 
     mp_arg_check_num(n_args, kwargs->used, 1, 2, true);
 
@@ -367,7 +369,7 @@ STATIC mp_obj_t dict_update(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw
             if (args[1] != args[0]) {
                 mp_uint_t cur = 0;
                 mp_map_elem_t *elem = NULL;
-                while ((elem = dict_iter_next((mp_obj_dict_t*)args[1], &cur)) != NULL) {
+                while ((elem = dict_iter_next((mp_obj_dict_t*)MP_OBJ_TO_PTR(args[1]), &cur)) != NULL) {
                     mp_map_lookup(&self->map, elem->key, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = elem->value;
                 }
             }
@@ -434,8 +436,8 @@ typedef struct _mp_obj_dict_view_t {
 
 STATIC mp_obj_t dict_view_it_iternext(mp_obj_t self_in) {
     assert(MP_OBJ_IS_TYPE(self_in, &dict_view_it_type));
-    mp_obj_dict_view_it_t *self = MP_OBJ_CAST(self_in);
-    mp_map_elem_t *next = dict_iter_next(MP_OBJ_CAST(self->dict), &self->cur);
+    mp_obj_dict_view_it_t *self = MP_OBJ_TO_PTR(self_in);
+    mp_map_elem_t *next = dict_iter_next(MP_OBJ_TO_PTR(self->dict), &self->cur);
 
     if (next == NULL) {
         return MP_OBJ_STOP_ITERATION;
@@ -463,20 +465,19 @@ STATIC const mp_obj_type_t dict_view_it_type = {
 
 STATIC mp_obj_t dict_view_getiter(mp_obj_t view_in) {
     assert(MP_OBJ_IS_TYPE(view_in, &dict_view_type));
-    mp_obj_dict_view_t *view = MP_OBJ_CAST(view_in);
-    mp_obj_t o_out = m_new_obj(mp_obj_dict_view_it_t);
-    mp_obj_dict_view_it_t *o = MP_OBJ_CAST(o_out);
+    mp_obj_dict_view_t *view = MP_OBJ_TO_PTR(view_in);
+    mp_obj_dict_view_it_t *o = m_new_obj(mp_obj_dict_view_it_t);
     o->base.type = &dict_view_it_type;
     o->kind = view->kind;
     o->dict = view->dict;
     o->cur = 0;
-    return o_out;
+    return MP_OBJ_FROM_PTR(o);
 }
 
 STATIC void dict_view_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
     (void)kind;
     assert(MP_OBJ_IS_TYPE(self_in, &dict_view_type));
-    mp_obj_dict_view_t *self = MP_OBJ_CAST(self_in);
+    mp_obj_dict_view_t *self = MP_OBJ_TO_PTR(self_in);
     bool first = true;
     mp_print_str(print, mp_dict_view_names[self->kind]);
     mp_print_str(print, "([");
@@ -494,7 +495,7 @@ STATIC void dict_view_print(const mp_print_t *print, mp_obj_t self_in, mp_print_
 
 STATIC mp_obj_t dict_view_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
     // only supported for the 'keys' kind until sets and dicts are refactored
-    mp_obj_dict_view_t *o = MP_OBJ_CAST(lhs_in);
+    mp_obj_dict_view_t *o = MP_OBJ_TO_PTR(lhs_in);
     if (o->kind != MP_DICT_VIEW_KEYS) {
         return MP_OBJ_NULL; // op not supported
     }
@@ -513,12 +514,11 @@ STATIC const mp_obj_type_t dict_view_type = {
 };
 
 STATIC mp_obj_t mp_obj_new_dict_view(mp_obj_t dict, mp_dict_view_kind_t kind) {
-    mp_obj_t o_out = m_new_obj(mp_obj_dict_view_t);
-    mp_obj_dict_view_t *o = MP_OBJ_CAST(o_out);
+    mp_obj_dict_view_t *o = m_new_obj(mp_obj_dict_view_t);
     o->base.type = &dict_view_type;
     o->dict = dict;
     o->kind = kind;
-    return o_out;
+    return MP_OBJ_FROM_PTR(o);
 }
 
 STATIC mp_obj_t dict_view(mp_obj_t self_in, mp_dict_view_kind_t kind) {
@@ -572,7 +572,7 @@ const mp_obj_type_t mp_type_dict = {
     .binary_op = dict_binary_op,
     .subscr = dict_subscr,
     .getiter = dict_getiter,
-    .locals_dict = (mp_obj_t)&dict_locals_dict,
+    .locals_dict = (mp_obj_dict_t*)&dict_locals_dict,
 };
 
 #if MICROPY_PY_COLLECTIONS_ORDEREDDICT
@@ -587,8 +587,8 @@ const mp_obj_type_t mp_type_ordereddict = {
     .binary_op = dict_binary_op,
     .subscr = dict_subscr,
     .getiter = dict_getiter,
-    .bases_tuple = (mp_obj_t)&ordereddict_base_tuple,
-    .locals_dict = (mp_obj_t)&dict_locals_dict,
+    .bases_tuple = (mp_obj_tuple_t*)(mp_rom_obj_tuple_t*)&ordereddict_base_tuple,
+    .locals_dict = (mp_obj_dict_t*)&dict_locals_dict,
 };
 #endif
 
@@ -598,33 +598,32 @@ void mp_obj_dict_init(mp_obj_dict_t *dict, mp_uint_t n_args) {
 }
 
 mp_obj_t mp_obj_new_dict(mp_uint_t n_args) {
-    mp_obj_t o_out = m_new_obj(mp_obj_dict_t);
-    mp_obj_dict_t *o = MP_OBJ_CAST(o_out);
+    mp_obj_dict_t *o = m_new_obj(mp_obj_dict_t);
     mp_obj_dict_init(o, n_args);
-    return o_out;
+    return MP_OBJ_FROM_PTR(o);
 }
 
 mp_uint_t mp_obj_dict_len(mp_obj_t self_in) {
-    mp_obj_dict_t *self = MP_OBJ_CAST(self_in);
+    mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in);
     return self->map.used;
 }
 
 mp_obj_t mp_obj_dict_store(mp_obj_t self_in, mp_obj_t key, mp_obj_t value) {
     assert(MP_OBJ_IS_DICT_TYPE(self_in));
-    mp_obj_dict_t *self = MP_OBJ_CAST(self_in);
+    mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in);
     mp_map_lookup(&self->map, key, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value;
     return self_in;
 }
 
 mp_obj_t mp_obj_dict_delete(mp_obj_t self_in, mp_obj_t key) {
     assert(MP_OBJ_IS_DICT_TYPE(self_in));
-    mp_obj_dict_t *self = MP_OBJ_CAST(self_in);
+    mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in);
     dict_get_helper(&self->map, key, MP_OBJ_NULL, MP_MAP_LOOKUP_REMOVE_IF_FOUND);
     return self_in;
 }
 
 mp_map_t *mp_obj_dict_get_map(mp_obj_t self_in) {
     assert(MP_OBJ_IS_DICT_TYPE(self_in));
-    mp_obj_dict_t *self = MP_OBJ_CAST(self_in);
+    mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in);
     return &self->map;
 }
diff --git a/py/objenumerate.c b/py/objenumerate.c
index 9cdd4fda5da8bc2c66eb93e735580306e8ae41e2..3629c1a20bb5227e9dba7ade69a7e98f5c74dbdf 100644
--- a/py/objenumerate.c
+++ b/py/objenumerate.c
@@ -53,7 +53,7 @@ STATIC mp_obj_t enumerate_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t
 
     // create enumerate object
     mp_obj_enumerate_t *o = m_new_obj(mp_obj_enumerate_t);
-    o->base.type = type_in;
+    o->base.type = MP_OBJ_TO_PTR(type_in);
     o->iter = mp_getiter(vals[0].u_obj);
     o->cur = vals[1].u_int;
 #else
@@ -64,7 +64,7 @@ STATIC mp_obj_t enumerate_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t
     o->cur = n_args > 1 ? mp_obj_get_int(args[1]) : 0;
 #endif
 
-    return o;
+    return MP_OBJ_FROM_PTR(o);
 }
 
 const mp_obj_type_t mp_type_enumerate = {
@@ -77,7 +77,7 @@ const mp_obj_type_t mp_type_enumerate = {
 
 STATIC mp_obj_t enumerate_iternext(mp_obj_t self_in) {
     assert(MP_OBJ_IS_TYPE(self_in, &mp_type_enumerate));
-    mp_obj_enumerate_t *self = self_in;
+    mp_obj_enumerate_t *self = MP_OBJ_TO_PTR(self_in);
     mp_obj_t next = mp_iternext(self->iter);
     if (next == MP_OBJ_STOP_ITERATION) {
         return MP_OBJ_STOP_ITERATION;
diff --git a/py/objexcept.c b/py/objexcept.c
index 2e0ad6ed265f4c4ce438d5d5791bcd8e3f674563..da31dddf7952f2e66cc4cddd0d39cd34a7dd170b 100644
--- a/py/objexcept.c
+++ b/py/objexcept.c
@@ -38,7 +38,7 @@
 #include "py/gc.h"
 
 // Instance of MemoryError exception - needed by mp_malloc_fail
-const mp_obj_exception_t mp_const_MemoryError_obj = {{&mp_type_MemoryError}, 0, 0, MP_OBJ_NULL, mp_const_empty_tuple};
+const mp_obj_exception_t mp_const_MemoryError_obj = {{&mp_type_MemoryError}, 0, 0, NULL, (mp_obj_tuple_t*)&mp_const_empty_tuple_obj};
 
 // Optionally allocated buffer for storing the first argument of an exception
 // allocated when the heap is locked.
@@ -88,10 +88,10 @@ mp_obj_t mp_alloc_emergency_exception_buf(mp_obj_t size_in) {
 // Instance of GeneratorExit exception - needed by generator.close()
 // This would belong to objgenerator.c, but to keep mp_obj_exception_t
 // definition module-private so far, have it here.
-const mp_obj_exception_t mp_const_GeneratorExit_obj = {{&mp_type_GeneratorExit}, 0, 0, MP_OBJ_NULL, mp_const_empty_tuple};
+const mp_obj_exception_t mp_const_GeneratorExit_obj = {{&mp_type_GeneratorExit}, 0, 0, NULL, (mp_obj_tuple_t*)&mp_const_empty_tuple_obj};
 
 STATIC void mp_obj_exception_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
-    mp_obj_exception_t *o = o_in;
+    mp_obj_exception_t *o = MP_OBJ_TO_PTR(o_in);
     mp_print_kind_t k = kind & ~PRINT_EXC_SUBCLASS;
     bool is_subclass = kind & PRINT_EXC_SUBCLASS;
     if (!is_subclass && (k == PRINT_REPR || k == PRINT_EXC)) {
@@ -111,7 +111,7 @@ STATIC void mp_obj_exception_print(const mp_print_t *print, mp_obj_t o_in, mp_pr
             return;
         }
     }
-    mp_obj_tuple_print(print, o->args, kind);
+    mp_obj_tuple_print(print, MP_OBJ_FROM_PTR(o->args), kind);
 }
 
 mp_obj_t mp_obj_exception_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
@@ -121,18 +121,18 @@ mp_obj_t mp_obj_exception_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t
         // Couldn't allocate heap memory; use local data instead.
         o = &MP_STATE_VM(mp_emergency_exception_obj);
         // We can't store any args.
-        o->args = mp_const_empty_tuple;
+        o->args = (mp_obj_tuple_t*)&mp_const_empty_tuple_obj;
     } else {
-        o->args = mp_obj_new_tuple(n_args, args);
+        o->args = MP_OBJ_TO_PTR(mp_obj_new_tuple(n_args, args));
     }
-    o->base.type = type_in;
+    o->base.type = MP_OBJ_TO_PTR(type_in);
     o->traceback_data = NULL;
-    return o;
+    return MP_OBJ_FROM_PTR(o);
 }
 
 // Get exception "value" - that is, first argument, or None
 mp_obj_t mp_obj_exception_get_value(mp_obj_t self_in) {
-    mp_obj_exception_t *self = self_in;
+    mp_obj_exception_t *self = MP_OBJ_TO_PTR(self_in);
     if (self->args->len == 0) {
         return mp_const_none;
     } else {
@@ -145,18 +145,18 @@ STATIC void exception_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
         // not load attribute
         return;
     }
-    mp_obj_exception_t *self = self_in;
+    mp_obj_exception_t *self = MP_OBJ_TO_PTR(self_in);
     if (attr == MP_QSTR_args) {
-        dest[0] = self->args;
+        dest[0] = MP_OBJ_FROM_PTR(self->args);
     } else if (self->base.type == &mp_type_StopIteration && attr == MP_QSTR_value) {
-        dest[0] = mp_obj_exception_get_value(self);
+        dest[0] = mp_obj_exception_get_value(self_in);
     }
 }
 
 STATIC mp_obj_t exc___init__(mp_uint_t n_args, const mp_obj_t *args) {
-    mp_obj_exception_t *self = args[0];
+    mp_obj_exception_t *self = MP_OBJ_TO_PTR(args[0]);
     mp_obj_t argst = mp_obj_new_tuple(n_args - 1, args + 1);
-    self->args = argst;
+    self->args = MP_OBJ_TO_PTR(argst);
     return mp_const_none;
 }
 STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(exc___init___obj, 1, MP_OBJ_FUN_ARGS_MAX, exc___init__);
@@ -173,7 +173,7 @@ const mp_obj_type_t mp_type_BaseException = {
     .print = mp_obj_exception_print,
     .make_new = mp_obj_exception_make_new,
     .attr = exception_attr,
-    .locals_dict = (mp_obj_t)&exc_locals_dict,
+    .locals_dict = (mp_obj_dict_t*)&exc_locals_dict,
 };
 
 #define MP_DEFINE_EXCEPTION_BASE(base_name) \
@@ -186,7 +186,7 @@ const mp_obj_type_t mp_type_ ## exc_name = { \
     .print = mp_obj_exception_print, \
     .make_new = mp_obj_exception_make_new, \
     .attr = exception_attr, \
-    .bases_tuple = (mp_obj_t)&mp_type_ ## base_name ## _base_tuple, \
+    .bases_tuple = (mp_obj_tuple_t*)(mp_rom_obj_tuple_t*)&mp_type_ ## base_name ## _base_tuple, \
 };
 
 // List of all exceptions, arranged as in the table at:
@@ -290,7 +290,7 @@ mp_obj_t mp_obj_new_exception_arg1(const mp_obj_type_t *exc_type, mp_obj_t arg)
 
 mp_obj_t mp_obj_new_exception_args(const mp_obj_type_t *exc_type, mp_uint_t n_args, const mp_obj_t *args) {
     assert(exc_type->make_new == mp_obj_exception_make_new);
-    return exc_type->make_new((mp_obj_t)exc_type, n_args, 0, args);
+    return exc_type->make_new(MP_OBJ_FROM_PTR(exc_type), n_args, 0, args);
 }
 
 mp_obj_t mp_obj_new_exception_msg(const mp_obj_type_t *exc_type, const char *msg) {
@@ -309,7 +309,7 @@ mp_obj_t mp_obj_new_exception_msg_varg(const mp_obj_type_t *exc_type, const char
         o = &MP_STATE_VM(mp_emergency_exception_obj);
         o->base.type = exc_type;
         o->traceback_data = NULL;
-        o->args = mp_const_empty_tuple;
+        o->args = (mp_obj_tuple_t*)&mp_const_empty_tuple_obj;
 
 #if MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF
         // If the user has provided a buffer, then we try to create a tuple
@@ -321,7 +321,7 @@ mp_obj_t mp_obj_new_exception_msg_varg(const mp_obj_type_t *exc_type, const char
 
             tuple->base.type = &mp_type_tuple;
             tuple->len = 1;
-            tuple->items[0] = str;
+            tuple->items[0] = MP_OBJ_FROM_PTR(str);
 
             byte *str_data = (byte *)&str[1];
             uint max_len = MP_STATE_VM(mp_emergency_exception_buf) + mp_emergency_exception_buf_size
@@ -357,7 +357,7 @@ mp_obj_t mp_obj_new_exception_msg_varg(const mp_obj_type_t *exc_type, const char
     } else {
         o->base.type = exc_type;
         o->traceback_data = NULL;
-        o->args = mp_obj_new_tuple(1, NULL);
+        o->args = MP_OBJ_TO_PTR(mp_obj_new_tuple(1, NULL));
 
         if (fmt == NULL) {
             // no message
@@ -379,24 +379,24 @@ mp_obj_t mp_obj_new_exception_msg_varg(const mp_obj_type_t *exc_type, const char
         }
     }
 
-    return o;
+    return MP_OBJ_FROM_PTR(o);
 }
 
 // return true if the given object is an exception type
 bool mp_obj_is_exception_type(mp_obj_t self_in) {
     if (MP_OBJ_IS_TYPE(self_in, &mp_type_type)) {
         // optimisation when self_in is a builtin exception
-        mp_obj_type_t *self = self_in;
+        mp_obj_type_t *self = MP_OBJ_TO_PTR(self_in);
         if (self->make_new == mp_obj_exception_make_new) {
             return true;
         }
     }
-    return mp_obj_is_subclass_fast(self_in, &mp_type_BaseException);
+    return mp_obj_is_subclass_fast(self_in, MP_OBJ_FROM_PTR(&mp_type_BaseException));
 }
 
 // return true if the given object is an instance of an exception type
 bool mp_obj_is_exception_instance(mp_obj_t self_in) {
-    return mp_obj_is_exception_type(mp_obj_get_type(self_in));
+    return mp_obj_is_exception_type(MP_OBJ_FROM_PTR(mp_obj_get_type(self_in)));
 }
 
 // Return true if exception (type or instance) is a subclass of given
@@ -405,7 +405,7 @@ bool mp_obj_is_exception_instance(mp_obj_t self_in) {
 bool mp_obj_exception_match(mp_obj_t exc, mp_const_obj_t exc_type) {
     // if exc is an instance of an exception, then extract and use its type
     if (mp_obj_is_exception_instance(exc)) {
-        exc = mp_obj_get_type(exc);
+        exc = MP_OBJ_FROM_PTR(mp_obj_get_type(exc));
     }
     return mp_obj_is_subclass_fast(exc, exc_type);
 }
@@ -417,9 +417,9 @@ bool mp_obj_exception_match(mp_obj_t exc, mp_const_obj_t exc_type) {
     assert(mp_obj_is_exception_instance(self_in)); \
     mp_obj_exception_t *self; \
     if (mp_obj_is_native_exception_instance(self_in)) { \
-        self = self_in; \
+        self = MP_OBJ_TO_PTR(self_in); \
     } else { \
-        self = ((mp_obj_instance_t*)self_in)->subobj[0]; \
+        self = MP_OBJ_TO_PTR(((mp_obj_instance_t*)MP_OBJ_TO_PTR(self_in))->subobj[0]); \
     }
 
 void mp_obj_exception_clear_traceback(mp_obj_t self_in) {
diff --git a/py/objfilter.c b/py/objfilter.c
index 9ed37f5986ce8998ca3e7958b0a3489f345103e6..cc3083c96ca33a87c5376d675714b5d8bccf46f4 100644
--- a/py/objfilter.c
+++ b/py/objfilter.c
@@ -37,15 +37,15 @@ typedef struct _mp_obj_filter_t {
 STATIC mp_obj_t filter_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
     mp_arg_check_num(n_args, n_kw, 2, 2, false);
     mp_obj_filter_t *o = m_new_obj(mp_obj_filter_t);
-    o->base.type = type_in;
+    o->base.type = MP_OBJ_TO_PTR(type_in);
     o->fun = args[0];
     o->iter = mp_getiter(args[1]);
-    return o;
+    return MP_OBJ_FROM_PTR(o);
 }
 
 STATIC mp_obj_t filter_iternext(mp_obj_t self_in) {
     assert(MP_OBJ_IS_TYPE(self_in, &mp_type_filter));
-    mp_obj_filter_t *self = self_in;
+    mp_obj_filter_t *self = MP_OBJ_TO_PTR(self_in);
     mp_obj_t next;
     while ((next = mp_iternext(self->iter)) != MP_OBJ_STOP_ITERATION) {
         mp_obj_t val;
diff --git a/py/objfloat.c b/py/objfloat.c
index 81eac99bd19cf2ee428f75b814aedda83fe7672a..c9e3ddd3761aa4b22754c88eb75fd1a63c4a2605 100644
--- a/py/objfloat.c
+++ b/py/objfloat.c
@@ -131,12 +131,12 @@ mp_obj_t mp_obj_new_float(mp_float_t value) {
     mp_obj_float_t *o = m_new(mp_obj_float_t, 1);
     o->base.type = &mp_type_float;
     o->value = value;
-    return (mp_obj_t)o;
+    return MP_OBJ_FROM_PTR(o);
 }
 
 mp_float_t mp_obj_float_get(mp_obj_t self_in) {
     assert(mp_obj_is_float(self_in));
-    mp_obj_float_t *self = self_in;
+    mp_obj_float_t *self = MP_OBJ_TO_PTR(self_in);
     return self->value;
 }
 
diff --git a/py/objfun.c b/py/objfun.c
index 86dbe32e7f9bcbcd06aa27aea35b3183dbb59cdf..88e84ce9fcef5ef6f8f297744706075d83263a07 100644
--- a/py/objfun.c
+++ b/py/objfun.c
@@ -54,7 +54,7 @@
 
 STATIC mp_obj_t fun_builtin_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
     assert(MP_OBJ_IS_TYPE(self_in, &mp_type_fun_builtin));
-    mp_obj_fun_builtin_t *self = self_in;
+    mp_obj_fun_builtin_t *self = MP_OBJ_TO_PTR(self_in);
 
     // check number of arguments
     mp_arg_check_num(n_args, n_kw, self->n_args_min, self->n_args_max, self->is_kw);
@@ -118,7 +118,7 @@ STATIC const mp_obj_type_t mp_type_fun_native;
 #endif
 
 qstr mp_obj_fun_get_name(mp_const_obj_t fun_in) {
-    const mp_obj_fun_bc_t *fun = fun_in;
+    const mp_obj_fun_bc_t *fun = MP_OBJ_TO_PTR(fun_in);
     #if MICROPY_EMIT_NATIVE
     if (fun->base.type == &mp_type_fun_native) {
         // TODO native functions don't have name stored
@@ -139,8 +139,8 @@ qstr mp_obj_fun_get_name(mp_const_obj_t fun_in) {
 #if MICROPY_CPYTHON_COMPAT
 STATIC void fun_bc_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
     (void)kind;
-    mp_obj_fun_bc_t *o = o_in;
-    mp_printf(print, "<function %q at 0x%x>", mp_obj_fun_get_name(o), o);
+    mp_obj_fun_bc_t *o = MP_OBJ_TO_PTR(o_in);
+    mp_printf(print, "<function %q at 0x%p>", mp_obj_fun_get_name(o_in), o);
 }
 #endif
 
@@ -204,7 +204,7 @@ STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw,
     dump_args(args, n_args);
     DEBUG_printf("Input kw args: ");
     dump_args(args + n_args, n_kw * 2);
-    mp_obj_fun_bc_t *self = self_in;
+    mp_obj_fun_bc_t *self = MP_OBJ_TO_PTR(self_in);
     DEBUG_printf("Func n_def_args: %d\n", self->n_def_args);
 
     // get start of bytecode
@@ -325,9 +325,9 @@ const mp_obj_type_t mp_type_fun_bc = {
 mp_obj_t mp_obj_new_fun_bc(mp_obj_t def_args_in, mp_obj_t def_kw_args, const byte *code, const mp_uint_t *const_table) {
     mp_uint_t n_def_args = 0;
     mp_uint_t n_extra_args = 0;
-    mp_obj_tuple_t *def_args = def_args_in;
-    if (def_args != MP_OBJ_NULL) {
-        assert(MP_OBJ_IS_TYPE(def_args, &mp_type_tuple));
+    mp_obj_tuple_t *def_args = MP_OBJ_TO_PTR(def_args_in);
+    if (def_args_in != MP_OBJ_NULL) {
+        assert(MP_OBJ_IS_TYPE(def_args_in, &mp_type_tuple));
         n_def_args = def_args->len;
         n_extra_args = def_args->len;
     }
@@ -339,13 +339,13 @@ mp_obj_t mp_obj_new_fun_bc(mp_obj_t def_args_in, mp_obj_t def_kw_args, const byt
     o->globals = mp_globals_get();
     o->bytecode = code;
     o->const_table = const_table;
-    if (def_args != MP_OBJ_NULL) {
+    if (def_args != NULL) {
         memcpy(o->extra_args, def_args->items, n_def_args * sizeof(mp_obj_t));
     }
     if (def_kw_args != MP_OBJ_NULL) {
         o->extra_args[n_def_args] = def_kw_args;
     }
-    return o;
+    return MP_OBJ_FROM_PTR(o);
 }
 
 /******************************************************************************/
diff --git a/py/objgenerator.c b/py/objgenerator.c
index 25c31a59405192705bc7c3e95b012df28ea1b1e8..0a684856289e9f5b2b07d67643bd9bfa9a536ea5 100644
--- a/py/objgenerator.c
+++ b/py/objgenerator.c
@@ -50,9 +50,9 @@ typedef struct _mp_obj_gen_instance_t {
 } mp_obj_gen_instance_t;
 
 STATIC mp_obj_t gen_wrap_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
-    mp_obj_gen_wrap_t *self = self_in;
+    mp_obj_gen_wrap_t *self = MP_OBJ_TO_PTR(self_in);
     mp_obj_fun_bc_t *self_fun = (mp_obj_fun_bc_t*)self->fun;
-    assert(MP_OBJ_IS_TYPE(self_fun, &mp_type_fun_bc));
+    assert(self_fun->base.type == &mp_type_fun_bc);
 
     // get start of bytecode
     const byte *ip = self_fun->bytecode;
@@ -70,7 +70,7 @@ STATIC mp_obj_t gen_wrap_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw
     o->code_state.n_state = n_state;
     o->code_state.ip = (byte*)(ip - self_fun->bytecode); // offset to prelude
     mp_setup_code_state(&o->code_state, self_fun, n_args, n_kw, args);
-    return o;
+    return MP_OBJ_FROM_PTR(o);
 }
 
 const mp_obj_type_t mp_type_gen_wrap = {
@@ -82,8 +82,8 @@ const mp_obj_type_t mp_type_gen_wrap = {
 mp_obj_t mp_obj_new_gen_wrap(mp_obj_t fun) {
     mp_obj_gen_wrap_t *o = m_new_obj(mp_obj_gen_wrap_t);
     o->base.type = &mp_type_gen_wrap;
-    o->fun = fun;
-    return o;
+    o->fun = MP_OBJ_TO_PTR(fun);
+    return MP_OBJ_FROM_PTR(o);
 }
 
 /******************************************************************************/
@@ -91,13 +91,13 @@ mp_obj_t mp_obj_new_gen_wrap(mp_obj_t fun) {
 
 STATIC void gen_instance_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
     (void)kind;
-    mp_obj_gen_instance_t *self = self_in;
-    mp_printf(print, "<generator object '%q' at %p>", mp_obj_code_get_name(self->code_state.code_info), self_in);
+    mp_obj_gen_instance_t *self = MP_OBJ_TO_PTR(self_in);
+    mp_printf(print, "<generator object '%q' at %p>", mp_obj_code_get_name(self->code_state.code_info), self);
 }
 
 mp_vm_return_kind_t mp_obj_gen_resume(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t throw_value, mp_obj_t *ret_val) {
     assert(MP_OBJ_IS_TYPE(self_in, &mp_type_gen_instance));
-    mp_obj_gen_instance_t *self = self_in;
+    mp_obj_gen_instance_t *self = MP_OBJ_TO_PTR(self_in);
     if (self->code_state.ip == 0) {
         *ret_val = MP_OBJ_STOP_ITERATION;
         return MP_VM_RETURN_NORMAL;
@@ -155,7 +155,7 @@ STATIC mp_obj_t gen_resume_and_raise(mp_obj_t self_in, mp_obj_t send_value, mp_o
             }
 
         case MP_VM_RETURN_YIELD:
-            if (throw_value != MP_OBJ_NULL && mp_obj_is_subclass_fast(mp_obj_get_type(throw_value), &mp_type_GeneratorExit)) {
+            if (throw_value != MP_OBJ_NULL && mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(mp_obj_get_type(throw_value)), MP_OBJ_FROM_PTR(&mp_type_GeneratorExit))) {
                 nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "generator ignored GeneratorExit"));
             }
             return ret;
@@ -164,7 +164,7 @@ STATIC mp_obj_t gen_resume_and_raise(mp_obj_t self_in, mp_obj_t send_value, mp_o
             // TODO: Optimization of returning MP_OBJ_STOP_ITERATION is really part
             // of mp_iternext() protocol, but this function is called by other methods
             // too, which may not handled MP_OBJ_STOP_ITERATION.
-            if (mp_obj_is_subclass_fast(mp_obj_get_type(ret), &mp_type_StopIteration)) {
+            if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(mp_obj_get_type(ret)), MP_OBJ_FROM_PTR(&mp_type_StopIteration))) {
                 mp_obj_t val = mp_obj_exception_get_value(ret);
                 if (val == mp_const_none) {
                     return MP_OBJ_STOP_ITERATION;
@@ -206,15 +206,15 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(gen_instance_throw_obj, 2, 4, gen_ins
 
 STATIC mp_obj_t gen_instance_close(mp_obj_t self_in) {
     mp_obj_t ret;
-    switch (mp_obj_gen_resume(self_in, mp_const_none, (mp_obj_t)&mp_const_GeneratorExit_obj, &ret)) {
+    switch (mp_obj_gen_resume(self_in, mp_const_none, MP_OBJ_FROM_PTR(&mp_const_GeneratorExit_obj), &ret)) {
         case MP_VM_RETURN_YIELD:
             nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "generator ignored GeneratorExit"));
 
         // Swallow StopIteration & GeneratorExit (== successful close), and re-raise any other
         case MP_VM_RETURN_EXCEPTION:
             // ret should always be an instance of an exception class
-            if (mp_obj_is_subclass_fast(mp_obj_get_type(ret), &mp_type_GeneratorExit) ||
-                mp_obj_is_subclass_fast(mp_obj_get_type(ret), &mp_type_StopIteration)) {
+            if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(mp_obj_get_type(ret)), MP_OBJ_FROM_PTR(&mp_type_GeneratorExit)) ||
+                mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(mp_obj_get_type(ret)), MP_OBJ_FROM_PTR(&mp_type_StopIteration))) {
                 return mp_const_none;
             }
             nlr_raise(ret);
@@ -241,5 +241,5 @@ const mp_obj_type_t mp_type_gen_instance = {
     .print = gen_instance_print,
     .getiter = mp_identity,
     .iternext = gen_instance_iternext,
-    .locals_dict = (mp_obj_t)&gen_instance_locals_dict,
+    .locals_dict = (mp_obj_dict_t*)&gen_instance_locals_dict,
 };
diff --git a/py/objgetitemiter.c b/py/objgetitemiter.c
index ae98db8c7b6d894d482395b1dbff68eef6579002..b0e23e6d32b19b6e7faaeb240b54558bc97627fb 100644
--- a/py/objgetitemiter.c
+++ b/py/objgetitemiter.c
@@ -37,7 +37,7 @@ typedef struct _mp_obj_getitem_iter_t {
 } mp_obj_getitem_iter_t;
 
 STATIC mp_obj_t it_iternext(mp_obj_t self_in) {
-    mp_obj_getitem_iter_t *self = self_in;
+    mp_obj_getitem_iter_t *self = MP_OBJ_TO_PTR(self_in);
     nlr_buf_t nlr;
     if (nlr_push(&nlr) == 0) {
         // try to get next item
@@ -47,13 +47,13 @@ STATIC mp_obj_t it_iternext(mp_obj_t self_in) {
         return value;
     } else {
         // an exception was raised
-        mp_obj_type_t *t = mp_obj_get_type(nlr.ret_val);
+        mp_obj_type_t *t = (mp_obj_type_t*)((mp_obj_base_t*)nlr.ret_val)->type;
         if (t == &mp_type_StopIteration || t == &mp_type_IndexError) {
             // return MP_OBJ_STOP_ITERATION instead of raising
             return MP_OBJ_STOP_ITERATION;
         } else {
             // re-raise exception
-            nlr_raise(nlr.ret_val);
+            nlr_jump(nlr.ret_val);
         }
     }
 }
@@ -72,5 +72,5 @@ mp_obj_t mp_obj_new_getitem_iter(mp_obj_t *args) {
     o->args[0] = args[0];
     o->args[1] = args[1];
     o->args[2] = MP_OBJ_NEW_SMALL_INT(0);
-    return o;
+    return MP_OBJ_FROM_PTR(o);
 }
diff --git a/py/objint.c b/py/objint.c
index 8e9325960f32b8bad86e35e9f099113292b4a7b2..f3d699c45ee93dd3212a43c7c7450fa9b68d20c6 100644
--- a/py/objint.c
+++ b/py/objint.c
@@ -434,5 +434,5 @@ const mp_obj_type_t mp_type_int = {
     .make_new = mp_obj_int_make_new,
     .unary_op = mp_obj_int_unary_op,
     .binary_op = mp_obj_int_binary_op,
-    .locals_dict = (mp_obj_t)&int_locals_dict,
+    .locals_dict = (mp_obj_dict_t*)&int_locals_dict,
 };
diff --git a/py/objint_mpz.c b/py/objint_mpz.c
index 18e698fa2b52797ccc8fc9388deee01da042fd53..385bbc5e3fe0407e2b4920d813f95deeb32aaa5c 100644
--- a/py/objint_mpz.c
+++ b/py/objint_mpz.c
@@ -93,7 +93,7 @@ STATIC mp_obj_int_t *mp_obj_int_new_mpz(void) {
 char *mp_obj_int_formatted_impl(char **buf, mp_uint_t *buf_size, mp_uint_t *fmt_size, mp_const_obj_t self_in,
                                 int base, const char *prefix, char base_char, char comma) {
     assert(MP_OBJ_IS_TYPE(self_in, &mp_type_int));
-    const mp_obj_int_t *self = self_in;
+    const mp_obj_int_t *self = MP_OBJ_TO_PTR(self_in);
 
     mp_uint_t needed_size = mpz_as_str_size(&self->mpz, base, prefix, comma);
     if (needed_size > *buf_size) {
@@ -109,7 +109,7 @@ char *mp_obj_int_formatted_impl(char **buf, mp_uint_t *buf_size, mp_uint_t *fmt_
 
 void mp_obj_int_to_bytes_impl(mp_obj_t self_in, bool big_endian, mp_uint_t len, byte *buf) {
     assert(MP_OBJ_IS_TYPE(self_in, &mp_type_int));
-    mp_obj_int_t *self = self_in;
+    mp_obj_int_t *self = MP_OBJ_TO_PTR(self_in);
     mpz_as_bytes(&self->mpz, big_endian, len, buf);
 }
 
@@ -117,7 +117,7 @@ bool mp_obj_int_is_positive(mp_obj_t self_in) {
     if (MP_OBJ_IS_SMALL_INT(self_in)) {
         return MP_OBJ_SMALL_INT_VALUE(self_in) >= 0;
     }
-    mp_obj_int_t *self = self_in;
+    mp_obj_int_t *self = MP_OBJ_TO_PTR(self_in);
     return !self->mpz.neg;
 }
 
@@ -125,10 +125,10 @@ bool mp_obj_int_is_positive(mp_obj_t self_in) {
 // TypeError if the argument is not integral
 mp_obj_t mp_obj_int_abs(mp_obj_t self_in) {
     if (MP_OBJ_IS_TYPE(self_in, &mp_type_int)) {
-        mp_obj_int_t *self = self_in;
+        mp_obj_int_t *self = MP_OBJ_TO_PTR(self_in);
         mp_obj_int_t *self2 = mp_obj_int_new_mpz();
         mpz_abs_inpl(&self2->mpz, &self->mpz);
-        return self2;
+        return MP_OBJ_FROM_PTR(self2);
     } else {
         mp_int_t val = mp_obj_get_int(self_in);
         if (val == MP_SMALL_INT_MIN) {
@@ -143,13 +143,13 @@ mp_obj_t mp_obj_int_abs(mp_obj_t self_in) {
 }
 
 mp_obj_t mp_obj_int_unary_op(mp_uint_t op, mp_obj_t o_in) {
-    mp_obj_int_t *o = o_in;
+    mp_obj_int_t *o = MP_OBJ_TO_PTR(o_in);
     switch (op) {
         case MP_UNARY_OP_BOOL: return mp_obj_new_bool(!mpz_is_zero(&o->mpz));
         case MP_UNARY_OP_HASH: return MP_OBJ_NEW_SMALL_INT(mpz_hash(&o->mpz));
         case MP_UNARY_OP_POSITIVE: return o_in;
-        case MP_UNARY_OP_NEGATIVE: { mp_obj_int_t *o2 = mp_obj_int_new_mpz(); mpz_neg_inpl(&o2->mpz, &o->mpz); return o2; }
-        case MP_UNARY_OP_INVERT: { mp_obj_int_t *o2 = mp_obj_int_new_mpz(); mpz_not_inpl(&o2->mpz, &o->mpz); return o2; }
+        case MP_UNARY_OP_NEGATIVE: { mp_obj_int_t *o2 = mp_obj_int_new_mpz(); mpz_neg_inpl(&o2->mpz, &o->mpz); return MP_OBJ_FROM_PTR(o2); }
+        case MP_UNARY_OP_INVERT: { mp_obj_int_t *o2 = mp_obj_int_new_mpz(); mpz_not_inpl(&o2->mpz, &o->mpz); return MP_OBJ_FROM_PTR(o2); }
         default: return MP_OBJ_NULL; // op not supported
     }
 }
@@ -165,7 +165,7 @@ mp_obj_t mp_obj_int_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
         mpz_init_fixed_from_int(&z_int, z_int_dig, MPZ_NUM_DIG_FOR_INT, MP_OBJ_SMALL_INT_VALUE(lhs_in));
         zlhs = &z_int;
     } else if (MP_OBJ_IS_TYPE(lhs_in, &mp_type_int)) {
-        zlhs = &((mp_obj_int_t*)lhs_in)->mpz;
+        zlhs = &((mp_obj_int_t*)MP_OBJ_TO_PTR(lhs_in))->mpz;
     } else {
         // unsupported type
         return MP_OBJ_NULL;
@@ -176,7 +176,7 @@ mp_obj_t mp_obj_int_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
         mpz_init_fixed_from_int(&z_int, z_int_dig, MPZ_NUM_DIG_FOR_INT, MP_OBJ_SMALL_INT_VALUE(rhs_in));
         zrhs = &z_int;
     } else if (MP_OBJ_IS_TYPE(rhs_in, &mp_type_int)) {
-        zrhs = &((mp_obj_int_t*)rhs_in)->mpz;
+        zrhs = &((mp_obj_int_t*)MP_OBJ_TO_PTR(rhs_in))->mpz;
 #if MICROPY_PY_BUILTINS_FLOAT
     } else if (mp_obj_is_float(rhs_in)) {
         return mp_obj_float_binary_op(op, mpz_as_float(zlhs), rhs_in);
@@ -294,7 +294,7 @@ mp_obj_t mp_obj_int_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
                 if (zlhs->neg != zrhs->neg) {
                     mpz_add_inpl(&res->mpz, &res->mpz, zrhs);
                 }
-                mp_obj_t tuple[2] = {quo, res};
+                mp_obj_t tuple[2] = {MP_OBJ_FROM_PTR(quo), MP_OBJ_FROM_PTR(res)};
                 return mp_obj_new_tuple(2, tuple);
             }
 
@@ -302,7 +302,7 @@ mp_obj_t mp_obj_int_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
                 return MP_OBJ_NULL; // op not supported
         }
 
-        return res;
+        return MP_OBJ_FROM_PTR(res);
 
     } else {
         int cmp = mpz_cmp(zlhs, zrhs);
@@ -334,13 +334,13 @@ mp_obj_t mp_obj_new_int(mp_int_t value) {
 mp_obj_t mp_obj_new_int_from_ll(long long val) {
     mp_obj_int_t *o = mp_obj_int_new_mpz();
     mpz_set_from_ll(&o->mpz, val, true);
-    return o;
+    return MP_OBJ_FROM_PTR(o);
 }
 
 mp_obj_t mp_obj_new_int_from_ull(unsigned long long val) {
     mp_obj_int_t *o = mp_obj_int_new_mpz();
     mpz_set_from_ll(&o->mpz, val, false);
-    return o;
+    return MP_OBJ_FROM_PTR(o);
 }
 
 mp_obj_t mp_obj_new_int_from_uint(mp_uint_t value) {
@@ -366,7 +366,7 @@ mp_obj_t mp_obj_new_int_from_float(mp_float_t val) {
         } else {
             mp_obj_int_t *o = mp_obj_int_new_mpz();
             mpz_set_from_float(&o->mpz, val);
-            return o;
+            return MP_OBJ_FROM_PTR(o);
         }
     }
 }
@@ -376,14 +376,14 @@ mp_obj_t mp_obj_new_int_from_str_len(const char **str, mp_uint_t len, bool neg,
     mp_obj_int_t *o = mp_obj_int_new_mpz();
     mp_uint_t n = mpz_set_from_str(&o->mpz, *str, len, neg, base);
     *str += n;
-    return o;
+    return MP_OBJ_FROM_PTR(o);
 }
 
 mp_int_t mp_obj_int_get_truncated(mp_const_obj_t self_in) {
     if (MP_OBJ_IS_SMALL_INT(self_in)) {
         return MP_OBJ_SMALL_INT_VALUE(self_in);
     } else {
-        const mp_obj_int_t *self = self_in;
+        const mp_obj_int_t *self = MP_OBJ_TO_PTR(self_in);
         // hash returns actual int value if it fits in mp_int_t
         return mpz_hash(&self->mpz);
     }
@@ -393,7 +393,7 @@ mp_int_t mp_obj_int_get_checked(mp_const_obj_t self_in) {
     if (MP_OBJ_IS_SMALL_INT(self_in)) {
         return MP_OBJ_SMALL_INT_VALUE(self_in);
     } else {
-        const mp_obj_int_t *self = self_in;
+        const mp_obj_int_t *self = MP_OBJ_TO_PTR(self_in);
         mp_int_t value;
         if (mpz_as_int_checked(&self->mpz, &value)) {
             return value;
@@ -409,7 +409,7 @@ mp_float_t mp_obj_int_as_float(mp_obj_t self_in) {
     if (MP_OBJ_IS_SMALL_INT(self_in)) {
         return MP_OBJ_SMALL_INT_VALUE(self_in);
     } else {
-        mp_obj_int_t *self = self_in;
+        mp_obj_int_t *self = MP_OBJ_TO_PTR(self_in);
         return mpz_as_float(&self->mpz);
     }
 }
diff --git a/py/objlist.c b/py/objlist.c
index 4dd6db27a002fd50f3982daf8e3aee3b6486597f..a4bec9e32067c8ee39a828081d118688f3ea4b53 100644
--- a/py/objlist.c
+++ b/py/objlist.c
@@ -45,7 +45,7 @@ STATIC mp_obj_t list_pop(mp_uint_t n_args, const mp_obj_t *args);
 /* list                                                                       */
 
 STATIC void list_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
-    mp_obj_list_t *o = MP_OBJ_CAST(o_in);
+    mp_obj_list_t *o = MP_OBJ_TO_PTR(o_in);
     if (!(MICROPY_PY_UJSON && kind == PRINT_JSON)) {
         kind = PRINT_REPR;
     }
@@ -93,14 +93,14 @@ STATIC bool list_cmp_helper(mp_uint_t op, mp_obj_t self_in, mp_obj_t another_in)
     if (!MP_OBJ_IS_TYPE(another_in, &mp_type_list)) {
         return false;
     }
-    mp_obj_list_t *self = MP_OBJ_CAST(self_in);
-    mp_obj_list_t *another = MP_OBJ_CAST(another_in);
+    mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
+    mp_obj_list_t *another = MP_OBJ_TO_PTR(another_in);
 
     return mp_seq_cmp_objs(op, self->items, self->len, another->items, another->len);
 }
 
 STATIC mp_obj_t list_unary_op(mp_uint_t op, mp_obj_t self_in) {
-    mp_obj_list_t *self = MP_OBJ_CAST(self_in);
+    mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
     switch (op) {
         case MP_UNARY_OP_BOOL: return mp_obj_new_bool(self->len != 0);
         case MP_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT(self->len);
@@ -109,16 +109,16 @@ STATIC mp_obj_t list_unary_op(mp_uint_t op, mp_obj_t self_in) {
 }
 
 STATIC mp_obj_t list_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs) {
-    mp_obj_list_t *o = MP_OBJ_CAST(lhs);
+    mp_obj_list_t *o = MP_OBJ_TO_PTR(lhs);
     switch (op) {
         case MP_BINARY_OP_ADD: {
             if (!MP_OBJ_IS_TYPE(rhs, &mp_type_list)) {
                 return MP_OBJ_NULL; // op not supported
             }
-            mp_obj_list_t *p = MP_OBJ_CAST(rhs);
+            mp_obj_list_t *p = MP_OBJ_TO_PTR(rhs);
             mp_obj_list_t *s = list_new(o->len + p->len);
             mp_seq_cat(s->items, o->items, o->len, p->items, p->len, mp_obj_t);
-            return MP_OBJ_UNCAST(s);
+            return MP_OBJ_FROM_PTR(s);
         }
         case MP_BINARY_OP_INPLACE_ADD: {
             list_extend(lhs, rhs);
@@ -134,7 +134,7 @@ STATIC mp_obj_t list_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs) {
             }
             mp_obj_list_t *s = list_new(o->len * n);
             mp_seq_multiply(o->items, sizeof(*o->items), o->len, n, s->items);
-            return MP_OBJ_UNCAST(s);
+            return MP_OBJ_FROM_PTR(s);
         }
         case MP_BINARY_OP_EQUAL:
         case MP_BINARY_OP_LESS:
@@ -153,7 +153,7 @@ STATIC mp_obj_t list_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
         // delete
 #if MICROPY_PY_BUILTINS_SLICE
         if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) {
-            mp_obj_list_t *self = MP_OBJ_CAST(self_in);
+            mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
             mp_bound_slice_t slice;
             if (!mp_seq_get_fast_slice_indexes(self->len, index, &slice)) {
                 assert(0);
@@ -174,7 +174,7 @@ STATIC mp_obj_t list_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
         return mp_const_none;
     } else if (value == MP_OBJ_SENTINEL) {
         // load
-        mp_obj_list_t *self = MP_OBJ_CAST(self_in);
+        mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
 #if MICROPY_PY_BUILTINS_SLICE
         if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) {
             mp_bound_slice_t slice;
@@ -183,7 +183,7 @@ STATIC mp_obj_t list_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
             }
             mp_obj_list_t *res = list_new(slice.stop - slice.start);
             mp_seq_copy(res->items, self->items + slice.start, res->len, mp_obj_t);
-            return MP_OBJ_UNCAST(res);
+            return MP_OBJ_FROM_PTR(res);
         }
 #endif
         mp_uint_t index_val = mp_get_index(self->base.type, self->len, index, false);
@@ -191,9 +191,9 @@ STATIC mp_obj_t list_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
     } else {
 #if MICROPY_PY_BUILTINS_SLICE
         if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) {
-            mp_obj_list_t *self = MP_OBJ_CAST(self_in);
+            mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
             assert(MP_OBJ_IS_TYPE(value, &mp_type_list));
-            mp_obj_list_t *slice = MP_OBJ_CAST(value);
+            mp_obj_list_t *slice = MP_OBJ_TO_PTR(value);
             mp_bound_slice_t slice_out;
             if (!mp_seq_get_fast_slice_indexes(self->len, index, &slice_out)) {
                 assert(0);
@@ -231,7 +231,7 @@ STATIC mp_obj_t list_getiter(mp_obj_t o_in) {
 
 mp_obj_t mp_obj_list_append(mp_obj_t self_in, mp_obj_t arg) {
     assert(MP_OBJ_IS_TYPE(self_in, &mp_type_list));
-    mp_obj_list_t *self = MP_OBJ_CAST(self_in);
+    mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
     if (self->len >= self->alloc) {
         self->items = m_renew(mp_obj_t, self->items, self->alloc, self->alloc * 2);
         self->alloc *= 2;
@@ -244,8 +244,8 @@ mp_obj_t mp_obj_list_append(mp_obj_t self_in, mp_obj_t arg) {
 STATIC mp_obj_t list_extend(mp_obj_t self_in, mp_obj_t arg_in) {
     assert(MP_OBJ_IS_TYPE(self_in, &mp_type_list));
     if (MP_OBJ_IS_TYPE(arg_in, &mp_type_list)) {
-        mp_obj_list_t *self = MP_OBJ_CAST(self_in);
-        mp_obj_list_t *arg = MP_OBJ_CAST(arg_in);
+        mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
+        mp_obj_list_t *arg = MP_OBJ_TO_PTR(arg_in);
 
         if (self->len + arg->len > self->alloc) {
             // TODO: use alloc policy for "4"
@@ -265,7 +265,7 @@ STATIC mp_obj_t list_extend(mp_obj_t self_in, mp_obj_t arg_in) {
 STATIC mp_obj_t list_pop(mp_uint_t n_args, const mp_obj_t *args) {
     assert(1 <= n_args && n_args <= 2);
     assert(MP_OBJ_IS_TYPE(args[0], &mp_type_list));
-    mp_obj_list_t *self = MP_OBJ_CAST(args[0]);
+    mp_obj_list_t *self = MP_OBJ_TO_PTR(args[0]);
     if (self->len == 0) {
         nlr_raise(mp_obj_new_exception_msg(&mp_type_IndexError, "pop from empty list"));
     }
@@ -322,7 +322,7 @@ mp_obj_t mp_obj_list_sort(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *
     mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
 
     assert(MP_OBJ_IS_TYPE(pos_args[0], &mp_type_list));
-    mp_obj_list_t *self = MP_OBJ_CAST(pos_args[0]);
+    mp_obj_list_t *self = MP_OBJ_TO_PTR(pos_args[0]);
 
     if (self->len > 1) {
         mp_quicksort(self->items, self->items + self->len - 1,
@@ -335,7 +335,7 @@ mp_obj_t mp_obj_list_sort(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *
 
 STATIC mp_obj_t list_clear(mp_obj_t self_in) {
     assert(MP_OBJ_IS_TYPE(self_in, &mp_type_list));
-    mp_obj_list_t *self = MP_OBJ_CAST(self_in);
+    mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
     self->len = 0;
     self->items = m_renew(mp_obj_t, self->items, self->alloc, LIST_MIN_ALLOC);
     self->alloc = LIST_MIN_ALLOC;
@@ -345,26 +345,26 @@ STATIC mp_obj_t list_clear(mp_obj_t self_in) {
 
 STATIC mp_obj_t list_copy(mp_obj_t self_in) {
     assert(MP_OBJ_IS_TYPE(self_in, &mp_type_list));
-    mp_obj_list_t *self = MP_OBJ_CAST(self_in);
+    mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
     return mp_obj_new_list(self->len, self->items);
 }
 
 STATIC mp_obj_t list_count(mp_obj_t self_in, mp_obj_t value) {
     assert(MP_OBJ_IS_TYPE(self_in, &mp_type_list));
-    mp_obj_list_t *self = MP_OBJ_CAST(self_in);
+    mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
     return mp_seq_count_obj(self->items, self->len, value);
 }
 
 STATIC mp_obj_t list_index(mp_uint_t n_args, const mp_obj_t *args) {
     assert(2 <= n_args && n_args <= 4);
     assert(MP_OBJ_IS_TYPE(args[0], &mp_type_list));
-    mp_obj_list_t *self = MP_OBJ_CAST(args[0]);
+    mp_obj_list_t *self = MP_OBJ_TO_PTR(args[0]);
     return mp_seq_index_obj(self->items, self->len, n_args, args);
 }
 
 STATIC mp_obj_t list_insert(mp_obj_t self_in, mp_obj_t idx, mp_obj_t obj) {
     assert(MP_OBJ_IS_TYPE(self_in, &mp_type_list));
-    mp_obj_list_t *self = MP_OBJ_CAST(self_in);
+    mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
     // insert has its own strange index logic
     mp_int_t index = MP_OBJ_SMALL_INT_VALUE(idx);
     if (index < 0) {
@@ -398,7 +398,7 @@ mp_obj_t mp_obj_list_remove(mp_obj_t self_in, mp_obj_t value) {
 
 STATIC mp_obj_t list_reverse(mp_obj_t self_in) {
     assert(MP_OBJ_IS_TYPE(self_in, &mp_type_list));
-    mp_obj_list_t *self = MP_OBJ_CAST(self_in);
+    mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
 
     mp_int_t len = self->len;
     for (mp_int_t i = 0; i < len/2; i++) {
@@ -447,7 +447,7 @@ const mp_obj_type_t mp_type_list = {
     .binary_op = list_binary_op,
     .subscr = list_subscr,
     .getiter = list_getiter,
-    .locals_dict = (mp_obj_t)&list_locals_dict,
+    .locals_dict = (mp_obj_dict_t*)&list_locals_dict,
 };
 
 void mp_obj_list_init(mp_obj_list_t *o, mp_uint_t n) {
@@ -459,8 +459,7 @@ void mp_obj_list_init(mp_obj_list_t *o, mp_uint_t n) {
 }
 
 STATIC mp_obj_list_t *list_new(mp_uint_t n) {
-    mp_obj_t o_in = m_new_obj(mp_obj_list_t);
-    mp_obj_list_t *o = MP_OBJ_CAST(o_in);
+    mp_obj_list_t *o = m_new_obj(mp_obj_list_t);
     mp_obj_list_init(o, n);
     return o;
 }
@@ -472,11 +471,11 @@ mp_obj_t mp_obj_new_list(mp_uint_t n, mp_obj_t *items) {
             o->items[i] = items[i];
         }
     }
-    return MP_OBJ_UNCAST(o);
+    return MP_OBJ_FROM_PTR(o);
 }
 
 void mp_obj_list_get(mp_obj_t self_in, mp_uint_t *len, mp_obj_t **items) {
-    mp_obj_list_t *self = MP_OBJ_CAST(self_in);
+    mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
     *len = self->len;
     *items = self->items;
 }
@@ -484,12 +483,12 @@ void mp_obj_list_get(mp_obj_t self_in, mp_uint_t *len, mp_obj_t **items) {
 void mp_obj_list_set_len(mp_obj_t self_in, mp_uint_t len) {
     // trust that the caller knows what it's doing
     // TODO realloc if len got much smaller than alloc
-    mp_obj_list_t *self = MP_OBJ_CAST(self_in);
+    mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
     self->len = len;
 }
 
 void mp_obj_list_store(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
-    mp_obj_list_t *self = MP_OBJ_CAST(self_in);
+    mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
     mp_uint_t i = mp_get_index(self->base.type, self->len, index, false);
     self->items[i] = value;
 }
@@ -504,8 +503,8 @@ typedef struct _mp_obj_list_it_t {
 } mp_obj_list_it_t;
 
 STATIC mp_obj_t list_it_iternext(mp_obj_t self_in) {
-    mp_obj_list_it_t *self = MP_OBJ_CAST(self_in);
-    mp_obj_list_t *list = MP_OBJ_CAST(self->list);
+    mp_obj_list_it_t *self = MP_OBJ_TO_PTR(self_in);
+    mp_obj_list_t *list = MP_OBJ_TO_PTR(self->list);
     if (self->cur < list->len) {
         mp_obj_t o_out = list->items[self->cur];
         self->cur += 1;
@@ -523,10 +522,9 @@ STATIC const mp_obj_type_t mp_type_list_it = {
 };
 
 mp_obj_t mp_obj_new_list_iterator(mp_obj_t list, mp_uint_t cur) {
-    mp_obj_t o_out = m_new_obj(mp_obj_list_it_t);
-    mp_obj_list_it_t *o = MP_OBJ_CAST(o_out);
+    mp_obj_list_it_t *o = m_new_obj(mp_obj_list_it_t);
     o->base.type = &mp_type_list_it;
     o->list = list;
     o->cur = cur;
-    return o_out;
+    return MP_OBJ_FROM_PTR(o);
 }
diff --git a/py/objmap.c b/py/objmap.c
index d9df9fdea38438b3e5aebb60b3ae3798eea9a5fa..6dbfaca05f2f9c36de6927ddf89c49f2e5db2982 100644
--- a/py/objmap.c
+++ b/py/objmap.c
@@ -39,18 +39,18 @@ typedef struct _mp_obj_map_t {
 STATIC mp_obj_t map_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
     mp_arg_check_num(n_args, n_kw, 2, MP_OBJ_FUN_ARGS_MAX, false);
     mp_obj_map_t *o = m_new_obj_var(mp_obj_map_t, mp_obj_t, n_args - 1);
-    o->base.type = type_in;
+    o->base.type = MP_OBJ_TO_PTR(type_in);
     o->n_iters = n_args - 1;
     o->fun = args[0];
     for (mp_uint_t i = 0; i < n_args - 1; i++) {
         o->iters[i] = mp_getiter(args[i + 1]);
     }
-    return o;
+    return MP_OBJ_FROM_PTR(o);
 }
 
 STATIC mp_obj_t map_iternext(mp_obj_t self_in) {
     assert(MP_OBJ_IS_TYPE(self_in, &mp_type_map));
-    mp_obj_map_t *self = self_in;
+    mp_obj_map_t *self = MP_OBJ_TO_PTR(self_in);
     mp_obj_t *nextses = m_new(mp_obj_t, self->n_iters);
 
     for (mp_uint_t i = 0; i < self->n_iters; i++) {
diff --git a/py/objmodule.c b/py/objmodule.c
index b3757d6a1e697b9e432fa8da6a6b66d4ae188505..46c508160063d584f88adc0551f1648008ef6656 100644
--- a/py/objmodule.c
+++ b/py/objmodule.c
@@ -35,7 +35,7 @@
 
 STATIC void module_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
     (void)kind;
-    mp_obj_module_t *self = self_in;
+    mp_obj_module_t *self = MP_OBJ_TO_PTR(self_in);
 
 #if MICROPY_PY___FILE__
     // If we store __file__ to imported modules then try to lookup this
@@ -51,7 +51,7 @@ STATIC void module_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kin
 }
 
 STATIC void module_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
-    mp_obj_module_t *self = self_in;
+    mp_obj_module_t *self = MP_OBJ_TO_PTR(self_in);
     if (dest[0] == MP_OBJ_NULL) {
         // load attribute
         mp_map_elem_t *elem = mp_map_lookup(&self->globals->map, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP);
@@ -65,7 +65,7 @@ STATIC void module_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
             #if MICROPY_CAN_OVERRIDE_BUILTINS
             if (dict == &mp_module_builtins_globals) {
                 if (MP_STATE_VM(mp_module_builtins_override_dict) == NULL) {
-                    MP_STATE_VM(mp_module_builtins_override_dict) = mp_obj_new_dict(1);
+                    MP_STATE_VM(mp_module_builtins_override_dict) = MP_OBJ_TO_PTR(mp_obj_new_dict(1));
                 }
                 dict = MP_STATE_VM(mp_module_builtins_override_dict);
             } else
@@ -77,11 +77,11 @@ STATIC void module_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
         }
         if (dest[1] == MP_OBJ_NULL) {
             // delete attribute
-            mp_obj_dict_delete(dict, MP_OBJ_NEW_QSTR(attr));
+            mp_obj_dict_delete(MP_OBJ_FROM_PTR(dict), MP_OBJ_NEW_QSTR(attr));
         } else {
             // store attribute
             // TODO CPython allows STORE_ATTR to a module, but is this the correct implementation?
-            mp_obj_dict_store(dict, MP_OBJ_NEW_QSTR(attr), dest[1]);
+            mp_obj_dict_store(MP_OBJ_FROM_PTR(dict), MP_OBJ_NEW_QSTR(attr), dest[1]);
         }
         dest[0] = MP_OBJ_NULL; // indicate success
     }
@@ -106,21 +106,21 @@ mp_obj_t mp_obj_new_module(qstr module_name) {
     mp_obj_module_t *o = m_new_obj(mp_obj_module_t);
     o->base.type = &mp_type_module;
     o->name = module_name;
-    o->globals = mp_obj_new_dict(MICROPY_MODULE_DICT_SIZE);
+    o->globals = MP_OBJ_TO_PTR(mp_obj_new_dict(MICROPY_MODULE_DICT_SIZE));
 
     // store __name__ entry in the module
-    mp_obj_dict_store(o->globals, MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(module_name));
+    mp_obj_dict_store(MP_OBJ_FROM_PTR(o->globals), MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(module_name));
 
     // store the new module into the slot in the global dict holding all modules
-    el->value = o;
+    el->value = MP_OBJ_FROM_PTR(o);
 
     // return the new module
-    return o;
+    return MP_OBJ_FROM_PTR(o);
 }
 
 mp_obj_dict_t *mp_obj_module_get_globals(mp_obj_t self_in) {
     assert(MP_OBJ_IS_TYPE(self_in, &mp_type_module));
-    mp_obj_module_t *self = self_in;
+    mp_obj_module_t *self = MP_OBJ_TO_PTR(self_in);
     return self->globals;
 }
 
diff --git a/py/objnamedtuple.c b/py/objnamedtuple.c
index 778d1f776e86fb032e584c8c60af3c39a79af5d1..167e23b4a434325cb6d9c623dfe1992c3b22535e 100644
--- a/py/objnamedtuple.c
+++ b/py/objnamedtuple.c
@@ -55,7 +55,7 @@ STATIC mp_uint_t namedtuple_find_field(mp_obj_namedtuple_type_t *type, qstr name
 
 STATIC void namedtuple_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
     (void)kind;
-    mp_obj_namedtuple_t *o = o_in;
+    mp_obj_namedtuple_t *o = MP_OBJ_TO_PTR(o_in);
     mp_printf(print, "%q", o->tuple.base.type->name);
     const qstr *fields = ((mp_obj_namedtuple_type_t*)o->tuple.base.type)->fields;
     mp_obj_attrtuple_print_helper(print, fields, &o->tuple);
@@ -64,7 +64,7 @@ STATIC void namedtuple_print(const mp_print_t *print, mp_obj_t o_in, mp_print_ki
 STATIC void namedtuple_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
     if (dest[0] == MP_OBJ_NULL) {
         // load attribute
-        mp_obj_namedtuple_t *self = self_in;
+        mp_obj_namedtuple_t *self = MP_OBJ_TO_PTR(self_in);
         int id = namedtuple_find_field((mp_obj_namedtuple_type_t*)self->tuple.base.type, attr);
         if (id == -1) {
             return;
@@ -78,7 +78,7 @@ STATIC void namedtuple_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
 }
 
 STATIC mp_obj_t namedtuple_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
-    mp_obj_namedtuple_type_t *type = type_in;
+    mp_obj_namedtuple_type_t *type = MP_OBJ_TO_PTR(type_in);
     mp_uint_t num_fields = type->n_fields;
     if (n_args + n_kw != num_fields) {
         if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
@@ -117,7 +117,7 @@ STATIC mp_obj_t namedtuple_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_
                         "unexpected keyword argument '%q'", kw));
                 }
             }
-            if (arg_objects[id] != NULL) {
+            if (arg_objects[id] != MP_OBJ_NULL) {
                 if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
                     mp_arg_error_terse_mismatch();
                 } else {
@@ -129,9 +129,9 @@ STATIC mp_obj_t namedtuple_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_
         }
     }
 
-    mp_obj_tuple_t *tuple = mp_obj_new_tuple(num_fields, arg_objects);
-    tuple->base.type = type_in;
-    return tuple;
+    mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR(mp_obj_new_tuple(num_fields, arg_objects));
+    tuple->base.type = MP_OBJ_TO_PTR(type_in);
+    return MP_OBJ_FROM_PTR(tuple);
 }
 
 STATIC const mp_rom_obj_tuple_t namedtuple_base_tuple = {{&mp_type_tuple}, 1, {MP_ROM_PTR(&mp_type_tuple)}};
@@ -148,12 +148,12 @@ STATIC mp_obj_t mp_obj_new_namedtuple_type(qstr name, mp_uint_t n_fields, mp_obj
     o->base.attr = namedtuple_attr;
     o->base.subscr = mp_obj_tuple_subscr;
     o->base.getiter = mp_obj_tuple_getiter;
-    o->base.bases_tuple = (mp_obj_t)&namedtuple_base_tuple;
+    o->base.bases_tuple = (mp_obj_tuple_t*)(mp_rom_obj_tuple_t*)&namedtuple_base_tuple;
     o->n_fields = n_fields;
     for (mp_uint_t i = 0; i < n_fields; i++) {
         o->fields[i] = mp_obj_str_get_qstr(fields[i]);
     }
-    return o;
+    return MP_OBJ_FROM_PTR(o);
 }
 
 STATIC mp_obj_t new_namedtuple_type(mp_obj_t name_in, mp_obj_t fields_in) {
diff --git a/py/objobject.c b/py/objobject.c
index 6e4d5d4cc43a61d100c5006a4ebf200daba9e24f..afb9d5af723187e4480f635db3f9bd5ffd28fc5c 100644
--- a/py/objobject.c
+++ b/py/objobject.c
@@ -37,8 +37,8 @@ STATIC mp_obj_t object_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_
     (void)args;
     mp_arg_check_num(n_args, n_kw, 0, 0, false);
     mp_obj_object_t *o = m_new_obj(mp_obj_object_t);
-    o->base.type = type_in;
-    return o;
+    o->base.type = MP_OBJ_TO_PTR(type_in);
+    return MP_OBJ_FROM_PTR(o);
 }
 
 #if MICROPY_CPYTHON_COMPAT
@@ -49,7 +49,7 @@ STATIC mp_obj_t object___init__(mp_obj_t self) {
 STATIC MP_DEFINE_CONST_FUN_OBJ_1(object___init___obj, object___init__);
 
 STATIC mp_obj_t object___new__(mp_obj_t cls) {
-    if (!MP_OBJ_IS_TYPE(cls, &mp_type_type) || !mp_obj_is_instance_type((mp_obj_type_t*)cls)) {
+    if (!MP_OBJ_IS_TYPE(cls, &mp_type_type) || !mp_obj_is_instance_type((mp_obj_type_t*)MP_OBJ_TO_PTR(cls))) {
         nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
                     "__new__ arg must be a user-type"));
     }
@@ -77,6 +77,6 @@ const mp_obj_type_t mp_type_object = {
     .name = MP_QSTR_object,
     .make_new = object_make_new,
     #if MICROPY_CPYTHON_COMPAT
-    .locals_dict = (mp_obj_t)&object_locals_dict,
+    .locals_dict = (mp_obj_dict_t*)&object_locals_dict,
     #endif
 };
diff --git a/py/objproperty.c b/py/objproperty.c
index 818547725c6acf36e9238a3af54101431d066181..fb814cba1af7e1d8f9c57fc6f2001a41b951a019 100644
--- a/py/objproperty.c
+++ b/py/objproperty.c
@@ -41,7 +41,7 @@ STATIC mp_obj_t property_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t
     mp_arg_check_num(n_args, n_kw, 0, 4, false);
 
     mp_obj_property_t *o = m_new_obj(mp_obj_property_t);
-    o->base.type = type_in;
+    o->base.type = MP_OBJ_TO_PTR(type_in);
     if (n_args >= 4) {
         // doc ignored
     }
@@ -60,32 +60,32 @@ STATIC mp_obj_t property_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t
     } else {
         o->proxy[0] = mp_const_none;
     }
-    return o;
+    return MP_OBJ_FROM_PTR(o);
 }
 
 STATIC mp_obj_t property_getter(mp_obj_t self_in, mp_obj_t getter) {
     mp_obj_property_t *p2 = m_new_obj(mp_obj_property_t);
-    *p2 = *(mp_obj_property_t*)self_in;
+    *p2 = *(mp_obj_property_t*)MP_OBJ_TO_PTR(self_in);
     p2->proxy[0] = getter;
-    return p2;
+    return MP_OBJ_FROM_PTR(p2);
 }
 
 STATIC MP_DEFINE_CONST_FUN_OBJ_2(property_getter_obj, property_getter);
 
 STATIC mp_obj_t property_setter(mp_obj_t self_in, mp_obj_t setter) {
     mp_obj_property_t *p2 = m_new_obj(mp_obj_property_t);
-    *p2 = *(mp_obj_property_t*)self_in;
+    *p2 = *(mp_obj_property_t*)MP_OBJ_TO_PTR(self_in);
     p2->proxy[1] = setter;
-    return p2;
+    return MP_OBJ_FROM_PTR(p2);
 }
 
 STATIC MP_DEFINE_CONST_FUN_OBJ_2(property_setter_obj, property_setter);
 
 STATIC mp_obj_t property_deleter(mp_obj_t self_in, mp_obj_t deleter) {
     mp_obj_property_t *p2 = m_new_obj(mp_obj_property_t);
-    *p2 = *(mp_obj_property_t*)self_in;
+    *p2 = *(mp_obj_property_t*)MP_OBJ_TO_PTR(self_in);
     p2->proxy[2] = deleter;
-    return p2;
+    return MP_OBJ_FROM_PTR(p2);
 }
 
 STATIC MP_DEFINE_CONST_FUN_OBJ_2(property_deleter_obj, property_deleter);
@@ -102,12 +102,12 @@ const mp_obj_type_t mp_type_property = {
     { &mp_type_type },
     .name = MP_QSTR_property,
     .make_new = property_make_new,
-    .locals_dict = (mp_obj_t)&property_locals_dict,
+    .locals_dict = (mp_obj_dict_t*)&property_locals_dict,
 };
 
 const mp_obj_t *mp_obj_property_get(mp_obj_t self_in) {
     assert(MP_OBJ_IS_TYPE(self_in, &mp_type_property));
-    mp_obj_property_t *self = self_in;
+    mp_obj_property_t *self = MP_OBJ_TO_PTR(self_in);
     return self->proxy;
 }
 
diff --git a/py/objrange.c b/py/objrange.c
index f703f2fb0f052d5cc99dd6764dc415138ab57b44..7a4aaa72cd17498802d4f723be6ef70baf6c8760 100644
--- a/py/objrange.c
+++ b/py/objrange.c
@@ -42,7 +42,7 @@ typedef struct _mp_obj_range_it_t {
 } mp_obj_range_it_t;
 
 STATIC mp_obj_t range_it_iternext(mp_obj_t o_in) {
-    mp_obj_range_it_t *o = o_in;
+    mp_obj_range_it_t *o = MP_OBJ_TO_PTR(o_in);
     if ((o->step > 0 && o->cur < o->stop) || (o->step < 0 && o->cur > o->stop)) {
         mp_obj_t o_out = MP_OBJ_NEW_SMALL_INT(o->cur);
         o->cur += o->step;
@@ -65,7 +65,7 @@ STATIC mp_obj_t mp_obj_new_range_iterator(mp_int_t cur, mp_int_t stop, mp_int_t
     o->cur = cur;
     o->stop = stop;
     o->step = step;
-    return o;
+    return MP_OBJ_FROM_PTR(o);
 }
 
 /******************************************************************************/
@@ -81,12 +81,12 @@ typedef struct _mp_obj_range_t {
 
 STATIC void range_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
     (void)kind;
-    mp_obj_range_t *self = self_in;
-    mp_printf(print, "range(%d, %d", self->start, self->stop);
+    mp_obj_range_t *self = MP_OBJ_TO_PTR(self_in);
+    mp_printf(print, "range(" INT_FMT ", " INT_FMT "", self->start, self->stop);
     if (self->step == 1) {
         mp_print_str(print, ")");
     } else {
-        mp_printf(print, ", %d)", self->step);
+        mp_printf(print, ", " INT_FMT ")", self->step);
     }
 }
 
@@ -94,7 +94,7 @@ STATIC mp_obj_t range_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_k
     mp_arg_check_num(n_args, n_kw, 1, 3, false);
 
     mp_obj_range_t *o = m_new_obj(mp_obj_range_t);
-    o->base.type = type_in;
+    o->base.type = MP_OBJ_TO_PTR(type_in);
     o->start = 0;
     o->step = 1;
 
@@ -109,7 +109,7 @@ STATIC mp_obj_t range_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_k
         }
     }
 
-    return o;
+    return MP_OBJ_FROM_PTR(o);
 }
 
 STATIC mp_int_t range_len(mp_obj_range_t *self) {
@@ -128,7 +128,7 @@ STATIC mp_int_t range_len(mp_obj_range_t *self) {
 }
 
 STATIC mp_obj_t range_unary_op(mp_uint_t op, mp_obj_t self_in) {
-    mp_obj_range_t *self = self_in;
+    mp_obj_range_t *self = MP_OBJ_TO_PTR(self_in);
     mp_int_t len = range_len(self);
     switch (op) {
         case MP_UNARY_OP_BOOL: return mp_obj_new_bool(len > 0);
@@ -140,7 +140,7 @@ STATIC mp_obj_t range_unary_op(mp_uint_t op, mp_obj_t self_in) {
 STATIC mp_obj_t range_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
     if (value == MP_OBJ_SENTINEL) {
         // load
-        mp_obj_range_t *self = self_in;
+        mp_obj_range_t *self = MP_OBJ_TO_PTR(self_in);
         mp_int_t len = range_len(self);
 #if MICROPY_PY_BUILTINS_SLICE
         if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) {
@@ -151,7 +151,7 @@ STATIC mp_obj_t range_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
             o->start = self->start + slice.start * self->step;
             o->stop = self->start + slice.stop * self->step;
             o->step = slice.step * self->step;
-            return o;
+            return MP_OBJ_FROM_PTR(o);
         }
 #endif
         uint index_val = mp_get_index(self->base.type, len, index, false);
@@ -162,7 +162,7 @@ STATIC mp_obj_t range_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
 }
 
 STATIC mp_obj_t range_getiter(mp_obj_t o_in) {
-    mp_obj_range_t *o = o_in;
+    mp_obj_range_t *o = MP_OBJ_TO_PTR(o_in);
     return mp_obj_new_range_iterator(o->start, o->stop, o->step);
 }
 
@@ -173,7 +173,7 @@ STATIC void range_attr(mp_obj_t o_in, qstr attr, mp_obj_t *dest) {
         // not load attribute
         return;
     }
-    mp_obj_range_t *o = o_in;
+    mp_obj_range_t *o = MP_OBJ_TO_PTR(o_in);
     if (attr == MP_QSTR_start) {
         dest[0] = mp_obj_new_int(o->start);
     } else if (attr == MP_QSTR_stop) {
diff --git a/py/objreversed.c b/py/objreversed.c
index 7ad0f89edc74c4d09f420b5e3b321516f6e994b0..2b16f0893fc0d78ea566fa3745e3d54e5a1fd40a 100644
--- a/py/objreversed.c
+++ b/py/objreversed.c
@@ -49,16 +49,16 @@ STATIC mp_obj_t reversed_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t
     }
 
     mp_obj_reversed_t *o = m_new_obj(mp_obj_reversed_t);
-    o->base.type = type_in;
+    o->base.type = MP_OBJ_TO_PTR(type_in);
     o->seq = args[0];
     o->cur_index = mp_obj_get_int(mp_obj_len(args[0])); // start at the end of the sequence
 
-    return o;
+    return MP_OBJ_FROM_PTR(o);
 }
 
 STATIC mp_obj_t reversed_iternext(mp_obj_t self_in) {
     assert(MP_OBJ_IS_TYPE(self_in, &mp_type_reversed));
-    mp_obj_reversed_t *self = self_in;
+    mp_obj_reversed_t *self = MP_OBJ_TO_PTR(self_in);
 
     // "raise" stop iteration if we are at the end (the start) of the sequence
     if (self->cur_index == 0) {
diff --git a/py/objset.c b/py/objset.c
index e8519b62be8acf99e905cd32c38605abf9f4d597..c09616e0ba89542460b8b23937f3bdb690bde93f 100644
--- a/py/objset.c
+++ b/py/objset.c
@@ -81,7 +81,7 @@ STATIC void check_set(mp_obj_t o) {
 
 STATIC void set_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
     (void)kind;
-    mp_obj_set_t *self = self_in;
+    mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in);
     #if MICROPY_PY_BUILTINS_FROZENSET
     bool is_frozen = MP_OBJ_IS_TYPE(self_in, &mp_type_frozenset);
     #endif
@@ -124,23 +124,23 @@ STATIC mp_obj_t set_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw,
     switch (n_args) {
         case 0: {
             // create a new, empty set
-            mp_obj_set_t *set = mp_obj_new_set(0, NULL);
+            mp_obj_set_t *set = MP_OBJ_TO_PTR(mp_obj_new_set(0, NULL));
             // set actual set/frozenset type
-            set->base.type = type_in;
-            return set;
+            set->base.type = MP_OBJ_TO_PTR(type_in);
+            return MP_OBJ_FROM_PTR(set);
         }
 
         case 1:
         default: { // can only be 0 or 1 arg
             // 1 argument, an iterable from which we make a new set
-            mp_obj_set_t *set = mp_obj_new_set(0, NULL);
+            mp_obj_t set = mp_obj_new_set(0, NULL);
             mp_obj_t iterable = mp_getiter(args[0]);
             mp_obj_t item;
             while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
                 mp_obj_set_store(set, item);
             }
             // Set actual set/frozenset type
-            set->base.type = type_in;
+            ((mp_obj_set_t*)MP_OBJ_TO_PTR(set))->base.type = MP_OBJ_TO_PTR(type_in);
             return set;
         }
     }
@@ -155,7 +155,7 @@ const mp_obj_type_t mp_type_set_it = {
 
 STATIC mp_obj_t set_it_iternext(mp_obj_t self_in) {
     assert(MP_OBJ_IS_TYPE(self_in, &mp_type_set_it));
-    mp_obj_set_it_t *self = self_in;
+    mp_obj_set_it_t *self = MP_OBJ_TO_PTR(self_in);
     mp_uint_t max = self->set->set.alloc;
     mp_set_t *set = &self->set->set;
 
@@ -172,9 +172,9 @@ STATIC mp_obj_t set_it_iternext(mp_obj_t self_in) {
 STATIC mp_obj_t set_getiter(mp_obj_t set_in) {
     mp_obj_set_it_t *o = m_new_obj(mp_obj_set_it_t);
     o->base.type = &mp_type_set_it;
-    o->set = (mp_obj_set_t *)set_in;
+    o->set = (mp_obj_set_t *)MP_OBJ_TO_PTR(set_in);
     o->cur = 0;
-    return o;
+    return MP_OBJ_FROM_PTR(o);
 }
 
 
@@ -183,7 +183,7 @@ STATIC mp_obj_t set_getiter(mp_obj_t set_in) {
 
 STATIC mp_obj_t set_add(mp_obj_t self_in, mp_obj_t item) {
     check_set(self_in);
-    mp_obj_set_t *self = self_in;
+    mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in);
     mp_set_lookup(&self->set, item, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
     return mp_const_none;
 }
@@ -191,7 +191,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_add_obj, set_add);
 
 STATIC mp_obj_t set_clear(mp_obj_t self_in) {
     check_set(self_in);
-    mp_obj_set_t *self = self_in;
+    mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in);
 
     mp_set_clear(&self->set);
 
@@ -200,7 +200,7 @@ STATIC mp_obj_t set_clear(mp_obj_t self_in) {
 STATIC MP_DEFINE_CONST_FUN_OBJ_1(set_clear_obj, set_clear);
 
 STATIC mp_obj_t set_copy_as_mutable(mp_obj_t self_in) {
-    mp_obj_set_t *self = self_in;
+    mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in);
 
     mp_obj_set_t *other = m_new_obj(mp_obj_set_t);
     other->base.type = &mp_type_set;
@@ -208,15 +208,14 @@ STATIC mp_obj_t set_copy_as_mutable(mp_obj_t self_in) {
     other->set.used = self->set.used;
     memcpy(other->set.table, self->set.table, self->set.alloc * sizeof(mp_obj_t));
 
-    return other;
+    return MP_OBJ_FROM_PTR(other);
 }
 
 STATIC mp_obj_t set_copy(mp_obj_t self_in) {
     check_set_or_frozenset(self_in);
-    mp_obj_set_t *self = self_in;
 
-    mp_obj_set_t *other = set_copy_as_mutable(self);
-    other->base.type = self->base.type;
+    mp_obj_t other = set_copy_as_mutable(self_in);
+    ((mp_obj_base_t*)MP_OBJ_TO_PTR(other))->type = ((mp_obj_base_t*)MP_OBJ_TO_PTR(self_in))->type;
 
     return other;
 }
@@ -224,7 +223,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(set_copy_obj, set_copy);
 
 STATIC mp_obj_t set_discard(mp_obj_t self_in, mp_obj_t item) {
     check_set(self_in);
-    mp_obj_set_t *self = self_in;
+    mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in);
     mp_set_lookup(&self->set, item, MP_MAP_LOOKUP_REMOVE_IF_FOUND);
     return mp_const_none;
 }
@@ -233,7 +232,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_discard_obj, set_discard);
 STATIC mp_obj_t set_diff_int(mp_uint_t n_args, const mp_obj_t *args, bool update) {
     assert(n_args > 0);
 
-    mp_obj_set_t *self;
+    mp_obj_t self;
     if (update) {
         check_set(args[0]);
         self = args[0];
@@ -256,7 +255,7 @@ STATIC mp_obj_t set_diff_int(mp_uint_t n_args, const mp_obj_t *args, bool update
         }
     }
 
-    self->base.type = ((mp_obj_set_t*)args[0])->base.type;
+    ((mp_obj_base_t*)MP_OBJ_TO_PTR(self))->type = ((mp_obj_base_t*)MP_OBJ_TO_PTR(args[0]))->type;
     return self;
 }
 
@@ -282,14 +281,14 @@ STATIC mp_obj_t set_intersect_int(mp_obj_t self_in, mp_obj_t other, bool update)
         return update ? mp_const_none : set_copy(self_in);
     }
 
-    mp_obj_set_t *self = self_in;
-    mp_obj_set_t *out = mp_obj_new_set(0, NULL);
+    mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in);
+    mp_obj_set_t *out = MP_OBJ_TO_PTR(mp_obj_new_set(0, NULL));
 
     mp_obj_t iter = mp_getiter(other);
     mp_obj_t next;
     while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) {
         if (mp_set_lookup(&self->set, next, MP_MAP_LOOKUP)) {
-            set_add(out, next);
+            set_add(MP_OBJ_FROM_PTR(out), next);
         }
     }
 
@@ -300,7 +299,7 @@ STATIC mp_obj_t set_intersect_int(mp_obj_t self_in, mp_obj_t other, bool update)
         self->set.table = out->set.table;
     }
 
-    return update ? mp_const_none : out;
+    return update ? mp_const_none : MP_OBJ_FROM_PTR(out);
 }
 
 STATIC mp_obj_t set_intersect(mp_obj_t self_in, mp_obj_t other) {
@@ -315,7 +314,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_intersect_update_obj, set_intersect_update)
 
 STATIC mp_obj_t set_isdisjoint(mp_obj_t self_in, mp_obj_t other) {
     check_set_or_frozenset(self_in);
-    mp_obj_set_t *self = self_in;
+    mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in);
 
     mp_obj_t iter = mp_getiter(other);
     mp_obj_t next;
@@ -332,25 +331,25 @@ STATIC mp_obj_t set_issubset_internal(mp_obj_t self_in, mp_obj_t other_in, bool
     mp_obj_set_t *self;
     bool cleanup_self = false;
     if (is_set_or_frozenset(self_in)) {
-        self = self_in;
+        self = MP_OBJ_TO_PTR(self_in);
     } else {
-        self = set_make_new((mp_obj_t)&mp_type_set, 1, 0, &self_in);
+        self = MP_OBJ_TO_PTR(set_make_new(MP_OBJ_FROM_PTR(&mp_type_set), 1, 0, &self_in));
         cleanup_self = true;
     }
 
     mp_obj_set_t *other;
     bool cleanup_other = false;
     if (is_set_or_frozenset(other_in)) {
-        other = other_in;
+        other = MP_OBJ_TO_PTR(other_in);
     } else {
-        other = set_make_new((mp_obj_t)&mp_type_set, 1, 0, &other_in);
+        other = MP_OBJ_TO_PTR(set_make_new(MP_OBJ_FROM_PTR(&mp_type_set), 1, 0, &other_in));
         cleanup_other = true;
     }
     bool out = true;
     if (proper && self->set.used == other->set.used) {
         out = false;
     } else {
-        mp_obj_t iter = set_getiter(self);
+        mp_obj_t iter = set_getiter(MP_OBJ_FROM_PTR(self));
         mp_obj_t next;
         while ((next = set_it_iternext(iter)) != MP_OBJ_STOP_ITERATION) {
             if (!mp_set_lookup(&other->set, next, MP_MAP_LOOKUP)) {
@@ -361,10 +360,10 @@ STATIC mp_obj_t set_issubset_internal(mp_obj_t self_in, mp_obj_t other_in, bool
     }
     // TODO: Should free objects altogether
     if (cleanup_self) {
-        set_clear(self);
+        set_clear(MP_OBJ_FROM_PTR(self));
     }
     if (cleanup_other) {
-        set_clear(other);
+        set_clear(MP_OBJ_FROM_PTR(other));
     }
     return mp_obj_new_bool(out);
 }
@@ -388,11 +387,11 @@ STATIC mp_obj_t set_issuperset_proper(mp_obj_t self_in, mp_obj_t other_in) {
 
 STATIC mp_obj_t set_equal(mp_obj_t self_in, mp_obj_t other_in) {
     check_set_or_frozenset(self_in);
-    mp_obj_set_t *self = self_in;
+    mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in);
     if (!is_set_or_frozenset(other_in)) {
         return mp_const_false;
     }
-    mp_obj_set_t *other = other_in;
+    mp_obj_set_t *other = MP_OBJ_TO_PTR(other_in);
     if (self->set.used != other->set.used) {
         return mp_const_false;
     }
@@ -401,7 +400,7 @@ STATIC mp_obj_t set_equal(mp_obj_t self_in, mp_obj_t other_in) {
 
 STATIC mp_obj_t set_pop(mp_obj_t self_in) {
     check_set(self_in);
-    mp_obj_set_t *self = self_in;
+    mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in);
     mp_obj_t obj = mp_set_remove_first(&self->set);
     if (obj == MP_OBJ_NULL) {
         nlr_raise(mp_obj_new_exception_msg(&mp_type_KeyError, "pop from an empty set"));
@@ -412,7 +411,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(set_pop_obj, set_pop);
 
 STATIC mp_obj_t set_remove(mp_obj_t self_in, mp_obj_t item) {
     check_set(self_in);
-    mp_obj_set_t *self = self_in;
+    mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in);
     if (mp_set_lookup(&self->set, item, MP_MAP_LOOKUP_REMOVE_IF_FOUND) == MP_OBJ_NULL) {
         nlr_raise(mp_obj_new_exception(&mp_type_KeyError));
     }
@@ -422,7 +421,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_remove_obj, set_remove);
 
 STATIC mp_obj_t set_symmetric_difference_update(mp_obj_t self_in, mp_obj_t other_in) {
     check_set(self_in);
-    mp_obj_set_t *self = self_in;
+    mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in);
     mp_obj_t iter = mp_getiter(other_in);
     mp_obj_t next;
     while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) {
@@ -434,9 +433,9 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_symmetric_difference_update_obj, set_symmet
 
 STATIC mp_obj_t set_symmetric_difference(mp_obj_t self_in, mp_obj_t other_in) {
     check_set_or_frozenset(self_in);
-    mp_obj_set_t *self_out = set_copy_as_mutable(self_in);
+    mp_obj_t self_out = set_copy_as_mutable(self_in);
     set_symmetric_difference_update(self_out, other_in);
-    self_out->base.type = ((mp_obj_set_t*)self_in)->base.type;
+    ((mp_obj_base_t*)MP_OBJ_TO_PTR(self_out))->type = ((mp_obj_base_t*)MP_OBJ_TO_PTR(self_in))->type;
     return self_out;
 }
 STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_symmetric_difference_obj, set_symmetric_difference);
@@ -453,7 +452,7 @@ STATIC mp_obj_t set_update(mp_uint_t n_args, const mp_obj_t *args) {
     assert(n_args > 0);
 
     for (mp_uint_t i = 1; i < n_args; i++) {
-        set_update_int(args[0], args[i]);
+        set_update_int(MP_OBJ_TO_PTR(args[0]), args[i]);
     }
 
     return mp_const_none;
@@ -462,14 +461,14 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR(set_update_obj, 1, set_update);
 
 STATIC mp_obj_t set_union(mp_obj_t self_in, mp_obj_t other_in) {
     check_set_or_frozenset(self_in);
-    mp_obj_set_t *self = set_copy(self_in);
-    set_update_int(self, other_in);
+    mp_obj_t self = set_copy(self_in);
+    set_update_int(MP_OBJ_TO_PTR(self), other_in);
     return self;
 }
 STATIC MP_DEFINE_CONST_FUN_OBJ_2(set_union_obj, set_union);
 
 STATIC mp_obj_t set_unary_op(mp_uint_t op, mp_obj_t self_in) {
-    mp_obj_set_t *self = self_in;
+    mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in);
     switch (op) {
         case MP_UNARY_OP_BOOL: return mp_obj_new_bool(self->set.used != 0);
         case MP_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT(self->set.used);
@@ -477,7 +476,7 @@ STATIC mp_obj_t set_unary_op(mp_uint_t op, mp_obj_t self_in) {
         case MP_UNARY_OP_HASH:
             if (MP_OBJ_IS_TYPE(self_in, &mp_type_frozenset)) {
                 // start hash with unique value
-                mp_int_t hash = (mp_int_t)&mp_type_frozenset;
+                mp_int_t hash = (mp_int_t)(uintptr_t)&mp_type_frozenset;
                 mp_uint_t max = self->set.alloc;
                 mp_set_t *set = &self->set;
 
@@ -523,9 +522,9 @@ STATIC mp_obj_t set_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs) {
         case MP_BINARY_OP_MORE_EQUAL:
             return set_issuperset(lhs, rhs);
         case MP_BINARY_OP_IN: {
-            mp_obj_set_t *o = lhs;
+            mp_obj_set_t *o = MP_OBJ_TO_PTR(lhs);
             mp_obj_t elem = mp_set_lookup(&o->set, rhs, MP_MAP_LOOKUP);
-            return mp_obj_new_bool(elem != NULL);
+            return mp_obj_new_bool(elem != MP_OBJ_NULL);
         }
         default:
             return MP_OBJ_NULL; // op not supported
@@ -567,7 +566,7 @@ const mp_obj_type_t mp_type_set = {
     .unary_op = set_unary_op,
     .binary_op = set_binary_op,
     .getiter = set_getiter,
-    .locals_dict = (mp_obj_t)&set_locals_dict,
+    .locals_dict = (mp_obj_dict_t*)&set_locals_dict,
 };
 
 #if MICROPY_PY_BUILTINS_FROZENSET
@@ -579,7 +578,7 @@ const mp_obj_type_t mp_type_frozenset = {
     .unary_op = set_unary_op,
     .binary_op = set_binary_op,
     .getiter = set_getiter,
-    .locals_dict = (mp_obj_t)&set_locals_dict,
+    .locals_dict = (mp_obj_dict_t*)&set_locals_dict,
 };
 #endif
 
@@ -590,12 +589,12 @@ mp_obj_t mp_obj_new_set(mp_uint_t n_args, mp_obj_t *items) {
     for (mp_uint_t i = 0; i < n_args; i++) {
         mp_set_lookup(&o->set, items[i], MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
     }
-    return o;
+    return MP_OBJ_FROM_PTR(o);
 }
 
 void mp_obj_set_store(mp_obj_t self_in, mp_obj_t item) {
     assert(MP_OBJ_IS_TYPE(self_in, &mp_type_set));
-    mp_obj_set_t *self = self_in;
+    mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in);
     mp_set_lookup(&self->set, item, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
 }
 
diff --git a/py/objsingleton.c b/py/objsingleton.c
index 23a5cd4d6e05037b2db68b95b773851e2635ed3a..394c12767715bc92a728c2a38f019ab60f4e75e2 100644
--- a/py/objsingleton.c
+++ b/py/objsingleton.c
@@ -41,7 +41,7 @@ typedef struct _mp_obj_singleton_t {
 
 STATIC void singleton_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
     (void)kind;
-    mp_obj_singleton_t *self = self_in;
+    mp_obj_singleton_t *self = MP_OBJ_TO_PTR(self_in);
     mp_printf(print, "%q", self->name);
 }
 
diff --git a/py/objslice.c b/py/objslice.c
index d0e8e7e73e69615bb49191d559403d2e99e2605f..928be6dab1427f188fb60e25580087f8587a3680 100644
--- a/py/objslice.c
+++ b/py/objslice.c
@@ -47,7 +47,7 @@ typedef struct _mp_obj_slice_t {
 
 STATIC void slice_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
     (void)kind;
-    mp_obj_slice_t *o = o_in;
+    mp_obj_slice_t *o = MP_OBJ_TO_PTR(o_in);
     mp_print_str(print, "slice(");
     mp_obj_print_helper(print, o->start, PRINT_REPR);
     mp_print_str(print, ", ");
@@ -63,7 +63,7 @@ STATIC void slice_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
         // not load attribute
         return;
     }
-    mp_obj_slice_t *self = self_in;
+    mp_obj_slice_t *self = MP_OBJ_TO_PTR(self_in);
     if (attr == MP_QSTR_start) {
         dest[0] = self->start;
     } else if (attr == MP_QSTR_stop) {
@@ -89,12 +89,12 @@ mp_obj_t mp_obj_new_slice(mp_obj_t ostart, mp_obj_t ostop, mp_obj_t ostep) {
     o->start = ostart;
     o->stop = ostop;
     o->step = ostep;
-    return o;
+    return MP_OBJ_FROM_PTR(o);
 }
 
 void mp_obj_slice_get(mp_obj_t self_in, mp_obj_t *start, mp_obj_t *stop, mp_obj_t *step) {
     assert(MP_OBJ_IS_TYPE(self_in, &mp_type_slice));
-    mp_obj_slice_t *self = self_in;
+    mp_obj_slice_t *self = MP_OBJ_TO_PTR(self_in);
     *start = self->start;
     *stop = self->stop;
     *step = self->step;
diff --git a/py/objstr.c b/py/objstr.c
index 5fb465a6e768d432ccd243a7dfba65181908f683..7765f426d9a48ba8e75d5a97593541bd06cf498c 100644
--- a/py/objstr.c
+++ b/py/objstr.c
@@ -83,7 +83,7 @@ void mp_str_print_quoted(const mp_print_t *print, const byte *str_data, mp_uint_
 }
 
 #if MICROPY_PY_UJSON
-void mp_str_print_json(const mp_print_t *print, const byte *str_data, mp_uint_t str_len) {
+void mp_str_print_json(const mp_print_t *print, const byte *str_data, size_t str_len) {
     // for JSON spec, see http://www.ietf.org/rfc/rfc4627.txt
     // if we are given a valid utf8-encoded string, we will print it in a JSON-conforming way
     mp_print_str(print, "\"");
@@ -149,7 +149,7 @@ mp_obj_t mp_obj_str_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw,
             mp_print_t print;
             vstr_init_print(&vstr, 16, &print);
             mp_obj_print_helper(&print, args[0], PRINT_STR);
-            return mp_obj_new_str_from_vstr(type_in, &vstr);
+            return mp_obj_new_str_from_vstr(MP_OBJ_TO_PTR(type_in), &vstr);
         }
 
         default: // 2 or 3 args
@@ -157,10 +157,10 @@ mp_obj_t mp_obj_str_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw,
             if (MP_OBJ_IS_TYPE(args[0], &mp_type_bytes)) {
                 GET_STR_DATA_LEN(args[0], str_data, str_len);
                 GET_STR_HASH(args[0], str_hash);
-                mp_obj_str_t *o = mp_obj_new_str_of_type(type_in, NULL, str_len);
+                mp_obj_str_t *o = MP_OBJ_TO_PTR(mp_obj_new_str_of_type(MP_OBJ_TO_PTR(type_in), NULL, str_len));
                 o->data = str_data;
                 o->hash = str_hash;
-                return o;
+                return MP_OBJ_FROM_PTR(o);
             } else {
                 mp_buffer_info_t bufinfo;
                 mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ);
@@ -190,10 +190,10 @@ STATIC mp_obj_t bytes_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_k
         }
         GET_STR_DATA_LEN(args[0], str_data, str_len);
         GET_STR_HASH(args[0], str_hash);
-        mp_obj_str_t *o = mp_obj_new_str_of_type(&mp_type_bytes, NULL, str_len);
+        mp_obj_str_t *o = MP_OBJ_TO_PTR(mp_obj_new_str_of_type(&mp_type_bytes, NULL, str_len));
         o->data = str_data;
         o->hash = str_hash;
-        return o;
+        return MP_OBJ_FROM_PTR(o);
     }
 
     if (n_args > 1) {
@@ -376,7 +376,7 @@ mp_obj_t mp_obj_str_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
 
 #if !MICROPY_PY_BUILTINS_STR_UNICODE
 // objstrunicode defines own version
-const byte *str_index_to_ptr(const mp_obj_type_t *type, const byte *self_data, mp_uint_t self_len,
+const byte *str_index_to_ptr(const mp_obj_type_t *type, const byte *self_data, size_t self_len,
                              mp_obj_t index, bool is_slice) {
     mp_uint_t index_val = mp_get_index(type, self_len, index, is_slice);
     return self_data + index_val;
@@ -426,7 +426,7 @@ STATIC mp_obj_t str_join(mp_obj_t self_in, mp_obj_t arg) {
         if (!MP_OBJ_IS_TYPE(arg, &mp_type_list)) {
             // arg is not a list, try to convert it to one
             // TODO: Try to optimize?
-            arg = mp_type_list.make_new((mp_obj_t)&mp_type_list, 1, 0, &arg);
+            arg = mp_type_list.make_new(MP_OBJ_FROM_PTR(&mp_type_list), 1, 0, &arg);
         }
         mp_obj_list_get(arg, &seq_len, &seq_items);
     }
@@ -579,7 +579,7 @@ STATIC mp_obj_t str_rsplit(mp_uint_t n_args, const mp_obj_t *args) {
     mp_int_t org_splits = splits;
     // Preallocate list to the max expected # of elements, as we
     // will fill it from the end.
-    mp_obj_list_t *res = mp_obj_new_list(splits + 1, NULL);
+    mp_obj_list_t *res = MP_OBJ_TO_PTR(mp_obj_new_list(splits + 1, NULL));
     mp_int_t idx = splits;
 
     if (sep == mp_const_none) {
@@ -623,7 +623,7 @@ STATIC mp_obj_t str_rsplit(mp_uint_t n_args, const mp_obj_t *args) {
         }
     }
 
-    return res;
+    return MP_OBJ_FROM_PTR(res);
 }
 
 STATIC mp_obj_t str_finder(mp_uint_t n_args, const mp_obj_t *args, mp_int_t direction, bool is_index) {
@@ -1763,7 +1763,7 @@ STATIC mp_obj_t bytes_decode(mp_uint_t n_args, const mp_obj_t *args) {
         args = new_args;
         n_args++;
     }
-    return mp_obj_str_make_new((mp_obj_t)&mp_type_str, n_args, 0, args);
+    return mp_obj_str_make_new(MP_OBJ_FROM_PTR(&mp_type_str), n_args, 0, args);
 }
 
 // TODO: should accept kwargs too
@@ -1775,7 +1775,7 @@ STATIC mp_obj_t str_encode(mp_uint_t n_args, const mp_obj_t *args) {
         args = new_args;
         n_args++;
     }
-    return bytes_make_new(NULL, n_args, 0, args);
+    return bytes_make_new(MP_OBJ_NULL, n_args, 0, args);
 }
 #endif
 
@@ -1882,7 +1882,7 @@ const mp_obj_type_t mp_type_str = {
     .subscr = bytes_subscr,
     .getiter = mp_obj_new_str_iterator,
     .buffer_p = { .get_buffer = mp_obj_str_get_buffer },
-    .locals_dict = (mp_obj_t)&str8_locals_dict,
+    .locals_dict = (mp_obj_dict_t*)&str8_locals_dict,
 };
 #endif
 
@@ -1896,7 +1896,7 @@ const mp_obj_type_t mp_type_bytes = {
     .subscr = bytes_subscr,
     .getiter = mp_obj_new_bytes_iterator,
     .buffer_p = { .get_buffer = mp_obj_str_get_buffer },
-    .locals_dict = (mp_obj_t)&str8_locals_dict,
+    .locals_dict = (mp_obj_dict_t*)&str8_locals_dict,
 };
 
 // the zero-length bytes
@@ -1904,7 +1904,7 @@ const mp_obj_str_t mp_const_empty_bytes_obj = {{&mp_type_bytes}, 0, 0, NULL};
 
 // Create a str/bytes object using the given data.  New memory is allocated and
 // the data is copied across.
-mp_obj_t mp_obj_new_str_of_type(const mp_obj_type_t *type, const byte* data, mp_uint_t len) {
+mp_obj_t mp_obj_new_str_of_type(const mp_obj_type_t *type, const byte* data, size_t len) {
     mp_obj_str_t *o = m_new_obj(mp_obj_str_t);
     o->base.type = type;
     o->len = len;
@@ -1915,7 +1915,7 @@ mp_obj_t mp_obj_new_str_of_type(const mp_obj_type_t *type, const byte* data, mp_
         memcpy(p, data, len * sizeof(byte));
         p[len] = '\0'; // for now we add null for compatibility with C ASCIIZ strings
     }
-    return o;
+    return MP_OBJ_FROM_PTR(o);
 }
 
 // Create a str/bytes object from the given vstr.  The vstr buffer is resized to
@@ -1945,7 +1945,7 @@ mp_obj_t mp_obj_new_str_from_vstr(const mp_obj_type_t *type, vstr_t *vstr) {
     ((byte*)o->data)[o->len] = '\0'; // add null byte
     vstr->buf = NULL;
     vstr->alloc = 0;
-    return o;
+    return MP_OBJ_FROM_PTR(o);
 }
 
 mp_obj_t mp_obj_new_str(const char* data, mp_uint_t len, bool make_qstr_if_not_already) {
@@ -2009,7 +2009,7 @@ qstr mp_obj_str_get_qstr(mp_obj_t self_in) {
     if (MP_OBJ_IS_QSTR(self_in)) {
         return MP_OBJ_QSTR_VALUE(self_in);
     } else if (MP_OBJ_IS_TYPE(self_in, &mp_type_str)) {
-        mp_obj_str_t *self = self_in;
+        mp_obj_str_t *self = MP_OBJ_TO_PTR(self_in);
         return qstr_from_strn((char*)self->data, self->len);
     } else {
         bad_implicit_conversion(self_in);
@@ -2088,7 +2088,7 @@ STATIC mp_obj_t mp_obj_new_str_iterator(mp_obj_t str) {
 #endif
 
 STATIC mp_obj_t bytes_it_iternext(mp_obj_t self_in) {
-    mp_obj_str8_it_t *self = self_in;
+    mp_obj_str8_it_t *self = MP_OBJ_TO_PTR(self_in);
     GET_STR_DATA_LEN(self->str, str, len);
     if (self->cur < len) {
         mp_obj_t o_out = MP_OBJ_NEW_SMALL_INT(str[self->cur]);
@@ -2111,5 +2111,5 @@ mp_obj_t mp_obj_new_bytes_iterator(mp_obj_t str) {
     o->base.type = &mp_type_bytes_it;
     o->str = str;
     o->cur = 0;
-    return o;
+    return MP_OBJ_FROM_PTR(o);
 }
diff --git a/py/objstr.h b/py/objstr.h
index 2c2bdbaee36aa1c2fac786cb7e1ce1c982586f0e..d9cc85ef0b0fe64c171aa3a3101e087e6180c6de 100644
--- a/py/objstr.h
+++ b/py/objstr.h
@@ -41,12 +41,12 @@ typedef struct _mp_obj_str_t {
 // use this macro to extract the string hash
 #define GET_STR_HASH(str_obj_in, str_hash) \
     mp_uint_t str_hash; if (MP_OBJ_IS_QSTR(str_obj_in)) \
-    { str_hash = qstr_hash(MP_OBJ_QSTR_VALUE(str_obj_in)); } else { str_hash = ((mp_obj_str_t*)str_obj_in)->hash; }
+    { str_hash = qstr_hash(MP_OBJ_QSTR_VALUE(str_obj_in)); } else { str_hash = ((mp_obj_str_t*)MP_OBJ_TO_PTR(str_obj_in))->hash; }
 
 // use this macro to extract the string length
 #define GET_STR_LEN(str_obj_in, str_len) \
     size_t str_len; if (MP_OBJ_IS_QSTR(str_obj_in)) \
-    { str_len = qstr_len(MP_OBJ_QSTR_VALUE(str_obj_in)); } else { str_len = ((mp_obj_str_t*)str_obj_in)->len; }
+    { str_len = qstr_len(MP_OBJ_QSTR_VALUE(str_obj_in)); } else { str_len = ((mp_obj_str_t*)MP_OBJ_TO_PTR(str_obj_in))->len; }
 
 // use this macro to extract the string data and length
 #if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_C
@@ -57,19 +57,19 @@ const byte *mp_obj_str_get_data_no_check(mp_obj_t self_in, size_t *len);
 #define GET_STR_DATA_LEN(str_obj_in, str_data, str_len) \
     const byte *str_data; size_t str_len; if (MP_OBJ_IS_QSTR(str_obj_in)) \
     { str_data = qstr_data(MP_OBJ_QSTR_VALUE(str_obj_in), &str_len); } \
-    else { str_len = ((mp_obj_str_t*)str_obj_in)->len; str_data = ((mp_obj_str_t*)str_obj_in)->data; }
+    else { str_len = ((mp_obj_str_t*)MP_OBJ_TO_PTR(str_obj_in))->len; str_data = ((mp_obj_str_t*)MP_OBJ_TO_PTR(str_obj_in))->data; }
 #endif
 
 mp_obj_t mp_obj_str_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args);
-void mp_str_print_json(const mp_print_t *print, const byte *str_data, mp_uint_t str_len);
+void mp_str_print_json(const mp_print_t *print, const byte *str_data, size_t str_len);
 mp_obj_t mp_obj_str_format(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kwargs);
 mp_obj_t mp_obj_str_split(mp_uint_t n_args, const mp_obj_t *args);
-mp_obj_t mp_obj_new_str_of_type(const mp_obj_type_t *type, const byte* data, mp_uint_t len);
+mp_obj_t mp_obj_new_str_of_type(const mp_obj_type_t *type, const byte* data, size_t len);
 
 mp_obj_t mp_obj_str_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in);
 mp_int_t mp_obj_str_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags);
 
-const byte *str_index_to_ptr(const mp_obj_type_t *type, const byte *self_data, mp_uint_t self_len,
+const byte *str_index_to_ptr(const mp_obj_type_t *type, const byte *self_data, size_t self_len,
                              mp_obj_t index, bool is_slice);
 
 MP_DECLARE_CONST_FUN_OBJ(str_encode_obj);
diff --git a/py/objstringio.c b/py/objstringio.c
index d0c0a4f4e29665089660e1ce76370a2ad18f6eb8..5a8f43da13098d146b7fa7c3ba4cae970f0ff22a 100644
--- a/py/objstringio.c
+++ b/py/objstringio.c
@@ -54,13 +54,13 @@ STATIC void check_stringio_is_open(const mp_obj_stringio_t *o) {
 
 STATIC void stringio_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
     (void)kind;
-    mp_obj_stringio_t *self = self_in;
+    mp_obj_stringio_t *self = MP_OBJ_TO_PTR(self_in);
     mp_printf(print, self->base.type == &mp_type_stringio ? "<io.StringIO 0x%x>" : "<io.BytesIO 0x%x>", self);
 }
 
 STATIC mp_uint_t stringio_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) {
     (void)errcode;
-    mp_obj_stringio_t *o = o_in;
+    mp_obj_stringio_t *o = MP_OBJ_TO_PTR(o_in);
     check_stringio_is_open(o);
     mp_uint_t remaining = o->vstr->len - o->pos;
     if (size > remaining) {
@@ -73,7 +73,7 @@ STATIC mp_uint_t stringio_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *er
 
 STATIC mp_uint_t stringio_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) {
     (void)errcode;
-    mp_obj_stringio_t *o = o_in;
+    mp_obj_stringio_t *o = MP_OBJ_TO_PTR(o_in);
     check_stringio_is_open(o);
     mp_uint_t remaining = o->vstr->alloc - o->pos;
     if (size > remaining) {
@@ -93,14 +93,14 @@ STATIC mp_uint_t stringio_write(mp_obj_t o_in, const void *buf, mp_uint_t size,
 #define STREAM_TO_CONTENT_TYPE(o) (((o)->base.type == &mp_type_stringio) ? &mp_type_str : &mp_type_bytes)
 
 STATIC mp_obj_t stringio_getvalue(mp_obj_t self_in) {
-    mp_obj_stringio_t *self = self_in;
+    mp_obj_stringio_t *self = MP_OBJ_TO_PTR(self_in);
     check_stringio_is_open(self);
     return mp_obj_new_str_of_type(STREAM_TO_CONTENT_TYPE(self), (byte*)self->vstr->buf, self->vstr->len);
 }
 STATIC MP_DEFINE_CONST_FUN_OBJ_1(stringio_getvalue_obj, stringio_getvalue);
 
 STATIC mp_obj_t stringio_close(mp_obj_t self_in) {
-    mp_obj_stringio_t *self = self_in;
+    mp_obj_stringio_t *self = MP_OBJ_TO_PTR(self_in);
 #if MICROPY_CPYTHON_COMPAT
     vstr_free(self->vstr);
     self->vstr = NULL;
@@ -122,7 +122,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(stringio___exit___obj, 4, 4, stringio
 
 STATIC mp_obj_stringio_t *stringio_new(mp_obj_t type_in) {
     mp_obj_stringio_t *o = m_new_obj(mp_obj_stringio_t);
-    o->base.type = type_in;
+    o->base.type = MP_OBJ_TO_PTR(type_in);
     o->vstr = vstr_new();
     o->pos = 0;
     return o;
@@ -135,11 +135,11 @@ STATIC mp_obj_t stringio_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t
     if (n_args > 0) {
         mp_buffer_info_t bufinfo;
         mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ);
-        stringio_write(o, bufinfo.buf, bufinfo.len, NULL);
+        stringio_write(MP_OBJ_FROM_PTR(o), bufinfo.buf, bufinfo.len, NULL);
         // Cur ptr is always at the beginning of buffer at the construction
         o->pos = 0;
     }
-    return o;
+    return MP_OBJ_FROM_PTR(o);
 }
 
 STATIC const mp_rom_map_elem_t stringio_locals_dict_table[] = {
@@ -174,7 +174,7 @@ const mp_obj_type_t mp_type_stringio = {
     .getiter = mp_identity,
     .iternext = mp_stream_unbuffered_iter,
     .stream_p = &stringio_stream_p,
-    .locals_dict = (mp_obj_t)&stringio_locals_dict,
+    .locals_dict = (mp_obj_dict_t*)&stringio_locals_dict,
 };
 
 #if MICROPY_PY_IO_BYTESIO
@@ -186,7 +186,7 @@ const mp_obj_type_t mp_type_bytesio = {
     .getiter = mp_identity,
     .iternext = mp_stream_unbuffered_iter,
     .stream_p = &bytesio_stream_p,
-    .locals_dict = (mp_obj_t)&stringio_locals_dict,
+    .locals_dict = (mp_obj_dict_t*)&stringio_locals_dict,
 };
 #endif
 
diff --git a/py/objstrunicode.c b/py/objstrunicode.c
index 50916c34b9b0efd98739409cc50d5b823274deea..fb3d5200747ba81bc51bfb929ca4b685b03793cf 100644
--- a/py/objstrunicode.c
+++ b/py/objstrunicode.c
@@ -114,7 +114,7 @@ STATIC mp_obj_t uni_unary_op(mp_uint_t op, mp_obj_t self_in) {
 
 // Convert an index into a pointer to its lead byte. Out of bounds indexing will raise IndexError or
 // be capped to the first/last character of the string, depending on is_slice.
-const byte *str_index_to_ptr(const mp_obj_type_t *type, const byte *self_data, mp_uint_t self_len,
+const byte *str_index_to_ptr(const mp_obj_type_t *type, const byte *self_data, size_t self_len,
                              mp_obj_t index, bool is_slice) {
     (void)type;
     mp_int_t i;
@@ -259,7 +259,7 @@ const mp_obj_type_t mp_type_str = {
     .subscr = str_subscr,
     .getiter = mp_obj_new_str_iterator,
     .buffer_p = { .get_buffer = mp_obj_str_get_buffer },
-    .locals_dict = (mp_obj_t)&struni_locals_dict,
+    .locals_dict = (mp_obj_dict_t*)&struni_locals_dict,
 };
 
 /******************************************************************************/
@@ -272,7 +272,7 @@ typedef struct _mp_obj_str_it_t {
 } mp_obj_str_it_t;
 
 STATIC mp_obj_t str_it_iternext(mp_obj_t self_in) {
-    mp_obj_str_it_t *self = self_in;
+    mp_obj_str_it_t *self = MP_OBJ_TO_PTR(self_in);
     GET_STR_DATA_LEN(self->str, str, len);
     if (self->cur < len) {
         const byte *cur = str + self->cur;
@@ -297,7 +297,7 @@ STATIC mp_obj_t mp_obj_new_str_iterator(mp_obj_t str) {
     o->base.type = &mp_type_str_it;
     o->str = str;
     o->cur = 0;
-    return o;
+    return MP_OBJ_FROM_PTR(o);
 }
 
 #endif // MICROPY_PY_BUILTINS_STR_UNICODE
diff --git a/py/objtuple.c b/py/objtuple.c
index 1734721d79cbb314bfc97f60bc87f045fdb5adb5..71cb458f95330399e2fce8707959960848dd04d8 100644
--- a/py/objtuple.c
+++ b/py/objtuple.c
@@ -38,7 +38,7 @@ STATIC mp_obj_t mp_obj_new_tuple_iterator(mp_obj_tuple_t *tuple, mp_uint_t cur);
 /* tuple                                                                      */
 
 void mp_obj_tuple_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
-    mp_obj_tuple_t *o = o_in;
+    mp_obj_tuple_t *o = MP_OBJ_TO_PTR(o_in);
     if (MICROPY_PY_UJSON && kind == PRINT_JSON) {
         mp_print_str(print, "[");
     } else {
@@ -109,21 +109,21 @@ STATIC bool tuple_cmp_helper(mp_uint_t op, mp_obj_t self_in, mp_obj_t another_in
         assert(0);
     }
     mp_obj_type_t *another_type = mp_obj_get_type(another_in);
-    mp_obj_tuple_t *self = self_in;
-    mp_obj_tuple_t *another = another_in;
+    mp_obj_tuple_t *self = MP_OBJ_TO_PTR(self_in);
     if (another_type->getiter != mp_obj_tuple_getiter) {
         // Slow path for user subclasses
-        another = mp_instance_cast_to_native_base(another, &mp_type_tuple);
-        if (another == MP_OBJ_NULL) {
+        another_in = mp_instance_cast_to_native_base(another_in, MP_OBJ_FROM_PTR(&mp_type_tuple));
+        if (another_in == MP_OBJ_NULL) {
             return false;
         }
     }
+    mp_obj_tuple_t *another = MP_OBJ_TO_PTR(another_in);
 
     return mp_seq_cmp_objs(op, self->items, self->len, another->items, another->len);
 }
 
 mp_obj_t mp_obj_tuple_unary_op(mp_uint_t op, mp_obj_t self_in) {
-    mp_obj_tuple_t *self = self_in;
+    mp_obj_tuple_t *self = MP_OBJ_TO_PTR(self_in);
     switch (op) {
         case MP_UNARY_OP_BOOL: return mp_obj_new_bool(self->len != 0);
         case MP_UNARY_OP_HASH: {
@@ -140,16 +140,16 @@ mp_obj_t mp_obj_tuple_unary_op(mp_uint_t op, mp_obj_t self_in) {
 }
 
 mp_obj_t mp_obj_tuple_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs) {
-    mp_obj_tuple_t *o = lhs;
+    mp_obj_tuple_t *o = MP_OBJ_TO_PTR(lhs);
     switch (op) {
         case MP_BINARY_OP_ADD: {
-            if (!mp_obj_is_subclass_fast(mp_obj_get_type(rhs), (mp_obj_t)&mp_type_tuple)) {
+            if (!mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(mp_obj_get_type(rhs)), MP_OBJ_FROM_PTR(&mp_type_tuple))) {
                 return MP_OBJ_NULL; // op not supported
             }
-            mp_obj_tuple_t *p = rhs;
-            mp_obj_tuple_t *s = mp_obj_new_tuple(o->len + p->len, NULL);
+            mp_obj_tuple_t *p = MP_OBJ_TO_PTR(rhs);
+            mp_obj_tuple_t *s = MP_OBJ_TO_PTR(mp_obj_new_tuple(o->len + p->len, NULL));
             mp_seq_cat(s->items, o->items, o->len, p->items, p->len, mp_obj_t);
-            return s;
+            return MP_OBJ_FROM_PTR(s);
         }
         case MP_BINARY_OP_MULTIPLY: {
             mp_int_t n;
@@ -159,9 +159,9 @@ mp_obj_t mp_obj_tuple_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs) {
             if (n <= 0) {
                 return mp_const_empty_tuple;
             }
-            mp_obj_tuple_t *s = mp_obj_new_tuple(o->len * n, NULL);
+            mp_obj_tuple_t *s = MP_OBJ_TO_PTR(mp_obj_new_tuple(o->len * n, NULL));
             mp_seq_multiply(o->items, sizeof(*o->items), o->len, n, s->items);
-            return s;
+            return MP_OBJ_FROM_PTR(s);
         }
         case MP_BINARY_OP_EQUAL:
         case MP_BINARY_OP_LESS:
@@ -178,16 +178,16 @@ mp_obj_t mp_obj_tuple_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs) {
 mp_obj_t mp_obj_tuple_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
     if (value == MP_OBJ_SENTINEL) {
         // load
-        mp_obj_tuple_t *self = self_in;
+        mp_obj_tuple_t *self = MP_OBJ_TO_PTR(self_in);
 #if MICROPY_PY_BUILTINS_SLICE
         if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) {
             mp_bound_slice_t slice;
             if (!mp_seq_get_fast_slice_indexes(self->len, index, &slice)) {
                 mp_not_implemented("only slices with step=1 (aka None) are supported");
             }
-            mp_obj_tuple_t *res = mp_obj_new_tuple(slice.stop - slice.start, NULL);
+            mp_obj_tuple_t *res = MP_OBJ_TO_PTR(mp_obj_new_tuple(slice.stop - slice.start, NULL));
             mp_seq_copy(res->items, self->items + slice.start, res->len, mp_obj_t);
-            return res;
+            return MP_OBJ_FROM_PTR(res);
         }
 #endif
         mp_uint_t index_value = mp_get_index(self->base.type, self->len, index, false);
@@ -198,19 +198,19 @@ mp_obj_t mp_obj_tuple_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
 }
 
 mp_obj_t mp_obj_tuple_getiter(mp_obj_t o_in) {
-    return mp_obj_new_tuple_iterator(o_in, 0);
+    return mp_obj_new_tuple_iterator(MP_OBJ_TO_PTR(o_in), 0);
 }
 
 STATIC mp_obj_t tuple_count(mp_obj_t self_in, mp_obj_t value) {
     assert(MP_OBJ_IS_TYPE(self_in, &mp_type_tuple));
-    mp_obj_tuple_t *self = self_in;
+    mp_obj_tuple_t *self = MP_OBJ_TO_PTR(self_in);
     return mp_seq_count_obj(self->items, self->len, value);
 }
 STATIC MP_DEFINE_CONST_FUN_OBJ_2(tuple_count_obj, tuple_count);
 
 STATIC mp_obj_t tuple_index(mp_uint_t n_args, const mp_obj_t *args) {
     assert(MP_OBJ_IS_TYPE(args[0], &mp_type_tuple));
-    mp_obj_tuple_t *self = args[0];
+    mp_obj_tuple_t *self = MP_OBJ_TO_PTR(args[0]);
     return mp_seq_index_obj(self->items, self->len, n_args, args);
 }
 STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(tuple_index_obj, 2, 4, tuple_index);
@@ -231,7 +231,7 @@ const mp_obj_type_t mp_type_tuple = {
     .binary_op = mp_obj_tuple_binary_op,
     .subscr = mp_obj_tuple_subscr,
     .getiter = mp_obj_tuple_getiter,
-    .locals_dict = (mp_obj_t)&tuple_locals_dict,
+    .locals_dict = (mp_obj_dict_t*)&tuple_locals_dict,
 };
 
 // the zero-length tuple
@@ -249,19 +249,19 @@ mp_obj_t mp_obj_new_tuple(mp_uint_t n, const mp_obj_t *items) {
             o->items[i] = items[i];
         }
     }
-    return o;
+    return MP_OBJ_FROM_PTR(o);
 }
 
 void mp_obj_tuple_get(mp_obj_t self_in, mp_uint_t *len, mp_obj_t **items) {
     assert(MP_OBJ_IS_TYPE(self_in, &mp_type_tuple));
-    mp_obj_tuple_t *self = self_in;
+    mp_obj_tuple_t *self = MP_OBJ_TO_PTR(self_in);
     *len = self->len;
     *items = &self->items[0];
 }
 
 void mp_obj_tuple_del(mp_obj_t self_in) {
     assert(MP_OBJ_IS_TYPE(self_in, &mp_type_tuple));
-    mp_obj_tuple_t *self = self_in;
+    mp_obj_tuple_t *self = MP_OBJ_TO_PTR(self_in);
     m_del_var(mp_obj_tuple_t, mp_obj_t, self->len, self);
 }
 
@@ -275,7 +275,7 @@ typedef struct _mp_obj_tuple_it_t {
 } mp_obj_tuple_it_t;
 
 STATIC mp_obj_t tuple_it_iternext(mp_obj_t self_in) {
-    mp_obj_tuple_it_t *self = self_in;
+    mp_obj_tuple_it_t *self = MP_OBJ_TO_PTR(self_in);
     if (self->cur < self->tuple->len) {
         mp_obj_t o_out = self->tuple->items[self->cur];
         self->cur += 1;
@@ -297,5 +297,5 @@ STATIC mp_obj_t mp_obj_new_tuple_iterator(mp_obj_tuple_t *tuple, mp_uint_t cur)
     o->base.type = &mp_type_tuple_it;
     o->tuple = tuple;
     o->cur = cur;
-    return o;
+    return MP_OBJ_FROM_PTR(o);
 }
diff --git a/py/objtype.c b/py/objtype.c
index 06a067dcdc0ad2e20044eec82cc40466b265f0c0..db99d407acfcd5b6c176abe1184f101a5a0c8615 100644
--- a/py/objtype.c
+++ b/py/objtype.c
@@ -50,21 +50,20 @@ STATIC mp_obj_t static_class_method_make_new(mp_obj_t self_in, mp_uint_t n_args,
 
 STATIC mp_obj_t mp_obj_new_instance(mp_obj_t class, uint subobjs) {
     mp_obj_instance_t *o = m_new_obj_var(mp_obj_instance_t, mp_obj_t, subobjs);
-    o->base.type = class;
+    o->base.type = MP_OBJ_TO_PTR(class);
     mp_map_init(&o->members, 0);
     mp_seq_clear(o->subobj, 0, subobjs, sizeof(*o->subobj));
-    return o;
+    return MP_OBJ_FROM_PTR(o);
 }
 
 STATIC int instance_count_native_bases(const mp_obj_type_t *type, const mp_obj_type_t **last_native_base) {
-    mp_uint_t len;
-    mp_obj_t *items;
-    mp_obj_tuple_get(type->bases_tuple, &len, &items);
+    mp_uint_t len = type->bases_tuple->len;
+    mp_obj_t *items = type->bases_tuple->items;
 
     int count = 0;
     for (uint i = 0; i < len; i++) {
         assert(MP_OBJ_IS_TYPE(items[i], &mp_type_type));
-        const mp_obj_type_t *bt = (const mp_obj_type_t *)items[i];
+        const mp_obj_type_t *bt = (const mp_obj_type_t *)MP_OBJ_TO_PTR(items[i]);
         if (bt == &mp_type_object) {
             // Not a "real" type
             continue;
@@ -103,8 +102,8 @@ struct class_lookup_data {
 };
 
 STATIC void mp_obj_class_lookup(struct class_lookup_data  *lookup, const mp_obj_type_t *type) {
-    assert(lookup->dest[0] == NULL);
-    assert(lookup->dest[1] == NULL);
+    assert(lookup->dest[0] == MP_OBJ_NULL);
+    assert(lookup->dest[1] == MP_OBJ_NULL);
     for (;;) {
         // Optimize special method lookup for native types
         // This avoids extra method_name => slot lookup. On the other hand,
@@ -120,22 +119,25 @@ STATIC void mp_obj_class_lookup(struct class_lookup_data  *lookup, const mp_obj_
 
         if (type->locals_dict != NULL) {
             // search locals_dict (the set of methods/attributes)
-            assert(MP_OBJ_IS_TYPE(type->locals_dict, &mp_type_dict)); // Micro Python restriction, for now
-            mp_map_t *locals_map = mp_obj_dict_get_map(type->locals_dict);
+            assert(type->locals_dict->base.type == &mp_type_dict); // MicroPython restriction, for now
+            mp_map_t *locals_map = &type->locals_dict->map;
             mp_map_elem_t *elem = mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(lookup->attr), MP_MAP_LOOKUP);
             if (elem != NULL) {
                 if (lookup->is_type) {
                     // If we look up a class method, we need to return original type for which we
                     // do a lookup, not a (base) type in which we found the class method.
                     const mp_obj_type_t *org_type = (const mp_obj_type_t*)lookup->obj;
-                    mp_convert_member_lookup(NULL, org_type, elem->value, lookup->dest);
+                    mp_convert_member_lookup(MP_OBJ_NULL, org_type, elem->value, lookup->dest);
                 } else {
                     mp_obj_instance_t *obj = lookup->obj;
-                    if (obj != MP_OBJ_NULL && mp_obj_is_native_type(type) && type != &mp_type_object /* object is not a real type */) {
+                    mp_obj_t obj_obj;
+                    if (obj != NULL && mp_obj_is_native_type(type) && type != &mp_type_object /* object is not a real type */) {
                         // If we're dealing with native base class, then it applies to native sub-object
-                        obj = obj->subobj[0];
+                        obj_obj = obj->subobj[0];
+                    } else {
+                        obj_obj = MP_OBJ_FROM_PTR(obj);
                     }
-                    mp_convert_member_lookup(obj, type, elem->value, lookup->dest);
+                    mp_convert_member_lookup(obj_obj, type, elem->value, lookup->dest);
                 }
 #if DEBUG_PRINT
                 printf("mp_obj_class_lookup: Returning: ");
@@ -149,7 +151,7 @@ STATIC void mp_obj_class_lookup(struct class_lookup_data  *lookup, const mp_obj_
         // Previous code block takes care about attributes defined in .locals_dict,
         // but some attributes of native types may be handled using .load_attr method,
         // so make sure we try to lookup those too.
-        if (lookup->obj != MP_OBJ_NULL && !lookup->is_type && mp_obj_is_native_type(type) && type != &mp_type_object /* object is not a real type */) {
+        if (lookup->obj != NULL && !lookup->is_type && mp_obj_is_native_type(type) && type != &mp_type_object /* object is not a real type */) {
             mp_load_method_maybe(lookup->obj->subobj[0], lookup->attr, lookup->dest);
             if (lookup->dest[0] != MP_OBJ_NULL) {
                 return;
@@ -159,19 +161,18 @@ STATIC void mp_obj_class_lookup(struct class_lookup_data  *lookup, const mp_obj_
         // attribute not found, keep searching base classes
 
         // for a const struct, this entry might be NULL
-        if (type->bases_tuple == MP_OBJ_NULL) {
+        if (type->bases_tuple == NULL) {
             return;
         }
 
-        mp_uint_t len;
-        mp_obj_t *items;
-        mp_obj_tuple_get(type->bases_tuple, &len, &items);
+        mp_uint_t len = type->bases_tuple->len;
+        mp_obj_t *items = type->bases_tuple->items;
         if (len == 0) {
             return;
         }
         for (uint i = 0; i < len - 1; i++) {
             assert(MP_OBJ_IS_TYPE(items[i], &mp_type_type));
-            mp_obj_type_t *bt = (mp_obj_type_t*)items[i];
+            mp_obj_type_t *bt = (mp_obj_type_t*)MP_OBJ_TO_PTR(items[i]);
             if (bt == &mp_type_object) {
                 // Not a "real" type
                 continue;
@@ -184,7 +185,7 @@ STATIC void mp_obj_class_lookup(struct class_lookup_data  *lookup, const mp_obj_
 
         // search last base (simple tail recursion elimination)
         assert(MP_OBJ_IS_TYPE(items[len - 1], &mp_type_type));
-        type = (mp_obj_type_t*)items[len - 1];
+        type = (mp_obj_type_t*)MP_OBJ_TO_PTR(items[len - 1]);
         if (type == &mp_type_object) {
             // Not a "real" type
             return;
@@ -193,7 +194,7 @@ STATIC void mp_obj_class_lookup(struct class_lookup_data  *lookup, const mp_obj_
 }
 
 STATIC void instance_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
-    mp_obj_instance_t *self = self_in;
+    mp_obj_instance_t *self = MP_OBJ_TO_PTR(self_in);
     qstr meth = (kind == PRINT_STR) ? MP_QSTR___str__ : MP_QSTR___repr__;
     mp_obj_t member[2] = {MP_OBJ_NULL};
     struct class_lookup_data lookup = {
@@ -236,21 +237,21 @@ STATIC void instance_print(const mp_print_t *print, mp_obj_t self_in, mp_print_k
 
 mp_obj_t mp_obj_instance_make_new(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
     assert(MP_OBJ_IS_TYPE(self_in, &mp_type_type));
-    mp_obj_type_t *self = self_in;
+    mp_obj_type_t *self = MP_OBJ_TO_PTR(self_in);
     assert(mp_obj_is_instance_type(self));
 
     const mp_obj_type_t *native_base;
     uint num_native_bases = instance_count_native_bases(self, &native_base);
     assert(num_native_bases < 2);
 
-    mp_obj_instance_t *o = mp_obj_new_instance(self_in, num_native_bases);
+    mp_obj_instance_t *o = MP_OBJ_TO_PTR(mp_obj_new_instance(self_in, num_native_bases));
 
     // This executes only "__new__" part of obejection creation.
     // TODO: This won't work will for classes with native bases.
     // TODO: This is hack, should be resolved along the lines of
     // https://github.com/micropython/micropython/issues/606#issuecomment-43685883
     if (n_args == 1 && *args == MP_OBJ_SENTINEL) {
-        return o;
+        return MP_OBJ_FROM_PTR(o);
     }
 
     // look for __new__ function
@@ -264,11 +265,11 @@ mp_obj_t mp_obj_instance_make_new(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t
     };
     mp_obj_class_lookup(&lookup, self);
 
-    mp_obj_t new_ret = o;
+    mp_obj_t new_ret = MP_OBJ_FROM_PTR(o);
     if (init_fn[0] == MP_OBJ_SENTINEL) {
         // Native type's constructor is what wins - it gets all our arguments,
         // and none Python classes are initialized at all.
-        o->subobj[0] = native_base->make_new((mp_obj_type_t*)native_base, n_args, n_kw, args);
+        o->subobj[0] = native_base->make_new(MP_OBJ_FROM_PTR(native_base), n_args, n_kw, args);
     } else if (init_fn[0] != MP_OBJ_NULL) {
         // now call Python class __new__ function with all args
         if (n_args == 0 && n_kw == 0) {
@@ -285,11 +286,11 @@ mp_obj_t mp_obj_instance_make_new(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t
 
     // https://docs.python.org/3.4/reference/datamodel.html#object.__new__
     // "If __new__() does not return an instance of cls, then the new instance’s __init__() method will not be invoked."
-    if (mp_obj_get_type(new_ret) != self_in) {
+    if (mp_obj_get_type(new_ret) != self) {
         return new_ret;
     }
 
-    o = new_ret;
+    o = MP_OBJ_TO_PTR(new_ret);
 
     // now call Python class __init__ function with all args
     init_fn[0] = init_fn[1] = MP_OBJ_NULL;
@@ -321,7 +322,7 @@ mp_obj_t mp_obj_instance_make_new(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t
 
     }
 
-    return o;
+    return MP_OBJ_FROM_PTR(o);
 }
 
 const qstr mp_unary_op_method_name[] = {
@@ -337,7 +338,7 @@ const qstr mp_unary_op_method_name[] = {
 };
 
 STATIC mp_obj_t instance_unary_op(mp_uint_t op, mp_obj_t self_in) {
-    mp_obj_instance_t *self = self_in;
+    mp_obj_instance_t *self = MP_OBJ_TO_PTR(self_in);
     qstr op_name = mp_unary_op_method_name[op];
     /* Still try to lookup native slot
     if (op_name == 0) {
@@ -433,7 +434,7 @@ const qstr mp_binary_op_method_name[] = {
 STATIC mp_obj_t instance_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
     // Note: For ducktyping, CPython does not look in the instance members or use
     // __getattr__ or __getattribute__.  It only looks in the class dictionary.
-    mp_obj_instance_t *lhs = lhs_in;
+    mp_obj_instance_t *lhs = MP_OBJ_TO_PTR(lhs_in);
     qstr op_name = mp_binary_op_method_name[op];
     /* Still try to lookup native slot
     if (op_name == 0) {
@@ -462,7 +463,7 @@ STATIC mp_obj_t instance_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_i
 STATIC void mp_obj_instance_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
     // logic: look in instance members then class locals
     assert(mp_obj_is_instance_type(mp_obj_get_type(self_in)));
-    mp_obj_instance_t *self = self_in;
+    mp_obj_instance_t *self = MP_OBJ_TO_PTR(self_in);
 
     mp_map_elem_t *elem = mp_map_lookup(&self->members, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP);
     if (elem != NULL) {
@@ -510,7 +511,7 @@ STATIC void mp_obj_instance_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *des
         mp_load_method_maybe(member, MP_QSTR___get__, attr_get_method);
         if (attr_get_method[0] != MP_OBJ_NULL) {
             attr_get_method[2] = self_in;
-            attr_get_method[3] = mp_obj_get_type(self_in);
+            attr_get_method[3] = MP_OBJ_FROM_PTR(mp_obj_get_type(self_in));
             dest[0] = mp_call_method_n_kw(2, 0, attr_get_method);
         }
         #endif
@@ -532,7 +533,7 @@ STATIC void mp_obj_instance_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *des
 }
 
 STATIC bool mp_obj_instance_store_attr(mp_obj_t self_in, qstr attr, mp_obj_t value) {
-    mp_obj_instance_t *self = self_in;
+    mp_obj_instance_t *self = MP_OBJ_TO_PTR(self_in);
 
     #if MICROPY_PY_BUILTINS_PROPERTY || MICROPY_PY_DESCRIPTORS
     // With property and/or descriptors enabled we need to do a lookup
@@ -632,7 +633,7 @@ void mp_obj_instance_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
 }
 
 STATIC mp_obj_t instance_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
-    mp_obj_instance_t *self = self_in;
+    mp_obj_instance_t *self = MP_OBJ_TO_PTR(self_in);
     mp_obj_t member[2] = {MP_OBJ_NULL};
     struct class_lookup_data lookup = {
         .obj = self,
@@ -674,7 +675,7 @@ STATIC mp_obj_t instance_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value
 }
 
 STATIC mp_obj_t mp_obj_instance_get_call(mp_obj_t self_in) {
-    mp_obj_instance_t *self = self_in;
+    mp_obj_instance_t *self = MP_OBJ_TO_PTR(self_in);
     mp_obj_t member[2] = {MP_OBJ_NULL, MP_OBJ_NULL};
     struct class_lookup_data lookup = {
         .obj = self,
@@ -702,16 +703,16 @@ mp_obj_t mp_obj_instance_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw
                 "'%s' object is not callable", mp_obj_get_type_str(self_in)));
         }
     }
-    mp_obj_instance_t *self = self_in;
+    mp_obj_instance_t *self = MP_OBJ_TO_PTR(self_in);
     if (call == MP_OBJ_SENTINEL) {
         return mp_call_function_n_kw(self->subobj[0], n_args, n_kw, args);
     }
-    mp_obj_t meth = mp_obj_new_bound_meth(call, self);
+    mp_obj_t meth = mp_obj_new_bound_meth(call, self_in);
     return mp_call_function_n_kw(meth, n_args, n_kw, args);
 }
 
 STATIC mp_obj_t instance_getiter(mp_obj_t self_in) {
-    mp_obj_instance_t *self = self_in;
+    mp_obj_instance_t *self = MP_OBJ_TO_PTR(self_in);
     mp_obj_t member[2] = {MP_OBJ_NULL};
     struct class_lookup_data lookup = {
         .obj = self,
@@ -732,7 +733,7 @@ STATIC mp_obj_t instance_getiter(mp_obj_t self_in) {
 }
 
 STATIC mp_int_t instance_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) {
-    mp_obj_instance_t *self = self_in;
+    mp_obj_instance_t *self = MP_OBJ_TO_PTR(self_in);
     mp_obj_t member[2] = {MP_OBJ_NULL};
     struct class_lookup_data lookup = {
         .obj = self,
@@ -758,7 +759,7 @@ STATIC mp_int_t instance_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo,
 
 STATIC void type_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
     (void)kind;
-    mp_obj_type_t *self = self_in;
+    mp_obj_type_t *self = MP_OBJ_TO_PTR(self_in);
     mp_printf(print, "<class '%q'>", self->name);
 }
 
@@ -769,7 +770,7 @@ STATIC mp_obj_t type_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw
 
     switch (n_args) {
         case 1:
-            return mp_obj_get_type(args[0]);
+            return MP_OBJ_FROM_PTR(mp_obj_get_type(args[0]));
 
         case 3:
             // args[0] = name
@@ -785,7 +786,7 @@ STATIC mp_obj_t type_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw
 STATIC mp_obj_t type_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
     // instantiate an instance of a class
 
-    mp_obj_type_t *self = self_in;
+    mp_obj_type_t *self = MP_OBJ_TO_PTR(self_in);
 
     if (self->make_new == NULL) {
         if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
@@ -797,7 +798,7 @@ STATIC mp_obj_t type_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, co
     }
 
     // make new instance
-    mp_obj_t o = self->make_new(self, n_args, n_kw, args);
+    mp_obj_t o = self->make_new(self_in, n_args, n_kw, args);
 
     // return new instance
     return o;
@@ -805,7 +806,7 @@ STATIC mp_obj_t type_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, co
 
 STATIC void type_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
     assert(MP_OBJ_IS_TYPE(self_in, &mp_type_type));
-    mp_obj_type_t *self = self_in;
+    mp_obj_type_t *self = MP_OBJ_TO_PTR(self_in);
 
     if (dest[0] == MP_OBJ_NULL) {
         // load attribute
@@ -816,7 +817,7 @@ STATIC void type_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
         }
         #endif
         struct class_lookup_data lookup = {
-            .obj = self_in,
+            .obj = (mp_obj_instance_t*)self,
             .attr = attr,
             .meth_offset = 0,
             .dest = dest,
@@ -829,8 +830,8 @@ STATIC void type_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
         // TODO CPython allows STORE_ATTR to a class, but is this the correct implementation?
 
         if (self->locals_dict != NULL) {
-            assert(MP_OBJ_IS_TYPE(self->locals_dict, &mp_type_dict)); // Micro Python restriction, for now
-            mp_map_t *locals_map = mp_obj_dict_get_map(self->locals_dict);
+            assert(self->locals_dict->base.type == &mp_type_dict); // MicroPython restriction, for now
+            mp_map_t *locals_map = &self->locals_dict->map;
             if (dest[1] == MP_OBJ_NULL) {
                 // delete attribute
                 mp_map_elem_t *elem = mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP_REMOVE_IF_FOUND);
@@ -873,7 +874,7 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict)
     mp_obj_tuple_get(bases_tuple, &len, &items);
     for (uint i = 0; i < len; i++) {
         assert(MP_OBJ_IS_TYPE(items[i], &mp_type_type));
-        mp_obj_type_t *t = items[i];
+        mp_obj_type_t *t = MP_OBJ_TO_PTR(items[i]);
         // TODO: Verify with CPy, tested on function type
         if (t->make_new == NULL) {
             if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
@@ -900,8 +901,8 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict)
     //o->iternext = ; not implemented
     o->buffer_p.get_buffer = instance_get_buffer;
     //o->stream_p = ; not implemented
-    o->bases_tuple = bases_tuple;
-    o->locals_dict = locals_dict;
+    o->bases_tuple = MP_OBJ_TO_PTR(bases_tuple);
+    o->locals_dict = MP_OBJ_TO_PTR(locals_dict);
 
     const mp_obj_type_t *native_base;
     uint num_native_bases = instance_count_native_bases(o, &native_base);
@@ -909,17 +910,17 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict)
         nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "multiple bases have instance lay-out conflict"));
     }
 
-    mp_map_t *locals_map = mp_obj_dict_get_map(o->locals_dict);
+    mp_map_t *locals_map = &o->locals_dict->map;
     mp_map_elem_t *elem = mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(MP_QSTR___new__), MP_MAP_LOOKUP);
     if (elem != NULL) {
         // __new__ slot exists; check if it is a function
         if (MP_OBJ_IS_FUN(elem->value)) {
             // __new__ is a function, wrap it in a staticmethod decorator
-            elem->value = static_class_method_make_new((mp_obj_t)&mp_type_staticmethod, 1, 0, &elem->value);
+            elem->value = static_class_method_make_new(MP_OBJ_FROM_PTR(&mp_type_staticmethod), 1, 0, &elem->value);
         }
     }
 
-    return o;
+    return MP_OBJ_FROM_PTR(o);
 }
 
 /******************************************************************************/
@@ -933,7 +934,7 @@ typedef struct _mp_obj_super_t {
 
 STATIC void super_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
     (void)kind;
-    mp_obj_super_t *self = self_in;
+    mp_obj_super_t *self = MP_OBJ_TO_PTR(self_in);
     mp_print_str(print, "<super: ");
     mp_obj_print_helper(print, self->type, PRINT_STR);
     mp_print_str(print, ", ");
@@ -956,22 +957,21 @@ STATIC void super_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
     }
 
     assert(MP_OBJ_IS_TYPE(self_in, &mp_type_super));
-    mp_obj_super_t *self = self_in;
+    mp_obj_super_t *self = MP_OBJ_TO_PTR(self_in);
 
     assert(MP_OBJ_IS_TYPE(self->type, &mp_type_type));
 
-    mp_obj_type_t *type = self->type;
+    mp_obj_type_t *type = MP_OBJ_TO_PTR(self->type);
 
     // for a const struct, this entry might be NULL
-    if (type->bases_tuple == MP_OBJ_NULL) {
+    if (type->bases_tuple == NULL) {
         return;
     }
 
-    mp_uint_t len;
-    mp_obj_t *items;
-    mp_obj_tuple_get(type->bases_tuple, &len, &items);
+    mp_uint_t len = type->bases_tuple->len;
+    mp_obj_t *items = type->bases_tuple->items;
     struct class_lookup_data lookup = {
-        .obj = self->obj,
+        .obj = MP_OBJ_TO_PTR(self->obj),
         .attr = attr,
         .meth_offset = 0,
         .dest = dest,
@@ -979,7 +979,7 @@ STATIC void super_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
     };
     for (uint i = 0; i < len; i++) {
         assert(MP_OBJ_IS_TYPE(items[i], &mp_type_type));
-        mp_obj_class_lookup(&lookup, (mp_obj_type_t*)items[i]);
+        mp_obj_class_lookup(&lookup, (mp_obj_type_t*)MP_OBJ_TO_PTR(items[i]));
         if (dest[0] != MP_OBJ_NULL) {
             return;
         }
@@ -998,7 +998,7 @@ const mp_obj_type_t mp_type_super = {
 mp_obj_t mp_obj_new_super(mp_obj_t type, mp_obj_t obj) {
     mp_obj_super_t *o = m_new_obj(mp_obj_super_t);
     *o = (mp_obj_super_t){{&mp_type_super}, type, obj};
-    return o;
+    return MP_OBJ_FROM_PTR(o);
 }
 
 /******************************************************************************/
@@ -1019,17 +1019,16 @@ bool mp_obj_is_subclass_fast(mp_const_obj_t object, mp_const_obj_t classinfo) {
             return false;
         }
 
-        const mp_obj_type_t *self = object;
+        const mp_obj_type_t *self = MP_OBJ_TO_PTR(object);
 
         // for a const struct, this entry might be NULL
-        if (self->bases_tuple == MP_OBJ_NULL) {
+        if (self->bases_tuple == NULL) {
             return false;
         }
 
         // get the base objects (they should be type objects)
-        mp_uint_t len;
-        mp_obj_t *items;
-        mp_obj_tuple_get(self->bases_tuple, &len, &items);
+        mp_uint_t len = self->bases_tuple->len;
+        mp_obj_t *items = self->bases_tuple->items;
         if (len == 0) {
             return false;
         }
@@ -1060,7 +1059,7 @@ STATIC mp_obj_t mp_obj_is_subclass(mp_obj_t object, mp_obj_t classinfo) {
 
     for (uint i = 0; i < len; i++) {
         // We explicitly check for 'object' here since no-one explicitly derives from it
-        if (items[i] == &mp_type_object || mp_obj_is_subclass_fast(object, items[i])) {
+        if (items[i] == MP_OBJ_FROM_PTR(&mp_type_object) || mp_obj_is_subclass_fast(object, items[i])) {
             return mp_const_true;
         }
     }
@@ -1077,17 +1076,17 @@ STATIC mp_obj_t mp_builtin_issubclass(mp_obj_t object, mp_obj_t classinfo) {
 MP_DEFINE_CONST_FUN_OBJ_2(mp_builtin_issubclass_obj, mp_builtin_issubclass);
 
 STATIC mp_obj_t mp_builtin_isinstance(mp_obj_t object, mp_obj_t classinfo) {
-    return mp_obj_is_subclass(mp_obj_get_type(object), classinfo);
+    return mp_obj_is_subclass(MP_OBJ_FROM_PTR(mp_obj_get_type(object)), classinfo);
 }
 
 MP_DEFINE_CONST_FUN_OBJ_2(mp_builtin_isinstance_obj, mp_builtin_isinstance);
 
 mp_obj_t mp_instance_cast_to_native_base(mp_const_obj_t self_in, mp_const_obj_t native_type) {
     mp_obj_type_t *self_type = mp_obj_get_type(self_in);
-    if (!mp_obj_is_subclass_fast(self_type, native_type)) {
+    if (!mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(self_type), native_type)) {
         return MP_OBJ_NULL;
     }
-    mp_obj_instance_t *self = (mp_obj_instance_t*)self_in;
+    mp_obj_instance_t *self = (mp_obj_instance_t*)MP_OBJ_TO_PTR(self_in);
     return self->subobj[0];
 }
 
@@ -1095,13 +1094,14 @@ mp_obj_t mp_instance_cast_to_native_base(mp_const_obj_t self_in, mp_const_obj_t
 // staticmethod and classmethod types (probably should go in a different file)
 
 STATIC mp_obj_t static_class_method_make_new(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
-    assert(self_in == &mp_type_staticmethod || self_in == &mp_type_classmethod);
+    mp_obj_type_t *self = MP_OBJ_TO_PTR(self_in);
+    assert(self == &mp_type_staticmethod || self == &mp_type_classmethod);
 
     mp_arg_check_num(n_args, n_kw, 1, 1, false);
 
     mp_obj_static_class_method_t *o = m_new_obj(mp_obj_static_class_method_t);
-    *o = (mp_obj_static_class_method_t){{(mp_obj_type_t*)self_in}, args[0]};
-    return o;
+    *o = (mp_obj_static_class_method_t){{self}, args[0]};
+    return MP_OBJ_FROM_PTR(o);
 }
 
 const mp_obj_type_t mp_type_staticmethod = {
diff --git a/py/objzip.c b/py/objzip.c
index 68f9ed3f395a3e8958e510785f23ed5d0191c53a..3ac6af15cd5875929b7fd2c7ea6b93b59c847535 100644
--- a/py/objzip.c
+++ b/py/objzip.c
@@ -40,31 +40,31 @@ STATIC mp_obj_t zip_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw,
     mp_arg_check_num(n_args, n_kw, 0, MP_OBJ_FUN_ARGS_MAX, false);
 
     mp_obj_zip_t *o = m_new_obj_var(mp_obj_zip_t, mp_obj_t, n_args);
-    o->base.type = type_in;
+    o->base.type = MP_OBJ_TO_PTR(type_in);
     o->n_iters = n_args;
     for (mp_uint_t i = 0; i < n_args; i++) {
         o->iters[i] = mp_getiter(args[i]);
     }
-    return o;
+    return MP_OBJ_FROM_PTR(o);
 }
 
 STATIC mp_obj_t zip_iternext(mp_obj_t self_in) {
     assert(MP_OBJ_IS_TYPE(self_in, &mp_type_zip));
-    mp_obj_zip_t *self = self_in;
+    mp_obj_zip_t *self = MP_OBJ_TO_PTR(self_in);
     if (self->n_iters == 0) {
         return MP_OBJ_STOP_ITERATION;
     }
-    mp_obj_tuple_t *tuple = mp_obj_new_tuple(self->n_iters, NULL);
+    mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR(mp_obj_new_tuple(self->n_iters, NULL));
 
     for (mp_uint_t i = 0; i < self->n_iters; i++) {
         mp_obj_t next = mp_iternext(self->iters[i]);
         if (next == MP_OBJ_STOP_ITERATION) {
-            mp_obj_tuple_del(tuple);
+            mp_obj_tuple_del(MP_OBJ_FROM_PTR(tuple));
             return MP_OBJ_STOP_ITERATION;
         }
         tuple->items[i] = next;
     }
-    return tuple;
+    return MP_OBJ_FROM_PTR(tuple);
 }
 
 const mp_obj_type_t mp_type_zip = {
diff --git a/py/parse.c b/py/parse.c
index 61c98b9037fdeb47967c9b787e7d8fffdf588df3..afe8711a2d29af43e663bd3a4a22bd60841857a7 100644
--- a/py/parse.c
+++ b/py/parse.c
@@ -350,13 +350,13 @@ STATIC mp_parse_node_t make_node_string_bytes(parser_t *parser, mp_uint_t src_li
     pn->kind_num_nodes = rule_kind | (2 << 8);
     char *p = m_new(char, len);
     memcpy(p, str, len);
-    pn->nodes[0] = (mp_int_t)p;
+    pn->nodes[0] = (uintptr_t)p;
     pn->nodes[1] = len;
     return (mp_parse_node_t)pn;
 }
 
 STATIC mp_parse_node_t make_node_const_object(parser_t *parser, mp_uint_t src_line, mp_obj_t obj) {
-    mp_parse_node_struct_t *pn = parser_alloc(parser, sizeof(mp_parse_node_struct_t) + sizeof(mp_parse_node_t));
+    mp_parse_node_struct_t *pn = parser_alloc(parser, sizeof(mp_parse_node_struct_t) + sizeof(mp_obj_t));
     if (pn == NULL) {
         parser->parse_error = PARSE_ERROR_MEMORY;
         return MP_PARSE_NODE_NULL;
@@ -612,7 +612,7 @@ STATIC bool fold_constants(parser_t *parser, const rule_t *rule, mp_uint_t num_a
         }
         mp_obj_t dest[2];
         mp_load_method_maybe(elem->value, q_attr, dest);
-        if (!(MP_OBJ_IS_SMALL_INT(dest[0]) && dest[1] == NULL)) {
+        if (!(MP_OBJ_IS_SMALL_INT(dest[0]) && dest[1] == MP_OBJ_NULL)) {
             return false;
         }
         arg0 = MP_OBJ_SMALL_INT_VALUE(dest[0]);
diff --git a/py/parse.h b/py/parse.h
index 65ca0f4d48d57f42a4cff267576da0d9deae622a..b814350c93496491ea75ea85d8076f6ef0c13b32 100644
--- a/py/parse.h
+++ b/py/parse.h
@@ -48,7 +48,7 @@ struct _mp_lexer_t;
 #define MP_PARSE_NODE_BYTES     (0x0a)
 #define MP_PARSE_NODE_TOKEN     (0x0e)
 
-typedef mp_uint_t mp_parse_node_t; // must be pointer size
+typedef uintptr_t mp_parse_node_t; // must be pointer size
 
 typedef struct _mp_parse_node_struct_t {
     uint32_t source_line;       // line number in source file
@@ -71,7 +71,7 @@ typedef struct _mp_parse_node_struct_t {
 
 #define MP_PARSE_NODE_LEAF_KIND(pn) ((pn) & 0x0f)
 #define MP_PARSE_NODE_LEAF_ARG(pn) (((mp_uint_t)(pn)) >> 4)
-#define MP_PARSE_NODE_LEAF_SMALL_INT(pn) (((mp_int_t)(pn)) >> 1)
+#define MP_PARSE_NODE_LEAF_SMALL_INT(pn) (((mp_int_t)(intptr_t)(pn)) >> 1)
 #define MP_PARSE_NODE_STRUCT_KIND(pns) ((pns)->kind_num_nodes & 0xff)
 #define MP_PARSE_NODE_STRUCT_NUM_NODES(pns) ((pns)->kind_num_nodes >> 8)
 
diff --git a/py/parsenum.c b/py/parsenum.c
index 1a39c899d55317bb887bcc531bf9662e9b412beb..57261de40dd71485acbecdebf4080af8dec69442 100644
--- a/py/parsenum.c
+++ b/py/parsenum.c
@@ -39,7 +39,7 @@ STATIC NORETURN void raise_exc(mp_obj_t exc, mp_lexer_t *lex) {
     // if lex!=NULL then the parser called us and we need to convert the
     // exception's type from ValueError to SyntaxError and add traceback info
     if (lex != NULL) {
-        ((mp_obj_base_t*)exc)->type = &mp_type_SyntaxError;
+        ((mp_obj_base_t*)MP_OBJ_TO_PTR(exc))->type = &mp_type_SyntaxError;
         mp_obj_exception_add_traceback(exc, lex->source_name, lex->tok_line, MP_QSTR_NULL);
     }
     nlr_raise(exc);
diff --git a/py/repl.c b/py/repl.c
index 440606996764dc2acd021b82156113fe941125f1..182961b4b9e470b7d6f481c3f23332f7ab0440b3 100644
--- a/py/repl.c
+++ b/py/repl.c
@@ -169,11 +169,11 @@ mp_uint_t mp_repl_autocomplete(const char *str, mp_uint_t len, const mp_print_t
             } else {
                 mp_obj_type_t *type;
                 if (MP_OBJ_IS_TYPE(obj, &mp_type_type)) {
-                    type = obj;
+                    type = MP_OBJ_TO_PTR(obj);
                 } else {
                     type = mp_obj_get_type(obj);
                 }
-                if (type->locals_dict != MP_OBJ_NULL && MP_OBJ_IS_TYPE(type->locals_dict, &mp_type_dict)) {
+                if (type->locals_dict != NULL && type->locals_dict->base.type == &mp_type_dict) {
                     dict = type->locals_dict;
                 } else {
                     // obj has no dict
diff --git a/py/runtime.c b/py/runtime.c
index dd2c17797d1518e34d4700eb93800b2c7a753caf..e45591bbe23badacd1951c2a5b8d352ab5de4e83 100644
--- a/py/runtime.c
+++ b/py/runtime.c
@@ -83,7 +83,7 @@ void mp_init(void) {
 
     // initialise the __main__ module
     mp_obj_dict_init(&MP_STATE_VM(dict_main), 1);
-    mp_obj_dict_store(&MP_STATE_VM(dict_main), MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR___main__));
+    mp_obj_dict_store(MP_OBJ_FROM_PTR(&MP_STATE_VM(dict_main)), MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR___main__));
 
     // locals = globals for outer module (see Objects/frameobject.c/PyFrame_New())
     MP_STATE_CTX(dict_locals) = MP_STATE_CTX(dict_globals) = &MP_STATE_VM(dict_main);
@@ -156,29 +156,29 @@ mp_obj_t mp_load_build_class(void) {
         }
     }
     #endif
-    return (mp_obj_t)&mp_builtin___build_class___obj;
+    return MP_OBJ_FROM_PTR(&mp_builtin___build_class___obj);
 }
 
 void mp_store_name(qstr qst, mp_obj_t obj) {
     DEBUG_OP_printf("store name %s <- %p\n", qstr_str(qst), obj);
-    mp_obj_dict_store(MP_STATE_CTX(dict_locals), MP_OBJ_NEW_QSTR(qst), obj);
+    mp_obj_dict_store(MP_OBJ_FROM_PTR(MP_STATE_CTX(dict_locals)), MP_OBJ_NEW_QSTR(qst), obj);
 }
 
 void mp_delete_name(qstr qst) {
     DEBUG_OP_printf("delete name %s\n", qstr_str(qst));
     // TODO convert KeyError to NameError if qst not found
-    mp_obj_dict_delete(MP_STATE_CTX(dict_locals), MP_OBJ_NEW_QSTR(qst));
+    mp_obj_dict_delete(MP_OBJ_FROM_PTR(MP_STATE_CTX(dict_locals)), MP_OBJ_NEW_QSTR(qst));
 }
 
 void mp_store_global(qstr qst, mp_obj_t obj) {
     DEBUG_OP_printf("store global %s <- %p\n", qstr_str(qst), obj);
-    mp_obj_dict_store(MP_STATE_CTX(dict_globals), MP_OBJ_NEW_QSTR(qst), obj);
+    mp_obj_dict_store(MP_OBJ_FROM_PTR(MP_STATE_CTX(dict_globals)), MP_OBJ_NEW_QSTR(qst), obj);
 }
 
 void mp_delete_global(qstr qst) {
     DEBUG_OP_printf("delete global %s\n", qstr_str(qst));
     // TODO convert KeyError to NameError if qst not found
-    mp_obj_dict_delete(MP_STATE_CTX(dict_globals), MP_OBJ_NEW_QSTR(qst));
+    mp_obj_dict_delete(MP_OBJ_FROM_PTR(MP_STATE_CTX(dict_globals)), MP_OBJ_NEW_QSTR(qst));
 }
 
 mp_obj_t mp_unary_op(mp_uint_t op, mp_obj_t arg) {
@@ -273,7 +273,7 @@ mp_obj_t mp_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs) {
                 return mp_const_false;
             }
         } else if (MP_OBJ_IS_TYPE(rhs, &mp_type_tuple)) {
-            mp_obj_tuple_t *tuple = rhs;
+            mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR(rhs);
             for (mp_uint_t i = 0; i < tuple->len; i++) {
                 rhs = tuple->items[i];
                 if (!mp_obj_is_exception_type(rhs)) {
@@ -437,10 +437,10 @@ mp_obj_t mp_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs) {
                         goto zero_division;
                     }
                     // to reduce stack usage we don't pass a temp array of the 2 items
-                    mp_obj_tuple_t *tuple = mp_obj_new_tuple(2, NULL);
+                    mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR(mp_obj_new_tuple(2, NULL));
                     tuple->items[0] = MP_OBJ_NEW_SMALL_INT(mp_small_int_floor_divide(lhs_val, rhs_val));
                     tuple->items[1] = MP_OBJ_NEW_SMALL_INT(mp_small_int_modulo(lhs_val, rhs_val));
-                    return tuple;
+                    return MP_OBJ_FROM_PTR(tuple);
                 }
 
                 case MP_BINARY_OP_LESS: return mp_obj_new_bool(lhs_val < rhs_val); break;
@@ -582,7 +582,7 @@ mp_obj_t mp_call_function_n_kw(mp_obj_t fun_in, mp_uint_t n_args, mp_uint_t n_kw
 // if n_args==0 and n_kw==0 then there are only fun and self/NULL
 mp_obj_t mp_call_method_n_kw(mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
     DEBUG_OP_printf("call method (fun=%p, self=%p, n_args=" UINT_FMT ", n_kw=" UINT_FMT ", args=%p)\n", args[0], args[1], n_args, n_kw, args);
-    int adjust = (args[1] == NULL) ? 0 : 1;
+    int adjust = (args[1] == MP_OBJ_NULL) ? 0 : 1;
     return mp_call_function_n_kw(args[0], n_args + adjust, n_kw, args + 2 - adjust);
 }
 
@@ -839,18 +839,18 @@ void mp_unpack_ex(mp_obj_t seq_in, mp_uint_t num_in, mp_obj_t *items) {
             }
             items[num_left + num_right + 1 - 1 - seq_len] = item;
         }
-        mp_obj_list_t *rest = mp_obj_new_list(0, NULL);
+        mp_obj_list_t *rest = MP_OBJ_TO_PTR(mp_obj_new_list(0, NULL));
         while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
-            mp_obj_list_append(rest, item);
+            mp_obj_list_append(MP_OBJ_FROM_PTR(rest), item);
         }
         if (rest->len < num_right) {
             goto too_short;
         }
-        items[num_right] = rest;
+        items[num_right] = MP_OBJ_FROM_PTR(rest);
         for (mp_uint_t i = 0; i < num_right; i++) {
             items[num_right - 1 - i] = rest->items[rest->len - num_right + i];
         }
-        mp_obj_list_set_len(rest, rest->len - num_right);
+        mp_obj_list_set_len(MP_OBJ_FROM_PTR(rest), rest->len - num_right);
     }
     return;
 
@@ -891,7 +891,7 @@ typedef struct _mp_obj_checked_fun_t {
 } mp_obj_checked_fun_t;
 
 STATIC mp_obj_t checked_fun_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
-    mp_obj_checked_fun_t *self = self_in;
+    mp_obj_checked_fun_t *self = MP_OBJ_TO_PTR(self_in);
     if (n_args > 0) {
         const mp_obj_type_t *arg0_type = mp_obj_get_type(args[0]);
         if (arg0_type != self->type) {
@@ -918,7 +918,7 @@ STATIC mp_obj_t mp_obj_new_checked_fun(const mp_obj_type_t *type, mp_obj_t fun)
     o->base.type = &mp_type_checked_fun;
     o->type = type;
     o->fun = fun;
-    return o;
+    return MP_OBJ_FROM_PTR(o);
 }
 
 #endif // MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG
@@ -930,11 +930,11 @@ STATIC mp_obj_t mp_obj_new_checked_fun(const mp_obj_type_t *type, mp_obj_t fun)
 void mp_convert_member_lookup(mp_obj_t self, const mp_obj_type_t *type, mp_obj_t member, mp_obj_t *dest) {
     if (MP_OBJ_IS_TYPE(member, &mp_type_staticmethod)) {
         // return just the function
-        dest[0] = ((mp_obj_static_class_method_t*)member)->fun;
+        dest[0] = ((mp_obj_static_class_method_t*)MP_OBJ_TO_PTR(member))->fun;
     } else if (MP_OBJ_IS_TYPE(member, &mp_type_classmethod)) {
         // return a bound method, with self being the type of this object
-        dest[0] = ((mp_obj_static_class_method_t*)member)->fun;
-        dest[1] = (mp_obj_t)type;
+        dest[0] = ((mp_obj_static_class_method_t*)MP_OBJ_TO_PTR(member))->fun;
+        dest[1] = MP_OBJ_FROM_PTR(type);
     } else if (MP_OBJ_IS_TYPE(member, &mp_type_type)) {
         // Don't try to bind types (even though they're callable)
         dest[0] = member;
@@ -973,11 +973,11 @@ void mp_load_method_maybe(mp_obj_t obj, qstr attr, mp_obj_t *dest) {
 #if MICROPY_CPYTHON_COMPAT
     } else if (attr == MP_QSTR___class__) {
         // a.__class__ is equivalent to type(a)
-        dest[0] = type;
+        dest[0] = MP_OBJ_FROM_PTR(type);
 #endif
 
     } else if (attr == MP_QSTR___next__ && type->iternext != NULL) {
-        dest[0] = (mp_obj_t)&mp_builtin_next_obj;
+        dest[0] = MP_OBJ_FROM_PTR(&mp_builtin_next_obj);
         dest[1] = obj;
 
     } else if (type->attr != NULL) {
@@ -987,8 +987,8 @@ void mp_load_method_maybe(mp_obj_t obj, qstr attr, mp_obj_t *dest) {
     } else if (type->locals_dict != NULL) {
         // generic method lookup
         // this is a lookup in the object (ie not class or type)
-        assert(MP_OBJ_IS_TYPE(type->locals_dict, &mp_type_dict)); // Micro Python restriction, for now
-        mp_map_t *locals_map = mp_obj_dict_get_map(type->locals_dict);
+        assert(type->locals_dict->base.type == &mp_type_dict); // Micro Python restriction, for now
+        mp_map_t *locals_map = &type->locals_dict->map;
         mp_map_elem_t *elem = mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP);
         if (elem != NULL) {
             mp_convert_member_lookup(obj, type, elem->value, dest);
@@ -1011,7 +1011,7 @@ void mp_load_method(mp_obj_t base, qstr attr, mp_obj_t *dest) {
             if (MP_OBJ_IS_TYPE(base, &mp_type_type)) {
                 nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_AttributeError,
                     "type object '%q' has no attribute '%q'",
-                    ((mp_obj_type_t*)base)->name, attr));
+                    ((mp_obj_type_t*)MP_OBJ_TO_PTR(base))->name, attr));
             } else {
                 nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_AttributeError,
                     "'%s' object has no attribute '%q'",
@@ -1116,10 +1116,10 @@ mp_obj_t mp_iternext(mp_obj_t o_in) {
                 nlr_pop();
                 return ret;
             } else {
-                if (mp_obj_is_subclass_fast(mp_obj_get_type(nlr.ret_val), &mp_type_StopIteration)) {
+                if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(((mp_obj_base_t*)nlr.ret_val)->type), MP_OBJ_FROM_PTR(&mp_type_StopIteration))) {
                     return MP_OBJ_STOP_ITERATION;
                 } else {
-                    nlr_raise(nlr.ret_val);
+                    nlr_jump(nlr.ret_val);
                 }
             }
         } else {
@@ -1174,7 +1174,7 @@ mp_vm_return_kind_t mp_resume(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t th
     }
 
     if (throw_value != MP_OBJ_NULL) {
-        if (mp_obj_is_subclass_fast(mp_obj_get_type(throw_value), &mp_type_GeneratorExit)) {
+        if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(mp_obj_get_type(throw_value)), MP_OBJ_FROM_PTR(&mp_type_GeneratorExit))) {
             mp_load_method_maybe(self_in, MP_QSTR_close, dest);
             if (dest[0] != MP_OBJ_NULL) {
                 // TODO: Exceptions raised in close() are not propagated,
@@ -1284,7 +1284,7 @@ void mp_import_all(mp_obj_t module) {
     DEBUG_printf("import all %p\n", module);
 
     // TODO: Support __all__
-    mp_map_t *map = mp_obj_dict_get_map(mp_obj_module_get_globals(module));
+    mp_map_t *map = mp_obj_dict_get_map(MP_OBJ_FROM_PTR(mp_obj_module_get_globals(module)));
     for (mp_uint_t i = 0; i < map->alloc; i++) {
         if (MP_MAP_SLOT_IS_FILLED(map, i)) {
             qstr name = MP_OBJ_QSTR_VALUE(map->table[i].key);
@@ -1329,7 +1329,7 @@ mp_obj_t mp_parse_compile_execute(mp_lexer_t *lex, mp_parse_input_kind_t parse_i
         // exception; restore context and re-raise same exception
         mp_globals_set(old_globals);
         mp_locals_set(old_locals);
-        nlr_raise(nlr.ret_val);
+        nlr_jump(nlr.ret_val);
     }
 }
 
diff --git a/py/runtime.h b/py/runtime.h
index 14496196674e18852153c65b585bdf50ab8ab3d8..10b133ebdec18c5221bc98c44d8fc12881de7f0b 100644
--- a/py/runtime.h
+++ b/py/runtime.h
@@ -140,8 +140,8 @@ mp_obj_t mp_convert_native_to_obj(mp_uint_t val, mp_uint_t type);
 mp_obj_t mp_native_call_function_n_kw(mp_obj_t fun_in, mp_uint_t n_args_kw, const mp_obj_t *args);
 void mp_native_raise(mp_obj_t o);
 
-#define mp_sys_path ((mp_obj_t)&MP_STATE_VM(mp_sys_path_obj))
-#define mp_sys_argv ((mp_obj_t)&MP_STATE_VM(mp_sys_argv_obj))
+#define mp_sys_path (MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_sys_path_obj)))
+#define mp_sys_argv (MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_sys_argv_obj)))
 
 #if MICROPY_WARNINGS
 void mp_warning(const char *msg, ...);
diff --git a/py/sequence.c b/py/sequence.c
index 27815344e31b92afcbc76c73a00e3ea05bb35cc8..6f715ff79502149f8afbd2dbd9d56f01380bded9 100644
--- a/py/sequence.c
+++ b/py/sequence.c
@@ -217,7 +217,7 @@ bool mp_seq_cmp_objs(mp_uint_t op, const mp_obj_t *items1, mp_uint_t len1, const
 // Special-case of index() which searches for mp_obj_t
 mp_obj_t mp_seq_index_obj(const mp_obj_t *items, mp_uint_t len, mp_uint_t n_args, const mp_obj_t *args) {
     mp_obj_type_t *type = mp_obj_get_type(args[0]);
-    mp_obj_t *value = args[1];
+    mp_obj_t value = args[1];
     uint start = 0;
     uint stop = len;
 
diff --git a/py/showbc.c b/py/showbc.c
index 0e1edb60d716a3378a799d5b9bf984197ab170b8..9b08fa6d6387952653ea0996570035ae77b5126f 100644
--- a/py/showbc.c
+++ b/py/showbc.c
@@ -49,6 +49,9 @@
 #define DECODE_PTR \
     DECODE_UINT; \
     unum = mp_showbc_const_table[unum]
+#define DECODE_OBJ \
+    DECODE_UINT; \
+    unum = mp_showbc_const_table[unum]
 
 #else
 
@@ -59,9 +62,14 @@
     } while ((*ip++ & 0x80) != 0); \
 }
 #define DECODE_PTR do { \
-    ip = (byte*)(((mp_uint_t)ip + sizeof(mp_uint_t) - 1) & (~(sizeof(mp_uint_t) - 1))); /* align ip */ \
-    unum = *(mp_uint_t*)ip; \
-    ip += sizeof(mp_uint_t); \
+    ip = (byte*)MP_ALIGN(ip, sizeof(void*)); \
+    unum = (uintptr_t)*(void**)ip; \
+    ip += sizeof(void*); \
+} while (0)
+#define DECODE_OBJ do { \
+    ip = (byte*)MP_ALIGN(ip, sizeof(mp_obj_t)); \
+    unum = (mp_uint_t)*(mp_obj_t*)ip; \
+    ip += sizeof(mp_obj_t); \
 } while (0)
 
 #endif
@@ -186,8 +194,8 @@ const byte *mp_bytecode_print_str(const byte *ip) {
             break;
 
         case MP_BC_LOAD_CONST_OBJ:
-            DECODE_PTR;
-            printf("LOAD_CONST_OBJ %p=", (void*)unum);
+            DECODE_OBJ;
+            printf("LOAD_CONST_OBJ %p=", MP_OBJ_TO_PTR(unum));
             mp_obj_print_helper(&mp_plat_print, (mp_obj_t)unum, PRINT_REPR);
             break;
 
@@ -316,32 +324,32 @@ const byte *mp_bytecode_print_str(const byte *ip) {
 
         case MP_BC_JUMP:
             DECODE_SLABEL;
-            printf("JUMP " UINT_FMT, ip + unum - mp_showbc_code_start);
+            printf("JUMP " UINT_FMT, (mp_uint_t)(ip + unum - mp_showbc_code_start));
             break;
 
         case MP_BC_POP_JUMP_IF_TRUE:
             DECODE_SLABEL;
-            printf("POP_JUMP_IF_TRUE " UINT_FMT, ip + unum - mp_showbc_code_start);
+            printf("POP_JUMP_IF_TRUE " UINT_FMT, (mp_uint_t)(ip + unum - mp_showbc_code_start));
             break;
 
         case MP_BC_POP_JUMP_IF_FALSE:
             DECODE_SLABEL;
-            printf("POP_JUMP_IF_FALSE " UINT_FMT, ip + unum - mp_showbc_code_start);
+            printf("POP_JUMP_IF_FALSE " UINT_FMT, (mp_uint_t)(ip + unum - mp_showbc_code_start));
             break;
 
         case MP_BC_JUMP_IF_TRUE_OR_POP:
             DECODE_SLABEL;
-            printf("JUMP_IF_TRUE_OR_POP " UINT_FMT, ip + unum - mp_showbc_code_start);
+            printf("JUMP_IF_TRUE_OR_POP " UINT_FMT, (mp_uint_t)(ip + unum - mp_showbc_code_start));
             break;
 
         case MP_BC_JUMP_IF_FALSE_OR_POP:
             DECODE_SLABEL;
-            printf("JUMP_IF_FALSE_OR_POP " UINT_FMT, ip + unum - mp_showbc_code_start);
+            printf("JUMP_IF_FALSE_OR_POP " UINT_FMT, (mp_uint_t)(ip + unum - mp_showbc_code_start));
             break;
 
         case MP_BC_SETUP_WITH:
             DECODE_ULABEL; // loop-like labels are always forward
-            printf("SETUP_WITH " UINT_FMT, ip + unum - mp_showbc_code_start);
+            printf("SETUP_WITH " UINT_FMT, (mp_uint_t)(ip + unum - mp_showbc_code_start));
             break;
 
         case MP_BC_WITH_CLEANUP:
@@ -350,18 +358,18 @@ const byte *mp_bytecode_print_str(const byte *ip) {
 
         case MP_BC_UNWIND_JUMP:
             DECODE_SLABEL;
-            printf("UNWIND_JUMP " UINT_FMT " %d", ip + unum - mp_showbc_code_start, *ip);
+            printf("UNWIND_JUMP " UINT_FMT " %d", (mp_uint_t)(ip + unum - mp_showbc_code_start), *ip);
             ip += 1;
             break;
 
         case MP_BC_SETUP_EXCEPT:
             DECODE_ULABEL; // except labels are always forward
-            printf("SETUP_EXCEPT " UINT_FMT, ip + unum - mp_showbc_code_start);
+            printf("SETUP_EXCEPT " UINT_FMT, (mp_uint_t)(ip + unum - mp_showbc_code_start));
             break;
 
         case MP_BC_SETUP_FINALLY:
             DECODE_ULABEL; // except labels are always forward
-            printf("SETUP_FINALLY " UINT_FMT, ip + unum - mp_showbc_code_start);
+            printf("SETUP_FINALLY " UINT_FMT, (mp_uint_t)(ip + unum - mp_showbc_code_start));
             break;
 
         case MP_BC_END_FINALLY:
@@ -378,7 +386,7 @@ const byte *mp_bytecode_print_str(const byte *ip) {
 
         case MP_BC_FOR_ITER:
             DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward
-            printf("FOR_ITER " UINT_FMT, ip + unum - mp_showbc_code_start);
+            printf("FOR_ITER " UINT_FMT, (mp_uint_t)(ip + unum - mp_showbc_code_start));
             break;
 
         case MP_BC_POP_BLOCK:
@@ -453,25 +461,25 @@ const byte *mp_bytecode_print_str(const byte *ip) {
 
         case MP_BC_MAKE_FUNCTION:
             DECODE_PTR;
-            printf("MAKE_FUNCTION %p", (void*)unum);
+            printf("MAKE_FUNCTION %p", (void*)(uintptr_t)unum);
             break;
 
         case MP_BC_MAKE_FUNCTION_DEFARGS:
             DECODE_PTR;
-            printf("MAKE_FUNCTION_DEFARGS %p", (void*)unum);
+            printf("MAKE_FUNCTION_DEFARGS %p", (void*)(uintptr_t)unum);
             break;
 
         case MP_BC_MAKE_CLOSURE: {
             DECODE_PTR;
             mp_uint_t n_closed_over = *ip++;
-            printf("MAKE_CLOSURE %p " UINT_FMT, (void*)unum, n_closed_over);
+            printf("MAKE_CLOSURE %p " UINT_FMT, (void*)(uintptr_t)unum, n_closed_over);
             break;
         }
 
         case MP_BC_MAKE_CLOSURE_DEFARGS: {
             DECODE_PTR;
             mp_uint_t n_closed_over = *ip++;
-            printf("MAKE_CLOSURE_DEFARGS %p " UINT_FMT, (void*)unum, n_closed_over);
+            printf("MAKE_CLOSURE_DEFARGS %p " UINT_FMT, (void*)(uintptr_t)unum, n_closed_over);
             break;
         }
 
diff --git a/py/stream.c b/py/stream.c
index 5c161ec2dc2012838788c46810070d7b49a646d5..025d6aee576b5dfbfaccdbe8b942357223901dd7 100644
--- a/py/stream.c
+++ b/py/stream.c
@@ -50,7 +50,7 @@ STATIC mp_obj_t stream_readall(mp_obj_t self_in);
 #define STREAM_CONTENT_TYPE(stream) (((stream)->is_text) ? &mp_type_str : &mp_type_bytes)
 
 STATIC mp_obj_t stream_read(mp_uint_t n_args, const mp_obj_t *args) {
-    struct _mp_obj_base_t *o = (struct _mp_obj_base_t *)args[0];
+    struct _mp_obj_base_t *o = (struct _mp_obj_base_t *)MP_OBJ_TO_PTR(args[0]);
     if (o->type->stream_p == NULL || o->type->stream_p->read == NULL) {
         // CPython: io.UnsupportedOperation, OSError subclass
         nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Operation not supported"));
@@ -85,7 +85,7 @@ STATIC mp_obj_t stream_read(mp_uint_t n_args, const mp_obj_t *args) {
                 nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_MemoryError, "out of memory"));
             }
             int error;
-            mp_uint_t out_sz = o->type->stream_p->read(o, p, more_bytes, &error);
+            mp_uint_t out_sz = o->type->stream_p->read(MP_OBJ_FROM_PTR(o), p, more_bytes, &error);
             if (out_sz == MP_STREAM_ERROR) {
                 vstr_cut_tail_bytes(&vstr, more_bytes);
                 if (mp_is_nonblocking_error(error)) {
@@ -156,7 +156,7 @@ STATIC mp_obj_t stream_read(mp_uint_t n_args, const mp_obj_t *args) {
     vstr_t vstr;
     vstr_init_len(&vstr, sz);
     int error;
-    mp_uint_t out_sz = o->type->stream_p->read(o, vstr.buf, sz, &error);
+    mp_uint_t out_sz = o->type->stream_p->read(MP_OBJ_FROM_PTR(o), vstr.buf, sz, &error);
     if (out_sz == MP_STREAM_ERROR) {
         vstr_clear(&vstr);
         if (mp_is_nonblocking_error(error)) {
@@ -175,7 +175,7 @@ STATIC mp_obj_t stream_read(mp_uint_t n_args, const mp_obj_t *args) {
 }
 
 mp_obj_t mp_stream_write(mp_obj_t self_in, const void *buf, size_t len) {
-    struct _mp_obj_base_t *o = (struct _mp_obj_base_t *)self_in;
+    struct _mp_obj_base_t *o = (struct _mp_obj_base_t *)MP_OBJ_TO_PTR(self_in);
     if (o->type->stream_p == NULL || o->type->stream_p->write == NULL) {
         // CPython: io.UnsupportedOperation, OSError subclass
         nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Operation not supported"));
@@ -198,6 +198,11 @@ mp_obj_t mp_stream_write(mp_obj_t self_in, const void *buf, size_t len) {
     }
 }
 
+// XXX hack
+void mp_stream_write_adaptor(void *self, const char *buf, size_t len) {
+    mp_stream_write(MP_OBJ_FROM_PTR(self), buf, len);
+}
+
 STATIC mp_obj_t stream_write_method(mp_obj_t self_in, mp_obj_t arg) {
     mp_buffer_info_t bufinfo;
     mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_READ);
@@ -205,7 +210,7 @@ STATIC mp_obj_t stream_write_method(mp_obj_t self_in, mp_obj_t arg) {
 }
 
 STATIC mp_obj_t stream_readinto(mp_uint_t n_args, const mp_obj_t *args) {
-    struct _mp_obj_base_t *o = (struct _mp_obj_base_t *)args[0];
+    struct _mp_obj_base_t *o = (struct _mp_obj_base_t *)MP_OBJ_TO_PTR(args[0]);
     if (o->type->stream_p == NULL || o->type->stream_p->read == NULL) {
         // CPython: io.UnsupportedOperation, OSError subclass
         nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Operation not supported"));
@@ -225,7 +230,7 @@ STATIC mp_obj_t stream_readinto(mp_uint_t n_args, const mp_obj_t *args) {
     }
 
     int error;
-    mp_uint_t out_sz = o->type->stream_p->read(o, bufinfo.buf, len, &error);
+    mp_uint_t out_sz = o->type->stream_p->read(MP_OBJ_FROM_PTR(o), bufinfo.buf, len, &error);
     if (out_sz == MP_STREAM_ERROR) {
         if (mp_is_nonblocking_error(error)) {
             return mp_const_none;
@@ -237,7 +242,7 @@ STATIC mp_obj_t stream_readinto(mp_uint_t n_args, const mp_obj_t *args) {
 }
 
 STATIC mp_obj_t stream_readall(mp_obj_t self_in) {
-    struct _mp_obj_base_t *o = (struct _mp_obj_base_t *)self_in;
+    struct _mp_obj_base_t *o = (struct _mp_obj_base_t *)MP_OBJ_TO_PTR(self_in);
     if (o->type->stream_p == NULL || o->type->stream_p->read == NULL) {
         // CPython: io.UnsupportedOperation, OSError subclass
         nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Operation not supported"));
@@ -286,7 +291,7 @@ STATIC mp_obj_t stream_readall(mp_obj_t self_in) {
 
 // Unbuffered, inefficient implementation of readline() for raw I/O files.
 STATIC mp_obj_t stream_unbuffered_readline(mp_uint_t n_args, const mp_obj_t *args) {
-    struct _mp_obj_base_t *o = (struct _mp_obj_base_t *)args[0];
+    struct _mp_obj_base_t *o = (struct _mp_obj_base_t *)MP_OBJ_TO_PTR(args[0]);
     if (o->type->stream_p == NULL || o->type->stream_p->read == NULL) {
         // CPython: io.UnsupportedOperation, OSError subclass
         nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Operation not supported"));
@@ -311,7 +316,7 @@ STATIC mp_obj_t stream_unbuffered_readline(mp_uint_t n_args, const mp_obj_t *arg
         }
 
         int error;
-        mp_uint_t out_sz = o->type->stream_p->read(o, p, 1, &error);
+        mp_uint_t out_sz = o->type->stream_p->read(MP_OBJ_FROM_PTR(o), p, 1, &error);
         if (out_sz == MP_STREAM_ERROR) {
             if (mp_is_nonblocking_error(error)) {
                 if (vstr.len == 1) {
@@ -368,7 +373,7 @@ mp_obj_t mp_stream_unbuffered_iter(mp_obj_t self) {
 }
 
 STATIC mp_obj_t stream_seek(mp_uint_t n_args, const mp_obj_t *args) {
-    struct _mp_obj_base_t *o = (struct _mp_obj_base_t *)args[0];
+    struct _mp_obj_base_t *o = (struct _mp_obj_base_t *)MP_OBJ_TO_PTR(args[0]);
     if (o->type->stream_p == NULL || o->type->stream_p->ioctl == NULL) {
         // CPython: io.UnsupportedOperation, OSError subclass
         nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Operation not supported"));
@@ -383,7 +388,7 @@ STATIC mp_obj_t stream_seek(mp_uint_t n_args, const mp_obj_t *args) {
     }
 
     int error;
-    mp_uint_t res = o->type->stream_p->ioctl(o, MP_STREAM_SEEK, (mp_uint_t)&seek_s, &error);
+    mp_uint_t res = o->type->stream_p->ioctl(MP_OBJ_FROM_PTR(o), MP_STREAM_SEEK, (mp_uint_t)(uintptr_t)&seek_s, &error);
     if (res == MP_STREAM_ERROR) {
         nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(error)));
     }
diff --git a/py/stream.h b/py/stream.h
index 16761217aadaab24f30cb96803506960708cbb27..b3958d301b44050962ea24bbd9ba7c1e0916b8f5 100644
--- a/py/stream.h
+++ b/py/stream.h
@@ -51,3 +51,4 @@ mp_obj_t mp_stream_write(mp_obj_t self_in, const void *buf, size_t len);
 #endif
 
 #endif // __MICROPY_INCLUDED_PY_STREAM_H__
+void mp_stream_write_adaptor(void *self, const char *buf, size_t len);
diff --git a/py/vm.c b/py/vm.c
index f9aa0f9b3c72aa9017beca86296e5d56a5b7c4b4..f0a0bad8b761b0b91baf41b02b21e90516ab5b7f 100644
--- a/py/vm.c
+++ b/py/vm.c
@@ -38,7 +38,8 @@
 #include "py/bc.h"
 
 #if 0
-#define TRACE(ip) printf("sp=" INT_FMT " ", sp - code_state->sp); mp_bytecode_print2(ip, 1);
+//#define TRACE(ip) printf("sp=" INT_FMT " ", sp - code_state->sp); mp_bytecode_print2(ip, 1);
+#define TRACE(ip) printf("sp=%d ", sp - code_state->sp); mp_bytecode_print2(ip, 1);
 #else
 #define TRACE(ip)
 #endif
@@ -73,7 +74,10 @@ typedef enum {
     ip += 2;
 #define DECODE_PTR \
     DECODE_UINT; \
-    void *ptr = (void*)code_state->const_table[unum]
+    void *ptr = (void*)(uintptr_t)code_state->const_table[unum]
+#define DECODE_OBJ \
+    DECODE_UINT; \
+    mp_obj_t obj = (mp_obj_t)code_state->const_table[unum]
 
 #else
 
@@ -82,9 +86,13 @@ typedef enum {
         qst = (qst << 7) + (*ip & 0x7f); \
     } while ((*ip++ & 0x80) != 0)
 #define DECODE_PTR \
-    ip = (byte*)(((mp_uint_t)ip + sizeof(mp_uint_t) - 1) & (~(sizeof(mp_uint_t) - 1))); /* align ip */ \
-    void *ptr = (void*)*(mp_uint_t*)ip; \
-    ip += sizeof(mp_uint_t)
+    ip = (byte*)MP_ALIGN(ip, sizeof(void*)); \
+    void *ptr = *(void**)ip; \
+    ip += sizeof(void*)
+#define DECODE_OBJ \
+    ip = (byte*)MP_ALIGN(ip, sizeof(mp_obj_t)); \
+    mp_obj_t obj = *(mp_obj_t*)ip; \
+    ip += sizeof(mp_obj_t)
 
 #endif
 
@@ -94,7 +102,7 @@ typedef enum {
 #define SET_TOP(val) *sp = (val)
 
 #if MICROPY_PY_SYS_EXC_INFO
-#define CLEAR_SYS_EXC_INFO() MP_STATE_VM(cur_exception) = MP_OBJ_NULL;
+#define CLEAR_SYS_EXC_INFO() MP_STATE_VM(cur_exception) = NULL;
 #else
 #define CLEAR_SYS_EXC_INFO()
 #endif
@@ -104,7 +112,7 @@ typedef enum {
     ++exc_sp; \
     exc_sp->handler = ip + ulab; \
     exc_sp->val_sp = MP_TAGPTR_MAKE(sp, ((with_or_finally) << 1) | currently_in_except_block); \
-    exc_sp->prev_exc = MP_OBJ_NULL; \
+    exc_sp->prev_exc = NULL; \
     currently_in_except_block = 0; /* in a try block now */ \
 } while (0)
 
@@ -149,7 +157,7 @@ mp_vm_return_kind_t mp_execute_bytecode(mp_code_state *code_state, volatile mp_o
     // sees that it's possible for us to jump from the dispatch loop to the exception
     // handler.  Without this, the code may have a different stack layout in the dispatch
     // loop and the exception handler, leading to very obscure bugs.
-    #define RAISE(o) do { nlr_pop(); nlr.ret_val = o; goto exception_handler; } while (0)
+    #define RAISE(o) do { nlr_pop(); nlr.ret_val = MP_OBJ_TO_PTR(o); goto exception_handler; } while (0)
 
 #if MICROPY_STACKLESS
 run_code_state: ;
@@ -227,8 +235,8 @@ dispatch_loop:
                 }
 
                 ENTRY(MP_BC_LOAD_CONST_OBJ): {
-                    DECODE_PTR;
-                    PUSH(ptr);
+                    DECODE_OBJ;
+                    PUSH(obj);
                     DISPATCH();
                 }
 
@@ -328,7 +336,7 @@ dispatch_loop:
                     DECODE_QSTR;
                     mp_obj_t top = TOP();
                     if (mp_obj_get_type(top)->attr == mp_obj_instance_attr) {
-                        mp_obj_instance_t *self = top;
+                        mp_obj_instance_t *self = MP_OBJ_TO_PTR(top);
                         mp_uint_t x = *ip;
                         mp_obj_t key = MP_OBJ_NEW_QSTR(qst);
                         mp_map_elem_t *elem;
@@ -418,7 +426,7 @@ dispatch_loop:
                     DECODE_QSTR;
                     mp_obj_t top = TOP();
                     if (mp_obj_get_type(top)->attr == mp_obj_instance_attr && sp[-1] != MP_OBJ_NULL) {
-                        mp_obj_instance_t *self = top;
+                        mp_obj_instance_t *self = MP_OBJ_TO_PTR(top);
                         mp_uint_t x = *ip;
                         mp_obj_t key = MP_OBJ_NEW_QSTR(qst);
                         mp_map_elem_t *elem;
@@ -644,8 +652,8 @@ dispatch_loop:
                 ENTRY(MP_BC_UNWIND_JUMP): {
                     MARK_EXC_IP_SELECTIVE();
                     DECODE_SLABEL;
-                    PUSH((void*)(ip + slab)); // push destination ip for jump
-                    PUSH((void*)(mp_uint_t)(*ip)); // push number of exception handlers to unwind (0x80 bit set if we also need to pop stack)
+                    PUSH((mp_obj_t)(mp_uint_t)(uintptr_t)(ip + slab)); // push destination ip for jump
+                    PUSH((mp_obj_t)(mp_uint_t)(*ip)); // push number of exception handlers to unwind (0x80 bit set if we also need to pop stack)
 unwind_jump:;
                     mp_uint_t unum = (mp_uint_t)POP(); // get number of exception handlers to unwind
                     while ((unum & 0x7f) > 0) {
@@ -660,7 +668,7 @@ unwind_jump:;
                             // (not calling it recursively). Set up a sentinel
                             // on a stack so it can return back to us when it is
                             // done (when WITH_CLEANUP or END_FINALLY reached).
-                            PUSH((void*)unum); // push number of exception handlers left to unwind
+                            PUSH((mp_obj_t)unum); // push number of exception handlers left to unwind
                             PUSH(MP_OBJ_NEW_SMALL_INT(UNWIND_JUMP)); // push sentinel
                             ip = exc_sp->handler; // get exception handler byte code address
                             exc_sp--; // pop exception handler
@@ -668,7 +676,7 @@ unwind_jump:;
                         }
                         exc_sp--;
                     }
-                    ip = (const byte*)POP(); // pop destination ip for jump
+                    ip = (const byte*)MP_OBJ_TO_PTR(POP()); // pop destination ip for jump
                     if (unum != 0) {
                         sp--;
                     }
@@ -1085,8 +1093,8 @@ unwind_return:
                         // search for the inner-most previous exception, to reraise it
                         obj = MP_OBJ_NULL;
                         for (mp_exc_stack_t *e = exc_sp; e >= exc_stack; e--) {
-                            if (e->prev_exc != MP_OBJ_NULL) {
-                                obj = e->prev_exc;
+                            if (e->prev_exc != NULL) {
+                                obj = MP_OBJ_FROM_PTR(e->prev_exc);
                                 break;
                             }
                         }
@@ -1113,7 +1121,7 @@ yield:
                     MARK_EXC_IP_SELECTIVE();
 //#define EXC_MATCH(exc, type) MP_OBJ_IS_TYPE(exc, type)
 #define EXC_MATCH(exc, type) mp_obj_exception_match(exc, type)
-#define GENERATOR_EXIT_IF_NEEDED(t) if (t != MP_OBJ_NULL && EXC_MATCH(t, &mp_type_GeneratorExit)) { RAISE(t); }
+#define GENERATOR_EXIT_IF_NEEDED(t) if (t != MP_OBJ_NULL && EXC_MATCH(t, MP_OBJ_FROM_PTR(&mp_type_GeneratorExit))) { RAISE(t); }
                     mp_vm_return_kind_t ret_kind;
                     mp_obj_t send_value = POP();
                     mp_obj_t t_exc = MP_OBJ_NULL;
@@ -1150,7 +1158,7 @@ yield:
                     if (ret_kind == MP_VM_RETURN_EXCEPTION) {
                         // Pop exhausted gen
                         sp--;
-                        if (EXC_MATCH(ret_value, &mp_type_StopIteration)) {
+                        if (EXC_MATCH(ret_value, MP_OBJ_FROM_PTR(&mp_type_StopIteration))) {
                             PUSH(mp_obj_exception_get_value(ret_value));
                             // If we injected GeneratorExit downstream, then even
                             // if it was swallowed, we re-raise GeneratorExit
@@ -1266,7 +1274,7 @@ exception_handler:
             code_state->ip -= 1;
             #endif
 
-            if (mp_obj_is_subclass_fast(mp_obj_get_type(nlr.ret_val), &mp_type_StopIteration)) {
+            if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(((mp_obj_base_t*)nlr.ret_val)->type), MP_OBJ_FROM_PTR(&mp_type_StopIteration))) {
                 if (code_state->ip) {
                     // check if it's a StopIteration within a for block
                     if (*code_state->ip == MP_BC_FOR_ITER) {
@@ -1278,7 +1286,7 @@ exception_handler:
                     } else if (*code_state->ip == MP_BC_YIELD_FROM) {
                         // StopIteration inside yield from call means return a value of
                         // yield from, so inject exception's value as yield from's result
-                        *++code_state->sp = mp_obj_exception_get_value(nlr.ret_val);
+                        *++code_state->sp = mp_obj_exception_get_value(MP_OBJ_FROM_PTR(nlr.ret_val));
                         code_state->ip++; // yield from is over, move to next instruction
                         goto outer_dispatch_loop; // continue with dispatch loop
                     }
@@ -1292,7 +1300,7 @@ unwind_loop:
             // TODO: don't set traceback for exceptions re-raised by END_FINALLY.
             // But consider how to handle nested exceptions.
             // TODO need a better way of not adding traceback to constant objects (right now, just GeneratorExit_obj and MemoryError_obj)
-            if (mp_obj_is_exception_instance(nlr.ret_val) && nlr.ret_val != &mp_const_GeneratorExit_obj && nlr.ret_val != &mp_const_MemoryError_obj) {
+            if (nlr.ret_val != &mp_const_GeneratorExit_obj && nlr.ret_val != &mp_const_MemoryError_obj) {
                 const byte *ip = code_state->code_info;
                 mp_uint_t code_info_size = mp_decode_uint(&ip);
                 #if MICROPY_PERSISTENT_CODE
@@ -1327,7 +1335,7 @@ unwind_loop:
                         break;
                     }
                 }
-                mp_obj_exception_add_traceback(nlr.ret_val, source_file, source_line, block_name);
+                mp_obj_exception_add_traceback(MP_OBJ_FROM_PTR(nlr.ret_val), source_file, source_line, block_name);
             }
 
             while (currently_in_except_block) {
@@ -1353,8 +1361,8 @@ unwind_loop:
                 exc_sp->prev_exc = nlr.ret_val;
                 // push(traceback, exc-val, exc-type)
                 PUSH(mp_const_none);
-                PUSH(nlr.ret_val);
-                PUSH(mp_obj_get_type(nlr.ret_val));
+                PUSH(MP_OBJ_FROM_PTR(nlr.ret_val));
+                PUSH(MP_OBJ_FROM_PTR(((mp_obj_base_t*)nlr.ret_val)->type));
                 code_state->sp = sp;
 
             #if MICROPY_STACKLESS
@@ -1372,7 +1380,7 @@ unwind_loop:
             } else {
                 // propagate exception to higher level
                 // TODO what to do about ip and sp? they don't really make sense at this point
-                fastn[0] = nlr.ret_val; // must put exception here because sp is invalid
+                fastn[0] = MP_OBJ_FROM_PTR(nlr.ret_val); // must put exception here because sp is invalid
                 return MP_VM_RETURN_EXCEPTION;
             }
         }
diff --git a/unix/file.c b/unix/file.c
index 2b191c4de513bd47bdd76ae76cdf8f64213a12d3..448cd50edc3e2e05266057966d89b704d43712ed 100644
--- a/unix/file.c
+++ b/unix/file.c
@@ -62,12 +62,12 @@ extern const mp_obj_type_t mp_type_textio;
 
 STATIC void fdfile_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
     (void)kind;
-    mp_obj_fdfile_t *self = self_in;
-    mp_printf(print, "<io.%s %d>", mp_obj_get_type_str(self), self->fd);
+    mp_obj_fdfile_t *self = MP_OBJ_TO_PTR(self_in);
+    mp_printf(print, "<io.%s %d>", mp_obj_get_type_str(self_in), self->fd);
 }
 
 STATIC mp_uint_t fdfile_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) {
-    mp_obj_fdfile_t *o = o_in;
+    mp_obj_fdfile_t *o = MP_OBJ_TO_PTR(o_in);
     check_fd_is_open(o);
     mp_int_t r = read(o->fd, buf, size);
     if (r == -1) {
@@ -78,7 +78,7 @@ STATIC mp_uint_t fdfile_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errc
 }
 
 STATIC mp_uint_t fdfile_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) {
-    mp_obj_fdfile_t *o = o_in;
+    mp_obj_fdfile_t *o = MP_OBJ_TO_PTR(o_in);
     check_fd_is_open(o);
     mp_int_t r = write(o->fd, buf, size);
     if (r == -1) {
@@ -88,8 +88,8 @@ STATIC mp_uint_t fdfile_write(mp_obj_t o_in, const void *buf, mp_uint_t size, in
     return r;
 }
 
-STATIC mp_uint_t fdfile_ioctl(mp_obj_t o_in, mp_uint_t request, mp_uint_t arg, int *errcode) {
-    mp_obj_fdfile_t *o = o_in;
+STATIC mp_uint_t fdfile_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, int *errcode) {
+    mp_obj_fdfile_t *o = MP_OBJ_TO_PTR(o_in);
     if (request == MP_STREAM_SEEK) {
         struct mp_stream_seek_t *s = (struct mp_stream_seek_t*)arg;
         off_t off = lseek(o->fd, s->offset, s->whence);
@@ -106,7 +106,7 @@ STATIC mp_uint_t fdfile_ioctl(mp_obj_t o_in, mp_uint_t request, mp_uint_t arg, i
 }
 
 STATIC mp_obj_t fdfile_flush(mp_obj_t self_in) {
-    mp_obj_fdfile_t *self = self_in;
+    mp_obj_fdfile_t *self = MP_OBJ_TO_PTR(self_in);
     check_fd_is_open(self);
     fsync(self->fd);
     return mp_const_none;
@@ -114,7 +114,7 @@ STATIC mp_obj_t fdfile_flush(mp_obj_t self_in) {
 STATIC MP_DEFINE_CONST_FUN_OBJ_1(fdfile_flush_obj, fdfile_flush);
 
 STATIC mp_obj_t fdfile_close(mp_obj_t self_in) {
-    mp_obj_fdfile_t *self = self_in;
+    mp_obj_fdfile_t *self = MP_OBJ_TO_PTR(self_in);
     close(self->fd);
 #ifdef MICROPY_CPYTHON_COMPAT
     self->fd = -1;
@@ -130,7 +130,7 @@ STATIC mp_obj_t fdfile___exit__(mp_uint_t n_args, const mp_obj_t *args) {
 STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(fdfile___exit___obj, 4, 4, fdfile___exit__);
 
 STATIC mp_obj_t fdfile_fileno(mp_obj_t self_in) {
-    mp_obj_fdfile_t *self = self_in;
+    mp_obj_fdfile_t *self = MP_OBJ_TO_PTR(self_in);
     check_fd_is_open(self);
     return MP_OBJ_NEW_SMALL_INT(self->fd);
 }
@@ -145,9 +145,8 @@ STATIC const mp_arg_t file_open_args[] = {
 };
 #define FILE_OPEN_NUM_ARGS MP_ARRAY_SIZE(file_open_args)
 
-STATIC mp_obj_t fdfile_open(mp_obj_t type_in, mp_arg_val_t *args) {
+STATIC mp_obj_t fdfile_open(const mp_obj_type_t *type, mp_arg_val_t *args) {
     mp_obj_fdfile_t *o = m_new_obj(mp_obj_fdfile_t);
-    mp_const_obj_t type = type_in;
     const char *mode_s = mp_obj_str_get_str(args[1].u_obj);
 
     int mode = 0;
@@ -184,7 +183,7 @@ STATIC mp_obj_t fdfile_open(mp_obj_t type_in, mp_arg_val_t *args) {
 
     if (MP_OBJ_IS_SMALL_INT(fid)) {
         o->fd = MP_OBJ_SMALL_INT_VALUE(fid);
-        return o;
+        return MP_OBJ_FROM_PTR(o);
     }
 
     const char *fname = mp_obj_str_get_str(fid);
@@ -193,13 +192,13 @@ STATIC mp_obj_t fdfile_open(mp_obj_t type_in, mp_arg_val_t *args) {
         nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(errno)));
     }
     o->fd = fd;
-    return o;
+    return MP_OBJ_FROM_PTR(o);
 }
 
 STATIC mp_obj_t fdfile_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
     mp_arg_val_t arg_vals[FILE_OPEN_NUM_ARGS];
     mp_arg_parse_all_kw_array(n_args, n_kw, args, FILE_OPEN_NUM_ARGS, file_open_args, arg_vals);
-    return fdfile_open(type_in, arg_vals);
+    return fdfile_open(MP_OBJ_TO_PTR(type_in), arg_vals);
 }
 
 STATIC const mp_rom_map_elem_t rawfile_locals_dict_table[] = {
@@ -235,7 +234,7 @@ const mp_obj_type_t mp_type_fileio = {
     .getiter = mp_identity,
     .iternext = mp_stream_unbuffered_iter,
     .stream_p = &fileio_stream_p,
-    .locals_dict = (mp_obj_t)&rawfile_locals_dict,
+    .locals_dict = (mp_obj_dict_t*)&rawfile_locals_dict,
 };
 #endif
 
@@ -254,7 +253,7 @@ const mp_obj_type_t mp_type_textio = {
     .getiter = mp_identity,
     .iternext = mp_stream_unbuffered_iter,
     .stream_p = &textio_stream_p,
-    .locals_dict = (mp_obj_t)&rawfile_locals_dict,
+    .locals_dict = (mp_obj_dict_t*)&rawfile_locals_dict,
 };
 
 // Factory function for I/O stream classes
@@ -262,7 +261,7 @@ mp_obj_t mp_builtin_open(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kwarg
     // TODO: analyze buffering args and instantiate appropriate type
     mp_arg_val_t arg_vals[FILE_OPEN_NUM_ARGS];
     mp_arg_parse_all(n_args, args, kwargs, FILE_OPEN_NUM_ARGS, file_open_args, arg_vals);
-    return fdfile_open((mp_obj_t)&mp_type_textio, arg_vals);
+    return fdfile_open(&mp_type_textio, arg_vals);
 }
 MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, mp_builtin_open);
 
diff --git a/unix/gccollect.c b/unix/gccollect.c
index 007fbfcdbc5b727323f5cc1862920058649698e6..125c273a308231dd2e5aeb11f2c7595e7b93edb1 100644
--- a/unix/gccollect.c
+++ b/unix/gccollect.c
@@ -144,7 +144,7 @@ void gc_collect(void) {
     gc_helper_get_regs(regs);
     // GC stack (and regs because we captured them)
     void **regs_ptr = (void**)(void*)&regs;
-    gc_collect_root(regs_ptr, ((mp_uint_t)MP_STATE_VM(stack_top) - (mp_uint_t)&regs) / sizeof(mp_uint_t));
+    gc_collect_root(regs_ptr, ((uintptr_t)MP_STATE_VM(stack_top) - (uintptr_t)&regs) / sizeof(uintptr_t));
     #if MICROPY_EMIT_NATIVE
     mp_unix_mark_exec();
     #endif
diff --git a/unix/main.c b/unix/main.c
index ae09b895d100d61c31782374b9a63d6844340f03..e22176e13a77e73660afe52457addc971e35dc8e 100644
--- a/unix/main.c
+++ b/unix/main.c
@@ -58,7 +58,7 @@ STATIC uint emit_opt = MP_EMIT_OPT_NONE;
 long heap_size = 1024*1024 * (sizeof(mp_uint_t) / 4);
 #endif
 
-STATIC void stderr_print_strn(void *env, const char *str, mp_uint_t len) {
+STATIC void stderr_print_strn(void *env, const char *str, size_t len) {
     (void)env;
     ssize_t dummy = write(STDERR_FILENO, str, len);
     (void)dummy;
@@ -70,11 +70,11 @@ const mp_print_t mp_stderr_print = {NULL, stderr_print_strn};
 // If exc is SystemExit, return value where FORCED_EXIT bit set,
 // and lower 8 bits are SystemExit value. For all other exceptions,
 // return 1.
-STATIC int handle_uncaught_exception(mp_obj_t exc) {
+STATIC int handle_uncaught_exception(mp_obj_base_t *exc) {
     // check for SystemExit
-    if (mp_obj_is_subclass_fast(mp_obj_get_type(exc), &mp_type_SystemExit)) {
+    if (mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(exc->type), MP_OBJ_FROM_PTR(&mp_type_SystemExit))) {
         // None is an exit value of 0; an int is its value; anything else is 1
-        mp_obj_t exit_val = mp_obj_exception_get_value(exc);
+        mp_obj_t exit_val = mp_obj_exception_get_value(MP_OBJ_FROM_PTR(exc));
         mp_int_t val = 0;
         if (exit_val != mp_const_none && !mp_obj_get_int_maybe(exit_val, &val)) {
             val = 1;
@@ -83,7 +83,7 @@ STATIC int handle_uncaught_exception(mp_obj_t exc) {
     }
 
     // Report all other exceptions
-    mp_obj_print_exception(&mp_stderr_print, exc);
+    mp_obj_print_exception(&mp_stderr_print, MP_OBJ_FROM_PTR(exc));
     return 1;
 }
 
@@ -130,7 +130,7 @@ STATIC int execute_from_lexer(mp_lexer_t *lex, mp_parse_input_kind_t input_kind,
     } else {
         // uncaught exception
         mp_hal_set_interrupt_char(-1);
-        return handle_uncaught_exception((mp_obj_t)nlr.ret_val);
+        return handle_uncaught_exception(nlr.ret_val);
     }
 }
 
@@ -364,7 +364,26 @@ STATIC void set_sys_argv(char *argv[], int argc, int start_arg) {
 #define PATHLIST_SEP_CHAR ':'
 #endif
 
+/*
+typedef union _a_t { uint32_t u32; uint64_t u64; } a_t;
+STATIC const uint64_t table[4] = {
+    1,
+    2,
+    3,
+    //(a_t){(uint32_t)&set_sys_argv}.u64,
+    ((a_t){(uint32_t)123}).u64,
+};
+*/
+
 int main(int argc, char **argv) {
+    /*
+    printf("sizeof(void*)=%u\n", (uint)sizeof(void*));
+    for (int i = 0; i < sizeof(table); ++i) {
+        byte *ptr = (void*)&table[0];
+        printf(" %02x", ptr[i]);
+        if ((i + 1)%8 == 0) printf("\n");
+    }
+    */
     mp_stack_set_limit(40000 * (BYTES_PER_WORD / 4));
 
     pre_process_options(argc, argv);
@@ -397,7 +416,7 @@ int main(int argc, char **argv) {
             p++;
         }
     }
-    mp_obj_list_init(mp_sys_path, path_num);
+    mp_obj_list_init(MP_OBJ_TO_PTR(mp_sys_path), path_num);
     mp_obj_t *path_items;
     mp_obj_list_get(mp_sys_path, &path_num, &path_items);
     path_items[0] = MP_OBJ_NEW_QSTR(MP_QSTR_);
@@ -421,7 +440,7 @@ int main(int argc, char **argv) {
     }
     }
 
-    mp_obj_list_init(mp_sys_argv, 0);
+    mp_obj_list_init(MP_OBJ_TO_PTR(mp_sys_argv), 0);
 
     #if defined(MICROPY_UNIX_COVERAGE)
     {
@@ -487,7 +506,7 @@ int main(int argc, char **argv) {
                     nlr_pop();
                 } else {
                     // uncaught exception
-                    return handle_uncaught_exception((mp_obj_t)nlr.ret_val) & 0xff;
+                    return handle_uncaught_exception(nlr.ret_val) & 0xff;
                 }
 
                 if (mp_obj_is_package(mod)) {
diff --git a/unix/modffi.c b/unix/modffi.c
index 48834fb739c78dea92fb7f0f6caca74de13dd6f6..c998a809e4bc2029be6e547b914b67f5b3c12a19 100644
--- a/unix/modffi.c
+++ b/unix/modffi.c
@@ -170,12 +170,12 @@ STATIC mp_obj_t return_ffi_value(ffi_arg val, char type)
 
 STATIC void ffimod_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
     (void)kind;
-    mp_obj_ffimod_t *self = self_in;
+    mp_obj_ffimod_t *self = MP_OBJ_TO_PTR(self_in);
     mp_printf(print, "<ffimod %p>", self->handle);
 }
 
 STATIC mp_obj_t ffimod_close(mp_obj_t self_in) {
-    mp_obj_ffimod_t *self = self_in;
+    mp_obj_ffimod_t *self = MP_OBJ_TO_PTR(self_in);
     dlclose(self->handle);
     return mp_const_none;
 }
@@ -205,12 +205,12 @@ STATIC mp_obj_t make_func(mp_obj_t rettype_in, void *func, mp_obj_t argtypes_in)
         nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Error in ffi_prep_cif"));
     }
 
-    return o;
+    return MP_OBJ_FROM_PTR(o);
 }
 
 STATIC mp_obj_t ffimod_func(mp_uint_t n_args, const mp_obj_t *args) {
     (void)n_args; // always 4
-    mp_obj_ffimod_t *self = args[0];
+    mp_obj_ffimod_t *self = MP_OBJ_TO_PTR(args[0]);
     const char *symname = mp_obj_str_get_str(args[2]);
 
     void *sym = dlsym(self->handle, symname);
@@ -222,7 +222,7 @@ STATIC mp_obj_t ffimod_func(mp_uint_t n_args, const mp_obj_t *args) {
 MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(ffimod_func_obj, 4, 4, ffimod_func);
 
 STATIC mp_obj_t mod_ffi_func(mp_obj_t rettype, mp_obj_t addr_in, mp_obj_t argtypes) {
-    void *addr = (void*)mp_obj_int_get_truncated(addr_in);
+    void *addr = (void*)MP_OBJ_TO_PTR(mp_obj_int_get_truncated(addr_in));
     return make_func(rettype, addr, argtypes);
 }
 MP_DEFINE_CONST_FUN_OBJ_3(mod_ffi_func_obj, mod_ffi_func);
@@ -267,12 +267,12 @@ STATIC mp_obj_t mod_ffi_callback(mp_obj_t rettype_in, mp_obj_t func_in, mp_obj_t
         nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "ffi_prep_closure_loc"));
     }
 
-    return o;
+    return MP_OBJ_FROM_PTR(o);
 }
 MP_DEFINE_CONST_FUN_OBJ_3(mod_ffi_callback_obj, mod_ffi_callback);
 
 STATIC mp_obj_t ffimod_var(mp_obj_t self_in, mp_obj_t vartype_in, mp_obj_t symname_in) {
-    mp_obj_ffimod_t *self = self_in;
+    mp_obj_ffimod_t *self = MP_OBJ_TO_PTR(self_in);
     const char *rettype = mp_obj_str_get_str(vartype_in);
     const char *symname = mp_obj_str_get_str(symname_in);
 
@@ -285,12 +285,12 @@ STATIC mp_obj_t ffimod_var(mp_obj_t self_in, mp_obj_t vartype_in, mp_obj_t symna
 
     o->var = sym;
     o->type = *rettype;
-    return o;
+    return MP_OBJ_FROM_PTR(o);
 }
 MP_DEFINE_CONST_FUN_OBJ_3(ffimod_var_obj, ffimod_var);
 
 STATIC mp_obj_t ffimod_addr(mp_obj_t self_in, mp_obj_t symname_in) {
-    mp_obj_ffimod_t *self = self_in;
+    mp_obj_ffimod_t *self = MP_OBJ_TO_PTR(self_in);
     const char *symname = mp_obj_str_get_str(symname_in);
 
     void *sym = dlsym(self->handle, symname);
@@ -315,9 +315,9 @@ STATIC mp_obj_t ffimod_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_
         nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(errno)));
     }
     mp_obj_ffimod_t *o = m_new_obj(mp_obj_ffimod_t);
-    o->base.type = type_in;
+    o->base.type = MP_OBJ_TO_PTR(type_in);
     o->handle = mod;
-    return o;
+    return MP_OBJ_FROM_PTR(o);
 }
 
 STATIC const mp_rom_map_elem_t ffimod_locals_dict_table[] = {
@@ -334,19 +334,19 @@ STATIC const mp_obj_type_t ffimod_type = {
     .name = MP_QSTR_ffimod,
     .print = ffimod_print,
     .make_new = ffimod_make_new,
-    .locals_dict = (mp_obj_t)&ffimod_locals_dict,
+    .locals_dict = (mp_obj_dict_t*)&ffimod_locals_dict,
 };
 
 // FFI function
 
 STATIC void ffifunc_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
     (void)kind;
-    mp_obj_ffifunc_t *self = self_in;
+    mp_obj_ffifunc_t *self = MP_OBJ_TO_PTR(self_in);
     mp_printf(print, "<ffifunc %p>", self->func);
 }
 
 STATIC mp_obj_t ffifunc_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
-    mp_obj_ffifunc_t *self = self_in;
+    mp_obj_ffifunc_t *self = MP_OBJ_TO_PTR(self_in);
     assert(n_kw == 0);
     assert(n_args == self->cif.nargs);
 
diff --git a/unix/modos.c b/unix/modos.c
index 3e8c5a6eb401e32d6c8f45977a065c231c47ee7b..faf33dac9cb25bb995b296743fa7e7cc5cebc349 100644
--- a/unix/modos.c
+++ b/unix/modos.c
@@ -53,7 +53,7 @@ STATIC mp_obj_t mod_os_stat(mp_obj_t path_in) {
     int res = stat(path, &sb);
     RAISE_ERRNO(res, errno);
 
-    mp_obj_tuple_t *t = mp_obj_new_tuple(10, NULL);
+    mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(10, NULL));
     t->items[0] = MP_OBJ_NEW_SMALL_INT(sb.st_mode);
     t->items[1] = MP_OBJ_NEW_SMALL_INT(sb.st_ino);
     t->items[2] = MP_OBJ_NEW_SMALL_INT(sb.st_dev);
@@ -64,7 +64,7 @@ STATIC mp_obj_t mod_os_stat(mp_obj_t path_in) {
     t->items[7] = MP_OBJ_NEW_SMALL_INT(sb.st_atime);
     t->items[8] = MP_OBJ_NEW_SMALL_INT(sb.st_mtime);
     t->items[9] = MP_OBJ_NEW_SMALL_INT(sb.st_ctime);
-    return t;
+    return MP_OBJ_FROM_PTR(t);
 }
 STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_os_stat_obj, mod_os_stat);
 
@@ -94,7 +94,7 @@ STATIC mp_obj_t mod_os_statvfs(mp_obj_t path_in) {
     int res = STATVFS(path, &sb);
     RAISE_ERRNO(res, errno);
 
-    mp_obj_tuple_t *t = mp_obj_new_tuple(10, NULL);
+    mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(10, NULL));
     t->items[0] = MP_OBJ_NEW_SMALL_INT(sb.f_bsize);
     t->items[1] = MP_OBJ_NEW_SMALL_INT(sb.f_frsize);
     t->items[2] = MP_OBJ_NEW_SMALL_INT(sb.f_blocks);
@@ -105,7 +105,7 @@ STATIC mp_obj_t mod_os_statvfs(mp_obj_t path_in) {
     t->items[7] = MP_OBJ_NEW_SMALL_INT(F_FAVAIL);
     t->items[8] = MP_OBJ_NEW_SMALL_INT(F_FLAG);
     t->items[9] = MP_OBJ_NEW_SMALL_INT(F_NAMEMAX);
-    return t;
+    return MP_OBJ_FROM_PTR(t);
 }
 STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_os_statvfs_obj, mod_os_statvfs);
 #endif
diff --git a/unix/modsocket.c b/unix/modsocket.c
index db36c727ace31461ddddf28d8dc935739d7c53c8..6a7c3f5510533df68a816259ee31eb525ce32aa1 100644
--- a/unix/modsocket.c
+++ b/unix/modsocket.c
@@ -88,12 +88,12 @@ STATIC mp_obj_socket_t *socket_new(int fd) {
 
 STATIC void socket_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
     (void)kind;
-    mp_obj_socket_t *self = self_in;
+    mp_obj_socket_t *self = MP_OBJ_TO_PTR(self_in);
     mp_printf(print, "<_socket %d>", self->fd);
 }
 
 STATIC mp_uint_t socket_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) {
-    mp_obj_socket_t *o = o_in;
+    mp_obj_socket_t *o = MP_OBJ_TO_PTR(o_in);
     mp_int_t r = read(o->fd, buf, size);
     if (r == -1) {
         *errcode = errno;
@@ -103,7 +103,7 @@ STATIC mp_uint_t socket_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errc
 }
 
 STATIC mp_uint_t socket_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) {
-    mp_obj_socket_t *o = o_in;
+    mp_obj_socket_t *o = MP_OBJ_TO_PTR(o_in);
     mp_int_t r = write(o->fd, buf, size);
     if (r == -1) {
         *errcode = errno;
@@ -113,20 +113,20 @@ STATIC mp_uint_t socket_write(mp_obj_t o_in, const void *buf, mp_uint_t size, in
 }
 
 STATIC mp_obj_t socket_close(mp_obj_t self_in) {
-    mp_obj_socket_t *self = self_in;
+    mp_obj_socket_t *self = MP_OBJ_TO_PTR(self_in);
     close(self->fd);
     return mp_const_none;
 }
 STATIC MP_DEFINE_CONST_FUN_OBJ_1(socket_close_obj, socket_close);
 
 STATIC mp_obj_t socket_fileno(mp_obj_t self_in) {
-    mp_obj_socket_t *self = self_in;
+    mp_obj_socket_t *self = MP_OBJ_TO_PTR(self_in);
     return MP_OBJ_NEW_SMALL_INT(self->fd);
 }
 STATIC MP_DEFINE_CONST_FUN_OBJ_1(socket_fileno_obj, socket_fileno);
 
 STATIC mp_obj_t socket_connect(mp_obj_t self_in, mp_obj_t addr_in) {
-    mp_obj_socket_t *self = self_in;
+    mp_obj_socket_t *self = MP_OBJ_TO_PTR(self_in);
     mp_buffer_info_t bufinfo;
     mp_get_buffer_raise(addr_in, &bufinfo, MP_BUFFER_READ);
     int r = connect(self->fd, (const struct sockaddr *)bufinfo.buf, bufinfo.len);
@@ -136,7 +136,7 @@ STATIC mp_obj_t socket_connect(mp_obj_t self_in, mp_obj_t addr_in) {
 STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_connect_obj, socket_connect);
 
 STATIC mp_obj_t socket_bind(mp_obj_t self_in, mp_obj_t addr_in) {
-    mp_obj_socket_t *self = self_in;
+    mp_obj_socket_t *self = MP_OBJ_TO_PTR(self_in);
     mp_buffer_info_t bufinfo;
     mp_get_buffer_raise(addr_in, &bufinfo, MP_BUFFER_READ);
     int r = bind(self->fd, (const struct sockaddr *)bufinfo.buf, bufinfo.len);
@@ -146,7 +146,7 @@ STATIC mp_obj_t socket_bind(mp_obj_t self_in, mp_obj_t addr_in) {
 STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_bind_obj, socket_bind);
 
 STATIC mp_obj_t socket_listen(mp_obj_t self_in, mp_obj_t backlog_in) {
-    mp_obj_socket_t *self = self_in;
+    mp_obj_socket_t *self = MP_OBJ_TO_PTR(self_in);
     int r = listen(self->fd, MP_OBJ_SMALL_INT_VALUE(backlog_in));
     RAISE_ERRNO(r, errno);
     return mp_const_none;
@@ -154,17 +154,17 @@ STATIC mp_obj_t socket_listen(mp_obj_t self_in, mp_obj_t backlog_in) {
 STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_listen_obj, socket_listen);
 
 STATIC mp_obj_t socket_accept(mp_obj_t self_in) {
-    mp_obj_socket_t *self = self_in;
+    mp_obj_socket_t *self = MP_OBJ_TO_PTR(self_in);
     struct sockaddr addr;
     socklen_t addr_len = sizeof(addr);
     int fd = accept(self->fd, &addr, &addr_len);
     RAISE_ERRNO(fd, errno);
 
-    mp_obj_tuple_t *t = mp_obj_new_tuple(2, NULL);
-    t->items[0] = socket_new(fd);
+    mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(2, NULL));
+    t->items[0] = MP_OBJ_FROM_PTR(socket_new(fd));
     t->items[1] = mp_obj_new_bytearray(addr_len, &addr);
 
-    return t;
+    return MP_OBJ_FROM_PTR(t);
 }
 STATIC MP_DEFINE_CONST_FUN_OBJ_1(socket_accept_obj, socket_accept);
 
@@ -172,7 +172,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(socket_accept_obj, socket_accept);
 // this does not swallow blocking errors (EAGAIN, EWOULDBLOCK) -
 // these would be thrown as exceptions.
 STATIC mp_obj_t socket_recv(mp_uint_t n_args, const mp_obj_t *args) {
-    mp_obj_socket_t *self = args[0];
+    mp_obj_socket_t *self = MP_OBJ_TO_PTR(args[0]);
     int sz = MP_OBJ_SMALL_INT_VALUE(args[1]);
     int flags = 0;
 
@@ -191,7 +191,7 @@ STATIC mp_obj_t socket_recv(mp_uint_t n_args, const mp_obj_t *args) {
 STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_recv_obj, 2, 3, socket_recv);
 
 STATIC mp_obj_t socket_recvfrom(mp_uint_t n_args, const mp_obj_t *args) {
-    mp_obj_socket_t *self = args[0];
+    mp_obj_socket_t *self = MP_OBJ_TO_PTR(args[0]);
     int sz = MP_OBJ_SMALL_INT_VALUE(args[1]);
     int flags = 0;
 
@@ -209,11 +209,11 @@ STATIC mp_obj_t socket_recvfrom(mp_uint_t n_args, const mp_obj_t *args) {
     mp_obj_t buf_o = mp_obj_new_str_of_type(&mp_type_bytes, buf, out_sz);
     m_del(char, buf, sz);
 
-    mp_obj_tuple_t *t = mp_obj_new_tuple(2, NULL);
+    mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(2, NULL));
     t->items[0] = buf_o;
     t->items[1] = mp_obj_from_sockaddr((struct sockaddr*)&addr, addr_len);
 
-    return t;
+    return MP_OBJ_FROM_PTR(t);
 }
 STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_recvfrom_obj, 2, 3, socket_recvfrom);
 
@@ -221,7 +221,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_recvfrom_obj, 2, 3, socket_rec
 // this does not swallow blocking errors (EAGAIN, EWOULDBLOCK) -
 // these would be thrown as exceptions.
 STATIC mp_obj_t socket_send(mp_uint_t n_args, const mp_obj_t *args) {
-    mp_obj_socket_t *self = args[0];
+    mp_obj_socket_t *self = MP_OBJ_TO_PTR(args[0]);
     int flags = 0;
 
     if (n_args > 2) {
@@ -238,7 +238,7 @@ STATIC mp_obj_t socket_send(mp_uint_t n_args, const mp_obj_t *args) {
 STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_send_obj, 2, 3, socket_send);
 
 STATIC mp_obj_t socket_sendto(mp_uint_t n_args, const mp_obj_t *args) {
-    mp_obj_socket_t *self = args[0];
+    mp_obj_socket_t *self = MP_OBJ_TO_PTR(args[0]);
     int flags = 0;
 
     mp_obj_t dst_addr = args[2];
@@ -260,7 +260,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_sendto_obj, 3, 4, socket_sendt
 
 STATIC mp_obj_t socket_setsockopt(mp_uint_t n_args, const mp_obj_t *args) {
     (void)n_args; // always 4
-    mp_obj_socket_t *self = args[0];
+    mp_obj_socket_t *self = MP_OBJ_TO_PTR(args[0]);
     int level = MP_OBJ_SMALL_INT_VALUE(args[1]);
     int option = mp_obj_get_int(args[2]);
 
@@ -284,7 +284,7 @@ STATIC mp_obj_t socket_setsockopt(mp_uint_t n_args, const mp_obj_t *args) {
 STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_setsockopt_obj, 4, 4, socket_setsockopt);
 
 STATIC mp_obj_t socket_setblocking(mp_obj_t self_in, mp_obj_t flag_in) {
-    mp_obj_socket_t *self = self_in;
+    mp_obj_socket_t *self = MP_OBJ_TO_PTR(self_in);
     int val = mp_obj_is_true(flag_in);
     int flags = fcntl(self->fd, F_GETFL, 0);
     RAISE_ERRNO(flags, errno);
@@ -303,7 +303,7 @@ STATIC mp_obj_t socket_makefile(mp_uint_t n_args, const mp_obj_t *args) {
     // TODO: CPython explicitly says that closing returned object doesn't close
     // the original socket (Python2 at all says that fd is dup()ed). But we
     // save on the bloat.
-    mp_obj_socket_t *self = args[0];
+    mp_obj_socket_t *self = MP_OBJ_TO_PTR(args[0]);
     mp_obj_t *new_args = alloca(n_args * sizeof(mp_obj_t));
     memcpy(new_args + 1, args + 1, (n_args - 1) * sizeof(mp_obj_t));
     new_args[0] = MP_OBJ_NEW_SMALL_INT(self->fd);
@@ -336,7 +336,7 @@ STATIC mp_obj_t socket_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_
 
     int fd = socket(family, type, proto);
     RAISE_ERRNO(fd, errno);
-    return socket_new(fd);
+    return MP_OBJ_FROM_PTR(socket_new(fd));
 }
 
 STATIC const mp_rom_map_elem_t usocket_locals_dict_table[] = {
@@ -375,7 +375,7 @@ STATIC const mp_obj_type_t usocket_type = {
     .getiter = NULL,
     .iternext = NULL,
     .stream_p = &usocket_stream_p,
-    .locals_dict = (mp_obj_t)&usocket_locals_dict,
+    .locals_dict = (mp_obj_dict_t*)&usocket_locals_dict,
 };
 
 #if MICROPY_SOCKET_EXTRA
@@ -474,7 +474,7 @@ STATIC mp_obj_t mod_socket_getaddrinfo(mp_uint_t n_args, const mp_obj_t *args) {
 
     mp_obj_t list = mp_obj_new_list(0, NULL);
     for (struct addrinfo *addr = addr_list; addr; addr = addr->ai_next) {
-        mp_obj_tuple_t *t = mp_obj_new_tuple(5, NULL);
+        mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(5, NULL));
         t->items[0] = MP_OBJ_NEW_SMALL_INT(addr->ai_family);
         t->items[1] = MP_OBJ_NEW_SMALL_INT(addr->ai_socktype);
         t->items[2] = MP_OBJ_NEW_SMALL_INT(addr->ai_protocol);
@@ -486,7 +486,7 @@ STATIC mp_obj_t mod_socket_getaddrinfo(mp_uint_t n_args, const mp_obj_t *args) {
             t->items[3] = mp_const_none;
         }
         t->items[4] = mp_obj_new_bytearray(addr->ai_addrlen, addr->ai_addr);
-        mp_obj_list_append(list, t);
+        mp_obj_list_append(list, MP_OBJ_FROM_PTR(t));
     }
     freeaddrinfo(addr_list);
     return list;
@@ -499,18 +499,18 @@ STATIC mp_obj_t mod_socket_sockaddr(mp_obj_t sockaddr_in) {
     switch (((struct sockaddr*)bufinfo.buf)->sa_family) {
         case AF_INET: {
             struct sockaddr_in *sa = (struct sockaddr_in*)bufinfo.buf;
-            mp_obj_tuple_t *t = mp_obj_new_tuple(3, NULL);
+            mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(3, NULL));
             t->items[0] = MP_OBJ_NEW_SMALL_INT(AF_INET);
             t->items[1] = mp_obj_new_bytes((byte*)&sa->sin_addr, sizeof(sa->sin_addr));
             t->items[2] = MP_OBJ_NEW_SMALL_INT(ntohs(sa->sin_port));
-            return t;
+            return MP_OBJ_FROM_PTR(t);
         }
         default: {
             struct sockaddr *sa = (struct sockaddr*)bufinfo.buf;
-            mp_obj_tuple_t *t = mp_obj_new_tuple(2, NULL);
+            mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(2, NULL));
             t->items[0] = MP_OBJ_NEW_SMALL_INT(sa->sa_family);
             t->items[1] = mp_obj_new_bytes((byte*)sa->sa_data, bufinfo.len - offsetof(struct sockaddr, sa_data));
-            return t;
+            return MP_OBJ_FROM_PTR(t);
         }
     }
     return mp_const_none;
diff --git a/unix/modtermios.c b/unix/modtermios.c
index c49014c940145538104b0e5efa01c20efcee9b0c..a70edf5bf45f711f42433b7014740ca62ac8ab9d 100644
--- a/unix/modtermios.c
+++ b/unix/modtermios.c
@@ -44,7 +44,7 @@ STATIC mp_obj_t mod_termios_tcgetattr(mp_obj_t fd_in) {
     int res = tcgetattr(fd, &term);
     RAISE_ERRNO(res, errno);
 
-    mp_obj_list_t *r = mp_obj_new_list(7, NULL);
+    mp_obj_list_t *r = MP_OBJ_TO_PTR(mp_obj_new_list(7, NULL));
     r->items[0] = MP_OBJ_NEW_SMALL_INT(term.c_iflag);
     r->items[1] = MP_OBJ_NEW_SMALL_INT(term.c_oflag);
     r->items[2] = MP_OBJ_NEW_SMALL_INT(term.c_cflag);
@@ -52,8 +52,8 @@ STATIC mp_obj_t mod_termios_tcgetattr(mp_obj_t fd_in) {
     r->items[4] = MP_OBJ_NEW_SMALL_INT(cfgetispeed(&term));
     r->items[5] = MP_OBJ_NEW_SMALL_INT(cfgetospeed(&term));
 
-    mp_obj_list_t *cc = mp_obj_new_list(NCCS, NULL);
-    r->items[6] = cc;
+    mp_obj_list_t *cc = MP_OBJ_TO_PTR(mp_obj_new_list(NCCS, NULL));
+    r->items[6] = MP_OBJ_FROM_PTR(cc);
     for (int i = 0; i < NCCS; i++) {
         if (i == VMIN || i == VTIME) {
             cc->items[i] = MP_OBJ_NEW_SMALL_INT(term.c_cc[i]);
@@ -63,7 +63,7 @@ STATIC mp_obj_t mod_termios_tcgetattr(mp_obj_t fd_in) {
             cc->items[i] = mp_obj_new_bytes(&term.c_cc[i], 1);
         }
     }
-    return r;
+    return MP_OBJ_FROM_PTR(r);
 }
 STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_termios_tcgetattr_obj, mod_termios_tcgetattr);
 
@@ -80,14 +80,14 @@ STATIC mp_obj_t mod_termios_tcsetattr(mp_obj_t fd_in, mp_obj_t when_in, mp_obj_t
     }
 
     assert(MP_OBJ_IS_TYPE(attrs_in, &mp_type_list));
-    mp_obj_list_t *attrs = attrs_in;
+    mp_obj_list_t *attrs = MP_OBJ_TO_PTR(attrs_in);
 
     term.c_iflag = mp_obj_get_int(attrs->items[0]);
     term.c_oflag = mp_obj_get_int(attrs->items[1]);
     term.c_cflag = mp_obj_get_int(attrs->items[2]);
     term.c_lflag = mp_obj_get_int(attrs->items[3]);
 
-    mp_obj_list_t *cc = attrs->items[6];
+    mp_obj_list_t *cc = MP_OBJ_TO_PTR(attrs->items[6]);
     for (int i = 0; i < NCCS; i++) {
         if (i == VMIN || i == VTIME) {
             term.c_cc[i] = mp_obj_get_int(cc->items[i]);
diff --git a/unix/moduselect.c b/unix/moduselect.c
index 41255ff904de3a20d6bcb2f5efb15ef1a7fd45aa..0d06cc5309092a89d5993148c0153ca75942a8aa 100644
--- a/unix/moduselect.c
+++ b/unix/moduselect.c
@@ -46,7 +46,7 @@ typedef struct _mp_obj_poll_t {
 
 /// \method register(obj[, eventmask])
 STATIC mp_obj_t poll_register(uint n_args, const mp_obj_t *args) {
-    mp_obj_poll_t *self = args[0];
+    mp_obj_poll_t *self = MP_OBJ_TO_PTR(args[0]);
     mp_uint_t flags;
     if (n_args == 3) {
         flags = mp_obj_get_int(args[2]);
@@ -79,7 +79,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(poll_register_obj, 2, 3, poll_register);
 
 /// \method unregister(obj)
 STATIC mp_obj_t poll_unregister(mp_obj_t self_in, mp_obj_t obj_in) {
-    mp_obj_poll_t *self = self_in;
+    mp_obj_poll_t *self = MP_OBJ_TO_PTR(self_in);
     struct pollfd *entries = self->entries;
     int fd = mp_obj_get_int(obj_in);
     for (int i = self->len - 1; i >= 0; i--) {
@@ -97,7 +97,7 @@ MP_DEFINE_CONST_FUN_OBJ_2(poll_unregister_obj, poll_unregister);
 
 /// \method modify(obj, eventmask)
 STATIC mp_obj_t poll_modify(mp_obj_t self_in, mp_obj_t obj_in, mp_obj_t eventmask_in) {
-    mp_obj_poll_t *self = self_in;
+    mp_obj_poll_t *self = MP_OBJ_TO_PTR(self_in);
     struct pollfd *entries = self->entries;
     int fd = mp_obj_get_int(obj_in);
     for (int i = self->len - 1; i >= 0; i--) {
@@ -116,7 +116,7 @@ MP_DEFINE_CONST_FUN_OBJ_3(poll_modify_obj, poll_modify);
 /// \method poll([timeout])
 /// Timeout is in milliseconds.
 STATIC mp_obj_t poll_poll(uint n_args, const mp_obj_t *args) {
-    mp_obj_poll_t *self = args[0];
+    mp_obj_poll_t *self = MP_OBJ_TO_PTR(args[0]);
 
     // work out timeout (its given already in ms)
     int timeout = -1;
@@ -135,19 +135,19 @@ STATIC mp_obj_t poll_poll(uint n_args, const mp_obj_t *args) {
         return mp_const_empty_tuple;
     }
 
-    mp_obj_list_t *ret_list = mp_obj_new_list(n_ready, NULL);
+    mp_obj_list_t *ret_list = MP_OBJ_TO_PTR(mp_obj_new_list(n_ready, NULL));
     int ret_i = 0;
     struct pollfd *entries = self->entries;
     for (int i = 0; i < self->len; i++, entries++) {
         if (entries->revents != 0) {
-            mp_obj_tuple_t *t = mp_obj_new_tuple(2, NULL);
+            mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(2, NULL));
             t->items[0] = MP_OBJ_NEW_SMALL_INT(entries->fd);
             t->items[1] = MP_OBJ_NEW_SMALL_INT(entries->revents);
-            ret_list->items[ret_i++] = t;
+            ret_list->items[ret_i++] = MP_OBJ_FROM_PTR(t);
         }
     }
 
-    return ret_list;
+    return MP_OBJ_FROM_PTR(ret_list);
 }
 MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(poll_poll_obj, 1, 2, poll_poll);
 
@@ -162,7 +162,7 @@ STATIC MP_DEFINE_CONST_DICT(poll_locals_dict, poll_locals_dict_table);
 STATIC const mp_obj_type_t mp_type_poll = {
     { &mp_type_type },
     .name = MP_QSTR_poll,
-    .locals_dict = (mp_obj_t)&poll_locals_dict,
+    .locals_dict = (void*)&poll_locals_dict,
 };
 
 STATIC mp_obj_t select_poll(mp_uint_t n_args, const mp_obj_t *args) {
@@ -175,7 +175,7 @@ STATIC mp_obj_t select_poll(mp_uint_t n_args, const mp_obj_t *args) {
     poll->entries = m_new(struct pollfd, alloc);
     poll->alloc = alloc;
     poll->len = 0;
-    return poll;
+    return MP_OBJ_FROM_PTR(poll);
 }
 MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_select_poll_obj, 0, 1, select_poll);