rewrite.inc 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. static stock
  2. YSI_g_sNextJumpPoint;
  3. stock LAM@1()
  4. {
  5. //printf("LAM@1");
  6. static
  7. addrLAM@1 = 0;
  8. if (!addrLAM@1)
  9. {
  10. #emit CONST.pri LAM@1
  11. #emit STOR.pri addrLAM@1
  12. addrLAM@1 += AMX_REAL_DATA + AMX_HEADER_COD;
  13. P:5("LAM@1: LAM@1 addresses = %d %d %d %d", GetAmxBaseAddress(), addrLAM@1 - (AMX_REAL_DATA + AMX_HEADER_COD), AMX_REAL_DATA + AMX_HEADER_COD, addrLAM@1);
  14. //printf("LAM@0: LAM@1 addresses = %d %d %d %d", GetAmxBaseAddress(), addrLAM@1 - (AMX_REAL_DATA + AMX_HEADER_COD), AMX_REAL_DATA + AMX_HEADER_COD, addrLAM@1);
  15. }
  16. // Rewrite our call code to jump to "YSI_g_sNextJumpPoint". Then adjust
  17. // that to our return point, and jump to the new code.
  18. new
  19. addrRet = GetCurrentFrameReturn(),
  20. addrNext = YSI_g_sNextJumpPoint;
  21. SetCurrentFrameReturn(addrNext);
  22. YSI_g_sNextJumpPoint = addrRet,
  23. addrRet -= 16;
  24. {
  25. new
  26. dis[DisasmContext];
  27. DisasmInit(dis, addrRet);
  28. if (DisasmNextInsn(dis) != OP_PUSH_C || DisasmGetOperand(dis) != 0 ||
  29. DisasmNextInsn(dis) != OP_CALL || DisasmGetOperand(dis) != addrLAM@1)
  30. {
  31. P:E("Unknown call of LAM@1");
  32. return 0;
  33. }
  34. }
  35. {
  36. new
  37. ctx[AsmContext];
  38. AsmInitPtr(ctx, addrRet + AMX_HEADER_COD, 16);
  39. // Replace with a jump to a point after "@LAM@1".
  40. @emit JUMP (addrNext + AMX_REAL_DATA + AMX_HEADER_COD)
  41. // Code to POP the result.
  42. @emit NOP
  43. @emit NOP
  44. }
  45. return 1;
  46. }
  47. stock LAM@2(par)
  48. {
  49. //printf("LAM@2");
  50. #pragma unused par
  51. static
  52. addrLAM@2 = 0;
  53. if (!addrLAM@2)
  54. {
  55. #emit CONST.pri LAM@2
  56. #emit STOR.pri addrLAM@2
  57. addrLAM@2 += AMX_REAL_DATA + AMX_HEADER_COD;
  58. P:5("LAM@2: LAM@2 addresses = %d %d %d %d", GetAmxBaseAddress(), addrLAM@2 - (AMX_REAL_DATA + AMX_HEADER_COD), AMX_REAL_DATA + AMX_HEADER_COD, addrLAM@2);
  59. //printf("LAM@0: LAM@1 addresses = %d %d %d %d", GetAmxBaseAddress(), addrLAM@2 - (AMX_REAL_DATA + AMX_HEADER_COD), AMX_REAL_DATA + AMX_HEADER_COD, addrLAM@2);
  60. }
  61. // Rewrite our call code to jump to "YSI_g_sNextJumpPoint". Then adjust
  62. // that to our return point, and jump to the new code.
  63. new
  64. addrRet = GetCurrentFrameReturn(),
  65. addrNext = YSI_g_sNextJumpPoint;
  66. SetCurrentFrameReturn(addrNext);
  67. YSI_g_sNextJumpPoint = addrRet,
  68. addrRet -= 16;
  69. {
  70. new
  71. dis[DisasmContext];
  72. DisasmInit(dis, addrRet);
  73. if (DisasmNextInsn(dis) != OP_PUSH_C || DisasmGetOperand(dis) != 4 ||
  74. DisasmNextInsn(dis) != OP_CALL || DisasmGetOperand(dis) != addrLAM@2)
  75. {
  76. P:E("Unknown call of LAM@2");
  77. return 0;
  78. }
  79. }
  80. {
  81. new
  82. ctx[AsmContext];
  83. AsmInitPtr(ctx, addrRet + AMX_HEADER_COD, 16);
  84. // Replace with a jump to a point after "LAM@0".
  85. @emit JUMP (addrNext - 4 + AMX_REAL_DATA + AMX_HEADER_COD)
  86. // Code to POP the result.
  87. @emit NOP
  88. @emit NOP
  89. }
  90. return par;
  91. }
  92. stock LAM@0()
  93. {
  94. static
  95. addrLAM@0 = 0,
  96. addrLAM@1 = 0;
  97. if (!addrLAM@1)
  98. {
  99. #emit CONST.pri LAM@0
  100. #emit STOR.pri addrLAM@0
  101. addrLAM@0 += AMX_REAL_DATA + AMX_HEADER_COD;
  102. P:5("LAM@0: LAM@0 addresses = %d %d %d %d", GetAmxBaseAddress(), addrLAM@0 - (AMX_REAL_DATA + AMX_HEADER_COD), AMX_REAL_DATA + AMX_HEADER_COD, addrLAM@0);
  103. //printf("LAM@0: LAM@0 addresses = %d %d %d %d", GetAmxBaseAddress(), addrLAM@0 - (AMX_REAL_DATA + AMX_HEADER_COD), AMX_REAL_DATA + AMX_HEADER_COD, addrLAM@0);
  104. #emit CONST.pri LAM@1
  105. #emit STOR.pri addrLAM@1
  106. addrLAM@1 += AMX_REAL_DATA + AMX_HEADER_COD;
  107. P:5("LAM@0: LAM@1 addresses = %d %d %d %d", GetAmxBaseAddress(), addrLAM@1 - (AMX_REAL_DATA + AMX_HEADER_COD), AMX_REAL_DATA + AMX_HEADER_COD, addrLAM@1);
  108. //printf("LAM@0: LAM@1 addresses = %d %d %d %d", GetAmxBaseAddress(), addrLAM@1 - (AMX_REAL_DATA + AMX_HEADER_COD), AMX_REAL_DATA + AMX_HEADER_COD, addrLAM@1);
  109. }
  110. // Get the return address.
  111. new
  112. addrRet = GetCurrentFrameReturn(),
  113. addrNext;
  114. YSI_g_sNextJumpPoint = addrRet,
  115. addrRet -= 16,
  116. SetCurrentFrameReturn(addrRet);
  117. {
  118. new
  119. dis[DisasmContext];
  120. // Move on until we find the next call to "@LAM@1".
  121. DisasmInit(dis, YSI_g_sNextJumpPoint);
  122. new
  123. Opcode:nxt = DisasmNextInsn(dis),
  124. i = 0;
  125. while (i != 100)
  126. {
  127. if (nxt == OP_PUSH_C && DisasmGetOperand(dis) == 0)
  128. {
  129. nxt = DisasmNextInsn(dis);
  130. if (nxt == OP_CALL && DisasmGetOperand(dis) == addrLAM@1)
  131. {
  132. P:6("LAM@0: Found %d", DisasmGetOperand(dis));
  133. break;
  134. }
  135. }
  136. else nxt = DisasmNextInsn(dis);
  137. ++i;
  138. }
  139. if (i == 10)
  140. {
  141. P:E("Unable to find LAM@1");
  142. return 0;
  143. }
  144. addrNext = DisasmGetNextIp(dis) + AMX_REAL_DATA; // - AMX_HEADER_COD; //(AMX_REAL_DATA + AMX_HEADER_COD);
  145. // Go backwards to before this function was called.
  146. DisasmInit(dis, addrRet);
  147. if (DisasmNextInsn(dis) != OP_PUSH_C || DisasmGetOperand(dis) != 0 ||
  148. DisasmNextInsn(dis) != OP_CALL || DisasmGetOperand(dis) != addrLAM@0)
  149. {
  150. P:E("Unknown call of LAM@0");
  151. return 0;
  152. }
  153. }
  154. {
  155. new
  156. ctx[AsmContext];
  157. AsmInitPtr(ctx, addrRet + AMX_HEADER_COD, 16);
  158. // Replace with a jump to a point after "@LAM@1".
  159. @emit JUMP addrNext
  160. // Code to POP the result.
  161. @emit NOP
  162. @emit POP.pri
  163. }
  164. return 1;
  165. }
  166. /*
  167. - The original code is:
  168. myVar = FoldR({ _0 + _1 }, arr, 0);
  169. - The compiled code generated is:
  170. myVar = @LAM0();
  171. @LAM1();
  172. inline Func(_0, _1) YSI_gInlineRet += _0 + _1;
  173. @LAM2(FoldR("Func", arr, 0));
  174. - The rewritten code is:
  175. goto Func:
  176. :Write
  177. myVar = I@;
  178. goto Cont;
  179. :Func
  180. // Inline code.
  181. I@ = FoldR("Func", arr, 0);
  182. goto Write;
  183. :Cont
  184. */