Commit bf014d529a
Changed files (4)
src-self-hosted
src-self-hosted/astgen.zig
@@ -274,6 +274,7 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr
.ErrorSetDecl => return errorSetDecl(mod, scope, rl, node.castTag(.ErrorSetDecl).?),
.ErrorType => return rlWrap(mod, scope, rl, try errorType(mod, scope, node.castTag(.ErrorType).?)),
.For => return forExpr(mod, scope, rl, node.castTag(.For).?),
+ .ArrayAccess => return arrayAccess(mod, scope, rl, node.castTag(.ArrayAccess).?),
.Defer => return mod.failNode(scope, node, "TODO implement astgen.expr for .Defer", .{}),
.Catch => return mod.failNode(scope, node, "TODO implement astgen.expr for .Catch", .{}),
@@ -283,7 +284,6 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr
.Resume => return mod.failNode(scope, node, "TODO implement astgen.expr for .Resume", .{}),
.Try => return mod.failNode(scope, node, "TODO implement astgen.expr for .Try", .{}),
.Slice => return mod.failNode(scope, node, "TODO implement astgen.expr for .Slice", .{}),
- .ArrayAccess => return mod.failNode(scope, node, "TODO implement astgen.expr for .ArrayAccess", .{}),
.ArrayInitializer => return mod.failNode(scope, node, "TODO implement astgen.expr for .ArrayInitializer", .{}),
.ArrayInitializerDot => return mod.failNode(scope, node, "TODO implement astgen.expr for .ArrayInitializerDot", .{}),
.StructInitializer => return mod.failNode(scope, node, "TODO implement astgen.expr for .StructInitializer", .{}),
@@ -797,6 +797,16 @@ fn field(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.SimpleInfix
return rlWrapPtr(mod, scope, rl, try addZIRInst(mod, scope, src, zir.Inst.FieldPtr, .{ .object_ptr = lhs, .field_name = field_name }, .{}));
}
+fn arrayAccess(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.ArrayAccess) InnerError!*zir.Inst {
+ const tree = scope.tree();
+ const src = tree.token_locs[node.rtoken].start;
+
+ const array_ptr = try expr(mod, scope, .ref, node.lhs);
+ const index = try expr(mod, scope, .none, node.index_expr);
+
+ return rlWrapPtr(mod, scope, rl, try addZIRInst(mod, scope, src, zir.Inst.ElemPtr, .{ .array_ptr = array_ptr, .index = index }, .{}));
+}
+
fn deref(mod: *Module, scope: *Scope, node: *ast.Node.SimpleSuffixOp) InnerError!*zir.Inst {
const tree = scope.tree();
const src = tree.token_locs[node.rtoken].start;
src-self-hosted/zir_sema.zig
@@ -1076,9 +1076,19 @@ fn analyzeInstElemPtr(mod: *Module, scope: *Scope, inst: *zir.Inst.ElemPtr) Inne
const array_ptr = try resolveInst(mod, scope, inst.positionals.array_ptr);
const uncasted_index = try resolveInst(mod, scope, inst.positionals.index);
const elem_index = try mod.coerce(scope, Type.initTag(.usize), uncasted_index);
+
+ const elem_ty = switch (array_ptr.ty.zigTypeTag()) {
+ .Pointer => array_ptr.ty.elemType(),
+ else => return mod.fail(scope, inst.positionals.array_ptr.src, "expected pointer, found '{}'", .{array_ptr.ty}),
+ };
+ if (!elem_ty.isIndexable()) {
+ return mod.fail(scope, inst.base.src, "array access of non-array type '{}'", .{elem_ty});
+ }
- if (array_ptr.ty.isSinglePointer() and array_ptr.ty.elemType().zigTypeTag() == .Array) {
- if (array_ptr.value()) |array_ptr_val| {
+ if (elem_ty.isSinglePointer() and elem_ty.elemType().zigTypeTag() == .Array) {
+ // we have to deref the ptr operand to get the actual array pointer
+ const array_ptr_deref = try mod.analyzeDeref(scope, inst.base.src, array_ptr, inst.positionals.array_ptr.src);
+ if (array_ptr_deref.value()) |array_ptr_val| {
if (elem_index.value()) |index_val| {
// Both array pointer and index are compile-time known.
const index_u64 = index_val.toUnsignedInt();
@@ -1089,7 +1099,7 @@ fn analyzeInstElemPtr(mod: *Module, scope: *Scope, inst: *zir.Inst.ElemPtr) Inne
const type_payload = try scope.arena().create(Type.Payload.PointerSimple);
type_payload.* = .{
.base = .{ .tag = .single_const_pointer },
- .pointee_type = array_ptr.ty.elemType().elemType(),
+ .pointee_type = elem_ty.elemType().elemType(),
};
return mod.constInst(scope, inst.base.src, .{
test/stage2/test.zig
@@ -820,6 +820,31 @@ pub fn addCases(ctx: *TestContext) !void {
,
"",
);
+
+ // Array access.
+ case.addCompareOutput(
+ \\export fn _start() noreturn {
+ \\ assert("hello"[0] == 'h');
+ \\
+ \\ exit();
+ \\}
+ \\
+ \\pub fn assert(ok: bool) void {
+ \\ if (!ok) unreachable; // assertion failure
+ \\}
+ \\
+ \\fn exit() noreturn {
+ \\ asm volatile ("syscall"
+ \\ :
+ \\ : [number] "{rax}" (231),
+ \\ [arg1] "{rdi}" (0)
+ \\ : "rcx", "r11", "memory"
+ \\ );
+ \\ unreachable;
+ \\}
+ ,
+ "",
+ );
}
{
test/stage2/zir.zig
@@ -43,10 +43,11 @@ pub fn addCases(ctx: *TestContext) !void {
\\
\\@entry = fn(@fnty, {
\\ %a = str("\x32\x08\x01\x0a")
- \\ %eptr0 = elemptr(%a, @0)
- \\ %eptr1 = elemptr(%a, @1)
- \\ %eptr2 = elemptr(%a, @2)
- \\ %eptr3 = elemptr(%a, @3)
+ \\ %a_ref = ref(%a)
+ \\ %eptr0 = elemptr(%a_ref, @0)
+ \\ %eptr1 = elemptr(%a_ref, @1)
+ \\ %eptr2 = elemptr(%a_ref, @2)
+ \\ %eptr3 = elemptr(%a_ref, @3)
\\ %v0 = deref(%eptr0)
\\ %v1 = deref(%eptr1)
\\ %v2 = deref(%eptr2)