authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-03-31 00:38:19+03:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-03-31 01:33:28-04:00
log75c2cff40ef5c758ec18455324a50378684aff85
treedbad1cafdd53fcab11e9be52aa27702b9bbb1345
parent6655c6092efbdc8b1aeb89ff9f7a8b05f736916a

stage2: handle assembly input names


7 files changed, 63 insertions(+), 22 deletions(-)

src/Air.zig+2
......@@ -815,6 +815,8 @@ pub const VectorCmp = struct {
815815/// terminated string. pad to the next u32 after the null byte.
816816/// 3. for every inputs_len
817817/// - constraint: memory at this position is reinterpreted as a null
818/// terminated string.
819/// - name: memory at this position is reinterpreted as a null
818820/// terminated string. pad to the next u32 after the null byte.
819821/// 4. for every clobbers_len
820822/// - clobber_name: memory at this position is reinterpreted as a null
src/Sema.zig+10-10
......@@ -10295,15 +10295,12 @@ fn zirAsm(
1029510295 };
1029610296
1029710297 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);
1029910299
1030010300 for (args) |*arg, arg_i| {
1030110301 const input = sema.code.extraData(Zir.Inst.Asm.Input, extra_i);
1030210302 extra_i = input.end;
1030310303
10304 const name = sema.code.nullTerminatedString(input.data.name);
10305 _ = name; // TODO: use the name
10306
1030710304 const uncasted_arg = sema.resolveInst(input.data.operand);
1030810305 const uncasted_arg_ty = sema.typeOf(uncasted_arg);
1030910306 switch (uncasted_arg_ty.zigTypeTag()) {
......@@ -10313,8 +10310,9 @@ fn zirAsm(
1031310310 }
1031410311
1031510312 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 };
1031810316 }
1031910317
1032010318 const clobbers = try sema.arena.alloc([]const u8, clobbers_len);
......@@ -10353,11 +10351,13 @@ fn zirAsm(
1035310351 buffer[o.constraint.len] = 0;
1035410352 sema.air_extra.items.len += o.constraint.len / 4 + 1;
1035510353 }
10356 for (inputs) |constraint| {
10354 for (inputs) |input| {
1035710355 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;
1036110361 }
1036210362 for (clobbers) |clobber| {
1036310363 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 {
32003200 } else null;
32013201
32023202 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);
32043206 // This equation accounts for the fact that even if we have exactly 4 bytes
32053207 // 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;
32073209
32083210 if (constraint.len < 3 or constraint[0] != '{' or constraint[constraint.len - 1] != '}') {
32093211 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 {
36093609 } else null;
36103610
36113611 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);
36133615 // This equation accounts for the fact that even if we have exactly 4 bytes
36143616 // 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;
36163618
36173619 if (constraint.len < 3 or constraint[0] != '{' or constraint[constraint.len - 1] != '}') {
36183620 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 {
21132113 } else null;
21142114
21152115 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);
21172119 // This equation accounts for the fact that even if we have exactly 4 bytes
21182120 // 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;
21202122
21212123 if (constraint.len < 3 or constraint[0] != '{' or constraint[constraint.len - 1] != '}') {
21222124 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 {
46184618 } else null;
46194619
46204620 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);
46224624 // This equation accounts for the fact that even if we have exactly 4 bytes
46234625 // 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;
46254627
46264628 if (constraint.len < 3 or constraint[0] != '{' or constraint[constraint.len - 1] != '}') {
46274629 return self.fail("unrecognized asm input constraint: '{s}'", .{constraint});
src/codegen/llvm.zig+35-4
......@@ -4545,11 +4545,14 @@ pub const FuncGen = struct {
45454545 total_i += 1;
45464546 }
45474547
4548 const input_start_extra_i = extra_i;
45484549 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);
45504553 // This equation accounts for the fact that even if we have exactly 4 bytes
45514554 // 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;
45534556
45544557 const arg_llvm_value = try self.resolveInst(input);
45554558
......@@ -4591,11 +4594,12 @@ pub const FuncGen = struct {
45914594 var rendered_template = std.ArrayList(u8).init(self.gpa);
45924595 defer rendered_template.deinit();
45934596
4594 const State = enum { start, percent };
4597 const State = enum { start, percent, input };
45954598
45964599 var state: State = .start;
45974600
4598 for (asm_source) |byte| {
4601 var name_start: usize = undefined;
4602 for (asm_source) |byte, i| {
45994603 switch (state) {
46004604 .start => switch (byte) {
46014605 '%' => state = .percent,
......@@ -4606,12 +4610,39 @@ pub const FuncGen = struct {
46064610 try rendered_template.append('%');
46074611 state = .start;
46084612 },
4613 '[' => {
4614 try rendered_template.append('$');
4615 name_start = i + 1;
4616 state = .input;
4617 },
46094618 else => {
46104619 try rendered_template.append('%');
46114620 try rendered_template.append(byte);
46124621 state = .start;
46134622 },
46144623 },
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 },
46154646 }
46164647 }
46174648