diff --git a/src/alloy/backend/x64/lowering/lowering_sequences.cc b/src/alloy/backend/x64/lowering/lowering_sequences.cc index 1d11baf4e..5b2cac041 100644 --- a/src/alloy/backend/x64/lowering/lowering_sequences.cc +++ b/src/alloy/backend/x64/lowering/lowering_sequences.cc @@ -60,6 +60,8 @@ void IssueCall(X64Emitter& e, FunctionInfo* symbol_info, uint32_t flags) { e.jmp(e.rax); } else { e.call(e.rax); + e.mov(e.rdx, e.qword[e.rsp + 8]); + e.mov(e.rcx, e.qword[e.rsp + 0]); } } @@ -514,6 +516,8 @@ void alloy::backend::x64::lowering::RegisterSequences(LoweringTable* table) { e.mov(e.r8, (uint64_t)str_copy); e.mov(e.rax, (uint64_t)PrintString); e.call(e.rax); + e.mov(e.rdx, e.qword[e.rsp + 8]); + e.mov(e.rcx, e.qword[e.rsp + 0]); i = e.Advance(i); return true; }); @@ -624,18 +628,18 @@ void alloy::backend::x64::lowering::RegisterSequences(LoweringTable* table) { }); table->AddSequence(OPCODE_RETURN, [](X64Emitter& e, Instr*& i) { - e.ret(); + // If this is the last instruction in the last block, just let us + // fall through. + if (i->next || i->block->next) { + e.jmp("epilog"); + } i = e.Advance(i); return true; }); table->AddSequence(OPCODE_RETURN_TRUE, [](X64Emitter& e, Instr*& i) { - e.inLocalLabel(); CheckBoolean(e, i->src1.value); - e.jne(".x", e.T_SHORT); - e.ret(); - e.L(".x"); - e.outLocalLabel(); + e.je("epilog"); i = e.Advance(i); return true; }); diff --git a/src/alloy/backend/x64/x64_code_cache.cc b/src/alloy/backend/x64/x64_code_cache.cc index 76398989b..7bbf91f2a 100644 --- a/src/alloy/backend/x64/x64_code_cache.cc +++ b/src/alloy/backend/x64/x64_code_cache.cc @@ -214,7 +214,7 @@ void X64CodeChunk::AddTableEntry(uint8_t* code, size_t code_size) { offset += UNWIND_INFO_SIZE; // TODO(benvanik): take as parameters? - bool has_prolog = false; + bool has_prolog = true; uint8_t prolog_size = 4; uint8_t stack_bytes = 64; diff --git a/src/alloy/backend/x64/x64_emitter.cc b/src/alloy/backend/x64/x64_emitter.cc index 13c832621..3d6b3cfa3 100644 --- a/src/alloy/backend/x64/x64_emitter.cc +++ b/src/alloy/backend/x64/x64_emitter.cc @@ -119,11 +119,17 @@ int X64Emitter::Emit(HIRBuilder* builder) { // IMPORTANT: any changes to the prolog must be kept in sync with // X64CodeCache, which dynamically generates exception information. // Adding or changing anything here must be matched! - const bool emit_prolog = false; + const bool emit_prolog = true; const size_t stack_size = 64; if (emit_prolog) { + mov(qword[rsp + 16], rdx); + mov(qword[rsp + 8], rcx); sub(rsp, stack_size); - // TODO(benvanik): save registers. + mov(qword[rsp + 8 * 0], rbx); + mov(qword[rsp + 8 * 1], r12); + mov(qword[rsp + 8 * 2], r13); + mov(qword[rsp + 8 * 3], r14); + mov(qword[rsp + 8 * 4], r15); } auto lowering_table = backend_->lowering_table(); @@ -157,8 +163,12 @@ int X64Emitter::Emit(HIRBuilder* builder) { // Function epilog. L("epilog"); if (emit_prolog) { + mov(rbx, qword[rsp + 8 * 0]); + mov(r12, qword[rsp + 8 * 1]); + mov(r13, qword[rsp + 8 * 2]); + mov(r14, qword[rsp + 8 * 3]); + mov(r15, qword[rsp + 8 * 4]); add(rsp, stack_size); - // TODO(benvanik): restore registers. } ret();