@@ -1491,6 +1491,46 @@ fn asmPseudo(self: *Self, ops: Mir.Inst.Ops) !void {
14911491 });
14921492}
14931493
1494+ fn asmPseudoRegister(self: *Self, ops: Mir.Inst.Ops, reg: Register) !void {
1495+ assert(std.mem.startsWith(u8, @tagName(ops), "pseudo_") and
1496+ std.mem.endsWith(u8, @tagName(ops), "_r"));
1497+ _ = try self.addInst(.{
1498+ .tag = .pseudo,
1499+ .ops = ops,
1500+ .data = .{ .r = .{ .r1 = reg } },
1501+ });
1502+ }
1503+
1504+ fn asmPseudoImmediate(self: *Self, ops: Mir.Inst.Ops, imm: Immediate) !void {
1505+ assert(std.mem.startsWith(u8, @tagName(ops), "pseudo_") and
1506+ std.mem.endsWith(u8, @tagName(ops), "_i_s"));
1507+ _ = try self.addInst(.{
1508+ .tag = .pseudo,
1509+ .ops = ops,
1510+ .data = .{ .i = .{ .i = @bitCast(imm.signed) } },
1511+ });
1512+ }
1513+
1514+ fn asmPseudoRegisterRegister(self: *Self, ops: Mir.Inst.Ops, reg1: Register, reg2: Register) !void {
1515+ assert(std.mem.startsWith(u8, @tagName(ops), "pseudo_") and
1516+ std.mem.endsWith(u8, @tagName(ops), "_rr"));
1517+ _ = try self.addInst(.{
1518+ .tag = .pseudo,
1519+ .ops = ops,
1520+ .data = .{ .rr = .{ .r1 = reg1, .r2 = reg2 } },
1521+ });
1522+ }
1523+
1524+ fn asmPseudoRegisterImmediate(self: *Self, ops: Mir.Inst.Ops, reg: Register, imm: Immediate) !void {
1525+ assert(std.mem.startsWith(u8, @tagName(ops), "pseudo_") and
1526+ std.mem.endsWith(u8, @tagName(ops), "_ri_s"));
1527+ _ = try self.addInst(.{
1528+ .tag = .pseudo,
1529+ .ops = ops,
1530+ .data = .{ .ri = .{ .r1 = reg, .i = @bitCast(imm.signed) } },
1531+ });
1532+ }
1533+
14941534fn asmRegister(self: *Self, tag: Mir.Inst.FixedTag, reg: Register) !void {
14951535 _ = try self.addInst(.{
14961536 .tag = tag[1],
@@ -1877,7 +1917,10 @@ fn gen(self: *Self) InnerError!void {
18771917 const cc = abi.resolveCallingConvention(fn_info.cc, self.target.*);
18781918 if (cc != .Naked) {
18791919 try self.asmRegister(.{ ._, .push }, .rbp);
1920+ try self.asmPseudoImmediate(.pseudo_cfi_adjust_cfa_offset_i_s, Immediate.s(8));
1921+ try self.asmPseudoRegisterImmediate(.pseudo_cfi_rel_offset_ri_s, .rbp, Immediate.s(0));
18801922 try self.asmRegisterRegister(.{ ._, .mov }, .rbp, .rsp);
1923+ try self.asmPseudoRegister(.pseudo_cfi_def_cfa_register_r, .rbp);
18811924 const backpatch_push_callee_preserved_regs = try self.asmPlaceholder();
18821925 const backpatch_frame_align = try self.asmPlaceholder();
18831926 const backpatch_frame_align_extra = try self.asmPlaceholder();
@@ -1962,6 +2005,7 @@ fn gen(self: *Self) InnerError!void {
19622005 const backpatch_stack_dealloc = try self.asmPlaceholder();
19632006 const backpatch_pop_callee_preserved_regs = try self.asmPlaceholder();
19642007 try self.asmRegister(.{ ._, .pop }, .rbp);
2008+ try self.asmPseudoRegisterImmediate(.pseudo_cfi_def_cfa_ri_s, .rsp, Immediate.s(8));
19652009 try self.asmOpOnly(.{ ._, .ret });
19662010
19672011 const frame_layout = try self.computeFrameLayout(cc);
@@ -14038,7 +14082,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
1403814082 var mnem_it = mem.tokenizeAny(u8, line, " \t");
1403914083 var prefix: Instruction.Prefix = .none;
1404014084 const mnem_str = while (mnem_it.next()) |mnem_str| {
14041- if (mem.startsWith(u8, mnem_str, "#") ) continue :next_line;
14085+ if (mnem_str[0] == '#' ) continue :next_line;
1404214086 if (mem.startsWith(u8, mnem_str, "//")) continue :next_line;
1404314087 if (std.meta.stringToEnum(Instruction.Prefix, mnem_str)) |pre| {
1404414088 if (prefix != .none) return self.fail("extra prefix: '{s}'", .{mnem_str});
@@ -14063,8 +14107,14 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
1406314107 }
1406414108 label_gop.value_ptr.target = @intCast(self.mir_instructions.len);
1406514109 } else continue;
14110+ if (mnem_str[0] == '.') {
14111+ if (prefix != .none) return self.fail("prefixed directive: '{s} {s}'", .{ @tagName(prefix), mnem_str });
14112+ prefix = .directive;
14113+ }
1406614114
14067- var mnem_size: ?Memory.Size = if (mem.endsWith(u8, mnem_str, "b"))
14115+ var mnem_size: ?Memory.Size = if (prefix == .directive)
14116+ null
14117+ else if (mem.endsWith(u8, mnem_str, "b"))
1406814118 .byte
1406914119 else if (mem.endsWith(u8, mnem_str, "w"))
1407014120 .word
@@ -14095,7 +14145,9 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
1409514145 mnem_size = fixed_mnem_size;
1409614146 }
1409714147 const mnem_name = @tagName(mnem_tag);
14098- const mnem_fixed_tag: Mir.Inst.FixedTag = for (std.enums.values(Mir.Inst.Fixes)) |fixes| {
14148+ const mnem_fixed_tag: Mir.Inst.FixedTag = if (prefix == .directive)
14149+ .{ ._, .pseudo }
14150+ else for (std.enums.values(Mir.Inst.Fixes)) |fixes| {
1409914151 const fixes_name = @tagName(fixes);
1410014152 const space_i = mem.indexOfScalar(u8, fixes_name, ' ');
1410114153 const fixes_prefix = if (space_i) |i|
@@ -14116,7 +14168,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
1411614168 } else {
1411714169 assert(prefix != .none); // no combination of fixes produced a known mnemonic
1411814170 return self.fail("invalid prefix for mnemonic: '{s} {s}'", .{
14119- @tagName(prefix), mnem_str ,
14171+ @tagName(prefix), mnem_name ,
1412014172 });
1412114173 };
1412214174
@@ -14324,7 +14376,62 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
1432414376 } else return self.fail("invalid operand: '{s}'", .{op_str});
1432514377 } else if (op_it.next()) |op_str| return self.fail("extra operand: '{s}'", .{op_str});
1432614378
14327- (switch (ops[0]) {
14379+ (if (prefix == .directive) switch (mnem_tag) {
14380+ .@".cfi_def_cfa" => if (ops[0] == .reg and ops[1] == .imm and ops[2] == .none)
14381+ self.asmPseudoRegisterImmediate(.pseudo_cfi_def_cfa_ri_s, ops[0].reg, ops[1].imm)
14382+ else
14383+ error.InvalidInstruction,
14384+ .@".cfi_def_cfa_register" => if (ops[0] == .reg and ops[1] == .none)
14385+ self.asmPseudoRegister(.pseudo_cfi_def_cfa_register_r, ops[0].reg)
14386+ else
14387+ error.InvalidInstruction,
14388+ .@".cfi_def_cfa_offset" => if (ops[0] == .imm and ops[1] == .none)
14389+ self.asmPseudoImmediate(.pseudo_cfi_def_cfa_offset_i_s, ops[0].imm)
14390+ else
14391+ error.InvalidInstruction,
14392+ .@".cfi_adjust_cfa_offset" => if (ops[0] == .imm and ops[1] == .none)
14393+ self.asmPseudoImmediate(.pseudo_cfi_adjust_cfa_offset_i_s, ops[0].imm)
14394+ else
14395+ error.InvalidInstruction,
14396+ .@".cfi_offset" => if (ops[0] == .reg and ops[1] == .imm and ops[2] == .none)
14397+ self.asmPseudoRegisterImmediate(.pseudo_cfi_offset_ri_s, ops[0].reg, ops[1].imm)
14398+ else
14399+ error.InvalidInstruction,
14400+ .@".cfi_val_offset" => if (ops[0] == .reg and ops[1] == .imm and ops[2] == .none)
14401+ self.asmPseudoRegisterImmediate(.pseudo_cfi_val_offset_ri_s, ops[0].reg, ops[1].imm)
14402+ else
14403+ error.InvalidInstruction,
14404+ .@".cfi_rel_offset" => if (ops[0] == .reg and ops[1] == .imm and ops[2] == .none)
14405+ self.asmPseudoRegisterImmediate(.pseudo_cfi_rel_offset_ri_s, ops[0].reg, ops[1].imm)
14406+ else
14407+ error.InvalidInstruction,
14408+ .@".cfi_register" => if (ops[0] == .reg and ops[1] == .reg and ops[2] == .none)
14409+ self.asmPseudoRegisterRegister(.pseudo_cfi_register_rr, ops[0].reg, ops[1].reg)
14410+ else
14411+ error.InvalidInstruction,
14412+ .@".cfi_restore" => if (ops[0] == .reg and ops[1] == .none)
14413+ self.asmPseudoRegister(.pseudo_cfi_restore_r, ops[0].reg)
14414+ else
14415+ error.InvalidInstruction,
14416+ .@".cfi_undefined" => if (ops[0] == .reg and ops[1] == .none)
14417+ self.asmPseudoRegister(.pseudo_cfi_undefined_r, ops[0].reg)
14418+ else
14419+ error.InvalidInstruction,
14420+ .@".cfi_same_value" => if (ops[0] == .reg and ops[1] == .none)
14421+ self.asmPseudoRegister(.pseudo_cfi_same_value_r, ops[0].reg)
14422+ else
14423+ error.InvalidInstruction,
14424+ .@".cfi_remember_state" => if (ops[0] == .none)
14425+ self.asmPseudo(.pseudo_cfi_remember_state_none)
14426+ else
14427+ error.InvalidInstruction,
14428+ .@".cfi_restore_state" => if (ops[0] == .none)
14429+ self.asmPseudo(.pseudo_cfi_restore_state_none)
14430+ else
14431+ error.InvalidInstruction,
14432+ .@".cfi_escape" => error.InvalidInstruction,
14433+ else => unreachable,
14434+ } else switch (ops[0]) {
1432814435 .none => self.asmOpOnly(mnem_fixed_tag),
1432914436 .reg => |reg0| switch (ops[1]) {
1433014437 .none => self.asmRegister(mnem_fixed_tag, reg0),
@@ -19210,14 +19317,6 @@ fn fail(self: *Self, comptime format: []const u8, args: anytype) InnerError {
1921019317 return error.CodegenFail;
1921119318}
1921219319
19213- fn failSymbol(self: *Self, comptime format: []const u8, args: anytype) InnerError {
19214- @branchHint(.cold);
19215- assert(self.err_msg == null);
19216- const gpa = self.gpa;
19217- self.err_msg = try ErrorMsg.create(gpa, self.src_loc, format, args);
19218- return error.CodegenFail;
19219- }
19220-
1922119320fn parseRegName(name: []const u8) ?Register {
1922219321 if (@hasDecl(Register, "parseRegName")) {
1922319322 return Register.parseRegName(name);
0 commit comments