Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/arch/wasm/CodeGen.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2289,6 +2289,14 @@ fn lowerParentPtr(self: *Self, ptr_val: Value, ptr_child_ty: Type) InnerError!WV
const offset = @intCast(u32, std.mem.alignForwardGeneric(u64, layout.tag_size, layout.tag_align));
break :blk offset;
},
.Pointer => switch (parent_ty.ptrSize()) {
.Slice => switch (field_ptr.field_index) {
0 => 0,
1 => self.ptrSize(),
else => unreachable,
},
else => unreachable,
},
else => unreachable,
};

Expand Down
14 changes: 12 additions & 2 deletions src/codegen.zig
Original file line number Diff line number Diff line change
Expand Up @@ -363,11 +363,21 @@ pub fn generateSymbol(
const mod = bin_file.options.module.?;
const decl = mod.declPtr(decl_index);
const addend = blk: {
switch (decl.ty.tag()) {
.@"struct" => {
switch (decl.ty.zigTypeTag()) {
.Struct => {
const addend = decl.ty.structFieldOffset(field_ptr.field_index, target);
break :blk @intCast(u32, addend);
},
.Pointer => {
assert(decl.ty.isSlice());
var buf: Type.SlicePtrFieldTypeBuffer = undefined;
const addend = switch (field_ptr.field_index) {
0 => 0,
1 => decl.ty.slicePtrFieldType(&buf).abiSize(target),
else => unreachable,
};
break :blk @intCast(u32, addend);
},
else => return Result{
.fail = try ErrorMsg.create(
bin_file.allocator,
Expand Down
34 changes: 22 additions & 12 deletions src/codegen/c.zig
Original file line number Diff line number Diff line change
Expand Up @@ -485,14 +485,24 @@ pub const DeclGen = struct {
const field_ptr = ptr_val.castTag(.field_ptr).?.data;
const container_ty = field_ptr.container_ty;
const index = field_ptr.field_index;
const field_name = switch (container_ty.zigTypeTag()) {
.Struct => container_ty.structFields().keys()[index],
.Union => container_ty.unionFields().keys()[index],
else => unreachable,
};
const field_ty = switch (container_ty.zigTypeTag()) {
.Struct => container_ty.structFields().values()[index].ty,
.Union => container_ty.unionFields().values()[index].ty,
const FieldInfo = struct { name: []const u8, ty: Type };
const field_info: FieldInfo = switch (container_ty.zigTypeTag()) {
.Struct => .{
.name = container_ty.structFields().keys()[index],
.ty = container_ty.structFields().values()[index].ty,
},
.Union => .{
.name = container_ty.unionFields().keys()[index],
.ty = container_ty.unionFields().values()[index].ty,
},
.Pointer => switch (container_ty.ptrSize()) {
.Slice => switch (index) {
0 => FieldInfo{ .name = "ptr", .ty = container_ty.childType() },
1 => FieldInfo{ .name = "len", .ty = Type.usize },
else => unreachable,
},
else => unreachable,
},
else => unreachable,
};
var container_ptr_ty_pl: Type.Payload.ElemType = .{
Expand All @@ -501,16 +511,16 @@ pub const DeclGen = struct {
};
const container_ptr_ty = Type.initPayload(&container_ptr_ty_pl.base);

if (field_ty.hasRuntimeBitsIgnoreComptime()) {
if (field_info.ty.hasRuntimeBitsIgnoreComptime()) {
try writer.writeAll("&(");
try dg.renderParentPtr(writer, field_ptr.container_ptr, container_ptr_ty);
if (field_ptr.container_ty.tag() == .union_tagged or field_ptr.container_ty.tag() == .union_safety_tagged) {
try writer.print(")->payload.{ }", .{fmtIdent(field_name)});
try writer.print(")->payload.{ }", .{fmtIdent(field_info.name)});
} else {
try writer.print(")->{ }", .{fmtIdent(field_name)});
try writer.print(")->{ }", .{fmtIdent(field_info.name)});
}
} else {
try dg.renderParentPtr(writer, field_ptr.container_ptr, field_ty);
try dg.renderParentPtr(writer, field_ptr.container_ptr, field_info.ty);
}
},
.elem_ptr => {
Expand Down
9 changes: 9 additions & 0 deletions src/codegen/llvm.zig
Original file line number Diff line number Diff line change
Expand Up @@ -3938,6 +3938,15 @@ pub const DeclGen = struct {
const parent_llvm_ty = try dg.lowerType(parent_ty);
break :blk parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len);
},
.Pointer => {
assert(parent_ty.isSlice());
const indices: [2]*llvm.Value = .{
llvm_u32.constInt(0, .False),
llvm_u32.constInt(field_index, .False),
};
const parent_llvm_ty = try dg.lowerType(parent_ty);
break :blk parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len);
},
else => unreachable,
}
},
Expand Down
1 change: 1 addition & 0 deletions test/behavior.zig
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ test {
_ = @import("behavior/bugs/12928.zig");
_ = @import("behavior/bugs/12945.zig");
_ = @import("behavior/bugs/12984.zig");
_ = @import("behavior/bugs/13068.zig");
_ = @import("behavior/bugs/13128.zig");
_ = @import("behavior/byteswap.zig");
_ = @import("behavior/byval_arg_var.zig");
Expand Down
15 changes: 15 additions & 0 deletions test/behavior/bugs/13068.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const std = @import("std");
const builtin = @import("builtin");

pub const allocator = std.heap.page_allocator;
var list = std.ArrayList(u32).init(allocator);

test {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO

list.items.len = 0;
}
20 changes: 16 additions & 4 deletions test/behavior/slice.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const builtin = @import("builtin");
const std = @import("std");
const expect = std.testing.expect;
const expectEqualSlices = std.testing.expectEqualSlices;
const expectEqualStrings = std.testing.expectEqualStrings;
const expectEqual = std.testing.expectEqual;
const mem = std.mem;

Expand Down Expand Up @@ -686,8 +687,6 @@ test "slice len modification at comptime" {
}

test "slice field ptr const" {
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO

const const_slice: []const u8 = "string";

const const_ptr_const_slice = &const_slice;
Expand All @@ -700,8 +699,6 @@ test "slice field ptr const" {
}

test "slice field ptr var" {
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO

var var_slice: []const u8 = "string";

var var_ptr_var_slice = &var_slice;
Expand All @@ -712,3 +709,18 @@ test "slice field ptr var" {
try expectEqual(*[]const u8, @TypeOf(&const_ptr_var_slice.*));
try expectEqual(*[*]const u8, @TypeOf(&const_ptr_var_slice.ptr));
}

test "global slice field access" {
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO

const S = struct {
var slice: []const u8 = undefined;
};
S.slice = "string";
S.slice.ptr += 1;
S.slice.len -= 2;
try expectEqualStrings("trin", S.slice);
}