asm: make fixed labels possible as displacement (#9549)
							parent
							
								
									63f835c4ce
								
							
						
					
					
						commit
						8d5e310189
					
				|  | @ -540,6 +540,7 @@ pub mut: | ||||||
| 	warnings         []errors.Warning  // all the checker warnings in the file
 | 	warnings         []errors.Warning  // all the checker warnings in the file
 | ||||||
| 	notices          []errors.Notice   // all the checker notices in the file
 | 	notices          []errors.Notice   // all the checker notices in the file
 | ||||||
| 	generic_fns      []&FnDecl | 	generic_fns      []&FnDecl | ||||||
|  | 	global_labels    []string // from `asm { .globl labelname }`
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub struct IdentFn { | pub struct IdentFn { | ||||||
|  | @ -1064,13 +1065,12 @@ pub: | ||||||
| 	clobbered    []AsmClobbered | 	clobbered    []AsmClobbered | ||||||
| 	pos          token.Position | 	pos          token.Position | ||||||
| pub mut: | pub mut: | ||||||
| 	templates        []AsmTemplate | 	templates     []AsmTemplate | ||||||
| 	scope            &Scope | 	scope         &Scope | ||||||
| 	output           []AsmIO | 	output        []AsmIO | ||||||
| 	input            []AsmIO | 	input         []AsmIO | ||||||
| 	global_labels    []string // listed after clobbers, paired with is_goto == true
 | 	global_labels []string // labels defined in assembly block, exported with `.globl`
 | ||||||
| 	local_labels     []string // local to the assembly block
 | 	local_labels  []string // local to the assembly block
 | ||||||
| 	exported_symbols []string // functions defined in assembly block, exported with `.globl`
 |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub struct AsmTemplate { | pub struct AsmTemplate { | ||||||
|  | @ -1083,8 +1083,8 @@ pub mut: | ||||||
| 	pos          token.Position | 	pos          token.Position | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // [eax+5] | j | eax | true | `a` | 0.594 | 123 | 'hi' | label_name
 | // [eax+5] | j | displacement literal (e.g. 123 in [rax + 123] ) | eax | true | `a` | 0.594 | 123 | label_name
 | ||||||
| pub type AsmArg = AsmAddressing | AsmAlias | AsmRegister | BoolLiteral | CharLiteral | | pub type AsmArg = AsmAddressing | AsmAlias | AsmDisp | AsmRegister | BoolLiteral | CharLiteral | | ||||||
| 	FloatLiteral | IntegerLiteral | string | 	FloatLiteral | IntegerLiteral | string | ||||||
| 
 | 
 | ||||||
| pub struct AsmRegister { | pub struct AsmRegister { | ||||||
|  | @ -1095,6 +1095,12 @@ mut: | ||||||
| 	size int | 	size int | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | pub struct AsmDisp { | ||||||
|  | pub: | ||||||
|  | 	val string | ||||||
|  | 	pos token.Position | ||||||
|  | } | ||||||
|  | 
 | ||||||
| pub struct AsmAlias { | pub struct AsmAlias { | ||||||
| pub: | pub: | ||||||
| 	name string // a
 | 	name string // a
 | ||||||
|  | @ -1103,13 +1109,13 @@ pub: | ||||||
| 
 | 
 | ||||||
| pub struct AsmAddressing { | pub struct AsmAddressing { | ||||||
| pub: | pub: | ||||||
| 	displacement u32 // 8, 16 or 32 bit literal value
 | 	scale int = -1 // 1, 2, 4, or 8 literal 
 | ||||||
| 	scale        int = -1 // 1, 2, 4, or 8 literal
 | 	mode  AddressingMode | ||||||
| 	mode         AddressingMode | 	pos   token.Position | ||||||
| 	pos          token.Position |  | ||||||
| pub mut: | pub mut: | ||||||
| 	base  AsmArg // gpr
 | 	displacement AsmArg // 8, 16 or 32 bit literal value
 | ||||||
| 	index AsmArg // gpr
 | 	base         AsmArg // gpr
 | ||||||
|  | 	index        AsmArg // gpr
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // adressing modes:
 | // adressing modes:
 | ||||||
|  | @ -1125,9 +1131,8 @@ pub enum AddressingMode { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub struct AsmClobbered { | pub struct AsmClobbered { | ||||||
| pub: |  | ||||||
| 	reg AsmRegister |  | ||||||
| pub mut: | pub mut: | ||||||
|  | 	reg      AsmRegister | ||||||
| 	comments []Comment | 	comments []Comment | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -1204,7 +1209,7 @@ pub const ( | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // TODO: saved priviled registers for arm
 | // TODO: saved priviled registers for arm
 | ||||||
| const ( | pub const ( | ||||||
| 	arm_no_number_register_list   = ['fp' /* aka r11 */, /* not instruction pointer: */ 'ip' /* aka r12 */, | 	arm_no_number_register_list   = ['fp' /* aka r11 */, /* not instruction pointer: */ 'ip' /* aka r12 */, | ||||||
| 		'sp' /* aka r13 */, 'lr' /* aka r14 */, /* this is instruction pointer ('program counter'): */ | 		'sp' /* aka r13 */, 'lr' /* aka r14 */, /* this is instruction pointer ('program counter'): */ | ||||||
| 		'pc' /* aka r15 */, | 		'pc' /* aka r15 */, | ||||||
|  | @ -1214,7 +1219,7 @@ const ( | ||||||
| 	} | 	} | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| const ( | pub const ( | ||||||
| 	riscv_no_number_register_list   = ['zero', 'ra', 'sp', 'gp', 'tp'] | 	riscv_no_number_register_list   = ['zero', 'ra', 'sp', 'gp', 'tp'] | ||||||
| 	riscv_with_number_register_list = map{ | 	riscv_with_number_register_list = map{ | ||||||
| 		'x#': 32 | 		'x#': 32 | ||||||
|  |  | ||||||
|  | @ -3768,11 +3768,11 @@ fn (mut c Checker) asm_stmt(mut stmt ast.AsmStmt) { | ||||||
| 
 | 
 | ||||||
| 			// }
 | 			// }
 | ||||||
| 		} | 		} | ||||||
| 		for arg in template.args { | 		for mut arg in template.args { | ||||||
| 			c.asm_arg(arg, stmt, aliases) | 			c.asm_arg(arg, stmt, aliases) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	for clob in stmt.clobbered { | 	for mut clob in stmt.clobbered { | ||||||
| 		c.asm_arg(clob.reg, stmt, aliases) | 		c.asm_arg(clob.reg, stmt, aliases) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | @ -3781,8 +3781,11 @@ fn (mut c Checker) asm_arg(arg ast.AsmArg, stmt ast.AsmStmt, aliases []string) { | ||||||
| 	match mut arg { | 	match mut arg { | ||||||
| 		ast.AsmAlias { | 		ast.AsmAlias { | ||||||
| 			name := arg.name | 			name := arg.name | ||||||
| 			if name !in aliases && name !in stmt.local_labels && name !in stmt.global_labels { | 			if name !in aliases && name !in stmt.local_labels && name !in c.file.global_labels { | ||||||
| 				suggestion := util.new_suggestion(name, aliases) | 				mut possible := aliases.clone() | ||||||
|  | 				possible << stmt.local_labels | ||||||
|  | 				possible << c.file.global_labels | ||||||
|  | 				suggestion := util.new_suggestion(name, possible) | ||||||
| 				c.error(suggestion.say('alias or label `$arg.name` does not exist'), arg.pos) | 				c.error(suggestion.say('alias or label `$arg.name` does not exist'), arg.pos) | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | @ -3790,6 +3793,7 @@ fn (mut c Checker) asm_arg(arg ast.AsmArg, stmt ast.AsmStmt, aliases []string) { | ||||||
| 			if arg.scale !in [-1, 1, 2, 4, 8] { | 			if arg.scale !in [-1, 1, 2, 4, 8] { | ||||||
| 				c.error('scale must be one of 1, 2, 4, or 8', arg.pos) | 				c.error('scale must be one of 1, 2, 4, or 8', arg.pos) | ||||||
| 			} | 			} | ||||||
|  | 			c.asm_arg(arg.displacement, stmt, aliases) | ||||||
| 			c.asm_arg(arg.base, stmt, aliases) | 			c.asm_arg(arg.base, stmt, aliases) | ||||||
| 			c.asm_arg(arg.index, stmt, aliases) | 			c.asm_arg(arg.index, stmt, aliases) | ||||||
| 		} | 		} | ||||||
|  | @ -3798,6 +3802,7 @@ fn (mut c Checker) asm_arg(arg ast.AsmArg, stmt ast.AsmStmt, aliases []string) { | ||||||
| 		ast.CharLiteral {} | 		ast.CharLiteral {} | ||||||
| 		ast.IntegerLiteral {} | 		ast.IntegerLiteral {} | ||||||
| 		ast.AsmRegister {} // if the register is not found, the parser will register it as an alias
 | 		ast.AsmRegister {} // if the register is not found, the parser will register it as an alias
 | ||||||
|  | 		ast.AsmDisp {} | ||||||
| 		string {} | 		string {} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -750,31 +750,36 @@ fn (mut f Fmt) asm_arg(arg ast.AsmArg) { | ||||||
| 					f.asm_arg(base) | 					f.asm_arg(base) | ||||||
| 				} | 				} | ||||||
| 				.displacement { | 				.displacement { | ||||||
| 					f.write('$displacement') | 					f.asm_arg(displacement) | ||||||
| 				} | 				} | ||||||
| 				.base_plus_displacement { | 				.base_plus_displacement { | ||||||
| 					f.asm_arg(base) | 					f.asm_arg(base) | ||||||
| 					f.write(' + $displacement') | 					f.write(' + ') | ||||||
|  | 					f.asm_arg(displacement) | ||||||
| 				} | 				} | ||||||
| 				.index_times_scale_plus_displacement { | 				.index_times_scale_plus_displacement { | ||||||
| 					f.asm_arg(index) | 					f.asm_arg(index) | ||||||
| 					f.write(' * $scale + $displacement') | 					f.write(' * $scale + ') | ||||||
|  | 					f.asm_arg(displacement) | ||||||
| 				} | 				} | ||||||
| 				.base_plus_index_plus_displacement { | 				.base_plus_index_plus_displacement { | ||||||
| 					f.asm_arg(base) | 					f.asm_arg(base) | ||||||
| 					f.write(' + ') | 					f.write(' + ') | ||||||
| 					f.asm_arg(index) | 					f.asm_arg(index) | ||||||
| 					f.write(' + $displacement') | 					f.write(' + ') | ||||||
|  | 					f.asm_arg(displacement) | ||||||
| 				} | 				} | ||||||
| 				.base_plus_index_times_scale_plus_displacement { | 				.base_plus_index_times_scale_plus_displacement { | ||||||
| 					f.asm_arg(base) | 					f.asm_arg(base) | ||||||
| 					f.write(' + ') | 					f.write(' + ') | ||||||
| 					f.asm_arg(index) | 					f.asm_arg(index) | ||||||
| 					f.write(' * $scale + $displacement') | 					f.write(' * $scale + ') | ||||||
|  | 					f.asm_arg(displacement) | ||||||
| 				} | 				} | ||||||
| 				.rip_plus_displacement { | 				.rip_plus_displacement { | ||||||
| 					f.asm_arg(base) | 					f.asm_arg(base) | ||||||
| 					f.write(' + $displacement') | 					f.write(' + ') | ||||||
|  | 					f.asm_arg(displacement) | ||||||
| 				} | 				} | ||||||
| 				.invalid { | 				.invalid { | ||||||
| 					panic('fmt: invalid addressing mode') | 					panic('fmt: invalid addressing mode') | ||||||
|  | @ -782,6 +787,9 @@ fn (mut f Fmt) asm_arg(arg ast.AsmArg) { | ||||||
| 			} | 			} | ||||||
| 			f.write(']') | 			f.write(']') | ||||||
| 		} | 		} | ||||||
|  | 		ast.AsmDisp { | ||||||
|  | 			f.write(arg.val) | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1861,12 +1861,9 @@ fn (mut g Gen) asm_arg(arg ast.AsmArg, stmt ast.AsmStmt) { | ||||||
| 	match arg { | 	match arg { | ||||||
| 		ast.AsmAlias { | 		ast.AsmAlias { | ||||||
| 			name := arg.name | 			name := arg.name | ||||||
| 			if name in stmt.local_labels || name in stmt.global_labels { | 			if name in stmt.local_labels || name in stmt.global_labels | ||||||
| 				asm_formatted_name := if name in stmt.local_labels { | 				|| name in g.file.global_labels { | ||||||
| 					name | 				asm_formatted_name := if name in stmt.global_labels { '%l[$name]' } else { name } | ||||||
| 				} else { // val in stmt.global_labels
 |  | ||||||
| 					'%l[$name]' |  | ||||||
| 				} |  | ||||||
| 				g.write(asm_formatted_name) | 				g.write(asm_formatted_name) | ||||||
| 			} else { | 			} else { | ||||||
| 				g.write('%[$name]') | 				g.write('%[$name]') | ||||||
|  | @ -1896,43 +1893,53 @@ fn (mut g Gen) asm_arg(arg ast.AsmArg, stmt ast.AsmStmt) { | ||||||
| 				.base { | 				.base { | ||||||
| 					g.write('(') | 					g.write('(') | ||||||
| 					g.asm_arg(base, stmt) | 					g.asm_arg(base, stmt) | ||||||
|  | 					g.write(')') | ||||||
| 				} | 				} | ||||||
| 				.displacement { | 				.displacement { | ||||||
| 					g.write('${displacement}(') | 					g.asm_arg(displacement, stmt) | ||||||
|  | 					g.write('()') | ||||||
| 				} | 				} | ||||||
| 				.base_plus_displacement { | 				.base_plus_displacement { | ||||||
| 					g.write('${displacement}(') | 					g.asm_arg(displacement, stmt) | ||||||
|  | 					g.write('(') | ||||||
| 					g.asm_arg(base, stmt) | 					g.asm_arg(base, stmt) | ||||||
|  | 					g.write(')') | ||||||
| 				} | 				} | ||||||
| 				.index_times_scale_plus_displacement { | 				.index_times_scale_plus_displacement { | ||||||
| 					g.write('${displacement}(,') | 					g.asm_arg(displacement, stmt) | ||||||
|  | 					g.write('(') | ||||||
| 					g.asm_arg(index, stmt) | 					g.asm_arg(index, stmt) | ||||||
| 					g.write(',') | 					g.write(',$scale)') | ||||||
| 					g.write(scale.str()) |  | ||||||
| 				} | 				} | ||||||
| 				.base_plus_index_plus_displacement { | 				.base_plus_index_plus_displacement { | ||||||
| 					g.write('${displacement}(') | 					g.asm_arg(displacement, stmt) | ||||||
|  | 					g.write('(') | ||||||
| 					g.asm_arg(base, stmt) | 					g.asm_arg(base, stmt) | ||||||
| 					g.write(',') | 					g.write(',') | ||||||
| 					g.asm_arg(index, stmt) | 					g.asm_arg(index, stmt) | ||||||
| 					g.write(',1') | 					g.write(',1)') | ||||||
| 				} | 				} | ||||||
| 				.base_plus_index_times_scale_plus_displacement { | 				.base_plus_index_times_scale_plus_displacement { | ||||||
| 					g.write('${displacement}(') | 					g.asm_arg(displacement, stmt) | ||||||
|  | 					g.write('(') | ||||||
| 					g.asm_arg(base, stmt) | 					g.asm_arg(base, stmt) | ||||||
| 					g.write(',') | 					g.write(',') | ||||||
| 					g.asm_arg(index, stmt) | 					g.asm_arg(index, stmt) | ||||||
| 					g.write(',$scale') | 					g.write(',$scale)') | ||||||
| 				} | 				} | ||||||
| 				.rip_plus_displacement { | 				.rip_plus_displacement { | ||||||
| 					g.write('${displacement}(') | 					g.asm_arg(displacement, stmt) | ||||||
|  | 					g.write('(') | ||||||
| 					g.asm_arg(base, stmt) | 					g.asm_arg(base, stmt) | ||||||
|  | 					g.write(')') | ||||||
| 				} | 				} | ||||||
| 				.invalid { | 				.invalid { | ||||||
| 					g.error('invalid addressing mode', arg.pos) | 					g.error('invalid addressing mode', arg.pos) | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 			g.write(')') | 		} | ||||||
|  | 		ast.AsmDisp { | ||||||
|  | 			g.write(arg.val) | ||||||
| 		} | 		} | ||||||
| 		string { | 		string { | ||||||
| 			g.write('$arg') | 			g.write('$arg') | ||||||
|  | @ -1945,7 +1952,9 @@ fn (mut g Gen) gen_asm_ios(ios []ast.AsmIO) { | ||||||
| 		if io.alias != '' { | 		if io.alias != '' { | ||||||
| 			g.write('[$io.alias] ') | 			g.write('[$io.alias] ') | ||||||
| 		} | 		} | ||||||
| 		g.write('"$io.constraint" ($io.expr)') | 		g.write('"$io.constraint" (') | ||||||
|  | 		g.expr(io.expr) | ||||||
|  | 		g.write(')') | ||||||
| 		if i + 1 < ios.len { | 		if i + 1 < ios.len { | ||||||
| 			g.writeln(',') | 			g.writeln(',') | ||||||
| 		} else { | 		} else { | ||||||
|  |  | ||||||
|  | @ -73,6 +73,7 @@ mut: | ||||||
| 	n_asm               int  // controls assembly labels
 | 	n_asm               int  // controls assembly labels
 | ||||||
| 	inside_asm_template bool | 	inside_asm_template bool | ||||||
| 	inside_asm          bool | 	inside_asm          bool | ||||||
|  | 	global_labels       []string | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // for tests
 | // for tests
 | ||||||
|  | @ -281,6 +282,7 @@ pub fn (mut p Parser) parse() ast.File { | ||||||
| 		global_scope: p.global_scope | 		global_scope: p.global_scope | ||||||
| 		errors: p.errors | 		errors: p.errors | ||||||
| 		warnings: p.warnings | 		warnings: p.warnings | ||||||
|  | 		global_labels: p.global_labels | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -876,7 +878,6 @@ fn (mut p Parser) asm_stmt(is_top_level bool) ast.AsmStmt { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	mut local_labels := []string{} | 	mut local_labels := []string{} | ||||||
| 	mut exported_symbols := []string{} |  | ||||||
| 	// riscv: https://github.com/jameslzhu/riscv-card/blob/master/riscv-card.pdf
 | 	// riscv: https://github.com/jameslzhu/riscv-card/blob/master/riscv-card.pdf
 | ||||||
| 	// x86: https://www.felixcloutier.com/x86/
 | 	// x86: https://www.felixcloutier.com/x86/
 | ||||||
| 	// arm: https://developer.arm.com/documentation/dui0068/b/arm-instruction-reference
 | 	// arm: https://developer.arm.com/documentation/dui0068/b/arm-instruction-reference
 | ||||||
|  | @ -921,8 +922,15 @@ fn (mut p Parser) asm_stmt(is_top_level bool) ast.AsmStmt { | ||||||
| 							} | 							} | ||||||
| 						} | 						} | ||||||
| 						ast.IntegerLiteral { | 						ast.IntegerLiteral { | ||||||
| 							args << ast.IntegerLiteral{ | 							if is_directive { | ||||||
| 								...number_lit | 								args << ast.AsmDisp{ | ||||||
|  | 									val: number_lit.val | ||||||
|  | 									pos: number_lit.pos | ||||||
|  | 								} | ||||||
|  | 							} else { | ||||||
|  | 								args << ast.IntegerLiteral{ | ||||||
|  | 									...number_lit | ||||||
|  | 								} | ||||||
| 							} | 							} | ||||||
| 						} | 						} | ||||||
| 						else { | 						else { | ||||||
|  | @ -967,7 +975,9 @@ fn (mut p Parser) asm_stmt(is_top_level bool) ast.AsmStmt { | ||||||
| 			comments << p.comment() | 			comments << p.comment() | ||||||
| 		} | 		} | ||||||
| 		if is_directive && name in ['globl', 'global'] { | 		if is_directive && name in ['globl', 'global'] { | ||||||
| 			exported_symbols << args | 			for arg in args { | ||||||
|  | 				p.global_labels << (arg as ast.AsmAlias).name | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 		templates << ast.AsmTemplate{ | 		templates << ast.AsmTemplate{ | ||||||
| 			name: name | 			name: name | ||||||
|  | @ -1045,7 +1055,6 @@ fn (mut p Parser) asm_stmt(is_top_level bool) ast.AsmStmt { | ||||||
| 		scope: scope | 		scope: scope | ||||||
| 		global_labels: global_labels | 		global_labels: global_labels | ||||||
| 		local_labels: local_labels | 		local_labels: local_labels | ||||||
| 		exported_symbols: exported_symbols |  | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -1058,7 +1067,8 @@ fn (mut p Parser) reg_or_alias() ast.AsmArg { | ||||||
| 			p.check(.name) | 			p.check(.name) | ||||||
| 			return b | 			return b | ||||||
| 		} else { | 		} else { | ||||||
| 			panic('parser bug: non-register ast.ScopeObject found in scope') | 			verror('parser bug: non-register ast.ScopeObject found in scope') | ||||||
|  | 			return ast.AsmDisp{} // should not be reached
 | ||||||
| 		} | 		} | ||||||
| 	} else { | 	} else { | ||||||
| 		p.check(.name) | 		p.check(.name) | ||||||
|  | @ -1173,8 +1183,15 @@ fn (mut p Parser) asm_addressing() ast.AsmAddressing { | ||||||
| 				pos: pos.extend(p.prev_tok.position()) | 				pos: pos.extend(p.prev_tok.position()) | ||||||
| 			} | 			} | ||||||
| 		} else if p.tok.kind == .number { | 		} else if p.tok.kind == .number { | ||||||
| 			displacement := p.tok.lit.u32() | 			displacement := if p.tok.kind == .name { | ||||||
| 			p.check(.name) | 				x := ast.AsmArg(p.tok.lit) | ||||||
|  | 				p.check(.name) | ||||||
|  | 				x | ||||||
|  | 			} else { | ||||||
|  | 				x := ast.AsmArg(p.tok.lit) | ||||||
|  | 				p.check(.number) | ||||||
|  | 				x | ||||||
|  | 			} | ||||||
| 			p.check(.rsbr) | 			p.check(.rsbr) | ||||||
| 			return ast.AsmAddressing{ | 			return ast.AsmAddressing{ | ||||||
| 				mode: .displacement | 				mode: .displacement | ||||||
|  | @ -1187,13 +1204,22 @@ fn (mut p Parser) asm_addressing() ast.AsmAddressing { | ||||||
| 	} | 	} | ||||||
| 	if p.peek_tok.kind == .plus && p.tok.kind == .name { // [base + displacement], [base + index ∗ scale + displacement], [base + index + displacement] or [rip + displacement]
 | 	if p.peek_tok.kind == .plus && p.tok.kind == .name { // [base + displacement], [base + index ∗ scale + displacement], [base + index + displacement] or [rip + displacement]
 | ||||||
| 		if p.tok.lit == 'rip' { | 		if p.tok.lit == 'rip' { | ||||||
| 			p.check(.name) | 			rip := p.reg_or_alias() | ||||||
| 			p.check(.plus) | 			p.check(.plus) | ||||||
| 			displacement := p.tok.lit.u32() | 
 | ||||||
| 			p.check(.number) | 			displacement := if p.tok.kind == .name { | ||||||
|  | 				x := ast.AsmArg(p.tok.lit) | ||||||
|  | 				p.check(.name) | ||||||
|  | 				x | ||||||
|  | 			} else { | ||||||
|  | 				x := ast.AsmArg(p.tok.lit) | ||||||
|  | 				p.check(.number) | ||||||
|  | 				x | ||||||
|  | 			} | ||||||
|  | 			p.check(.rsbr) | ||||||
| 			return ast.AsmAddressing{ | 			return ast.AsmAddressing{ | ||||||
| 				mode: .rip_plus_displacement | 				mode: .rip_plus_displacement | ||||||
| 				base: 'rip' | 				base: rip | ||||||
| 				displacement: displacement | 				displacement: displacement | ||||||
| 				pos: pos.extend(p.prev_tok.position()) | 				pos: pos.extend(p.prev_tok.position()) | ||||||
| 			} | 			} | ||||||
|  | @ -1202,8 +1228,15 @@ fn (mut p Parser) asm_addressing() ast.AsmAddressing { | ||||||
| 		p.check(.plus) | 		p.check(.plus) | ||||||
| 		if p.peek_tok.kind == .rsbr { | 		if p.peek_tok.kind == .rsbr { | ||||||
| 			if p.tok.kind == .number { | 			if p.tok.kind == .number { | ||||||
| 				displacement := p.tok.lit.u32() | 				displacement := if p.tok.kind == .name { | ||||||
| 				p.check(.number) | 					x := ast.AsmArg(p.tok.lit) | ||||||
|  | 					p.check(.name) | ||||||
|  | 					x | ||||||
|  | 				} else { | ||||||
|  | 					x := ast.AsmArg(p.tok.lit) | ||||||
|  | 					p.check(.name) | ||||||
|  | 					x | ||||||
|  | 				} | ||||||
| 				p.check(.rsbr) | 				p.check(.rsbr) | ||||||
| 				return ast.AsmAddressing{ | 				return ast.AsmAddressing{ | ||||||
| 					mode: .base_plus_displacement | 					mode: .base_plus_displacement | ||||||
|  | @ -1221,8 +1254,15 @@ fn (mut p Parser) asm_addressing() ast.AsmAddressing { | ||||||
| 			scale := p.tok.lit.int() | 			scale := p.tok.lit.int() | ||||||
| 			p.check(.number) | 			p.check(.number) | ||||||
| 			p.check(.plus) | 			p.check(.plus) | ||||||
| 			displacement := p.tok.lit.u32() | 			displacement := if p.tok.kind == .name { | ||||||
| 			p.check(.number) | 				x := ast.AsmArg(p.tok.lit) | ||||||
|  | 				p.check(.name) | ||||||
|  | 				x | ||||||
|  | 			} else { | ||||||
|  | 				x := ast.AsmArg(p.tok.lit) | ||||||
|  | 				p.check(.number) | ||||||
|  | 				x | ||||||
|  | 			} | ||||||
| 			p.check(.rsbr) | 			p.check(.rsbr) | ||||||
| 			return ast.AsmAddressing{ | 			return ast.AsmAddressing{ | ||||||
| 				mode: .base_plus_index_times_scale_plus_displacement | 				mode: .base_plus_index_times_scale_plus_displacement | ||||||
|  | @ -1234,8 +1274,15 @@ fn (mut p Parser) asm_addressing() ast.AsmAddressing { | ||||||
| 			} | 			} | ||||||
| 		} else if p.tok.kind == .plus { | 		} else if p.tok.kind == .plus { | ||||||
| 			p.check(.plus) | 			p.check(.plus) | ||||||
| 			displacement := p.tok.lit.u32() | 			displacement := if p.tok.kind == .name { | ||||||
| 			p.check(.number) | 				x := ast.AsmArg(p.tok.lit) | ||||||
|  | 				p.check(.name) | ||||||
|  | 				x | ||||||
|  | 			} else { | ||||||
|  | 				x := ast.AsmArg(p.tok.lit) | ||||||
|  | 				p.check(.number) | ||||||
|  | 				x | ||||||
|  | 			} | ||||||
| 			p.check(.rsbr) | 			p.check(.rsbr) | ||||||
| 			return ast.AsmAddressing{ | 			return ast.AsmAddressing{ | ||||||
| 				mode: .base_plus_index_plus_displacement | 				mode: .base_plus_index_plus_displacement | ||||||
|  | @ -1252,8 +1299,15 @@ fn (mut p Parser) asm_addressing() ast.AsmAddressing { | ||||||
| 		scale := p.tok.lit.int() | 		scale := p.tok.lit.int() | ||||||
| 		p.check(.number) | 		p.check(.number) | ||||||
| 		p.check(.plus) | 		p.check(.plus) | ||||||
| 		displacement := p.tok.lit.u32() | 		displacement := if p.tok.kind == .name { | ||||||
| 		p.check(.number) | 			x := ast.AsmArg(p.tok.lit) | ||||||
|  | 			p.check(.name) | ||||||
|  | 			x | ||||||
|  | 		} else { | ||||||
|  | 			x := ast.AsmArg(p.tok.lit) | ||||||
|  | 			p.check(.number) | ||||||
|  | 			x | ||||||
|  | 		} | ||||||
| 		p.check(.rsbr) | 		p.check(.rsbr) | ||||||
| 		return ast.AsmAddressing{ | 		return ast.AsmAddressing{ | ||||||
| 			mode: .index_times_scale_plus_displacement | 			mode: .index_times_scale_plus_displacement | ||||||
|  |  | ||||||
|  | @ -1,7 +1,7 @@ | ||||||
| import v.tests.assembly.util | import v.tests.assembly.util | ||||||
| 
 | 
 | ||||||
| fn test_inline_asm() { | fn test_inline_asm() { | ||||||
| 	a, mut b := 10, 0 | 	a, mut b := i64(10), i64(0) | ||||||
| 	asm amd64 { | 	asm amd64 { | ||||||
| 		mov rax, a | 		mov rax, a | ||||||
| 		mov b, rax | 		mov b, rax | ||||||
|  | @ -97,3 +97,26 @@ fn test_inline_asm() { | ||||||
| 
 | 
 | ||||||
| 	assert util.add(8, 9, 34, 7) == 58 // test .amd64.v files
 | 	assert util.add(8, 9, 34, 7) == 58 // test .amd64.v files
 | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | // this test does not appear in i386 test since rip relative addressing was introduced in 64-bit mode
 | ||||||
|  | fn test_rip_relative_label() { | ||||||
|  | 	mut a := i64(4) | ||||||
|  | 	asm amd64 { | ||||||
|  | 		mov a, [rip + one_two_three] // see below
 | ||||||
|  | 		; =r (a) | ||||||
|  | 	} | ||||||
|  | 	assert a == 48321074923 | ||||||
|  | 
 | ||||||
|  | 	mut b := i64(4) | ||||||
|  | 	asm amd64 { | ||||||
|  | 		mov b, one_two_three // see below
 | ||||||
|  | 		; =r (b) | ||||||
|  | 	} | ||||||
|  | 	assert b == 48321074923 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | asm amd64 { | ||||||
|  | 	.global one_two_three | ||||||
|  | 	one_two_three: | ||||||
|  | 	.quad 48321074923 | ||||||
|  | } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue