Advertisement
Guest User

Untitled

a guest
Nov 16th, 2018
87
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 7.61 KB | None | 0 0
  1. #include <cctype>
  2. #include <iostream>
  3. #include <map>
  4. #include <sstream>
  5. #include <string>
  6. #include <vector>
  7. #include <sstream>
  8.  
  9. //  r3 - то, что возвращается из atom(), term(), expr()
  10. //  r2 - для доп операций
  11. //  r0 - r3 для вызова функций
  12. //  r4 - возвращаемое значение функции
  13.  
  14. extern "C" {
  15.   int my_div(int a, int b);
  16.   int my_mod(int a, int b);
  17.   int my_inc(int a);
  18.   int my_dec(int a);
  19.   struct symbol_t {
  20.     const char * name;
  21.     void       * pointer;
  22.   };
  23.   void jit_compile_expression_to_arm(const char* expression, const symbol_t* externs, void* out_buffer);
  24. }
  25.  
  26. enum TokenValue : char {
  27.   NAME,
  28.   NUMBER,
  29.   END,
  30.   PLUS = '+',
  31.   MINUS = '-',
  32.   MUL = '*',
  33.   LB = '(',
  34.   RB = ')',
  35.   COM = ','
  36. };
  37.  
  38. enum NumberValue : char {
  39.   NUM0 = '0', NUM1 = '1', NUM2 = '2',
  40.   NUM3 = '3', NUM4 = '4', NUM5 = '5',
  41.   NUM6 = '6', NUM7 = '7', NUM8 = '8',
  42.   NUM9 = '9',
  43. };
  44.  
  45. TokenValue last_operation_token = NUMBER;
  46. int number_value;                         //  last number value
  47. std::string string_value;                 //  last string value
  48. std::map<std::string, int*> table;        //  names table
  49. std::vector<uint> result;                 //  asm codes
  50. std::vector<std::pair<uint, uint>> big_numbers;  //  pair of offset and number that will be stored at the end
  51. std::vector<std::pair<uint, std::string>> function_ptrs;  //  pair of offset for functions
  52.  
  53. void expr(std::istream*, bool);            //  expression with +, -
  54. void term(std::istream*, bool);            //  term (multiplicity)
  55. void atom(std::istream*, bool);            //  basic expressions (numbers, variables, functions)
  56.  
  57. TokenValue get_token(std::istream* input) {
  58.   char ch;
  59.   do {
  60.     if (!input->get(ch)) {
  61.       return last_operation_token = END;
  62.     }
  63.   } while (ch != '\n' && ch == ' ');
  64.  
  65.   switch (ch) {
  66.     case 0:                                         // end of file
  67.     case '\n':
  68.       return last_operation_token = END;
  69.     case MUL:
  70.     case PLUS:
  71.     case MINUS:
  72.     case LB:
  73.     case RB:
  74.     case COM:
  75.       return last_operation_token = TokenValue(ch); //  update operation
  76.     case NUM0:
  77.     case NUM1:
  78.     case NUM2:
  79.     case NUM3:
  80.     case NUM4:
  81.     case NUM5:
  82.     case NUM6:
  83.     case NUM7:
  84.     case NUM8:
  85.     case NUM9:
  86.       //  read all number with first symbol (first put back it)
  87.       input->putback(ch);
  88.       *input >> number_value;
  89.       return last_operation_token = NUMBER;
  90.     default:
  91.       if (isalpha(ch)) {
  92.         string_value = ch;
  93.         while (input->get(ch) && isalnum(ch)) {
  94.           string_value.push_back(ch);
  95.         }
  96.         input->putback(ch);
  97.         return last_operation_token = NAME;
  98.       }
  99.       return last_operation_token = END;
  100.   }
  101. }
  102.  
  103. void atom(std::istream* input, bool get) {
  104.   if (get) {
  105.     get_token(input);
  106.   }
  107.  
  108.   switch (last_operation_token) {
  109.     case NUMBER: {
  110.       int v = number_value;
  111.       get_token(input);
  112.       if ((v >> 12) == 0) {
  113.         result.push_back(0xE3003000 + v);   //  mov r3, #num
  114.       } else {
  115.         result.push_back(0xE59F3000);       //  mov r3, .num, num declared later
  116.         big_numbers.push_back(std::make_pair(result.size(), v));
  117.       }
  118.       return;
  119.     }
  120.     case NAME: {
  121.       get_token(input);
  122.       // function name
  123.       if (last_operation_token == LB) {
  124.         std::string func_name = string_value;
  125.         int func_args = 0;
  126.         int* v = table[func_name];
  127.         do {
  128.           result.push_back(0xE24DD004);   //  sub sp, sp, #4
  129.           expr(input, true);
  130.           func_args++;
  131.           result.push_back(0xE58D3000);   //  str r3, [sp]
  132.         } while (last_operation_token == COM);
  133.         for (int i = 0; i < func_args; ++i) {
  134.           result.push_back(0xE59D0000 + (i << 12) + 4*(func_args - 1 - i));
  135.         }
  136.         result.push_back(0xE59F4000);   //  ldr r4, .func_ptr
  137.         function_ptrs.push_back(std::make_pair(result.size(), func_name));
  138.         result.push_back(0xE12FFF34);   //  blx r4
  139.         result.push_back(0xE1A03000);   //  mov r3, r0
  140.         result.push_back(0xE28DD000 + func_args * 4);
  141.         get_token(input);
  142.       } else {
  143.         int v = *table[string_value];
  144.         result.push_back(0xE59F3000);   //  ldr r3, .var_ptr
  145.         big_numbers.push_back(std::make_pair(result.size(), v));
  146.       }
  147.       return;
  148.     }
  149.     case LB: {
  150.       expr(input, true);
  151.       get_token(input);
  152.       return;
  153.     }
  154.     case MINUS: {
  155.       atom(input, true);
  156.       result.push_back(0xE3E02000);
  157.       result.push_back(0xE0233002);
  158.       result.push_back(0xE2833001);
  159.       return;
  160.     }
  161.     default:
  162.       return;
  163.   }
  164. }
  165.  
  166. void term(std::istream* input, bool get) {
  167.   result.push_back(0xE24DD004);   //  sub sp, sp, #4
  168.   atom(input, get);
  169.   result.push_back(0xE58D3000);   //  str r3, [sp]
  170.  
  171.   while (true) {
  172.     switch (last_operation_token) {
  173.       case MUL:
  174.         atom(input, true);
  175.         result.push_back(0xE59D2000);   //  ldr r2, [sp]
  176.         result.push_back(0xE0030293);   //  mul r3, r3, r2
  177.         result.push_back(0xE58D3000);   //  str r3, [sp]
  178.         break;
  179.       default:
  180.         result.push_back(0xE59D3000);   //  ldr r3, [sp]
  181.         result.push_back(0xE28DD004);   //  add sp, sp, #4
  182.         return;
  183.     }
  184.   }
  185. }
  186.  
  187. void expr(std::istream* input, bool get) {
  188.   result.push_back(0xE24DD004);   //  sub sp, sp, #4
  189.   term(input, get);
  190.   result.push_back(0xE58D3000);   //  str r3, [sp]
  191.  
  192.   while (true) {
  193.     switch (last_operation_token) {
  194.       case PLUS:
  195.         term(input, true);
  196.         result.push_back(0xE59D2000);   //  ldr r2, [sp]
  197.         result.push_back(0xE0833002);   //  add r3, r3, r2
  198.         result.push_back(0xE58D3000);   //  str r3, [sp]
  199.         break;
  200.       case MINUS:
  201.         term(input, true);
  202.         result.push_back(0xE59D2000);   //  ldr r2, [sp]
  203.         result.push_back(0xE0423003);   //  sub r3, r2, r3
  204.         result.push_back(0xE58D3000);   //  str r3, [sp]
  205.         break;
  206.       default:
  207.         result.push_back(0xE59D3000);   //  ldr r3, [sp]
  208.         result.push_back(0xE28DD004);   //  add sp, sp, #4
  209.         return;
  210.     }
  211.   }
  212. }
  213.  
  214. extern "C" void
  215. jit_compile_expression_to_arm(const char* expression, const symbol_t* externs, void* out_buffer) {
  216.   result.push_back(0xE52DE004);   //  push {r4}, same as str r4, [sp, #-4]!
  217.   result.push_back(0xE24DD004);   //  sub sp, sp, #4
  218.   const symbol_t* data = externs;
  219.   int it = 0;
  220.   while (data[it].name != NULL) {
  221.     int *ptr = (int*)data[it].pointer;
  222.     table[data[it].name] = ptr;
  223.     ++it;
  224.   }
  225.   std::string s (expression);
  226.   std::istringstream istr(s);
  227.   std::istream* input = &istr; // stream pointer
  228.   while (*input) {
  229.     get_token(input);
  230.     if (last_operation_token == END) {
  231.       break;
  232.     }
  233.     expr(input, false);
  234.   }
  235.  
  236.   result.push_back(0xE1A00003);     //  mov r0, r3
  237.   result.push_back(0xE28DD004);     //  add sp, sp, #4
  238.   result.push_back(0xE49DE004);     //  pop  {lr}, same as ldr [sp], #4
  239.   result.push_back(0xE12FFF1E);     //  bx  lr
  240.  
  241.   //  execute functions
  242.   for (int i = 0; i < function_ptrs.size(); ++i) {
  243.     result.push_back((int)table[function_ptrs[i].second]); //  function ptr
  244.     result[function_ptrs[i].first - 1] += (result.size() - function_ptrs[i].first - 2)*4;
  245.   }
  246.  
  247.   //  set big numbers
  248.   for (int i = 0; i < big_numbers.size(); i++) {
  249.     result.push_back(big_numbers[i].second);    //  number
  250.     result[big_numbers[i].first - 1] += (result.size() - big_numbers[i].first - 2)*4;   //  address offset
  251.   }
  252.  
  253.   uint *res_buff = (uint*)out_buffer;
  254.   for (int i = 0; i < result.size(); ++i) {
  255.     res_buff[i] = result[i];
  256.   }
  257. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement