authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-08-04 23:02:13-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-08-04 23:02:13-07:00
logf58cbef1659742e57377d3f8c92a0b9b97af91ad
tree43bc60f54b5a4252df309d9c3cb5dbe3aca20297
parentd4468affb751668e156230c32b29c84684825b4f

stage2: std.mem.eql works now

* The `indexable_ptr_len` ZIR instruction now uses a `none_or_ref` ResultLoc. This prevents an unnecessary `ref` instruction from being emitted. * Sema: Fix `analyzeCall` using the incorrect ZIR object for the generic function callee. * LLVM backend: `genTypedValue` supports a `Slice` type encoded with the `decl_ref` `Value`.

5 files changed, 75 insertions(+), 47 deletions(-)

src/AstGen.zig+1-1
...@@ -5423,7 +5423,7 @@ fn forExpr(...@@ -5423,7 +5423,7 @@ fn forExpr(
5423 const tree = astgen.tree;5423 const tree = astgen.tree;
5424 const token_tags = tree.tokens.items(.tag);5424 const token_tags = tree.tokens.items(.tag);
54255425
5426 const array_ptr = try expr(parent_gz, scope, .ref, for_full.ast.cond_expr);5426 const array_ptr = try expr(parent_gz, scope, .none_or_ref, for_full.ast.cond_expr);
5427 const len = try parent_gz.addUnNode(.indexable_ptr_len, array_ptr, for_full.ast.cond_expr);5427 const len = try parent_gz.addUnNode(.indexable_ptr_len, array_ptr, for_full.ast.cond_expr);
54285428
5429 const index_ptr = blk: {5429 const index_ptr = blk: {
src/Sema.zig+40-33
...@@ -1306,38 +1306,44 @@ fn zirIndexablePtrLen(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Co...@@ -1306,38 +1306,44 @@ fn zirIndexablePtrLen(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Co
13061306
1307 const inst_data = sema.code.instructions.items(.data)[inst].un_node;1307 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
1308 const src = inst_data.src();1308 const src = inst_data.src();
1309 const array_ptr = sema.resolveInst(inst_data.operand);1309 const array = sema.resolveInst(inst_data.operand);
1310 const array_ptr_src = src;1310 const array_ty = sema.typeOf(array);
13111311
1312 const elem_ty = sema.typeOf(array_ptr).elemType();1312 if (array_ty.isSlice()) {
1313 if (elem_ty.isSlice()) {1313 return sema.analyzeSliceLen(block, src, array);
1314 const slice_inst = try sema.analyzeLoad(block, src, array_ptr, array_ptr_src);
1315 return sema.analyzeSliceLen(block, src, slice_inst);
1316 }1314 }
1317 if (!elem_ty.isIndexable()) {1315
1318 const cond_src: LazySrcLoc = .{ .node_offset_for_cond = inst_data.src_node };1316 if (array_ty.isSinglePointer()) {
1319 const msg = msg: {1317 const elem_ty = array_ty.elemType();
1320 const msg = try sema.mod.errMsg(1318 if (elem_ty.isSlice()) {
1321 &block.base,1319 const slice_inst = try sema.analyzeLoad(block, src, array, src);
1322 cond_src,1320 return sema.analyzeSliceLen(block, src, slice_inst);
1323 "type '{}' does not support indexing",1321 }
1324 .{elem_ty},1322 if (!elem_ty.isIndexable()) {
1325 );1323 const msg = msg: {
1326 errdefer msg.destroy(sema.gpa);1324 const msg = try sema.mod.errMsg(
1327 try sema.mod.errNote(1325 &block.base,
1328 &block.base,1326 src,
1329 cond_src,1327 "type '{}' does not support indexing",
1330 msg,1328 .{elem_ty},
1331 "for loop operand must be an array, slice, tuple, or vector",1329 );
1332 .{},1330 errdefer msg.destroy(sema.gpa);
1333 );1331 try sema.mod.errNote(
1334 break :msg msg;1332 &block.base,
1335 };1333 src,
1336 return sema.mod.failWithOwnedErrorMsg(&block.base, msg);1334 msg,
1335 "for loop operand must be an array, slice, tuple, or vector",
1336 .{},
1337 );
1338 break :msg msg;
1339 };
1340 return sema.mod.failWithOwnedErrorMsg(&block.base, msg);
1341 }
1342 const result_ptr = try sema.fieldPtr(block, src, array, "len", src);
1343 return sema.analyzeLoad(block, src, result_ptr, src);
1337 }1344 }
1338 const result_ptr = try sema.fieldPtr(block, src, array_ptr, "len", src);1345
1339 const result_ptr_src = array_ptr_src;1346 return sema.mod.fail(&block.base, src, "TODO implement Sema.zirIndexablePtrLen", .{});
1340 return sema.analyzeLoad(block, src, result_ptr, result_ptr_src);
1341}1347}
13421348
1343fn zirAllocExtended(1349fn zirAllocExtended(
...@@ -2520,10 +2526,11 @@ fn analyzeCall(...@@ -2520,10 +2526,11 @@ fn analyzeCall(
2520 // generic Scope only to junk it if it matches an existing instantiation.2526 // generic Scope only to junk it if it matches an existing instantiation.
2521 // TODO2527 // TODO
25222528
2523 const fn_info = sema.code.getFnInfo(module_fn.zir_body_inst);2529 const namespace = module_fn.owner_decl.namespace;
2524 const zir_tags = sema.code.instructions.items(.tag);2530 const fn_zir = namespace.file_scope.zir;
2531 const fn_info = fn_zir.getFnInfo(module_fn.zir_body_inst);
2532 const zir_tags = fn_zir.instructions.items(.tag);
2525 const new_func = new_func: {2533 const new_func = new_func: {
2526 const namespace = module_fn.owner_decl.namespace;
2527 try namespace.anon_decls.ensureUnusedCapacity(gpa, 1);2534 try namespace.anon_decls.ensureUnusedCapacity(gpa, 1);
25282535
2529 // Create a Decl for the new function.2536 // Create a Decl for the new function.
...@@ -2558,7 +2565,7 @@ fn analyzeCall(...@@ -2558,7 +2565,7 @@ fn analyzeCall(
2558 .mod = mod,2565 .mod = mod,
2559 .gpa = gpa,2566 .gpa = gpa,
2560 .arena = sema.arena,2567 .arena = sema.arena,
2561 .code = sema.code,2568 .code = fn_zir,
2562 .owner_decl = new_decl,2569 .owner_decl = new_decl,
2563 .namespace = namespace,2570 .namespace = namespace,
2564 .func = null,2571 .func = null,
src/codegen/llvm.zig+25-5
...@@ -701,11 +701,31 @@ pub const DeclGen = struct {...@@ -701,11 +701,31 @@ pub const DeclGen = struct {
701 },701 },
702 .Pointer => switch (tv.val.tag()) {702 .Pointer => switch (tv.val.tag()) {
703 .decl_ref => {703 .decl_ref => {
704 const decl = tv.val.castTag(.decl_ref).?.data;704 if (tv.ty.isSlice()) {
705 decl.alive = true;705 var buf: Type.Payload.ElemType = undefined;
706 const val = try self.resolveGlobalDecl(decl);706 const ptr_ty = tv.ty.slicePtrFieldType(&buf);
707 const llvm_type = try self.llvmType(tv.ty);707 var slice_len: Value.Payload.U64 = .{
708 return val.constBitCast(llvm_type);708 .base = .{ .tag = .int_u64 },
709 .data = tv.val.sliceLen(),
710 };
711 const fields: [2]*const llvm.Value = .{
712 try self.genTypedValue(.{
713 .ty = ptr_ty,
714 .val = tv.val,
715 }),
716 try self.genTypedValue(.{
717 .ty = Type.initTag(.usize),
718 .val = Value.initPayload(&slice_len.base),
719 }),
720 };
721 return self.context.constStruct(&fields, fields.len, .False);
722 } else {
723 const decl = tv.val.castTag(.decl_ref).?.data;
724 decl.alive = true;
725 const val = try self.resolveGlobalDecl(decl);
726 const llvm_type = try self.llvmType(tv.ty);
727 return val.constBitCast(llvm_type);
728 }
709 },729 },
710 .variable => {730 .variable => {
711 const decl = tv.val.castTag(.variable).?.data.owner_decl;731 const decl = tv.val.castTag(.variable).?.data.owner_decl;
test/behavior/basic.zig+9
...@@ -1,4 +1,5 @@...@@ -1,4 +1,5 @@
1const std = @import("std");1const std = @import("std");
2const mem = std.mem;
2const expect = std.testing.expect;3const expect = std.testing.expect;
34
4// normal comment5// normal comment
...@@ -83,3 +84,11 @@ test "unicode escape in character literal" {...@@ -83,3 +84,11 @@ test "unicode escape in character literal" {
83test "unicode character in character literal" {84test "unicode character in character literal" {
84 try expect('💩' == 128169);85 try expect('💩' == 128169);
85}86}
87
88fn first4KeysOfHomeRow() []const u8 {
89 return "aoeu";
90}
91
92test "return string from function" {
93 try expect(mem.eql(u8, first4KeysOfHomeRow(), "aoeu"));
94}
test/behavior/misc.zig-8
...@@ -5,14 +5,6 @@ const expectEqualStrings = std.testing.expectEqualStrings;...@@ -5,14 +5,6 @@ const expectEqualStrings = std.testing.expectEqualStrings;
5const mem = std.mem;5const mem = std.mem;
6const builtin = @import("builtin");6const builtin = @import("builtin");
77
8fn first4KeysOfHomeRow() []const u8 {
9 return "aoeu";
10}
11
12test "return string from function" {
13 try expect(mem.eql(u8, first4KeysOfHomeRow(), "aoeu"));
14}
15
16test "memcpy and memset intrinsics" {8test "memcpy and memset intrinsics" {
17 var foo: [20]u8 = undefined;9 var foo: [20]u8 = undefined;
18 var bar: [20]u8 = undefined;10 var bar: [20]u8 = undefined;