diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/codegen/c.zig | 31 | ||||
| -rw-r--r-- | src/link/C.zig | 13 |
2 files changed, 35 insertions, 9 deletions
diff --git a/src/codegen/c.zig b/src/codegen/c.zig index 37baad3e95..1e3669849b 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -1845,6 +1845,13 @@ pub const DeclGen = struct { } }; +pub fn genGlobalAsm(mod: *Module, code: *std.ArrayList(u8)) !void { + var it = mod.global_assembly.valueIterator(); + while (it.next()) |asm_source| { + try code.writer().print("__asm({s});\n", .{fmtStringLiteral(asm_source.*)}); + } +} + pub fn genErrDecls(o: *Object) !void { if (o.dg.module.global_error_set.size == 0) return; const writer = o.writer(); @@ -3450,8 +3457,10 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { try writer.writeAll("{\n"); f.object.indent_writer.pushIndent(); + const output_locals_begin = f.next_local_index; + f.next_local_index += outputs.len; const constraints_extra_begin = extra_i; - for (outputs) |output| { + for (outputs) |output, index| { const extra_bytes = std.mem.sliceAsBytes(f.air.extra[extra_i..]); const constraint = std.mem.sliceTo(extra_bytes, 0); const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0); @@ -3461,7 +3470,9 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { const output_ty = if (output == .none) inst_ty else f.air.typeOf(output).childType(); try writer.writeAll("register "); - try f.object.dg.renderTypeAndName(writer, output_ty, .{ .identifier = name }, .Mut, 0); + try f.object.dg.renderTypeAndName(writer, output_ty, .{ + .local = output_locals_begin + index, + }, .Mut, 0); if (std.mem.startsWith(u8, constraint, "={") and std.mem.endsWith(u8, constraint, "}")) { try writer.writeAll(" __asm(\""); try writer.writeAll(constraint["={".len .. constraint.len - "}".len]); @@ -3475,7 +3486,9 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { } try writer.writeAll(";\n"); } - for (inputs) |input| { + const input_locals_begin = f.next_local_index; + f.next_local_index += inputs.len; + for (inputs) |input, index| { const extra_bytes = std.mem.sliceAsBytes(f.air.extra[extra_i..]); const constraint = std.mem.sliceTo(extra_bytes, 0); const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0); @@ -3485,7 +3498,9 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { const input_ty = f.air.typeOf(input); try writer.writeAll("register "); - try f.object.dg.renderTypeAndName(writer, input_ty, .{ .identifier = name }, .Const, 0); + try f.object.dg.renderTypeAndName(writer, input_ty, .{ + .local = input_locals_begin + index, + }, .Const, 0); if (std.mem.startsWith(u8, constraint, "{") and std.mem.endsWith(u8, constraint, "}")) { try writer.writeAll(" __asm(\""); try writer.writeAll(constraint["{".len .. constraint.len - "}".len]); @@ -3524,7 +3539,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { if (index > 0) try writer.writeByte(','); try writer.print(" {s}(", .{fmtStringLiteral(if (constraint[1] == '{') "=r" else constraint)}); - try f.writeCValue(writer, .{ .identifier = name }); + try f.writeCValue(writer, .{ .local = output_locals_begin + index }); try writer.writeByte(')'); } try writer.writeByte(':'); @@ -3538,7 +3553,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { if (index > 0) try writer.writeByte(','); try writer.print(" {s}(", .{fmtStringLiteral(if (constraint[0] == '{') "r" else constraint)}); - try f.writeCValue(writer, .{ .identifier = name }); + try f.writeCValue(writer, .{ .local = input_locals_begin + index }); try writer.writeByte(')'); } try writer.writeByte(':'); @@ -3559,7 +3574,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { try writer.writeAll(");\n"); extra_i = constraints_extra_begin; - for (outputs) |output| { + for (outputs) |output, index| { const extra_bytes = std.mem.sliceAsBytes(f.air.extra[extra_i..]); const constraint = std.mem.sliceTo(extra_bytes, 0); const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0); @@ -3571,7 +3586,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { .local_ref = local.local, } else try f.resolveInst(output)); try writer.writeAll(" = "); - try f.writeCValue(writer, .{ .identifier = name }); + try f.writeCValue(writer, .{ .local = output_locals_begin + index }); try writer.writeAll(";\n"); } diff --git a/src/link/C.zig b/src/link/C.zig index d7432eb015..8509e4ae8a 100644 --- a/src/link/C.zig +++ b/src/link/C.zig @@ -256,7 +256,7 @@ pub fn flushModule(self: *C, comp: *Compilation, prog_node: *std.Progress.Node) var f: Flush = .{}; defer f.deinit(gpa); - // Covers zig.h and typedef. + // Covers zig.h, typedef, and asm. try f.all_buffers.ensureUnusedCapacity(gpa, 2); f.appendBufAssumeCapacity(zig_h); @@ -264,6 +264,16 @@ pub fn flushModule(self: *C, comp: *Compilation, prog_node: *std.Progress.Node) const typedef_index = f.all_buffers.items.len; f.all_buffers.items.len += 1; + { + var asm_buf = f.asm_buf.toManaged(module.gpa); + defer asm_buf.deinit(); + + try codegen.genGlobalAsm(module, &asm_buf); + + f.asm_buf = asm_buf.moveToUnmanaged(); + f.appendBufAssumeCapacity(f.asm_buf.items); + } + try self.flushErrDecls(&f); // Typedefs, forward decls, and non-functions first. @@ -307,6 +317,7 @@ const Flush = struct { remaining_decls: std.AutoArrayHashMapUnmanaged(Module.Decl.Index, void) = .{}, typedefs: Typedefs = .{}, typedef_buf: std.ArrayListUnmanaged(u8) = .{}, + asm_buf: std.ArrayListUnmanaged(u8) = .{}, /// We collect a list of buffers to write, and write them all at once with pwritev 😎 all_buffers: std.ArrayListUnmanaged(std.os.iovec_const) = .{}, /// Keeps track of the total bytes of `all_buffers`. |
