Takashi Kawai
/
Nucleo_blink_led_for_mrubyc
This is a port of the mruby/c tutorial Chapter 03 to the mbed environment.
Embed:
(wiki syntax)
Show/hide line numbers
load.c
Go to the documentation of this file.
00001 /*! @file 00002 @brief 00003 mruby bytecode loader. 00004 00005 <pre> 00006 Copyright (C) 2015 Kyushu Institute of Technology. 00007 Copyright (C) 2015 Shimane IT Open-Innovation Center. 00008 00009 This file is distributed under BSD 3-Clause License. 00010 00011 </pre> 00012 */ 00013 00014 #include <stdlib.h> 00015 #include <stdint.h> 00016 #include <string.h> 00017 #include "vm.h" 00018 #include "vm_config.h" 00019 #include "load.h" 00020 #include "errorcode.h " 00021 #include "static.h" 00022 #include "value.h " 00023 00024 00025 //================================================================ 00026 /*!@brief 00027 Parse header section. 00028 00029 @param vm A pointer of VM. 00030 @param pos A pointer of pointer of RITE header. 00031 @return int zero if no error. 00032 00033 <pre> 00034 Structure 00035 "RITE" identifier 00036 "0003" version 00037 0000 CRC 00038 0000_0000 total size 00039 "MATZ" compiler name 00040 "0000" compiler version 00041 </pre> 00042 */ 00043 static int load_header(struct VM *vm, const uint8_t **pos) 00044 { 00045 const uint8_t *p = *pos; 00046 00047 if( memcmp(p + 4, "0003", 4) != 0 ) { 00048 vm->error_code = LOAD_FILE_HEADER_ERROR_VERSION; 00049 return -1; 00050 } 00051 00052 /* Ignore CRC */ 00053 00054 /* Ignore size */ 00055 00056 if( memcmp(p + 14, "MATZ", 4) != 0 ) { 00057 vm->error_code = LOAD_FILE_HEADER_ERROR_MATZ; 00058 return -1; 00059 } 00060 if( memcmp(p + 18, "0000", 4) != 0 ) { 00061 vm->error_code = LOAD_FILE_HEADER_ERROR_VERSION; 00062 return -1; 00063 } 00064 00065 *pos += 22; 00066 return 0; 00067 } 00068 00069 00070 //================================================================ 00071 /*!@brief 00072 Parse IREP section. 00073 00074 @param vm A pointer of VM. 00075 @param pos A pointer of pointer of IREP section. 00076 @return int zero if no error. 00077 00078 <pre> 00079 Structure 00080 "IREP" section identifier 00081 0000_0000 section size 00082 "0000" rite version 00083 00084 (loop n of child irep bellow) 00085 0000_0000 record size 00086 0000 n of local variable 00087 0000 n of register 00088 0000 n of child irep 00089 00090 0000_0000 n of byte code (ISEQ BLOCK) 00091 ... byte codes 00092 00093 0000_0000 n of pool (POOL BLOCK) 00094 (loop n of pool) 00095 00 type 00096 0000 length 00097 ... pool data 00098 00099 0000_0000 n of symbol (SYMS BLOCK) 00100 (loop n of symbol) 00101 0000 length 00102 ... symbol data 00103 </pre> 00104 */ 00105 static int load_irep(struct VM *vm, const uint8_t **pos) 00106 { 00107 const uint8_t *p = *pos; 00108 p += 4; 00109 int section_size = bin_to_uint32(p); 00110 p += 4; 00111 00112 if( memcmp(p, "0000", 4) != 0 ) { 00113 vm->error_code = LOAD_FILE_IREP_ERROR_VERSION; 00114 return -1; 00115 } 00116 p += 4; 00117 00118 int cnt = 0; 00119 while( cnt < section_size ) { 00120 cnt += bin_to_uint32(p) + 8; 00121 p += 4; 00122 00123 // new irep 00124 mrb_irep *irep = new_irep(vm); 00125 if( irep == 0 ) { 00126 vm->error_code = LOAD_FILE_IREP_ERROR_ALLOCATION; 00127 return -1; 00128 } 00129 00130 // add irep into vm->irep (at tail) 00131 // TODO: Optimize this process 00132 if( vm->irep == 0 ) { 00133 vm->irep = irep; 00134 } else { 00135 mrb_irep *p = vm->irep; 00136 while( p->next != 0 ) { 00137 p = p->next; 00138 } 00139 p->next = irep; 00140 } 00141 irep->next = 0; 00142 00143 // nlocals,nregs,rlen 00144 irep->nlocals = bin_to_uint16(p); p += 2; 00145 irep->nregs = bin_to_uint16(p); p += 2; 00146 irep->rlen = bin_to_uint16(p); p += 2; 00147 irep->ilen = bin_to_uint32(p); p += 4; 00148 00149 // padding 00150 p += (-(p - *pos + 2) & 0x03); // +2 = (RITE(22) + IREP(12)) & 0x03 00151 00152 // ISEQ (code) BLOCK 00153 irep->code = (uint8_t *)p; 00154 p += irep->ilen * 4; 00155 00156 // POOL BLOCK 00157 irep->ptr_to_pool = 0; 00158 int plen = bin_to_uint32(p); p += 4; 00159 int i; 00160 for( i=0 ; i<plen ; i++ ){ 00161 int tt = (int)*p++; 00162 int obj_size = bin_to_uint16(p); p += 2; 00163 mrb_object *ptr = mrbc_obj_alloc(vm, MRB_TT_FALSE); 00164 if( ptr == 0 ){ 00165 vm->error_code = LOAD_FILE_IREP_ERROR_ALLOCATION; 00166 return -1; 00167 } 00168 switch( tt ){ 00169 #if MRBC_USE_STRING 00170 case 0: { // IREP_TT_STRING 00171 ptr->tt = MRB_TT_STRING; 00172 ptr->value.str = (char*)p; 00173 } break; 00174 #endif 00175 case 1: { // IREP_TT_FIXNUM 00176 char buf[obj_size+1]; 00177 memcpy(buf, p, obj_size); 00178 buf[obj_size] = '\0'; 00179 ptr->tt = MRB_TT_FIXNUM; 00180 ptr->value.i = atoi(buf); 00181 } break; 00182 #if MRBC_USE_FLOAT 00183 case 2: { // IREP_TT_FLOAT 00184 char buf[obj_size+1]; 00185 memcpy(buf, p, obj_size); 00186 buf[obj_size] = '\0'; 00187 ptr->tt = MRB_TT_FLOAT; 00188 ptr->value.d = atof(buf); 00189 } break; 00190 #endif 00191 default: 00192 break; 00193 } 00194 if( irep->ptr_to_pool == 0 ){ 00195 irep->ptr_to_pool = ptr; 00196 } else { 00197 mrb_object *pp = irep->ptr_to_pool; 00198 while( pp->next != 0 ) pp = pp->next; 00199 pp->next = ptr; 00200 } 00201 p += obj_size; 00202 } 00203 00204 // SYMS BLOCK 00205 irep->ptr_to_sym = (uint8_t*)p; 00206 int slen = bin_to_uint32(p); p += 4; 00207 for( i=0 ; i<slen ; i++ ){ 00208 int s = bin_to_uint16(p); p += 2; 00209 p += s+1; 00210 } 00211 } 00212 00213 /* TODO: size */ 00214 *pos += section_size; 00215 return 0; 00216 } 00217 00218 00219 //================================================================ 00220 /*!@brief 00221 Parse LVAR section. 00222 00223 @param vm A pointer of VM. 00224 @param pos A pointer of pointer of LVAR section. 00225 @return int zero if no error. 00226 */ 00227 static int load_lvar(struct VM *vm, const uint8_t **pos) 00228 { 00229 const uint8_t *p = *pos; 00230 00231 /* size */ 00232 *pos += bin_to_uint32(p+4); 00233 00234 return 0; 00235 } 00236 00237 00238 //================================================================ 00239 /*!@brief 00240 Setup mrb program 00241 00242 @param vm A pointer of VM. 00243 @return int zero if no error. 00244 */ 00245 int load_mrb(struct VM *vm) 00246 { 00247 int ret = -1; 00248 const uint8_t *pos = vm->mrb; 00249 00250 if( memcmp(pos, "RITE", 4) == 0 ) { 00251 ret = load_header(vm, &pos); 00252 } 00253 while( ret == 0 ) { 00254 if( memcmp(pos, "IREP", 4) == 0 ) { 00255 ret = load_irep(vm, &pos); 00256 } 00257 else if( memcmp(pos, "LVAR", 4) == 0 ) { 00258 ret = load_lvar(vm, &pos); 00259 } 00260 else if( memcmp(pos, "END\0", 4) == 0 ) { 00261 break; 00262 } 00263 } 00264 00265 return ret; 00266 } 00267 00268 00269 //================================================================ 00270 /*!@brief 00271 00272 00273 @param vm A pointer of VM. 00274 @param ptr A pointer of RITE (.mrb) code. 00275 00276 */ 00277 int loca_mrb_array (struct VM *vm, const uint8_t *ptr) 00278 { 00279 vm->mrb = ptr; 00280 return load_mrb(vm); 00281 } 00282
Generated on Tue Jul 12 2022 23:36:30 by 1.7.2