authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2026-02-21 16:52:34-05:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2026-02-21 18:10:50-05:00
logd7f90722f75c887eb9f2a3f0603ce2d2f7ed7d84
treed22309f4089e936767ed6749e423c4cbee43a3c2
parentcd02b1703b6acad7e76f3592b0e637ff6a7c8c99

x86_64: fix parsing of sib operands


1 files changed, 59 insertions(+), 25 deletions(-)

src/codegen/x86_64/CodeGen.zig+59-25
......@@ -177397,7 +177397,10 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
177397177397 label_gop.value_ptr.target = @intCast(self.mir_instructions.len);
177398177398 } else continue;
177399177399 if (mnem_str[0] == '.') {
177400 if (prefix != .none) return self.fail("prefixed directive: '{s} {s}'", .{ @tagName(prefix), mnem_str });
177400 if (prefix != .none) return self.fail("prefixed directive: '{s} {s}'", .{
177401 @tagName(prefix),
177402 mnem_str,
177403 });
177401177404 prefix = .directive;
177402177405 }
177403177406
......@@ -177426,7 +177429,8 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
177426177429 else if (std.mem.endsWith(u8, mnem_str, "l"))
177427177430 .dword
177428177431 else if (std.mem.endsWith(u8, mnem_str, "q") and
177429 (std.mem.indexOfScalar(u8, "vp", mnem_str[0]) == null or !std.mem.endsWith(u8, mnem_str, "dq")))
177432 (std.mem.indexOfScalar(u8, "vp", mnem_str[0]) == null or
177433 !std.mem.endsWith(u8, mnem_str, "dq")))
177430177434 .qword
177431177435 else if (std.mem.endsWith(u8, mnem_str, "t"))
177432177436 .tbyte
......@@ -177463,23 +177467,40 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
177463177467 mnem_size = .init(fixed_mnem_size);
177464177468 }
177465177469
177470 const ops_str = mnem_it.rest();
177471 var ops_index: usize = 0;
177466177472 var ops: [4]Operand = @splat(.none);
177467177473 var ops_len: usize = 0;
177468
177469 var last_op = false;
177470 var op_it = std.mem.splitScalar(u8, mnem_it.rest(), ',');
177471177474 next_op: for (&ops, 0..) |*op, op_index| {
177472 const op_str = while (!last_op) {
177473 const full_str = op_it.next() orelse break :next_op;
177474 const code_str = if (std.mem.indexOfScalar(u8, full_str, '#') orelse
177475 std.mem.indexOf(u8, full_str, "//")) |comment|
177476 code: {
177477 last_op = true;
177478 break :code full_str[0..comment];
177479 } else full_str;
177480 const trim_str = std.mem.trim(u8, code_str, " \t*");
177481 if (trim_str.len > 0) break trim_str;
177482 } else break;
177475 const op_str = while (true) {
177476 const op_start = ops_index;
177477 if (ops_str.len - op_start == 0) break :next_op;
177478 const full_op_str = while (true) {
177479 const op_end = std.mem.findAnyPos(u8, ops_str, ops_index, ",(") orelse {
177480 ops_index = ops_str.len;
177481 break ops_str[op_start..];
177482 };
177483 switch (ops_str[op_end]) {
177484 else => unreachable,
177485 ',' => {
177486 ops_index = op_end + 1;
177487 break ops_str[op_start..op_end];
177488 },
177489 '(' => ops_index = (std.mem.findScalarPos(u8, ops_str, op_end + 1, ')') orelse {
177490 ops_index = ops_str.len;
177491 break ops_str[op_start..];
177492 }) + 1,
177493 }
177494 };
177495 const untrimmed_op_str = if (std.mem.indexOfScalar(u8, full_op_str, '#') orelse
177496 std.mem.indexOf(u8, full_op_str, "//")) |comment|
177497 untrimmed_op_str: {
177498 ops_index = ops_str.len;
177499 break :untrimmed_op_str full_op_str[0..comment];
177500 } else full_op_str;
177501 const trimmed_op_str = std.mem.trim(u8, untrimmed_op_str, " \t*");
177502 if (trimmed_op_str.len > 0) break trimmed_op_str;
177503 };
177483177504 if (std.mem.startsWith(u8, op_str, "%%")) {
177484177505 const colon = std.mem.indexOfScalarPos(u8, op_str, "%%".len + 2, ':');
177485177506 const reg = parseRegName(op_str["%%".len .. colon orelse op_str.len]) orelse
......@@ -177496,7 +177517,8 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
177496177517 } },
177497177518 } };
177498177519 } else {
177499 if (mnem_size.use(op_index)) |size| if (reg.size().bitSize(self.target) != size.bitSize(self.target))
177520 if (mnem_size.use(op_index)) |size| if (reg.size().bitSize(self.target) !=
177521 size.bitSize(self.target))
177500177522 return self.fail("invalid register size: '{s}'", .{op_str});
177501177523 op.* = .{ .reg = reg };
177502177524 }
......@@ -177510,15 +177532,20 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
177510177532 arg_map.get(op_str["%[".len .. colon orelse op_str.len - "]".len]) orelse
177511177533 return self.fail("no matching constraint: '{s}'", .{op_str})
177512177534 ]) {
177513 .immediate => |imm| if (std.mem.eql(u8, modifier, "") or std.mem.eql(u8, modifier, "c"))
177535 .immediate => |imm| if (std.mem.eql(u8, modifier, "") or
177536 std.mem.eql(u8, modifier, "c"))
177514177537 .{ .imm = .u(imm) }
177515177538 else
177516177539 return self.fail("invalid modifier: '{s}'", .{modifier}),
177517177540 .register => |reg| if (std.mem.eql(u8, modifier, ""))
177518 .{ .reg = if (mnem_size.use(op_index)) |size| reg.toSize(size, self.target) else reg }
177541 .{ .reg = if (mnem_size.use(op_index)) |size|
177542 reg.toSize(size, self.target)
177543 else
177544 reg }
177519177545 else
177520177546 return self.fail("invalid modifier: '{s}'", .{modifier}),
177521 .memory => |addr| if (std.mem.eql(u8, modifier, "") or std.mem.eql(u8, modifier, "P"))
177547 .memory => |addr| if (std.mem.eql(u8, modifier, "") or
177548 std.mem.eql(u8, modifier, "P"))
177522177549 .{ .mem = .{
177523177550 .base = .{ .reg = .ds },
177524177551 .mod = .{ .rm = .{
......@@ -177564,7 +177591,9 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
177564177591 else
177565177592 return self.fail("invalid modifier: '{s}'", .{modifier}),
177566177593 .lea_extern_func => |extern_func| if (std.mem.eql(u8, modifier, "P"))
177567 .{ .reg = try self.copyToTmpRegister(.usize, .{ .lea_extern_func = extern_func }) }
177594 .{ .reg = try self.copyToTmpRegister(.usize, .{
177595 .lea_extern_func = extern_func,
177596 }) }
177568177597 else
177569177598 return self.fail("invalid modifier: '{s}'", .{modifier}),
177570177599 else => return self.fail("invalid constraint: '{s}'", .{op_str}),
......@@ -177579,7 +177608,8 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
177579177608 } else if (std.mem.endsWith(u8, op_str, ")")) {
177580177609 const open = std.mem.indexOfScalar(u8, op_str, '(') orelse
177581177610 return self.fail("invalid operand: '{s}'", .{op_str});
177582 var sib_it = std.mem.splitScalar(u8, op_str[open + "(".len .. op_str.len - ")".len], ',');
177611 var sib_it =
177612 std.mem.splitScalar(u8, op_str[open + "(".len .. op_str.len - ")".len], ',');
177583177613 const base_str = sib_it.next() orelse
177584177614 return self.fail("invalid memory operand: '{s}'", .{op_str});
177585177615 if (base_str.len > 0 and !std.mem.startsWith(u8, base_str, "%%"))
......@@ -177626,7 +177656,8 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
177626177656 else
177627177657 .none,
177628177658 .mod = .{ .rm = .{
177629 .size = mnem_size.use(op_index) orelse return self.fail("unknown size: '{s}'", .{op_str}),
177659 .size = mnem_size.use(op_index) orelse
177660 return self.fail("unknown size: '{s}'", .{op_str}),
177630177661 .index = if (index_str.len > 0)
177631177662 parseRegName(index_str["%%".len..]) orelse
177632177663 return self.fail("invalid index register: '{s}'", .{op_str})
......@@ -177675,7 +177706,9 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
177675177706 op.* = .{ .inst = label_gop.value_ptr.target };
177676177707 } else return self.fail("invalid operand: '{s}'", .{op_str});
177677177708 ops_len += 1;
177678 } else if (op_it.next()) |op_str| return self.fail("extra operand: '{s}'", .{op_str});
177709 } else if (ops_str.len - ops_index > 0) return self.fail("extra operand: '{s}'", .{
177710 ops_str[ops_index..],
177711 });
177679177712
177680177713 // convert from att syntax to intel syntax
177681177714 std.mem.reverse(Operand, ops[0..ops_len]);
......@@ -177695,7 +177728,8 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void {
177695177728 else => unreachable,
177696177729 }),
177697177730 }) catch unreachable;
177698 if (std.meta.stringToEnum(encoder.Instruction.Mnemonic, intel_mnem_str)) |intel_mnem_tag| mnem_tag = intel_mnem_tag;
177731 if (std.meta.stringToEnum(encoder.Instruction.Mnemonic, intel_mnem_str)) |intel_mnem_tag|
177732 mnem_tag = intel_mnem_tag;
177699177733 }
177700177734 const mnem_name = @tagName(mnem_tag);
177701177735 const mnem_fixed_tag: Mir.Inst.FixedTag = if (prefix == .directive)