This is a port of the mruby/c tutorial Chapter 03 to the mbed environment.
For details, refer to the following.
http://www.s-itoc.jp/activity/research/mrubyc/mrubyc_tutorial/436
Note:There is a change in rtt0.h from the original source in the mruby/c. It was necessary for inclusion in C ++ source.
mrubyc/load.c@0:33feccbba3ff, 2017-02-15 (annotated)
- Committer:
- tk_takateku
- Date:
- Wed Feb 15 01:03:35 2017 +0000
- Revision:
- 0:33feccbba3ff
Commit before publishing
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
tk_takateku | 0:33feccbba3ff | 1 | /*! @file |
tk_takateku | 0:33feccbba3ff | 2 | @brief |
tk_takateku | 0:33feccbba3ff | 3 | mruby bytecode loader. |
tk_takateku | 0:33feccbba3ff | 4 | |
tk_takateku | 0:33feccbba3ff | 5 | <pre> |
tk_takateku | 0:33feccbba3ff | 6 | Copyright (C) 2015 Kyushu Institute of Technology. |
tk_takateku | 0:33feccbba3ff | 7 | Copyright (C) 2015 Shimane IT Open-Innovation Center. |
tk_takateku | 0:33feccbba3ff | 8 | |
tk_takateku | 0:33feccbba3ff | 9 | This file is distributed under BSD 3-Clause License. |
tk_takateku | 0:33feccbba3ff | 10 | |
tk_takateku | 0:33feccbba3ff | 11 | </pre> |
tk_takateku | 0:33feccbba3ff | 12 | */ |
tk_takateku | 0:33feccbba3ff | 13 | |
tk_takateku | 0:33feccbba3ff | 14 | #include <stdlib.h> |
tk_takateku | 0:33feccbba3ff | 15 | #include <stdint.h> |
tk_takateku | 0:33feccbba3ff | 16 | #include <string.h> |
tk_takateku | 0:33feccbba3ff | 17 | #include "vm.h" |
tk_takateku | 0:33feccbba3ff | 18 | #include "vm_config.h" |
tk_takateku | 0:33feccbba3ff | 19 | #include "load.h" |
tk_takateku | 0:33feccbba3ff | 20 | #include "errorcode.h" |
tk_takateku | 0:33feccbba3ff | 21 | #include "static.h" |
tk_takateku | 0:33feccbba3ff | 22 | #include "value.h" |
tk_takateku | 0:33feccbba3ff | 23 | |
tk_takateku | 0:33feccbba3ff | 24 | |
tk_takateku | 0:33feccbba3ff | 25 | //================================================================ |
tk_takateku | 0:33feccbba3ff | 26 | /*!@brief |
tk_takateku | 0:33feccbba3ff | 27 | Parse header section. |
tk_takateku | 0:33feccbba3ff | 28 | |
tk_takateku | 0:33feccbba3ff | 29 | @param vm A pointer of VM. |
tk_takateku | 0:33feccbba3ff | 30 | @param pos A pointer of pointer of RITE header. |
tk_takateku | 0:33feccbba3ff | 31 | @return int zero if no error. |
tk_takateku | 0:33feccbba3ff | 32 | |
tk_takateku | 0:33feccbba3ff | 33 | <pre> |
tk_takateku | 0:33feccbba3ff | 34 | Structure |
tk_takateku | 0:33feccbba3ff | 35 | "RITE" identifier |
tk_takateku | 0:33feccbba3ff | 36 | "0003" version |
tk_takateku | 0:33feccbba3ff | 37 | 0000 CRC |
tk_takateku | 0:33feccbba3ff | 38 | 0000_0000 total size |
tk_takateku | 0:33feccbba3ff | 39 | "MATZ" compiler name |
tk_takateku | 0:33feccbba3ff | 40 | "0000" compiler version |
tk_takateku | 0:33feccbba3ff | 41 | </pre> |
tk_takateku | 0:33feccbba3ff | 42 | */ |
tk_takateku | 0:33feccbba3ff | 43 | static int load_header(struct VM *vm, const uint8_t **pos) |
tk_takateku | 0:33feccbba3ff | 44 | { |
tk_takateku | 0:33feccbba3ff | 45 | const uint8_t *p = *pos; |
tk_takateku | 0:33feccbba3ff | 46 | |
tk_takateku | 0:33feccbba3ff | 47 | if( memcmp(p + 4, "0003", 4) != 0 ) { |
tk_takateku | 0:33feccbba3ff | 48 | vm->error_code = LOAD_FILE_HEADER_ERROR_VERSION; |
tk_takateku | 0:33feccbba3ff | 49 | return -1; |
tk_takateku | 0:33feccbba3ff | 50 | } |
tk_takateku | 0:33feccbba3ff | 51 | |
tk_takateku | 0:33feccbba3ff | 52 | /* Ignore CRC */ |
tk_takateku | 0:33feccbba3ff | 53 | |
tk_takateku | 0:33feccbba3ff | 54 | /* Ignore size */ |
tk_takateku | 0:33feccbba3ff | 55 | |
tk_takateku | 0:33feccbba3ff | 56 | if( memcmp(p + 14, "MATZ", 4) != 0 ) { |
tk_takateku | 0:33feccbba3ff | 57 | vm->error_code = LOAD_FILE_HEADER_ERROR_MATZ; |
tk_takateku | 0:33feccbba3ff | 58 | return -1; |
tk_takateku | 0:33feccbba3ff | 59 | } |
tk_takateku | 0:33feccbba3ff | 60 | if( memcmp(p + 18, "0000", 4) != 0 ) { |
tk_takateku | 0:33feccbba3ff | 61 | vm->error_code = LOAD_FILE_HEADER_ERROR_VERSION; |
tk_takateku | 0:33feccbba3ff | 62 | return -1; |
tk_takateku | 0:33feccbba3ff | 63 | } |
tk_takateku | 0:33feccbba3ff | 64 | |
tk_takateku | 0:33feccbba3ff | 65 | *pos += 22; |
tk_takateku | 0:33feccbba3ff | 66 | return 0; |
tk_takateku | 0:33feccbba3ff | 67 | } |
tk_takateku | 0:33feccbba3ff | 68 | |
tk_takateku | 0:33feccbba3ff | 69 | |
tk_takateku | 0:33feccbba3ff | 70 | //================================================================ |
tk_takateku | 0:33feccbba3ff | 71 | /*!@brief |
tk_takateku | 0:33feccbba3ff | 72 | Parse IREP section. |
tk_takateku | 0:33feccbba3ff | 73 | |
tk_takateku | 0:33feccbba3ff | 74 | @param vm A pointer of VM. |
tk_takateku | 0:33feccbba3ff | 75 | @param pos A pointer of pointer of IREP section. |
tk_takateku | 0:33feccbba3ff | 76 | @return int zero if no error. |
tk_takateku | 0:33feccbba3ff | 77 | |
tk_takateku | 0:33feccbba3ff | 78 | <pre> |
tk_takateku | 0:33feccbba3ff | 79 | Structure |
tk_takateku | 0:33feccbba3ff | 80 | "IREP" section identifier |
tk_takateku | 0:33feccbba3ff | 81 | 0000_0000 section size |
tk_takateku | 0:33feccbba3ff | 82 | "0000" rite version |
tk_takateku | 0:33feccbba3ff | 83 | |
tk_takateku | 0:33feccbba3ff | 84 | (loop n of child irep bellow) |
tk_takateku | 0:33feccbba3ff | 85 | 0000_0000 record size |
tk_takateku | 0:33feccbba3ff | 86 | 0000 n of local variable |
tk_takateku | 0:33feccbba3ff | 87 | 0000 n of register |
tk_takateku | 0:33feccbba3ff | 88 | 0000 n of child irep |
tk_takateku | 0:33feccbba3ff | 89 | |
tk_takateku | 0:33feccbba3ff | 90 | 0000_0000 n of byte code (ISEQ BLOCK) |
tk_takateku | 0:33feccbba3ff | 91 | ... byte codes |
tk_takateku | 0:33feccbba3ff | 92 | |
tk_takateku | 0:33feccbba3ff | 93 | 0000_0000 n of pool (POOL BLOCK) |
tk_takateku | 0:33feccbba3ff | 94 | (loop n of pool) |
tk_takateku | 0:33feccbba3ff | 95 | 00 type |
tk_takateku | 0:33feccbba3ff | 96 | 0000 length |
tk_takateku | 0:33feccbba3ff | 97 | ... pool data |
tk_takateku | 0:33feccbba3ff | 98 | |
tk_takateku | 0:33feccbba3ff | 99 | 0000_0000 n of symbol (SYMS BLOCK) |
tk_takateku | 0:33feccbba3ff | 100 | (loop n of symbol) |
tk_takateku | 0:33feccbba3ff | 101 | 0000 length |
tk_takateku | 0:33feccbba3ff | 102 | ... symbol data |
tk_takateku | 0:33feccbba3ff | 103 | </pre> |
tk_takateku | 0:33feccbba3ff | 104 | */ |
tk_takateku | 0:33feccbba3ff | 105 | static int load_irep(struct VM *vm, const uint8_t **pos) |
tk_takateku | 0:33feccbba3ff | 106 | { |
tk_takateku | 0:33feccbba3ff | 107 | const uint8_t *p = *pos; |
tk_takateku | 0:33feccbba3ff | 108 | p += 4; |
tk_takateku | 0:33feccbba3ff | 109 | int section_size = bin_to_uint32(p); |
tk_takateku | 0:33feccbba3ff | 110 | p += 4; |
tk_takateku | 0:33feccbba3ff | 111 | |
tk_takateku | 0:33feccbba3ff | 112 | if( memcmp(p, "0000", 4) != 0 ) { |
tk_takateku | 0:33feccbba3ff | 113 | vm->error_code = LOAD_FILE_IREP_ERROR_VERSION; |
tk_takateku | 0:33feccbba3ff | 114 | return -1; |
tk_takateku | 0:33feccbba3ff | 115 | } |
tk_takateku | 0:33feccbba3ff | 116 | p += 4; |
tk_takateku | 0:33feccbba3ff | 117 | |
tk_takateku | 0:33feccbba3ff | 118 | int cnt = 0; |
tk_takateku | 0:33feccbba3ff | 119 | while( cnt < section_size ) { |
tk_takateku | 0:33feccbba3ff | 120 | cnt += bin_to_uint32(p) + 8; |
tk_takateku | 0:33feccbba3ff | 121 | p += 4; |
tk_takateku | 0:33feccbba3ff | 122 | |
tk_takateku | 0:33feccbba3ff | 123 | // new irep |
tk_takateku | 0:33feccbba3ff | 124 | mrb_irep *irep = new_irep(vm); |
tk_takateku | 0:33feccbba3ff | 125 | if( irep == 0 ) { |
tk_takateku | 0:33feccbba3ff | 126 | vm->error_code = LOAD_FILE_IREP_ERROR_ALLOCATION; |
tk_takateku | 0:33feccbba3ff | 127 | return -1; |
tk_takateku | 0:33feccbba3ff | 128 | } |
tk_takateku | 0:33feccbba3ff | 129 | |
tk_takateku | 0:33feccbba3ff | 130 | // add irep into vm->irep (at tail) |
tk_takateku | 0:33feccbba3ff | 131 | // TODO: Optimize this process |
tk_takateku | 0:33feccbba3ff | 132 | if( vm->irep == 0 ) { |
tk_takateku | 0:33feccbba3ff | 133 | vm->irep = irep; |
tk_takateku | 0:33feccbba3ff | 134 | } else { |
tk_takateku | 0:33feccbba3ff | 135 | mrb_irep *p = vm->irep; |
tk_takateku | 0:33feccbba3ff | 136 | while( p->next != 0 ) { |
tk_takateku | 0:33feccbba3ff | 137 | p = p->next; |
tk_takateku | 0:33feccbba3ff | 138 | } |
tk_takateku | 0:33feccbba3ff | 139 | p->next = irep; |
tk_takateku | 0:33feccbba3ff | 140 | } |
tk_takateku | 0:33feccbba3ff | 141 | irep->next = 0; |
tk_takateku | 0:33feccbba3ff | 142 | |
tk_takateku | 0:33feccbba3ff | 143 | // nlocals,nregs,rlen |
tk_takateku | 0:33feccbba3ff | 144 | irep->nlocals = bin_to_uint16(p); p += 2; |
tk_takateku | 0:33feccbba3ff | 145 | irep->nregs = bin_to_uint16(p); p += 2; |
tk_takateku | 0:33feccbba3ff | 146 | irep->rlen = bin_to_uint16(p); p += 2; |
tk_takateku | 0:33feccbba3ff | 147 | irep->ilen = bin_to_uint32(p); p += 4; |
tk_takateku | 0:33feccbba3ff | 148 | |
tk_takateku | 0:33feccbba3ff | 149 | // padding |
tk_takateku | 0:33feccbba3ff | 150 | p += (-(p - *pos + 2) & 0x03); // +2 = (RITE(22) + IREP(12)) & 0x03 |
tk_takateku | 0:33feccbba3ff | 151 | |
tk_takateku | 0:33feccbba3ff | 152 | // ISEQ (code) BLOCK |
tk_takateku | 0:33feccbba3ff | 153 | irep->code = (uint8_t *)p; |
tk_takateku | 0:33feccbba3ff | 154 | p += irep->ilen * 4; |
tk_takateku | 0:33feccbba3ff | 155 | |
tk_takateku | 0:33feccbba3ff | 156 | // POOL BLOCK |
tk_takateku | 0:33feccbba3ff | 157 | irep->ptr_to_pool = 0; |
tk_takateku | 0:33feccbba3ff | 158 | int plen = bin_to_uint32(p); p += 4; |
tk_takateku | 0:33feccbba3ff | 159 | int i; |
tk_takateku | 0:33feccbba3ff | 160 | for( i=0 ; i<plen ; i++ ){ |
tk_takateku | 0:33feccbba3ff | 161 | int tt = (int)*p++; |
tk_takateku | 0:33feccbba3ff | 162 | int obj_size = bin_to_uint16(p); p += 2; |
tk_takateku | 0:33feccbba3ff | 163 | mrb_object *ptr = mrbc_obj_alloc(vm, MRB_TT_FALSE); |
tk_takateku | 0:33feccbba3ff | 164 | if( ptr == 0 ){ |
tk_takateku | 0:33feccbba3ff | 165 | vm->error_code = LOAD_FILE_IREP_ERROR_ALLOCATION; |
tk_takateku | 0:33feccbba3ff | 166 | return -1; |
tk_takateku | 0:33feccbba3ff | 167 | } |
tk_takateku | 0:33feccbba3ff | 168 | switch( tt ){ |
tk_takateku | 0:33feccbba3ff | 169 | #if MRBC_USE_STRING |
tk_takateku | 0:33feccbba3ff | 170 | case 0: { // IREP_TT_STRING |
tk_takateku | 0:33feccbba3ff | 171 | ptr->tt = MRB_TT_STRING; |
tk_takateku | 0:33feccbba3ff | 172 | ptr->value.str = (char*)p; |
tk_takateku | 0:33feccbba3ff | 173 | } break; |
tk_takateku | 0:33feccbba3ff | 174 | #endif |
tk_takateku | 0:33feccbba3ff | 175 | case 1: { // IREP_TT_FIXNUM |
tk_takateku | 0:33feccbba3ff | 176 | char buf[obj_size+1]; |
tk_takateku | 0:33feccbba3ff | 177 | memcpy(buf, p, obj_size); |
tk_takateku | 0:33feccbba3ff | 178 | buf[obj_size] = '\0'; |
tk_takateku | 0:33feccbba3ff | 179 | ptr->tt = MRB_TT_FIXNUM; |
tk_takateku | 0:33feccbba3ff | 180 | ptr->value.i = atoi(buf); |
tk_takateku | 0:33feccbba3ff | 181 | } break; |
tk_takateku | 0:33feccbba3ff | 182 | #if MRBC_USE_FLOAT |
tk_takateku | 0:33feccbba3ff | 183 | case 2: { // IREP_TT_FLOAT |
tk_takateku | 0:33feccbba3ff | 184 | char buf[obj_size+1]; |
tk_takateku | 0:33feccbba3ff | 185 | memcpy(buf, p, obj_size); |
tk_takateku | 0:33feccbba3ff | 186 | buf[obj_size] = '\0'; |
tk_takateku | 0:33feccbba3ff | 187 | ptr->tt = MRB_TT_FLOAT; |
tk_takateku | 0:33feccbba3ff | 188 | ptr->value.d = atof(buf); |
tk_takateku | 0:33feccbba3ff | 189 | } break; |
tk_takateku | 0:33feccbba3ff | 190 | #endif |
tk_takateku | 0:33feccbba3ff | 191 | default: |
tk_takateku | 0:33feccbba3ff | 192 | break; |
tk_takateku | 0:33feccbba3ff | 193 | } |
tk_takateku | 0:33feccbba3ff | 194 | if( irep->ptr_to_pool == 0 ){ |
tk_takateku | 0:33feccbba3ff | 195 | irep->ptr_to_pool = ptr; |
tk_takateku | 0:33feccbba3ff | 196 | } else { |
tk_takateku | 0:33feccbba3ff | 197 | mrb_object *pp = irep->ptr_to_pool; |
tk_takateku | 0:33feccbba3ff | 198 | while( pp->next != 0 ) pp = pp->next; |
tk_takateku | 0:33feccbba3ff | 199 | pp->next = ptr; |
tk_takateku | 0:33feccbba3ff | 200 | } |
tk_takateku | 0:33feccbba3ff | 201 | p += obj_size; |
tk_takateku | 0:33feccbba3ff | 202 | } |
tk_takateku | 0:33feccbba3ff | 203 | |
tk_takateku | 0:33feccbba3ff | 204 | // SYMS BLOCK |
tk_takateku | 0:33feccbba3ff | 205 | irep->ptr_to_sym = (uint8_t*)p; |
tk_takateku | 0:33feccbba3ff | 206 | int slen = bin_to_uint32(p); p += 4; |
tk_takateku | 0:33feccbba3ff | 207 | for( i=0 ; i<slen ; i++ ){ |
tk_takateku | 0:33feccbba3ff | 208 | int s = bin_to_uint16(p); p += 2; |
tk_takateku | 0:33feccbba3ff | 209 | p += s+1; |
tk_takateku | 0:33feccbba3ff | 210 | } |
tk_takateku | 0:33feccbba3ff | 211 | } |
tk_takateku | 0:33feccbba3ff | 212 | |
tk_takateku | 0:33feccbba3ff | 213 | /* TODO: size */ |
tk_takateku | 0:33feccbba3ff | 214 | *pos += section_size; |
tk_takateku | 0:33feccbba3ff | 215 | return 0; |
tk_takateku | 0:33feccbba3ff | 216 | } |
tk_takateku | 0:33feccbba3ff | 217 | |
tk_takateku | 0:33feccbba3ff | 218 | |
tk_takateku | 0:33feccbba3ff | 219 | //================================================================ |
tk_takateku | 0:33feccbba3ff | 220 | /*!@brief |
tk_takateku | 0:33feccbba3ff | 221 | Parse LVAR section. |
tk_takateku | 0:33feccbba3ff | 222 | |
tk_takateku | 0:33feccbba3ff | 223 | @param vm A pointer of VM. |
tk_takateku | 0:33feccbba3ff | 224 | @param pos A pointer of pointer of LVAR section. |
tk_takateku | 0:33feccbba3ff | 225 | @return int zero if no error. |
tk_takateku | 0:33feccbba3ff | 226 | */ |
tk_takateku | 0:33feccbba3ff | 227 | static int load_lvar(struct VM *vm, const uint8_t **pos) |
tk_takateku | 0:33feccbba3ff | 228 | { |
tk_takateku | 0:33feccbba3ff | 229 | const uint8_t *p = *pos; |
tk_takateku | 0:33feccbba3ff | 230 | |
tk_takateku | 0:33feccbba3ff | 231 | /* size */ |
tk_takateku | 0:33feccbba3ff | 232 | *pos += bin_to_uint32(p+4); |
tk_takateku | 0:33feccbba3ff | 233 | |
tk_takateku | 0:33feccbba3ff | 234 | return 0; |
tk_takateku | 0:33feccbba3ff | 235 | } |
tk_takateku | 0:33feccbba3ff | 236 | |
tk_takateku | 0:33feccbba3ff | 237 | |
tk_takateku | 0:33feccbba3ff | 238 | //================================================================ |
tk_takateku | 0:33feccbba3ff | 239 | /*!@brief |
tk_takateku | 0:33feccbba3ff | 240 | Setup mrb program |
tk_takateku | 0:33feccbba3ff | 241 | |
tk_takateku | 0:33feccbba3ff | 242 | @param vm A pointer of VM. |
tk_takateku | 0:33feccbba3ff | 243 | @return int zero if no error. |
tk_takateku | 0:33feccbba3ff | 244 | */ |
tk_takateku | 0:33feccbba3ff | 245 | int load_mrb(struct VM *vm) |
tk_takateku | 0:33feccbba3ff | 246 | { |
tk_takateku | 0:33feccbba3ff | 247 | int ret = -1; |
tk_takateku | 0:33feccbba3ff | 248 | const uint8_t *pos = vm->mrb; |
tk_takateku | 0:33feccbba3ff | 249 | |
tk_takateku | 0:33feccbba3ff | 250 | if( memcmp(pos, "RITE", 4) == 0 ) { |
tk_takateku | 0:33feccbba3ff | 251 | ret = load_header(vm, &pos); |
tk_takateku | 0:33feccbba3ff | 252 | } |
tk_takateku | 0:33feccbba3ff | 253 | while( ret == 0 ) { |
tk_takateku | 0:33feccbba3ff | 254 | if( memcmp(pos, "IREP", 4) == 0 ) { |
tk_takateku | 0:33feccbba3ff | 255 | ret = load_irep(vm, &pos); |
tk_takateku | 0:33feccbba3ff | 256 | } |
tk_takateku | 0:33feccbba3ff | 257 | else if( memcmp(pos, "LVAR", 4) == 0 ) { |
tk_takateku | 0:33feccbba3ff | 258 | ret = load_lvar(vm, &pos); |
tk_takateku | 0:33feccbba3ff | 259 | } |
tk_takateku | 0:33feccbba3ff | 260 | else if( memcmp(pos, "END\0", 4) == 0 ) { |
tk_takateku | 0:33feccbba3ff | 261 | break; |
tk_takateku | 0:33feccbba3ff | 262 | } |
tk_takateku | 0:33feccbba3ff | 263 | } |
tk_takateku | 0:33feccbba3ff | 264 | |
tk_takateku | 0:33feccbba3ff | 265 | return ret; |
tk_takateku | 0:33feccbba3ff | 266 | } |
tk_takateku | 0:33feccbba3ff | 267 | |
tk_takateku | 0:33feccbba3ff | 268 | |
tk_takateku | 0:33feccbba3ff | 269 | //================================================================ |
tk_takateku | 0:33feccbba3ff | 270 | /*!@brief |
tk_takateku | 0:33feccbba3ff | 271 | |
tk_takateku | 0:33feccbba3ff | 272 | |
tk_takateku | 0:33feccbba3ff | 273 | @param vm A pointer of VM. |
tk_takateku | 0:33feccbba3ff | 274 | @param ptr A pointer of RITE (.mrb) code. |
tk_takateku | 0:33feccbba3ff | 275 | |
tk_takateku | 0:33feccbba3ff | 276 | */ |
tk_takateku | 0:33feccbba3ff | 277 | int loca_mrb_array(struct VM *vm, const uint8_t *ptr) |
tk_takateku | 0:33feccbba3ff | 278 | { |
tk_takateku | 0:33feccbba3ff | 279 | vm->mrb = ptr; |
tk_takateku | 0:33feccbba3ff | 280 | return load_mrb(vm); |
tk_takateku | 0:33feccbba3ff | 281 | } |
tk_takateku | 0:33feccbba3ff | 282 |