authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-10-20 14:50:07-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-10-20 15:34:10-07:00
log361217bda2b4ce397a2b49ab7613162d1abcab67
treebcaaada7ab445f6eaa7724557adb6f3b365a72c4
parentd949180ab04f550d672e20a8f9bdd6619cc3c05c

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.

3 files changed, 60 insertions(+), 18 deletions(-)

lib/std/heap.zig+2-2
...@@ -295,7 +295,7 @@ const PageAllocator = struct {...@@ -295,7 +295,7 @@ const PageAllocator = struct {
295 }295 }
296 }296 }
297297
298 const max_drop_len = alignment - std.math.min(alignment, mem.page_size);298 const max_drop_len = alignment - @minimum(alignment, mem.page_size);
299 const alloc_len = if (max_drop_len <= aligned_len - n)299 const alloc_len = if (max_drop_len <= aligned_len - n)
300 aligned_len300 aligned_len
301 else301 else
...@@ -529,7 +529,7 @@ const WasmPageAllocator = struct {...@@ -529,7 +529,7 @@ const WasmPageAllocator = struct {
529529
530 fn freePages(start: usize, end: usize) void {530 fn freePages(start: usize, end: usize) void {
531 if (start < extendedOffset()) {531 if (start < extendedOffset()) {
532 conventional.recycle(start, std.math.min(extendedOffset(), end) - start);532 conventional.recycle(start, @minimum(extendedOffset(), end) - start);
533 }533 }
534 if (end > extendedOffset()) {534 if (end > extendedOffset()) {
535 var new_end = end;535 var new_end = end;
src/codegen/llvm.zig+12-13
...@@ -2331,17 +2331,19 @@ pub const FuncGen = struct {...@@ -2331,17 +2331,19 @@ pub const FuncGen = struct {
2331 const air_asm = self.air.extraData(Air.Asm, ty_pl.payload);2331 const air_asm = self.air.extraData(Air.Asm, ty_pl.payload);
2332 const zir = self.dg.decl.getFileScope().zir;2332 const zir = self.dg.decl.getFileScope().zir;
2333 const extended = zir.instructions.items(.data)[air_asm.data.zir_index].extended;2333 const extended = zir.instructions.items(.data)[air_asm.data.zir_index].extended;
2334 const zir_extra = zir.extraData(Zir.Inst.Asm, extended.operand);
2335 const asm_source = zir.nullTerminatedString(zir_extra.data.asm_source);
2336 const outputs_len = @truncate(u5, extended.small);
2337 const args_len = @truncate(u5, extended.small >> 5);
2338 const clobbers_len = @truncate(u5, extended.small >> 10);
2339 const is_volatile = @truncate(u1, extended.small >> 15) != 0;2334 const is_volatile = @truncate(u1, extended.small >> 15) != 0;
2340 const outputs = @bitCast([]const Air.Inst.Ref, self.air.extra[air_asm.end..][0..outputs_len]);2335 if (!is_volatile and self.liveness.isUnused(inst)) {
2341 const args = @bitCast([]const Air.Inst.Ref, self.air.extra[air_asm.end + outputs.len ..][0..args_len]);2336 return null;
2337 }
2338 const outputs_len = @truncate(u5, extended.small);
2342 if (outputs_len > 1) {2339 if (outputs_len > 1) {
2343 return self.todo("implement llvm codegen for asm with more than 1 output", .{});2340 return self.todo("implement llvm codegen for asm with more than 1 output", .{});
2344 }2341 }
2342 const args_len = @truncate(u5, extended.small >> 5);
2343 const clobbers_len = @truncate(u5, extended.small >> 10);
2344 const zir_extra = zir.extraData(Zir.Inst.Asm, extended.operand);
2345 const asm_source = zir.nullTerminatedString(zir_extra.data.asm_source);
2346 const args = @bitCast([]const Air.Inst.Ref, self.air.extra[air_asm.end..][0..args_len]);
23452347
2346 var extra_i: usize = zir_extra.end;2348 var extra_i: usize = zir_extra.end;
2347 const output_constraint: ?[]const u8 = out: {2349 const output_constraint: ?[]const u8 = out: {
...@@ -2354,10 +2356,6 @@ pub const FuncGen = struct {...@@ -2354,10 +2356,6 @@ pub const FuncGen = struct {
2354 break :out null;2356 break :out null;
2355 };2357 };
23562358
2357 if (!is_volatile and self.liveness.isUnused(inst)) {
2358 return null;
2359 }
2360
2361 var llvm_constraints: std.ArrayListUnmanaged(u8) = .{};2359 var llvm_constraints: std.ArrayListUnmanaged(u8) = .{};
2362 defer llvm_constraints.deinit(self.gpa);2360 defer llvm_constraints.deinit(self.gpa);
23632361
...@@ -2365,7 +2363,7 @@ pub const FuncGen = struct {...@@ -2365,7 +2363,7 @@ pub const FuncGen = struct {
2365 defer arena_allocator.deinit();2363 defer arena_allocator.deinit();
2366 const arena = &arena_allocator.allocator;2364 const arena = &arena_allocator.allocator;
23672365
2368 const llvm_params_len = args.len + @boolToInt(output_constraint != null);2366 const llvm_params_len = args.len;
2369 const llvm_param_types = try arena.alloc(*const llvm.Type, llvm_params_len);2367 const llvm_param_types = try arena.alloc(*const llvm.Type, llvm_params_len);
2370 const llvm_param_values = try arena.alloc(*const llvm.Value, llvm_params_len);2368 const llvm_param_values = try arena.alloc(*const llvm.Value, llvm_params_len);
23712369
...@@ -2377,7 +2375,8 @@ pub const FuncGen = struct {...@@ -2377,7 +2375,8 @@ pub const FuncGen = struct {
2377 if (total_i != 0) {2375 if (total_i != 0) {
2378 llvm_constraints.appendAssumeCapacity(',');2376 llvm_constraints.appendAssumeCapacity(',');
2379 }2377 }
2380 llvm_constraints.appendSliceAssumeCapacity(constraint);2378 llvm_constraints.appendAssumeCapacity('=');
2379 llvm_constraints.appendSliceAssumeCapacity(constraint[1..]);
23812380
2382 total_i += 1;2381 total_i += 1;
2383 }2382 }
src/print_air.zig+46-3
...@@ -370,9 +370,52 @@ const Writer = struct {...@@ -370,9 +370,52 @@ const Writer = struct {
370 }370 }
371371
372 fn writeAssembly(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {372 fn writeAssembly(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
373 _ = w;373 const ty_pl = w.air.instructions.items(.data)[inst].ty_pl;
374 _ = inst;374 const air_asm = w.air.extraData(Air.Asm, ty_pl.payload);
375 try s.writeAll("TODO");375 const zir = w.zir;
376 const extended = zir.instructions.items(.data)[air_asm.data.zir_index].extended;
377 const zir_extra = zir.extraData(Zir.Inst.Asm, extended.operand);
378 const asm_source = zir.nullTerminatedString(zir_extra.data.asm_source);
379 const outputs_len = @truncate(u5, extended.small);
380 const args_len = @truncate(u5, extended.small >> 5);
381 const clobbers_len = @truncate(u5, extended.small >> 10);
382 const args = @bitCast([]const Air.Inst.Ref, w.air.extra[air_asm.end..][0..args_len]);
383
384 var extra_i: usize = zir_extra.end;
385 const output_constraint: ?[]const u8 = out: {
386 var i: usize = 0;
387 while (i < outputs_len) : (i += 1) {
388 const output = zir.extraData(Zir.Inst.Asm.Output, extra_i);
389 extra_i = output.end;
390 break :out zir.nullTerminatedString(output.data.constraint);
391 }
392 break :out null;
393 };
394
395 try s.print("\"{s}\"", .{asm_source});
396
397 if (output_constraint) |constraint| {
398 const ret_ty = w.air.typeOfIndex(inst);
399 try s.print(", {s} -> {}", .{ constraint, ret_ty });
400 }
401
402 for (args) |arg| {
403 const input = zir.extraData(Zir.Inst.Asm.Input, extra_i);
404 extra_i = input.end;
405 const constraint = zir.nullTerminatedString(input.data.constraint);
406
407 try s.print(", {s} = (", .{constraint});
408 try w.writeOperand(s, inst, 0, arg);
409 try s.writeByte(')');
410 }
411
412 const clobbers = zir.extra[extra_i..][0..clobbers_len];
413 for (clobbers) |clobber_index| {
414 const clobber = zir.nullTerminatedString(clobber_index);
415 try s.writeAll(", ~{");
416 try s.writeAll(clobber);
417 try s.writeAll("}");
418 }
376 }419 }
377420
378 fn writeDbgStmt(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {421 fn writeDbgStmt(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {