Commit 91e1414b50

Andrew Kelley <andrew@ziglang.org>
2021-04-09 06:56:42
stage2: implement array access to a global array
1 parent 6d616d8
Changed files (3)
src/AstGen.zig
@@ -2349,7 +2349,7 @@ fn arrayAccess(
         ),
         else => return rvalue(gz, scope, rl, try gz.addBin(
             .elem_val,
-            try expr(gz, scope, .none, node_datas[node].lhs),
+            try expr(gz, scope, .none_or_ref, node_datas[node].lhs),
             try expr(gz, scope, .{ .ty = .usize_type }, node_datas[node].rhs),
         ), node),
     }
src/Sema.zig
@@ -1430,9 +1430,6 @@ fn zirDbgStmtNode(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerE
 }
 
 fn zirDeclRef(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
-    const tracy = trace(@src());
-    defer tracy.end();
-
     const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
     const src = inst_data.src();
     const decl = sema.owner_decl.dependencies.entries.items[inst_data.payload_index].key;
@@ -1440,9 +1437,6 @@ fn zirDeclRef(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError
 }
 
 fn zirDeclVal(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
-    const tracy = trace(@src());
-    defer tracy.end();
-
     const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
     const src = inst_data.src();
     const decl = sema.owner_decl.dependencies.entries.items[inst_data.payload_index].key;
@@ -2571,7 +2565,10 @@ fn zirElemVal(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError
 
     const bin_inst = sema.code.instructions.items(.data)[inst].bin;
     const array = try sema.resolveInst(bin_inst.lhs);
-    const array_ptr = try sema.analyzeRef(block, sema.src, array);
+    const array_ptr = if (array.ty.zigTypeTag() == .Pointer)
+        array
+    else
+        try sema.analyzeRef(block, sema.src, array);
     const elem_index = try sema.resolveInst(bin_inst.rhs);
     const result_ptr = try sema.elemPtr(block, sema.src, array_ptr, elem_index, sema.src);
     return sema.analyzeLoad(block, sema.src, result_ptr, sema.src);
@@ -2586,7 +2583,10 @@ fn zirElemValNode(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerE
     const elem_index_src: LazySrcLoc = .{ .node_offset_array_access_index = inst_data.src_node };
     const extra = sema.code.extraData(zir.Inst.Bin, inst_data.payload_index).data;
     const array = try sema.resolveInst(extra.lhs);
-    const array_ptr = try sema.analyzeRef(block, src, array);
+    const array_ptr = if (array.ty.zigTypeTag() == .Pointer)
+        array
+    else
+        try sema.analyzeRef(block, src, array);
     const elem_index = try sema.resolveInst(extra.rhs);
     const result_ptr = try sema.elemPtr(block, src, array_ptr, elem_index, elem_index_src);
     return sema.analyzeLoad(block, src, result_ptr, src);
@@ -4786,37 +4786,51 @@ fn elemPtr(
     elem_index: *Inst,
     elem_index_src: LazySrcLoc,
 ) InnerError!*Inst {
-    const elem_ty = switch (array_ptr.ty.zigTypeTag()) {
+    const array_ty = switch (array_ptr.ty.zigTypeTag()) {
         .Pointer => array_ptr.ty.elemType(),
         else => return sema.mod.fail(&block.base, array_ptr.src, "expected pointer, found '{}'", .{array_ptr.ty}),
     };
-    if (!elem_ty.isIndexable()) {
-        return sema.mod.fail(&block.base, src, "array access of non-array type '{}'", .{elem_ty});
+    if (!array_ty.isIndexable()) {
+        return sema.mod.fail(&block.base, src, "array access of non-array type '{}'", .{array_ty});
     }
-
-    if (elem_ty.isSinglePointer() and elem_ty.elemType().zigTypeTag() == .Array) {
+    if (array_ty.isSinglePointer() and array_ty.elemType().zigTypeTag() == .Array) {
         // we have to deref the ptr operand to get the actual array pointer
         const array_ptr_deref = try sema.analyzeLoad(block, src, array_ptr, 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();
-                // @intCast here because it would have been impossible to construct a value that
-                // required a larger index.
-                const elem_ptr = try array_ptr_val.elemPtr(sema.arena, @intCast(usize, index_u64));
-                const pointee_type = elem_ty.elemType().elemType();
-
-                return sema.mod.constInst(sema.arena, src, .{
-                    .ty = try Type.Tag.single_const_pointer.create(sema.arena, pointee_type),
-                    .val = elem_ptr,
-                });
-            }
-        }
+        return sema.elemPtrArray(block, src, array_ptr_deref, elem_index, elem_index_src);
+    }
+    if (array_ty.zigTypeTag() == .Array) {
+        return sema.elemPtrArray(block, src, array_ptr, elem_index, elem_index_src);
     }
 
     return sema.mod.fail(&block.base, src, "TODO implement more analyze elemptr", .{});
 }
 
+fn elemPtrArray(
+    sema: *Sema,
+    block: *Scope.Block,
+    src: LazySrcLoc,
+    array_ptr: *Inst,
+    elem_index: *Inst,
+    elem_index_src: LazySrcLoc,
+) InnerError!*Inst {
+    if (array_ptr.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();
+            // @intCast here because it would have been impossible to construct a value that
+            // required a larger index.
+            const elem_ptr = try array_ptr_val.elemPtr(sema.arena, @intCast(usize, index_u64));
+            const pointee_type = array_ptr.ty.elemType().elemType();
+
+            return sema.mod.constInst(sema.arena, src, .{
+                .ty = try Type.Tag.single_const_pointer.create(sema.arena, pointee_type),
+                .val = elem_ptr,
+            });
+        }
+    }
+    return sema.mod.fail(&block.base, src, "TODO implement more analyze elemptr for arrays", .{});
+}
+
 fn coerce(
     sema: *Sema,
     block: *Scope.Block,
test/stage2/test.zig
@@ -941,6 +941,32 @@ pub fn addCases(ctx: *TestContext) !void {
             "",
         );
 
+        // Array access to a global array.
+        case.addCompareOutput(
+            \\const hello = "hello".*;
+            \\export fn _start() noreturn {
+            \\    assert(hello[1] == 'e');
+            \\
+            \\    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;
+            \\}
+        ,
+            "",
+        );
+
         // 64bit set stack
         case.addCompareOutput(
             \\export fn _start() noreturn {