cgen, parser: fix several assembly bugs (#10498)
							parent
							
								
									39e7290416
								
							
						
					
					
						commit
						4688c75389
					
				|  | @ -1950,7 +1950,7 @@ fn (mut g Gen) gen_asm_stmt(stmt ast.AsmStmt) { | ||||||
| 			g.write(' ') | 			g.write(' ') | ||||||
| 		} | 		} | ||||||
| 		// swap destionation and operands for att syntax
 | 		// swap destionation and operands for att syntax
 | ||||||
| 		if template.args.len != 0 { | 		if template.args.len != 0 && !template.is_directive { | ||||||
| 			template.args.prepend(template.args[template.args.len - 1]) | 			template.args.prepend(template.args[template.args.len - 1]) | ||||||
| 			template.args.delete(template.args.len - 1) | 			template.args.delete(template.args.len - 1) | ||||||
| 		} | 		} | ||||||
|  | @ -2052,8 +2052,16 @@ fn (mut g Gen) asm_arg(arg ast.AsmArg, stmt ast.AsmStmt) { | ||||||
| 					g.write(')') | 					g.write(')') | ||||||
| 				} | 				} | ||||||
| 				.index_times_scale_plus_displacement { | 				.index_times_scale_plus_displacement { | ||||||
|  | 					if displacement is ast.AsmDisp { | ||||||
| 						g.asm_arg(displacement, stmt) | 						g.asm_arg(displacement, stmt) | ||||||
|  | 						g.write('(, ') | ||||||
|  | 					} else if displacement is ast.AsmRegister { | ||||||
| 						g.write('(') | 						g.write('(') | ||||||
|  | 						g.asm_arg(displacement, stmt) | ||||||
|  | 						g.write(',') | ||||||
|  | 					} else { | ||||||
|  | 						panic('unexpected $displacement.type_name()') | ||||||
|  | 					} | ||||||
| 					g.asm_arg(index, stmt) | 					g.asm_arg(index, stmt) | ||||||
| 					g.write(',$scale)') | 					g.write(',$scale)') | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
|  | @ -885,22 +885,32 @@ fn (mut p Parser) asm_stmt(is_top_level bool) ast.AsmStmt { | ||||||
| 	for p.tok.kind !in [.semicolon, .rcbr] { | 	for p.tok.kind !in [.semicolon, .rcbr] { | ||||||
| 		template_pos := p.tok.position() | 		template_pos := p.tok.position() | ||||||
| 		mut name := '' | 		mut name := '' | ||||||
|  | 		if p.tok.kind == .name && arch == .amd64 && p.tok.lit in ['rex', 'vex', 'xop'] { | ||||||
|  | 			name += p.tok.lit | ||||||
|  | 			p.next() | ||||||
|  | 			for p.tok.kind == .dot { | ||||||
|  | 				p.next() | ||||||
|  | 				name += '.' + p.tok.lit | ||||||
|  | 				p.check(.name) | ||||||
|  | 			} | ||||||
|  | 			name += ' ' | ||||||
|  | 		} | ||||||
| 		is_directive := p.tok.kind == .dot | 		is_directive := p.tok.kind == .dot | ||||||
| 		if is_directive { | 		if is_directive { | ||||||
| 			p.next() | 			p.next() | ||||||
| 		} | 		} | ||||||
| 		if p.tok.kind in [.key_in, .key_lock, .key_orelse] { // `in`, `lock`, `or` are v keywords that are also x86/arm/riscv instructions.
 | 		if p.tok.kind in [.key_in, .key_lock, .key_orelse] { // `in`, `lock`, `or` are v keywords that are also x86/arm/riscv instructions.
 | ||||||
| 			name = p.tok.kind.str() | 			name += p.tok.kind.str() | ||||||
| 			p.next() | 			p.next() | ||||||
| 		} else if p.tok.kind == .number { | 		} else if p.tok.kind == .number { | ||||||
| 			name = p.tok.lit | 			name += p.tok.lit | ||||||
| 			p.next() | 			p.next() | ||||||
| 		} else { | 		} else { | ||||||
| 			name = p.tok.lit | 			name += p.tok.lit | ||||||
| 			p.check(.name) | 			p.check(.name) | ||||||
| 		} | 		} | ||||||
| 		// dots are part of instructions for some riscv extensions
 | 		// dots are part of instructions for some riscv extensions
 | ||||||
| 		if arch in [.rv32, .rv64, .amd64] { | 		if arch in [.rv32, .rv64] { | ||||||
| 			for p.tok.kind == .dot { | 			for p.tok.kind == .dot { | ||||||
| 				name += '.' | 				name += '.' | ||||||
| 				p.next() | 				p.next() | ||||||
|  | @ -949,8 +959,9 @@ fn (mut p Parser) asm_stmt(is_top_level bool) ast.AsmStmt { | ||||||
| 								} | 								} | ||||||
| 							} | 							} | ||||||
| 							ast.IntegerLiteral { | 							ast.IntegerLiteral { | ||||||
| 								if is_directive || number_lit.val.ends_with('b') | 								if (is_directive || number_lit.val.ends_with('b') | ||||||
| 									|| number_lit.val.ends_with('f') { | 									|| number_lit.val.ends_with('f')) | ||||||
|  | 									&& !number_lit.val.starts_with('0x') { | ||||||
| 									args << ast.AsmDisp{ | 									args << ast.AsmDisp{ | ||||||
| 										val: number_lit.val | 										val: number_lit.val | ||||||
| 										pos: number_lit.pos | 										pos: number_lit.pos | ||||||
|  | @ -1217,11 +1228,12 @@ fn (mut p Parser) asm_addressing() ast.AsmAddressing { | ||||||
| 			} | 			} | ||||||
| 		} else if p.tok.kind == .number { | 		} else if p.tok.kind == .number { | ||||||
| 			displacement := if p.tok.kind == .name { | 			displacement := if p.tok.kind == .name { | ||||||
| 				x := ast.AsmArg(p.tok.lit) | 				p.reg_or_alias() | ||||||
| 				p.next() |  | ||||||
| 				x |  | ||||||
| 			} else { | 			} else { | ||||||
| 				x := ast.AsmArg(p.tok.lit) | 				x := ast.AsmArg(ast.AsmDisp{ | ||||||
|  | 					val: p.tok.lit | ||||||
|  | 					pos: p.tok.position() | ||||||
|  | 				}) | ||||||
| 				p.check(.number) | 				p.check(.number) | ||||||
| 				x | 				x | ||||||
| 			} | 			} | ||||||
|  | @ -1241,11 +1253,12 @@ fn (mut p Parser) asm_addressing() ast.AsmAddressing { | ||||||
| 			p.next() | 			p.next() | ||||||
| 
 | 
 | ||||||
| 			displacement := if p.tok.kind == .name { | 			displacement := if p.tok.kind == .name { | ||||||
| 				x := ast.AsmArg(p.tok.lit) | 				p.reg_or_alias() | ||||||
| 				p.next() |  | ||||||
| 				x |  | ||||||
| 			} else { | 			} else { | ||||||
| 				x := ast.AsmArg(p.tok.lit) | 				x := ast.AsmArg(ast.AsmDisp{ | ||||||
|  | 					val: p.tok.lit | ||||||
|  | 					pos: p.tok.position() | ||||||
|  | 				}) | ||||||
| 				p.check(.number) | 				p.check(.number) | ||||||
| 				x | 				x | ||||||
| 			} | 			} | ||||||
|  | @ -1262,11 +1275,12 @@ fn (mut p Parser) asm_addressing() ast.AsmAddressing { | ||||||
| 		if p.peek_tok.kind == .rsbr { | 		if p.peek_tok.kind == .rsbr { | ||||||
| 			if p.tok.kind == .number { | 			if p.tok.kind == .number { | ||||||
| 				displacement := if p.tok.kind == .name { | 				displacement := if p.tok.kind == .name { | ||||||
| 					x := ast.AsmArg(p.tok.lit) | 					p.reg_or_alias() | ||||||
| 					p.next() |  | ||||||
| 					x |  | ||||||
| 				} else { | 				} else { | ||||||
| 					x := ast.AsmArg(p.tok.lit) | 					x := ast.AsmArg(ast.AsmDisp{ | ||||||
|  | 						val: p.tok.lit | ||||||
|  | 						pos: p.tok.position() | ||||||
|  | 					}) | ||||||
| 					p.check(.number) | 					p.check(.number) | ||||||
| 					x | 					x | ||||||
| 				} | 				} | ||||||
|  | @ -1288,11 +1302,12 @@ fn (mut p Parser) asm_addressing() ast.AsmAddressing { | ||||||
| 			p.check(.number) | 			p.check(.number) | ||||||
| 			p.check(.plus) | 			p.check(.plus) | ||||||
| 			displacement := if p.tok.kind == .name { | 			displacement := if p.tok.kind == .name { | ||||||
| 				x := ast.AsmArg(p.tok.lit) | 				p.reg_or_alias() | ||||||
| 				p.next() |  | ||||||
| 				x |  | ||||||
| 			} else { | 			} else { | ||||||
| 				x := ast.AsmArg(p.tok.lit) | 				x := ast.AsmArg(ast.AsmDisp{ | ||||||
|  | 					val: p.tok.lit | ||||||
|  | 					pos: p.tok.position() | ||||||
|  | 				}) | ||||||
| 				p.check(.number) | 				p.check(.number) | ||||||
| 				x | 				x | ||||||
| 			} | 			} | ||||||
|  | @ -1308,11 +1323,12 @@ fn (mut p Parser) asm_addressing() ast.AsmAddressing { | ||||||
| 		} else if p.tok.kind == .plus { | 		} else if p.tok.kind == .plus { | ||||||
| 			p.next() | 			p.next() | ||||||
| 			displacement := if p.tok.kind == .name { | 			displacement := if p.tok.kind == .name { | ||||||
| 				x := ast.AsmArg(p.tok.lit) | 				p.reg_or_alias() | ||||||
| 				p.next() |  | ||||||
| 				x |  | ||||||
| 			} else { | 			} else { | ||||||
| 				x := ast.AsmArg(p.tok.lit) | 				x := ast.AsmArg(ast.AsmDisp{ | ||||||
|  | 					val: p.tok.lit | ||||||
|  | 					pos: p.tok.position() | ||||||
|  | 				}) | ||||||
| 				p.check(.number) | 				p.check(.number) | ||||||
| 				x | 				x | ||||||
| 			} | 			} | ||||||
|  | @ -1333,11 +1349,12 @@ fn (mut p Parser) asm_addressing() ast.AsmAddressing { | ||||||
| 		p.check(.number) | 		p.check(.number) | ||||||
| 		p.check(.plus) | 		p.check(.plus) | ||||||
| 		displacement := if p.tok.kind == .name { | 		displacement := if p.tok.kind == .name { | ||||||
| 			x := ast.AsmArg(p.tok.lit) | 			p.reg_or_alias() | ||||||
| 			p.next() |  | ||||||
| 			x |  | ||||||
| 		} else { | 		} else { | ||||||
| 			x := ast.AsmArg(p.tok.lit) | 			x := ast.AsmArg(ast.AsmDisp{ | ||||||
|  | 				val: p.tok.lit | ||||||
|  | 				pos: p.tok.position() | ||||||
|  | 			}) | ||||||
| 			p.check(.number) | 			p.check(.number) | ||||||
| 			x | 			x | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -80,6 +80,7 @@ fn test_inline_asm() { | ||||||
| 	asm amd64 { | 	asm amd64 { | ||||||
| 		movq [m], 7 // have to specify size with q
 | 		movq [m], 7 // have to specify size with q
 | ||||||
| 		; ; r (m) | 		; ; r (m) | ||||||
|  | 		; memory | ||||||
| 	} | 	} | ||||||
| 	assert l == 7 | 	assert l == 7 | ||||||
| 
 | 
 | ||||||
|  | @ -98,15 +99,15 @@ fn test_inline_asm() { | ||||||
| 
 | 
 | ||||||
| 	assert util.add(8, 9, 34, 7) == 58 // test .amd64.v imported files
 | 	assert util.add(8, 9, 34, 7) == 58 // test .amd64.v imported files
 | ||||||
| 
 | 
 | ||||||
| 	mut manu := Manu{} | 	mut o := Manu{} | ||||||
| 	asm amd64 { | 	asm amd64 { | ||||||
| 		mov eax, 0 | 		mov eax, 0 | ||||||
| 		cpuid | 		cpuid | ||||||
| 		; =b (manu.ebx) as ebx0 | 		; =b (o.ebx) as ebx0 | ||||||
| 		  =d (manu.edx) as edx0 | 		  =d (o.edx) as edx0 | ||||||
| 		  =c (manu.ecx) as ecx0 | 		  =c (o.ecx) as ecx0 | ||||||
| 	} | 	} | ||||||
| 	manu.str() | 	o.str() | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| [packed] | [packed] | ||||||
|  | @ -129,7 +130,10 @@ fn (m Manu) str() string { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // this test does not appear in i386 test since rip relative addressing was introduced in 64-bit mode
 | // this test does not appear in i386 test since rip relative addressing was introduced in 64-bit mode
 | ||||||
|  | // doesn't actually work
 | ||||||
|  | [if !macos] | ||||||
| fn test_rip_relative_label() { | fn test_rip_relative_label() { | ||||||
|  | 	$if !macos { | ||||||
| 		mut a := i64(4) | 		mut a := i64(4) | ||||||
| 		asm amd64 { | 		asm amd64 { | ||||||
| 			mov a, [rip + one_two_three] // see below
 | 			mov a, [rip + one_two_three] // see below
 | ||||||
|  | @ -137,12 +141,37 @@ fn test_rip_relative_label() { | ||||||
| 		} | 		} | ||||||
| 		assert a == 48321074923 | 		assert a == 48321074923 | ||||||
| 	} | 	} | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
|  | $if !macos { | ||||||
| 	asm amd64 { | 	asm amd64 { | ||||||
| 		.global one_two_three | 		.global one_two_three | ||||||
| 		one_two_three: | 		one_two_three: | ||||||
| 		.quad 48321074923 | 		.quad 48321074923 | ||||||
| 	} | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // this test does not appear in i386 test since rip relative addressing was introduced in 64-bit mode
 | ||||||
|  | // doesn't actually work
 | ||||||
|  | [if !macos] | ||||||
|  | fn test_rip_relative_label_byte() { | ||||||
|  | 	$if !macos { | ||||||
|  | 		mut a := int(4) | ||||||
|  | 		asm amd64 { | ||||||
|  | 			mov a, [rip + byte_sequence] // see below
 | ||||||
|  | 			; =r (a) | ||||||
|  | 		} | ||||||
|  | 		assert a == 0x480f3527 | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | $if !macos { | ||||||
|  | 	asm amd64 { | ||||||
|  | 		.global one_two_three | ||||||
|  | 		byte_sequence: | ||||||
|  | 		.byte 0x27, 0x35, 0x0f, 0x48 | ||||||
|  | 	} | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| fn test_flag_output() { | fn test_flag_output() { | ||||||
| 	a, b := 4, 9 | 	a, b := 4, 9 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue