diff --git a/Makefile b/Makefile index 8c341019..8202ec7d 100644 --- a/Makefile +++ b/Makefile @@ -159,6 +159,7 @@ JANET_CORE_SOURCES=src/core/abstract.c \ src/core/struct.c \ src/core/symcache.c \ src/core/sysir.c \ + src/core/sysir_x86.c \ src/core/table.c \ src/core/tuple.c \ src/core/util.c \ diff --git a/examples/sysir/frontend.janet b/examples/sysir/frontend.janet index e8a96a2f..dfdde5d8 100644 --- a/examples/sysir/frontend.janet +++ b/examples/sysir/frontend.janet @@ -356,6 +356,16 @@ [] (eprintf "%.99M\n" (sysir/to-ir ctx))) +(defn dumpx64 + [] + (print (sysir/to-x64 ctx))) + (defn dumpc [] (print (sysir/to-c ctx))) + +#### + +(compile1 myprog) +#(dump) +(dumpx64) diff --git a/meson.build b/meson.build index 753173a1..5e7bc6d7 100644 --- a/meson.build +++ b/meson.build @@ -142,6 +142,7 @@ core_src = [ 'src/core/struct.c', 'src/core/symcache.c', 'src/core/sysir.c', + 'src/core/sysir_x86.c', 'src/core/table.c', 'src/core/tuple.c', 'src/core/util.c', diff --git a/src/core/sysir.c b/src/core/sysir.c index d3c66fac..0db31a84 100644 --- a/src/core/sysir.c +++ b/src/core/sysir.c @@ -1839,12 +1839,23 @@ JANET_CORE_FN(cfun_sysir_toir, return janet_wrap_array(array); } +JANET_CORE_FN(cfun_sysir_tox64, + "(sysir/to-x64 context &opt buffer options)", + "Lower IR to x64 machine code.") { + janet_arity(argc, 1, 3); + JanetSysIRLinkage *ir = janet_getabstract(argv, 0, &janet_sysir_context_type); + JanetBuffer *buffer = janet_optbuffer(argv, argc, 1, 0); + janet_sys_ir_lower_to_x64(ir, buffer); + return janet_wrap_buffer(buffer); +} + void janet_lib_sysir(JanetTable *env) { JanetRegExt cfuns[] = { JANET_CORE_REG("sysir/context", cfun_sysir_context), JANET_CORE_REG("sysir/asm", cfun_sysir_asm), JANET_CORE_REG("sysir/to-c", cfun_sysir_toc), JANET_CORE_REG("sysir/to-ir", cfun_sysir_toir), + JANET_CORE_REG("sysir/to-x64", cfun_sysir_tox64), JANET_REG_END }; janet_core_cfuns_ext(env, NULL, cfuns); diff --git a/src/core/sysir_x86.c b/src/core/sysir_x86.c index a48fec5a..62aab717 100644 --- a/src/core/sysir_x86.c +++ b/src/core/sysir_x86.c @@ -170,11 +170,17 @@ JanetSysSpill *assign_registers(JanetSysIR *ir, JanetTable *assignments, void janet_sys_ir_lower_to_x64(JanetSysIRLinkage *linkage, JanetBuffer *buffer) { /* Do register allocation */ - for (int32_t i = 0; i < janet_v_count(linkage->irs); i++) { + for (int32_t i = 0; i < linkage->ir_ordered->count; i++) { JanetSysIR *ir = janet_unwrap_pointer(linkage->ir_ordered->data[i]); JanetTable *assignments = janet_table(0); JanetSysSpill *spills = assign_registers(ir, assignments, 15); + /* Emit prelude */ + if (ir->link_name != NULL) { + janet_formatb(buffer, ".%s\n", ir->link_name); + } else { + janet_formatb(buffer, "._section_%d\n", i); + } for (uint32_t j = 0; j < ir->instruction_count; j++) { JanetSysInstruction instruction = ir->instructions[j]; JanetSysSpill spill = spills[j]; @@ -183,21 +189,29 @@ void janet_sys_ir_lower_to_x64(JanetSysIRLinkage *linkage, JanetBuffer *buffer) // emit load uint32_t reg = spill.regs[spi]; void *x = (void *) 0x123456; - janet_formatb(buffer, "load r%u from %p\n", reg, x); + janet_formatb(buffer, "load r%u from %v ; SPILL\n", reg, janet_wrap_pointer(x)); } if (spill.spills[spi] == JANET_SYS_SPILL_WRITE || spill.spills[spi] == JANET_SYS_SPILL_BOTH) { // emit store uint32_t reg = spill.regs[spi]; void *x = (void *) 0x123456; - janet_formatb(buffer, "store r%u to %p\n", reg, x); + janet_formatb(buffer, "store r%u to %v ; SPILL\n", reg, janet_wrap_pointer(x)); } } switch (instruction.opcode) { default: + janet_formatb(buffer, "; nyi: %s\n", janet_sysop_names[instruction.opcode]); + break; + case JANET_SYSOP_TYPE_PRIMITIVE: + case JANET_SYSOP_TYPE_UNION: + case JANET_SYSOP_TYPE_STRUCT: + case JANET_SYSOP_TYPE_BIND: + case JANET_SYSOP_TYPE_ARRAY: + case JANET_SYSOP_TYPE_POINTER: + /* Non synthesized instructions */ break; case JANET_SYSOP_POINTER_ADD: case JANET_SYSOP_POINTER_SUBTRACT: - break; case JANET_SYSOP_ADD: case JANET_SYSOP_SUBTRACT: case JANET_SYSOP_MULTIPLY: @@ -208,6 +222,24 @@ void janet_sys_ir_lower_to_x64(JanetSysIRLinkage *linkage, JanetBuffer *buffer) v2reg(assignments, instruction.three.lhs), v2reg(assignments, instruction.three.rhs)); break; + case JANET_SYSOP_MOVE: + janet_formatb(buffer, "r%u = r%u\n", + v2reg(assignments, instruction.two.dest), + v2reg(assignments, instruction.two.src)); + break; + case JANET_SYSOP_RETURN: + janet_formatb(buffer, "return r%u\n", + v2reg(assignments, instruction.one.src)); + break; + case JANET_SYSOP_CONSTANT: + janet_formatb(buffer, "r%u = constant $%v\n", + v2reg(assignments, instruction.constant.dest), + ir->constants[instruction.constant.constant]); + break; + case JANET_SYSOP_LABEL: + janet_formatb(buffer, ":label_%u\n", + v2reg(assignments, instruction.label.id)); + break; // On a comparison, if next instruction is branch that reads from dest, combine into a single op. }