diff options
| author | Veikka Tuominen <git@vexu.eu> | 2022-06-07 19:13:50 +0300 |
|---|---|---|
| committer | Veikka Tuominen <git@vexu.eu> | 2022-06-07 21:27:06 +0300 |
| commit | fbd7e4506f46b73e351e1f3eb5e7cfc16ebbfc1f (patch) | |
| tree | 574527e8cba0bc39eb18b722ef6a4221528215c8 /src/Sema.zig | |
| parent | e4c0b848a46347fccced787488605ac66e83c38a (diff) | |
| download | zig-fbd7e4506f46b73e351e1f3eb5e7cfc16ebbfc1f.tar.gz zig-fbd7e4506f46b73e351e1f3eb5e7cfc16ebbfc1f.zip | |
stage2: implement asm with multiple outputs
Diffstat (limited to 'src/Sema.zig')
| -rw-r--r-- | src/Sema.zig | 54 |
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()); |
