mruby/c VM Source Code release 4.0.0
Loading...
Searching...
No Matches
load.c
Go to the documentation of this file.
1
14
15/***** Feature test switches ************************************************/
16/***** System headers *******************************************************/
17//@cond
18#include "vm_config.h"
19#include <stdlib.h>
20#include <stdint.h>
21#include <string.h>
22#include <assert.h>
23//@endcond
24
25/***** Local headers ********************************************************/
26#include "mrubyc.h"
27
28/***** Constat values *******************************************************/
29// for mrb file structure.
30static const char RITE[4] = "RITE";
31static const char RITE_VERSION[4] = "0400";
32static const int SIZE_RITE_BINARY_HEADER = 20;
33static const int SIZE_RITE_SECTION_HEADER = 12;
34static const int SIZE_RITE_CATCH_HANDLER = 13;
35static const char IREP[4] = "IREP";
36static const char END[4] = "END\0";
37
38
41 IREP_TT_STR = 0, // string (need free)
42 IREP_TT_SSTR = 2, // string (static)
43 IREP_TT_INT32 = 1, // 32bit integer
44 IREP_TT_INT64 = 3, // 64bit integer
45 IREP_TT_BIGINT = 7, // big integer
46 IREP_TT_FLOAT = 5, // float (double/float)
47};
48
49
50/***** Macros ***************************************************************/
51/***** Typedefs *************************************************************/
52/***** Function prototypes **************************************************/
53/***** Local variables ******************************************************/
54/***** Global variables *****************************************************/
55/***** Signal catching functions ********************************************/
56/***** Local functions ******************************************************/
57
58//================================================================
75static int load_header(mrbc_vm *vm, const uint8_t *bin)
76{
77 if( memcmp(bin, RITE, sizeof(RITE)) != 0 ) {
78 mrbc_raise( vm, MRBC_CLASS(Exception), "Illegal bytecode");
79 return -1;
80 }
81 bin += sizeof(RITE);
82
83 if( memcmp(bin, RITE_VERSION, sizeof(RITE_VERSION)) != 0 ) {
84 mrbc_raise( vm, MRBC_CLASS(Exception), "Bytecode version mismatch");
85 return -1;
86 }
87
88 /* Ignore others. */
89
90 return 0;
91}
92
93
94//================================================================
131static mrbc_irep * load_irep_1(mrbc_vm *vm, const uint8_t *bin, int *len)
132{
133 mrbc_irep irep;
134 const uint8_t *p = bin + 4; // 4 = skip record size.
135
136#if defined(MRBC_DEBUG)
137 irep.obj_mark_[0] = 'I'; // set "IR"
138 irep.obj_mark_[1] = 'R';
139#endif
140
141 irep.ref_count = 0;
142#if defined(MRBC_DEBUG)
143 irep.nlocals = bin_to_uint16(p); p += 2;
144#else
145 p += 2; // skip nlocals
146#endif
147 irep.nregs = bin_to_uint16(p); p += 2;
148 irep.rlen = bin_to_uint16(p); p += 2;
149 irep.clen = bin_to_uint16(p); p += 2;
150 uint32_t ilen = bin_to_uint32(p); p += 4;
151 if( ilen > 0xffff ) goto ERROR_TOO_LARGE;
152 irep.ilen = ilen;
153 irep.inst = p;
154
155 // POOL block
156 p += irep.ilen + SIZE_RITE_CATCH_HANDLER * irep.clen;
157 irep.pool = p;
158 uint16_t plen = bin_to_uint16(p); p += 2;
159
160 // skip pool
161 for( int i = 0; i < plen; i++ ) {
162 int siz = 0;
163 int tt = *p++;
164
165 switch( tt ) {
166 case IREP_TT_STR:
167 case IREP_TT_SSTR: siz = bin_to_uint16(p) + 3; break;
168 case IREP_TT_INT32: siz = 4; break;
169
170#if defined(MRBC_INT64)
171 case IREP_TT_INT64: siz = 8; break;
172 case IREP_TT_BIGINT: siz = *p + 2; break;
173#else
174 case IREP_TT_INT64:
175 case IREP_TT_BIGINT:
176 mrbc_raise(vm, MRBC_CLASS(NotImplementedError), "Unsupported int64 (set MRBC_INT64 in vm_config)");
177 return NULL;
178#endif
179
180 case IREP_TT_FLOAT: siz = 8; break;
181 default:
182 mrbc_raisef(vm, MRBC_CLASS(Exception), "Not support such type (IREP_TT=%d)", tt);
183 return NULL;
184 }
185 p += siz;
186 }
187
188 // num of symbols, offset of tbl_ireps.
189 uint16_t slen = bin_to_uint16(p); p += 2;
190 uint32_t siz = sizeof(mrbc_sym) * slen;
191 if( siz > 0xffff ) goto ERROR_TOO_LARGE;
192 irep.ofs_pools = siz;
193
194 siz += sizeof(uint16_t) * plen;
195 if( siz > 0xffff ) goto ERROR_TOO_LARGE;
196 siz += (-siz & 0x03); // padding. 32bit align.
197 irep.ofs_ireps = siz;
198
199#if defined(MRBC_DEBUG)
200 irep.plen = plen;
201 irep.slen = slen;
202#endif
203
204 // allocate new irep
205 siz = sizeof(mrbc_irep) + siz + sizeof(mrbc_irep*) * irep.rlen;
206 mrbc_irep *p_irep = mrbc_raw_alloc( siz );
207 *p_irep = irep;
208
209 // make a symbol ID table. (tbl_syms[slen])
210 mrbc_sym *tbl_syms = mrbc_irep_tbl_syms(p_irep);
211 for( int i = 0; i < slen; i++ ) {
212 int siz = bin_to_uint16(p) + 1; p += 2;
213 char *sym_str;
214
215 if (vm->flag_permanence == 1) {
216 sym_str = mrbc_raw_alloc_no_free(siz);
217 memcpy(sym_str, p, siz);
218 } else {
219 sym_str = (char *)p;
220 }
221
222 mrbc_sym sym = mrbc_str_to_symid( sym_str );
223 if( sym < 0 ) {
224 mrbc_raise(vm, MRBC_CLASS(Exception), "Overflow MAX_SYMBOLS_COUNT");
225 return NULL;
226 }
227
228 *tbl_syms++ = sym;
229 p += siz;
230 }
231
232 // make a pool data's offset table. (tbl_pools[plen])
233 uint16_t *ofs_pools = mrbc_irep_tbl_pools(p_irep);
234 p = p_irep->pool + 2;
235 for( int i = 0; i < plen; i++ ) {
236 int siz = 0;
237 if( (p - irep.pool) > UINT16_MAX ) {
238 mrbc_raise(vm, MRBC_CLASS(Exception), "Overflow IREP data offset table");
239 return NULL;
240 }
241 *ofs_pools++ = (uint16_t)(p - irep.pool);
242 switch( *p++ ) {
243 case IREP_TT_STR:
244 case IREP_TT_SSTR: siz = bin_to_uint16(p) + 3; break;
245 case IREP_TT_INT32: siz = 4; break;
246#if defined(MRBC_INT64)
247 case IREP_TT_INT64: siz = 8; break;
248 case IREP_TT_BIGINT: siz = *p + 2; break;
249#endif
250 case IREP_TT_FLOAT: siz = 8; break;
251 }
252 p += siz;
253 }
254
255 // return length
256 *len = bin_to_uint32(bin);
257 return p_irep;
258
259
260 ERROR_TOO_LARGE:
261 mrbc_raise(vm, MRBC_CLASS(Exception), "Too large IREP size");
262 return NULL;
263}
264
265
266//================================================================
274static mrbc_irep *load_irep(mrbc_vm *vm, const uint8_t *bin, int *len)
275{
276 int len1;
277 mrbc_irep *irep = load_irep_1(vm, bin, &len1);
278 if( !irep ) return NULL;
279 int total_len = len1;
280
281 mrbc_irep **tbl_ireps = mrbc_irep_tbl_ireps(irep);
282
283 for( int i = 0; i < irep->rlen; i++ ) {
284 tbl_ireps[i] = load_irep(vm, bin + total_len, &len1);
285 if( ! tbl_ireps[i] ) return NULL;
286 total_len += len1;
287 }
288
289 if( len ) *len = total_len;
290 return irep;
291}
292
293
294/***** Global functions *****************************************************/
295
296//================================================================
303int mrbc_load_mrb(mrbc_vm *vm, const void *bytecode)
304{
305 const uint8_t *bin = bytecode;
306
307 mrbc_set_nil( &vm->exception );
308 if( load_header(vm, bin) != 0 ) return -1;
309
311
312 while( 1 ) {
313 if( memcmp(bin, IREP, sizeof(IREP)) == 0 ) {
314 if( mrbc_load_irep( vm, bin ) != 0 ) break;
315
316 } else if( memcmp(bin, END, sizeof(END)) == 0 ) {
317 break;
318 }
319 // ignore other section.
320
321 bin += bin_to_uint32(bin+4); // add section size, to next section.
322 }
323
324 return mrbc_israised(vm);
325}
326
327
328//================================================================
335int mrbc_load_irep(mrbc_vm *vm, const void *bytecode)
336{
337 const uint8_t *bin = bytecode;
338
339 vm->top_irep = load_irep( vm, bin + SIZE_RITE_SECTION_HEADER, 0 );
340 if( vm->top_irep == NULL ) return -1;
341
342 return mrbc_israised(vm);
343}
344
345
346//================================================================
351//void mrbc_irep_free(struct IREP *irep)
353{
354 // release child ireps.
355 for( int i = 0; i < irep->rlen; i++ ) {
357 }
358
359 if( irep->ref_count == 0 ) {
360 mrbc_raw_free( irep );
361 }
362}
363
364#if defined(MRBC_INT64)
365//----------------------------------------------------------------
366static mrbc_int_t conv_bigint( const uint8_t *p )
367{
368 int len = *p++;
369 int base = *(const int8_t *)p++;
370 int sign = base;
371 if( base < 0 ) base = -base;
372 mrbc_int_t ret = 0;
373
374 if( base <= 10 ) {
375 for( int i = 0; i < len; i++ ) {
376 ret = (ret * base) + (*p++ - '0');
377 }
378 } else {
379 for( int i = 0; i < len; i++ ) {
380 int n = *p++ - '0';
381 if( n > 9 ) n += ('9' - 'a' + 1);
382 ret = (ret * base) + n;
383 }
384 }
385
386 return (sign < 0) ? -ret : ret;
387}
388#endif
389
390
391//================================================================
399{
400 const uint8_t *p = mrbc_irep_pool_ptr(vm->cur_irep, n);
401 mrbc_value obj;
402
403 int tt = *p++;
404 switch( tt ) {
405#if MRBC_USE_STRING
406 case IREP_TT_STR:
407 case IREP_TT_SSTR: {
408 int len = bin_to_uint16(p);
409 obj = mrbc_string_new( vm, p+2, len );
410 break;
411 }
412#endif
413
414 case IREP_TT_INT32:
416 break;
417
418#if MRBC_USE_FLOAT
419 case IREP_TT_FLOAT:
421 break;
422#endif
423
424#if defined(MRBC_INT64)
425 case IREP_TT_INT64:
426 mrbc_set_integer(&obj, bin_to_int64(p));
427 break;
428
429 case IREP_TT_BIGINT:
430 mrbc_set_integer(&obj, conv_bigint(p));
431 break;
432#endif
433
434 default:
435 mrbc_raisef(vm, MRBC_CLASS(Exception), "Not support such type (IREP_TT=%d)", tt);
436 mrbc_set_nil(&obj);
437 }
438
439 return obj;
440}
void * mrbc_raw_alloc(unsigned int size)
Definition alloc.c:514
void * mrbc_raw_alloc_no_free(unsigned int size)
Definition alloc.c:631
void mrbc_raw_free(void *ptr)
Definition alloc.c:707
static void mrbc_set_nil(mrbc_value *p)
Definition boxing_no.h:93
static void mrbc_set_float(mrbc_value *p, mrbc_float_t d)
Definition boxing_no.h:87
struct RObject mrbc_value
Value object. Default version.
static void mrbc_set_integer(mrbc_value *p, mrbc_int_t n)
Definition boxing_no.h:81
mrbc_value mrbc_string_new(mrbc_vm *vm, const void *src, int len)
Definition c_string.c:64
#define MRBC_CLASS(cls)
Definition class.h:55
void mrbc_raise(struct VM *vm, struct RClass *exc_cls, const char *msg)
Definition error.c:145
void mrbc_raisef(struct VM *vm, struct RClass *exc_cls, const char *fstr,...)
Definition error.c:168
#define mrbc_israised(vm)
Definition error.h:38
static const int SIZE_RITE_CATCH_HANDLER
Definition load.c:34
static const int SIZE_RITE_SECTION_HEADER
Definition load.c:33
static mrbc_irep * load_irep(mrbc_vm *vm, const uint8_t *bin, int *len)
Definition load.c:274
static const char RITE_VERSION[4]
Definition load.c:31
static const char RITE[4]
Definition load.c:30
static int load_header(mrbc_vm *vm, const uint8_t *bin)
Definition load.c:75
mrbc_value mrbc_irep_pool_value(mrbc_vm *vm, int n)
Definition load.c:398
static const char END[4]
Definition load.c:36
void mrbc_irep_free(mrbc_irep *irep)
Definition load.c:352
int mrbc_load_mrb(mrbc_vm *vm, const void *bytecode)
Definition load.c:303
irep_pool_type
Definition load.c:40
@ IREP_TT_BIGINT
Definition load.c:45
@ IREP_TT_STR
Definition load.c:41
@ IREP_TT_INT32
Definition load.c:43
@ IREP_TT_FLOAT
Definition load.c:46
@ IREP_TT_INT64
Definition load.c:44
@ IREP_TT_SSTR
Definition load.c:42
static mrbc_irep * load_irep_1(mrbc_vm *vm, const uint8_t *bin, int *len)
Definition load.c:131
static const int SIZE_RITE_BINARY_HEADER
Definition load.c:32
int mrbc_load_irep(mrbc_vm *vm, const void *bytecode)
Definition load.c:335
Include at once the necessary header files.
IREP Internal REPresentation.
Definition vm.h:43
uint16_t ofs_pools
offset of data->tbl_pools.
Definition vm.h:60
const uint8_t * inst
pointer to instruction in RITE binary
Definition vm.h:63
const uint8_t * pool
pointer to pool in RITE binary
Definition vm.h:64
uint16_t ilen
num of bytes in OpCode
Definition vm.h:55
uint16_t ref_count
reference counter
Definition vm.h:48
uint16_t ofs_ireps
offset of data->tbl_ireps. (32bit aligned)
Definition vm.h:61
uint16_t rlen
num of child IREP blocks
Definition vm.h:53
uint16_t clen
num of catch handlers
Definition vm.h:54
uint16_t nregs
num of register variables
Definition vm.h:52
const mrbc_irep * cur_irep
IREP currently running.
Definition vm.h:162
mrbc_value exception
Raised exception or nil.
Definition vm.h:169
unsigned int flag_permanence
Definition vm.h:158
mrbc_irep * top_irep
IREP tree top.
Definition vm.h:160
mrbc_sym mrbc_str_to_symid(const char *str)
Definition symbol.c:221
int32_t mrbc_int_t
Definition value.h:47
static uint32_t bin_to_uint32(const void *s)
Definition value.h:635
static double bin_to_double64(const void *s)
Definition value.h:721
int16_t mrbc_sym
mruby/c symbol ID
Definition value.h:62
static uint16_t bin_to_uint16(const void *s)
Definition value.h:603
#define mrbc_irep_tbl_syms(irep)
get a symbol id table pointer.
Definition vm.h:77
#define mrbc_irep_pool_ptr(irep, n)
get a pointer to n'th pool data.
Definition vm.h:91
#define mrbc_irep_child_irep(irep, n)
get a n'th child irep
Definition vm.h:100
#define mrbc_irep_tbl_pools(irep)
get a pool data offset table pointer.
Definition vm.h:87
#define mrbc_irep_tbl_ireps(irep)
get a child irep table pointer.
Definition vm.h:96
struct IREP mrbc_irep
IREP Internal REPresentation.
struct VM mrbc_vm
Virtual Machine.
Global configuration of mruby/c VM's.