Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <cctype>
- #include <iostream>
- #include <map>
- #include <sstream>
- #include <string>
- #include <vector>
- #include <sstream>
- // r3 - то, что возвращается из atom(), term(), expr()
- // r2 - для доп операций
- // r0 - r3 для вызова функций
- // r4 - возвращаемое значение функции
- extern "C" {
- int my_div(int a, int b);
- int my_mod(int a, int b);
- int my_inc(int a);
- int my_dec(int a);
- struct symbol_t {
- const char * name;
- void * pointer;
- };
- void jit_compile_expression_to_arm(const char* expression, const symbol_t* externs, void* out_buffer);
- }
- enum TokenValue : char {
- NAME,
- NUMBER,
- END,
- PLUS = '+',
- MINUS = '-',
- MUL = '*',
- LB = '(',
- RB = ')',
- COM = ','
- };
- enum NumberValue : char {
- NUM0 = '0', NUM1 = '1', NUM2 = '2',
- NUM3 = '3', NUM4 = '4', NUM5 = '5',
- NUM6 = '6', NUM7 = '7', NUM8 = '8',
- NUM9 = '9',
- };
- TokenValue last_operation_token = NUMBER;
- int number_value; // last number value
- std::string string_value; // last string value
- std::map<std::string, int*> table; // names table
- std::vector<uint> result; // asm codes
- std::vector<std::pair<uint, uint>> big_numbers; // pair of offset and number that will be stored at the end
- std::vector<std::pair<uint, std::string>> function_ptrs; // pair of offset for functions
- void expr(std::istream*, bool); // expression with +, -
- void term(std::istream*, bool); // term (multiplicity)
- void atom(std::istream*, bool); // basic expressions (numbers, variables, functions)
- TokenValue get_token(std::istream* input) {
- char ch;
- do {
- if (!input->get(ch)) {
- return last_operation_token = END;
- }
- } while (ch != '\n' && ch == ' ');
- switch (ch) {
- case 0: // end of file
- case '\n':
- return last_operation_token = END;
- case MUL:
- case PLUS:
- case MINUS:
- case LB:
- case RB:
- case COM:
- return last_operation_token = TokenValue(ch); // update operation
- case NUM0:
- case NUM1:
- case NUM2:
- case NUM3:
- case NUM4:
- case NUM5:
- case NUM6:
- case NUM7:
- case NUM8:
- case NUM9:
- // read all number with first symbol (first put back it)
- input->putback(ch);
- *input >> number_value;
- return last_operation_token = NUMBER;
- default:
- if (isalpha(ch)) {
- string_value = ch;
- while (input->get(ch) && isalnum(ch)) {
- string_value.push_back(ch);
- }
- input->putback(ch);
- return last_operation_token = NAME;
- }
- return last_operation_token = END;
- }
- }
- void atom(std::istream* input, bool get) {
- if (get) {
- get_token(input);
- }
- switch (last_operation_token) {
- case NUMBER: {
- int v = number_value;
- get_token(input);
- if ((v >> 12) == 0) {
- result.push_back(0xE3003000 + v); // mov r3, #num
- } else {
- result.push_back(0xE59F3000); // mov r3, .num, num declared later
- big_numbers.push_back(std::make_pair(result.size(), v));
- }
- return;
- }
- case NAME: {
- get_token(input);
- // function name
- if (last_operation_token == LB) {
- std::string func_name = string_value;
- int func_args = 0;
- int* v = table[func_name];
- do {
- result.push_back(0xE24DD004); // sub sp, sp, #4
- expr(input, true);
- func_args++;
- result.push_back(0xE58D3000); // str r3, [sp]
- } while (last_operation_token == COM);
- for (int i = 0; i < func_args; ++i) {
- result.push_back(0xE59D0000 + (i << 12) + 4*(func_args - 1 - i));
- }
- result.push_back(0xE59F4000); // ldr r4, .func_ptr
- function_ptrs.push_back(std::make_pair(result.size(), func_name));
- result.push_back(0xE12FFF34); // blx r4
- result.push_back(0xE1A03000); // mov r3, r0
- result.push_back(0xE28DD000 + func_args * 4);
- get_token(input);
- } else {
- int v = *table[string_value];
- result.push_back(0xE59F3000); // ldr r3, .var_ptr
- big_numbers.push_back(std::make_pair(result.size(), v));
- }
- return;
- }
- case LB: {
- expr(input, true);
- get_token(input);
- return;
- }
- case MINUS: {
- atom(input, true);
- result.push_back(0xE3E02000);
- result.push_back(0xE0233002);
- result.push_back(0xE2833001);
- return;
- }
- default:
- return;
- }
- }
- void term(std::istream* input, bool get) {
- result.push_back(0xE24DD004); // sub sp, sp, #4
- atom(input, get);
- result.push_back(0xE58D3000); // str r3, [sp]
- while (true) {
- switch (last_operation_token) {
- case MUL:
- atom(input, true);
- result.push_back(0xE59D2000); // ldr r2, [sp]
- result.push_back(0xE0030293); // mul r3, r3, r2
- result.push_back(0xE58D3000); // str r3, [sp]
- break;
- default:
- result.push_back(0xE59D3000); // ldr r3, [sp]
- result.push_back(0xE28DD004); // add sp, sp, #4
- return;
- }
- }
- }
- void expr(std::istream* input, bool get) {
- result.push_back(0xE24DD004); // sub sp, sp, #4
- term(input, get);
- result.push_back(0xE58D3000); // str r3, [sp]
- while (true) {
- switch (last_operation_token) {
- case PLUS:
- term(input, true);
- result.push_back(0xE59D2000); // ldr r2, [sp]
- result.push_back(0xE0833002); // add r3, r3, r2
- result.push_back(0xE58D3000); // str r3, [sp]
- break;
- case MINUS:
- term(input, true);
- result.push_back(0xE59D2000); // ldr r2, [sp]
- result.push_back(0xE0423003); // sub r3, r2, r3
- result.push_back(0xE58D3000); // str r3, [sp]
- break;
- default:
- result.push_back(0xE59D3000); // ldr r3, [sp]
- result.push_back(0xE28DD004); // add sp, sp, #4
- return;
- }
- }
- }
- extern "C" void
- jit_compile_expression_to_arm(const char* expression, const symbol_t* externs, void* out_buffer) {
- result.push_back(0xE52DE004); // push {r4}, same as str r4, [sp, #-4]!
- result.push_back(0xE24DD004); // sub sp, sp, #4
- const symbol_t* data = externs;
- int it = 0;
- while (data[it].name != NULL) {
- int *ptr = (int*)data[it].pointer;
- table[data[it].name] = ptr;
- ++it;
- }
- std::string s (expression);
- std::istringstream istr(s);
- std::istream* input = &istr; // stream pointer
- while (*input) {
- get_token(input);
- if (last_operation_token == END) {
- break;
- }
- expr(input, false);
- }
- result.push_back(0xE1A00003); // mov r0, r3
- result.push_back(0xE28DD004); // add sp, sp, #4
- result.push_back(0xE49DE004); // pop {lr}, same as ldr [sp], #4
- result.push_back(0xE12FFF1E); // bx lr
- // execute functions
- for (int i = 0; i < function_ptrs.size(); ++i) {
- result.push_back((int)table[function_ptrs[i].second]); // function ptr
- result[function_ptrs[i].first - 1] += (result.size() - function_ptrs[i].first - 2)*4;
- }
- // set big numbers
- for (int i = 0; i < big_numbers.size(); i++) {
- result.push_back(big_numbers[i].second); // number
- result[big_numbers[i].first - 1] += (result.size() - big_numbers[i].first - 2)*4; // address offset
- }
- uint *res_buff = (uint*)out_buffer;
- for (int i = 0; i < result.size(); ++i) {
- res_buff[i] = result[i];
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement