x64: local variables; if
							parent
							
								
									c35e0e49ce
								
							
						
					
					
						commit
						50436a0e4a
					
				| 
						 | 
				
			
			@ -18,6 +18,8 @@ mut:
 | 
			
		|||
	main_fn_addr         i64
 | 
			
		||||
	code_start_pos       i64 // location of the start of the assembly instructions
 | 
			
		||||
	fn_addr              map[string]i64
 | 
			
		||||
	var_offset           map[string]int // local var stack offset
 | 
			
		||||
	stack_var_pos        int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// string_addr map[string]i64
 | 
			
		||||
| 
						 | 
				
			
			@ -70,14 +72,17 @@ pub fn gen(files []ast.File, out_name string) {
 | 
			
		|||
	}
 | 
			
		||||
	g.generate_elf_header()
 | 
			
		||||
	for file in files {
 | 
			
		||||
		for stmt in file.stmts {
 | 
			
		||||
			g.stmt(stmt)
 | 
			
		||||
			g.writeln('')
 | 
			
		||||
		}
 | 
			
		||||
		g.stmts(file.stmts)
 | 
			
		||||
	}
 | 
			
		||||
	g.generate_elf_footer()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn (mut g Gen) stmts(stmts []ast.Stmt) {
 | 
			
		||||
	for stmt in stmts {
 | 
			
		||||
		g.stmt(stmt)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
pub fn new_gen(out_name string) &Gen {
 | 
			
		||||
	return &Gen{
 | 
			
		||||
| 
						 | 
				
			
			@ -172,6 +177,27 @@ fn (mut g Gen) cmp(reg Register, size Size, val i64) {
 | 
			
		|||
	g.write8(int(val))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// `a == 1`
 | 
			
		||||
// `cmp DWORD [rbp-0x4],0x1`
 | 
			
		||||
fn (mut g Gen) cmp_var(var_name string, val int) {
 | 
			
		||||
	g.write8(0x81) // 83 for 1 byte?
 | 
			
		||||
	g.write8(0x7d)
 | 
			
		||||
	offset := g.var_offset[var_name]
 | 
			
		||||
	if offset == 0 {
 | 
			
		||||
		verror('cmp_var 0 offset $var_name')
 | 
			
		||||
	}
 | 
			
		||||
	g.write8(0xff - offset + 1)
 | 
			
		||||
	g.write32(val)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Returns the position of the address to jump to (set later).
 | 
			
		||||
fn (mut g Gen) jne() int {
 | 
			
		||||
	g.write16(0x850f)
 | 
			
		||||
	pos := g.pos()
 | 
			
		||||
	g.write32(PLACEHOLDER)
 | 
			
		||||
	return pos
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn abs(a i64) i64 {
 | 
			
		||||
	return if a < 0 {
 | 
			
		||||
		-a
 | 
			
		||||
| 
						 | 
				
			
			@ -371,12 +397,6 @@ pub fn (mut g Gen) register_function_address(name string) {
 | 
			
		|||
	g.fn_addr[name] = addr
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn (g &Gen) write(s string) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn (g &Gen) writeln(s string) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn (mut g Gen) call_fn(name string) {
 | 
			
		||||
	println('call fn $name')
 | 
			
		||||
	if !name.contains('__') {
 | 
			
		||||
| 
						 | 
				
			
			@ -440,19 +460,81 @@ fn (mut g Gen) expr(node ast.Expr) {
 | 
			
		|||
		ast.ArrayInit {}
 | 
			
		||||
		ast.Ident {}
 | 
			
		||||
		ast.BoolLiteral {}
 | 
			
		||||
		ast.IfExpr {}
 | 
			
		||||
		ast.IfExpr {
 | 
			
		||||
			g.if_expr(it)
 | 
			
		||||
		}
 | 
			
		||||
		else {
 | 
			
		||||
			// println(term.red('x64.expr(): bad node'))
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn (mut g Gen) allocate_var(name string, size, initial_val int) {
 | 
			
		||||
	// `a := 3`  =>
 | 
			
		||||
	// `move DWORD [rbp-0x4],0x3`
 | 
			
		||||
	match size {
 | 
			
		||||
		1 {
 | 
			
		||||
			// BYTE
 | 
			
		||||
			g.write8(0xc6)
 | 
			
		||||
			g.write8(0x45)
 | 
			
		||||
		}
 | 
			
		||||
		4 {
 | 
			
		||||
			// DWORD
 | 
			
		||||
			g.write8(0xc7)
 | 
			
		||||
			g.write8(0x45)
 | 
			
		||||
		}
 | 
			
		||||
		8 {
 | 
			
		||||
			// QWORD
 | 
			
		||||
			g.write8(0x48)
 | 
			
		||||
			g.write8(0xc7)
 | 
			
		||||
			g.write8(0x45)
 | 
			
		||||
		}
 | 
			
		||||
		else {
 | 
			
		||||
			verror('allocate_var: bad size $size')
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	// Generate N in `[rbp-N]`
 | 
			
		||||
	g.write8(0xff - (g.stack_var_pos + size) + 1)
 | 
			
		||||
	g.stack_var_pos += size
 | 
			
		||||
	g.var_offset[name] = g.stack_var_pos
 | 
			
		||||
	// Generate the value assigned to the variable
 | 
			
		||||
	g.write32(initial_val)
 | 
			
		||||
	println('allocate_var(size=$size, initial_val=$initial_val)')
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn (mut g Gen) assign_stmt(node ast.AssignStmt) {
 | 
			
		||||
	// `a := 1` | `a,b := 1,2`
 | 
			
		||||
	for i, ident in node.left {
 | 
			
		||||
		match node.right[0] {
 | 
			
		||||
			ast.IntegerLiteral {
 | 
			
		||||
				print(it.val)
 | 
			
		||||
				g.allocate_var(ident.name, 4, it.val.int())
 | 
			
		||||
			}
 | 
			
		||||
			else {}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn (mut g Gen) if_expr(node ast.IfExpr) {
 | 
			
		||||
	branch := node.branches[0]
 | 
			
		||||
	infix_expr := branch.cond as ast.InfixExpr
 | 
			
		||||
	mut jne_addr := 0 // location of `jne *00 00 00 00*`
 | 
			
		||||
	match infix_expr.left {
 | 
			
		||||
		ast.Ident {
 | 
			
		||||
			lit := infix_expr.right as ast.IntegerLiteral
 | 
			
		||||
			g.cmp_var(it.name, lit.val.int())
 | 
			
		||||
			jne_addr = g.jne()
 | 
			
		||||
		}
 | 
			
		||||
		else {}
 | 
			
		||||
	}
 | 
			
		||||
	g.stmts(branch.stmts)
 | 
			
		||||
	// Now that we know where we need to jump if the condition is false, update the `jne` call.
 | 
			
		||||
	// The value is the relative address, difference between current position and the location
 | 
			
		||||
	// after `jne 00 00 00 00`
 | 
			
		||||
	println('after if g.pos=$g.pos() jneaddr=$jne_addr')
 | 
			
		||||
	g.write32_at(jne_addr, g.pos() - jne_addr - 4) // 4 is for "00 00 00 00"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn (mut g Gen) fn_decl(it ast.FnDecl) {
 | 
			
		||||
	is_main := it.name == 'main'
 | 
			
		||||
	println('saving addr $it.name $g.buf.len.hex()')
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,20 @@
 | 
			
		|||
fn test() {
 | 
			
		||||
	a := 1
 | 
			
		||||
	if a == 1 {
 | 
			
		||||
		println('a == 1')
 | 
			
		||||
		b := 2
 | 
			
		||||
		if b == 2 {
 | 
			
		||||
			println('b == 2')
 | 
			
		||||
		}
 | 
			
		||||
		//if b != 2 {
 | 
			
		||||
			//println('b != 2')
 | 
			
		||||
		//}
 | 
			
		||||
	}
 | 
			
		||||
	if a == 2 {
 | 
			
		||||
		println('a == 2')
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn main() {
 | 
			
		||||
	test()
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,2 @@
 | 
			
		|||
a == 1
 | 
			
		||||
b == 2
 | 
			
		||||
		Loading…
	
		Reference in New Issue