aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-10-20 14:50:07 -0700
committerAndrew Kelley <andrew@ziglang.org>2021-10-20 15:34:10 -0700
commit361217bda2b4ce397a2b49ab7613162d1abcab67 (patch)
treebcaaada7ab445f6eaa7724557adb6f3b365a72c4
parentd949180ab04f550d672e20a8f9bdd6619cc3c05c (diff)
downloadzig-361217bda2b4ce397a2b49ab7613162d1abcab67.tar.gz
zig-361217bda2b4ce397a2b49ab7613162d1abcab67.zip
stage2: fix inline assembly with expression output
Thanks @g-w1 for the print_air.zig implementation for inline assembly. I copied it and slightly modified it from your open pull request.
-rw-r--r--lib/std/heap.zig4
-rw-r--r--src/codegen/llvm.zig25
-rw-r--r--src/print_air.zig49
3 files changed, 60 insertions, 18 deletions
diff --git a/lib/std/heap.zig b/lib/std/heap.zig
index 47d964c239..fcea90d751 100644
--- a/lib/std/heap.zig
+++ b/lib/std/heap.zig
@@ -295,7 +295,7 @@ const PageAllocator = struct {
}
}
- const max_drop_len = alignment - std.math.min(alignment, mem.page_size);
+ const max_drop_len = alignment - @minimum(alignment, mem.page_size);
const alloc_len = if (max_drop_len <= aligned_len - n)
aligned_len
else
@@ -529,7 +529,7 @@ const WasmPageAllocator = struct {
fn freePages(start: usize, end: usize) void {
if (start < extendedOffset()) {
- conventional.recycle(start, std.math.min(extendedOffset(), end) - start);
+ conventional.recycle(start, @minimum(extendedOffset(), end) - start);
}
if (end > extendedOffset()) {
var new_end = end;
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig
index 5dc0a251bd..734a5de78e 100644
--- a/src/codegen/llvm.zig
+++ b/src/codegen/llvm.zig
@@ -2331,17 +2331,19 @@ pub const FuncGen = struct {
const air_asm = self.air.extraData(Air.Asm, ty_pl.payload);
const zir = self.dg.decl.getFileScope().zir;
const extended = zir.instructions.items(.data)[air_asm.data.zir_index].extended;
- const zir_extra = zir.extraData(Zir.Inst.Asm, extended.operand);
- const asm_source = zir.nullTerminatedString(zir_extra.data.asm_source);
- const outputs_len = @truncate(u5, extended.small);
- const args_len = @truncate(u5, extended.small >> 5);
- const clobbers_len = @truncate(u5, extended.small >> 10);
const is_volatile = @truncate(u1, extended.small >> 15) != 0;
- const outputs = @bitCast([]const Air.Inst.Ref, self.air.extra[air_asm.end..][0..outputs_len]);
- const args = @bitCast([]const Air.Inst.Ref, self.air.extra[air_asm.end + outputs.len ..][0..args_len]);
+ if (!is_volatile and self.liveness.isUnused(inst)) {
+ return null;
+ }
+ const outputs_len = @truncate(u5, extended.small);
if (outputs_len > 1) {
return self.todo("implement llvm codegen for asm with more than 1 output", .{});
}
+ const args_len = @truncate(u5, extended.small >> 5);
+ const clobbers_len = @truncate(u5, extended.small >> 10);
+ const zir_extra = zir.extraData(Zir.Inst.Asm, extended.operand);
+ const asm_source = zir.nullTerminatedString(zir_extra.data.asm_source);
+ const args = @bitCast([]const Air.Inst.Ref, self.air.extra[air_asm.end..][0..args_len]);
var extra_i: usize = zir_extra.end;
const output_constraint: ?[]const u8 = out: {
@@ -2354,10 +2356,6 @@ pub const FuncGen = struct {
break :out null;
};
- if (!is_volatile and self.liveness.isUnused(inst)) {
- return null;
- }
-
var llvm_constraints: std.ArrayListUnmanaged(u8) = .{};
defer llvm_constraints.deinit(self.gpa);
@@ -2365,7 +2363,7 @@ pub const FuncGen = struct {
defer arena_allocator.deinit();
const arena = &arena_allocator.allocator;
- const llvm_params_len = args.len + @boolToInt(output_constraint != null);
+ const llvm_params_len = args.len;
const llvm_param_types = try arena.alloc(*const llvm.Type, llvm_params_len);
const llvm_param_values = try arena.alloc(*const llvm.Value, llvm_params_len);
@@ -2377,7 +2375,8 @@ pub const FuncGen = struct {
if (total_i != 0) {
llvm_constraints.appendAssumeCapacity(',');
}
- llvm_constraints.appendSliceAssumeCapacity(constraint);
+ llvm_constraints.appendAssumeCapacity('=');
+ llvm_constraints.appendSliceAssumeCapacity(constraint[1..]);
total_i += 1;
}
diff --git a/src/print_air.zig b/src/print_air.zig
index 48014d02b0..3d1ab225f4 100644
--- a/src/print_air.zig
+++ b/src/print_air.zig
@@ -370,9 +370,52 @@ const Writer = struct {
}
fn writeAssembly(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
- _ = w;
- _ = inst;
- try s.writeAll("TODO");
+ const ty_pl = w.air.instructions.items(.data)[inst].ty_pl;
+ const air_asm = w.air.extraData(Air.Asm, ty_pl.payload);
+ const zir = w.zir;
+ const extended = zir.instructions.items(.data)[air_asm.data.zir_index].extended;
+ const zir_extra = zir.extraData(Zir.Inst.Asm, extended.operand);
+ const asm_source = zir.nullTerminatedString(zir_extra.data.asm_source);
+ const outputs_len = @truncate(u5, extended.small);
+ const args_len = @truncate(u5, extended.small >> 5);
+ const clobbers_len = @truncate(u5, extended.small >> 10);
+ const args = @bitCast([]const Air.Inst.Ref, w.air.extra[air_asm.end..][0..args_len]);
+
+ var extra_i: usize = zir_extra.end;
+ const output_constraint: ?[]const u8 = out: {
+ var i: usize = 0;
+ while (i < outputs_len) : (i += 1) {
+ const output = zir.extraData(Zir.Inst.Asm.Output, extra_i);
+ extra_i = output.end;
+ break :out zir.nullTerminatedString(output.data.constraint);
+ }
+ break :out null;
+ };
+
+ try s.print("\"{s}\"", .{asm_source});
+
+ if (output_constraint) |constraint| {
+ const ret_ty = w.air.typeOfIndex(inst);
+ try s.print(", {s} -> {}", .{ constraint, ret_ty });
+ }
+
+ for (args) |arg| {
+ const input = zir.extraData(Zir.Inst.Asm.Input, extra_i);
+ extra_i = input.end;
+ const constraint = zir.nullTerminatedString(input.data.constraint);
+
+ try s.print(", {s} = (", .{constraint});
+ try w.writeOperand(s, inst, 0, arg);
+ try s.writeByte(')');
+ }
+
+ const clobbers = zir.extra[extra_i..][0..clobbers_len];
+ for (clobbers) |clobber_index| {
+ const clobber = zir.nullTerminatedString(clobber_index);
+ try s.writeAll(", ~{");
+ try s.writeAll(clobber);
+ try s.writeAll("}");
+ }
}
fn writeDbgStmt(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {