wsopt.c
上传用户:gzpyjq
上传日期:2013-01-31
资源大小:1852k
文件大小:9k
源码类别:

手机WAP编程

开发平台:

WINDOWS

  1. /*
  2.  *
  3.  * wsopt.c
  4.  *
  5.  * Author: Markku Rossi <mtr@iki.fi>
  6.  *
  7.  * Copyright (c) 1999-2000 WAPIT OY LTD.
  8.  *  All rights reserved.
  9.  *
  10.  * Optimizations for the WMLScript symbolic assembler.
  11.  *
  12.  */
  13. #include "wsint.h"
  14. #include "wsasm.h"
  15. /* TODO: liveness analyzation */
  16. /* TODO: jumps to return or return_es */
  17. /* TODO: remove empty labels (helps peephole opt) */
  18. /* TODO: i++; becomes "load, incr, pop", optimize to just incr. */
  19. /* TODO: { const; tjump } -> { jump or nothing } */
  20. /********************* Optimization functions ***************************/
  21. static WsBool opt_jumps_to_jumps(WsCompilerPtr compiler)
  22. {
  23.     WsAsmIns *i;
  24.     WsBool change = WS_TRUE;
  25.     unsigned int count = 0;
  26.     ws_info(compiler, "optimize: jumps to jumps");
  27.     while (change) {
  28.         count++;
  29.         change = WS_FALSE;
  30.         for (i = compiler->asm_head; i; i = i->next) {
  31.             WsAsmIns * j;
  32.             if (!WS_ASM_P_BRANCH(i))
  33.                 continue;
  34.             /* Find the next instruction following the label. */
  35.             for (j = i->ws_label; j && j->type == WS_ASM_P_LABEL; j = j->next)
  36.                 ;
  37.             if (j == NULL || j->type != WS_ASM_P_JUMP)
  38.                 /* Can't optimize this case. */
  39.                 continue;
  40.             /* We can optimize the jump `i' directly to the label of
  41.                       `j'.  We must remember to update the reference counts
  42.                       too. */
  43.             i->ws_label->ws_label_refcount--;
  44.             j->ws_label->ws_label_refcount++;
  45.             i->ws_label = j->ws_label;
  46.             change = WS_TRUE;
  47.         }
  48.     }
  49.     return count > 1;
  50. }
  51. static WsBool opt_jumps_to_next_instruction(WsCompilerPtr compiler)
  52. {
  53.     WsAsmIns *i;
  54.     WsBool change = WS_FALSE;
  55.     ws_info(compiler, "optimize: jumps to next instruction");
  56.     for (i = compiler->asm_head; i; i = i->next) {
  57.         WsAsmIns * j;
  58.         if (i->type != WS_ASM_P_JUMP)
  59.             continue;
  60.         for (j = i->next;
  61.              j && j->type == WS_ASM_P_LABEL && i->ws_label != j;
  62.              j = j->next)
  63.             ;
  64.         if (i->ws_label != j)
  65.             /* Nop. */
  66.             continue;
  67.         /* Remove the jump instruction `i'. */
  68.         change = WS_TRUE;
  69.         i->ws_label->ws_label_refcount--;
  70.         if (i->next)
  71.             i->next->prev = i->prev;
  72.         else
  73.             compiler->asm_tail = i->prev;
  74.         if (i->prev)
  75.             i->prev->next = i->next;
  76.         else
  77.             compiler->asm_head = i->next;
  78.         /* Continue from the label `j'. */
  79.         i = j;
  80.     }
  81.     return change;
  82. }
  83. static WsBool opt_dead_code(WsCompilerPtr compiler)
  84. {
  85.     WsBool change = WS_FALSE;
  86.     WsAsmIns *i;
  87.     ws_info(compiler, "optimize: dead code");
  88.     for (i = compiler->asm_head; i; i = i->next) {
  89.         WsAsmIns * j;
  90.         if (!(i->type == WS_ASM_P_JUMP ||
  91.               i->type == WS_ASM_RETURN ||
  92.               i->type == WS_ASM_RETURN_ES))
  93.             continue;
  94.         /* Skip until the next referenced label is found. */
  95.         for (j = i->next;
  96.              j && (j->type != WS_ASM_P_LABEL || j->ws_label_refcount == 0);
  97.              j = j->next) {
  98.             /* Update label reference counts in the deleted block. */
  99.             if (WS_ASM_P_BRANCH(j))
  100.                 j->ws_label->ws_label_refcount--;
  101.         }
  102.         if (j == i->next)
  103.             /* Nothing to delete. */
  104.             continue;
  105.         /* Delete everything between `i' and `j'. */
  106.         i->next = j;
  107.         if (j)
  108.             j->prev = i;
  109.         else
  110.             compiler->asm_tail = i;
  111.         change = WS_TRUE;
  112.     }
  113.     return change;
  114. }
  115. static WsBool opt_peephole(WsCompilerPtr compiler)
  116. {
  117.     WsBool change = WS_FALSE;
  118.     WsAsmIns *i, *i2, *prev;
  119.     WsAsmIns *new;
  120.     ws_info(compiler, "optimize: peephole");
  121.     prev = NULL;
  122.     i = compiler->asm_head;
  123.     while (i) {
  124.         /* Two instructions wide peephole. */
  125.         if (i->next) {
  126.             i2 = i->next;
  127.             /*
  128.              * {load*,const*} => -
  129.              * pop
  130.              */
  131.             if (i2->type == WS_ASM_POP
  132.                 && (i->type == WS_ASM_P_LOAD_VAR
  133.                     || i->type == WS_ASM_P_LOAD_CONST
  134.                     || i->type == WS_ASM_CONST_0
  135.                     || i->type == WS_ASM_CONST_1
  136.                     || i->type == WS_ASM_CONST_M1
  137.                     || i->type == WS_ASM_CONST_ES
  138.                     || i->type == WS_ASM_CONST_INVALID
  139.                     || i->type == WS_ASM_CONST_TRUE
  140.                     || i->type == WS_ASM_CONST_FALSE)) {
  141.                 /* Remove both instructions. */
  142.                 change = WS_TRUE;
  143.                 if (prev)
  144.                     prev->next = i2->next;
  145.                 else
  146.                     compiler->asm_head = i2->next;
  147.                 if (i2->next)
  148.                     i2->next->prev = prev;
  149.                 else
  150.                     compiler->asm_tail = prev;
  151.                 i = i2->next;
  152.                 continue;
  153.             }
  154.             /*
  155.              * const_es           =>      return_es
  156.              * return
  157.              */
  158.             if (i2->type == WS_ASM_RETURN && i->type == WS_ASM_CONST_ES) {
  159.                 /* Replace with WS_ASM_RETURN_ES */
  160.                 new = ws_asm_ins(compiler, i->line, WS_ASM_RETURN_ES);
  161.                 if (new) {
  162.                     change = WS_TRUE;
  163.                     if (prev)
  164.                         prev->next = new;
  165.                     else
  166.                         compiler->asm_head = new;
  167.                     new->prev = prev;
  168.                     new->next = i2->next;
  169.                     if (new->next)
  170.                         new->next->prev = new;
  171.                     else
  172.                         compiler->asm_tail = new;
  173.                     i = new;
  174.                     continue;
  175.                 }
  176.             }
  177.         }
  178.         /* Move forward. */
  179.         prev = i;
  180.         i = i->next;
  181.     }
  182.     /* The interpreter will by default return the empty string if a
  183.      * function ends without a return statement, so returning the
  184.      * empty string at the end of a function is never useful. */
  185.     if (compiler->asm_tail && compiler->asm_tail->type == WS_ASM_RETURN_ES) {
  186.         compiler->asm_tail = compiler->asm_tail->prev;
  187.         if (compiler->asm_tail == NULL)
  188.             compiler->asm_head = NULL;
  189.         else
  190.             compiler->asm_tail->next = NULL;
  191.     }
  192.     return change;
  193. }
  194. /*
  195.  * Remove conversions that are followed by an opcode that does
  196.  * that conversion automatically anyway.
  197.  */
  198. static WsBool opt_conv(WsCompilerPtr compiler)
  199. {
  200.     WsBool change = WS_FALSE;
  201.     WsAsmIns *i, *next, *prev;
  202.     ws_info(compiler, "optimize: peephole");
  203.     prev = NULL;
  204.     i = compiler->asm_head;
  205.     while (i) {
  206.         if (i->type == WS_ASM_TOBOOL) {
  207.     next = i->next;
  208.             /* Skip labels.  They're not going to affect which instruction
  209.              * gets executed after this TOBOOL. */
  210.        while (next != NULL && next->type == WS_ASM_P_LABEL)
  211.         next = next->next;
  212.         if (next != NULL &&
  213.                 (next->type == WS_ASM_P_TJUMP ||
  214.                  next->type == WS_ASM_NOT ||
  215.          next->type == WS_ASM_SCAND ||
  216.          next->type == WS_ASM_SCOR ||
  217.          next->type == WS_ASM_TOBOOL ||
  218.          next->type == WS_ASM_POP)) {
  219.         /* The next instruction will automatically convert its
  220.          * operand to boolean, or does not care about its operand
  221.          * (POP), so the TOBOOL is not necessary.  Delete it.  */
  222.         change = WS_TRUE;
  223.         /* Use i->next here because next might have been incremented
  224.          * past a label, which we do not want to delete. */
  225.         if (prev)
  226.          prev->next = i->next;
  227.         else
  228.          compiler->asm_head = i->next;
  229.         if (i->next)
  230.                     i->next->prev = prev;
  231.                 else
  232.                     compiler->asm_tail = prev;
  233.     }
  234.         }
  235. prev = i;
  236. i = i->next;
  237.     }
  238.     return change;
  239. }
  240. /********************* Global entry point *******************************/
  241. void ws_asm_optimize(WsCompilerPtr compiler)
  242. {
  243.     WsBool change = WS_TRUE;
  244.     /* While we manage to change the assembler, perform the requested
  245.        optimizations. */
  246.     while (change) {
  247.         change = WS_FALSE;
  248. /* Useless conversions */
  249. if (!compiler->params.no_opt_conv && opt_conv(compiler))
  250.     change = WS_TRUE;
  251.         /* Peephole. */
  252.         if (!compiler->params.no_opt_peephole && opt_peephole(compiler))
  253.             change = WS_TRUE;
  254.         /* Jumps to jump instructions. */
  255.         if (!compiler->params.no_opt_jumps_to_jumps
  256.             && opt_jumps_to_jumps(compiler))
  257.             change = WS_TRUE;
  258.         /* Jumps to the next instruction. */
  259.         if (!compiler->params.no_opt_jumps_to_next_instruction
  260.             && opt_jumps_to_next_instruction(compiler))
  261.             change = WS_TRUE;
  262.         /* Unreachable code. */
  263.         if (!compiler->params.no_opt_dead_code && opt_dead_code(compiler))
  264.             change = WS_TRUE;
  265.     }
  266. }