authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-08-25 19:59:35+03:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-08-26 19:50:56-07:00
logbf014d529a8373d43f92b0dd5c8a5d8509150ca9
tree483a07e52b3149709935323092268acf86163fd2
parentbcd04089ebf563659972c1a0fe1864521b128d37

stage2: array access astgen


4 files changed, 54 insertions(+), 8 deletions(-)

src-self-hosted/astgen.zig+11-1
......@@ -274,6 +274,7 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr
274274 .ErrorSetDecl => return errorSetDecl(mod, scope, rl, node.castTag(.ErrorSetDecl).?),
275275 .ErrorType => return rlWrap(mod, scope, rl, try errorType(mod, scope, node.castTag(.ErrorType).?)),
276276 .For => return forExpr(mod, scope, rl, node.castTag(.For).?),
277 .ArrayAccess => return arrayAccess(mod, scope, rl, node.castTag(.ArrayAccess).?),
277278
278279 .Defer => return mod.failNode(scope, node, "TODO implement astgen.expr for .Defer", .{}),
279280 .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
283284 .Resume => return mod.failNode(scope, node, "TODO implement astgen.expr for .Resume", .{}),
284285 .Try => return mod.failNode(scope, node, "TODO implement astgen.expr for .Try", .{}),
285286 .Slice => return mod.failNode(scope, node, "TODO implement astgen.expr for .Slice", .{}),
286 .ArrayAccess => return mod.failNode(scope, node, "TODO implement astgen.expr for .ArrayAccess", .{}),
287287 .ArrayInitializer => return mod.failNode(scope, node, "TODO implement astgen.expr for .ArrayInitializer", .{}),
288288 .ArrayInitializerDot => return mod.failNode(scope, node, "TODO implement astgen.expr for .ArrayInitializerDot", .{}),
289289 .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
797797 return rlWrapPtr(mod, scope, rl, try addZIRInst(mod, scope, src, zir.Inst.FieldPtr, .{ .object_ptr = lhs, .field_name = field_name }, .{}));
798798}
799799
800fn arrayAccess(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.ArrayAccess) InnerError!*zir.Inst {
801 const tree = scope.tree();
802 const src = tree.token_locs[node.rtoken].start;
803
804 const array_ptr = try expr(mod, scope, .ref, node.lhs);
805 const index = try expr(mod, scope, .none, node.index_expr);
806
807 return rlWrapPtr(mod, scope, rl, try addZIRInst(mod, scope, src, zir.Inst.ElemPtr, .{ .array_ptr = array_ptr, .index = index }, .{}));
808}
809
800810fn deref(mod: *Module, scope: *Scope, node: *ast.Node.SimpleSuffixOp) InnerError!*zir.Inst {
801811 const tree = scope.tree();
802812 const src = tree.token_locs[node.rtoken].start;
src-self-hosted/zir_sema.zig+13-3
......@@ -1076,9 +1076,19 @@ fn analyzeInstElemPtr(mod: *Module, scope: *Scope, inst: *zir.Inst.ElemPtr) Inne
10761076 const array_ptr = try resolveInst(mod, scope, inst.positionals.array_ptr);
10771077 const uncasted_index = try resolveInst(mod, scope, inst.positionals.index);
10781078 const elem_index = try mod.coerce(scope, Type.initTag(.usize), uncasted_index);
1079
1080 const elem_ty = switch (array_ptr.ty.zigTypeTag()) {
1081 .Pointer => array_ptr.ty.elemType(),
1082 else => return mod.fail(scope, inst.positionals.array_ptr.src, "expected pointer, found '{}'", .{array_ptr.ty}),
1083 };
1084 if (!elem_ty.isIndexable()) {
1085 return mod.fail(scope, inst.base.src, "array access of non-array type '{}'", .{elem_ty});
1086 }
10791087
1080 if (array_ptr.ty.isSinglePointer() and array_ptr.ty.elemType().zigTypeTag() == .Array) {
1081 if (array_ptr.value()) |array_ptr_val| {
1088 if (elem_ty.isSinglePointer() and elem_ty.elemType().zigTypeTag() == .Array) {
1089 // we have to deref the ptr operand to get the actual array pointer
1090 const array_ptr_deref = try mod.analyzeDeref(scope, inst.base.src, array_ptr, inst.positionals.array_ptr.src);
1091 if (array_ptr_deref.value()) |array_ptr_val| {
10821092 if (elem_index.value()) |index_val| {
10831093 // Both array pointer and index are compile-time known.
10841094 const index_u64 = index_val.toUnsignedInt();
......@@ -1089,7 +1099,7 @@ fn analyzeInstElemPtr(mod: *Module, scope: *Scope, inst: *zir.Inst.ElemPtr) Inne
10891099 const type_payload = try scope.arena().create(Type.Payload.PointerSimple);
10901100 type_payload.* = .{
10911101 .base = .{ .tag = .single_const_pointer },
1092 .pointee_type = array_ptr.ty.elemType().elemType(),
1102 .pointee_type = elem_ty.elemType().elemType(),
10931103 };
10941104
10951105 return mod.constInst(scope, inst.base.src, .{
test/stage2/test.zig+25
......@@ -820,6 +820,31 @@ pub fn addCases(ctx: *TestContext) !void {
820820 ,
821821 "",
822822 );
823
824 // Array access.
825 case.addCompareOutput(
826 \\export fn _start() noreturn {
827 \\ assert("hello"[0] == 'h');
828 \\
829 \\ exit();
830 \\}
831 \\
832 \\pub fn assert(ok: bool) void {
833 \\ if (!ok) unreachable; // assertion failure
834 \\}
835 \\
836 \\fn exit() noreturn {
837 \\ asm volatile ("syscall"
838 \\ :
839 \\ : [number] "{rax}" (231),
840 \\ [arg1] "{rdi}" (0)
841 \\ : "rcx", "r11", "memory"
842 \\ );
843 \\ unreachable;
844 \\}
845 ,
846 "",
847 );
823848 }
824849
825850 {
test/stage2/zir.zig+5-4
......@@ -43,10 +43,11 @@ pub fn addCases(ctx: *TestContext) !void {
4343 \\
4444 \\@entry = fn(@fnty, {
4545 \\ %a = str("\x32\x08\x01\x0a")
46 \\ %eptr0 = elemptr(%a, @0)
47 \\ %eptr1 = elemptr(%a, @1)
48 \\ %eptr2 = elemptr(%a, @2)
49 \\ %eptr3 = elemptr(%a, @3)
46 \\ %a_ref = ref(%a)
47 \\ %eptr0 = elemptr(%a_ref, @0)
48 \\ %eptr1 = elemptr(%a_ref, @1)
49 \\ %eptr2 = elemptr(%a_ref, @2)
50 \\ %eptr3 = elemptr(%a_ref, @3)
5051 \\ %v0 = deref(%eptr0)
5152 \\ %v1 = deref(%eptr1)
5253 \\ %v2 = deref(%eptr2)