x64: pass fn args
							parent
							
								
									0f4c5fb1c9
								
							
						
					
					
						commit
						1247718cbd
					
				|  | @ -48,6 +48,10 @@ enum Register { | ||||||
| 	r15 | 	r15 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | const ( | ||||||
|  | 	fn_arg_registers = [x64.Register.rdi, .rsi, .rdx, .rcx, .r8, .r9] | ||||||
|  | ) | ||||||
|  | 
 | ||||||
| /* | /* | ||||||
| rax // 0
 | rax // 0
 | ||||||
| 	rcx // 1
 | 	rcx // 1
 | ||||||
|  | @ -269,6 +273,17 @@ fn (mut g Gen) mov64(reg Register, val i64) { | ||||||
| 	g.write64(val) | 	g.write64(val) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | fn (mut g Gen) mov_from_reg(var_offset int, reg Register) { | ||||||
|  | 	// 89 7d fc                mov    DWORD PTR [rbp-0x4],edi
 | ||||||
|  | 	g.write8(0x89) | ||||||
|  | 	match reg { | ||||||
|  | 		.edi, .rdi { g.write8(0x7d) } | ||||||
|  | 		.rsi { g.write8(0x75) } | ||||||
|  | 		else { verror('mov_from_reg $reg') } | ||||||
|  | 	} | ||||||
|  | 	g.write8(0xff - var_offset + 1) | ||||||
|  | } | ||||||
|  | 
 | ||||||
| fn (mut g Gen) call(addr int) { | fn (mut g Gen) call(addr int) { | ||||||
| 	// Need to calculate the difference between current position (position after the e8 call)
 | 	// Need to calculate the difference between current position (position after the e8 call)
 | ||||||
| 	// and the function to call.
 | 	// and the function to call.
 | ||||||
|  | @ -378,7 +393,7 @@ fn (mut g Gen) mov(reg Register, val int) { | ||||||
| 		.eax, .rax { | 		.eax, .rax { | ||||||
| 			g.write8(0xb8) | 			g.write8(0xb8) | ||||||
| 		} | 		} | ||||||
| 		.edi { | 		.edi, .rdi { | ||||||
| 			g.write8(0xbf) | 			g.write8(0xbf) | ||||||
| 		} | 		} | ||||||
| 		.edx { | 		.edx { | ||||||
|  | @ -399,7 +414,6 @@ fn (mut g Gen) mov(reg Register, val int) { | ||||||
| 	g.write32(val) | 	g.write32(val) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* |  | ||||||
| fn (mut g Gen) mov_reg(a, b Register) { | fn (mut g Gen) mov_reg(a, b Register) { | ||||||
| 	match a { | 	match a { | ||||||
| 		.rbp { | 		.rbp { | ||||||
|  | @ -409,7 +423,7 @@ fn (mut g Gen) mov_reg(a, b Register) { | ||||||
| 		else {} | 		else {} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| */ | 
 | ||||||
| // generates `mov rbp, rsp`
 | // generates `mov rbp, rsp`
 | ||||||
| fn (mut g Gen) mov_rbp_rsp() { | fn (mut g Gen) mov_rbp_rsp() { | ||||||
| 	g.write8(0x48) | 	g.write8(0x48) | ||||||
|  | @ -423,15 +437,23 @@ pub fn (mut g Gen) register_function_address(name string) { | ||||||
| 	g.fn_addr[name] = addr | 	g.fn_addr[name] = addr | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub fn (mut g Gen) call_fn(name string) { | pub fn (mut g Gen) call_fn(node ast.CallExpr) { | ||||||
|  | 	name := node.name | ||||||
| 	println('call fn $name') | 	println('call fn $name') | ||||||
| 	if !name.contains('__') { |  | ||||||
| 		// return
 |  | ||||||
| 	} |  | ||||||
| 	addr := g.fn_addr[name] | 	addr := g.fn_addr[name] | ||||||
| 	if addr == 0 { | 	if addr == 0 { | ||||||
| 		verror('fn addr of `$name` = 0') | 		verror('fn addr of `$name` = 0') | ||||||
| 	} | 	} | ||||||
|  | 	// Copy values to registers (calling convention)
 | ||||||
|  | 	g.mov(.eax, 0) | ||||||
|  | 	for i in 0 .. node.args.len { | ||||||
|  | 		expr := node.args[i].expr | ||||||
|  | 		int_lit := expr as ast.IntegerLiteral | ||||||
|  | 		g.mov(fn_arg_registers[i], int_lit.val.int()) | ||||||
|  | 	} | ||||||
|  | 	if node.args.len > 6 { | ||||||
|  | 		verror('more than 6 args not allowed for now') | ||||||
|  | 	} | ||||||
| 	g.call(int(addr)) | 	g.call(int(addr)) | ||||||
| 	println('call $name $addr') | 	println('call $name $addr') | ||||||
| } | } | ||||||
|  | @ -473,7 +495,7 @@ fn (mut g Gen) expr(node ast.Expr) { | ||||||
| 				g.gen_print_from_expr(expr, it.name in ['println', 'eprintln']) | 				g.gen_print_from_expr(expr, it.name in ['println', 'eprintln']) | ||||||
| 				return | 				return | ||||||
| 			} | 			} | ||||||
| 			g.call_fn(it.name) | 			g.call_fn(it) | ||||||
| 		} | 		} | ||||||
| 		ast.FloatLiteral {} | 		ast.FloatLiteral {} | ||||||
| 		ast.Ident {} | 		ast.Ident {} | ||||||
|  | @ -585,23 +607,33 @@ fn (mut g Gen) for_stmt(node ast.ForStmt) { | ||||||
| 	g.write32_at(jump_addr, g.pos() - jump_addr - 4) // 4 is for "00 00 00 00"
 | 	g.write32_at(jump_addr, g.pos() - jump_addr - 4) // 4 is for "00 00 00 00"
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn (mut g Gen) fn_decl(it ast.FnDecl) { | fn (mut g Gen) fn_decl(node ast.FnDecl) { | ||||||
| 	is_main := it.name == 'main' | 	is_main := node.name == 'main' | ||||||
| 	println('saving addr $it.name $g.buf.len.hex()') | 	println('saving addr $node.name $g.buf.len.hex()') | ||||||
| 	if is_main { | 	if is_main { | ||||||
| 		g.save_main_fn_addr() | 		g.save_main_fn_addr() | ||||||
| 	} else { | 	} else { | ||||||
| 		g.register_function_address(it.name) | 		g.register_function_address(node.name) | ||||||
| 		// g.write32(SEVENS)
 | 		// g.write32(SEVENS)
 | ||||||
| 		g.push(.rbp) | 		g.push(.rbp) | ||||||
| 		g.mov_rbp_rsp() | 		g.mov_rbp_rsp() | ||||||
| 		// g.sub32(.rsp, 0x10)
 | 		// g.sub32(.rsp, 0x10)
 | ||||||
| 	} | 	} | ||||||
| 	for arg in it.args { | 	if node.args.len > 0 { | ||||||
|  | 		// g.mov(.r12, 0x77777777)
 | ||||||
| 	} | 	} | ||||||
| 	for stmt in it.stmts { | 	// Copy values from registers to local vars (calling convention)
 | ||||||
| 		g.stmt(stmt) | 	mut offset := 0 | ||||||
|  | 	for i in 0 .. node.args.len { | ||||||
|  | 		name := node.args[i].name | ||||||
|  | 		// TODO optimize. Right now 2 mov's are used instead of 1.
 | ||||||
|  | 		g.allocate_var(name, 4, 0) | ||||||
|  | 		// `mov DWORD PTR [rbp-0x4],edi`
 | ||||||
|  | 		offset += 4 | ||||||
|  | 		g.mov_from_reg(offset, fn_arg_registers[i]) | ||||||
| 	} | 	} | ||||||
|  | 	//
 | ||||||
|  | 	g.stmts(node.stmts) | ||||||
| 	if is_main { | 	if is_main { | ||||||
| 		println('end of main: gen exit') | 		println('end of main: gen exit') | ||||||
| 		g.gen_exit() | 		g.gen_exit() | ||||||
|  |  | ||||||
|  | @ -27,7 +27,25 @@ fn loop() { | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | fn foo(a int) { | ||||||
|  | 	println('foo') | ||||||
|  | 	if a == 1 { | ||||||
|  | 		println('foo(1)') | ||||||
|  | 	} | ||||||
|  | 	a++ | ||||||
|  | 	if a == 1 { | ||||||
|  | 		println('foo(2)') | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn args() { | ||||||
|  | 	println('===args===') | ||||||
|  | 	args(1) | ||||||
|  | 	args(2) | ||||||
|  | } | ||||||
|  | 
 | ||||||
| fn main() { | fn main() { | ||||||
| 	test() | 	test() | ||||||
| 	loop() | 	loop() | ||||||
|  | 	args() | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -6,3 +6,8 @@ hello | ||||||
| hello | hello | ||||||
| hello | hello | ||||||
| hello | hello | ||||||
|  | ===args=== | ||||||
|  | foo | ||||||
|  | foo(1) | ||||||
|  | foo(2) | ||||||
|  | foo | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue