aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-08-04 23:02:13 -0700
committerAndrew Kelley <andrew@ziglang.org>2021-08-04 23:02:13 -0700
commitf58cbef1659742e57377d3f8c92a0b9b97af91ad (patch)
tree43bc60f54b5a4252df309d9c3cb5dbe3aca20297 /src
parentd4468affb751668e156230c32b29c84684825b4f (diff)
downloadzig-f58cbef1659742e57377d3f8c92a0b9b97af91ad.tar.gz
zig-f58cbef1659742e57377d3f8c92a0b9b97af91ad.zip
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`.
Diffstat (limited to 'src')
-rw-r--r--src/AstGen.zig2
-rw-r--r--src/Sema.zig73
-rw-r--r--src/codegen/llvm.zig30
3 files changed, 66 insertions, 39 deletions
diff --git a/src/AstGen.zig b/src/AstGen.zig
index 493e0a75f4..9886e4d809 100644
--- a/src/AstGen.zig
+++ b/src/AstGen.zig
@@ -5423,7 +5423,7 @@ fn forExpr(
const tree = astgen.tree;
const token_tags = tree.tokens.items(.tag);
- const array_ptr = try expr(parent_gz, scope, .ref, for_full.ast.cond_expr);
+ const array_ptr = try expr(parent_gz, scope, .none_or_ref, for_full.ast.cond_expr);
const len = try parent_gz.addUnNode(.indexable_ptr_len, array_ptr, for_full.ast.cond_expr);
const index_ptr = blk: {
diff --git a/src/Sema.zig b/src/Sema.zig
index 8bcdcb63c9..dff11301db 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -1306,38 +1306,44 @@ fn zirIndexablePtrLen(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Co
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
const src = inst_data.src();
- const array_ptr = sema.resolveInst(inst_data.operand);
- const array_ptr_src = src;
+ const array = sema.resolveInst(inst_data.operand);
+ const array_ty = sema.typeOf(array);
- const elem_ty = sema.typeOf(array_ptr).elemType();
- if (elem_ty.isSlice()) {
- const slice_inst = try sema.analyzeLoad(block, src, array_ptr, array_ptr_src);
- return sema.analyzeSliceLen(block, src, slice_inst);
+ if (array_ty.isSlice()) {
+ return sema.analyzeSliceLen(block, src, array);
}
- if (!elem_ty.isIndexable()) {
- const cond_src: LazySrcLoc = .{ .node_offset_for_cond = inst_data.src_node };
- const msg = msg: {
- const msg = try sema.mod.errMsg(
- &block.base,
- cond_src,
- "type '{}' does not support indexing",
- .{elem_ty},
- );
- errdefer msg.destroy(sema.gpa);
- try sema.mod.errNote(
- &block.base,
- cond_src,
- msg,
- "for loop operand must be an array, slice, tuple, or vector",
- .{},
- );
- break :msg msg;
- };
- return sema.mod.failWithOwnedErrorMsg(&block.base, msg);
+
+ if (array_ty.isSinglePointer()) {
+ const elem_ty = array_ty.elemType();
+ if (elem_ty.isSlice()) {
+ const slice_inst = try sema.analyzeLoad(block, src, array, src);
+ return sema.analyzeSliceLen(block, src, slice_inst);
+ }
+ if (!elem_ty.isIndexable()) {
+ const msg = msg: {
+ const msg = try sema.mod.errMsg(
+ &block.base,
+ src,
+ "type '{}' does not support indexing",
+ .{elem_ty},
+ );
+ errdefer msg.destroy(sema.gpa);
+ try sema.mod.errNote(
+ &block.base,
+ src,
+ msg,
+ "for loop operand must be an array, slice, tuple, or vector",
+ .{},
+ );
+ break :msg msg;
+ };
+ return sema.mod.failWithOwnedErrorMsg(&block.base, msg);
+ }
+ const result_ptr = try sema.fieldPtr(block, src, array, "len", src);
+ return sema.analyzeLoad(block, src, result_ptr, src);
}
- const result_ptr = try sema.fieldPtr(block, src, array_ptr, "len", src);
- const result_ptr_src = array_ptr_src;
- return sema.analyzeLoad(block, src, result_ptr, result_ptr_src);
+
+ return sema.mod.fail(&block.base, src, "TODO implement Sema.zirIndexablePtrLen", .{});
}
fn zirAllocExtended(
@@ -2520,10 +2526,11 @@ fn analyzeCall(
// generic Scope only to junk it if it matches an existing instantiation.
// TODO
- const fn_info = sema.code.getFnInfo(module_fn.zir_body_inst);
- const zir_tags = sema.code.instructions.items(.tag);
+ const namespace = module_fn.owner_decl.namespace;
+ const fn_zir = namespace.file_scope.zir;
+ const fn_info = fn_zir.getFnInfo(module_fn.zir_body_inst);
+ const zir_tags = fn_zir.instructions.items(.tag);
const new_func = new_func: {
- const namespace = module_fn.owner_decl.namespace;
try namespace.anon_decls.ensureUnusedCapacity(gpa, 1);
// Create a Decl for the new function.
@@ -2558,7 +2565,7 @@ fn analyzeCall(
.mod = mod,
.gpa = gpa,
.arena = sema.arena,
- .code = sema.code,
+ .code = fn_zir,
.owner_decl = new_decl,
.namespace = namespace,
.func = null,
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig
index 4a589ea66d..0e73469687 100644
--- a/src/codegen/llvm.zig
+++ b/src/codegen/llvm.zig
@@ -701,11 +701,31 @@ pub const DeclGen = struct {
},
.Pointer => switch (tv.val.tag()) {
.decl_ref => {
- const decl = tv.val.castTag(.decl_ref).?.data;
- decl.alive = true;
- const val = try self.resolveGlobalDecl(decl);
- const llvm_type = try self.llvmType(tv.ty);
- return val.constBitCast(llvm_type);
+ if (tv.ty.isSlice()) {
+ var buf: Type.Payload.ElemType = undefined;
+ const ptr_ty = tv.ty.slicePtrFieldType(&buf);
+ var slice_len: Value.Payload.U64 = .{
+ .base = .{ .tag = .int_u64 },
+ .data = tv.val.sliceLen(),
+ };
+ const fields: [2]*const llvm.Value = .{
+ try self.genTypedValue(.{
+ .ty = ptr_ty,
+ .val = tv.val,
+ }),
+ try self.genTypedValue(.{
+ .ty = Type.initTag(.usize),
+ .val = Value.initPayload(&slice_len.base),
+ }),
+ };
+ return self.context.constStruct(&fields, fields.len, .False);
+ } else {
+ const decl = tv.val.castTag(.decl_ref).?.data;
+ decl.alive = true;
+ const val = try self.resolveGlobalDecl(decl);
+ const llvm_type = try self.llvmType(tv.ty);
+ return val.constBitCast(llvm_type);
+ }
},
.variable => {
const decl = tv.val.castTag(.variable).?.data.owner_decl;