Main Page | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

wsasm.c

Go to the documentation of this file.
00001 /* ==================================================================== 
00002  * The Kannel Software License, Version 1.0 
00003  * 
00004  * Copyright (c) 2001-2008 Kannel Group  
00005  * Copyright (c) 1998-2001 WapIT Ltd.   
00006  * All rights reserved. 
00007  * 
00008  * Redistribution and use in source and binary forms, with or without 
00009  * modification, are permitted provided that the following conditions 
00010  * are met: 
00011  * 
00012  * 1. Redistributions of source code must retain the above copyright 
00013  *    notice, this list of conditions and the following disclaimer. 
00014  * 
00015  * 2. Redistributions in binary form must reproduce the above copyright 
00016  *    notice, this list of conditions and the following disclaimer in 
00017  *    the documentation and/or other materials provided with the 
00018  *    distribution. 
00019  * 
00020  * 3. The end-user documentation included with the redistribution, 
00021  *    if any, must include the following acknowledgment: 
00022  *       "This product includes software developed by the 
00023  *        Kannel Group (http://www.kannel.org/)." 
00024  *    Alternately, this acknowledgment may appear in the software itself, 
00025  *    if and wherever such third-party acknowledgments normally appear. 
00026  * 
00027  * 4. The names "Kannel" and "Kannel Group" must not be used to 
00028  *    endorse or promote products derived from this software without 
00029  *    prior written permission. For written permission, please  
00030  *    contact org@kannel.org. 
00031  * 
00032  * 5. Products derived from this software may not be called "Kannel", 
00033  *    nor may "Kannel" appear in their name, without prior written 
00034  *    permission of the Kannel Group. 
00035  * 
00036  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 
00037  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
00038  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
00039  * DISCLAIMED.  IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS 
00040  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,  
00041  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  
00042  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR  
00043  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,  
00044  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE  
00045  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,  
00046  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
00047  * ==================================================================== 
00048  * 
00049  * This software consists of voluntary contributions made by many 
00050  * individuals on behalf of the Kannel Group.  For more information on  
00051  * the Kannel Group, please see <http://www.kannel.org/>. 
00052  * 
00053  * Portions of this software are based upon software originally written at  
00054  * WapIT Ltd., Helsinki, Finland for the Kannel project.  
00055  */ 
00056 
00057 /*
00058  *
00059  * wsasm.c
00060  *
00061  * Author: Markku Rossi <mtr@iki.fi>
00062  *
00063  * Copyright (c) 1999-2000 WAPIT OY LTD.
00064  *       All rights reserved.
00065  *
00066  * Byte-code assembler.
00067  *
00068  */
00069 
00070 #include "wsint.h"
00071 #include "wsasm.h"
00072 #include "wsstdlib.h"
00073 
00074 /********************* Macros to fetch items from BC operands ***********/
00075 
00076 #define WS_OPNAME(op) (operands[(op)].name)
00077 #define WS_OPSIZE(op) (operands[(op)].size)
00078 
00079 /********************* Byte-code operands *******************************/
00080 
00081 static struct
00082 {
00083     char *name;
00084     int size;
00085 } operands[256] = {
00086 #include "wsopcodes.h"
00087 };
00088 
00089 /********************* Symbolic assembler instructions ******************/
00090 
00091 /* General helpers. */
00092 
00093 void ws_asm_link(WsCompiler *compiler, WsAsmIns *ins)
00094 {
00095     if (compiler->asm_tail) {
00096         compiler->asm_tail->next = ins;
00097         ins->prev = compiler->asm_tail;
00098 
00099         compiler->asm_tail = ins;
00100     } else
00101         compiler->asm_tail = compiler->asm_head = ins;
00102 }
00103 
00104 
00105 void ws_asm_print(WsCompiler *compiler)
00106 {
00107     WsAsmIns *ins;
00108 
00109     for (ins = compiler->asm_head; ins; ins = ins->next) {
00110         if (ins->type > 0xff) {
00111             /* A symbolic operand. */
00112             switch (ins->type) {
00113             case WS_ASM_P_LABEL:
00114                 ws_fprintf(WS_STDOUT, ".L%d:\t\t\t\t/* refcount=%d */\n",
00115                            ins->ws_label_idx, ins->ws_label_refcount);
00116                 break;
00117 
00118             case WS_ASM_P_JUMP:
00119                 ws_fprintf(WS_STDOUT, "\tjump*\t\tL%d\n",
00120                            ins->ws_label->ws_label_idx);
00121                 break;
00122 
00123             case WS_ASM_P_TJUMP:
00124                 ws_fprintf(WS_STDOUT, "\ttjump*\t\tL%d\n",
00125                            ins->ws_label->ws_label_idx);
00126                 break;
00127 
00128             case WS_ASM_P_CALL:
00129                 ws_fprintf(WS_STDOUT, "\tcall*\t\t%s\n",
00130                            compiler->functions[ins->ws_findex].name);
00131                 break;
00132 
00133             case WS_ASM_P_CALL_LIB:
00134                 {
00135                     const char *lib;
00136                     const char *func;
00137 
00138                     ws_stdlib_function_name(ins->ws_lindex,
00139                                             ins->ws_findex,
00140                                             &lib, &func);
00141                     ws_fprintf(WS_STDOUT, "\tcall_lib*\t%s.%s\n",
00142                                lib ? lib : "???",
00143                                func ? func : "???");
00144                 }
00145                 break;
00146 
00147             case WS_ASM_P_CALL_URL:
00148                 ws_fprintf(WS_STDOUT, "\tcall_url*\t%u %u %u\n",
00149                            ins->ws_lindex, ins->ws_findex, ins->ws_args);
00150                 break;
00151 
00152             case WS_ASM_P_LOAD_VAR:
00153                 ws_fprintf(WS_STDOUT, "\tload_var*\t%u\n", ins->ws_vindex);
00154                 break;
00155 
00156             case WS_ASM_P_STORE_VAR:
00157                 ws_fprintf(WS_STDOUT, "\tstore_var*\t%u\n", ins->ws_vindex);
00158                 break;
00159 
00160             case WS_ASM_P_INCR_VAR:
00161                 ws_fprintf(WS_STDOUT, "\tincr_var*\t%u\n", ins->ws_vindex);
00162                 break;
00163 
00164             case WS_ASM_P_LOAD_CONST:
00165                 ws_fprintf(WS_STDOUT, "\tload_const*\t%u\n", ins->ws_cindex);
00166                 break;
00167             }
00168         } else {
00169             WsUInt8 op = WS_ASM_OP(ins->type);
00170 
00171             if (operands[op].name) {
00172                 /* Operands add_asg and sub_asg are special. */
00173                 if (op == WS_ASM_ADD_ASG || op == WS_ASM_SUB_ASG)
00174                     ws_fprintf(WS_STDOUT, "\t%s\t\t%u\n", operands[ins->type].name,
00175                                ins->ws_vindex);
00176                 else
00177                     ws_fprintf(WS_STDOUT, "\t%s\n", operands[ins->type].name);
00178             } else
00179                 ws_fatal("ws_asm_print(): unknown operand 0x%x", op);
00180         }
00181     }
00182 }
00183 
00184 
00185 void ws_asm_dasm(WsCompilerPtr compiler, const unsigned char *code, size_t len)
00186 {
00187     size_t i = 0;
00188 
00189     while (i < len) {
00190         WsUInt8 byt = code[i];
00191         WsUInt8 op;
00192         WsUInt8 arg;
00193         WsUInt8 i8, j8, k8;
00194         WsUInt16 i16, j16;
00195 
00196         op = WS_ASM_OP(byt);
00197         arg = WS_ASM_ARG(byt);
00198 
00199         ws_fprintf(WS_STDOUT, "%4x:\t%-16s", i, WS_OPNAME(op));
00200 
00201         switch (op) {
00202             /* The `short jumps'. */
00203         case WS_ASM_JUMP_FW_S:
00204         case WS_ASM_TJUMP_FW_S:
00205             ws_fprintf(WS_STDOUT, "%x\n", i + WS_OPSIZE(op) + arg);
00206             break;
00207 
00208         case WS_ASM_JUMP_BW_S:
00209             ws_fprintf(WS_STDOUT, "%x\n", i - arg);
00210             break;
00211 
00212             /* Jumps with WsUInt8 argument. */
00213         case WS_ASM_JUMP_FW:
00214         case WS_ASM_TJUMP_FW:
00215             WS_GET_UINT8(code + i + 1, i8);
00216             ws_fprintf(WS_STDOUT, "%x\n", i + WS_OPSIZE(op) + i8);
00217             break;
00218 
00219         case WS_ASM_JUMP_BW:
00220         case WS_ASM_TJUMP_BW:
00221             WS_GET_UINT8(code + i + 1, i8);
00222             ws_fprintf(WS_STDOUT, "%x\n", i - i8);
00223             break;
00224 
00225             /* Jumps with wide argument. */
00226         case WS_ASM_JUMP_FW_W:
00227         case WS_ASM_TJUMP_FW_W:
00228             WS_GET_UINT16(code + i + 1, i16);
00229             ws_fprintf(WS_STDOUT, "%x\n", i + WS_OPSIZE(op) + i16);
00230             break;
00231 
00232         case WS_ASM_JUMP_BW_W:
00233         case WS_ASM_TJUMP_BW_W:
00234             WS_GET_UINT16(code + i + 1, i16);
00235             ws_fprintf(WS_STDOUT, "%x\n", i - i16);
00236             break;
00237 
00238             /* The `short' opcodes. */
00239         case WS_ASM_LOAD_VAR_S:
00240         case WS_ASM_STORE_VAR_S:
00241         case WS_ASM_INCR_VAR_S:
00242             ws_fprintf(WS_STDOUT, "%d\n", arg);
00243             break;
00244 
00245             /* Local script function calls. */
00246         case WS_ASM_CALL_S:
00247             ws_fprintf(WS_STDOUT, "%d\n", arg);
00248             break;
00249 
00250         case WS_ASM_CALL:
00251             WS_GET_UINT8(code + i + 1, i8);
00252             ws_fprintf(WS_STDOUT, "%d\n", i8);
00253             break;
00254 
00255             /* Library calls. */
00256         case WS_ASM_CALL_LIB_S:
00257         case WS_ASM_CALL_LIB:
00258         case WS_ASM_CALL_LIB_W:
00259             {
00260                 WsUInt8 findex;
00261                 WsUInt16 lindex;
00262                 char lnamebuf[64];
00263                 char fnamebuf[64];
00264                 const char *lname;
00265                 const char *fname;
00266 
00267                 if (op == WS_ASM_CALL_LIB_S) {
00268                     WS_GET_UINT8(code + i + 1, lindex);
00269                     findex = arg;
00270                 } else if (op == WS_ASM_CALL_LIB) {
00271                     WS_GET_UINT8(code + i + 1, findex);
00272                     WS_GET_UINT8(code + i + 2, lindex);
00273                 } else {
00274                     WS_GET_UINT8(code + i + 1, findex);
00275                     WS_GET_UINT16(code + i + 2, lindex);
00276                 }
00277 
00278                 if (!ws_stdlib_function_name(lindex, findex, &lname, &fname)) {
00279                     snprintf(lnamebuf, sizeof(lnamebuf), "%d", lindex);
00280                     snprintf(fnamebuf, sizeof(lnamebuf), "%d", findex);
00281                     lname = lnamebuf;
00282                     fname = fnamebuf;
00283                 }
00284                 ws_fprintf(WS_STDOUT, "%s.%s\n", lname, fname);
00285             }
00286             break;
00287 
00288             /* URL calls. */
00289         case WS_ASM_CALL_URL:
00290             WS_GET_UINT8(code + i + 1, i8);
00291             WS_GET_UINT8(code + i + 2, j8);
00292             WS_GET_UINT8(code + i + 3, k8);
00293             ws_fprintf(WS_STDOUT, "%d.%d %d\n", i8, j8, k8);
00294             break;
00295 
00296         case WS_ASM_CALL_URL_W:
00297             WS_GET_UINT16(code + i + 1, i16);
00298             WS_GET_UINT16(code + i + 3, j16);
00299             WS_GET_UINT8(code + i + 5, i8);
00300             ws_fprintf(WS_STDOUT, "%d.%d %d\n", i16, j16, i8);
00301             break;
00302 
00303             /* Constant access. */
00304         case WS_ASM_LOAD_CONST_S:
00305         case WS_ASM_LOAD_CONST:
00306         case WS_ASM_LOAD_CONST_W:
00307             if (op == WS_ASM_LOAD_CONST_S)
00308                 i16 = arg;
00309             else if (op == WS_ASM_LOAD_CONST) {
00310                 WS_GET_UINT8(code + i + 1, i8);
00311                 i16 = i8;
00312             } else
00313                 WS_GET_UINT16(code + i + 1, i16);
00314 
00315             ws_fprintf(WS_STDOUT, "%d\n", i16);
00316             break;
00317 
00318             /* Operands with WsUInt8 argument. */
00319         case WS_ASM_LOAD_VAR:
00320         case WS_ASM_STORE_VAR:
00321         case WS_ASM_INCR_VAR:
00322         case WS_ASM_DECR_VAR:
00323         case WS_ASM_ADD_ASG:
00324         case WS_ASM_SUB_ASG:
00325             WS_GET_UINT8(code + i + 1, i8);
00326             ws_fprintf(WS_STDOUT, "%d\n", i8);
00327             break;
00328 
00329             /* The trivial cases. */
00330         default:
00331             ws_fprintf(WS_STDOUT, "\n");
00332             break;
00333         }
00334 
00335         i += WS_OPSIZE(op);
00336     }
00337 }
00338 
00339 
00340 void
00341 ws_asm_linearize(WsCompiler *compiler)
00342 {
00343     WsAsmIns *ins;
00344     WsBool process_again = WS_TRUE;
00345 
00346     /* Calculate all offsets and select real assembler instructions for
00347        our internal pseudo instructions.  This is continued as long as
00348        the code changes. */
00349     while (process_again) {
00350         WsUInt32 offset = 1;
00351 
00352         process_again = WS_FALSE;
00353 
00354         for (ins = compiler->asm_head; ins; ins = ins->next) {
00355             ins->offset = offset;
00356 
00357             switch (ins->type) {
00358             case WS_ASM_JUMP_FW_S:
00359                 ins->ws_offset = (ins->ws_label->offset
00360                                   - (offset + WS_OPSIZE(ins->type)));
00361                 break;
00362 
00363             case WS_ASM_JUMP_FW:
00364                 ins->ws_offset = (ins->ws_label->offset
00365                                   - (offset + WS_OPSIZE(ins->type)));
00366 
00367                 if (ins->ws_offset <= 31) {
00368                     ins->type = WS_ASM_JUMP_FW_S;
00369                     process_again = WS_TRUE;
00370                 }
00371                 break;
00372 
00373             case WS_ASM_JUMP_FW_W:
00374                 ins->ws_offset = (ins->ws_label->offset
00375                                   - (offset + WS_OPSIZE(ins->type)));
00376 
00377                 if (ins->ws_offset <= 31) {
00378                     ins->type = WS_ASM_JUMP_FW_S;
00379                     process_again = WS_TRUE;
00380                 } else if (ins->ws_offset <= 255) {
00381                     ins->type = WS_ASM_JUMP_FW;
00382                     process_again = WS_TRUE;
00383                 }
00384                 break;
00385 
00386             case WS_ASM_JUMP_BW_S:
00387                 ins->ws_offset = offset - ins->ws_label->offset;
00388                 break;
00389 
00390             case WS_ASM_JUMP_BW:
00391                 ins->ws_offset = offset - ins->ws_label->offset;
00392 
00393                 if (ins->ws_offset <= 31) {
00394                     ins->type = WS_ASM_JUMP_BW_S;
00395                     process_again = WS_TRUE;
00396                 }
00397                 break;
00398 
00399             case WS_ASM_JUMP_BW_W:
00400                 ins->ws_offset = offset - ins->ws_label->offset;
00401 
00402                 if (ins->ws_offset <= 31) {
00403                     ins->type = WS_ASM_JUMP_BW_S;
00404                     process_again = WS_TRUE;
00405                 } else if (ins->ws_offset <= 255) {
00406                     ins->type = WS_ASM_JUMP_BW;
00407                     process_again = WS_TRUE;
00408                 }
00409                 break;
00410 
00411             case WS_ASM_TJUMP_FW_S:
00412                 ins->ws_offset = (ins->ws_label->offset
00413                                   - (offset + WS_OPSIZE(ins->type)));
00414                 break;
00415 
00416             case WS_ASM_TJUMP_FW:
00417                 ins->ws_offset = (ins->ws_label->offset
00418                                   - (offset + WS_OPSIZE(ins->type)));
00419 
00420                 if (ins->ws_offset <= 31) {
00421                     ins->type = WS_ASM_TJUMP_FW_S;
00422                     process_again = WS_TRUE;
00423                 }
00424                 break;
00425 
00426             case WS_ASM_TJUMP_FW_W:
00427                 ins->ws_offset = (ins->ws_label->offset
00428                                   - (offset + WS_OPSIZE(ins->type)));
00429 
00430                 if (ins->ws_offset <= 31) {
00431                     ins->type = WS_ASM_TJUMP_FW_S;
00432                     process_again = WS_TRUE;
00433                 } else if (ins->ws_offset <= 255) {
00434                     ins->type = WS_ASM_TJUMP_FW;
00435                     process_again = WS_TRUE;
00436                 }
00437                 break;
00438 
00439             case WS_ASM_TJUMP_BW:
00440                  ins->ws_offset = offset - ins->ws_label->offset;
00441                  break;
00442 
00443             case WS_ASM_TJUMP_BW_W:
00444                 ins->ws_offset = offset - ins->ws_label->offset;
00445 
00446                 if (ins->ws_offset <= 255) {
00447                     ins->type = WS_ASM_TJUMP_BW;
00448                     process_again = WS_TRUE;
00449                 }
00450                 break;
00451 
00452                 /*
00453                  * The pseudo instructions.
00454                  */
00455 
00456             case WS_ASM_P_LABEL:
00457                 /* Nothing here. */
00458                 break;
00459 
00460             case WS_ASM_P_JUMP:
00461                 if (ins->ws_label->offset == 0) {
00462                     /* A forward jump.  Let's assume the widest form. */
00463                     ins->type = WS_ASM_JUMP_FW_W;
00464                 } else {
00465                     ins->ws_offset = offset - ins->ws_label->offset;
00466 
00467                     /* Jump backwards. */
00468                     if (ins->ws_offset <= 31) {
00469                         ins->type = WS_ASM_JUMP_BW_S;
00470                     } else if (ins->ws_offset <= 255) {
00471                         ins->type = WS_ASM_JUMP_BW;
00472                     } else {
00473                         ins->type = WS_ASM_JUMP_BW_W;
00474                     }
00475                 }
00476                 break;
00477 
00478             case WS_ASM_P_TJUMP:
00479                 if (ins->ws_label->offset == 0) {
00480                     /* A forward jump.  Let's assume the widest form. */
00481                     ins->type = WS_ASM_TJUMP_FW_W;
00482                     process_again = WS_TRUE;
00483                 } else {
00484                     ins->ws_offset = offset - ins->ws_label->offset;
00485 
00486                     /* Jump backwards. */
00487                     if (ins->ws_offset <= 255) {
00488                         ins->type = WS_ASM_TJUMP_BW;
00489                     } else {
00490                         ins->type = WS_ASM_TJUMP_BW_W;
00491                     }
00492                 }
00493                 break;
00494 
00495             case WS_ASM_P_CALL:
00496                 if (ins->ws_findex <= 7) {
00497                     /* The most compact form. */
00498                     ins->type = WS_ASM_CALL_S;
00499                 } else {
00500                     /* The wider form. */
00501                     ins->type = WS_ASM_CALL;
00502                 }
00503                 break;
00504 
00505             case WS_ASM_P_CALL_LIB:
00506                 if (ins->ws_findex <= 7 && ins->ws_lindex <= 255) {
00507                     /* The most compact form. */
00508                     ins->type = WS_ASM_CALL_LIB_S;
00509                 } else if (ins->ws_findex <= 255 && ins->ws_lindex <= 255) {
00510                     /* The quite compact form. */
00511                     ins->type = WS_ASM_CALL_LIB;
00512                 } else {
00513                     /* The most liberal form. */
00514                     ins->type = WS_ASM_CALL_LIB_W;
00515                 }
00516                 break;
00517 
00518             case WS_ASM_P_CALL_URL:
00519                 if (ins->ws_findex <= 255 && ins->ws_lindex <= 255)
00520                     /* The compact form. */
00521                     ins->type = WS_ASM_CALL_URL;
00522                 else
00523                     ins->type = WS_ASM_CALL_URL_W;
00524                 break;
00525 
00526             case WS_ASM_P_LOAD_VAR:
00527                 if (ins->ws_vindex <= 31)
00528                     /* The compact form. */
00529                     ins->type = WS_ASM_LOAD_VAR_S;
00530                 else
00531                     ins->type = WS_ASM_LOAD_VAR;
00532                 break;
00533 
00534             case WS_ASM_P_STORE_VAR:
00535                 if (ins->ws_vindex <= 15)
00536                     ins->type = WS_ASM_STORE_VAR_S;
00537                 else
00538                     ins->type = WS_ASM_STORE_VAR;
00539                 break;
00540 
00541             case WS_ASM_P_INCR_VAR:
00542                 if (ins->ws_vindex <= 7)
00543                     ins->type = WS_ASM_INCR_VAR_S;
00544                 else
00545                     ins->type = WS_ASM_INCR_VAR;
00546                 break;
00547 
00548             case WS_ASM_P_LOAD_CONST:
00549                 if (ins->ws_cindex <= 15)
00550                     ins->type = WS_ASM_LOAD_CONST_S;
00551                 else if (ins->ws_cindex <= 255)
00552                     ins->type = WS_ASM_LOAD_CONST;
00553                 else
00554                     ins->type = WS_ASM_LOAD_CONST_W;
00555                 break;
00556             }
00557 
00558             gw_assert(ins->type == WS_ASM_P_LABEL || ins->type < 0x100);
00559 
00560             if (ins->type != WS_ASM_P_LABEL) {
00561                 gw_assert(operands[ins->type].name != NULL);
00562                 offset += operands[ins->type].size;
00563             }
00564         }
00565     }
00566 
00567     /* Ok, ready to linearize the byte-code. */
00568     for (ins = compiler->asm_head; ins; ins = ins->next) {
00569         if (ins->type == WS_ASM_P_LABEL)
00570             continue;
00571 
00572         gw_assert(ins->type <= 0xff);
00573 
00574         switch (ins->type) {
00575         case WS_ASM_JUMP_FW_S:
00576         case WS_ASM_JUMP_BW_S:
00577         case WS_ASM_TJUMP_FW_S:
00578             if (!ws_encode_buffer(&compiler->byte_code,
00579                                   WS_ENC_BYTE,
00580                                   WS_ASM_GLUE(ins->type, ins->ws_offset),
00581                                   WS_ENC_END))
00582                 goto error;
00583             break;
00584 
00585         case WS_ASM_JUMP_FW:
00586         case WS_ASM_JUMP_BW:
00587         case WS_ASM_TJUMP_FW:
00588         case WS_ASM_TJUMP_BW:
00589             if (!ws_encode_buffer(&compiler->byte_code,
00590                                   WS_ENC_BYTE, ins->type,
00591                                   WS_ENC_UINT8, (WsUInt8) ins->ws_offset,
00592                                   WS_ENC_END))
00593                 goto error;
00594             break;
00595 
00596         case WS_ASM_JUMP_FW_W:
00597         case WS_ASM_JUMP_BW_W:
00598         case WS_ASM_TJUMP_FW_W:
00599         case WS_ASM_TJUMP_BW_W:
00600             if (!ws_encode_buffer(&compiler->byte_code,
00601                                   WS_ENC_BYTE, ins->type,
00602                                   WS_ENC_UINT16, (WsUInt16) ins->ws_offset,
00603                                   WS_ENC_END))
00604                 goto error;
00605             break;
00606 
00607         case WS_ASM_CALL_S:
00608             if (!ws_encode_buffer(&compiler->byte_code,
00609                                   WS_ENC_BYTE,
00610                                   WS_ASM_GLUE(ins->type, ins->ws_findex),
00611                                   WS_ENC_END))
00612                 goto error;
00613             break;
00614 
00615         case WS_ASM_CALL:
00616             if (!ws_encode_buffer(&compiler->byte_code,
00617                                   WS_ENC_BYTE, (WsByte) ins->type,
00618                                   WS_ENC_UINT8, (WsUInt8) ins->ws_findex,
00619                                   WS_ENC_END))
00620                 goto error;
00621             break;
00622 
00623         case WS_ASM_CALL_LIB_S:
00624             if (!ws_encode_buffer(&compiler->byte_code,
00625                                   WS_ENC_BYTE,
00626                                   WS_ASM_GLUE(ins->type, ins->ws_findex),
00627                                   WS_ENC_UINT8, (WsUInt8) ins->ws_lindex,
00628                                   WS_ENC_END))
00629                 goto error;
00630             break;
00631 
00632         case WS_ASM_CALL_LIB:
00633             if (!ws_encode_buffer(&compiler->byte_code,
00634                                   WS_ENC_BYTE, (WsByte) ins->type,
00635                                   WS_ENC_UINT8, (WsUInt8) ins->ws_findex,
00636                                   WS_ENC_UINT8, (WsUInt8) ins->ws_lindex,
00637                                   WS_ENC_END))
00638                 goto error;
00639             break;
00640 
00641         case WS_ASM_CALL_LIB_W:
00642             if (!ws_encode_buffer(&compiler->byte_code,
00643                                   WS_ENC_BYTE, (WsByte) ins->type,
00644                                   WS_ENC_UINT8, (WsUInt8) ins->ws_findex,
00645                                   WS_ENC_UINT16, (WsUInt16) ins->ws_lindex,
00646                                   WS_ENC_END))
00647                 goto error;
00648             break;
00649 
00650         case WS_ASM_CALL_URL:
00651             if (!ws_encode_buffer(&compiler->byte_code,
00652                                   WS_ENC_BYTE, (WsByte) ins->type,
00653                                   WS_ENC_UINT8, (WsUInt8) ins->ws_lindex,
00654                                   WS_ENC_UINT8, (WsUInt8) ins->ws_findex,
00655                                   WS_ENC_UINT8, (WsUInt8) ins->ws_args,
00656                                   WS_ENC_END))
00657                 goto error;
00658             break;
00659 
00660         case WS_ASM_CALL_URL_W:
00661             if (!ws_encode_buffer(&compiler->byte_code,
00662                                   WS_ENC_BYTE, (WsByte) ins->type,
00663                                   WS_ENC_UINT16, (WsUInt16) ins->ws_lindex,
00664                                   WS_ENC_UINT16, (WsUInt16) ins->ws_findex,
00665                                   WS_ENC_UINT8, (WsUInt8) ins->ws_args,
00666                                   WS_ENC_END))
00667                 goto error;
00668             break;
00669 
00670         case WS_ASM_LOAD_VAR_S:
00671         case WS_ASM_STORE_VAR_S:
00672             if (!ws_encode_buffer(&compiler->byte_code,
00673                                   WS_ENC_BYTE,
00674                                   WS_ASM_GLUE(ins->type, ins->ws_vindex),
00675                                   WS_ENC_END))
00676                 goto error;
00677             break;
00678 
00679         case WS_ASM_LOAD_VAR:
00680         case WS_ASM_STORE_VAR:
00681             if (!ws_encode_buffer(&compiler->byte_code,
00682                                   WS_ENC_BYTE, (WsByte) ins->type,
00683                                   WS_ENC_UINT8, (WsUInt8) ins->ws_vindex,
00684                                   WS_ENC_END))
00685                 goto error;
00686             break;
00687 
00688         case WS_ASM_INCR_VAR_S:
00689             if (!ws_encode_buffer(&compiler->byte_code,
00690                                   WS_ENC_BYTE,
00691                                   WS_ASM_GLUE(ins->type, ins->ws_vindex),
00692                                   WS_ENC_END))
00693                 goto error;
00694             break;
00695 
00696         case WS_ASM_INCR_VAR:
00697         case WS_ASM_DECR_VAR:
00698             if (!ws_encode_buffer(&compiler->byte_code,
00699                                   WS_ENC_BYTE, (WsByte) ins->type,
00700                                   WS_ENC_UINT8, (WsUInt8) ins->ws_vindex,
00701                                   WS_ENC_END))
00702                 goto error;
00703             break;
00704 
00705         case WS_ASM_LOAD_CONST_S:
00706             if (!ws_encode_buffer(&compiler->byte_code,
00707                                   WS_ENC_BYTE,
00708                                   WS_ASM_GLUE(ins->type, ins->ws_cindex),
00709                                   WS_ENC_END))
00710                 goto error;
00711             break;
00712 
00713         case WS_ASM_LOAD_CONST:
00714             if (!ws_encode_buffer(&compiler->byte_code,
00715                                   WS_ENC_BYTE, (WsByte) ins->type,
00716                                   WS_ENC_UINT8, (WsUInt8) ins->ws_cindex,
00717                                   WS_ENC_END))
00718                 goto error;
00719             break;
00720 
00721         case WS_ASM_LOAD_CONST_W:
00722             if (!ws_encode_buffer(&compiler->byte_code,
00723                                   WS_ENC_BYTE, (WsByte) ins->type,
00724                                   WS_ENC_UINT16, (WsUInt16) ins->ws_cindex,
00725                                   WS_ENC_END))
00726                 goto error;
00727             break;
00728 
00729         case WS_ASM_ADD_ASG:
00730         case WS_ASM_SUB_ASG:
00731             if (!ws_encode_buffer(&compiler->byte_code,
00732                                   WS_ENC_BYTE, (WsByte) ins->type,
00733                                   WS_ENC_UINT8, (WsUInt8) ins->ws_vindex,
00734                                   WS_ENC_END))
00735                 goto error;
00736             break;
00737 
00738         case WS_ASM_CONST_0:
00739         case WS_ASM_CONST_1:
00740         case WS_ASM_CONST_M1:
00741         case WS_ASM_CONST_ES:
00742         case WS_ASM_CONST_INVALID:
00743         case WS_ASM_CONST_TRUE:
00744         case WS_ASM_CONST_FALSE:
00745         case WS_ASM_INCR:
00746         case WS_ASM_DECR:
00747         case WS_ASM_UMINUS:
00748         case WS_ASM_ADD:
00749         case WS_ASM_SUB:
00750         case WS_ASM_MUL:
00751         case WS_ASM_DIV:
00752         case WS_ASM_IDIV:
00753         case WS_ASM_REM:
00754         case WS_ASM_B_AND:
00755         case WS_ASM_B_OR:
00756         case WS_ASM_B_XOR:
00757         case WS_ASM_B_NOT:
00758         case WS_ASM_B_LSHIFT:
00759         case WS_ASM_B_RSSHIFT:
00760         case WS_ASM_B_RSZSHIFT:
00761         case WS_ASM_EQ:
00762         case WS_ASM_LE:
00763         case WS_ASM_LT:
00764         case WS_ASM_GE:
00765         case WS_ASM_GT:
00766         case WS_ASM_NE:
00767         case WS_ASM_NOT:
00768         case WS_ASM_SCAND:
00769         case WS_ASM_SCOR:
00770         case WS_ASM_TOBOOL:
00771         case WS_ASM_POP:
00772         case WS_ASM_TYPEOF:
00773         case WS_ASM_ISVALID:
00774         case WS_ASM_RETURN:
00775         case WS_ASM_RETURN_ES:
00776         case WS_ASM_DEBUG:
00777             if (!ws_encode_buffer(&compiler->byte_code,
00778                                   WS_ENC_BYTE, (WsByte) ins->type,
00779                                   WS_ENC_END))
00780                 goto error;
00781             break;
00782 
00783         default:
00784             ws_fatal("ws_asm_linearize(): unknown instruction 0x%02x",
00785                      ins->type);
00786             break;
00787         }
00788     }
00789 
00790     /*
00791      * Avoid generating 0-length functions, because not all clients
00792      * handle them correctly.
00793      */
00794     if (ws_buffer_len(&compiler->byte_code) == 0) {
00795     if (!ws_encode_buffer(&compiler->byte_code,
00796                   WS_ENC_BYTE, (WsByte) WS_ASM_RETURN_ES,
00797                   WS_ENC_END))
00798         goto error;
00799     }
00800 
00801     return;
00802 
00803     /*
00804      * Error handling.
00805      */
00806 
00807 error:
00808 
00809     ws_error_memory(compiler);
00810     return;
00811 }
00812 
00813 
00814 /* Contructors for assembler instructions. */
00815 
00816 static WsAsmIns *asm_alloc(WsCompiler *compiler, WsUInt16 type, WsUInt32 line)
00817 {
00818     WsAsmIns *ins = ws_f_calloc(compiler->pool_asm, 1, sizeof(*ins));
00819 
00820     if (ins == NULL)
00821         ws_error_memory(compiler);
00822     else {
00823         ins->type = type;
00824         ins->line = line;
00825     }
00826 
00827     return ins;
00828 }
00829 
00830 
00831 WsAsmIns *ws_asm_label(WsCompiler *compiler, WsUInt32 line)
00832 {
00833     WsAsmIns *ins = asm_alloc(compiler, WS_ASM_P_LABEL, line);
00834 
00835     if (ins)
00836         ins->ws_label_idx = compiler->next_label++;
00837 
00838     return ins;
00839 }
00840 
00841 
00842 WsAsmIns *ws_asm_branch(WsCompiler *compiler, WsUInt32 line, WsUInt16 inst,
00843                         WsAsmIns *label)
00844 {
00845     WsAsmIns *ins = asm_alloc(compiler, inst, line);
00846 
00847     if (ins) {
00848         ins->ws_label = label;
00849         label->ws_label_refcount++;
00850     }
00851 
00852     return ins;
00853 }
00854 
00855 
00856 WsAsmIns *ws_asm_call(WsCompiler *compiler, WsUInt32 line, WsUInt8 findex)
00857 {
00858     WsAsmIns *ins = asm_alloc(compiler, WS_ASM_P_CALL, line);
00859 
00860     if (ins)
00861         ins->ws_findex = findex;
00862 
00863     return ins;
00864 }
00865 
00866 
00867 WsAsmIns *ws_asm_call_lib(WsCompiler *compiler, WsUInt32 line, WsUInt8 findex,
00868                 WsUInt16 lindex)
00869 {
00870     WsAsmIns *ins = asm_alloc(compiler, WS_ASM_P_CALL_LIB, line);
00871 
00872     if (ins) {
00873         ins->ws_findex = findex;
00874         ins->ws_lindex = lindex;
00875     }
00876 
00877     return ins;
00878 }
00879 
00880 
00881 WsAsmIns *ws_asm_call_url(WsCompiler *compiler, WsUInt32 line, WsUInt16 findex,
00882                           WsUInt16 urlindex, WsUInt8 args)
00883 {
00884     WsAsmIns *ins = asm_alloc(compiler, WS_ASM_P_CALL_URL, line);
00885 
00886     if (ins) {
00887         ins->ws_findex = findex;
00888         ins->ws_lindex = urlindex;
00889         ins->ws_args = args;
00890     }
00891 
00892     return ins;
00893 }
00894 
00895 
00896 WsAsmIns *ws_asm_variable(WsCompiler *compiler, WsUInt32 line, WsUInt16 inst,
00897                           WsUInt8 vindex)
00898 {
00899     WsAsmIns *ins = asm_alloc(compiler, inst, line);
00900 
00901     if (ins)
00902         ins->ws_vindex = vindex;
00903 
00904     return ins;
00905 }
00906 
00907 
00908 WsAsmIns *ws_asm_load_const(WsCompiler *compiler, WsUInt32 line,
00909                             WsUInt16 cindex)
00910 {
00911     WsAsmIns *ins = asm_alloc(compiler, WS_ASM_P_LOAD_CONST, line);
00912 
00913     if (ins)
00914         ins->ws_cindex = cindex;
00915 
00916     return ins;
00917 }
00918 
00919 
00920 WsAsmIns *ws_asm_ins(WsCompiler *compiler, WsUInt32 line, WsUInt8 opcode)
00921 {
00922     return asm_alloc(compiler, opcode, line);
00923 }
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.