Kannel: Open Source WAP and SMS gateway  $Revision: 5037 $
wsasm.c
Go to the documentation of this file.
1 /* ====================================================================
2  * The Kannel Software License, Version 1.0
3  *
4  * Copyright (c) 2001-2016 Kannel Group
5  * Copyright (c) 1998-2001 WapIT Ltd.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Kannel Group (http://www.kannel.org/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Kannel" and "Kannel Group" must not be used to
28  * endorse or promote products derived from this software without
29  * prior written permission. For written permission, please
30  * contact org@kannel.org.
31  *
32  * 5. Products derived from this software may not be called "Kannel",
33  * nor may "Kannel" appear in their name, without prior written
34  * permission of the Kannel Group.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS
40  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
41  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
42  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
43  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
44  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
45  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
46  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47  * ====================================================================
48  *
49  * This software consists of voluntary contributions made by many
50  * individuals on behalf of the Kannel Group. For more information on
51  * the Kannel Group, please see <http://www.kannel.org/>.
52  *
53  * Portions of this software are based upon software originally written at
54  * WapIT Ltd., Helsinki, Finland for the Kannel project.
55  */
56 
57 /*
58  *
59  * wsasm.c
60  *
61  * Author: Markku Rossi <mtr@iki.fi>
62  *
63  * Copyright (c) 1999-2000 WAPIT OY LTD.
64  * All rights reserved.
65  *
66  * Byte-code assembler.
67  *
68  */
69 
70 #include "wsint.h"
71 #include "wsasm.h"
72 #include "wsstdlib.h"
73 
74 /********************* Macros to fetch items from BC operands ***********/
75 
76 #define WS_OPNAME(op) (operands[(op)].name)
77 #define WS_OPSIZE(op) (operands[(op)].size)
78 
79 /********************* Byte-code operands *******************************/
80 
81 static struct
82 {
83  char *name;
84  int size;
85 } operands[256] = {
86 #include "wsopcodes.h"
87 };
88 
89 /********************* Symbolic assembler instructions ******************/
90 
91 /* General helpers. */
92 
93 void ws_asm_link(WsCompiler *compiler, WsAsmIns *ins)
94 {
95  if (compiler->asm_tail) {
96  compiler->asm_tail->next = ins;
97  ins->prev = compiler->asm_tail;
98 
99  compiler->asm_tail = ins;
100  } else
101  compiler->asm_tail = compiler->asm_head = ins;
102 }
103 
104 
105 void ws_asm_print(WsCompiler *compiler)
106 {
107  WsAsmIns *ins;
108 
109  for (ins = compiler->asm_head; ins; ins = ins->next) {
110  if (ins->type > 0xff) {
111  /* A symbolic operand. */
112  switch (ins->type) {
113  case WS_ASM_P_LABEL:
114  ws_fprintf(WS_STDOUT, ".L%d:\t\t\t\t/* refcount=%d */\n",
115  ins->ws_label_idx, ins->ws_label_refcount);
116  break;
117 
118  case WS_ASM_P_JUMP:
119  ws_fprintf(WS_STDOUT, "\tjump*\t\tL%d\n",
120  ins->ws_label->ws_label_idx);
121  break;
122 
123  case WS_ASM_P_TJUMP:
124  ws_fprintf(WS_STDOUT, "\ttjump*\t\tL%d\n",
125  ins->ws_label->ws_label_idx);
126  break;
127 
128  case WS_ASM_P_CALL:
129  ws_fprintf(WS_STDOUT, "\tcall*\t\t%s\n",
130  compiler->functions[ins->ws_findex].name);
131  break;
132 
133  case WS_ASM_P_CALL_LIB:
134  {
135  const char *lib;
136  const char *func;
137 
138  ws_stdlib_function_name(ins->ws_lindex,
139  ins->ws_findex,
140  &lib, &func);
141  ws_fprintf(WS_STDOUT, "\tcall_lib*\t%s.%s\n",
142  lib ? lib : "???",
143  func ? func : "???");
144  }
145  break;
146 
147  case WS_ASM_P_CALL_URL:
148  ws_fprintf(WS_STDOUT, "\tcall_url*\t%u %u %u\n",
149  ins->ws_lindex, ins->ws_findex, ins->ws_args);
150  break;
151 
152  case WS_ASM_P_LOAD_VAR:
153  ws_fprintf(WS_STDOUT, "\tload_var*\t%u\n", ins->ws_vindex);
154  break;
155 
156  case WS_ASM_P_STORE_VAR:
157  ws_fprintf(WS_STDOUT, "\tstore_var*\t%u\n", ins->ws_vindex);
158  break;
159 
160  case WS_ASM_P_INCR_VAR:
161  ws_fprintf(WS_STDOUT, "\tincr_var*\t%u\n", ins->ws_vindex);
162  break;
163 
164  case WS_ASM_P_LOAD_CONST:
165  ws_fprintf(WS_STDOUT, "\tload_const*\t%u\n", ins->ws_cindex);
166  break;
167  }
168  } else {
169  WsUInt8 op = WS_ASM_OP(ins->type);
170 
171  if (operands[op].name) {
172  /* Operands add_asg and sub_asg are special. */
173  if (op == WS_ASM_ADD_ASG || op == WS_ASM_SUB_ASG)
174  ws_fprintf(WS_STDOUT, "\t%s\t\t%u\n", operands[ins->type].name,
175  ins->ws_vindex);
176  else
177  ws_fprintf(WS_STDOUT, "\t%s\n", operands[ins->type].name);
178  } else
179  ws_fatal("ws_asm_print(): unknown operand 0x%x", op);
180  }
181  }
182 }
183 
184 
185 void ws_asm_dasm(WsCompilerPtr compiler, const unsigned char *code, size_t len)
186 {
187  size_t i = 0;
188 
189  while (i < len) {
190  WsUInt8 byt = code[i];
191  WsUInt8 op;
192  WsUInt8 arg;
193  WsUInt8 i8, j8, k8;
194  WsUInt16 i16, j16;
195 
196  op = WS_ASM_OP(byt);
197  arg = WS_ASM_ARG(byt);
198 
199  ws_fprintf(WS_STDOUT, "%4x:\t%-16s", i, WS_OPNAME(op));
200 
201  switch (op) {
202  /* The `short jumps'. */
203  case WS_ASM_JUMP_FW_S:
204  case WS_ASM_TJUMP_FW_S:
205  ws_fprintf(WS_STDOUT, "%x\n", i + WS_OPSIZE(op) + arg);
206  break;
207 
208  case WS_ASM_JUMP_BW_S:
209  ws_fprintf(WS_STDOUT, "%x\n", i - arg);
210  break;
211 
212  /* Jumps with WsUInt8 argument. */
213  case WS_ASM_JUMP_FW:
214  case WS_ASM_TJUMP_FW:
215  WS_GET_UINT8(code + i + 1, i8);
216  ws_fprintf(WS_STDOUT, "%x\n", i + WS_OPSIZE(op) + i8);
217  break;
218 
219  case WS_ASM_JUMP_BW:
220  case WS_ASM_TJUMP_BW:
221  WS_GET_UINT8(code + i + 1, i8);
222  ws_fprintf(WS_STDOUT, "%x\n", i - i8);
223  break;
224 
225  /* Jumps with wide argument. */
226  case WS_ASM_JUMP_FW_W:
227  case WS_ASM_TJUMP_FW_W:
228  WS_GET_UINT16(code + i + 1, i16);
229  ws_fprintf(WS_STDOUT, "%x\n", i + WS_OPSIZE(op) + i16);
230  break;
231 
232  case WS_ASM_JUMP_BW_W:
233  case WS_ASM_TJUMP_BW_W:
234  WS_GET_UINT16(code + i + 1, i16);
235  ws_fprintf(WS_STDOUT, "%x\n", i - i16);
236  break;
237 
238  /* The `short' opcodes. */
239  case WS_ASM_LOAD_VAR_S:
240  case WS_ASM_STORE_VAR_S:
241  case WS_ASM_INCR_VAR_S:
242  ws_fprintf(WS_STDOUT, "%d\n", arg);
243  break;
244 
245  /* Local script function calls. */
246  case WS_ASM_CALL_S:
247  ws_fprintf(WS_STDOUT, "%d\n", arg);
248  break;
249 
250  case WS_ASM_CALL:
251  WS_GET_UINT8(code + i + 1, i8);
252  ws_fprintf(WS_STDOUT, "%d\n", i8);
253  break;
254 
255  /* Library calls. */
256  case WS_ASM_CALL_LIB_S:
257  case WS_ASM_CALL_LIB:
258  case WS_ASM_CALL_LIB_W:
259  {
260  WsUInt8 findex;
261  WsUInt16 lindex;
262  char lnamebuf[64];
263  char fnamebuf[64];
264  const char *lname;
265  const char *fname;
266 
267  if (op == WS_ASM_CALL_LIB_S) {
268  WS_GET_UINT8(code + i + 1, lindex);
269  findex = arg;
270  } else if (op == WS_ASM_CALL_LIB) {
271  WS_GET_UINT8(code + i + 1, findex);
272  WS_GET_UINT8(code + i + 2, lindex);
273  } else {
274  WS_GET_UINT8(code + i + 1, findex);
275  WS_GET_UINT16(code + i + 2, lindex);
276  }
277 
278  if (!ws_stdlib_function_name(lindex, findex, &lname, &fname)) {
279  snprintf(lnamebuf, sizeof(lnamebuf), "%d", lindex);
280  snprintf(fnamebuf, sizeof(lnamebuf), "%d", findex);
281  lname = lnamebuf;
282  fname = fnamebuf;
283  }
284  ws_fprintf(WS_STDOUT, "%s.%s\n", lname, fname);
285  }
286  break;
287 
288  /* URL calls. */
289  case WS_ASM_CALL_URL:
290  WS_GET_UINT8(code + i + 1, i8);
291  WS_GET_UINT8(code + i + 2, j8);
292  WS_GET_UINT8(code + i + 3, k8);
293  ws_fprintf(WS_STDOUT, "%d.%d %d\n", i8, j8, k8);
294  break;
295 
296  case WS_ASM_CALL_URL_W:
297  WS_GET_UINT16(code + i + 1, i16);
298  WS_GET_UINT16(code + i + 3, j16);
299  WS_GET_UINT8(code + i + 5, i8);
300  ws_fprintf(WS_STDOUT, "%d.%d %d\n", i16, j16, i8);
301  break;
302 
303  /* Constant access. */
304  case WS_ASM_LOAD_CONST_S:
305  case WS_ASM_LOAD_CONST:
306  case WS_ASM_LOAD_CONST_W:
307  if (op == WS_ASM_LOAD_CONST_S)
308  i16 = arg;
309  else if (op == WS_ASM_LOAD_CONST) {
310  WS_GET_UINT8(code + i + 1, i8);
311  i16 = i8;
312  } else
313  WS_GET_UINT16(code + i + 1, i16);
314 
315  ws_fprintf(WS_STDOUT, "%d\n", i16);
316  break;
317 
318  /* Operands with WsUInt8 argument. */
319  case WS_ASM_LOAD_VAR:
320  case WS_ASM_STORE_VAR:
321  case WS_ASM_INCR_VAR:
322  case WS_ASM_DECR_VAR:
323  case WS_ASM_ADD_ASG:
324  case WS_ASM_SUB_ASG:
325  WS_GET_UINT8(code + i + 1, i8);
326  ws_fprintf(WS_STDOUT, "%d\n", i8);
327  break;
328 
329  /* The trivial cases. */
330  default:
331  ws_fprintf(WS_STDOUT, "\n");
332  break;
333  }
334 
335  i += WS_OPSIZE(op);
336  }
337 }
338 
339 
340 void
342 {
343  WsAsmIns *ins;
344  WsBool process_again = WS_TRUE;
345 
346  /* Calculate all offsets and select real assembler instructions for
347  our internal pseudo instructions. This is continued as long as
348  the code changes. */
349  while (process_again) {
350  WsUInt32 offset = 1;
351 
352  process_again = WS_FALSE;
353 
354  for (ins = compiler->asm_head; ins; ins = ins->next) {
355  ins->offset = offset;
356 
357  switch (ins->type) {
358  case WS_ASM_JUMP_FW_S:
359  ins->ws_offset = (ins->ws_label->offset
360  - (offset + WS_OPSIZE(ins->type)));
361  break;
362 
363  case WS_ASM_JUMP_FW:
364  ins->ws_offset = (ins->ws_label->offset
365  - (offset + WS_OPSIZE(ins->type)));
366 
367  if (ins->ws_offset <= 31) {
368  ins->type = WS_ASM_JUMP_FW_S;
369  process_again = WS_TRUE;
370  }
371  break;
372 
373  case WS_ASM_JUMP_FW_W:
374  ins->ws_offset = (ins->ws_label->offset
375  - (offset + WS_OPSIZE(ins->type)));
376 
377  if (ins->ws_offset <= 31) {
378  ins->type = WS_ASM_JUMP_FW_S;
379  process_again = WS_TRUE;
380  } else if (ins->ws_offset <= 255) {
381  ins->type = WS_ASM_JUMP_FW;
382  process_again = WS_TRUE;
383  }
384  break;
385 
386  case WS_ASM_JUMP_BW_S:
387  ins->ws_offset = offset - ins->ws_label->offset;
388  break;
389 
390  case WS_ASM_JUMP_BW:
391  ins->ws_offset = offset - ins->ws_label->offset;
392 
393  if (ins->ws_offset <= 31) {
394  ins->type = WS_ASM_JUMP_BW_S;
395  process_again = WS_TRUE;
396  }
397  break;
398 
399  case WS_ASM_JUMP_BW_W:
400  ins->ws_offset = offset - ins->ws_label->offset;
401 
402  if (ins->ws_offset <= 31) {
403  ins->type = WS_ASM_JUMP_BW_S;
404  process_again = WS_TRUE;
405  } else if (ins->ws_offset <= 255) {
406  ins->type = WS_ASM_JUMP_BW;
407  process_again = WS_TRUE;
408  }
409  break;
410 
411  case WS_ASM_TJUMP_FW_S:
412  ins->ws_offset = (ins->ws_label->offset
413  - (offset + WS_OPSIZE(ins->type)));
414  break;
415 
416  case WS_ASM_TJUMP_FW:
417  ins->ws_offset = (ins->ws_label->offset
418  - (offset + WS_OPSIZE(ins->type)));
419 
420  if (ins->ws_offset <= 31) {
421  ins->type = WS_ASM_TJUMP_FW_S;
422  process_again = WS_TRUE;
423  }
424  break;
425 
426  case WS_ASM_TJUMP_FW_W:
427  ins->ws_offset = (ins->ws_label->offset
428  - (offset + WS_OPSIZE(ins->type)));
429 
430  if (ins->ws_offset <= 31) {
431  ins->type = WS_ASM_TJUMP_FW_S;
432  process_again = WS_TRUE;
433  } else if (ins->ws_offset <= 255) {
434  ins->type = WS_ASM_TJUMP_FW;
435  process_again = WS_TRUE;
436  }
437  break;
438 
439  case WS_ASM_TJUMP_BW:
440  ins->ws_offset = offset - ins->ws_label->offset;
441  break;
442 
443  case WS_ASM_TJUMP_BW_W:
444  ins->ws_offset = offset - ins->ws_label->offset;
445 
446  if (ins->ws_offset <= 255) {
447  ins->type = WS_ASM_TJUMP_BW;
448  process_again = WS_TRUE;
449  }
450  break;
451 
452  /*
453  * The pseudo instructions.
454  */
455 
456  case WS_ASM_P_LABEL:
457  /* Nothing here. */
458  break;
459 
460  case WS_ASM_P_JUMP:
461  if (ins->ws_label->offset == 0) {
462  /* A forward jump. Let's assume the widest form. */
463  ins->type = WS_ASM_JUMP_FW_W;
464  } else {
465  ins->ws_offset = offset - ins->ws_label->offset;
466 
467  /* Jump backwards. */
468  if (ins->ws_offset <= 31) {
469  ins->type = WS_ASM_JUMP_BW_S;
470  } else if (ins->ws_offset <= 255) {
471  ins->type = WS_ASM_JUMP_BW;
472  } else {
473  ins->type = WS_ASM_JUMP_BW_W;
474  }
475  }
476  break;
477 
478  case WS_ASM_P_TJUMP:
479  if (ins->ws_label->offset == 0) {
480  /* A forward jump. Let's assume the widest form. */
481  ins->type = WS_ASM_TJUMP_FW_W;
482  process_again = WS_TRUE;
483  } else {
484  ins->ws_offset = offset - ins->ws_label->offset;
485 
486  /* Jump backwards. */
487  if (ins->ws_offset <= 255) {
488  ins->type = WS_ASM_TJUMP_BW;
489  } else {
490  ins->type = WS_ASM_TJUMP_BW_W;
491  }
492  }
493  break;
494 
495  case WS_ASM_P_CALL:
496  if (ins->ws_findex <= 7) {
497  /* The most compact form. */
498  ins->type = WS_ASM_CALL_S;
499  } else {
500  /* The wider form. */
501  ins->type = WS_ASM_CALL;
502  }
503  break;
504 
505  case WS_ASM_P_CALL_LIB:
506  if (ins->ws_findex <= 7 && ins->ws_lindex <= 255) {
507  /* The most compact form. */
508  ins->type = WS_ASM_CALL_LIB_S;
509  } else if (ins->ws_findex <= 255 && ins->ws_lindex <= 255) {
510  /* The quite compact form. */
511  ins->type = WS_ASM_CALL_LIB;
512  } else {
513  /* The most liberal form. */
514  ins->type = WS_ASM_CALL_LIB_W;
515  }
516  break;
517 
518  case WS_ASM_P_CALL_URL:
519  if (ins->ws_findex <= 255 && ins->ws_lindex <= 255)
520  /* The compact form. */
521  ins->type = WS_ASM_CALL_URL;
522  else
523  ins->type = WS_ASM_CALL_URL_W;
524  break;
525 
526  case WS_ASM_P_LOAD_VAR:
527  if (ins->ws_vindex <= 31)
528  /* The compact form. */
529  ins->type = WS_ASM_LOAD_VAR_S;
530  else
531  ins->type = WS_ASM_LOAD_VAR;
532  break;
533 
534  case WS_ASM_P_STORE_VAR:
535  if (ins->ws_vindex <= 15)
536  ins->type = WS_ASM_STORE_VAR_S;
537  else
538  ins->type = WS_ASM_STORE_VAR;
539  break;
540 
541  case WS_ASM_P_INCR_VAR:
542  if (ins->ws_vindex <= 7)
543  ins->type = WS_ASM_INCR_VAR_S;
544  else
545  ins->type = WS_ASM_INCR_VAR;
546  break;
547 
548  case WS_ASM_P_LOAD_CONST:
549  if (ins->ws_cindex <= 15)
550  ins->type = WS_ASM_LOAD_CONST_S;
551  else if (ins->ws_cindex <= 255)
552  ins->type = WS_ASM_LOAD_CONST;
553  else
554  ins->type = WS_ASM_LOAD_CONST_W;
555  break;
556  }
557 
558  gw_assert(ins->type == WS_ASM_P_LABEL || ins->type < 0x100);
559 
560  if (ins->type != WS_ASM_P_LABEL) {
561  gw_assert(operands[ins->type].name != NULL);
562  offset += operands[ins->type].size;
563  }
564  }
565  }
566 
567  /* Ok, ready to linearize the byte-code. */
568  for (ins = compiler->asm_head; ins; ins = ins->next) {
569  if (ins->type == WS_ASM_P_LABEL)
570  continue;
571 
572  gw_assert(ins->type <= 0xff);
573 
574  switch (ins->type) {
575  case WS_ASM_JUMP_FW_S:
576  case WS_ASM_JUMP_BW_S:
577  case WS_ASM_TJUMP_FW_S:
578  if (!ws_encode_buffer(&compiler->byte_code,
579  WS_ENC_BYTE,
580  WS_ASM_GLUE(ins->type, ins->ws_offset),
581  WS_ENC_END))
582  goto error;
583  break;
584 
585  case WS_ASM_JUMP_FW:
586  case WS_ASM_JUMP_BW:
587  case WS_ASM_TJUMP_FW:
588  case WS_ASM_TJUMP_BW:
589  if (!ws_encode_buffer(&compiler->byte_code,
590  WS_ENC_BYTE, ins->type,
591  WS_ENC_UINT8, (WsUInt8) ins->ws_offset,
592  WS_ENC_END))
593  goto error;
594  break;
595 
596  case WS_ASM_JUMP_FW_W:
597  case WS_ASM_JUMP_BW_W:
598  case WS_ASM_TJUMP_FW_W:
599  case WS_ASM_TJUMP_BW_W:
600  if (!ws_encode_buffer(&compiler->byte_code,
601  WS_ENC_BYTE, ins->type,
602  WS_ENC_UINT16, (WsUInt16) ins->ws_offset,
603  WS_ENC_END))
604  goto error;
605  break;
606 
607  case WS_ASM_CALL_S:
608  if (!ws_encode_buffer(&compiler->byte_code,
609  WS_ENC_BYTE,
610  WS_ASM_GLUE(ins->type, ins->ws_findex),
611  WS_ENC_END))
612  goto error;
613  break;
614 
615  case WS_ASM_CALL:
616  if (!ws_encode_buffer(&compiler->byte_code,
617  WS_ENC_BYTE, (WsByte) ins->type,
618  WS_ENC_UINT8, (WsUInt8) ins->ws_findex,
619  WS_ENC_END))
620  goto error;
621  break;
622 
623  case WS_ASM_CALL_LIB_S:
624  if (!ws_encode_buffer(&compiler->byte_code,
625  WS_ENC_BYTE,
626  WS_ASM_GLUE(ins->type, ins->ws_findex),
627  WS_ENC_UINT8, (WsUInt8) ins->ws_lindex,
628  WS_ENC_END))
629  goto error;
630  break;
631 
632  case WS_ASM_CALL_LIB:
633  if (!ws_encode_buffer(&compiler->byte_code,
634  WS_ENC_BYTE, (WsByte) ins->type,
635  WS_ENC_UINT8, (WsUInt8) ins->ws_findex,
636  WS_ENC_UINT8, (WsUInt8) ins->ws_lindex,
637  WS_ENC_END))
638  goto error;
639  break;
640 
641  case WS_ASM_CALL_LIB_W:
642  if (!ws_encode_buffer(&compiler->byte_code,
643  WS_ENC_BYTE, (WsByte) ins->type,
644  WS_ENC_UINT8, (WsUInt8) ins->ws_findex,
645  WS_ENC_UINT16, (WsUInt16) ins->ws_lindex,
646  WS_ENC_END))
647  goto error;
648  break;
649 
650  case WS_ASM_CALL_URL:
651  if (!ws_encode_buffer(&compiler->byte_code,
652  WS_ENC_BYTE, (WsByte) ins->type,
653  WS_ENC_UINT8, (WsUInt8) ins->ws_lindex,
654  WS_ENC_UINT8, (WsUInt8) ins->ws_findex,
655  WS_ENC_UINT8, (WsUInt8) ins->ws_args,
656  WS_ENC_END))
657  goto error;
658  break;
659 
660  case WS_ASM_CALL_URL_W:
661  if (!ws_encode_buffer(&compiler->byte_code,
662  WS_ENC_BYTE, (WsByte) ins->type,
663  WS_ENC_UINT16, (WsUInt16) ins->ws_lindex,
664  WS_ENC_UINT16, (WsUInt16) ins->ws_findex,
665  WS_ENC_UINT8, (WsUInt8) ins->ws_args,
666  WS_ENC_END))
667  goto error;
668  break;
669 
670  case WS_ASM_LOAD_VAR_S:
671  case WS_ASM_STORE_VAR_S:
672  if (!ws_encode_buffer(&compiler->byte_code,
673  WS_ENC_BYTE,
674  WS_ASM_GLUE(ins->type, ins->ws_vindex),
675  WS_ENC_END))
676  goto error;
677  break;
678 
679  case WS_ASM_LOAD_VAR:
680  case WS_ASM_STORE_VAR:
681  if (!ws_encode_buffer(&compiler->byte_code,
682  WS_ENC_BYTE, (WsByte) ins->type,
683  WS_ENC_UINT8, (WsUInt8) ins->ws_vindex,
684  WS_ENC_END))
685  goto error;
686  break;
687 
688  case WS_ASM_INCR_VAR_S:
689  if (!ws_encode_buffer(&compiler->byte_code,
690  WS_ENC_BYTE,
691  WS_ASM_GLUE(ins->type, ins->ws_vindex),
692  WS_ENC_END))
693  goto error;
694  break;
695 
696  case WS_ASM_INCR_VAR:
697  case WS_ASM_DECR_VAR:
698  if (!ws_encode_buffer(&compiler->byte_code,
699  WS_ENC_BYTE, (WsByte) ins->type,
700  WS_ENC_UINT8, (WsUInt8) ins->ws_vindex,
701  WS_ENC_END))
702  goto error;
703  break;
704 
705  case WS_ASM_LOAD_CONST_S:
706  if (!ws_encode_buffer(&compiler->byte_code,
707  WS_ENC_BYTE,
708  WS_ASM_GLUE(ins->type, ins->ws_cindex),
709  WS_ENC_END))
710  goto error;
711  break;
712 
713  case WS_ASM_LOAD_CONST:
714  if (!ws_encode_buffer(&compiler->byte_code,
715  WS_ENC_BYTE, (WsByte) ins->type,
716  WS_ENC_UINT8, (WsUInt8) ins->ws_cindex,
717  WS_ENC_END))
718  goto error;
719  break;
720 
721  case WS_ASM_LOAD_CONST_W:
722  if (!ws_encode_buffer(&compiler->byte_code,
723  WS_ENC_BYTE, (WsByte) ins->type,
724  WS_ENC_UINT16, (WsUInt16) ins->ws_cindex,
725  WS_ENC_END))
726  goto error;
727  break;
728 
729  case WS_ASM_ADD_ASG:
730  case WS_ASM_SUB_ASG:
731  if (!ws_encode_buffer(&compiler->byte_code,
732  WS_ENC_BYTE, (WsByte) ins->type,
733  WS_ENC_UINT8, (WsUInt8) ins->ws_vindex,
734  WS_ENC_END))
735  goto error;
736  break;
737 
738  case WS_ASM_CONST_0:
739  case WS_ASM_CONST_1:
740  case WS_ASM_CONST_M1:
741  case WS_ASM_CONST_ES:
743  case WS_ASM_CONST_TRUE:
744  case WS_ASM_CONST_FALSE:
745  case WS_ASM_INCR:
746  case WS_ASM_DECR:
747  case WS_ASM_UMINUS:
748  case WS_ASM_ADD:
749  case WS_ASM_SUB:
750  case WS_ASM_MUL:
751  case WS_ASM_DIV:
752  case WS_ASM_IDIV:
753  case WS_ASM_REM:
754  case WS_ASM_B_AND:
755  case WS_ASM_B_OR:
756  case WS_ASM_B_XOR:
757  case WS_ASM_B_NOT:
758  case WS_ASM_B_LSHIFT:
759  case WS_ASM_B_RSSHIFT:
760  case WS_ASM_B_RSZSHIFT:
761  case WS_ASM_EQ:
762  case WS_ASM_LE:
763  case WS_ASM_LT:
764  case WS_ASM_GE:
765  case WS_ASM_GT:
766  case WS_ASM_NE:
767  case WS_ASM_NOT:
768  case WS_ASM_SCAND:
769  case WS_ASM_SCOR:
770  case WS_ASM_TOBOOL:
771  case WS_ASM_POP:
772  case WS_ASM_TYPEOF:
773  case WS_ASM_ISVALID:
774  case WS_ASM_RETURN:
775  case WS_ASM_RETURN_ES:
776  case WS_ASM_DEBUG:
777  if (!ws_encode_buffer(&compiler->byte_code,
778  WS_ENC_BYTE, (WsByte) ins->type,
779  WS_ENC_END))
780  goto error;
781  break;
782 
783  default:
784  ws_fatal("ws_asm_linearize(): unknown instruction 0x%02x",
785  ins->type);
786  break;
787  }
788  }
789 
790  /*
791  * Avoid generating 0-length functions, because not all clients
792  * handle them correctly.
793  */
794  if (ws_buffer_len(&compiler->byte_code) == 0) {
795  if (!ws_encode_buffer(&compiler->byte_code,
797  WS_ENC_END))
798  goto error;
799  }
800 
801  return;
802 
803  /*
804  * Error handling.
805  */
806 
807 error:
808 
809  ws_error_memory(compiler);
810  return;
811 }
812 
813 
814 /* Contructors for assembler instructions. */
815 
817 {
818  WsAsmIns *ins = ws_f_calloc(compiler->pool_asm, 1, sizeof(*ins));
819 
820  if (ins == NULL)
821  ws_error_memory(compiler);
822  else {
823  ins->type = type;
824  ins->line = line;
825  }
826 
827  return ins;
828 }
829 
830 
832 {
833  WsAsmIns *ins = asm_alloc(compiler, WS_ASM_P_LABEL, line);
834 
835  if (ins)
836  ins->ws_label_idx = compiler->next_label++;
837 
838  return ins;
839 }
840 
841 
843  WsAsmIns *label)
844 {
845  WsAsmIns *ins = asm_alloc(compiler, inst, line);
846 
847  if (ins) {
848  ins->ws_label = label;
849  label->ws_label_refcount++;
850  }
851 
852  return ins;
853 }
854 
855 
856 WsAsmIns *ws_asm_call(WsCompiler *compiler, WsUInt32 line, WsUInt8 findex)
857 {
858  WsAsmIns *ins = asm_alloc(compiler, WS_ASM_P_CALL, line);
859 
860  if (ins)
861  ins->ws_findex = findex;
862 
863  return ins;
864 }
865 
866 
868  WsUInt16 lindex)
869 {
870  WsAsmIns *ins = asm_alloc(compiler, WS_ASM_P_CALL_LIB, line);
871 
872  if (ins) {
873  ins->ws_findex = findex;
874  ins->ws_lindex = lindex;
875  }
876 
877  return ins;
878 }
879 
880 
882  WsUInt16 urlindex, WsUInt8 args)
883 {
884  WsAsmIns *ins = asm_alloc(compiler, WS_ASM_P_CALL_URL, line);
885 
886  if (ins) {
887  ins->ws_findex = findex;
888  ins->ws_lindex = urlindex;
889  ins->ws_args = args;
890  }
891 
892  return ins;
893 }
894 
895 
897  WsUInt8 vindex)
898 {
899  WsAsmIns *ins = asm_alloc(compiler, inst, line);
900 
901  if (ins)
902  ins->ws_vindex = vindex;
903 
904  return ins;
905 }
906 
907 
909  WsUInt16 cindex)
910 {
911  WsAsmIns *ins = asm_alloc(compiler, WS_ASM_P_LOAD_CONST, line);
912 
913  if (ins)
914  ins->ws_cindex = cindex;
915 
916  return ins;
917 }
918 
919 
921 {
922  return asm_alloc(compiler, opcode, line);
923 }
void ws_asm_link(WsCompiler *compiler, WsAsmIns *ins)
Definition: wsasm.c:93
void error(int err, const char *fmt,...)
Definition: log.c:612
void ws_fatal(char *fmt,...)
Definition: wserror.c:91
#define WS_ASM_JUMP_FW_S
Definition: wsasm.h:130
#define WS_ASM_CONST_TRUE
Definition: wsasm.h:175
int size
Definition: wsasm.c:84
#define WS_ASM_SCOR
Definition: wsasm.h:207
#define WS_ASM_B_RSSHIFT
Definition: wsasm.h:195
#define WS_ASM_P_CALL_LIB
Definition: wsasm.h:229
#define WS_GET_UINT16(buf, var)
Definition: wsencode.h:107
#define WS_ASM_JUMP_FW_W
Definition: wsasm.h:132
Definition: wsint.h:131
#define WS_ASM_P_LABEL
Definition: wsasm.h:225
WsAsmIns * ws_asm_call_lib(WsCompiler *compiler, WsUInt32 line, WsUInt8 findex, WsUInt16 lindex)
Definition: wsasm.c:867
WsAsmIns * ws_asm_branch(WsCompiler *compiler, WsUInt32 line, WsUInt16 inst, WsAsmIns *label)
Definition: wsasm.c:842
#define WS_ASM_GLUE(op, arg)
Definition: wsasm.h:125
#define WS_ASM_LOAD_CONST
Definition: wsasm.h:167
unsigned long WsUInt32
Definition: wsint.h:122
char * name
Definition: wsasm.c:83
#define WS_ASM_ADD_ASG
Definition: wsasm.h:180
WsAsmIns * ws_asm_label(WsCompiler *compiler, WsUInt32 line)
Definition: wsasm.c:831
#define WS_ASM_TYPEOF
Definition: wsasm.h:212
static WsAsmIns * asm_alloc(WsCompiler *compiler, WsUInt16 type, WsUInt32 line)
Definition: wsasm.c:816
int code
Definition: smsc_cimd2.c:346
int type
Definition: smsc_cimd2.c:215
#define WS_ASM_NOT
Definition: wsasm.h:205
#define WS_ASM_CALL_LIB
Definition: wsasm.h:149
WsAsmIns * ws_asm_call_url(WsCompiler *compiler, WsUInt32 line, WsUInt16 findex, WsUInt16 urlindex, WsUInt8 args)
Definition: wsasm.c:881
#define WS_ASM_JUMP_BW
Definition: wsasm.h:135
WsUInt32 offset
Definition: wsasm.h:263
#define WS_ASM_RETURN
Definition: wsasm.h:215
size_t ws_buffer_len(WsBuffer *buffer)
Definition: wsbuffer.c:139
#define WS_GET_UINT8(buf, var)
Definition: wsencode.h:101
WsAsmIns * asm_head
Definition: wsint.h:224
WsAsmIns * asm_tail
Definition: wsint.h:225
static struct @112 operands[256]
#define WS_ASM_CONST_INVALID
Definition: wsasm.h:174
#define WS_ASM_P_CALL_URL
Definition: wsasm.h:230
#define WS_ASM_ARG(op)
Definition: wsasm.h:114
#define WS_ASM_DIV
Definition: wsasm.h:186
#define WS_ASM_CALL_URL
Definition: wsasm.h:152
#define WS_ASM_CONST_M1
Definition: wsasm.h:172
#define WS_ASM_CONST_FALSE
Definition: wsasm.h:176
#define WS_ASM_P_JUMP
Definition: wsasm.h:226
WsAsmIns * ws_asm_load_const(WsCompiler *compiler, WsUInt32 line, WsUInt16 cindex)
Definition: wsasm.c:908
unsigned char WsUInt8
Definition: wsint.h:116
#define WS_ASM_B_LSHIFT
Definition: wsasm.h:194
#define WS_ASM_JUMP_BW_W
Definition: wsasm.h:136
#define WS_OPNAME(op)
Definition: wsasm.c:76
#define WS_ASM_ISVALID
Definition: wsasm.h:213
#define WS_ASM_TJUMP_BW_W
Definition: wsasm.h:143
#define WS_ASM_P_TJUMP
Definition: wsasm.h:227
WsUInt16 type
Definition: wsasm.h:257
#define WS_ASM_B_NOT
Definition: wsasm.h:193
WsAsmIns * ws_asm_call(WsCompiler *compiler, WsUInt32 line, WsUInt8 findex)
Definition: wsasm.c:856
void ws_fprintf(WsIOProc io, void *context, const char *fmt,...)
Definition: wserror.c:190
#define WS_ASM_LE
Definition: wsasm.h:199
#define WS_ASM_REM
Definition: wsasm.h:188
unsigned short WsUInt16
Definition: wsint.h:119
#define WS_ASM_CALL
Definition: wsasm.h:146
#define WS_ASM_JUMP_BW_S
Definition: wsasm.h:134
struct WsAsmInsRec * next
Definition: wsasm.h:255
#define WS_ASM_DECR
Definition: wsasm.h:179
#define WS_ASM_INCR_VAR_S
Definition: wsasm.h:161
void ws_asm_dasm(WsCompilerPtr compiler, const unsigned char *code, size_t len)
Definition: wsasm.c:185
#define WS_OPSIZE(op)
Definition: wsasm.c:77
#define WS_ASM_LOAD_VAR
Definition: wsasm.h:156
#define WS_ASM_GT
Definition: wsasm.h:202
#define WS_ASM_P_LOAD_VAR
Definition: wsasm.h:231
#define WS_ASM_NE
Definition: wsasm.h:203
#define WS_ASM_LOAD_CONST_W
Definition: wsasm.h:168
WsAsmIns * ws_asm_variable(WsCompiler *compiler, WsUInt32 line, WsUInt16 inst, WsUInt8 vindex)
Definition: wsasm.c:896
gw_assert(wtls_machine->packet_to_send!=NULL)
#define WS_ASM_CALL_LIB_S
Definition: wsasm.h:148
WsBool ws_encode_buffer(WsBuffer *buffer,...)
Definition: wsencode.c:123
WsAsmIns * ws_asm_ins(WsCompiler *compiler, WsUInt32 line, WsUInt8 opcode)
Definition: wsasm.c:920
WsUInt32 next_label
Definition: wsint.h:221
#define WS_ASM_LOAD_VAR_S
Definition: wsasm.h:155
#define WS_ASM_TOBOOL
Definition: wsasm.h:208
#define WS_ASM_B_OR
Definition: wsasm.h:191
#define WS_ASM_POP
Definition: wsasm.h:210
#define WS_ASM_TJUMP_BW
Definition: wsasm.h:142
struct WsAsmInsRec * prev
Definition: wsasm.h:256
#define WS_ASM_TJUMP_FW_S
Definition: wsasm.h:138
#define WS_ASM_B_XOR
Definition: wsasm.h:192
WsUInt32 line
Definition: wsasm.h:260
WsBool
Definition: wsint.h:128
#define WS_ASM_CONST_1
Definition: wsasm.h:171
void ws_asm_linearize(WsCompiler *compiler)
Definition: wsasm.c:341
#define WS_ASM_EQ
Definition: wsasm.h:198
#define WS_ASM_STORE_VAR
Definition: wsasm.h:159
WsFunction * functions
Definition: wsint.h:238
#define WS_ASM_DECR_VAR
Definition: wsasm.h:164
#define WS_ASM_P_STORE_VAR
Definition: wsasm.h:232
#define WS_ASM_CALL_URL_W
Definition: wsasm.h:153
#define WS_ASM_CALL_LIB_W
Definition: wsasm.h:150
void * ws_f_calloc(WsFastMalloc *pool, size_t num, size_t size)
Definition: wsfalloc.c:150
#define WS_ASM_TJUMP_FW
Definition: wsasm.h:139
void ws_asm_print(WsCompiler *compiler)
Definition: wsasm.c:105
#define WS_ASM_INCR
Definition: wsasm.h:178
#define WS_ASM_INCR_VAR
Definition: wsasm.h:162
#define WS_ASM_STORE_VAR_S
Definition: wsasm.h:158
#define WS_ASM_B_RSZSHIFT
Definition: wsasm.h:196
#define WS_ASM_P_LOAD_CONST
Definition: wsasm.h:234
WsBool ws_stdlib_function_name(WsUInt16 lindex, WsUInt8 findex, const char **library_return, const char **function_return)
Definition: wsstdlib.c:375
#define WS_ASM_SUB_ASG
Definition: wsasm.h:181
#define WS_ASM_DEBUG
Definition: wsasm.h:218
#define WS_ASM_TJUMP_FW_W
Definition: wsasm.h:140
#define WS_ASM_UMINUS
Definition: wsasm.h:182
#define WS_ASM_LOAD_CONST_S
Definition: wsasm.h:166
#define WS_ASM_GE
Definition: wsasm.h:201
#define WS_ASM_P_INCR_VAR
Definition: wsasm.h:233
#define WS_ASM_CALL_S
Definition: wsasm.h:145
unsigned char WsByte
Definition: wsint.h:113
#define WS_ASM_B_AND
Definition: wsasm.h:190
#define WS_ASM_IDIV
Definition: wsasm.h:187
#define WS_ASM_JUMP_FW
Definition: wsasm.h:131
#define WS_ASM_CONST_0
Definition: wsasm.h:170
#define WS_ASM_MUL
Definition: wsasm.h:185
#define WS_ASM_ADD
Definition: wsasm.h:183
char * name
Definition: wsstree.h:199
void ws_error_memory(WsCompilerPtr compiler)
Definition: wserror.c:107
#define WS_STDOUT
Definition: wserror.h:113
#define WS_ASM_CONST_ES
Definition: wsasm.h:173
#define WS_ASM_OP(op)
Definition: wsasm.h:102
WsBuffer byte_code
Definition: wsint.h:229
#define WS_ASM_P_CALL
Definition: wsasm.h:228
WsFastMalloc * pool_asm
Definition: wsint.h:207
int opcode
Definition: test_cimd2.c:769
#define WS_ASM_RETURN_ES
Definition: wsasm.h:216
#define WS_ASM_SCAND
Definition: wsasm.h:206
#define WS_ASM_LT
Definition: wsasm.h:200
#define WS_ASM_SUB
Definition: wsasm.h:184
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.