emitglue.c 6.19 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/*
 * This file is part of the Micro Python project, http://micropython.org/
 *
 * The MIT License (MIT)
 *
 * Copyright (c) 2013, 2014 Damien P. George
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

27
28
// This code glues the code emitters to the runtime.

29
#include <stdint.h>
30
#include <stdio.h>
31
#include <string.h>
32
33
#include <assert.h>

34
35
36
#include "py/emitglue.h"
#include "py/runtime0.h"
#include "py/bc.h"
37
38
39
40
41
42
43
44
45
46
47

#if 0 // print debugging info
#define DEBUG_PRINT (1)
#define WRITE_CODE (1)
#define DEBUG_printf DEBUG_printf
#define DEBUG_OP_printf(...) DEBUG_printf(__VA_ARGS__)
#else // don't print debugging info
#define DEBUG_printf(...) (void)0
#define DEBUG_OP_printf(...) (void)0
#endif

48
49
50
51
#if MICROPY_DEBUG_PRINTERS
mp_uint_t mp_verbose_flag = 0;
#endif

52
53
54
55
mp_raw_code_t *mp_emit_glue_new_raw_code(void) {
    mp_raw_code_t *rc = m_new0(mp_raw_code_t, 1);
    rc->kind = MP_CODE_RESERVED;
    return rc;
56
57
}

58
59
60
61
62
63
64
void mp_emit_glue_assign_bytecode(mp_raw_code_t *rc, const byte *code, mp_uint_t len,
    const mp_uint_t *const_table,
    #if MICROPY_PERSISTENT_CODE_SAVE
    uint16_t n_obj, uint16_t n_raw_code,
    #endif
    mp_uint_t scope_flags) {

65
    rc->kind = MP_CODE_BYTECODE;
66
    rc->scope_flags = scope_flags;
67
    rc->data.u_byte.bytecode = code;
68
    rc->data.u_byte.const_table = const_table;
69
70
71
72
73
    #if MICROPY_PERSISTENT_CODE_SAVE
    rc->data.u_byte.bc_len = len;
    rc->data.u_byte.n_obj = n_obj;
    rc->data.u_byte.n_raw_code = n_raw_code;
    #endif
74
75

#ifdef DEBUG_PRINT
76
    DEBUG_printf("assign byte code: code=%p len=" UINT_FMT " flags=%x\n", code, len, (uint)scope_flags);
77
#endif
78
#if MICROPY_DEBUG_PRINTERS
79
    if (mp_verbose_flag >= 2) {
80
        mp_bytecode_print(rc, code, len, const_table);
81
    }
82
83
84
#endif
}

85
#if MICROPY_EMIT_NATIVE || MICROPY_EMIT_INLINE_THUMB
86
void mp_emit_glue_assign_native(mp_raw_code_t *rc, mp_raw_code_kind_t kind, void *fun_data, mp_uint_t fun_len, const mp_uint_t *const_table, mp_uint_t n_pos_args, mp_uint_t scope_flags, mp_uint_t type_sig) {
87
88
    assert(kind == MP_CODE_NATIVE_PY || kind == MP_CODE_NATIVE_VIPER || kind == MP_CODE_NATIVE_ASM);
    rc->kind = kind;
89
90
    rc->scope_flags = scope_flags;
    rc->n_pos_args = n_pos_args;
91
    rc->data.u_native.fun_data = fun_data;
92
    rc->data.u_native.const_table = const_table;
93
    rc->data.u_native.type_sig = type_sig;
94
95

#ifdef DEBUG_PRINT
96
    DEBUG_printf("assign native: kind=%d fun=%p len=" UINT_FMT " n_pos_args=" UINT_FMT " flags=%x\n", kind, fun_data, fun_len, n_pos_args, (uint)scope_flags);
97
    for (mp_uint_t i = 0; i < fun_len; i++) {
98
99
100
        if (i > 0 && i % 16 == 0) {
            DEBUG_printf("\n");
        }
101
        DEBUG_printf(" %02x", ((byte*)fun_data)[i]);
102
103
104
105
    }
    DEBUG_printf("\n");

#ifdef WRITE_CODE
106
    FILE *fp_write_code = fopen("out-code", "wb");
107
    fwrite(fun_data, fun_len, 1, fp_write_code);
108
    fclose(fp_write_code);
109
#endif
110
111
#else
    (void)fun_len;
112
113
#endif
}
114
#endif
115

116
mp_obj_t mp_make_function_from_raw_code(const mp_raw_code_t *rc, mp_obj_t def_args, mp_obj_t def_kw_args) {
117
118
    DEBUG_OP_printf("make_function_from_raw_code %p\n", rc);
    assert(rc != NULL);
119

120
121
122
    // def_args must be MP_OBJ_NULL or a tuple
    assert(def_args == MP_OBJ_NULL || MP_OBJ_IS_TYPE(def_args, &mp_type_tuple));

123
124
    // def_kw_args must be MP_OBJ_NULL or a dict
    assert(def_kw_args == MP_OBJ_NULL || MP_OBJ_IS_TYPE(def_kw_args, &mp_type_dict));
125

126
    // make the function, depending on the raw code kind
127
    mp_obj_t fun;
128
    switch (rc->kind) {
129
        case MP_CODE_BYTECODE:
130
        no_other_choice:
131
            fun = mp_obj_new_fun_bc(def_args, def_kw_args, rc->data.u_byte.bytecode, rc->data.u_byte.const_table);
132
            break;
133
        #if MICROPY_EMIT_NATIVE
134
        case MP_CODE_NATIVE_PY:
135
            fun = mp_obj_new_fun_native(def_args, def_kw_args, rc->data.u_native.fun_data, rc->data.u_native.const_table);
136
            break;
137
        case MP_CODE_NATIVE_VIPER:
138
            fun = mp_obj_new_fun_viper(rc->n_pos_args, rc->data.u_native.fun_data, rc->data.u_native.type_sig);
139
140
141
            break;
        #endif
        #if MICROPY_EMIT_INLINE_THUMB
142
        case MP_CODE_NATIVE_ASM:
143
            fun = mp_obj_new_fun_asm(rc->n_pos_args, rc->data.u_native.fun_data, rc->data.u_native.type_sig);
144
            break;
145
        #endif
146
        default:
147
            // raw code was never set (this should not happen)
148
            assert(0);
149
            goto no_other_choice; // to help flow control analysis
150
151
152
    }

    // check for generator functions and if so wrap in generator object
153
    if ((rc->scope_flags & MP_SCOPE_FLAG_GENERATOR) != 0) {
154
155
156
        fun = mp_obj_new_gen_wrap(fun);
    }

157
158
159
    return fun;
}

160
mp_obj_t mp_make_closure_from_raw_code(const mp_raw_code_t *rc, mp_uint_t n_closed_over, const mp_obj_t *args) {
161
    DEBUG_OP_printf("make_closure_from_raw_code %p " UINT_FMT " %p\n", rc, n_closed_over, args);
162
    // make function object
163
164
165
166
167
168
169
170
    mp_obj_t ffun;
    if (n_closed_over & 0x100) {
        // default positional and keyword args given
        ffun = mp_make_function_from_raw_code(rc, args[0], args[1]);
    } else {
        // default positional and keyword args not given
        ffun = mp_make_function_from_raw_code(rc, MP_OBJ_NULL, MP_OBJ_NULL);
    }
171
    // wrap function in closure object
172
    return mp_obj_new_closure(ffun, n_closed_over & 0xff, args + ((n_closed_over >> 7) & 2));
173
}