zhangsongcui

JIT

Aug 4th, 2012
208
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.15 KB | None | 0 0
  1. #include <iostream>
  2. #include <string>
  3. #include <cassert>
  4. #include <algorithm>
  5. #include "xbyak/xbyak.h"
  6.  
  7. class JIT: public Xbyak::CodeGenerator {
  8. public:
  9.     template <typename Iter>
  10.     JIT(const Iter beg, const Iter end): Xbyak::CodeGenerator() {
  11.         // int (int a, int b, int c, int d)
  12. #ifndef XBYAK64
  13.         push(edi);
  14.         push(esi);
  15.         mov(ecx, ptr[esp + 0x0C]);
  16.         mov(edx, ptr[esp + 0x10]);
  17.         mov(edi, ptr[esp + 0x14]);
  18.         mov(esi, ptr[esp + 0x18]);
  19. #endif
  20.         int params[4] = {};
  21.         char Op = '\0';
  22.         int constNum = 0;
  23.         for (Iter it = beg; it != end; ++it) {
  24.             if (*it >= 'a' && *it <= 'd') {
  25.                 switch (Op) {
  26.                 case '\0':
  27.                 case '+':
  28.                     ++params[*it - 'a'];
  29.                     break;
  30.                 case '-':
  31.                     --params[*it - 'a'];
  32.                     break;
  33.                 default:
  34.                     assert(false);
  35.                 }
  36.             } else if (*it == '+' || *it == '-') {
  37.                 Op = *it;
  38.             } else if (*it >= '0' && *it <= '9') {
  39.                 int t = parseInt(it, end);
  40.                 --it;
  41.                 constNum += Op == '-' ? -t : t;
  42.             } else if (*it == ' ') {
  43.                 continue;
  44.             } else {
  45.                 throw std::invalid_argument("stynax error");
  46.             }
  47.         }
  48.        
  49. #ifndef XBYAK64
  50.         const static Xbyak::Reg32 regs[] = { ecx, edx, edi, esi };
  51.         const static Xbyak::Reg32 res_reg = eax;
  52. #else
  53.         const static Xbyak::Reg64 regs[] = { rcx, rdx, r8, r9 };
  54.         const static Xbyak::Reg64 res_reg = rax;
  55. #endif
  56.         bool resInitialized = false;
  57.  
  58.         for (int i = 0; i < 4; ++i) {
  59.             switch (params[i]) {
  60.             case 0:
  61.                 break;
  62.             case 1:
  63.                 if (resInitialized) {
  64.                     add(res_reg, regs[i]); // r += X
  65.                 } else {
  66.                     resInitialized = true;
  67.                     mov(res_reg, regs[i]); // r = X
  68.                 }
  69.                 break;
  70.             case -1:
  71.                 if (resInitialized) {
  72.                     sub(res_reg, regs[i]); // r -= X
  73.                 } else {
  74.                     resInitialized = true;
  75.                     neg(regs[i]);      // X = -X
  76.                     mov(res_reg, regs[i]); // r = X
  77.                 }
  78.                 break;
  79.             case 2:
  80.                 if (resInitialized)
  81.                     lea(res_reg, ptr[res_reg + regs[i] * 2]); // r = r + X * 2
  82.                 else {
  83.                     resInitialized = true;
  84.                     lea(res_reg, ptr[regs[i] + regs[i]]); // r = X + X
  85.                 }
  86.                 break;
  87.             case 3:
  88.             case 5:
  89.             case 9:
  90.                 if (resInitialized) {
  91.                     lea(regs[i], ptr[regs[i] + regs[i] * (params[i] - 1)]); // X = X + X * (N - 1)
  92.                     add(res_reg, regs[i]); // r += X
  93.                 } else {
  94.                     resInitialized = true;
  95.                     lea(res_reg, ptr[regs[i] + regs[i] * (params[i] - 1)]); // r = X + X * (N - 1)
  96.                 }
  97.                 break;
  98.             case -2:
  99.             case -3:
  100.             case -5:
  101.             case -9:
  102.                 if (resInitialized) {
  103.                     lea(regs[i], ptr[regs[i] + regs[i] * (-params[i] - 1)]); // X = X + X * (abs(N) - 1)
  104.                     sub(res_reg, regs[i]); // r = X
  105.                 } else {
  106.                     resInitialized = true;
  107.                     lea(res_reg, ptr[regs[i] + regs[i] * (-params[i] - 1)]); // r = X + X * (abs(N) - 1)
  108.                     neg(res_reg); // r = -r
  109.                 }
  110.                 break;
  111.             case 4:
  112.             case -4:
  113.             case 8:
  114.             case -8:
  115.                 if (resInitialized && params[i] > 0) {
  116.                     lea(res_reg, ptr[res_reg + regs[i] * params[i]]); // r = r + X * N
  117.                 } else {
  118.                     shl(regs[i], abs(params[i]) == 4 ? 2 : 3); // X <<= log2(abs(N))
  119.                     if (params[i] > 0) {
  120.                         resInitialized = true;
  121.                         mov(res_reg, regs[i]); // r = X
  122.                     } else { // params[i] < 0
  123.                         if (resInitialized) {
  124.                             sub(res_reg, regs[i]); // r -= X
  125.                         } else {
  126.                             resInitialized = true;
  127.                             neg(regs[i]); // X = -X
  128.                             mov(res_reg, regs[i]); // r = X
  129.                         }
  130.                     }
  131.                 }
  132.                 break;
  133.             default:
  134.                 if (resInitialized) {
  135.                     imul(regs[i], regs[i], params[i]); // X = X * N
  136.                     add(res_reg, regs[i]); // r += X
  137.                 } else {
  138.                     resInitialized = true;
  139.                     imul(res_reg, regs[i], params[i]); // r = X * N
  140.                 }
  141.                 break;
  142.             }
  143.         }
  144.         if (constNum != 0) {
  145.             if (resInitialized) {
  146.                 add(res_reg, constNum); // r += Num
  147.             } else {
  148.                 resInitialized = true;
  149.                 mov(res_reg, constNum); // r = Num
  150.             }
  151.         }
  152.         if (!resInitialized)
  153.             xor(res_reg, res_reg); // r = 0
  154. #ifndef XBYAK64
  155.         pop(edi);
  156.         pop(esi);
  157. #endif
  158.         ret();
  159.     }
  160.    
  161.     template <typename Iter>
  162.     static int parseInt(Iter& it, const Iter end) {
  163.         int res = 0, t;
  164.         while (it != end && (t = *it - '0', t>=0 && t<=9)) {
  165.             res *= 10;
  166.             res += t;
  167.             ++it;
  168.         }
  169.         return res;
  170.     }
  171.  
  172.     int exec(int a=0, int b=0, int c=0, int d=0) {
  173.         auto f = reinterpret_cast<int (*)(int, int, int, int)>(getCode());
  174.         return f(a, b, c, d);
  175.     }
  176. };
  177.  
  178. int main() {
  179.     std::string str = "a+a+b-b+c+c+c+c-d-d-d";
  180.     // std::getline(std::cin, str);
  181.     JIT jit(str.begin(), str.end());
  182.     int a=1, b=2, c=3, d=4;
  183.     int res = jit.exec(a, b, c, d);
  184.     assert(a+a+b-b+c+c+c+c-d-d-d == res);
  185.     std::cout << res;
  186. }
Advertisement
Add Comment
Please, Sign In to add comment