| 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 | 815 | /// terminated string. pad to the next u32 after the null byte. |
| 816 | 816 | /// 3. for every inputs_len |
| 817 | 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 | 820 | /// terminated string. pad to the next u32 after the null byte. |
| 819 | 821 | /// 4. for every clobbers_len |
| 820 | 822 | /// - clobber_name: memory at this position is reinterpreted as a null |
src/Sema.zig+10-10| ... | ... | @@ -10295,15 +10295,12 @@ fn zirAsm( |
| 10295 | 10295 | }; |
| 10296 | 10296 | |
| 10297 | 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 | 10300 | for (args) |*arg, arg_i| { |
| 10301 | 10301 | const input = sema.code.extraData(Zir.Inst.Asm.Input, extra_i); |
| 10302 | 10302 | extra_i = input.end; |
| 10303 | 10303 | |
| 10304 | const name = sema.code.nullTerminatedString(input.data.name); | |
| 10305 | _ = name; // TODO: use the name | |
| 10306 | ||
| 10307 | 10304 | const uncasted_arg = sema.resolveInst(input.data.operand); |
| 10308 | 10305 | const uncasted_arg_ty = sema.typeOf(uncasted_arg); |
| 10309 | 10306 | switch (uncasted_arg_ty.zigTypeTag()) { |
| ... | ... | @@ -10313,8 +10310,9 @@ fn zirAsm( |
| 10313 | 10310 | } |
| 10314 | 10311 | |
| 10315 | 10312 | const constraint = sema.code.nullTerminatedString(input.data.constraint); |
| 10316 | needed_capacity += constraint.len / 4 + 1; | |
| 10317 | inputs[arg_i] = constraint; | |
| 10313 | const name = sema.code.nullTerminatedString(input.data.name); | |
| 10314 | needed_capacity += (constraint.len + name.len + 1) / 4 + 1; | |
| 10315 | inputs[arg_i] = .{ .c = constraint, .n = name }; | |
| 10318 | 10316 | } |
| 10319 | 10317 | |
| 10320 | 10318 | const clobbers = try sema.arena.alloc([]const u8, clobbers_len); |
| ... | ... | @@ -10353,11 +10351,13 @@ fn zirAsm( |
| 10353 | 10351 | buffer[o.constraint.len] = 0; |
| 10354 | 10352 | sema.air_extra.items.len += o.constraint.len / 4 + 1; |
| 10355 | 10353 | } |
| 10356 | for (inputs) |constraint| { | |
| 10354 | for (inputs) |input| { | |
| 10357 | 10355 | const buffer = mem.sliceAsBytes(sema.air_extra.unusedCapacitySlice()); |
| 10358 | mem.copy(u8, buffer, constraint); | |
| 10359 | buffer[constraint.len] = 0; | |
| 10360 | sema.air_extra.items.len += constraint.len / 4 + 1; | |
| 10356 | mem.copy(u8, buffer, input.c); | |
| 10357 | buffer[input.c.len] = 0; | |
| 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 | 10362 | for (clobbers) |clobber| { |
| 10363 | 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 | 3200 | } else null; |
| 3201 | 3201 | |
| 3202 | 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 | 3206 | // This equation accounts for the fact that even if we have exactly 4 bytes |
| 3205 | 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 | 3210 | if (constraint.len < 3 or constraint[0] != '{' or constraint[constraint.len - 1] != '}') { |
| 3209 | 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 | 3609 | } else null; |
| 3610 | 3610 | |
| 3611 | 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 | 3615 | // This equation accounts for the fact that even if we have exactly 4 bytes |
| 3614 | 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 | 3619 | if (constraint.len < 3 or constraint[0] != '{' or constraint[constraint.len - 1] != '}') { |
| 3618 | 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 | 2113 | } else null; |
| 2114 | 2114 | |
| 2115 | 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 | 2119 | // This equation accounts for the fact that even if we have exactly 4 bytes |
| 2118 | 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 | 2123 | if (constraint.len < 3 or constraint[0] != '{' or constraint[constraint.len - 1] != '}') { |
| 2122 | 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 | 4618 | } else null; |
| 4619 | 4619 | |
| 4620 | 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 | 4624 | // This equation accounts for the fact that even if we have exactly 4 bytes |
| 4623 | 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 | 4628 | if (constraint.len < 3 or constraint[0] != '{' or constraint[constraint.len - 1] != '}') { |
| 4627 | 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 | 4545 | total_i += 1; |
| 4546 | 4546 | } |
| 4547 | 4547 | |
| 4548 | const input_start_extra_i = extra_i; | |
| 4548 | 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 | 4553 | // This equation accounts for the fact that even if we have exactly 4 bytes |
| 4551 | 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 | 4557 | const arg_llvm_value = try self.resolveInst(input); |
| 4555 | 4558 | |
| ... | ... | @@ -4591,11 +4594,12 @@ pub const FuncGen = struct { |
| 4591 | 4594 | var rendered_template = std.ArrayList(u8).init(self.gpa); |
| 4592 | 4595 | defer rendered_template.deinit(); |
| 4593 | 4596 | |
| 4594 | const State = enum { start, percent }; | |
| 4597 | const State = enum { start, percent, input }; | |
| 4595 | 4598 | |
| 4596 | 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 | 4603 | switch (state) { |
| 4600 | 4604 | .start => switch (byte) { |
| 4601 | 4605 | '%' => state = .percent, |
| ... | ... | @@ -4606,12 +4610,39 @@ pub const FuncGen = struct { |
| 4606 | 4610 | try rendered_template.append('%'); |
| 4607 | 4611 | state = .start; |
| 4608 | 4612 | }, |
| 4613 | '[' => { | |
| 4614 | try rendered_template.append('$'); | |
| 4615 | name_start = i + 1; | |
| 4616 | state = .input; | |
| 4617 | }, | |
| 4609 | 4618 | else => { |
| 4610 | 4619 | try rendered_template.append('%'); |
| 4611 | 4620 | try rendered_template.append(byte); |
| 4612 | 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 |