aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Air.zig2
-rw-r--r--src/Sema.zig20
-rw-r--r--src/arch/aarch64/CodeGen.zig6
-rw-r--r--src/arch/arm/CodeGen.zig6
-rw-r--r--src/arch/riscv64/CodeGen.zig6
-rw-r--r--src/arch/x86_64/CodeGen.zig6
-rw-r--r--src/codegen/llvm.zig39
7 files changed, 63 insertions, 22 deletions
diff --git a/src/Air.zig b/src/Air.zig
index 39215495c3..d02491ff89 100644
--- a/src/Air.zig
+++ b/src/Air.zig
@@ -815,6 +815,8 @@ pub const VectorCmp = struct {
/// terminated string. pad to the next u32 after the null byte.
/// 3. for every inputs_len
/// - constraint: memory at this position is reinterpreted as a null
+/// terminated string.
+/// - name: memory at this position is reinterpreted as a null
/// terminated string. pad to the next u32 after the null byte.
/// 4. for every clobbers_len
/// - clobber_name: memory at this position is reinterpreted as a null
diff --git a/src/Sema.zig b/src/Sema.zig
index 112939c995..9f5d6d5f9e 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -10295,15 +10295,12 @@ fn zirAsm(
};
const args = try sema.arena.alloc(Air.Inst.Ref, inputs_len);
- const inputs = try sema.arena.alloc([]const u8, inputs_len);
+ const inputs = try sema.arena.alloc(struct { c: []const u8, n: []const u8 }, inputs_len);
for (args) |*arg, arg_i| {
const input = sema.code.extraData(Zir.Inst.Asm.Input, extra_i);
extra_i = input.end;
- const name = sema.code.nullTerminatedString(input.data.name);
- _ = name; // TODO: use the name
-
const uncasted_arg = sema.resolveInst(input.data.operand);
const uncasted_arg_ty = sema.typeOf(uncasted_arg);
switch (uncasted_arg_ty.zigTypeTag()) {
@@ -10313,8 +10310,9 @@ fn zirAsm(
}
const constraint = sema.code.nullTerminatedString(input.data.constraint);
- needed_capacity += constraint.len / 4 + 1;
- inputs[arg_i] = constraint;
+ const name = sema.code.nullTerminatedString(input.data.name);
+ needed_capacity += (constraint.len + name.len + 1) / 4 + 1;
+ inputs[arg_i] = .{ .c = constraint, .n = name };
}
const clobbers = try sema.arena.alloc([]const u8, clobbers_len);
@@ -10353,11 +10351,13 @@ fn zirAsm(
buffer[o.constraint.len] = 0;
sema.air_extra.items.len += o.constraint.len / 4 + 1;
}
- for (inputs) |constraint| {
+ for (inputs) |input| {
const buffer = mem.sliceAsBytes(sema.air_extra.unusedCapacitySlice());
- mem.copy(u8, buffer, constraint);
- buffer[constraint.len] = 0;
- sema.air_extra.items.len += constraint.len / 4 + 1;
+ mem.copy(u8, buffer, input.c);
+ buffer[input.c.len] = 0;
+ mem.copy(u8, buffer[input.c.len + 1 ..], input.n);
+ buffer[input.c.len + 1 + input.n.len] = 0;
+ sema.air_extra.items.len += (input.c.len + input.n.len + 1) / 4 + 1;
}
for (clobbers) |clobber| {
const buffer = mem.sliceAsBytes(sema.air_extra.unusedCapacitySlice());
diff --git a/src/arch/aarch64/CodeGen.zig b/src/arch/aarch64/CodeGen.zig
index 142611d083..ea946d6ba6 100644
--- a/src/arch/aarch64/CodeGen.zig
+++ b/src/arch/aarch64/CodeGen.zig
@@ -3200,10 +3200,12 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
} else null;
for (inputs) |input| {
- const constraint = std.mem.sliceTo(std.mem.sliceAsBytes(self.air.extra[extra_i..]), 0);
+ const input_bytes = std.mem.sliceAsBytes(self.air.extra[extra_i..]);
+ const constraint = std.mem.sliceTo(input_bytes, 0);
+ const input_name = std.mem.sliceTo(input_bytes[constraint.len + 1 ..], 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 += constraint.len / 4 + 1;
+ extra_i += (constraint.len + input_name.len + 1) / 4 + 1;
if (constraint.len < 3 or constraint[0] != '{' or constraint[constraint.len - 1] != '}') {
return self.fail("unrecognized asm input constraint: '{s}'", .{constraint});
diff --git a/src/arch/arm/CodeGen.zig b/src/arch/arm/CodeGen.zig
index 6e03dbf4fa..85545e33a5 100644
--- a/src/arch/arm/CodeGen.zig
+++ b/src/arch/arm/CodeGen.zig
@@ -3609,10 +3609,12 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
} else null;
for (inputs) |input| {
- const constraint = std.mem.sliceTo(std.mem.sliceAsBytes(self.air.extra[extra_i..]), 0);
+ const input_bytes = std.mem.sliceAsBytes(self.air.extra[extra_i..]);
+ const constraint = std.mem.sliceTo(input_bytes, 0);
+ const input_name = std.mem.sliceTo(input_bytes[constraint.len + 1 ..], 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 += constraint.len / 4 + 1;
+ extra_i += (constraint.len + input_name.len + 1) / 4 + 1;
if (constraint.len < 3 or constraint[0] != '{' or constraint[constraint.len - 1] != '}') {
return self.fail("unrecognized asm input constraint: '{s}'", .{constraint});
diff --git a/src/arch/riscv64/CodeGen.zig b/src/arch/riscv64/CodeGen.zig
index bbc880f0bd..ac12bbceaf 100644
--- a/src/arch/riscv64/CodeGen.zig
+++ b/src/arch/riscv64/CodeGen.zig
@@ -2113,10 +2113,12 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
} else null;
for (inputs) |input| {
- const constraint = std.mem.sliceTo(std.mem.sliceAsBytes(self.air.extra[extra_i..]), 0);
+ const input_bytes = std.mem.sliceAsBytes(self.air.extra[extra_i..]);
+ const constraint = std.mem.sliceTo(input_bytes, 0);
+ const input_name = std.mem.sliceTo(input_bytes[constraint.len + 1 ..], 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 += constraint.len / 4 + 1;
+ extra_i += (constraint.len + input_name.len + 1) / 4 + 1;
if (constraint.len < 3 or constraint[0] != '{' or constraint[constraint.len - 1] != '}') {
return self.fail("unrecognized asm input constraint: '{s}'", .{constraint});
diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig
index 9ecd2d4551..b093209a2e 100644
--- a/src/arch/x86_64/CodeGen.zig
+++ b/src/arch/x86_64/CodeGen.zig
@@ -4618,10 +4618,12 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
} else null;
for (inputs) |input| {
- const constraint = std.mem.sliceTo(std.mem.sliceAsBytes(self.air.extra[extra_i..]), 0);
+ const input_bytes = std.mem.sliceAsBytes(self.air.extra[extra_i..]);
+ const constraint = std.mem.sliceTo(input_bytes, 0);
+ const input_name = std.mem.sliceTo(input_bytes[constraint.len + 1 ..], 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 += constraint.len / 4 + 1;
+ extra_i += (constraint.len + input_name.len + 1) / 4 + 1;
if (constraint.len < 3 or constraint[0] != '{' or constraint[constraint.len - 1] != '}') {
return self.fail("unrecognized asm input constraint: '{s}'", .{constraint});
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig
index af68255fe8..1391d8fe66 100644
--- a/src/codegen/llvm.zig
+++ b/src/codegen/llvm.zig
@@ -4545,11 +4545,14 @@ pub const FuncGen = struct {
total_i += 1;
}
+ const input_start_extra_i = extra_i;
for (inputs) |input| {
- const constraint = std.mem.sliceTo(std.mem.sliceAsBytes(self.air.extra[extra_i..]), 0);
+ const input_bytes = std.mem.sliceAsBytes(self.air.extra[extra_i..]);
+ const constraint = std.mem.sliceTo(input_bytes, 0);
+ const input_name = std.mem.sliceTo(input_bytes[constraint.len + 1 ..], 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 += constraint.len / 4 + 1;
+ extra_i += (constraint.len + input_name.len + 1) / 4 + 1;
const arg_llvm_value = try self.resolveInst(input);
@@ -4591,11 +4594,12 @@ pub const FuncGen = struct {
var rendered_template = std.ArrayList(u8).init(self.gpa);
defer rendered_template.deinit();
- const State = enum { start, percent };
+ const State = enum { start, percent, input };
var state: State = .start;
- for (asm_source) |byte| {
+ var name_start: usize = undefined;
+ for (asm_source) |byte, i| {
switch (state) {
.start => switch (byte) {
'%' => state = .percent,
@@ -4606,12 +4610,39 @@ pub const FuncGen = struct {
try rendered_template.append('%');
state = .start;
},
+ '[' => {
+ try rendered_template.append('$');
+ name_start = i + 1;
+ state = .input;
+ },
else => {
try rendered_template.append('%');
try rendered_template.append(byte);
state = .start;
},
},
+ .input => switch (byte) {
+ ']' => {
+ const name = asm_source[name_start..i];
+ state = .start;
+
+ extra_i = input_start_extra_i;
+ for (inputs) |_, input_i| {
+ const input_bytes = std.mem.sliceAsBytes(self.air.extra[extra_i..]);
+ const constraint = std.mem.sliceTo(input_bytes, 0);
+ const input_name = std.mem.sliceTo(input_bytes[constraint.len + 1 ..], 0);
+ extra_i += (constraint.len + input_name.len + 1) / 4 + 1;
+
+ if (std.mem.eql(u8, name, input_name)) {
+ try rendered_template.writer().print("{d}", .{input_i});
+ break;
+ }
+ } else {
+ return self.todo("TODO validate asm in Sema", .{});
+ }
+ },
+ else => {},
+ },
}
}