| 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,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 | pub fn genErrDecls(o: *Object) !void { | 1855 | pub fn genErrDecls(o: *Object) !void { |
| 1849 | if (o.dg.module.global_error_set.size == 0) return; | 1856 | if (o.dg.module.global_error_set.size == 0) return; |
| 1850 | const writer = o.writer(); | 1857 | const writer = o.writer(); |
| ... | @@ -3450,8 +3457,10 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3450,8 +3457,10 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3450 | try writer.writeAll("{\n"); | 3457 | try writer.writeAll("{\n"); |
| 3451 | f.object.indent_writer.pushIndent(); | 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 | const constraints_extra_begin = extra_i; | 3462 | const constraints_extra_begin = extra_i; |
| 3454 | for (outputs) |output| { | 3463 | for (outputs) |output, index| { |
| 3455 | const extra_bytes = std.mem.sliceAsBytes(f.air.extra[extra_i..]); | 3464 | const extra_bytes = std.mem.sliceAsBytes(f.air.extra[extra_i..]); |
| 3456 | const constraint = std.mem.sliceTo(extra_bytes, 0); | 3465 | const constraint = std.mem.sliceTo(extra_bytes, 0); |
| 3457 | const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0); | 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,7 +3470,9 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3461 | 3470 | ||
| 3462 | const output_ty = if (output == .none) inst_ty else f.air.typeOf(output).childType(); | 3471 | const output_ty = if (output == .none) inst_ty else f.air.typeOf(output).childType(); |
| 3463 | try writer.writeAll("register "); | 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 | if (std.mem.startsWith(u8, constraint, "={") and std.mem.endsWith(u8, constraint, "}")) { | 3476 | if (std.mem.startsWith(u8, constraint, "={") and std.mem.endsWith(u8, constraint, "}")) { |
| 3466 | try writer.writeAll(" __asm(\""); | 3477 | try writer.writeAll(" __asm(\""); |
| 3467 | try writer.writeAll(constraint["={".len .. constraint.len - "}".len]); | 3478 | try writer.writeAll(constraint["={".len .. constraint.len - "}".len]); |
| ... | @@ -3475,7 +3486,9 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3475,7 +3486,9 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3475 | } | 3486 | } |
| 3476 | try writer.writeAll(";\n"); | 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 | const extra_bytes = std.mem.sliceAsBytes(f.air.extra[extra_i..]); | 3492 | const extra_bytes = std.mem.sliceAsBytes(f.air.extra[extra_i..]); |
| 3480 | const constraint = std.mem.sliceTo(extra_bytes, 0); | 3493 | const constraint = std.mem.sliceTo(extra_bytes, 0); |
| 3481 | const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0); | 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,7 +3498,9 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3485 | 3498 | ||
| 3486 | const input_ty = f.air.typeOf(input); | 3499 | const input_ty = f.air.typeOf(input); |
| 3487 | try writer.writeAll("register "); | 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 | if (std.mem.startsWith(u8, constraint, "{") and std.mem.endsWith(u8, constraint, "}")) { | 3504 | if (std.mem.startsWith(u8, constraint, "{") and std.mem.endsWith(u8, constraint, "}")) { |
| 3490 | try writer.writeAll(" __asm(\""); | 3505 | try writer.writeAll(" __asm(\""); |
| 3491 | try writer.writeAll(constraint["{".len .. constraint.len - "}".len]); | 3506 | try writer.writeAll(constraint["{".len .. constraint.len - "}".len]); |
| ... | @@ -3524,7 +3539,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3524,7 +3539,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3524 | 3539 | ||
| 3525 | if (index > 0) try writer.writeByte(','); | 3540 | if (index > 0) try writer.writeByte(','); |
| 3526 | try writer.print(" {s}(", .{fmtStringLiteral(if (constraint[1] == '{') "=r" else constraint)}); | 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 | try writer.writeByte(')'); | 3543 | try writer.writeByte(')'); |
| 3529 | } | 3544 | } |
| 3530 | try writer.writeByte(':'); | 3545 | try writer.writeByte(':'); |
| ... | @@ -3538,7 +3553,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3538,7 +3553,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3538 | 3553 | ||
| 3539 | if (index > 0) try writer.writeByte(','); | 3554 | if (index > 0) try writer.writeByte(','); |
| 3540 | try writer.print(" {s}(", .{fmtStringLiteral(if (constraint[0] == '{') "r" else constraint)}); | 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 | try writer.writeByte(')'); | 3557 | try writer.writeByte(')'); |
| 3543 | } | 3558 | } |
| 3544 | try writer.writeByte(':'); | 3559 | try writer.writeByte(':'); |
| ... | @@ -3559,7 +3574,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -3559,7 +3574,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3559 | try writer.writeAll(");\n"); | 3574 | try writer.writeAll(");\n"); |
| 3560 | 3575 | ||
| 3561 | extra_i = constraints_extra_begin; | 3576 | extra_i = constraints_extra_begin; |
| 3562 | for (outputs) |output| { | 3577 | for (outputs) |output, index| { |
| 3563 | const extra_bytes = std.mem.sliceAsBytes(f.air.extra[extra_i..]); | 3578 | const extra_bytes = std.mem.sliceAsBytes(f.air.extra[extra_i..]); |
| 3564 | const constraint = std.mem.sliceTo(extra_bytes, 0); | 3579 | const constraint = std.mem.sliceTo(extra_bytes, 0); |
| 3565 | const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0); | 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,7 +3586,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3571 | .local_ref = local.local, | 3586 | .local_ref = local.local, |
| 3572 | } else try f.resolveInst(output)); | 3587 | } else try f.resolveInst(output)); |
| 3573 | try writer.writeAll(" = "); | 3588 | try writer.writeAll(" = "); |
| 3574 | try f.writeCValue(writer, .{ .identifier = name }); | 3589 | try f.writeCValue(writer, .{ .local = output_locals_begin + index }); |
| 3575 | try writer.writeAll(";\n"); | 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,7 +256,7 @@ pub fn flushModule(self: *C, comp: *Compilation, prog_node: *std.Progress.Node) |
| 256 | var f: Flush = .{}; | 256 | var f: Flush = .{}; |
| 257 | defer f.deinit(gpa); | 257 | defer f.deinit(gpa); |
| 258 | 258 | ||
| 259 | // Covers zig.h and typedef. | 259 | // Covers zig.h, typedef, and asm. |
| 260 | try f.all_buffers.ensureUnusedCapacity(gpa, 2); | 260 | try f.all_buffers.ensureUnusedCapacity(gpa, 2); |
| 261 | 261 | ||
| 262 | f.appendBufAssumeCapacity(zig_h); | 262 | f.appendBufAssumeCapacity(zig_h); |
| ... | @@ -264,6 +264,16 @@ pub fn flushModule(self: *C, comp: *Compilation, prog_node: *std.Progress.Node) | ... | @@ -264,6 +264,16 @@ pub fn flushModule(self: *C, comp: *Compilation, prog_node: *std.Progress.Node) |
| 264 | const typedef_index = f.all_buffers.items.len; | 264 | const typedef_index = f.all_buffers.items.len; |
| 265 | f.all_buffers.items.len += 1; | 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 | try self.flushErrDecls(&f); | 277 | try self.flushErrDecls(&f); |
| 268 | 278 | ||
| 269 | // Typedefs, forward decls, and non-functions first. | 279 | // Typedefs, forward decls, and non-functions first. |
| ... | @@ -307,6 +317,7 @@ const Flush = struct { | ... | @@ -307,6 +317,7 @@ const Flush = struct { |
| 307 | remaining_decls: std.AutoArrayHashMapUnmanaged(Module.Decl.Index, void) = .{}, | 317 | remaining_decls: std.AutoArrayHashMapUnmanaged(Module.Decl.Index, void) = .{}, |
| 308 | typedefs: Typedefs = .{}, | 318 | typedefs: Typedefs = .{}, |
| 309 | typedef_buf: std.ArrayListUnmanaged(u8) = .{}, | 319 | typedef_buf: std.ArrayListUnmanaged(u8) = .{}, |
| 320 | asm_buf: std.ArrayListUnmanaged(u8) = .{}, | ||
| 310 | /// We collect a list of buffers to write, and write them all at once with pwritev 😎 | 321 | /// We collect a list of buffers to write, and write them all at once with pwritev 😎 |
| 311 | all_buffers: std.ArrayListUnmanaged(std.os.iovec_const) = .{}, | 322 | all_buffers: std.ArrayListUnmanaged(std.os.iovec_const) = .{}, |
| 312 | /// Keeps track of the total bytes of `all_buffers`. | 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,7 +527,6 @@ test "type coercion of anon struct literal to array" { |
| 527 | } | 527 | } |
| 528 | 528 | ||
| 529 | test "type coercion of pointer to anon struct literal to pointer to array" { | 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 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 530 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 532 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 531 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 533 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 532 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
test/behavior/asm.zig-2| ... | @@ -18,7 +18,6 @@ comptime { | ... | @@ -18,7 +18,6 @@ comptime { |
| 18 | } | 18 | } |
| 19 | 19 | ||
| 20 | test "module level assembly" { | 20 | test "module level assembly" { |
| 21 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | ||
| 22 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | 21 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 23 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 22 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 24 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 23 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| ... | @@ -50,7 +49,6 @@ test "output constraint modifiers" { | ... | @@ -50,7 +49,6 @@ test "output constraint modifiers" { |
| 50 | } | 49 | } |
| 51 | 50 | ||
| 52 | test "alternative constraints" { | 51 | test "alternative constraints" { |
| 53 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | ||
| 54 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | 52 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 55 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 53 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 56 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 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,7 +746,6 @@ fn scalar(x: u32) u32 { |
| 746 | 746 | ||
| 747 | test "array concatenation peer resolves element types - value" { | 747 | test "array concatenation peer resolves element types - value" { |
| 748 | if (builtin.zig_backend == .stage1) return error.SkipZigTest; | 748 | if (builtin.zig_backend == .stage1) return error.SkipZigTest; |
| 749 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | ||
| 750 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 749 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 751 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 750 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 752 | 751 | ||
| ... | @@ -781,7 +780,6 @@ test "array concatenation sets the sentinel - value" { | ... | @@ -781,7 +780,6 @@ test "array concatenation sets the sentinel - value" { |
| 781 | if (builtin.zig_backend == .stage1) return error.SkipZigTest; | 780 | if (builtin.zig_backend == .stage1) return error.SkipZigTest; |
| 782 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; | 781 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; |
| 783 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | 782 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; |
| 784 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | ||
| 785 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 783 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 786 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 784 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 787 | 785 | ||
| ... | @@ -819,7 +817,6 @@ test "array multiplication sets the sentinel - value" { | ... | @@ -819,7 +817,6 @@ test "array multiplication sets the sentinel - value" { |
| 819 | if (builtin.zig_backend == .stage1) return error.SkipZigTest; | 817 | if (builtin.zig_backend == .stage1) return error.SkipZigTest; |
| 820 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; | 818 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; |
| 821 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | 819 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; |
| 822 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | ||
| 823 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 820 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 824 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 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,7 +533,6 @@ test "slice pointer-to-array zero length" { |
| 533 | } | 533 | } |
| 534 | 534 | ||
| 535 | test "type coercion of pointer to anon struct literal to pointer to slice" { | 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 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 536 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 538 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 537 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 539 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 538 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |