diff --git a/examples/sysir/typeerr0.janet b/examples/sysir/typeerr0.janet deleted file mode 100644 index 581d885f..00000000 --- a/examples/sysir/typeerr0.janet +++ /dev/null @@ -1,55 +0,0 @@ -### typedef struct {float x; float y; float z;} Vec3; -### -### Vec3 addv(Vec3 a, Vec3 b) { -### Vec3 ret; -### ret.x = a.x + b.x; -### ret.y = a.y + b.y; -### ret.z = a.z + b.z; -### return ret; -### } - -(def ir-asm - '((link-name "addv_with_err") - (parameter-count 2) - # Types - (type-prim Real f32) - (type-struct Vec3 Real Real Real) - (type-pointer PReal Real) - - # Declarations - (bind position Vec3) - (bind velocity Vec3) - (bind next-position Vec3) - (bind dest Real) - (bind lhs Real) - (bind rhs Real) - (bind pdest PReal) - (bind plhs PReal) - (bind prhs PReal) - - # Code (has type errors) - (fgetp pdest next-position 0) - (fgetp plhs position 0) - (fgetp prhs velocity 0) - (add dest plhs prhs) - (store pdest dest) - - (fgetp pdest next-position 1) - (fgetp plhs position 1) - (fgetp prhs velocity 1) - (add dest lhs rhs) - (load lhs plhs) - (load rhs prhs) - (store pdest dest) - - (fgetp pdest next-position 2) - (fgetp plhs position 2) - (fgetp prhs velocity 2) - (add dest plhs prhs) - (store pdest dest) - - (return next-position))) - -(def ctx (sysir/context)) -(sysir/asm ctx ir-asm) -(print (sysir/to-c ctx)) diff --git a/src/core/sysir_x86.c b/src/core/sysir_x86.c index a8da07f1..73f1d944 100644 --- a/src/core/sysir_x86.c +++ b/src/core/sysir_x86.c @@ -52,31 +52,6 @@ #define REX_X 0x42 #define REX_B 0x41 -static const char *register_names[] = { - "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", - "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" -}; - -static const char *register_names_32[] = { - "eax", "ecx", "edx", "ebx", "rsp", "rbp", "esi", "edi", - "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d" -}; - -static const char *register_names_16[] = { - "ax", "cx", "dx", "bx", "sp", "bp", "si", "di", - "r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w" -}; - -static const char *register_names_8[] = { - "al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil", - "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b" -}; - -static const char *register_names_xmm[] = { - "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", - "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15" -}; - typedef enum { JANET_SYSREG_8, JANET_SYSREG_16, @@ -103,6 +78,9 @@ typedef struct { JanetSysIRLinkage *linkage; JanetSysIR *ir; JanetBuffer *buffer; + JanetBuffer *constant_data; /* A buffer of constants for RIP-relative addressing to point to */ + uint32_t *v_rip_indicies; /* An array of pointers of all emitted addresses to patch at end. */ + JanetTable *constant_to_data; /* Table mapping constants to index into v_constant_data (dedupe constants) */ x64Reg *regs; /* Map IR virtual registers to hardware register or stack offset */ JanetSysTypeLayout *layouts; JanetSysTypeLayout *ir_layouts; @@ -317,6 +295,30 @@ static int operand_isreg(JanetSysx64Context *ctx, uint32_t o, uint32_t regindex) return reg.index == regindex; } +/* Visit a constant and return the index into the constant data buffer. */ +static uint32_t janet_x64_constant(JanetSysx64Context *ctx, uint32_t const_index) { + Janet key = janet_wrap_number((double) const_index); + Janet check = janet_table_get(ctx->constant_to_data, key); + if (janet_checktype(check, JANET_NUMBER)) { + /* Constant has been seen before */ + return (uint32_t) janet_unwrap_integer(check); + } + JanetSysConstant jsc = ctx->ir->constants[const_index]; + JanetSysTypeInfo tinfo = ctx->linkage->type_defs[jsc.type]; + /* TODO - check type and alignment for data types beyond pointers such as large struct and other immediates */ + uint32_t index = ctx->constant_data->count; + switch (janet_type(jsc.value)) { + default: + janet_assert(0, "cannot emit constant"); + break; + case JANET_STRING: + janet_assert(tinfo.prim == JANET_PRIM_POINTER, "expected pointer type for string constant"); + janet_buffer_push_string(ctx->constant_data, janet_unwrap_string(jsc.value)); + break; + } + return index; +} + /* * Machine code emission */ @@ -330,7 +332,7 @@ static const InstrChunk empty_chunk = { 0, 0 }; static void i_chunk(JanetSysx64Context *C, InstrChunk c) { for (int i = 0; i < c.bytes; i++) { - janet_formatb(C->buffer, "0x%.2X,", c.data & 0xFF); + janet_buffer_push_u8(C->buffer, c.data & 0xFF); c.data = c.data >> 8; } } @@ -347,22 +349,17 @@ static void i_combine(JanetSysx64Context *C, assert(mod_reg_rm.bytes < 3); assert(scaled_index.bytes < 2); assert(opcode < 512); - janet_buffer_push_cstring(C->buffer, "db "); i_chunk(C, prefix); if (opcode >= 256) { - janet_formatb(C->buffer, "0x%.2X,", 0x0Fu); + janet_buffer_push_u8(C->buffer, 0x0Fu); opcode -= 256; } - janet_formatb(C->buffer, "0x%.2X,", opcode); + janet_buffer_push_u8(C->buffer, opcode); i_chunk(C, mod_reg_rm); i_chunk(C, scaled_index); i_chunk(C, displacement); i_chunk(C, immediate); - if (msg) { - janet_formatb(C->buffer, "; %s\n", msg); - } else { - janet_buffer_push_cstring(C->buffer, "\n"); - } + (void) msg; } typedef enum { @@ -380,16 +377,19 @@ static void e_mov_ext(JanetSysx64Context *ctx, x64Reg d, x64Reg s, MoveMode mm, /* src is a constant */ if (s.storage == JANET_SYSREG_CONSTANT) { + //uint32_t disp = janet_x64_constant(ctx, s.index); if (d.index >= 8) rex |= REX_R; if (d.kind >= JANET_SYSREG_64) rex |= REX_W; Janet c = ctx->ir->constants[s.index].value; int32_t imm = 0; uint64_t imm64 = 0; int is64 = 0; + //int isRipRel = 0; InstrChunk dispchunk = empty_chunk; if (janet_checktype(c, JANET_STRING)) { is64 = 1; - imm64 = (uint64_t) janet_unwrap_pointer(c); + imm64 = (uint64_t) janet_unwrap_pointer(c);// janet_x64_constant(ctx, s.index); + //isRipRel = 1; } else if (s.kind >= JANET_SYSREG_64) { is64 = 1; imm64 = janet_unwrap_u64(c); @@ -407,7 +407,7 @@ static void e_mov_ext(JanetSysx64Context *ctx, x64Reg d, x64Reg s, MoveMode mm, } /* encode movabsq */ rex |= REX_W; - imm64 = 0xDEADBEEFCAFEBABEULL; + // imm64 = 0xDEADBEEFCAFEBABEULL; opcode = 0xB8; opcode += (d.index & 7); if (d.index >= 8) rex |= REX_R; @@ -496,7 +496,6 @@ static void e_mov_ext(JanetSysx64Context *ctx, x64Reg d, x64Reg s, MoveMode mm, if (!rex) prefix.bytes = 0; InstrChunk modregrm = {1, mod_rm}; i_combine(ctx, prefix, opcode, modregrm, empty_chunk, dispchunk, empty_chunk, msg); - //janet_formatb(ctx->buffer, ";mov %s <- %s, mode=%d, %s\n", register_names[d.index], register_names[s.index], mm, sizestr); } static void e_mov(JanetSysx64Context *ctx, uint32_t dest, uint32_t src, const char *msg) { @@ -516,9 +515,11 @@ static void e_fn_prefix(JanetSysx64Context *ctx, int32_t stack) { int b = (stack >> 8) & 0xFF; int c = (stack >> 16) & 0xFF; int d = (stack >> 24) & 0xFF; - janet_formatb(ctx->buffer, "db 0x55, 0x48, 0x89, 0xe5, 0x48, 0x81, 0xec, 0x%.2X, 0x%.2X, 0x%2X, 0x%2X ; function prefix\n", a, b, c, d); + uint8_t bytes[] = {0x55, 0x48, 0x89, 0xe5, 0x48, 0x81, 0xec, a, b, c, d}; + janet_buffer_push_bytes(ctx->buffer, bytes, sizeof(bytes)); } else { - janet_formatb(ctx->buffer, "db 0x55, 0x48, 0x89, 0xe5, 0x48, 0x83, 0xec, 0x%.2X ; function prefix\n", stack); + uint8_t bytes[] = {0x55, 0x48, 0x89, 0xe5, 0x48, 0x83, 0xec, stack}; + janet_buffer_push_bytes(ctx->buffer, bytes, sizeof(bytes)); } } @@ -526,9 +527,11 @@ static void e_pushreg(JanetSysx64Context *ctx, uint32_t reg) { assert(reg < 16); if (reg >= 8) { /* Use REX prefix */ - janet_formatb(ctx->buffer, "db 0x41, 0x%.2X ; push %s\n", 0x50 + (reg - 8), register_names[reg]); + uint8_t bytes[] = {0x41, 0x50 + (reg - 8)}; + janet_buffer_push_bytes(ctx->buffer, bytes, sizeof(bytes)); } else { - janet_formatb(ctx->buffer, "db 0x%.2X ; push %s\n", 0x50 + reg, register_names[reg]); + uint8_t bytes[] = {0x50 + reg}; + janet_buffer_push_bytes(ctx->buffer, bytes, sizeof(bytes)); } } @@ -536,15 +539,18 @@ static void e_popreg(JanetSysx64Context *ctx, uint32_t reg) { assert(reg < 16); if (reg >= 8) { /* Use REX prefix */ - janet_formatb(ctx->buffer, "db 0x41, 0x%.2X ; pop %s\n", 0x58 + (reg - 8), register_names[reg]); + uint8_t bytes[] = {0x41, 0x58 + (reg - 8)}; + janet_buffer_push_bytes(ctx->buffer, bytes, sizeof(bytes)); } else { - janet_formatb(ctx->buffer, "db 0x%.2X ; pop %s\n", 0x58 + reg, register_names[reg]); + uint8_t bytes[] = {0x58 + reg}; + janet_buffer_push_bytes(ctx->buffer, bytes, sizeof(bytes)); } } static void e_fn_suffix(JanetSysx64Context *ctx) { /* leave, ret */ - janet_formatb(ctx->buffer, "db 0xc9, 0xc3 ; function suffix\n"); + uint8_t bytes[] = {0xc9, 0xc3}; + janet_buffer_push_bytes(ctx->buffer, bytes, sizeof(bytes)); } /* Assembly emission */ @@ -557,47 +563,18 @@ static x64Reg mk_tmpreg(JanetSysx64Context *ctx, uint32_t src) { return tempreg; } -static void sysemit_reg(JanetSysx64Context *ctx, x64Reg reg, const char *after) { - const char *sizestr = sysemit_sizestr_reg(reg); - if (reg.storage == JANET_SYSREG_STACK) { - // TODO - use LEA for parameters larger than a qword - janet_formatb(ctx->buffer, "%s [rbp-%u]", sizestr, reg.index); - } else if (reg.storage == JANET_SYSREG_STACK_PARAMETER) { - // TODO - use LEA for parameters larger than a qword - janet_formatb(ctx->buffer, "%s [rbp+%u]", sizestr, reg.index); - } else if (reg.kind == JANET_SYSREG_64) { - janet_formatb(ctx->buffer, "%s", register_names[reg.index]); - } else if (reg.kind == JANET_SYSREG_32) { - janet_formatb(ctx->buffer, "%s", register_names_32[reg.index]); - } else if (reg.kind == JANET_SYSREG_16) { - janet_formatb(ctx->buffer, "%s", register_names_16[reg.index]); - } else if (reg.kind == JANET_SYSREG_8) { - janet_formatb(ctx->buffer, "%s", register_names_8[reg.index]); - } else { - janet_formatb(ctx->buffer, "%s", register_names_xmm[reg.index]); - } - if (after) janet_buffer_push_cstring(ctx->buffer, after); +static void sysemit_movreg(JanetSysx64Context *ctx, uint32_t regdest, uint32_t src) { + if (operand_isreg(ctx, src, regdest)) return; + x64Reg tempreg = mk_tmpreg(ctx, src); + tempreg.index = regdest; + e_mov_ext(ctx, tempreg, to_reg(ctx, src), MOV_FLAT, "sysemit_movreg"); } -static void sysemit_operand(JanetSysx64Context *ctx, uint32_t o, const char *after) { - if (o <= JANET_SYS_MAX_OPERAND) { - sysemit_reg(ctx, ctx->regs[o], NULL); - } else { - /* Constant */ - uint32_t index = o - JANET_SYS_CONSTANT_PREFIX; - Janet c = ctx->ir->constants[index].value; - // TODO - do this properly - if (janet_checktype(c, JANET_STRING)) { - janet_formatb(ctx->buffer, "CONST_%d_%u", ctx->ir_index, index); - } else { - // TODO - do this properly too. - // Also figure out how to load large constants to a temporary register - // In x64, only move to register is allowed to take a 64 bit immediate, so - // our methodology here changes based on what kind of operand we need. - janet_formatb(ctx->buffer, "%V", c); - } - } - if (after) janet_buffer_push_cstring(ctx->buffer, after); +static void sysemit_movfromreg(JanetSysx64Context *ctx, uint32_t dest, uint32_t srcreg) { + if (operand_isreg(ctx, dest, srcreg)) return; + x64Reg tempreg = mk_tmpreg(ctx, dest); + tempreg.index = srcreg; + e_mov_ext(ctx, ctx->regs[dest], tempreg, MOV_FLAT, "move from specific register"); } /* A = A op B */ @@ -607,14 +584,16 @@ static void sysemit_binop(JanetSysx64Context *ctx, const char *op, uint32_t dest x64Reg tempreg = mk_tmpreg(ctx, dest); x64Reg srcreg = ctx->regs[src]; e_mov_ext(ctx, tempreg, srcreg, MOV_FLAT, "mem -> RAX temp"); - janet_formatb(ctx->buffer, "%s ", op); - sysemit_operand(ctx, dest, ", "); - sysemit_reg(ctx, tempreg, "\n"); - } else { - janet_formatb(ctx->buffer, "%s ", op); - sysemit_operand(ctx, dest, ", "); - sysemit_operand(ctx, src, "\n"); - } + } + janet_formatb(ctx->buffer, "%s ", op); + //sysemit_operand(ctx, dest, ", "); + //sysemit_operand(ctx, src, "\n"); +} + +/* Dest = LHS op RHS */ +static void sysemit_threeop(JanetSysx64Context *ctx, const char *op, uint32_t dest, uint32_t lhs, uint32_t rhs) { + e_mov(ctx, dest, lhs, op); + sysemit_binop(ctx, op, dest, rhs); } /* dest = src[0] */ @@ -684,52 +663,15 @@ static void sysemit_store(JanetSysx64Context *ctx, uint32_t dest, uint32_t src) } } -static void sysemit_movreg(JanetSysx64Context *ctx, uint32_t regdest, uint32_t src) { - if (operand_isreg(ctx, src, regdest)) return; - x64Reg tempreg = mk_tmpreg(ctx, src); - tempreg.index = regdest; - e_mov_ext(ctx, tempreg, to_reg(ctx, src), MOV_FLAT, "sysemit_movreg"); -} - -static void sysemit_movfromreg(JanetSysx64Context *ctx, uint32_t dest, uint32_t srcreg) { - if (operand_isreg(ctx, dest, srcreg)) return; - x64Reg tempreg = mk_tmpreg(ctx, dest); - tempreg.index = srcreg; - e_mov_ext(ctx, ctx->regs[dest], tempreg, MOV_FLAT, "move from specific register"); -} - /* Move a value to a register, and save the contents of the old register on the stack */ static void sysemit_mov_save(JanetSysx64Context *ctx, uint32_t regdest, uint32_t src) { e_pushreg(ctx, regdest); if (operand_isreg(ctx, src, regdest)) return; x64Reg tempreg = mk_tmpreg(ctx, src); tempreg.index = regdest; - janet_formatb(ctx->buffer, "; mov save %s <- %u\n", register_names[regdest], src); e_mov_ext(ctx, tempreg, to_reg(ctx, src), MOV_FLAT, "mov save"); } -static void sysemit_threeop(JanetSysx64Context *ctx, const char *op, uint32_t dest, uint32_t lhs, uint32_t rhs) { - e_mov(ctx, dest, lhs, op); - sysemit_binop(ctx, op, dest, rhs); -} - -static void sysemit_threeop_nodeststack(JanetSysx64Context *ctx, const char *op, uint32_t dest, uint32_t lhs, - uint32_t rhs) { - if (operand_isstack(ctx, dest)) { - sysemit_movreg(ctx, RAX, lhs); - x64Reg tempreg; - tempreg.kind = get_slot_regkind(ctx, dest); - tempreg.storage = JANET_SYSREG_REGISTER; - tempreg.index = RAX; - janet_formatb(ctx->buffer, "%s ", op); - sysemit_reg(ctx, tempreg, ", "); - sysemit_operand(ctx, lhs, "\n"); - sysemit_movfromreg(ctx, dest, RAX); - } else { - sysemit_threeop(ctx, op, dest, lhs, rhs); - } -} - static void sysemit_three_inst(JanetSysx64Context *ctx, const char *op, JanetSysInstruction instruction) { sysemit_threeop(ctx, op, instruction.three.dest, instruction.three.lhs, instruction.three.rhs); } @@ -778,7 +720,7 @@ static int sysemit_comp(JanetSysx64Context *ctx, uint32_t index, /* Zero the upper bits */ sysemit_binop(ctx, "xor", instruction.three.dest, instruction.three.dest); } - janet_formatb(ctx->buffer, "%s %s\n", set, register_names_8[instruction.three.dest]); + //janet_formatb(ctx->buffer, "%s %s\n", set, register_names_8[instruction.three.dest]); return 0; } } @@ -846,7 +788,7 @@ static void sysemit_sysv_call(JanetSysx64Context *ctx, JanetSysInstruction instr 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"); + //sysemit_operand(ctx, args[argo], "\n"); } if (instruction.opcode == JANET_SYSOP_SYSCALL) { sysemit_movreg(ctx, RAX, instruction.call.callee); @@ -855,7 +797,7 @@ static void sysemit_sysv_call(JanetSysx64Context *ctx, JanetSysInstruction instr /* Save RAX to number of floating point args for varags - for now, always 0 :) */ janet_formatb(buffer, "db 0x48, 0x31, 0xc0 ; xor rax, rax\n"); janet_formatb(buffer, "call "); - sysemit_operand(ctx, instruction.call.callee, "\n"); + //sysemit_operand(ctx, instruction.call.callee, "\n"); } if (save_r11) e_popreg(ctx, 11); if (save_r10) e_popreg(ctx, 10); @@ -895,7 +837,7 @@ static void sysemit_win64_call(JanetSysx64Context *ctx, JanetSysInstruction inst janet_formatb(buffer, "syscall\n"); } else { janet_formatb(buffer, "call "); - sysemit_operand(ctx, instruction.call.callee, "\n"); + //sysemit_operand(ctx, instruction.call.callee, "\n"); } if (argcount > 4) { janet_formatb(buffer, "add rsp, %u\n", 8 * (argcount - 4)); @@ -909,12 +851,42 @@ static void sysemit_win64_call(JanetSysx64Context *ctx, JanetSysInstruction inst if (instruction.call.flags & JANET_SYS_CALLFLAG_HAS_DEST) sysemit_movfromreg(ctx, instruction.call.dest, RAX); } +static void emit_nasm_string(JanetBuffer *buffer, const uint8_t *str, int32_t len) { + /* Nasm syntax */ + int in_string = 0; + for (int32_t ci = 0; ci < len; ci++) { + int c = str[ci]; + if (c < 32) { + if (in_string) { + janet_formatb(buffer, "\", %d", c); + } else { + janet_formatb(buffer, ci ? ", %d" : "%d", c); + } + in_string = 0; + } else { + if (!in_string) { + janet_buffer_push_cstring(buffer, ci ? ", \"" : "\""); + } + janet_buffer_push_u8(buffer, c); + in_string = 1; + } + } + if (!in_string) { + janet_buffer_push_cstring(buffer, ", 0\n"); + } else { + janet_buffer_push_cstring(buffer, "\", 0\n"); + } +} + void janet_sys_ir_lower_to_x64(JanetSysIRLinkage *linkage, JanetSysTarget target, JanetBuffer *buffer) { /* Partially setup context */ JanetSysx64Context ctx; ctx.linkage = linkage; ctx.buffer = buffer; + ctx.constant_data = janet_buffer(0); + ctx.v_rip_indicies = NULL; + ctx.constant_to_data = janet_table(0); ctx.layouts = janet_smalloc(linkage->type_def_count * sizeof(JanetSysTypeLayout)); for (uint32_t i = 0; i < linkage->type_def_count; i++) { ctx.layouts[i] = get_x64layout(linkage->type_defs[i]); @@ -1018,7 +990,7 @@ void janet_sys_ir_lower_to_x64(JanetSysIRLinkage *linkage, JanetSysTarget target sysemit_three_inst(&ctx, "sub", instruction); break; case JANET_SYSOP_MULTIPLY: - sysemit_threeop_nodeststack(&ctx, "imul", instruction.three.dest, + sysemit_threeop(&ctx, "imul", instruction.three.dest, instruction.three.lhs, instruction.three.rhs); break; case JANET_SYSOP_DIVIDE: @@ -1073,7 +1045,7 @@ void janet_sys_ir_lower_to_x64(JanetSysIRLinkage *linkage, JanetSysTarget target case JANET_SYSOP_BRANCH_NOT: janet_formatb(buffer, "test "); // TODO - ensure branch condition is not a const - sysemit_operand(&ctx, instruction.branch.cond, ", 0\n"); + //sysemit_operand(&ctx, instruction.branch.cond, ", 0\n"); janet_formatb(buffer, "%s label_%d_%u\n", instruction.opcode == JANET_SYSOP_BRANCH ? "jnz" : "jz", @@ -1103,39 +1075,20 @@ void janet_sys_ir_lower_to_x64(JanetSysIRLinkage *linkage, JanetSysTarget target } /* End section .text */ + /* rodata */ janet_formatb(buffer, "\nsection .rodata\n"); + janet_formatb(buffer, "CONST_DATA: db "); + emit_nasm_string(buffer, ctx.constant_data->data, ctx.constant_data->count); + /* old rodata */ for (int32_t i = 0; i < linkage->ir_ordered->count; i++) { JanetSysIR *ir = janet_unwrap_pointer(linkage->ir_ordered->data[i]); /* Emit constant strings */ for (uint32_t j = 0; j < ir->constant_count; j++) { if (janet_checktype(ir->constants[j].value, JANET_STRING)) { + janet_formatb(buffer, "CONST_%d_%d: db ", i, j); JanetString str = janet_unwrap_string(ir->constants[j].value); - 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++) { - int c = str[ci]; - if (c < 32) { - if (in_string) { - janet_formatb(buffer, "\", %d", c); - } else { - janet_formatb(buffer, ci ? ", %d" : "%d", c); - } - in_string = 0; - } else { - if (!in_string) { - janet_buffer_push_cstring(buffer, ci ? ", \"" : "\""); - } - janet_buffer_push_u8(buffer, c); - in_string = 1; - } - } - if (!in_string) { - janet_buffer_push_cstring(buffer, ", 0\n"); - } else { - janet_buffer_push_cstring(buffer, "\", 0\n"); - } + emit_nasm_string(buffer, str, janet_string_length(str)); } } } diff --git a/test/helper.janet b/test/helper.janet index 4a6c8596..511d8f12 100644 --- a/test/helper.janet +++ b/test/helper.janet @@ -27,7 +27,7 @@ (if x (when is-verbose (eprintf "\e[32m✔\e[0m %s: %s: %v" line-info (describe e) x)) (do - (eprintf "\e[31m✘\e[0m %s: %s: %v" line-info (describe e) x) (eflush))) + (eprintf "\e[31m✘\e[0m %s: %s: %v" line-info (string e) x) (eflush))) x) (defn skip-asserts diff --git a/test/suite-sysir.janet b/test/suite-sysir.janet index 1cb2bd77..06f743a9 100644 --- a/test/suite-sysir.janet +++ b/test/suite-sysir.janet @@ -24,4 +24,27 @@ (use ../examples/sysir/frontend) (assert true) # smoke test +(def janet (dyn *executable*)) +(def run (filter next (string/split " " (os/getenv "SUBRUN" "")))) + +(defn do-expect-directory + "Iterate a directory, evaluating all scripts in the directory. Assert that the captured output of the script + is as expected according to a matching .expect file." + [dir] + (each path (sorted (os/dir dir)) + (when (string/has-suffix? ".janet" path) + (def fullpath (string dir "/" path)) + (def proc (os/spawn [;run janet fullpath] :p {:out :pipe :err :out})) + (def buff @"") + (var ret-code nil) + (ev/gather + (while (ev/read (proc :out) 4096 buff)) + (set ret-code (os/proc-wait proc))) + (def expect-file (string dir "/" path ".expect")) + (def expected-out (slurp expect-file)) + (assert (= (string/trim expected-out) (string/trim buff)) + (string "\nfile: " fullpath "\nexpected:\n======\n" expected-out "\n======\ngot:\n======\n" buff "\n======\n"))))) + +(do-expect-directory "test/sysir") + (end-suite) diff --git a/examples/sysir/arrays1.janet b/test/sysir/arrays1.janet similarity index 93% rename from examples/sysir/arrays1.janet rename to test/sysir/arrays1.janet index b51eafd6..4f9642ef 100644 --- a/examples/sysir/arrays1.janet +++ b/test/sysir/arrays1.janet @@ -25,4 +25,4 @@ (sysir/asm ctx types-asm) (sysir/asm ctx add-asm) (sysir/asm ctx sub-asm) -(print (sysir/to-c ctx)) +(printf "%.99j" (sysir/to-ir ctx)) diff --git a/test/sysir/arrays1.janet.expect b/test/sysir/arrays1.janet.expect new file mode 100644 index 00000000..134285e7 --- /dev/null +++ b/test/sysir/arrays1.janet.expect @@ -0,0 +1 @@ +@[@[(type-prim Double f64) (type-array BigVec Double 100)] @[(parameter-count 0)] @[(link-name "add_vector") (parameter-count 2) (type-bind 0 BigVec) (type-bind 1 BigVec) (type-bind 2 BigVec) (add 2 0 1) (return 2)] @[(link-name "sub_vector") (parameter-count 2) (type-bind 0 BigVec) (type-bind 1 BigVec) (type-bind 2 BigVec) (subtract 2 0 1) (return 2)]] diff --git a/examples/sysir/arrays2.janet b/test/sysir/arrays2.janet similarity index 74% rename from examples/sysir/arrays2.janet rename to test/sysir/arrays2.janet index 41f089e4..6aafe8dd 100644 --- a/examples/sysir/arrays2.janet +++ b/test/sysir/arrays2.janet @@ -16,8 +16,7 @@ (def ctx (sysir/context)) (sysir/asm ctx ir-asm) -(print (sysir/to-c ctx)) -(printf "%.99M" (sysir/to-ir ctx)) -(print (sysir/scalarize ctx)) -(printf "%.99M" (sysir/to-ir ctx)) +(printf "%j" (sysir/to-ir ctx)) +(sysir/scalarize ctx) +(printf "%j" (sysir/to-ir ctx)) (print (sysir/to-c ctx)) diff --git a/test/sysir/arrays2.janet.expect b/test/sysir/arrays2.janet.expect new file mode 100644 index 00000000..1064d99b --- /dev/null +++ b/test/sysir/arrays2.janet.expect @@ -0,0 +1,66 @@ +@[@[(type-prim Double f64) (type-array BigVec Double 100) (type-pointer BigVecP BigVec)] @[(link-name "add_vectorp") (parameter-count 2) (type-bind 0 BigVecP) (type-bind 1 BigVecP) (type-bind 2 BigVecP) (add 2 0 1) (return 2)]] +@[@[(type-prim Double f64) (type-array BigVec Double 100) (type-pointer BigVecP BigVec)] @[(link-name "add_vectorp") (parameter-count 2) (type-bind 0 BigVecP) (type-bind 1 BigVecP) (type-bind 2 BigVecP) (type-bind 3 U32Index) (type-bind 5 PointerTo) (type-bind 6 PointerTo) (type-bind 7 PointerTo) (type-bind 4 Boolean) (load 3 [U32Index 0]) (label 7) (gte 4 3 [U32Index 0]) (branch 4 21) (apgetp 5 0 3) (apgetp 6 1 3) (apgetp 7 2 3) (add 7 5 6) (add 3 3 [U32Index 1]) (jump 7) (label 21) (return 2)]] +#include +#include +#include +#include +#include +#include +#include +#define _t0 void + +#line 6 +typedef double _t1; +#line 7 +typedef struct { _t1 els[100]; } _t2; +#line 8 +typedef _t2 *_t3; + + +_t3 add_vectorp(_t3 _r0, _t3 _r1) +{ + _t3 _r2; + _t4 _r3; + _t5 _r4; + _t6 _r5; + _t6 _r6; + _t6 _r7; + +#line 6 +#line 7 +#line 8 +#line 11 +#line 12 +#line 13 +#line 14 +#line 14 +#line 14 +#line 14 +#line 14 +#line 14 + _r3 = *(0); +#line 14 + +_label_0: +#line 14 + _r4 = _r3 > 0; +#line 14 + if (_r4) goto _label_1; +#line 14 + _r5 = &(_r0->els[_r3]); +#line 14 + _r6 = &(_r1->els[_r3]); +#line 14 + _r7 = &(_r2->els[_r3]); +#line 14 + _r7 = _r5 + _r6; +#line 14 + _r3 = _r3 + 1; +#line 14 + goto _label_0; +#line 14 + +_label_1: +#line 15 + return _r2; +} diff --git a/examples/sysir/basic1.janet b/test/sysir/basic1.janet similarity index 74% rename from examples/sysir/basic1.janet rename to test/sysir/basic1.janet index 73193a80..b9b6eef2 100644 --- a/examples/sysir/basic1.janet +++ b/test/sysir/basic1.janet @@ -5,7 +5,7 @@ (type-prim Int s32) (type-prim Double f64) (type-struct MyPair 0 1) - (type-pointer PInt 0) + (type-pointer PInt Int) (type-array DoubleArray 1 1024) # Declarations @@ -18,14 +18,14 @@ (bind 6 MyPair) # Code - (constant 0 10) - (constant 0 21) + (move 0 (Int 10)) + (move 0 (Int 21)) :location (add 2 1 0) - (constant 3 1.77) - (call 3 sin 3) + (move 3 (Double 1.77)) + (call :default 3 (PInt sin) 3) (cast bob 2) - (call :default bob test_function) + (call :default bob (PInt test_function)) (add 5 bob 3) (jump :location) (return 5))) diff --git a/test/sysir/basic1.janet.expect b/test/sysir/basic1.janet.expect new file mode 100644 index 00000000..e875ee50 --- /dev/null +++ b/test/sysir/basic1.janet.expect @@ -0,0 +1,71 @@ +#include +#include +#include +#include +#include +#include +#include +#define _t0 void + +#line 5 +typedef int32_t _t1; +#line 6 +typedef double _t2; +#line 7 +typedef struct { + _t0 _f0; + _t1 _f1; +} _t3; +#line 8 +typedef _t1 *_t4; +#line 9 +typedef struct { _t1 els[1024]; } _t5; + + +_t2 test_function() +{ + _t1 _r0; + _t1 _r1; + _t1 _r2; + _t2 _r3; + _t2 _r4; + _t2 _r5; + _t3 _r6; + +#line 5 +#line 6 +#line 7 +#line 7 +#line 8 +#line 9 +#line 12 +#line 13 +#line 14 +#line 15 +#line 16 +#line 17 +#line 18 +#line 21 + _r0 = 10; +#line 22 + _r0 = 21; + +_label_0: +#line 24 + _r2 = _r1 + _r0; +#line 25 + _r3 = 1.77; +#line 26 + _r3 = sin(_r3); +#line 26 +#line 27 + _r4 = (_t2) _r2; +#line 28 + _r4 = test_function(); +#line 29 + _r5 = _r4 + _r3; +#line 30 + goto _label_0; +#line 31 + return _r5; +} diff --git a/examples/sysir/basic2.janet b/test/sysir/basic2.janet similarity index 100% rename from examples/sysir/basic2.janet rename to test/sysir/basic2.janet diff --git a/test/sysir/basic2.janet.expect b/test/sysir/basic2.janet.expect new file mode 100644 index 00000000..1634764a --- /dev/null +++ b/test/sysir/basic2.janet.expect @@ -0,0 +1 @@ +nope diff --git a/test/sysir/smoke.janet b/test/sysir/smoke.janet new file mode 100644 index 00000000..2ed187c3 --- /dev/null +++ b/test/sysir/smoke.janet @@ -0,0 +1 @@ +(print "hello") diff --git a/test/sysir/smoke.janet.expect b/test/sysir/smoke.janet.expect new file mode 100644 index 00000000..ce013625 --- /dev/null +++ b/test/sysir/smoke.janet.expect @@ -0,0 +1 @@ +hello