diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2021-10-20 14:50:07 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2021-10-20 15:34:10 -0700 |
| commit | 361217bda2b4ce397a2b49ab7613162d1abcab67 (patch) | |
| tree | bcaaada7ab445f6eaa7724557adb6f3b365a72c4 | |
| parent | d949180ab04f550d672e20a8f9bdd6619cc3c05c (diff) | |
| download | zig-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.zig | 4 | ||||
| -rw-r--r-- | src/codegen/llvm.zig | 25 | ||||
| -rw-r--r-- | src/print_air.zig | 49 |
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 { |
