authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2022-10-11 04:51:52-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2022-10-25 05:11:29-04:00
log1dd4a6102ff983c828cdaa3dbadef37272ffce7c
tree4b6ab99bf066ca96f72b7b6fc62f9952db6518b2
parente8bda9eb3ae9634a7b434e59df883ada3fdf8d9d

cbe: implement global assembly


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};
18471847
1848pub 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
1848pub fn genErrDecls(o: *Object) !void {1855pub 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();
34523459
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 {
34613470
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 {
34853498
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 {
35243539
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 {
35383553
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");
35603575
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 }
35773592
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);
258258
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);
261261
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;
266266
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);
268278
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}
528528
529test "type coercion of pointer to anon struct literal to pointer to array" {529test "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; // TODO530 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
532 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO531 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
533 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO532 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}
1919
20test "module level assembly" {20test "module level assembly" {
21 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
22 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO21 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
23 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO22 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
24 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO23 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}
5150
52test "alternative constraints" {51test "alternative constraints" {
53 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
54 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO52 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
55 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO53 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
56 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO54 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 {
746746
747test "array concatenation peer resolves element types - value" {747test "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;
752751
...@@ -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;
787785
...@@ -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;
825822
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}
534534
535test "type coercion of pointer to anon struct literal to pointer to slice" {535test "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; // TODO536 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
538 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO537 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
539 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO538 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO