#include "molasses/parser_primitives.h"
|
|
#include "molasses/generator_primitives.h"
|
|
|
|
namespace molasses {
|
|
parser_context register_integers(parser_context ctx)
|
|
requires (architecture == architecture_t::x86_64_linux) {
|
|
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)
|
|
requires (architecture == architecture_t::x86_64_linux) {
|
|
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> generate_call(const std::string& target)
|
|
requires (architecture == architecture_t::x86_64_linux) {
|
|
return {
|
|
" call "+target+"\n",
|
|
};
|
|
}
|
|
|
|
std::vector<std::string> generate_push_int32(int32_t target)
|
|
requires (architecture == architecture_t::x86_64_linux) {
|
|
return {
|
|
" pushq $" +std::to_string(target)+ "\n"
|
|
};
|
|
}
|
|
|
|
std::vector<std::string> generate_label(const std::string& target)
|
|
requires (architecture == architecture_t::x86_64_linux) {
|
|
return {
|
|
target+":\n"
|
|
};
|
|
}
|
|
|
|
std::vector<std::string> generate_return()
|
|
requires (architecture == architecture_t::x86_64_linux) {
|
|
return {
|
|
" // Return to caller\n",
|
|
" addq $-8, %r10\n",
|
|
" pushq (%r10)\n",
|
|
" retq\n"
|
|
};
|
|
}
|
|
|
|
std::vector<std::string> generate_enter()
|
|
requires (architecture == architecture_t::x86_64_linux) {
|
|
return {
|
|
" // Prepare the function stack\n",
|
|
" popq (%r10)\n"
|
|
" addq $8, %r10\n",
|
|
};
|
|
}
|
|
|
|
std::vector<std::string> initialize_stack()
|
|
requires (architecture == architecture_t::x86_64_linux) {
|
|
std::vector<std::string> operations = {
|
|
"code:\n",
|
|
" .skip 1000000\n",
|
|
".text\n",
|
|
" .globl _start\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, %r10\n",
|
|
" retq\n",
|
|
"_start:\n",
|
|
" call initialize_callstack\n"
|
|
};
|
|
|
|
for(const auto& op : generate_call("main")) {
|
|
operations.push_back(op);
|
|
}
|
|
|
|
for(const auto& op : std::vector<std::string>{
|
|
" movq $0, %rdi\n",
|
|
" movq $60, %rax\n",
|
|
" syscall\n"
|
|
}
|
|
) {
|
|
operations.push_back(op);
|
|
}
|
|
return operations;
|
|
}
|
|
}
|