@@ -1491,6 +1491,46 @@ fn asmPseudo(self: *Self, ops: Mir.Inst.Ops) !void {
1491
1491
});
1492
1492
}
1493
1493
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
+
1494
1534
fn asmRegister(self: *Self, tag: Mir.Inst.FixedTag, reg: Register) !void {
1495
1535
_ = try self.addInst(.{
1496
1536
.tag = tag[1],
@@ -1877,7 +1917,10 @@ fn gen(self: *Self) InnerError!void {
1877
1917
const cc = abi.resolveCallingConvention(fn_info.cc, self.target.*);
1878
1918
if (cc != .Naked) {
1879
1919
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));
1880
1922
try self.asmRegisterRegister(.{ ._, .mov }, .rbp, .rsp);
1923
+ try self.asmPseudoRegister(.pseudo_cfi_def_cfa_register_r, .rbp);
1881
1924
const backpatch_push_callee_preserved_regs = try self.asmPlaceholder();
1882
1925
const backpatch_frame_align = try self.asmPlaceholder();
1883
1926
const backpatch_frame_align_extra = try self.asmPlaceholder();
@@ -1962,6 +2005,7 @@ fn gen(self: *Self) InnerError!void {
1962
2005
const backpatch_stack_dealloc = try self.asmPlaceholder();
1963
2006
const backpatch_pop_callee_preserved_regs = try self.asmPlaceholder();
1964
2007
try self.asmRegister(.{ ._, .pop }, .rbp);
2008
+ try self.asmPseudoRegisterImmediate(.pseudo_cfi_def_cfa_ri_s, .rsp, Immediate.s(8));
1965
2009
try self.asmOpOnly(.{ ._, .ret });
1966
2010
1967
2011
const frame_layout = try self.computeFrameLayout(cc);
@@ -14038,7 +14082,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
14038
14082
var mnem_it = mem.tokenizeAny(u8, line, " \t");
14039
14083
var prefix: Instruction.Prefix = .none;
14040
14084
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;
14042
14086
if (mem.startsWith(u8, mnem_str, "//")) continue :next_line;
14043
14087
if (std.meta.stringToEnum(Instruction.Prefix, mnem_str)) |pre| {
14044
14088
if (prefix != .none) return self.fail("extra prefix: '{s}'", .{mnem_str});
@@ -14063,8 +14107,14 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
14063
14107
}
14064
14108
label_gop.value_ptr.target = @intCast(self.mir_instructions.len);
14065
14109
} 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
+ }
14066
14114
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"))
14068
14118
.byte
14069
14119
else if (mem.endsWith(u8, mnem_str, "w"))
14070
14120
.word
@@ -14095,7 +14145,9 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
14095
14145
mnem_size = fixed_mnem_size;
14096
14146
}
14097
14147
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| {
14099
14151
const fixes_name = @tagName(fixes);
14100
14152
const space_i = mem.indexOfScalar(u8, fixes_name, ' ');
14101
14153
const fixes_prefix = if (space_i) |i|
@@ -14116,7 +14168,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
14116
14168
} else {
14117
14169
assert(prefix != .none); // no combination of fixes produced a known mnemonic
14118
14170
return self.fail("invalid prefix for mnemonic: '{s} {s}'", .{
14119
- @tagName(prefix), mnem_str ,
14171
+ @tagName(prefix), mnem_name ,
14120
14172
});
14121
14173
};
14122
14174
@@ -14324,7 +14376,62 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
14324
14376
} else return self.fail("invalid operand: '{s}'", .{op_str});
14325
14377
} else if (op_it.next()) |op_str| return self.fail("extra operand: '{s}'", .{op_str});
14326
14378
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]) {
14328
14435
.none => self.asmOpOnly(mnem_fixed_tag),
14329
14436
.reg => |reg0| switch (ops[1]) {
14330
14437
.none => self.asmRegister(mnem_fixed_tag, reg0),
@@ -19210,14 +19317,6 @@ fn fail(self: *Self, comptime format: []const u8, args: anytype) InnerError {
19210
19317
return error.CodegenFail;
19211
19318
}
19212
19319
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
-
19221
19320
fn parseRegName(name: []const u8) ?Register {
19222
19321
if (@hasDecl(Register, "parseRegName")) {
19223
19322
return Register.parseRegName(name);
0 commit comments