#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("i8", 1)); ctx.types.push_back(std::make_shared("i16", 2)); ctx.types.push_back(std::make_shared("i32", 4)); ctx.types.push_back(std::make_shared("i64", 8)); ctx.types.push_back(std::make_shared("u8", 1)); ctx.types.push_back(std::make_shared("u16", 2)); ctx.types.push_back(std::make_shared("u32", 4)); ctx.types.push_back(std::make_shared("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( std::string{"+"}, std::vector({"i32", "i32"}), std::vector({"i32"}), std::vector({ " popq %rax\n", " popq %rbx\n", " addl %ebx, %eax\n", " andl $0xFFFFFFFF, %eax\n", " pushq %rax\n" }) ) ); ctx.operations.emplace_back( std::make_shared( std::string{"*"}, std::vector({"i32", "i32"}), std::vector({"i32"}), std::vector({ " popq %rax\n", " popq %rbx\n", " multl %ebx, %eax\n", " andl $0xFFFFFFFF, %eax\n", " pushq %rax\n" }) ) ); ctx.operations.emplace_back( std::make_shared( std::string{"-"}, std::vector({"i32", "i32"}), std::vector({"i32"}), std::vector({ " popq %rax\n", " popq %rbx\n", " subl %ebx, %eax\n", " andl $0xFFFFFFFF, %eax\n", " pushq %rax\n" }) ) ); ctx.operations.emplace_back( std::make_shared( std::string{"i32-to-i64"}, std::vector({"i32"}), std::vector({"i64"}), std::vector({ " popq %rax\n", " movslq %rax\n", " pushq %rax\n" }) ) ); ctx.operations.emplace_back( std::make_shared( std::string{"syscall1"}, std::vector({"i64", "i64"}), std::vector({"i64"}), std::vector({ " popq %rax\n", " popq %rdi\n", " syscall\n", " pushq %rax\n" }) ) ); ctx.operations.emplace_back( std::make_shared( std::string{"syscall2"}, std::vector({"i64", "i64", "i64"}), std::vector({"i64"}), std::vector({ " popq %rax\n", " popq %rdi\n", " popq %rsi\n", " syscall\n", " pushq %rax\n" }) ) ); ctx.operations.emplace_back( std::make_shared( std::string{"syscall3"}, std::vector({"i64", "i64", "i64", "i64"}), std::vector({"i64"}), std::vector({ " popq %rax\n", " popq %rdi\n", " popq %rsi\n", " popq %rdx\n", " syscall\n", " pushq %rax\n" }) ) ); ctx.operations.emplace_back( std::make_shared( std::string{"syscall4"}, std::vector({"i64", "i64", "i64", "i64", "i64"}), std::vector({"i64"}), std::vector({ " 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( std::string{"syscall5"}, std::vector({"i64", "i64", "i64", "i64", "i64", "i64"}), std::vector({"i64"}), std::vector({ " 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( std::string{"syscall6"}, std::vector({"i64", "i64", "i64", "i64", "i64", "i64", "i64"}), std::vector({"i64"}), std::vector({ " 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 generate_call(const std::string& target) requires (architecture == architecture_t::x86_64_linux) { return { " call "+target+"\n", }; } std::vector generate_push_int32(int32_t target) requires (architecture == architecture_t::x86_64_linux) { return { " pushq $" +std::to_string(target)+ "\n" }; } std::vector generate_label(const std::string& target) requires (architecture == architecture_t::x86_64_linux) { return { target+":\n" }; } std::vector 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 generate_enter() requires (architecture == architecture_t::x86_64_linux) { return { " // Prepare the function stack\n", " popq (%r10)\n" " addq $8, %r10\n", }; } std::vector initialize_stack() requires (architecture == architecture_t::x86_64_linux) { std::vector 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{ " movq $0, %rdi\n", " movq $60, %rax\n", " syscall\n" } ) { operations.push_back(op); } return operations; } }