mirror of
				https://github.com/janet-lang/janet
				synced 2025-10-31 15:43:01 +00:00 
			
		
		
		
	Add tool that lets us more easily compare compilation paths.
Compare: IR -> C -> x64 vs. IR -> x64
This commit is contained in:
		| @@ -57,11 +57,11 @@ | ||||
| (defsys test_arrays:myvec [a:myvec b:myvec] | ||||
|   (return (+ a b))) | ||||
|  | ||||
| (defsys make_array:myvec [] | ||||
| '(defsys make_array:myvec [] | ||||
|   (def vec:myvec [0 0 0 0]) | ||||
|   (return vec)) | ||||
|  | ||||
| (defsys make_mat:mymat [] | ||||
| '(defsys make_mat:mymat [] | ||||
|   (def mat:mymat [[1 0 0 0] [0 1 0 0] [0 0 1 0] [0 0 0 1]]) | ||||
|   (return mat)) | ||||
|  | ||||
|   | ||||
							
								
								
									
										25
									
								
								examples/sysir/x64.janet
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								examples/sysir/x64.janet
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | ||||
| (use ./frontend) | ||||
|  | ||||
| (defn-external printf:int [fmt:pointer x:int]) | ||||
| (defn-external exit:void [x:int]) | ||||
|  | ||||
| (defsys doloop [x:int y:int] | ||||
|   (var i:int x) | ||||
|   #(printf "i = %d\n" i) | ||||
|   (while (< i y) | ||||
|     (set i (+ 1 i)) | ||||
|     (printf "i = %d\n" i)) | ||||
|   (return x)) | ||||
|  | ||||
| (defsys _start:void [] | ||||
|   (doloop 10 20) | ||||
|   (exit (the int 0)) | ||||
|   (return)) | ||||
|  | ||||
| (defn main [& args] | ||||
|   (def [_ what] args) | ||||
|   (dump) | ||||
|   (eprint "MODE: " what) | ||||
|   (case what | ||||
|     "c" (dumpc) | ||||
|     "x64" (dumpx64))) | ||||
| @@ -204,6 +204,8 @@ void assign_registers(JanetSysx64Context *ctx) { | ||||
|                     /* TODO check sizing and alignment */ | ||||
|                     ctx->regs[i].storage = JANET_SYSREG_STACK_PARAMETER; | ||||
|                     ctx->regs[i].index = (i - 6) * 8 + 16; | ||||
|                 } else { | ||||
|                     assigned |= 1 << (ctx->regs[i].index); | ||||
|                 } | ||||
|             } else if (cc == JANET_SYS_CC_X64_WINDOWS) { | ||||
|                 if (i == 0) ctx->regs[i].index = RCX; | ||||
| @@ -214,6 +216,8 @@ void assign_registers(JanetSysx64Context *ctx) { | ||||
|                     /* TODO check sizing and alignment */ | ||||
|                     ctx->regs[i].storage = JANET_SYSREG_STACK_PARAMETER; | ||||
|                     ctx->regs[i].index = (i - 4) * 8 + 16; | ||||
|                 } else { | ||||
|                     assigned |= 1 << (ctx->regs[i].index); | ||||
|                 } | ||||
|             } else { | ||||
|                 janet_panic("cannot assign registers for calling convention"); | ||||
| @@ -457,6 +461,51 @@ static int e_mov(JanetSysx64Context *ctx, uint32_t dest, uint32_t src) { | ||||
|     } | ||||
| } | ||||
|  | ||||
| /* | ||||
| push rbp | ||||
| mov rbp, rsp | ||||
| sub rsp, <stack> | ||||
| */ | ||||
| static void e_fn_prefix(JanetSysx64Context *ctx, int32_t stack) { | ||||
|     if (stack >= 128) { | ||||
|         int a = stack & 0xFF; | ||||
|         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); | ||||
|     } else { | ||||
|         janet_formatb(ctx->buffer, "db 0x55, 0x48, 0x89, 0xe5, 0x48, 0x83, 0xec, 0x%.2X ; function prefix\n", stack); | ||||
|     } | ||||
| } | ||||
|  | ||||
| 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]); | ||||
|     } else { | ||||
|         janet_formatb(ctx->buffer, "db 0x%.2X ; push %s\n", 0x50 + reg, register_names[reg]); | ||||
|     } | ||||
| } | ||||
|  | ||||
| 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]); | ||||
|     } else { | ||||
|         janet_formatb(ctx->buffer, "db 0x%.2X ; pop %s\n", 0x58 + reg, register_names[reg]); | ||||
|     } | ||||
| } | ||||
|  | ||||
| /* | ||||
| leave | ||||
| ret | ||||
| */ | ||||
| static void e_fn_suffix(JanetSysx64Context *ctx) { | ||||
|     janet_formatb(ctx->buffer, "db 0xc9, 0xc3 ; function suffix\n"); | ||||
| } | ||||
|  | ||||
| /* Assembly emission */ | ||||
|  | ||||
| static const char *sysemit_sizestr(x64RegKind kind) { | ||||
| @@ -715,7 +764,8 @@ static void sysemit_movfromreg(JanetSysx64Context *ctx, uint32_t dest, uint32_t | ||||
| } | ||||
|  | ||||
| static void sysemit_pushreg(JanetSysx64Context *ctx, uint32_t dest_reg) { | ||||
|     janet_formatb(ctx->buffer, "push %s\n", register_names[dest_reg]); | ||||
|     e_pushreg(ctx, dest_reg); | ||||
|     //janet_formatb(ctx->buffer, "push %s\n", register_names[dest_reg]); | ||||
| } | ||||
|  | ||||
| /* Move a value to a register, and save the contents of the old register on fhe stack */ | ||||
| @@ -725,7 +775,8 @@ static void sysemit_mov_save(JanetSysx64Context *ctx, uint32_t dest_reg, uint32_ | ||||
| } | ||||
|  | ||||
| static void sysemit_popreg(JanetSysx64Context *ctx, uint32_t dest_reg) { | ||||
|     janet_formatb(ctx->buffer, "pop %s\n", register_names[dest_reg]); | ||||
|     e_popreg(ctx, dest_reg); | ||||
|     //janet_formatb(ctx->buffer, "pop %s\n", register_names[dest_reg]); | ||||
| } | ||||
|  | ||||
| static void sysemit_threeop(JanetSysx64Context *ctx, const char *op, uint32_t dest, uint32_t lhs, uint32_t rhs) { | ||||
| @@ -759,11 +810,13 @@ static void sysemit_ret(JanetSysx64Context *ctx, uint32_t arg, int has_return) { | ||||
|     /* 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]); | ||||
|             e_popreg(ctx, k); | ||||
|             //janet_formatb(ctx->buffer, "pop %s\n", register_names[k]); | ||||
|         } | ||||
|     } | ||||
|     janet_formatb(ctx->buffer, "leave\n"); | ||||
|     janet_formatb(ctx->buffer, "ret\n"); | ||||
|     e_fn_suffix(ctx); | ||||
|     //janet_formatb(ctx->buffer, "leave\n"); | ||||
|     //janet_formatb(ctx->buffer, "ret\n"); | ||||
| } | ||||
|  | ||||
| static int sysemit_comp(JanetSysx64Context *ctx, uint32_t index, | ||||
| @@ -908,8 +961,9 @@ static void sysemit_win64_call(JanetSysx64Context *ctx, JanetSysInstruction inst | ||||
|     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"); | ||||
|         e_pushreg(ctx, args[argo]); | ||||
|         //janet_formatb(buffer, "push "); | ||||
|         //sysemit_operand(ctx, args[argo], "\n"); | ||||
|     } | ||||
|     if (instruction.opcode == JANET_SYSOP_SYSCALL) { | ||||
|         sysemit_movreg(ctx, RAX, instruction.call.callee); | ||||
| @@ -1000,11 +1054,13 @@ void janet_sys_ir_lower_to_x64(JanetSysIRLinkage *linkage, JanetSysTarget target | ||||
|         } else { | ||||
|             janet_formatb(buffer, "\n_section_%d:\n", i); | ||||
|         } | ||||
|         janet_formatb(buffer, "push rbp\nmov rbp, rsp\nsub rsp, %u\n", ctx.frame_size); | ||||
|         e_fn_prefix(&ctx, ctx.frame_size); | ||||
|         //janet_formatb(buffer, "push rbp\nmov rbp, rsp\nsub rsp, %u\n", ctx.frame_size); | ||||
|  | ||||
|         for (uint32_t k = 0; k < 32; k++) { | ||||
|             if (ctx.clobbered_registers & (1u << k)) { | ||||
|                 janet_formatb(buffer, "push %s\n", register_names[k]); | ||||
|                 e_pushreg(&ctx, k); | ||||
|                 //janet_formatb(buffer, "push %s\n", register_names[k]); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|   | ||||
							
								
								
									
										21
									
								
								tools/x64.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										21
									
								
								tools/x64.sh
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| #!/usr/bin/env bash | ||||
|  | ||||
| case "$2" in | ||||
| c) | ||||
|     rm temp.bin temp.o temp.nasm | ||||
|     valgrind build/janet "$@" > temp.c | ||||
|     gcc -nostdlib temp.c -c temp.o | ||||
|     ;; | ||||
| x64) | ||||
|     rm temp.bin temp.o temp.nasm | ||||
|     valgrind build/janet "$@" > temp.nasm | ||||
|     nasm -felf64 temp.nasm -l temp.lst -o temp.o | ||||
|     ;; | ||||
| *) | ||||
|     echo "Unknown mode $2" | ||||
|     exit | ||||
|     ;; | ||||
| esac | ||||
|  | ||||
| ld -o temp.bin -dynamic-linker /lib64/ld-linux-x86-64.so.2 -lc temp.o | ||||
| valgrind ./temp.bin | ||||
		Reference in New Issue
	
	Block a user
	 Calvin Rose
					Calvin Rose