mruby/c VM Source Code release 3.4
Loading...
Searching...
No Matches
load.c
Go to the documentation of this file.
1
13
14/***** Feature test switches ************************************************/
15/***** System headers *******************************************************/
16//@cond
17#include "vm_config.h"
18#include <stdlib.h>
19#include <stdint.h>
20#include <string.h>
21#include <assert.h>
22//@endcond
23
24/***** Local headers ********************************************************/
25#include "mrubyc.h"
26
27/***** Constat values *******************************************************/
28// for mrb file structure.
29static const char RITE[4] = "RITE";
30static const char RITE_VERSION[4] = "0300";
31static const int SIZE_RITE_BINARY_HEADER = 20;
32static const int SIZE_RITE_SECTION_HEADER = 12;
33static const int SIZE_RITE_CATCH_HANDLER = 13;
34static const char IREP[4] = "IREP";
35static const char END[4] = "END\0";
36
37
40 IREP_TT_STR = 0, // string (need free)
41 IREP_TT_SSTR = 2, // string (static)
42 IREP_TT_INT32 = 1, // 32bit integer
43 IREP_TT_INT64 = 3, // 64bit integer
44 IREP_TT_FLOAT = 5, // float (double/float)
45};
46
47
48/***** Macros ***************************************************************/
49/***** Typedefs *************************************************************/
50/***** Function prototypes **************************************************/
51/***** Local variables ******************************************************/
52/***** Global variables *****************************************************/
53/***** Signal catching functions ********************************************/
54/***** Local functions ******************************************************/
55
56//================================================================
73static int load_header(struct VM *vm, const uint8_t *bin)
74{
75 if( memcmp(bin, RITE, sizeof(RITE)) != 0 ) {
76 mrbc_raise( vm, MRBC_CLASS(Exception), "Illegal bytecode");
77 return -1;
78 }
79 bin += sizeof(RITE);
80
81 if( memcmp(bin, RITE_VERSION, sizeof(RITE_VERSION)) != 0 ) {
82 mrbc_raise( vm, MRBC_CLASS(Exception), "Bytecode version mismatch");
83 return -1;
84 }
85
86 /* Ignore others. */
87
88 return 0;
89}
90
91
92//================================================================
129static mrbc_irep * load_irep_1(struct VM *vm, const uint8_t *bin, int *len)
130{
131 mrbc_irep irep;
132 const uint8_t *p = bin + 4; // 4 = skip record size.
133
134#if defined(MRBC_DEBUG)
135 irep.obj_mark_[0] = 'R'; // set "RP"
136 irep.obj_mark_[1] = 'P';
137#endif
138
139 irep.ref_count = 0;
140#if defined(MRBC_DEBUG)
141 irep.nlocals = bin_to_uint16(p); p += 2;
142#else
143 p += 2; // skip nlocals
144#endif
145 irep.nregs = bin_to_uint16(p); p += 2;
146 irep.rlen = bin_to_uint16(p); p += 2;
147 irep.clen = bin_to_uint16(p); p += 2;
148 uint32_t ilen = bin_to_uint32(p); p += 4;
149 if( ilen > 0xffff ) goto ERROR_TOO_LARGE;
150 irep.ilen = ilen;
151 irep.inst = p;
152
153 // POOL block
154 p += irep.ilen + SIZE_RITE_CATCH_HANDLER * irep.clen;
155 irep.pool = p;
156 uint16_t plen = bin_to_uint16(p); p += 2;
157
158 // skip pool
159 for( int i = 0; i < plen; i++ ) {
160 int siz = 0;
161 int tt = *p++;
162
163 switch( tt ) {
164 case IREP_TT_STR:
165 case IREP_TT_SSTR: siz = bin_to_uint16(p) + 3; break;
166 case IREP_TT_INT32: siz = 4; break;
167 case IREP_TT_INT64:
168#if !defined(MRBC_INT64)
169 mrbc_raise(vm, MRBC_CLASS(NotImplementedError), "Unsupported int64 (set MRBC_INT64 in vm_config)");
170#endif
171 case IREP_TT_FLOAT: siz = 8; break;
172 default:
173 mrbc_raisef(vm, MRBC_CLASS(Exception), "Not support such type (IREP_TT=%d)", tt);
174 return NULL;
175 }
176 p += siz;
177 }
178
179 // num of symbols, offset of tbl_ireps.
180 uint16_t slen = bin_to_uint16(p); p += 2;
181 uint32_t siz = sizeof(mrbc_sym) * slen;
182 if( siz > 0xffff ) goto ERROR_TOO_LARGE;
183 irep.ofs_pools = siz;
184
185 siz += sizeof(uint16_t) * plen;
186 if( siz > 0xffff ) goto ERROR_TOO_LARGE;
187 siz += (-siz & 0x03); // padding. 32bit align.
188 irep.ofs_ireps = siz;
189
190#if defined(MRBC_DEBUG)
191 irep.plen = plen;
192 irep.slen = slen;
193#endif
194
195 // allocate new irep
196 siz = sizeof(mrbc_irep) + siz + sizeof(mrbc_irep*) * irep.rlen;
197 mrbc_irep *p_irep = mrbc_raw_alloc( siz );
198 if( !p_irep ) { // ENOMEM
199 mrbc_raise(vm, MRBC_CLASS(NoMemoryError),0);
200 return NULL;
201 }
202 *p_irep = irep;
203
204 // make a symbol ID table. (tbl_syms[slen])
205 mrbc_sym *tbl_syms = mrbc_irep_tbl_syms(p_irep);
206 for( int i = 0; i < slen; i++ ) {
207 int siz = bin_to_uint16(p) + 1; p += 2;
208 char *sym_str;
209 if (vm->flag_permanence == 1) {
210 sym_str = mrbc_raw_alloc_no_free(siz);
211 memcpy(sym_str, p, siz);
212 } else {
213 sym_str = (char *)p;
214 }
215 mrbc_sym sym = mrbc_str_to_symid( sym_str );
216 if( sym < 0 ) {
217 mrbc_raise(vm, MRBC_CLASS(Exception), "Overflow MAX_SYMBOLS_COUNT");
218 return NULL;
219 }
220 *tbl_syms++ = sym;
221 p += (siz);
222 }
223
224 // make a pool data's offset table. (tbl_pools[plen])
225 uint16_t *ofs_pools = mrbc_irep_tbl_pools(p_irep);
226 p = p_irep->pool + 2;
227 for( int i = 0; i < plen; i++ ) {
228 int siz = 0;
229 if( (p - irep.pool) > UINT16_MAX ) {
230 mrbc_raise(vm, MRBC_CLASS(Exception), "Overflow IREP data offset table");
231 return NULL;
232 }
233 *ofs_pools++ = (uint16_t)(p - irep.pool);
234 switch( *p++ ) {
235 case IREP_TT_STR:
236 case IREP_TT_SSTR: siz = bin_to_uint16(p) + 3; break;
237 case IREP_TT_INT32: siz = 4; break;
238 case IREP_TT_INT64:
239 case IREP_TT_FLOAT: siz = 8; break;
240 }
241 p += siz;
242 }
243
244 // return length
245 *len = bin_to_uint32(bin);
246 return p_irep;
247
248
249 ERROR_TOO_LARGE:
250 mrbc_raise(vm, MRBC_CLASS(Exception), "Too large IREP size");
251 return NULL;
252}
253
254
255//================================================================
263static mrbc_irep *load_irep(struct VM *vm, const uint8_t *bin, int *len)
264{
265 int len1;
266 mrbc_irep *irep = load_irep_1(vm, bin, &len1);
267 if( !irep ) return NULL;
268 int total_len = len1;
269
270 mrbc_irep **tbl_ireps = mrbc_irep_tbl_ireps(irep);
271
272 for( int i = 0; i < irep->rlen; i++ ) {
273 tbl_ireps[i] = load_irep(vm, bin + total_len, &len1);
274 if( ! tbl_ireps[i] ) return NULL;
275 total_len += len1;
276 }
277
278 if( len ) *len = total_len;
279 return irep;
280}
281
282
283/***** Global functions *****************************************************/
284
285//================================================================
292int mrbc_load_mrb(struct VM *vm, const void *bytecode)
293{
294 const uint8_t *bin = bytecode;
295
297 if( load_header(vm, bin) != 0 ) return -1;
298
300
301 while( 1 ) {
302 if( memcmp(bin, IREP, sizeof(IREP)) == 0 ) {
303 if( mrbc_load_irep( vm, bin ) != 0 ) break;
304
305 } else if( memcmp(bin, END, sizeof(END)) == 0 ) {
306 break;
307 }
308 // ignore other section.
309
310 bin += bin_to_uint32(bin+4); // add section size, to next section.
311 }
312
313 return mrbc_israised(vm);
314}
315
316
317//================================================================
324int mrbc_load_irep(struct VM *vm, const void *bytecode)
325{
326 const uint8_t *bin = bytecode;
327
328 vm->top_irep = load_irep( vm, bin + SIZE_RITE_SECTION_HEADER, 0 );
329 if( vm->top_irep == NULL ) return -1;
330
331 return mrbc_israised(vm);
332}
333
334
335//================================================================
340void mrbc_irep_free(struct IREP *irep)
341{
342 // release child ireps.
343 for( int i = 0; i < irep->rlen; i++ ) {
345 }
346
347 if( irep->ref_count == 0 ) {
348 mrbc_raw_free( irep );
349 }
350}
351
352
353//================================================================
361{
362 const uint8_t *p = mrbc_irep_pool_ptr(vm->cur_irep, n);
363 mrbc_value obj;
364
365 int tt = *p++;
366 switch( tt ) {
367#if MRBC_USE_STRING
368 case IREP_TT_STR:
369 case IREP_TT_SSTR: {
370 int len = bin_to_uint16(p);
371 obj = mrbc_string_new( vm, p+2, len );
372 break;
373 }
374#endif
375
376 case IREP_TT_INT32:
378 break;
379
380#if MRBC_USE_FLOAT
381 case IREP_TT_FLOAT:
383 break;
384#endif
385
386#if defined(MRBC_INT64)
387 case IREP_TT_INT64:
388 mrbc_set_integer(&obj, bin_to_int64(p));
389 break;
390#endif
391
392 default:
393 mrbc_raisef(vm, MRBC_CLASS(Exception), "Not support such type (IREP_TT=%d)", tt);
394 mrbc_set_nil(&obj);
395 }
396
397 return obj;
398}
void * mrbc_raw_alloc(unsigned int size)
Definition alloc.c:500
void * mrbc_raw_alloc_no_free(unsigned int size)
Definition alloc.c:619
void mrbc_raw_free(void *ptr)
Definition alloc.c:695
mrbc_value mrbc_string_new(struct VM *vm, const void *src, int len)
Definition c_string.c:62
#define MRBC_CLASS(cls)
Definition class.h:51
void mrbc_raise(struct VM *vm, struct RClass *exc_cls, const char *msg)
Definition error.c:150
void mrbc_raisef(struct VM *vm, struct RClass *exc_cls, const char *fstr,...)
Definition error.c:173
#define mrbc_israised(vm)
Definition error.h:37
static const int SIZE_RITE_CATCH_HANDLER
Definition load.c:33
static const int SIZE_RITE_SECTION_HEADER
Definition load.c:32
static mrbc_irep * load_irep(struct VM *vm, const uint8_t *bin, int *len)
Definition load.c:263
static const char RITE_VERSION[4]
Definition load.c:30
static const char RITE[4]
Definition load.c:29
int mrbc_load_mrb(struct VM *vm, const void *bytecode)
Definition load.c:292
int mrbc_load_irep(struct VM *vm, const void *bytecode)
Definition load.c:324
mrbc_value mrbc_irep_pool_value(struct VM *vm, int n)
Definition load.c:360
static int load_header(struct VM *vm, const uint8_t *bin)
Definition load.c:73
static mrbc_irep * load_irep_1(struct VM *vm, const uint8_t *bin, int *len)
Definition load.c:129
static const char END[4]
Definition load.c:35
void mrbc_irep_free(struct IREP *irep)
Definition load.c:340
irep_pool_type
Definition load.c:39
@ IREP_TT_STR
Definition load.c:40
@ IREP_TT_INT32
Definition load.c:42
@ IREP_TT_FLOAT
Definition load.c:44
@ IREP_TT_INT64
Definition load.c:43
@ IREP_TT_SSTR
Definition load.c:41
static const int SIZE_RITE_BINARY_HEADER
Definition load.c:31
Include at once the necessary header files.
IREP Internal REPresentation.
Definition vm.h:42
uint16_t ofs_pools
offset of data->tbl_pools.
Definition vm.h:59
const uint8_t * inst
pointer to instruction in RITE binary
Definition vm.h:62
const uint8_t * pool
pointer to pool in RITE binary
Definition vm.h:63
uint16_t ilen
num of bytes in OpCode
Definition vm.h:54
uint16_t ref_count
reference counter
Definition vm.h:47
uint16_t ofs_ireps
offset of data->tbl_ireps. (32bit aligned)
Definition vm.h:60
uint16_t rlen
num of child IREP blocks
Definition vm.h:52
uint16_t clen
num of catch handlers
Definition vm.h:53
uint16_t nregs
num of register variables
Definition vm.h:51
Virtual Machine.
Definition vm.h:140
const mrbc_irep * cur_irep
IREP currently running.
Definition vm.h:153
mrbc_value exception
Raised exception or nil.
Definition vm.h:160
unsigned int flag_permanence
Definition vm.h:148
mrbc_irep * top_irep
IREP tree top.
Definition vm.h:152
mrbc_sym mrbc_str_to_symid(const char *str)
Definition symbol.c:217
#define mrbc_set_nil(p)
Definition value.h:201
#define mrbc_nil_value()
Definition value.h:210
static uint32_t bin_to_uint32(const void *s)
Definition value.h:678
static double bin_to_double64(const void *s)
Definition value.h:764
#define mrbc_set_integer(p, n)
Definition value.h:199
#define mrbc_set_float(p, n)
Definition value.h:200
int16_t mrbc_sym
mruby/c symbol ID
Definition value.h:59
struct RObject mrbc_value
Definition value.h:174
static uint16_t bin_to_uint16(const void *s)
Definition value.h:646
#define mrbc_irep_tbl_syms(irep)
get a symbol id table pointer.
Definition vm.h:74
#define mrbc_irep_pool_ptr(irep, n)
get a pointer to n'th pool data.
Definition vm.h:88
#define mrbc_irep_child_irep(irep, n)
get a n'th child irep
Definition vm.h:97
#define mrbc_irep_tbl_pools(irep)
get a pool data offset table pointer.
Definition vm.h:84
#define mrbc_irep_tbl_ireps(irep)
get a child irep table pointer.
Definition vm.h:93
struct IREP mrbc_irep
IREP Internal REPresentation.
Global configuration of mruby/c VM's.