|  |  | @ -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; | 
		
	
		
			
			|  |  |  | } | 
		
	
	
		
			
				|  |  |  |