|
|
@ -2,180 +2,9 @@ |
|
|
|
#include <cassert>
|
|
|
|
#include <iostream>
|
|
|
|
#include "molasses/parser_primitives.h"
|
|
|
|
|
|
|
|
enum class architecture_t { |
|
|
|
x86_64 |
|
|
|
}; |
|
|
|
|
|
|
|
constexpr architecture_t architecture = architecture_t::x86_64; |
|
|
|
#include "molasses/generator_primitives.h"
|
|
|
|
|
|
|
|
namespace molasses { |
|
|
|
parser_context register_integers(parser_context ctx) { |
|
|
|
ctx.types.push_back(std::make_shared<primitive_type>("i8",1)); |
|
|
|
ctx.types.push_back(std::make_shared<primitive_type>("i16",2)); |
|
|
|
ctx.types.push_back(std::make_shared<primitive_type>("i32",4)); |
|
|
|
ctx.types.push_back(std::make_shared<primitive_type>("i64",8)); |
|
|
|
ctx.types.push_back(std::make_shared<primitive_type>("u8",1)); |
|
|
|
ctx.types.push_back(std::make_shared<primitive_type>("u16",2)); |
|
|
|
ctx.types.push_back(std::make_shared<primitive_type>("u32",4)); |
|
|
|
ctx.types.push_back(std::make_shared<primitive_type>("u64",8)); |
|
|
|
|
|
|
|
return ctx; |
|
|
|
} |
|
|
|
|
|
|
|
parser_context register_i32_operations(parser_context ctx) { |
|
|
|
ctx.operations.emplace_back( |
|
|
|
std::make_shared<molasses::primitive_operation>( |
|
|
|
std::string{"+"}, |
|
|
|
std::vector<std::string>({"i32", "i32"}), |
|
|
|
std::vector<std::string>({"i32"}), |
|
|
|
std::vector<std::string>({ |
|
|
|
" popq %rax\n", |
|
|
|
" popq %rbx\n", |
|
|
|
" addl %ebx, %eax\n", |
|
|
|
" andl $0xFFFFFFFF, %eax\n", |
|
|
|
" pushq %rax\n" |
|
|
|
}) |
|
|
|
) |
|
|
|
); |
|
|
|
ctx.operations.emplace_back( |
|
|
|
std::make_shared<molasses::primitive_operation>( |
|
|
|
std::string{"*"}, |
|
|
|
std::vector<std::string>({"i32", "i32"}), |
|
|
|
std::vector<std::string>({"i32"}), |
|
|
|
std::vector<std::string>({ |
|
|
|
" popq %rax\n", |
|
|
|
" popq %rbx\n", |
|
|
|
" multl %ebx, %eax\n", |
|
|
|
" andl $0xFFFFFFFF, %eax\n", |
|
|
|
" pushq %rax\n" |
|
|
|
}) |
|
|
|
) |
|
|
|
); |
|
|
|
ctx.operations.emplace_back( |
|
|
|
std::make_shared<molasses::primitive_operation>( |
|
|
|
std::string{"-"}, |
|
|
|
std::vector<std::string>({"i32", "i32"}), |
|
|
|
std::vector<std::string>({"i32"}), |
|
|
|
std::vector<std::string>({ |
|
|
|
" popq %rax\n", |
|
|
|
" popq %rbx\n", |
|
|
|
" subl %ebx, %eax\n", |
|
|
|
" andl $0xFFFFFFFF, %eax\n", |
|
|
|
" pushq %rax\n" |
|
|
|
}) |
|
|
|
) |
|
|
|
); |
|
|
|
ctx.operations.emplace_back( |
|
|
|
std::make_shared<molasses::primitive_operation>( |
|
|
|
std::string{"i32-to-i64"}, |
|
|
|
std::vector<std::string>({"i32"}), |
|
|
|
std::vector<std::string>({"i64"}), |
|
|
|
std::vector<std::string>({ |
|
|
|
" popq %rax\n", |
|
|
|
" movslq %rax\n", |
|
|
|
" pushq %rax\n" |
|
|
|
}) |
|
|
|
) |
|
|
|
); |
|
|
|
|
|
|
|
ctx.operations.emplace_back( |
|
|
|
std::make_shared<molasses::primitive_operation>( |
|
|
|
std::string{"syscall1"}, |
|
|
|
std::vector<std::string>({"i64", "i64"}), |
|
|
|
std::vector<std::string>({"i64"}), |
|
|
|
std::vector<std::string>({ |
|
|
|
" popq %rax\n", |
|
|
|
" popq %rdi\n", |
|
|
|
" syscall\n", |
|
|
|
" pushq %rax\n" |
|
|
|
}) |
|
|
|
) |
|
|
|
); |
|
|
|
ctx.operations.emplace_back( |
|
|
|
std::make_shared<molasses::primitive_operation>( |
|
|
|
std::string{"syscall2"}, |
|
|
|
std::vector<std::string>({"i64", "i64", "i64"}), |
|
|
|
std::vector<std::string>({"i64"}), |
|
|
|
std::vector<std::string>({ |
|
|
|
" popq %rax\n", |
|
|
|
" popq %rdi\n", |
|
|
|
" popq %rsi\n", |
|
|
|
" syscall\n", |
|
|
|
" pushq %rax\n" |
|
|
|
}) |
|
|
|
) |
|
|
|
); |
|
|
|
ctx.operations.emplace_back( |
|
|
|
std::make_shared<molasses::primitive_operation>( |
|
|
|
std::string{"syscall3"}, |
|
|
|
std::vector<std::string>({"i64", "i64", "i64", "i64"}), |
|
|
|
std::vector<std::string>({"i64"}), |
|
|
|
std::vector<std::string>({ |
|
|
|
" popq %rax\n", |
|
|
|
" popq %rdi\n", |
|
|
|
" popq %rsi\n", |
|
|
|
" popq %rdx\n", |
|
|
|
" syscall\n", |
|
|
|
" pushq %rax\n" |
|
|
|
}) |
|
|
|
) |
|
|
|
); |
|
|
|
ctx.operations.emplace_back( |
|
|
|
std::make_shared<molasses::primitive_operation>( |
|
|
|
std::string{"syscall4"}, |
|
|
|
std::vector<std::string>({"i64", "i64", "i64", "i64", "i64"}), |
|
|
|
std::vector<std::string>({"i64"}), |
|
|
|
std::vector<std::string>({ |
|
|
|
" popq %rax\n", |
|
|
|
" popq %rdi\n", |
|
|
|
" popq %rsi\n", |
|
|
|
" popq %rdx\n", |
|
|
|
" popq %r10\n", |
|
|
|
" syscall\n", |
|
|
|
" pushq %rax\n" |
|
|
|
}) |
|
|
|
) |
|
|
|
); |
|
|
|
ctx.operations.emplace_back( |
|
|
|
std::make_shared<molasses::primitive_operation>( |
|
|
|
std::string{"syscall5"}, |
|
|
|
std::vector<std::string>({"i64", "i64", "i64", "i64", "i64", "i64"}), |
|
|
|
std::vector<std::string>({"i64"}), |
|
|
|
std::vector<std::string>({ |
|
|
|
" popq %rax\n", |
|
|
|
" popq %rdi\n", |
|
|
|
" popq %rsi\n", |
|
|
|
" popq %rdx\n", |
|
|
|
" popq %r10\n", |
|
|
|
" popq %r8\n", |
|
|
|
" syscall\n", |
|
|
|
" pushq %rax\n" |
|
|
|
}) |
|
|
|
) |
|
|
|
); |
|
|
|
ctx.operations.emplace_back( |
|
|
|
std::make_shared<molasses::primitive_operation>( |
|
|
|
std::string{"syscall6"}, |
|
|
|
std::vector<std::string>({"i64", "i64", "i64", "i64", "i64", "i64", "i64"}), |
|
|
|
std::vector<std::string>({"i64"}), |
|
|
|
std::vector<std::string>({ |
|
|
|
" popq %rax\n", |
|
|
|
" popq %rdi\n", |
|
|
|
" popq %rsi\n", |
|
|
|
" popq %rdx\n", |
|
|
|
" popq %r10\n", |
|
|
|
" popq %r8\n", |
|
|
|
" popq %r9\n", |
|
|
|
" syscall\n", |
|
|
|
" pushq %rax\n" |
|
|
|
}) |
|
|
|
) |
|
|
|
); |
|
|
|
|
|
|
|
return ctx; |
|
|
|
} |
|
|
|
|
|
|
|
std::vector<std::string> operator>>(std::vector<std::string> current_stack, const operation& next_op) { |
|
|
|
{ |
|
|
|
auto args = next_op.argument_types(); |
|
|
@ -249,27 +78,6 @@ namespace molasses { |
|
|
|
return type_stack == execution_output; |
|
|
|
} |
|
|
|
|
|
|
|
std::vector<std::string> initialize_stack() |
|
|
|
requires (architecture == architecture_t::x86_64) { |
|
|
|
return { |
|
|
|
".bss\n",// TODO: make threadlocal
|
|
|
|
"stack_instruction:\n", |
|
|
|
" .quad 0\n", |
|
|
|
".text\n", |
|
|
|
"initialize_callstack:\n", |
|
|
|
" movq $9, %rax\n", |
|
|
|
" movq $0, %rdi\n", |
|
|
|
" movq $8192, %rsi\n", |
|
|
|
" movq $3, %rdx\n", |
|
|
|
" movq $34, %r10\n", |
|
|
|
" movq $-1, %r8\n", |
|
|
|
" movq $0, %r9\n", |
|
|
|
" syscall\n", |
|
|
|
" movq %rax, (stack_instruction)\n", |
|
|
|
" retq\n", |
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
parser_context parse(parser_context ctx, const lexed_output& lexer_data) { |
|
|
|
enum op : int { |
|
|
|
DO_KW = 1, |
|
|
@ -375,48 +183,31 @@ namespace molasses { |
|
|
|
return ctx; |
|
|
|
} |
|
|
|
|
|
|
|
std::vector<std::string> generate_call(std::string target) |
|
|
|
requires (architecture == architecture_t::x86_64) { |
|
|
|
static uint64_t label_count= 0; |
|
|
|
return { |
|
|
|
" movq return_label_n"+std::to_string(label_count)+", (stack_instruction)\n", |
|
|
|
" addq $8, stack_instruction\n", |
|
|
|
" jmp "+target+"\n", |
|
|
|
" return_label_n"+std::to_string(label_count++)+":" |
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
std::vector<std::string> generate_push_int32(int32_t target) requires (architecture == architecture_t::x86_64) { |
|
|
|
return { |
|
|
|
" pushq $" +std::to_string(target)+ "\n" |
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
std::vector<std::string> procedure_operation::generate(const parser_context& ctx, const lexed_output& lexer_data) const |
|
|
|
requires (architecture == architecture_t::x86_64) { |
|
|
|
std::vector<std::string> ops; |
|
|
|
ops.emplace_back(name()+":\n"); |
|
|
|
|
|
|
|
std::vector<std::string> procedure_operation::generate(const parser_context& ctx, const lexed_output& lexer_data) const { |
|
|
|
std::vector<std::string> ops = generate_label(name()); |
|
|
|
|
|
|
|
for(auto&& instruction : generate_enter()) { |
|
|
|
ops.push_back(instruction); |
|
|
|
} |
|
|
|
|
|
|
|
for(auto elem : _body) { |
|
|
|
auto token = lexer_data.dictionary.at(elem); |
|
|
|
if(auto result = try_parse_int32(token); result) { |
|
|
|
for(auto&& elem : generate_push_int32(result.value())) { |
|
|
|
ops.push_back(elem); |
|
|
|
for(auto&& instruction : generate_push_int32(result.value())) { |
|
|
|
ops.push_back(instruction); |
|
|
|
} |
|
|
|
} else if(auto op = ctx.lookup_operation(token); op) { |
|
|
|
for(auto&& elem : op->emit(ctx)) { |
|
|
|
ops.push_back(elem); |
|
|
|
for(auto&& instruction : op->emit(ctx)) { |
|
|
|
ops.push_back(instruction); |
|
|
|
} |
|
|
|
} else { |
|
|
|
throw UnknownTokenError(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
ops.emplace_back(" // Return to caller\n"); |
|
|
|
ops.emplace_back(" addq $-8, stack_instruction\n"); |
|
|
|
ops.emplace_back(" movq (stack_instruction), %rax\n"); |
|
|
|
ops.emplace_back(" pushq %rax\n"); |
|
|
|
ops.emplace_back(" retq\n"); |
|
|
|
|
|
|
|
for(auto&& instruction : generate_return()) { |
|
|
|
ops.push_back(instruction); |
|
|
|
} |
|
|
|
|
|
|
|
return ops; |
|
|
|
} |
|
|
|