1
0
mirror of https://github.com/janet-lang/janet synced 2024-11-16 13:44:48 +00:00

Working examples on windows.

Add some support for windows x64 ABI.
This commit is contained in:
Calvin Rose 2024-06-17 07:07:20 -07:00
parent cdb3baaca3
commit e5765b26d4
7 changed files with 207 additions and 99 deletions

View File

@ -20,11 +20,11 @@
@setlocal
@rem Example use asan
@rem set JANET_COMPILE=cl /nologo /Isrc\include /Isrc\conf /c /O2 /W3 /D_CRT_SECURE_NO_WARNINGS /MD /fsanitize=address /Zi
@rem set JANET_LINK=link /nologo clang_rt.asan_dynamic-x86_64.lib clang_rt.asan_dynamic_runtime_thunk-x86_64.lib
@set JANET_COMPILE=cl /nologo /Isrc\include /Isrc\conf /c /O2 /W3 /D_CRT_SECURE_NO_WARNINGS /MD /fsanitize=address /Zi /DEBUG
@set JANET_LINK=link /nologo clang_rt.asan_dynamic-x86_64.lib clang_rt.asan_dynamic_runtime_thunk-x86_64.lib /DEBUG
@set JANET_COMPILE=cl /nologo /Isrc\include /Isrc\conf /c /O2 /W3 /D_CRT_SECURE_NO_WARNINGS /MD
@set JANET_LINK=link /nologo
@rem set JANET_COMPILE=cl /nologo /Isrc\include /Isrc\conf /c /O2 /W3 /D_CRT_SECURE_NO_WARNINGS /MD
@rem set JANET_LINK=link /nologo
@set JANET_LINK_STATIC=lib /nologo

View File

@ -57,6 +57,7 @@
(add-prim-type 'long 's64)
(add-prim-type 'pointer 'pointer)
(add-prim-type 'boolean 'boolean)
(add-prim-type 's16 's16)
(sysir/asm ctx into)
ctx)

View File

@ -1,4 +1,4 @@
janet.exe examples/sysir/samples.janet > temp.nasm
nasm -fwin64 temp.nasm -l temp.lst -o temp.o
link temp.o legacy_stdio_definitions.lib msvcrt.lib /out:temp.exe
link /entry:Start /subsystem:windows kernel32.lib user32.lib temp.o /out:temp.exe
temp.exe

View File

@ -32,19 +32,27 @@
(return x)))
(def main-fn
'(defn WinMain:void []
'(defn _start:void []
#(syscall 1 1 "Hello, world!\n" 14)
(doloop 10 20)
(exit (the int 0))
(return)))
(def winmain
'(defn Start:void []
(MessageBoxExA (the pointer 0) "Hello, world!" "Test" 0 (the s16 0))
(ExitProcess (the int 0))
(return)))
####
#(compile1 square)
(compile1 simple)
(compile1 myprog)
(compile1 doloop)
(compile1 main-fn)
#(compile1 simple)
#(compile1 myprog)
#(compile1 doloop)
#(compile1 main-fn)
(compile1 winmain)
#(dump)
#(dumpc)
(dumpx64)

View File

