aboutsummaryrefslogtreecommitdiff
path: root/src/Sema.zig
diff options
context:
space:
mode:
authorVeikka Tuominen <git@vexu.eu>2022-06-07 19:13:50 +0300
committerVeikka Tuominen <git@vexu.eu>2022-06-07 21:27:06 +0300
commitfbd7e4506f46b73e351e1f3eb5e7cfc16ebbfc1f (patch)
tree574527e8cba0bc39eb18b722ef6a4221528215c8 /src/Sema.zig
parente4c0b848a46347fccced787488605ac66e83c38a (diff)
downloadzig-fbd7e4506f46b73e351e1f3eb5e7cfc16ebbfc1f.tar.gz
zig-fbd7e4506f46b73e351e1f3eb5e7cfc16ebbfc1f.zip
stage2: implement asm with multiple outputs
Diffstat (limited to 'src/Sema.zig')
-rw-r--r--src/Sema.zig54
1 files changed, 24 insertions, 30 deletions
diff --git a/src/Sema.zig b/src/Sema.zig
index 550190654b..5159d6f5d3 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -11334,43 +11334,40 @@ fn zirAsm(
try sema.requireRuntimeBlock(block, src);
}
- if (outputs_len > 1) {
- return sema.fail(block, src, "TODO implement Sema for asm with more than 1 output", .{});
- }
-
var extra_i = extra.end;
var output_type_bits = extra.data.output_type_bits;
var needed_capacity: usize = @typeInfo(Air.Asm).Struct.fields.len + outputs_len + inputs_len;
- const Output = struct {
- constraint: []const u8,
- name: []const u8,
- ty: Type,
- };
- const output: ?Output = if (outputs_len == 0) null else blk: {
+ const ConstraintName = struct { c: []const u8, n: []const u8 };
+ const out_args = try sema.arena.alloc(Air.Inst.Ref, outputs_len);
+ const outputs = try sema.arena.alloc(ConstraintName, outputs_len);
+ var expr_ty = Air.Inst.Ref.void_type;
+
+ for (out_args) |*arg, out_i| {
const output = sema.code.extraData(Zir.Inst.Asm.Output, extra_i);
extra_i = output.end;
const is_type = @truncate(u1, output_type_bits) != 0;
output_type_bits >>= 1;
- if (!is_type) {
- return sema.fail(block, src, "TODO implement Sema for asm with non `->` output", .{});
+ if (is_type) {
+ // Indicate the output is the asm instruction return value.
+ arg.* = .none;
+ const out_ty = try sema.resolveType(block, ret_ty_src, output.data.operand);
+ expr_ty = try sema.addType(out_ty);
+ } else {
+ arg.* = try sema.resolveInst(output.data.operand);
}
const constraint = sema.code.nullTerminatedString(output.data.constraint);
const name = sema.code.nullTerminatedString(output.data.name);
needed_capacity += (constraint.len + name.len + (2 + 3)) / 4;
- break :blk Output{
- .constraint = constraint,
- .name = name,
- .ty = try sema.resolveType(block, ret_ty_src, output.data.operand),
- };
- };
+ outputs[out_i] = .{ .c = constraint, .n = name };
+ }
const args = try sema.arena.alloc(Air.Inst.Ref, inputs_len);
- const inputs = try sema.arena.alloc(struct { c: []const u8, n: []const u8 }, inputs_len);
+ const inputs = try sema.arena.alloc(ConstraintName, inputs_len);
for (args) |*arg, arg_i| {
const input = sema.code.extraData(Zir.Inst.Asm.Input, extra_i);
@@ -11405,7 +11402,7 @@ fn zirAsm(
const asm_air = try block.addInst(.{
.tag = .assembly,
.data = .{ .ty_pl = .{
- .ty = if (output) |o| try sema.addType(o.ty) else Air.Inst.Ref.void_type,
+ .ty = expr_ty,
.payload = sema.addExtraAssumeCapacity(Air.Asm{
.source_len = @intCast(u32, asm_source.len),
.outputs_len = outputs_len,
@@ -11414,18 +11411,15 @@ fn zirAsm(
}),
} },
});
- if (output != null) {
- // Indicate the output is the asm instruction return value.
- sema.air_extra.appendAssumeCapacity(@enumToInt(Air.Inst.Ref.none));
- }
+ sema.appendRefsAssumeCapacity(out_args);
sema.appendRefsAssumeCapacity(args);
- if (output) |o| {
+ for (outputs) |o| {
const buffer = mem.sliceAsBytes(sema.air_extra.unusedCapacitySlice());
- mem.copy(u8, buffer, o.constraint);
- buffer[o.constraint.len] = 0;
- mem.copy(u8, buffer[o.constraint.len + 1 ..], o.name);
- buffer[o.constraint.len + 1 + o.name.len] = 0;
- sema.air_extra.items.len += (o.constraint.len + o.name.len + (2 + 3)) / 4;
+ mem.copy(u8, buffer, o.c);
+ buffer[o.c.len] = 0;
+ mem.copy(u8, buffer[o.c.len + 1 ..], o.n);
+ buffer[o.c.len + 1 + o.n.len] = 0;
+ sema.air_extra.items.len += (o.c.len + o.n.len + (2 + 3)) / 4;
}
for (inputs) |input| {
const buffer = mem.sliceAsBytes(sema.air_extra.unusedCapacitySlice());