| author | |
| committer | |
| log | 75c2cff40ef5c758ec18455324a50378684aff85 |
| tree | dbad1cafdd53fcab11e9be52aa27702b9bbb1345 |
| parent | 6655c6092efbdc8b1aeb89ff9f7a8b05f736916a |
7 files changed, 63 insertions(+), 22 deletions(-)
src/Air.zig+2| ... | @@ -815,6 +815,8 @@ pub const VectorCmp = struct { | ... | @@ -815,6 +815,8 @@ pub const VectorCmp = struct { |
| 815 | /// terminated string. pad to the next u32 after the null byte. | 815 | /// terminated string. pad to the next u32 after the null byte. |
| 816 | /// 3. for every inputs_len | 816 | /// 3. for every inputs_len |
| 817 | /// - constraint: memory at this position is reinterpreted as a null | 817 | /// - constraint: memory at this position is reinterpreted as a null |
| 818 | /// terminated string. | ||
| 819 | /// - name: memory at this position is reinterpreted as a null | ||
| 818 | /// terminated string. pad to the next u32 after the null byte. | 820 | /// terminated string. pad to the next u32 after the null byte. |
| 819 | /// 4. for every clobbers_len | 821 | /// 4. for every clobbers_len |
| 820 | /// - clobber_name: memory at this position is reinterpreted as a null | 822 | /// - clobber_name: memory at this position is reinterpreted as a null |
src/Sema.zig+10-10| ... | @@ -10295,15 +10295,12 @@ fn zirAsm( | ... | @@ -10295,15 +10295,12 @@ fn zirAsm( |
| 10295 | }; | 10295 | }; |
| 10296 | 10296 | ||
| 10297 | const args = try sema.arena.alloc(Air.Inst.Ref, inputs_len); | 10297 | const args = try sema.arena.alloc(Air.Inst.Ref, inputs_len); |
| 10298 | const inputs = try sema.arena.alloc([]const u8, inputs_len); | 10298 | const inputs = try sema.arena.alloc(struct { c: []const u8, n: []const u8 }, inputs_len); |
| 10299 | 10299 | ||
| 10300 | for (args) |*arg, arg_i| { | 10300 | for (args) |*arg, arg_i| { |
| 10301 | const input = sema.code.extraData(Zir.Inst.Asm.Input, extra_i); | 10301 | const input = sema.code.extraData(Zir.Inst.Asm.Input, extra_i); |
| 10302 | extra_i = input.end; | 10302 | extra_i = input.end; |
| 10303 | 10303 | ||
| 10304 | const name = sema.code.nullTerminatedString(input.data.name); | ||
| 10305 | _ = name; // TODO: use the name | ||
| 10306 | |||
| 10307 | const uncasted_arg = sema.resolveInst(input.data.operand); | 10304 | const uncasted_arg = sema.resolveInst(input.data.operand); |
| 10308 | const uncasted_arg_ty = sema.typeOf(uncasted_arg); | 10305 | const uncasted_arg_ty = sema.typeOf(uncasted_arg); |
| 10309 | switch (uncasted_arg_ty.zigTypeTag()) { | 10306 | switch (uncasted_arg_ty.zigTypeTag()) { |
| ... | @@ -10313,8 +10310,9 @@ fn zirAsm( | ... | @@ -10313,8 +10310,9 @@ fn zirAsm( |
| 10313 | } | 10310 | } |
| 10314 | 10311 | ||
| 10315 | const constraint = sema.code.nullTerminatedString(input.data.constraint); | 10312 | const constraint = sema.code.nullTerminatedString(input.data.constraint); |
| 10316 | needed_capacity += constraint.len / 4 + 1; | 10313 | const name = sema.code.nullTerminatedString(input.data.name); |
| 10317 | inputs[arg_i] = constraint; | 10314 | needed_capacity += (constraint.len + name.len + 1) / 4 + 1; |
| 10315 | inputs[arg_i] = .{ .c = constraint, .n = name }; | ||
| 10318 | } | 10316 | } |
| 10319 | 10317 | ||
| 10320 | const clobbers = try sema.arena.alloc([]const u8, clobbers_len); | 10318 | const clobbers = try sema.arena.alloc([]const u8, clobbers_len); |
| ... | @@ -10353,11 +10351,13 @@ fn zirAsm( | ... | @@ -10353,11 +10351,13 @@ fn zirAsm( |
| 10353 | buffer[o.constraint.len] = 0; | 10351 | buffer[o.constraint.len] = 0; |
| 10354 | sema.air_extra.items.len += o.constraint.len / 4 + 1; | 10352 | sema.air_extra.items.len += o.constraint.len / 4 + 1; |
| 10355 | } | 10353 | } |
| 10356 | for (inputs) |constraint| { | 10354 | for (inputs) |input| { |
| 10357 | const buffer = mem.sliceAsBytes(sema.air_extra.unusedCapacitySlice()); | 10355 | const buffer = mem.sliceAsBytes(sema.air_extra.unusedCapacitySlice()); |
| 10358 | mem.copy(u8, buffer, constraint); | 10356 | mem.copy(u8, buffer, input.c); |
| 10359 | buffer[constraint.len] = 0; | 10357 | buffer[input.c.len] = 0; |
| 10360 | sema.air_extra.items.len += constraint.len / 4 + 1; | 10358 | mem.copy(u8, buffer[input.c.len + 1 ..], input.n); |
| 10359 | buffer[input.c.len + 1 + input.n.len] = 0; | ||
| 10360 | sema.air_extra.items.len += (input.c.len + input.n.len + 1) / 4 + 1; | ||
| 10361 | } | 10361 | } |
| 10362 | for (clobbers) |clobber| { | 10362 | for (clobbers) |clobber| { |
| 10363 | const buffer = mem.sliceAsBytes(sema.air_extra.unusedCapacitySlice()); | 10363 | const buffer = mem.sliceAsBytes(sema.air_extra.unusedCapacitySlice()); |
src/arch/aarch64/CodeGen.zig+4-2| ... | @@ -3200,10 +3200,12 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3200,10 +3200,12 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void { |
| 3200 | } else null; | 3200 | } else null; |
| 3201 | 3201 | ||
| 3202 | for (inputs) |input| { | 3202 | for (inputs) |input| { |
| 3203 | const constraint = std.mem.sliceTo(std.mem.sliceAsBytes(self.air.extra[extra_i..]), 0); | 3203 | const input_bytes = std.mem.sliceAsBytes(self.air.extra[extra_i..]); |
| 3204 | const constraint = std.mem.sliceTo(input_bytes, 0); | ||
| 3205 | const input_name = std.mem.sliceTo(input_bytes[constraint.len + 1 ..], 0); | ||
| 3204 | // This equation accounts for the fact that even if we have exactly 4 bytes | 3206 | // This equation accounts for the fact that even if we have exactly 4 bytes |
| 3205 | // for the string, we still use the next u32 for the null terminator. | 3207 | // for the string, we still use the next u32 for the null terminator. |
| 3206 | extra_i += constraint.len / 4 + 1; | 3208 | extra_i += (constraint.len + input_name.len + 1) / 4 + 1; |
| 3207 | 3209 | ||
| 3208 | if (constraint.len < 3 or constraint[0] != '{' or constraint[constraint.len - 1] != '}') { | 3210 | if (constraint.len < 3 or constraint[0] != '{' or constraint[constraint.len - 1] != '}') { |
| 3209 | return self.fail("unrecognized asm input constraint: '{s}'", .{constraint}); | 3211 | return self.fail("unrecognized asm input constraint: '{s}'", .{constraint}); |
src/arch/arm/CodeGen.zig+4-2| ... | @@ -3609,10 +3609,12 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3609,10 +3609,12 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void { |
| 3609 | } else null; | 3609 | } else null; |
| 3610 | 3610 | ||
| 3611 | for (inputs) |input| { | 3611 | for (inputs) |input| { |
| 3612 | const constraint = std.mem.sliceTo(std.mem.sliceAsBytes(self.air.extra[extra_i..]), 0); | 3612 | const input_bytes = std.mem.sliceAsBytes(self.air.extra[extra_i..]); |
| 3613 | const constraint = std.mem.sliceTo(input_bytes, 0); | ||
| 3614 | const input_name = std.mem.sliceTo(input_bytes[constraint.len + 1 ..], 0); | ||
| 3613 | // This equation accounts for the fact that even if we have exactly 4 bytes | 3615 | // This equation accounts for the fact that even if we have exactly 4 bytes |
| 3614 | // for the string, we still use the next u32 for the null terminator. | 3616 | // for the string, we still use the next u32 for the null terminator. |
| 3615 | extra_i += constraint.len / 4 + 1; | 3617 | extra_i += (constraint.len + input_name.len + 1) / 4 + 1; |
| 3616 | 3618 | ||
| 3617 | if (constraint.len < 3 or constraint[0] != '{' or constraint[constraint.len - 1] != '}') { | 3619 | if (constraint.len < 3 or constraint[0] != '{' or constraint[constraint.len - 1] != '}') { |
| 3618 | return self.fail("unrecognized asm input constraint: '{s}'", .{constraint}); | 3620 | return self.fail("unrecognized asm input constraint: '{s}'", .{constraint}); |
src/arch/riscv64/CodeGen.zig+4-2| ... | @@ -2113,10 +2113,12 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2113,10 +2113,12 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void { |
| 2113 | } else null; | 2113 | } else null; |
| 2114 | 2114 | ||
| 2115 | for (inputs) |input| { | 2115 | for (inputs) |input| { |
| 2116 | const constraint = std.mem.sliceTo(std.mem.sliceAsBytes(self.air.extra[extra_i..]), 0); | 2116 | const input_bytes = std.mem.sliceAsBytes(self.air.extra[extra_i..]); |
| 2117 | const constraint = std.mem.sliceTo(input_bytes, 0); | ||
| 2118 | const input_name = std.mem.sliceTo(input_bytes[constraint.len + 1 ..], 0); | ||
| 2117 | // This equation accounts for the fact that even if we have exactly 4 bytes | 2119 | // This equation accounts for the fact that even if we have exactly 4 bytes |
| 2118 | // for the string, we still use the next u32 for the null terminator. | 2120 | // for the string, we still use the next u32 for the null terminator. |
| 2119 | extra_i += constraint.len / 4 + 1; | 2121 | extra_i += (constraint.len + input_name.len + 1) / 4 + 1; |
| 2120 | 2122 | ||
| 2121 | if (constraint.len < 3 or constraint[0] != '{' or constraint[constraint.len - 1] != '}') { | 2123 | if (constraint.len < 3 or constraint[0] != '{' or constraint[constraint.len - 1] != '}') { |
| 2122 | return self.fail("unrecognized asm input constraint: '{s}'", .{constraint}); | 2124 | return self.fail("unrecognized asm input constraint: '{s}'", .{constraint}); |
src/arch/x86_64/CodeGen.zig+4-2| ... | @@ -4618,10 +4618,12 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4618,10 +4618,12 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void { |
| 4618 | } else null; | 4618 | } else null; |
| 4619 | 4619 | ||
| 4620 | for (inputs) |input| { | 4620 | for (inputs) |input| { |
| 4621 | const constraint = std.mem.sliceTo(std.mem.sliceAsBytes(self.air.extra[extra_i..]), 0); | 4621 | const input_bytes = std.mem.sliceAsBytes(self.air.extra[extra_i..]); |
| 4622 | const constraint = std.mem.sliceTo(input_bytes, 0); | ||
| 4623 | const input_name = std.mem.sliceTo(input_bytes[constraint.len + 1 ..], 0); | ||
| 4622 | // This equation accounts for the fact that even if we have exactly 4 bytes | 4624 | // This equation accounts for the fact that even if we have exactly 4 bytes |
| 4623 | // for the string, we still use the next u32 for the null terminator. | 4625 | // for the string, we still use the next u32 for the null terminator. |
| 4624 | extra_i += constraint.len / 4 + 1; | 4626 | extra_i += (constraint.len + input_name.len + 1) / 4 + 1; |
| 4625 | 4627 | ||
| 4626 | if (constraint.len < 3 or constraint[0] != '{' or constraint[constraint.len - 1] != '}') { | 4628 | if (constraint.len < 3 or constraint[0] != '{' or constraint[constraint.len - 1] != '}') { |
| 4627 | return self.fail("unrecognized asm input constraint: '{s}'", .{constraint}); | 4629 | return self.fail("unrecognized asm input constraint: '{s}'", .{constraint}); |
src/codegen/llvm.zig+35-4| ... | @@ -4545,11 +4545,14 @@ pub const FuncGen = struct { | ... | @@ -4545,11 +4545,14 @@ pub const FuncGen = struct { |
| 4545 | total_i += 1; | 4545 | total_i += 1; |
| 4546 | } | 4546 | } |
| 4547 | 4547 | ||
| 4548 | const input_start_extra_i = extra_i; | ||
| 4548 | for (inputs) |input| { | 4549 | for (inputs) |input| { |
| 4549 | const constraint = std.mem.sliceTo(std.mem.sliceAsBytes(self.air.extra[extra_i..]), 0); | 4550 | const input_bytes = std.mem.sliceAsBytes(self.air.extra[extra_i..]); |
| 4551 | const constraint = std.mem.sliceTo(input_bytes, 0); | ||
| 4552 | const input_name = std.mem.sliceTo(input_bytes[constraint.len + 1 ..], 0); | ||
| 4550 | // This equation accounts for the fact that even if we have exactly 4 bytes | 4553 | // This equation accounts for the fact that even if we have exactly 4 bytes |
| 4551 | // for the string, we still use the next u32 for the null terminator. | 4554 | // for the string, we still use the next u32 for the null terminator. |
| 4552 | extra_i += constraint.len / 4 + 1; | 4555 | extra_i += (constraint.len + input_name.len + 1) / 4 + 1; |
| 4553 | 4556 | ||
| 4554 | const arg_llvm_value = try self.resolveInst(input); | 4557 | const arg_llvm_value = try self.resolveInst(input); |
| 4555 | 4558 | ||
| ... | @@ -4591,11 +4594,12 @@ pub const FuncGen = struct { | ... | @@ -4591,11 +4594,12 @@ pub const FuncGen = struct { |
| 4591 | var rendered_template = std.ArrayList(u8).init(self.gpa); | 4594 | var rendered_template = std.ArrayList(u8).init(self.gpa); |
| 4592 | defer rendered_template.deinit(); | 4595 | defer rendered_template.deinit(); |
| 4593 | 4596 | ||
| 4594 | const State = enum { start, percent }; | 4597 | const State = enum { start, percent, input }; |
| 4595 | 4598 | ||
| 4596 | var state: State = .start; | 4599 | var state: State = .start; |
| 4597 | 4600 | ||
| 4598 | for (asm_source) |byte| { | 4601 | var name_start: usize = undefined; |
| 4602 | for (asm_source) |byte, i| { | ||
| 4599 | switch (state) { | 4603 | switch (state) { |
| 4600 | .start => switch (byte) { | 4604 | .start => switch (byte) { |
| 4601 | '%' => state = .percent, | 4605 | '%' => state = .percent, |
| ... | @@ -4606,12 +4610,39 @@ pub const FuncGen = struct { | ... | @@ -4606,12 +4610,39 @@ pub const FuncGen = struct { |
| 4606 | try rendered_template.append('%'); | 4610 | try rendered_template.append('%'); |
| 4607 | state = .start; | 4611 | state = .start; |
| 4608 | }, | 4612 | }, |
| 4613 | '[' => { | ||
| 4614 | try rendered_template.append('$'); | ||
| 4615 | name_start = i + 1; | ||
| 4616 | state = .input; | ||
| 4617 | }, | ||
| 4609 | else => { | 4618 | else => { |
| 4610 | try rendered_template.append('%'); | 4619 | try rendered_template.append('%'); |
| 4611 | try rendered_template.append(byte); | 4620 | try rendered_template.append(byte); |
| 4612 | state = .start; | 4621 | state = .start; |
| 4613 | }, | 4622 | }, |
| 4614 | }, | 4623 | }, |
| 4624 | .input => switch (byte) { | ||
| 4625 | ']' => { | ||
| 4626 | const name = asm_source[name_start..i]; | ||
| 4627 | state = .start; | ||
| 4628 | |||
| 4629 | extra_i = input_start_extra_i; | ||
| 4630 | for (inputs) |_, input_i| { | ||
| 4631 | const input_bytes = std.mem.sliceAsBytes(self.air.extra[extra_i..]); | ||
| 4632 | const constraint = std.mem.sliceTo(input_bytes, 0); | ||
| 4633 | const input_name = std.mem.sliceTo(input_bytes[constraint.len + 1 ..], 0); | ||
| 4634 | extra_i += (constraint.len + input_name.len + 1) / 4 + 1; | ||
| 4635 | |||
| 4636 | if (std.mem.eql(u8, name, input_name)) { | ||
| 4637 | try rendered_template.writer().print("{d}", .{input_i}); | ||
| 4638 | break; | ||
| 4639 | } | ||
| 4640 | } else { | ||
| 4641 | return self.todo("TODO validate asm in Sema", .{}); | ||
| 4642 | } | ||
| 4643 | }, | ||
| 4644 | else => {}, | ||
| 4645 | }, | ||
| 4615 | } | 4646 | } |
| 4616 | } | 4647 | } |
| 4617 | 4648 |