@ -71,6 +71,7 @@ const char *prim_to_prim_name[] = {
const char *janet_sysop_names[] = {
"link-name", /* JANET_SYSOP_LINK_NAME */
"parameter-count", /* JANET_SYSOP_PARAMETER_COUNT */
"calling-convention", /* JANET_SYSOP_CALLING_CONVENTION */
"move", /* JANET_SYSOP_MOVE */
"cast", /* JANET_SYSOP_CAST */
"add", /* JANET_SYSOP_ADD */
@ -158,6 +159,7 @@ static const JanetSysInstrName sys_op_names[] = {
{"branch-not", JANET_SYSOP_BRANCH_NOT},
{"bxor", JANET_SYSOP_BXOR},
{"call", JANET_SYSOP_CALL},
{"calling-convention", JANET_SYSOP_CALLING_CONVENTION},
{"cast", JANET_SYSOP_CAST},
{"divide", JANET_SYSOP_DIVIDE},
{"eq", JANET_SYSOP_EQ},
@ -287,7 +289,7 @@ static uint32_t instr_read_type_operand(Janet x, JanetSysIR *ir, ReadOpMode rmod
return (uint32_t) n;
} else if (rmode == READ_TYPE_FORWARD_REF) {
uint32_t operand = linkage->type_def_count++;
janet_table_put(linkage->type_name_lookup, x, janet_wrap_number(-(int64_t)operand - 1));
janet_table_put(linkage->type_name_lookup, x, janet_wrap_number(-(double)operand - 1.0));
return operand;
} else if (rmode == READ_TYPE_DEFINITION) {
uint32_t operand = linkage->type_def_count++;
@ -370,6 +372,7 @@ static void janet_sysir_init_instructions(JanetSysIR *out, JanetView instruction
JanetSysInstruction *ir = NULL;
JanetTable *labels = out->labels;
int found_parameter_count = 0;
int found_calling_convention = 0;
/* Parse instructions */
Janet x = janet_wrap_nil();
@ -436,6 +439,14 @@ static void janet_sysir_init_instructions(JanetSysIR *out, JanetView instruction
found_parameter_count = 1;
out->parameter_count = janet_getnat(tuple, 1);
break;
case JANET_SYSOP_CALLING_CONVENTION:
instr_assert_length(tuple, 2, opvalue);
if (found_calling_convention) {
janet_panic("duplicate calling-convention");
}
found_calling_convention = 1;
out->calling_convention = instr_read_cc(tuple[1]);
break;
case JANET_SYSOP_ADD:
case JANET_SYSOP_SUBTRACT:
case JANET_SYSOP_MULTIPLY:
@ -1063,6 +1074,7 @@ static void janet_sysir_type_check(JanetSysIR *sysir) {
case JANET_SYSOP_ARG:
case JANET_SYSOP_LINK_NAME:
case JANET_SYSOP_PARAMETER_COUNT:
case JANET_SYSOP_CALLING_CONVENTION:
case JANET_SYSOP_JUMP:
case JANET_SYSOP_LABEL:
break;
@ -1202,6 +1214,7 @@ static void janet_sys_ir_init(JanetSysIR *out, JanetView instructions, JanetSysI
ir.parameter_count = 0;
ir.link_name = NULL;
ir.error_ctx = janet_wrap_nil();
ir.calling_convention = JANET_SYS_CC_DEFAULT;
janet_sysir_init_instructions(&ir, instructions);
@ -1384,6 +1397,7 @@ void janet_sys_ir_lower_to_c(JanetSysIRLinkage *linkage, JanetBuffer *buffer) {
case JANET_SYSOP_ARG:
case JANET_SYSOP_LINK_NAME:
case JANET_SYSOP_PARAMETER_COUNT:
case JANET_SYSOP_CALLING_CONVENTION:
break;
case JANET_SYSOP_LABEL: {
janet_formatb(buffer, "\n_label_%u:\n", instruction.label.id);

View File

@ -102,6 +102,7 @@ typedef struct {
typedef enum {
JANET_SYSOP_LINK_NAME,
JANET_SYSOP_PARAMETER_COUNT,
JANET_SYSOP_CALLING_CONVENTION,
JANET_SYSOP_MOVE,
JANET_SYSOP_CAST,
JANET_SYSOP_ADD,
@ -300,6 +301,7 @@ typedef struct {
JanetSysConstant *constants;
JanetTable *register_name_lookup;
JanetTable *labels;
JanetSysCallingConvention calling_convention;
Janet error_ctx; /* Temporary for holding error messages */
} JanetSysIR;

View File

@ -91,11 +91,10 @@ typedef struct {
JanetSysTypeLayout *layouts;
JanetSysTypeLayout *ir_layouts;
uint32_t frame_size;
uint32_t restore_count;
uint32_t to_restore[128];
JanetSysCallingConvention calling_convention;
JanetSysCallingConvention calling_convention; /* Store normalized calling convention of current IR */
int32_t ir_index;
uint32_t occupied_registers;
uint32_t clobbered_registers; /* Restore these before returning */
} JanetSysx64Context;
/* Get the layout for types */
@ -167,6 +166,8 @@ void assign_registers(JanetSysx64Context *ctx) {
/* TODO - avoid spills inside loops if possible i.e. not all spills are equal */
/* TODO - move into sysir.c and allow reuse for multiple targets */
JanetSysCallingConvention cc = ctx->calling_convention;
/* Make trivial assigments */
uint32_t next_loc = 16;
ctx->regs = janet_smalloc(ctx->ir->register_count * sizeof(x64Reg));
@ -179,19 +180,28 @@ void assign_registers(JanetSysx64Context *ctx) {
ctx->regs[i].kind = get_slot_regkind(ctx, i);
if (i < ctx->ir->parameter_count) {
/* Assign to rdi, rsi, etc. according to ABI */
if (i == 0) ctx->regs[i].index = RDI;
if (i == 1) ctx->regs[i].index = RSI;
if (i == 2) ctx->regs[i].index = RDX;
if (i == 3) ctx->regs[i].index = RCX;
if (i == 4) ctx->regs[i].index = 8;
if (i == 5) ctx->regs[i].index = 9;
if (i >= 6) {
janet_panic("nyi");
ctx->regs[i].storage = JANET_SYSREG_STACK_PARAMETER;
if (cc == JANET_SYS_CC_X64_SYSV) {
if (i == 0) ctx->regs[i].index = RDI;
if (i == 1) ctx->regs[i].index = RSI;
if (i == 2) ctx->regs[i].index = RDX;
if (i == 3) ctx->regs[i].index = RCX;
if (i == 4) ctx->regs[i].index = 8;
if (i == 5) ctx->regs[i].index = 9;
if (i >= 6) {
janet_panic("nyi parameter count > 6");
ctx->regs[i].storage = JANET_SYSREG_STACK_PARAMETER;
}
} else if (cc == JANET_SYS_CC_X64_WINDOWS) {
if (i == 0) ctx->regs[i].index = RCX;
if (i == 1) ctx->regs[i].index = RDX;
if (i == 2) ctx->regs[i].index = 8;
if (i == 3) ctx->regs[i].index = 9;
if (i >= 4) {
ctx->regs[i].storage = JANET_SYSREG_STACK_PARAMETER;
ctx->regs[i].index = (i - 4) * 8 + 16;
}
} else {
ctx->regs[i].storage = JANET_SYSREG_REGISTER;
assigned |= 1 << ctx->regs[i].index;
occupied |= 1 << ctx->regs[i].index;
janet_panic("cannot assign registers for calling convention");
}
} else if (assigned < 0xFFFF) {
/* Assign to register */
@ -216,19 +226,24 @@ void assign_registers(JanetSysx64Context *ctx) {
ctx->occupied_registers = occupied;
/* Mark which registers need restoration before returning */
ctx->restore_count = 0;
unsigned char seen[16] = {0};
unsigned char tokeep[] = {3, 6, 7, 12, 13, 14, 15};
for (uint32_t i = 0; i < ctx->ir->register_count; i++) {
x64Reg reg = ctx->regs[i];
if (reg.storage != JANET_SYSREG_REGISTER) continue;
for (unsigned int j = 0; j < sizeof(tokeep); j++) {
if (!seen[j] && reg.index == tokeep[j]) {
ctx->to_restore[ctx->restore_count++] = reg.index;
seen[j] = 1;
}
}
uint32_t non_volatile_mask = 0;
if (cc == JANET_SYS_CC_X64_SYSV) {
non_volatile_mask = (1 << RBX)
| (1 << 12)
| (1 << 13)
| (1 << 14)
| (1 << 15);
}
if (cc == JANET_SYS_CC_X64_WINDOWS) {
non_volatile_mask = (1 << RBX)
| (RDI << 12)
| (RSI << 12)
| (1 << 12)
| (1 << 13)
| (1 << 14)
| (1 << 15);
}
ctx->clobbered_registers = assigned | non_volatile_mask;
}
static int operand_isstack(JanetSysx64Context *ctx, uint32_t o) {
@ -372,10 +387,11 @@ static void sysemit_three_inst(JanetSysx64Context *ctx, const char *op, JanetSys
static void sysemit_ret(JanetSysx64Context *ctx, uint32_t arg, int has_return) {
if (has_return) sysemit_movreg(ctx, RAX, arg);
/* TODO - depends on current calling convention */
for (uint32_t k = 0; k < ctx->restore_count; k++) {
/* Pop in reverse order */
janet_formatb(ctx->buffer, "pop %s\n", register_names[ctx->to_restore[ctx->restore_count - k - 1]]);
/* Pop in reverse order */
for (int32_t k = 31; k >= 0; k--) {
if (ctx->clobbered_registers & (1u << k)) {
janet_formatb(ctx->buffer, "pop %s\n", register_names[k]);
}
}
janet_formatb(ctx->buffer, "leave\n");
janet_formatb(ctx->buffer, "ret\n");
@ -404,7 +420,7 @@ static int sysemit_comp(JanetSysx64Context *ctx, uint32_t index,
nexti.branch.cond == instruction.three.dest) {
/* Combine compare and branch */
int invert = nexti.opcode == JANET_SYSOP_BRANCH_NOT;
janet_formatb(ctx->buffer, "%s label_%d_%u\n", invert ? branch_invert : branch, ctx->ir_index, nexti.branch.to);
janet_formatb(ctx->buffer, "%s label_%d_%u\n", invert ? branch_invert : branch, ctx->ir_index, (uint64_t) nexti.branch.to);
/* Skip next branch IR instruction */
return 1;
} else {
@ -438,6 +454,100 @@ static void sysemit_cast(JanetSysx64Context *ctx, JanetSysInstruction instructio
janet_formatb(ctx->buffer, "; cast nyi\n");
}
static void sysemit_sysv_call(JanetSysx64Context *ctx, JanetSysInstruction instruction, uint32_t *args, uint32_t argcount) {
/* Push first 6 arguments to particular registers */
JanetSysIR *ir = ctx->ir;
JanetBuffer *buffer = ctx->buffer;
int save_rdi = argcount >= 1 || (ctx->occupied_registers & (1 << RDI));
int save_rsi = argcount >= 2 || (ctx->occupied_registers & (1 << RSI));
int save_rdx = argcount >= 3 || (ctx->occupied_registers & (1 << RDX));
int save_rcx = argcount >= 4 || (ctx->occupied_registers & (1 << RCX));
int save_r8 = argcount >= 5 || (ctx->occupied_registers & (1 << 8));
int save_r9 = argcount >= 6 || (ctx->occupied_registers & (1 << 9));
int save_r10 = ctx->occupied_registers & (1 << 10);
int save_r11 = ctx->occupied_registers & (1 << 11);
if (save_rdi && argcount >= 1) sysemit_mov_save(ctx, RDI, args[0]);
if (save_rdi && argcount < 1) sysemit_pushreg(ctx, RDI);
if (save_rsi && argcount >= 2) sysemit_mov_save(ctx, RSI, args[1]);
if (save_rsi && argcount < 2) sysemit_pushreg(ctx, RSI);
if (save_rdx && argcount >= 3) sysemit_mov_save(ctx, RDX, args[2]);
if (save_rdx && argcount < 3) sysemit_pushreg(ctx, RDX);
if (save_rcx && argcount >= 4) sysemit_mov_save(ctx, RCX, args[3]);
if (save_rcx && argcount < 4) sysemit_pushreg(ctx, RCX);
if (save_r8 && argcount >= 5) sysemit_mov_save(ctx, 8, args[4]);
if (save_r8 && argcount < 5) sysemit_pushreg(ctx, 8);
if (save_r9 && argcount >= 6) sysemit_mov_save(ctx, 9, args[5]);
if (save_r9 && argcount < 6) sysemit_pushreg(ctx, 9);
if (save_r10) sysemit_pushreg(ctx, 10);
if (save_r11) sysemit_pushreg(ctx, 11);
for (int32_t argo = argcount - 1; argo >= 6; argo--) {
janet_panic("nyi push sysv args");
janet_formatb(buffer, "push ");
sysemit_operand(ctx, args[argo], "\n");
}
if (instruction.opcode == JANET_SYSOP_SYSCALL) {
sysemit_movreg(ctx, RAX, instruction.call.callee);
janet_formatb(buffer, "syscall\n");
} else {
/* Save RAX to number of floating point args for varags - for now, always 0 :) */
janet_formatb(buffer, "mov rax, 0\n");
janet_formatb(buffer, "call ");
sysemit_operand(ctx, instruction.call.callee, "\n");
}
if (instruction.call.flags & JANET_SYS_CALLFLAG_HAS_DEST) sysemit_movreg(ctx, RAX, instruction.call.dest);
if (save_r11) sysemit_popreg(ctx, 11);
if (save_r10) sysemit_popreg(ctx, 10);
if (save_r9) sysemit_popreg(ctx, 9);
if (save_r8) sysemit_popreg(ctx, 8);
if (save_rcx) sysemit_popreg(ctx, RCX);
if (save_rdx) sysemit_popreg(ctx, RDX);
if (save_rsi) sysemit_popreg(ctx, RSI);
if (save_rdi) sysemit_popreg(ctx, RDI);
}
static void sysemit_win64_call(JanetSysx64Context *ctx, JanetSysInstruction instruction, uint32_t *args, uint32_t argcount) {
/* Push first 6 arguments to particular registers */
JanetSysIR *ir = ctx->ir;
JanetBuffer *buffer = ctx->buffer;
int save_rcx = argcount >= 1 || (ctx->occupied_registers & (1 << RCX));
int save_rdx = argcount >= 2 || (ctx->occupied_registers & (1 << RDX));
int save_r8 = argcount >= 3 || (ctx->occupied_registers & (1 << 8));
int save_r9 = argcount >= 4 || (ctx->occupied_registers & (1 << 9));
int save_r10 = ctx->occupied_registers & (1 << 10);
int save_r11 = ctx->occupied_registers & (1 << 11);
if (save_rcx && argcount >= 1) sysemit_mov_save(ctx, RCX, args[0]);
if (save_rcx && argcount < 1) sysemit_pushreg(ctx, RCX);
if (save_rdx && argcount >= 2) sysemit_mov_save(ctx, RDX, args[1]);
if (save_rdx && argcount < 2) sysemit_pushreg(ctx, RDX);
if (save_r8 && argcount >= 3) sysemit_mov_save(ctx, 8, args[2]);
if (save_r8 && argcount < 3) sysemit_pushreg(ctx, 8);
if (save_r9 && argcount >= 4) sysemit_mov_save(ctx, 9, args[3]);
if (save_r9 && argcount < 4) sysemit_pushreg(ctx, 9);
if (save_r10) sysemit_pushreg(ctx, 10);
if (save_r11) sysemit_pushreg(ctx, 11);
for (uint32_t argo = 4; argo < argcount; argo++) {
janet_formatb(buffer, "push ");
sysemit_operand(ctx, args[argo], "\n");
}
if (instruction.opcode == JANET_SYSOP_SYSCALL) {
sysemit_movreg(ctx, RAX, instruction.call.callee);
janet_formatb(buffer, "syscall\n");
} else {
janet_formatb(buffer, "call ");
sysemit_operand(ctx, instruction.call.callee, "\n");
}
if (argcount > 4) {
janet_formatb(buffer, "add rsp, %u\n", 8 * (argcount - 4));
}
if (instruction.call.flags & JANET_SYS_CALLFLAG_HAS_DEST) sysemit_movreg(ctx, RAX, instruction.call.dest);
if (save_r11) sysemit_popreg(ctx, 11);
if (save_r10) sysemit_popreg(ctx, 10);
if (save_r9) sysemit_popreg(ctx, 9);
if (save_r8) sysemit_popreg(ctx, 8);
if (save_rdx) sysemit_popreg(ctx, RDX);
if (save_rcx) sysemit_popreg(ctx, RCX);
}
void janet_sys_ir_lower_to_x64(JanetSysIRLinkage *linkage, JanetBuffer *buffer) {
/* Partially setup context */
@ -480,8 +590,13 @@ void janet_sys_ir_lower_to_x64(JanetSysIRLinkage *linkage, JanetBuffer *buffer)
if (ir->link_name == NULL) {
continue;
}
ctx.calling_convention = ir->calling_convention;
if (ctx.calling_convention == JANET_SYS_CC_DEFAULT) {
/* Pick default calling convention */
ctx.calling_convention = JANET_SYS_CC_X64_WINDOWS;
}
/* Setup conttext */
/* Setup context */
ctx.ir_layouts = janet_smalloc(ir->register_count * sizeof(JanetSysTypeLayout));
for (uint32_t i = 0; i < ir->register_count; i++) {
ctx.ir_layouts[i] = ctx.layouts[ir->types[i]];
@ -497,9 +612,10 @@ void janet_sys_ir_lower_to_x64(JanetSysIRLinkage *linkage, JanetBuffer *buffer)
}
janet_formatb(buffer, "push rbp\nmov rbp, rsp\nsub rsp, %u\n", ctx.frame_size);
for (uint32_t k = 0; k < ctx.restore_count; k++) {
/* Pop in reverse order */
janet_formatb(buffer, "push %s\n", register_names[ctx.to_restore[k]]);
for (uint32_t k = 0; k < 32; k++) {
if (ctx.clobbered_registers & (1u << k)) {
janet_formatb(buffer, "push %s\n", register_names[k]);
}
}
/* Function body */
@ -593,64 +709,31 @@ void janet_sys_ir_lower_to_x64(JanetSysIRLinkage *linkage, JanetBuffer *buffer)
break;
case JANET_SYSOP_SYSCALL:
case JANET_SYSOP_CALL:
;
/* Push first 6 arguments to particular registers */
uint32_t argcount = 0;
uint32_t *args = janet_sys_callargs(ir->instructions + j, &argcount);
int save_rdi = argcount >= 1 || (ctx.occupied_registers & (1 << RDI));
int save_rsi = argcount >= 2 || (ctx.occupied_registers & (1 << RSI));
int save_rdx = argcount >= 3 || (ctx.occupied_registers & (1 << RDX));
int save_rcx = argcount >= 4 || (ctx.occupied_registers & (1 << RCX));
int save_r8 = argcount >= 5 || (ctx.occupied_registers & (1 << 8));
int save_r9 = argcount >= 6 || (ctx.occupied_registers & (1 << 9));
int save_r10 = ctx.occupied_registers & (1 << 10);
int save_r11 = ctx.occupied_registers & (1 << 11);
if (save_rdi && argcount >= 1) sysemit_mov_save(&ctx, RDI, args[0]);
if (save_rdi && argcount < 1) sysemit_pushreg(&ctx, RDI);
if (save_rsi && argcount >= 2) sysemit_mov_save(&ctx, RSI, args[1]);
if (save_rsi && argcount < 2) sysemit_pushreg(&ctx, RSI);
if (save_rdx && argcount >= 3) sysemit_mov_save(&ctx, RDX, args[2]);
if (save_rdx && argcount < 3) sysemit_pushreg(&ctx, RDX);
if (save_rcx && argcount >= 4) sysemit_mov_save(&ctx, RCX, args[3]);
if (save_rcx && argcount < 4) sysemit_pushreg(&ctx, RCX);
if (save_r8 && argcount >= 5) sysemit_mov_save(&ctx, 8, args[4]);
if (save_r8 && argcount < 5) sysemit_pushreg(&ctx, 8);
if (save_r9 && argcount >= 6) sysemit_mov_save(&ctx, 9, args[5]);
if (save_r9 && argcount < 6) sysemit_pushreg(&ctx, 9);
if (save_r10) sysemit_pushreg(&ctx, 10);
if (save_r11) sysemit_pushreg(&ctx, 11);
for (int32_t argo = argcount - 1; argo >= 5; argo--) {
janet_panic("nyi");
janet_formatb(buffer, "push ");
sysemit_operand(&ctx, args[argo], "\n");
{
uint32_t argcount = 0;
uint32_t *args = janet_sys_callargs(ir->instructions + j, &argcount);
JanetSysCallingConvention cc = instruction.call.calling_convention;
/* Set default calling convention based on context */
if (cc == JANET_SYS_CC_DEFAULT) {
cc = JANET_SYS_CC_X64_WINDOWS;
}
if (cc == JANET_SYS_CC_X64_SYSV) {
sysemit_sysv_call(&ctx, instruction, args, argcount);
} else if (cc == JANET_SYS_CC_X64_WINDOWS) {
sysemit_win64_call(&ctx, instruction, args, argcount);
}
janet_sfree(args);
break;
}
janet_sfree(args);
if (instruction.opcode == JANET_SYSOP_SYSCALL) {
sysemit_movreg(&ctx, RAX, instruction.call.callee);
janet_formatb(buffer, "syscall\n");
} else {
/* Save RAX to number of floating point args for varags - for now, always 0 :) */
janet_formatb(buffer, "mov rax, 0\n");
janet_formatb(buffer, "call ");
sysemit_operand(&ctx, instruction.call.callee, "\n");
}
if (instruction.call.flags & JANET_SYS_CALLFLAG_HAS_DEST) sysemit_movreg(&ctx, RAX, instruction.call.dest);
if (save_r11) sysemit_popreg(&ctx, 11);
if (save_r10) sysemit_popreg(&ctx, 10);
if (save_r9) sysemit_popreg(&ctx, 9);
if (save_r8) sysemit_popreg(&ctx, 8);
if (save_rcx) sysemit_popreg(&ctx, RCX);
if (save_rdx) sysemit_popreg(&ctx, RDX);
if (save_rsi) sysemit_popreg(&ctx, RSI);
if (save_rdi) sysemit_popreg(&ctx, RDI);
break;
// On a comparison, if next instruction is branch that reads from dest, combine into a single op.
}
}
}
/* End section .text */
janet_formatb(buffer, "section .rodata\n\n");
janet_formatb(buffer, "\nsection .rodata\n");
for (int32_t i = 0; i < linkage->ir_ordered->count; i++) {
JanetSysIR *ir = janet_unwrap_pointer(linkage->ir_ordered->data[i]);
@ -658,7 +741,7 @@ void janet_sys_ir_lower_to_x64(JanetSysIRLinkage *linkage, JanetBuffer *buffer)
for (uint32_t j = 0; j < ir->constant_count; j++) {
if (janet_checktype(ir->constants[j].value, JANET_STRING)) {
JanetString str = janet_unwrap_string(ir->constants[j].value);
janet_formatb(buffer, "\nCONST_%d_%u: db ", i, j);
janet_formatb(buffer, "CONST_%d_%u: db ", i, j);
/* Nasm syntax */
int in_string = 0;
for (int32_t ci = 0; ci < janet_string_length(str); ci++) {