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...@@ -274,6 +274,7 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr
274 .ErrorSetDecl => return errorSetDecl(mod, scope, rl, node.castTag(.ErrorSetDecl).?),274 .ErrorSetDecl => return errorSetDecl(mod, scope, rl, node.castTag(.ErrorSetDecl).?),
275 .ErrorType => return rlWrap(mod, scope, rl, try errorType(mod, scope, node.castTag(.ErrorType).?)),275 .ErrorType => return rlWrap(mod, scope, rl, try errorType(mod, scope, node.castTag(.ErrorType).?)),
276 .For => return forExpr(mod, scope, rl, node.castTag(.For).?),276 .For => return forExpr(mod, scope, rl, node.castTag(.For).?),
277 .ArrayAccess => return arrayAccess(mod, scope, rl, node.castTag(.ArrayAccess).?),
277278
278 .Defer => return mod.failNode(scope, node, "TODO implement astgen.expr for .Defer", .{}),279 .Defer => return mod.failNode(scope, node, "TODO implement astgen.expr for .Defer", .{}),
279 .Catch => return mod.failNode(scope, node, "TODO implement astgen.expr for .Catch", .{}),280 .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...@@ -283,7 +284,6 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr
283 .Resume => return mod.failNode(scope, node, "TODO implement astgen.expr for .Resume", .{}),284 .Resume => return mod.failNode(scope, node, "TODO implement astgen.expr for .Resume", .{}),
284 .Try => return mod.failNode(scope, node, "TODO implement astgen.expr for .Try", .{}),285 .Try => return mod.failNode(scope, node, "TODO implement astgen.expr for .Try", .{}),
285 .Slice => return mod.failNode(scope, node, "TODO implement astgen.expr for .Slice", .{}),286 .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", .{}),
287 .ArrayInitializer => return mod.failNode(scope, node, "TODO implement astgen.expr for .ArrayInitializer", .{}),287 .ArrayInitializer => return mod.failNode(scope, node, "TODO implement astgen.expr for .ArrayInitializer", .{}),
288 .ArrayInitializerDot => return mod.failNode(scope, node, "TODO implement astgen.expr for .ArrayInitializerDot", .{}),288 .ArrayInitializerDot => return mod.failNode(scope, node, "TODO implement astgen.expr for .ArrayInitializerDot", .{}),
289 .StructInitializer => return mod.failNode(scope, node, "TODO implement astgen.expr for .StructInitializer", .{}),289 .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...@@ -797,6 +797,16 @@ fn field(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.SimpleInfix
797 return rlWrapPtr(mod, scope, rl, try addZIRInst(mod, scope, src, zir.Inst.FieldPtr, .{ .object_ptr = lhs, .field_name = field_name }, .{}));797 return rlWrapPtr(mod, scope, rl, try addZIRInst(mod, scope, src, zir.Inst.FieldPtr, .{ .object_ptr = lhs, .field_name = field_name }, .{}));
798}798}
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
800fn deref(mod: *Module, scope: *Scope, node: *ast.Node.SimpleSuffixOp) InnerError!*zir.Inst {810fn deref(mod: *Module, scope: *Scope, node: *ast.Node.SimpleSuffixOp) InnerError!*zir.Inst {
801 const tree = scope.tree();811 const tree = scope.tree();
802 const src = tree.token_locs[node.rtoken].start;812 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...@@ -1076,9 +1076,19 @@ fn analyzeInstElemPtr(mod: *Module, scope: *Scope, inst: *zir.Inst.ElemPtr) Inne
1076 const array_ptr = try resolveInst(mod, scope, inst.positionals.array_ptr);1076 const array_ptr = try resolveInst(mod, scope, inst.positionals.array_ptr);
1077 const uncasted_index = try resolveInst(mod, scope, inst.positionals.index);1077 const uncasted_index = try resolveInst(mod, scope, inst.positionals.index);
1078 const elem_index = try mod.coerce(scope, Type.initTag(.usize), uncasted_index);1078 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) {1088 if (elem_ty.isSinglePointer() and elem_ty.elemType().zigTypeTag() == .Array) {
1081 if (array_ptr.value()) |array_ptr_val| {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| {
1082 if (elem_index.value()) |index_val| {1092 if (elem_index.value()) |index_val| {
1083 // Both array pointer and index are compile-time known.1093 // Both array pointer and index are compile-time known.
1084 const index_u64 = index_val.toUnsignedInt();1094 const index_u64 = index_val.toUnsignedInt();
...@@ -1089,7 +1099,7 @@ fn analyzeInstElemPtr(mod: *Module, scope: *Scope, inst: *zir.Inst.ElemPtr) Inne...@@ -1089,7 +1099,7 @@ fn analyzeInstElemPtr(mod: *Module, scope: *Scope, inst: *zir.Inst.ElemPtr) Inne
1089 const type_payload = try scope.arena().create(Type.Payload.PointerSimple);1099 const type_payload = try scope.arena().create(Type.Payload.PointerSimple);
1090 type_payload.* = .{1100 type_payload.* = .{
1091 .base = .{ .tag = .single_const_pointer },1101 .base = .{ .tag = .single_const_pointer },
1092 .pointee_type = array_ptr.ty.elemType().elemType(),1102 .pointee_type = elem_ty.elemType().elemType(),
1093 };1103 };
10941104
1095 return mod.constInst(scope, inst.base.src, .{1105 return mod.constInst(scope, inst.base.src, .{
test/stage2/test.zig+25
...@@ -820,6 +820,31 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -820,6 +820,31 @@ pub fn addCases(ctx: *TestContext) !void {
820 ,820 ,
821 "",821 "",
822 );822 );
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 );
823 }848 }
824849
825 {850 {
test/stage2/zir.zig+5-4
...@@ -43,10 +43,11 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -43,10 +43,11 @@ pub fn addCases(ctx: *TestContext) !void {
43 \\43 \\
44 \\@entry = fn(@fnty, {44 \\@entry = fn(@fnty, {
45 \\ %a = str("\x32\x08\x01\x0a")45 \\ %a = str("\x32\x08\x01\x0a")
46 \\ %eptr0 = elemptr(%a, @0)46 \\ %a_ref = ref(%a)
47 \\ %eptr1 = elemptr(%a, @1)47 \\ %eptr0 = elemptr(%a_ref, @0)
48 \\ %eptr2 = elemptr(%a, @2)48 \\ %eptr1 = elemptr(%a_ref, @1)
49 \\ %eptr3 = elemptr(%a, @3)49 \\ %eptr2 = elemptr(%a_ref, @2)
50 \\ %eptr3 = elemptr(%a_ref, @3)
50 \\ %v0 = deref(%eptr0)51 \\ %v0 = deref(%eptr0)
51 \\ %v1 = deref(%eptr1)52 \\ %v1 = deref(%eptr1)
52 \\ %v2 = deref(%eptr2)53 \\ %v2 = deref(%eptr2)