aboutsummaryrefslogtreecommitdiff
path: root/src/codegen
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2025-07-11 22:03:00 -0700
committerAndrew Kelley <andrew@ziglang.org>2025-07-16 10:23:02 -0700
commitfcafc63f3d5ce250e404871571aa3b26aeae6611 (patch)
tree49e3354bb24dd1d8663127598e4f2f63942f2655 /src/codegen
parent6002514b72cb2a571abc6ac4ac7fbec44d6302b1 (diff)
downloadzig-fcafc63f3d5ce250e404871571aa3b26aeae6611.tar.gz
zig-fcafc63f3d5ce250e404871571aa3b26aeae6611.zip
inline assembly: use types
until now these were stringly typed. it's kinda obvious when you think about it.
Diffstat (limited to 'src/codegen')
-rw-r--r--src/codegen/c.zig43
-rw-r--r--src/codegen/llvm.zig76
-rw-r--r--src/codegen/spirv.zig18
3 files changed, 77 insertions, 60 deletions
diff --git a/src/codegen/c.zig b/src/codegen/c.zig
index 61bd5259ae..955a83bc33 100644
--- a/src/codegen/c.zig
+++ b/src/codegen/c.zig
@@ -5545,11 +5545,11 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
const zcu = pt.zcu;
const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
const extra = f.air.extraData(Air.Asm, ty_pl.payload);
- const is_volatile = @as(u1, @truncate(extra.data.flags >> 31)) != 0;
- const clobbers_len: u31 = @truncate(extra.data.flags);
+ const is_volatile = extra.data.flags.is_volatile;
+ const outputs_len = extra.data.flags.outputs_len;
const gpa = f.object.dg.gpa;
var extra_i: usize = extra.end;
- const outputs: []const Air.Inst.Ref = @ptrCast(f.air.extra.items[extra_i..][0..extra.data.outputs_len]);
+ const outputs: []const Air.Inst.Ref = @ptrCast(f.air.extra.items[extra_i..][0..outputs_len]);
extra_i += outputs.len;
const inputs: []const Air.Inst.Ref = @ptrCast(f.air.extra.items[extra_i..][0..extra.data.inputs_len]);
extra_i += inputs.len;
@@ -5645,12 +5645,6 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
try f.object.newline();
}
}
- for (0..clobbers_len) |_| {
- const clobber = mem.sliceTo(mem.sliceAsBytes(f.air.extra.items[extra_i..]), 0);
- // This equation accounts for the fact that even if we have exactly 4 bytes
- // for the string, we still use the next u32 for the null terminator.
- extra_i += clobber.len / 4 + 1;
- }
{
const asm_source = mem.sliceAsBytes(f.air.extra.items[extra_i..])[0..extra.data.source_len];
@@ -5757,17 +5751,28 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
try w.writeByte(')');
}
try w.writeByte(':');
- for (0..clobbers_len) |clobber_i| {
- const clobber = mem.sliceTo(mem.sliceAsBytes(f.air.extra.items[extra_i..]), 0);
- // This equation accounts for the fact that even if we have exactly 4 bytes
- // for the string, we still use the next u32 for the null terminator.
- extra_i += clobber.len / 4 + 1;
-
- if (clobber.len == 0) continue;
-
- if (clobber_i > 0) try w.writeByte(',');
- try w.print(" {f}", .{fmtStringLiteral(clobber, null)});
+ const ip = &zcu.intern_pool;
+ const aggregate = ip.indexToKey(extra.data.clobbers).aggregate;
+ const struct_type: Type = .fromInterned(aggregate.ty);
+ switch (aggregate.storage) {
+ .elems => |elems| for (elems, 0..) |elem, i| switch (elem) {
+ .bool_true => {
+ const name = struct_type.structFieldName(i, zcu).toSlice(ip).?;
+ assert(name.len != 0);
+ try w.print(" {f}", .{fmtStringLiteral(name, null)});
+ (try w.writableArray(1))[0] = ',';
+ },
+ .bool_false => continue,
+ else => unreachable,
+ },
+ .repeated_elem => |elem| switch (elem) {
+ .bool_true => @panic("TODO"),
+ .bool_false => {},
+ else => unreachable,
+ },
+ .bytes => @panic("TODO"),
}
+ w.undo(1); // erase the last comma
try w.writeAll(");");
try f.object.newline();
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig
index e726a2bdd3..51e861cf6e 100644
--- a/src/codegen/llvm.zig
+++ b/src/codegen/llvm.zig
@@ -7241,19 +7241,20 @@ pub const FuncGen = struct {
const o = self.ng.object;
const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
const extra = self.air.extraData(Air.Asm, ty_pl.payload);
- const is_volatile = @as(u1, @truncate(extra.data.flags >> 31)) != 0;
- const clobbers_len: u31 = @truncate(extra.data.flags);
+ const is_volatile = extra.data.flags.is_volatile;
+ const outputs_len = extra.data.flags.outputs_len;
+ const gpa = self.gpa;
var extra_i: usize = extra.end;
- const outputs: []const Air.Inst.Ref = @ptrCast(self.air.extra.items[extra_i..][0..extra.data.outputs_len]);
+ const outputs: []const Air.Inst.Ref = @ptrCast(self.air.extra.items[extra_i..][0..outputs_len]);
extra_i += outputs.len;
const inputs: []const Air.Inst.Ref = @ptrCast(self.air.extra.items[extra_i..][0..extra.data.inputs_len]);
extra_i += inputs.len;
var llvm_constraints: std.ArrayListUnmanaged(u8) = .empty;
- defer llvm_constraints.deinit(self.gpa);
+ defer llvm_constraints.deinit(gpa);
- var arena_allocator = std.heap.ArenaAllocator.init(self.gpa);
+ var arena_allocator = std.heap.ArenaAllocator.init(gpa);
defer arena_allocator.deinit();
const arena = arena_allocator.allocator();
@@ -7290,7 +7291,7 @@ pub const FuncGen = struct {
// for the string, we still use the next u32 for the null terminator.
extra_i += (constraint.len + name.len + (2 + 3)) / 4;
- try llvm_constraints.ensureUnusedCapacity(self.gpa, constraint.len + 3);
+ try llvm_constraints.ensureUnusedCapacity(gpa, constraint.len + 3);
if (total_i != 0) {
llvm_constraints.appendAssumeCapacity(',');
}
@@ -7399,7 +7400,7 @@ pub const FuncGen = struct {
}
}
- try llvm_constraints.ensureUnusedCapacity(self.gpa, constraint.len + 1);
+ try llvm_constraints.ensureUnusedCapacity(gpa, constraint.len + 1);
if (total_i != 0) {
llvm_constraints.appendAssumeCapacity(',');
}
@@ -7456,7 +7457,7 @@ pub const FuncGen = struct {
llvm_param_types[llvm_param_i] = llvm_elem_ty;
}
- try llvm_constraints.print(self.gpa, ",{d}", .{output_index});
+ try llvm_constraints.print(gpa, ",{d}", .{output_index});
// In the case of indirect inputs, LLVM requires the callsite to have
// an elementtype(<ty>) attribute.
@@ -7466,24 +7467,41 @@ pub const FuncGen = struct {
total_i += 1;
}
- {
- var clobber_i: u32 = 0;
- while (clobber_i < clobbers_len) : (clobber_i += 1) {
- const clobber = std.mem.sliceTo(std.mem.sliceAsBytes(self.air.extra.items[extra_i..]), 0);
- // This equation accounts for the fact that even if we have exactly 4 bytes
- // for the string, we still use the next u32 for the null terminator.
- extra_i += clobber.len / 4 + 1;
-
- try llvm_constraints.ensureUnusedCapacity(self.gpa, clobber.len + 4);
- if (total_i != 0) {
- llvm_constraints.appendAssumeCapacity(',');
+ const ip = &zcu.intern_pool;
+ const aggregate = ip.indexToKey(extra.data.clobbers).aggregate;
+ const struct_type: Type = .fromInterned(aggregate.ty);
+ switch (aggregate.storage) {
+ .elems => |elems| for (elems, 0..) |elem, i| {
+ switch (elem) {
+ .bool_true => {
+ const name = struct_type.structFieldName(i, zcu).toSlice(ip).?;
+ try llvm_constraints.ensureUnusedCapacity(gpa, name.len + 4);
+ if (total_i != 0) llvm_constraints.appendAssumeCapacity(',');
+ llvm_constraints.appendSliceAssumeCapacity("~{");
+ llvm_constraints.appendSliceAssumeCapacity(name);
+ llvm_constraints.appendSliceAssumeCapacity("}");
+
+ total_i += 1;
+ },
+ .bool_false => continue,
+ else => unreachable,
}
- llvm_constraints.appendSliceAssumeCapacity("~{");
- llvm_constraints.appendSliceAssumeCapacity(clobber);
- llvm_constraints.appendSliceAssumeCapacity("}");
+ },
+ .repeated_elem => |elem| switch (elem) {
+ .bool_true => for (0..struct_type.structFieldCount(zcu)) |i| {
+ const name = struct_type.structFieldName(i, zcu).toSlice(ip).?;
+ try llvm_constraints.ensureUnusedCapacity(gpa, name.len + 4);
+ if (total_i != 0) llvm_constraints.appendAssumeCapacity(',');
+ llvm_constraints.appendSliceAssumeCapacity("~{");
+ llvm_constraints.appendSliceAssumeCapacity(name);
+ llvm_constraints.appendSliceAssumeCapacity("}");
- total_i += 1;
- }
+ total_i += 1;
+ },
+ .bool_false => {},
+ else => unreachable,
+ },
+ .bytes => @panic("TODO"),
}
// We have finished scanning through all inputs/outputs, so the number of
@@ -7497,13 +7515,13 @@ pub const FuncGen = struct {
// to be buggy and regress often.
switch (target.cpu.arch) {
.x86_64, .x86 => {
- if (total_i != 0) try llvm_constraints.append(self.gpa, ',');
- try llvm_constraints.appendSlice(self.gpa, "~{dirflag},~{fpsr},~{flags}");
+ if (total_i != 0) try llvm_constraints.append(gpa, ',');
+ try llvm_constraints.appendSlice(gpa, "~{dirflag},~{fpsr},~{flags}");
total_i += 3;
},
.mips, .mipsel, .mips64, .mips64el => {
- if (total_i != 0) try llvm_constraints.append(self.gpa, ',');
- try llvm_constraints.appendSlice(self.gpa, "~{$1}");
+ if (total_i != 0) try llvm_constraints.append(gpa, ',');
+ try llvm_constraints.appendSlice(gpa, "~{$1}");
total_i += 1;
},
else => {},
@@ -7512,7 +7530,7 @@ pub const FuncGen = struct {
const asm_source = std.mem.sliceAsBytes(self.air.extra.items[extra_i..])[0..extra.data.source_len];
// hackety hacks until stage2 has proper inline asm in the frontend.
- var rendered_template = std.ArrayList(u8).init(self.gpa);
+ var rendered_template = std.ArrayList(u8).init(gpa);
defer rendered_template.deinit();
const State = enum { start, percent, input, modifier };
diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig
index 255e957c8b..292f5a62fc 100644
--- a/src/codegen/spirv.zig
+++ b/src/codegen/spirv.zig
@@ -6387,13 +6387,13 @@ const NavGen = struct {
const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
const extra = self.air.extraData(Air.Asm, ty_pl.payload);
- const is_volatile = @as(u1, @truncate(extra.data.flags >> 31)) != 0;
- const clobbers_len: u31 = @truncate(extra.data.flags);
+ const is_volatile = extra.data.flags.is_volatile;
+ const outputs_len = extra.data.flags.outputs_len;
if (!is_volatile and self.liveness.isUnused(inst)) return null;
var extra_i: usize = extra.end;
- const outputs: []const Air.Inst.Ref = @ptrCast(self.air.extra.items[extra_i..][0..extra.data.outputs_len]);
+ const outputs: []const Air.Inst.Ref = @ptrCast(self.air.extra.items[extra_i..][0..outputs_len]);
extra_i += outputs.len;
const inputs: []const Air.Inst.Ref = @ptrCast(self.air.extra.items[extra_i..][0..extra.data.inputs_len]);
extra_i += inputs.len;
@@ -6402,7 +6402,7 @@ const NavGen = struct {
return self.todo("implement inline asm with more than 1 output", .{});
}
- var as = SpvAssembler{
+ var as: SpvAssembler = .{
.gpa = self.gpa,
.spv = self.spv,
.func = &self.func,
@@ -6486,14 +6486,8 @@ const NavGen = struct {
}
}
- {
- var clobber_i: u32 = 0;
- while (clobber_i < clobbers_len) : (clobber_i += 1) {
- const clobber = std.mem.sliceTo(std.mem.sliceAsBytes(self.air.extra.items[extra_i..]), 0);
- extra_i += clobber.len / 4 + 1;
- // TODO: Record clobber and use it somewhere.
- }
- }
+ // TODO: do something with clobbers
+ _ = extra.data.clobbers;
const asm_source = std.mem.sliceAsBytes(self.air.extra.items[extra_i..])[0..extra.data.source_len];