native: support defining functions in any order (#12511)
							parent
							
								
									d498c365c2
								
							
						
					
					
						commit
						b367ed9ba3
					
				|  | @ -778,10 +778,6 @@ pub fn (mut g Gen) call_fn(node ast.CallExpr) { | |||
| 		n = 'main.$n' | ||||
| 	} | ||||
| 	addr := g.fn_addr[n] | ||||
| 	if addr == 0 { | ||||
| 		// g.warning('fn addr of `$name` = 0')
 | ||||
| 		g.n_error('fn addr of `$name` = 0') | ||||
| 	} | ||||
| 	// Copy values to registers (calling convention)
 | ||||
| 	// g.mov(.eax, 0)
 | ||||
| 	for i in 0 .. node.args.len { | ||||
|  | @ -808,11 +804,41 @@ pub fn (mut g Gen) call_fn(node ast.CallExpr) { | |||
| 	if node.args.len > 6 { | ||||
| 		g.v_error('more than 6 args not allowed for now', node.pos) | ||||
| 	} | ||||
| 	g.call(int(addr)) | ||||
| 	if addr == 0 { | ||||
| 		g.delay_fn_call(name) | ||||
| 		g.call(int(0)) | ||||
| 	} else { | ||||
| 		g.call(int(addr)) | ||||
| 	} | ||||
| 	g.println('fn call `${name}()`') | ||||
| 	// println('call $name $addr')
 | ||||
| } | ||||
| 
 | ||||
| fn (mut g Gen) patch_calls() { | ||||
| 	for c in g.callpatches { | ||||
| 		addr := g.fn_addr[c.name] | ||||
| 		if addr == 0 { | ||||
| 			g.n_error('fn addr of `$c.name` = 0') | ||||
| 			return | ||||
| 		} | ||||
| 		last := g.buf.len | ||||
| 		g.call(int(addr + last - c.pos)) | ||||
| 		mut patch := []byte{} | ||||
| 		for last < g.buf.len { | ||||
| 			patch << g.buf.pop() | ||||
| 		} | ||||
| 		for i := 0; i < patch.len; i++ { | ||||
| 			g.buf[c.pos + i] = patch[patch.len - i - 1] | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| fn (mut g Gen) delay_fn_call(name string) { | ||||
| 	pos := g.buf.len | ||||
| 	g.callpatches << CallPatch{name, pos} | ||||
| 	// do nothing for now
 | ||||
| } | ||||
| 
 | ||||
| fn (mut g Gen) assign_stmt(node ast.AssignStmt) { | ||||
| 	// `a := 1` | `a,b := 1,2`
 | ||||
| 	for i, left in node.left { | ||||
|  |  | |||
|  | @ -44,9 +44,15 @@ mut: | |||
| 	errors               []errors.Error | ||||
| 	warnings             []errors.Warning | ||||
| 	syms                 []Symbol | ||||
| 	relocs               []Reloc | ||||
| 	size_pos             []int | ||||
| 	nlines               int | ||||
| 	// UNUSED relocs               []Reloc
 | ||||
| 	size_pos    []int | ||||
| 	nlines      int | ||||
| 	callpatches []CallPatch | ||||
| } | ||||
| 
 | ||||
| struct CallPatch { | ||||
| 	name string | ||||
| 	pos  int | ||||
| } | ||||
| 
 | ||||
| enum Size { | ||||
|  | @ -141,6 +147,7 @@ pub fn (mut g Gen) create_executable() { | |||
| } | ||||
| 
 | ||||
| pub fn (mut g Gen) generate_footer() { | ||||
| 	g.patch_calls() | ||||
| 	match g.pref.os { | ||||
| 		.macos { | ||||
| 			g.generate_macho_footer() | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue