| author | |
| committer | |
| log | 1dd4a6102ff983c828cdaa3dbadef37272ffce7c |
| tree | 4b6ab99bf066ca96f72b7b6fc62f9952db6518b2 |
| parent | e8bda9eb3ae9634a7b434e59df883ada3fdf8d9d |
6 files changed, 35 insertions(+), 16 deletions(-)
src/codegen/c.zig+23-8| ... | ... | @@ -1845,6 +1845,13 @@ pub const DeclGen = struct { |
| 1845 | 1845 | } |
| 1846 | 1846 | }; |
| 1847 | 1847 | |
| 1848 | pub fn genGlobalAsm(mod: *Module, code: *std.ArrayList(u8)) !void { | |
| 1849 | var it = mod.global_assembly.valueIterator(); | |
| 1850 | while (it.next()) |asm_source| { | |
| 1851 | try code.writer().print("__asm({s});\n", .{fmtStringLiteral(asm_source.*)}); | |
| 1852 | } | |
| 1853 | } | |
| 1854 | ||
| 1848 | 1855 | pub fn genErrDecls(o: *Object) !void { |
| 1849 | 1856 | if (o.dg.module.global_error_set.size == 0) return; |
| 1850 | 1857 | const writer = o.writer(); |
| ... | ... | @@ -3450,8 +3457,10 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3450 | 3457 | try writer.writeAll("{\n"); |
| 3451 | 3458 | f.object.indent_writer.pushIndent(); |
| 3452 | 3459 | |
| 3460 | const output_locals_begin = f.next_local_index; | |
| 3461 | f.next_local_index += outputs.len; | |
| 3453 | 3462 | const constraints_extra_begin = extra_i; |
| 3454 | for (outputs) |output| { | |
| 3463 | for (outputs) |output, index| { | |
| 3455 | 3464 | const extra_bytes = std.mem.sliceAsBytes(f.air.extra[extra_i..]); |
| 3456 | 3465 | const constraint = std.mem.sliceTo(extra_bytes, 0); |
| 3457 | 3466 | const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0); |
| ... | ... | @@ -3461,7 +3470,9 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3461 | 3470 | |
| 3462 | 3471 | const output_ty = if (output == .none) inst_ty else f.air.typeOf(output).childType(); |
| 3463 | 3472 | try writer.writeAll("register "); |
| 3464 | try f.object.dg.renderTypeAndName(writer, output_ty, .{ .identifier = name }, .Mut, 0); | |
| 3473 | try f.object.dg.renderTypeAndName(writer, output_ty, .{ | |
| 3474 | .local = output_locals_begin + index, | |
| 3475 | }, .Mut, 0); | |
| 3465 | 3476 | if (std.mem.startsWith(u8, constraint, "={") and std.mem.endsWith(u8, constraint, "}")) { |
| 3466 | 3477 | try writer.writeAll(" __asm(\""); |
| 3467 | 3478 | try writer.writeAll(constraint["={".len .. constraint.len - "}".len]); |
| ... | ... | @@ -3475,7 +3486,9 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3475 | 3486 | } |
| 3476 | 3487 | try writer.writeAll(";\n"); |
| 3477 | 3488 | } |
| 3478 | for (inputs) |input| { | |
| 3489 | const input_locals_begin = f.next_local_index; | |
| 3490 | f.next_local_index += inputs.len; | |
| 3491 | for (inputs) |input, index| { | |
| 3479 | 3492 | const extra_bytes = std.mem.sliceAsBytes(f.air.extra[extra_i..]); |
| 3480 | 3493 | const constraint = std.mem.sliceTo(extra_bytes, 0); |
| 3481 | 3494 | const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0); |
| ... | ... | @@ -3485,7 +3498,9 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3485 | 3498 | |
| 3486 | 3499 | const input_ty = f.air.typeOf(input); |
| 3487 | 3500 | try writer.writeAll("register "); |
| 3488 | try f.object.dg.renderTypeAndName(writer, input_ty, .{ .identifier = name }, .Const, 0); | |
| 3501 | try f.object.dg.renderTypeAndName(writer, input_ty, .{ | |
| 3502 | .local = input_locals_begin + index, | |
| 3503 | }, .Const, 0); | |
| 3489 | 3504 | if (std.mem.startsWith(u8, constraint, "{") and std.mem.endsWith(u8, constraint, "}")) { |
| 3490 | 3505 | try writer.writeAll(" __asm(\""); |
| 3491 | 3506 | try writer.writeAll(constraint["{".len .. constraint.len - "}".len]); |
| ... | ... | @@ -3524,7 +3539,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3524 | 3539 | |
| 3525 | 3540 | if (index > 0) try writer.writeByte(','); |
| 3526 | 3541 | try writer.print(" {s}(", .{fmtStringLiteral(if (constraint[1] == '{') "=r" else constraint)}); |
| 3527 | try f.writeCValue(writer, .{ .identifier = name }); | |
| 3542 | try f.writeCValue(writer, .{ .local = output_locals_begin + index }); | |
| 3528 | 3543 | try writer.writeByte(')'); |
| 3529 | 3544 | } |
| 3530 | 3545 | try writer.writeByte(':'); |
| ... | ... | @@ -3538,7 +3553,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3538 | 3553 | |
| 3539 | 3554 | if (index > 0) try writer.writeByte(','); |
| 3540 | 3555 | try writer.print(" {s}(", .{fmtStringLiteral(if (constraint[0] == '{') "r" else constraint)}); |
| 3541 | try f.writeCValue(writer, .{ .identifier = name }); | |
| 3556 | try f.writeCValue(writer, .{ .local = input_locals_begin + index }); | |
| 3542 | 3557 | try writer.writeByte(')'); |
| 3543 | 3558 | } |
| 3544 | 3559 | try writer.writeByte(':'); |
| ... | ... | @@ -3559,7 +3574,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3559 | 3574 | try writer.writeAll(");\n"); |
| 3560 | 3575 | |
| 3561 | 3576 | extra_i = constraints_extra_begin; |
| 3562 | for (outputs) |output| { | |
| 3577 | for (outputs) |output, index| { | |
| 3563 | 3578 | const extra_bytes = std.mem.sliceAsBytes(f.air.extra[extra_i..]); |
| 3564 | 3579 | const constraint = std.mem.sliceTo(extra_bytes, 0); |
| 3565 | 3580 | const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0); |
| ... | ... | @@ -3571,7 +3586,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3571 | 3586 | .local_ref = local.local, |
| 3572 | 3587 | } else try f.resolveInst(output)); |
| 3573 | 3588 | try writer.writeAll(" = "); |
| 3574 | try f.writeCValue(writer, .{ .identifier = name }); | |
| 3589 | try f.writeCValue(writer, .{ .local = output_locals_begin + index }); | |
| 3575 | 3590 | try writer.writeAll(";\n"); |
| 3576 | 3591 | } |
| 3577 | 3592 |
src/link/C.zig+12-1| ... | ... | @@ -256,7 +256,7 @@ pub fn flushModule(self: *C, comp: *Compilation, prog_node: *std.Progress.Node) |
| 256 | 256 | var f: Flush = .{}; |
| 257 | 257 | defer f.deinit(gpa); |
| 258 | 258 | |
| 259 | // Covers zig.h and typedef. | |
| 259 | // Covers zig.h, typedef, and asm. | |
| 260 | 260 | try f.all_buffers.ensureUnusedCapacity(gpa, 2); |
| 261 | 261 | |
| 262 | 262 | f.appendBufAssumeCapacity(zig_h); |
| ... | ... | @@ -264,6 +264,16 @@ pub fn flushModule(self: *C, comp: *Compilation, prog_node: *std.Progress.Node) |
| 264 | 264 | const typedef_index = f.all_buffers.items.len; |
| 265 | 265 | f.all_buffers.items.len += 1; |
| 266 | 266 | |
| 267 | { | |
| 268 | var asm_buf = f.asm_buf.toManaged(module.gpa); | |
| 269 | defer asm_buf.deinit(); | |
| 270 | ||
| 271 | try codegen.genGlobalAsm(module, &asm_buf); | |
| 272 | ||
| 273 | f.asm_buf = asm_buf.moveToUnmanaged(); | |
| 274 | f.appendBufAssumeCapacity(f.asm_buf.items); | |
| 275 | } | |
| 276 | ||
| 267 | 277 | try self.flushErrDecls(&f); |
| 268 | 278 | |
| 269 | 279 | // Typedefs, forward decls, and non-functions first. |
| ... | ... | @@ -307,6 +317,7 @@ const Flush = struct { |
| 307 | 317 | remaining_decls: std.AutoArrayHashMapUnmanaged(Module.Decl.Index, void) = .{}, |
| 308 | 318 | typedefs: Typedefs = .{}, |
| 309 | 319 | typedef_buf: std.ArrayListUnmanaged(u8) = .{}, |
| 320 | asm_buf: std.ArrayListUnmanaged(u8) = .{}, | |
| 310 | 321 | /// We collect a list of buffers to write, and write them all at once with pwritev 😎 |
| 311 | 322 | all_buffers: std.ArrayListUnmanaged(std.os.iovec_const) = .{}, |
| 312 | 323 | /// Keeps track of the total bytes of `all_buffers`. |
test/behavior/array.zig-1| ... | ... | @@ -527,7 +527,6 @@ test "type coercion of anon struct literal to array" { |
| 527 | 527 | } |
| 528 | 528 | |
| 529 | 529 | test "type coercion of pointer to anon struct literal to pointer to array" { |
| 530 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | |
| 531 | 530 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 532 | 531 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 533 | 532 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
test/behavior/asm.zig-2| ... | ... | @@ -18,7 +18,6 @@ comptime { |
| 18 | 18 | } |
| 19 | 19 | |
| 20 | 20 | test "module level assembly" { |
| 21 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | |
| 22 | 21 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 23 | 22 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 24 | 23 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| ... | ... | @@ -50,7 +49,6 @@ test "output constraint modifiers" { |
| 50 | 49 | } |
| 51 | 50 | |
| 52 | 51 | test "alternative constraints" { |
| 53 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | |
| 54 | 52 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 55 | 53 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 56 | 54 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
test/behavior/eval.zig-3| ... | ... | @@ -746,7 +746,6 @@ fn scalar(x: u32) u32 { |
| 746 | 746 | |
| 747 | 747 | test "array concatenation peer resolves element types - value" { |
| 748 | 748 | if (builtin.zig_backend == .stage1) return error.SkipZigTest; |
| 749 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 750 | 749 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 751 | 750 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 752 | 751 | |
| ... | ... | @@ -781,7 +780,6 @@ test "array concatenation sets the sentinel - value" { |
| 781 | 780 | if (builtin.zig_backend == .stage1) return error.SkipZigTest; |
| 782 | 781 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; |
| 783 | 782 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; |
| 784 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 785 | 783 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 786 | 784 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 787 | 785 | |
| ... | ... | @@ -819,7 +817,6 @@ test "array multiplication sets the sentinel - value" { |
| 819 | 817 | if (builtin.zig_backend == .stage1) return error.SkipZigTest; |
| 820 | 818 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; |
| 821 | 819 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; |
| 822 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 823 | 820 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 824 | 821 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 825 | 822 |
test/behavior/slice.zig-1| ... | ... | @@ -533,7 +533,6 @@ test "slice pointer-to-array zero length" { |
| 533 | 533 | } |
| 534 | 534 | |
| 535 | 535 | test "type coercion of pointer to anon struct literal to pointer to slice" { |
| 536 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | |
| 537 | 536 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 538 | 537 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 539 | 538 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |