authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-01-19 00:38:53-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-01-19 00:38:53-07:00
log30a824cb9e148adb0799a0a81721160c0d474b50
treeafdfb0a3e19fb956c66ade7b190b7ca4566ba7f7
parent7e56028bc7c00b884c92e2948728cbc47e5a8a09

astgen: eliminate rlWrapPtr and all its callsites

The following AST avoids unnecessary derefs now: * error set decl * field access * array access * for loops: replace ensure_indexable and deref on the len_ptr with a special purpose ZIR instruction called indexable_ptr_len. Added an error note when for loop operand is the wrong type. I also accidentally implemented `@field`.

8 files changed, 394 insertions(+), 222 deletions(-)

src/Module.zig+163
......@@ -2357,6 +2357,11 @@ pub fn lookupDeclName(self: *Module, scope: *Scope, ident_name: []const u8) ?*De
23572357 return self.decl_table.get(name_hash);
23582358}
23592359
2360pub fn analyzeDeclVal(mod: *Module, scope: *Scope, src: usize, decl: *Decl) InnerError!*Inst {
2361 const decl_ref = try mod.analyzeDeclRef(scope, src, decl);
2362 return mod.analyzeDeref(scope, src, decl_ref, src);
2363}
2364
23602365pub fn analyzeDeclRef(self: *Module, scope: *Scope, src: usize, decl: *Decl) InnerError!*Inst {
23612366 const scope_decl = scope.ownerDecl().?;
23622367 try self.declareDeclDependency(scope_decl, decl);
......@@ -2408,6 +2413,20 @@ fn analyzeVarRef(self: *Module, scope: *Scope, src: usize, tv: TypedValue) Inner
24082413 return &inst.base;
24092414}
24102415
2416pub fn analyzeRef(mod: *Module, scope: *Scope, src: usize, operand: *Inst) InnerError!*Inst {
2417 const ptr_type = try mod.simplePtrType(scope, src, operand.ty, false, .One);
2418
2419 if (operand.value()) |val| {
2420 return mod.constInst(scope, src, .{
2421 .ty = ptr_type,
2422 .val = try Value.Tag.ref_val.create(scope.arena(), val),
2423 });
2424 }
2425
2426 const b = try mod.requireRuntimeBlock(scope, src);
2427 return mod.addUnOp(b, src, ptr_type, .ref, operand);
2428}
2429
24112430pub fn analyzeDeref(self: *Module, scope: *Scope, src: usize, ptr: *Inst, ptr_src: usize) InnerError!*Inst {
24122431 const elem_ty = switch (ptr.ty.zigTypeTag()) {
24132432 .Pointer => ptr.ty.elemType(),
......@@ -3543,3 +3562,147 @@ pub fn emitBackwardBranch(mod: *Module, block: *Scope.Block, src: usize) !void {
35433562 });
35443563 }
35453564}
3565
3566pub fn namedFieldPtr(
3567 mod: *Module,
3568 scope: *Scope,
3569 src: usize,
3570 object_ptr: *Inst,
3571 field_name: []const u8,
3572 field_name_src: usize,
3573) InnerError!*Inst {
3574 const elem_ty = switch (object_ptr.ty.zigTypeTag()) {
3575 .Pointer => object_ptr.ty.elemType(),
3576 else => return mod.fail(scope, object_ptr.src, "expected pointer, found '{}'", .{object_ptr.ty}),
3577 };
3578 switch (elem_ty.zigTypeTag()) {
3579 .Array => {
3580 if (mem.eql(u8, field_name, "len")) {
3581 return mod.constInst(scope, src, .{
3582 .ty = Type.initTag(.single_const_pointer_to_comptime_int),
3583 .val = try Value.Tag.ref_val.create(
3584 scope.arena(),
3585 try Value.Tag.int_u64.create(scope.arena(), elem_ty.arrayLen()),
3586 ),
3587 });
3588 } else {
3589 return mod.fail(
3590 scope,
3591 field_name_src,
3592 "no member named '{s}' in '{}'",
3593 .{ field_name, elem_ty },
3594 );
3595 }
3596 },
3597 .Pointer => {
3598 const ptr_child = elem_ty.elemType();
3599 switch (ptr_child.zigTypeTag()) {
3600 .Array => {
3601 if (mem.eql(u8, field_name, "len")) {
3602 return mod.constInst(scope, src, .{
3603 .ty = Type.initTag(.single_const_pointer_to_comptime_int),
3604 .val = try Value.Tag.ref_val.create(
3605 scope.arena(),
3606 try Value.Tag.int_u64.create(scope.arena(), ptr_child.arrayLen()),
3607 ),
3608 });
3609 } else {
3610 return mod.fail(
3611 scope,
3612 field_name_src,
3613 "no member named '{s}' in '{}'",
3614 .{ field_name, elem_ty },
3615 );
3616 }
3617 },
3618 else => {},
3619 }
3620 },
3621 .Type => {
3622 _ = try mod.resolveConstValue(scope, object_ptr);
3623 const result = try mod.analyzeDeref(scope, src, object_ptr, object_ptr.src);
3624 const val = result.value().?;
3625 const child_type = try val.toType(scope.arena());
3626 switch (child_type.zigTypeTag()) {
3627 .ErrorSet => {
3628 // TODO resolve inferred error sets
3629 const entry = if (val.castTag(.error_set)) |payload|
3630 (payload.data.fields.getEntry(field_name) orelse
3631 return mod.fail(scope, src, "no error named '{s}' in '{}'", .{ field_name, child_type })).*
3632 else
3633 try mod.getErrorValue(field_name);
3634
3635 const result_type = if (child_type.tag() == .anyerror)
3636 try Type.Tag.error_set_single.create(scope.arena(), entry.key)
3637 else
3638 child_type;
3639
3640 return mod.constInst(scope, src, .{
3641 .ty = try mod.simplePtrType(scope, src, result_type, false, .One),
3642 .val = try Value.Tag.ref_val.create(
3643 scope.arena(),
3644 try Value.Tag.@"error".create(scope.arena(), .{
3645 .name = entry.key,
3646 .value = entry.value,
3647 }),
3648 ),
3649 });
3650 },
3651 .Struct => {
3652 const container_scope = child_type.getContainerScope();
3653 if (mod.lookupDeclName(&container_scope.base, field_name)) |decl| {
3654 // TODO if !decl.is_pub and inDifferentFiles() "{} is private"
3655 return mod.analyzeDeclRef(scope, src, decl);
3656 }
3657
3658 if (container_scope.file_scope == mod.root_scope) {
3659 return mod.fail(scope, src, "root source file has no member called '{s}'", .{field_name});
3660 } else {
3661 return mod.fail(scope, src, "container '{}' has no member called '{s}'", .{ child_type, field_name });
3662 }
3663 },
3664 else => return mod.fail(scope, src, "type '{}' does not support field access", .{child_type}),
3665 }
3666 },
3667 else => {},
3668 }
3669 return mod.fail(scope, src, "type '{}' does not support field access", .{elem_ty});
3670}
3671
3672pub fn elemPtr(
3673 mod: *Module,
3674 scope: *Scope,
3675 src: usize,
3676 array_ptr: *Inst,
3677 elem_index: *Inst,
3678) InnerError!*Inst {
3679 const elem_ty = switch (array_ptr.ty.zigTypeTag()) {
3680 .Pointer => array_ptr.ty.elemType(),
3681 else => return mod.fail(scope, array_ptr.src, "expected pointer, found '{}'", .{array_ptr.ty}),
3682 };
3683 if (!elem_ty.isIndexable()) {
3684 return mod.fail(scope, src, "array access of non-array type '{}'", .{elem_ty});
3685 }
3686
3687 if (elem_ty.isSinglePointer() and elem_ty.elemType().zigTypeTag() == .Array) {
3688 // we have to deref the ptr operand to get the actual array pointer
3689 const array_ptr_deref = try mod.analyzeDeref(scope, src, array_ptr, array_ptr.src);
3690 if (array_ptr_deref.value()) |array_ptr_val| {
3691 if (elem_index.value()) |index_val| {
3692 // Both array pointer and index are compile-time known.
3693 const index_u64 = index_val.toUnsignedInt();
3694 // @intCast here because it would have been impossible to construct a value that
3695 // required a larger index.
3696 const elem_ptr = try array_ptr_val.elemPtr(scope.arena(), @intCast(usize, index_u64));
3697 const pointee_type = elem_ty.elemType().elemType();
3698
3699 return mod.constInst(scope, src, .{
3700 .ty = try Type.Tag.single_const_pointer.create(scope.arena(), pointee_type),
3701 .val = elem_ptr,
3702 });
3703 }
3704 }
3705 }
3706
3707 return mod.fail(scope, src, "TODO implement more analyze elemptr", .{});
3708}
src/astgen.zig+85-30
......@@ -278,7 +278,7 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr
278278 .ErrorUnion => return rlWrap(mod, scope, rl, try typeInixOp(mod, scope, node.castTag(.ErrorUnion).?, .error_union_type)),
279279 .MergeErrorSets => return rlWrap(mod, scope, rl, try typeInixOp(mod, scope, node.castTag(.MergeErrorSets).?, .merge_error_sets)),
280280 .AnyFrameType => return rlWrap(mod, scope, rl, try anyFrameType(mod, scope, node.castTag(.AnyFrameType).?)),
281 .ErrorSetDecl => return errorSetDecl(mod, scope, rl, node.castTag(.ErrorSetDecl).?),
281 .ErrorSetDecl => return rlWrap(mod, scope, rl, try errorSetDecl(mod, scope, node.castTag(.ErrorSetDecl).?)),
282282 .ErrorType => return rlWrap(mod, scope, rl, try errorType(mod, scope, node.castTag(.ErrorType).?)),
283283 .For => return forExpr(mod, scope, rl, node.castTag(.For).?),
284284 .ArrayAccess => return arrayAccess(mod, scope, rl, node.castTag(.ArrayAccess).?),
......@@ -1107,7 +1107,7 @@ fn containerDecl(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Con
11071107 }
11081108}
11091109
1110fn errorSetDecl(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.ErrorSetDecl) InnerError!*zir.Inst {
1110fn errorSetDecl(mod: *Module, scope: *Scope, node: *ast.Node.ErrorSetDecl) InnerError!*zir.Inst {
11111111 const tree = scope.tree();
11121112 const src = tree.token_locs[node.error_token].start;
11131113 const decls = node.decls();
......@@ -1118,9 +1118,7 @@ fn errorSetDecl(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Erro
11181118 fields[i] = try mod.identifierTokenString(scope, tag.name_token);
11191119 }
11201120
1121 // analyzing the error set results in a decl ref, so we might need to dereference it
1122 // TODO remove all callsites to rlWrapPtr
1123 return rlWrapPtr(mod, scope, rl, try addZIRInst(mod, scope, src, zir.Inst.ErrorSet, .{ .fields = fields }, .{}));
1121 return addZIRInst(mod, scope, src, zir.Inst.ErrorSet, .{ .fields = fields }, .{});
11241122}
11251123
11261124fn errorType(mod: *Module, scope: *Scope, node: *ast.Node.OneToken) InnerError!*zir.Inst {
......@@ -1299,35 +1297,72 @@ fn tokenIdentEql(mod: *Module, scope: *Scope, token1: ast.TokenIndex, token2: as
12991297 return mem.eql(u8, ident_name_1, ident_name_2);
13001298}
13011299
1302pub fn identifierStringInst(mod: *Module, scope: *Scope, node: *ast.Node.OneToken) InnerError!*zir.Inst {
1300pub fn field(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.SimpleInfixOp) InnerError!*zir.Inst {
13031301 const tree = scope.tree();
1304 const src = tree.token_locs[node.token].start;
1305
1306 const ident_name = try mod.identifierTokenString(scope, node.token);
1307
1308 return addZIRInst(mod, scope, src, zir.Inst.Str, .{ .bytes = ident_name }, .{});
1302 const src = tree.token_locs[node.op_token].start;
1303 // TODO custom AST node for field access so that we don't have to go through a node cast here
1304 const field_name = try mod.identifierTokenString(scope, node.rhs.castTag(.Identifier).?.token);
1305 if (rl == .ref) {
1306 return addZirInstTag(mod, scope, src, .field_ptr, .{
1307 .object = try expr(mod, scope, .ref, node.lhs),
1308 .field_name = field_name,
1309 });
1310 }
1311 return rlWrap(mod, scope, rl, try addZirInstTag(mod, scope, src, .field_val, .{
1312 .object = try expr(mod, scope, .none, node.lhs),
1313 .field_name = field_name,
1314 }));
13091315}
13101316
1311fn field(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.SimpleInfixOp) InnerError!*zir.Inst {
1317fn namedField(
1318 mod: *Module,
1319 scope: *Scope,
1320 rl: ResultLoc,
1321 call: *ast.Node.BuiltinCall,
1322) InnerError!*zir.Inst {
1323 try ensureBuiltinParamCount(mod, scope, call, 2);
1324
13121325 const tree = scope.tree();
1313 const src = tree.token_locs[node.op_token].start;
1326 const src = tree.token_locs[call.builtin_token].start;
1327 const params = call.params();
13141328
1315 const lhs = try expr(mod, scope, .ref, node.lhs);
1316 const field_name = try identifierStringInst(mod, scope, node.rhs.castTag(.Identifier).?);
1329 const string_type = try addZIRInstConst(mod, scope, src, .{
1330 .ty = Type.initTag(.type),
1331 .val = Value.initTag(.const_slice_u8_type),
1332 });
1333 const string_rl: ResultLoc = .{ .ty = string_type };
13171334
1318 // TODO remove all callsites to rlWrapPtr
1319 return rlWrapPtr(mod, scope, rl, try addZIRInst(mod, scope, src, zir.Inst.FieldPtr, .{ .object_ptr = lhs, .field_name = field_name }, .{}));
1335 if (rl == .ref) {
1336 return addZirInstTag(mod, scope, src, .field_ptr_named, .{
1337 .object = try expr(mod, scope, .ref, params[0]),
1338 .field_name = try comptimeExpr(mod, scope, string_rl, params[1]),
1339 });
1340 }
1341 return rlWrap(mod, scope, rl, try addZirInstTag(mod, scope, src, .field_val_named, .{
1342 .object = try expr(mod, scope, .none, params[0]),
1343 .field_name = try comptimeExpr(mod, scope, string_rl, params[1]),
1344 }));
13201345}
13211346
13221347fn arrayAccess(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.ArrayAccess) InnerError!*zir.Inst {
13231348 const tree = scope.tree();
13241349 const src = tree.token_locs[node.rtoken].start;
1350 const usize_type = try addZIRInstConst(mod, scope, src, .{
1351 .ty = Type.initTag(.type),
1352 .val = Value.initTag(.usize_type),
1353 });
1354 const index_rl: ResultLoc = .{ .ty = usize_type };
13251355
1326 const array_ptr = try expr(mod, scope, .ref, node.lhs);
1327 const index = try expr(mod, scope, .none, node.index_expr);
1328
1329 // TODO remove all callsites to rlWrapPtr
1330 return rlWrapPtr(mod, scope, rl, try addZIRInst(mod, scope, src, zir.Inst.ElemPtr, .{ .array_ptr = array_ptr, .index = index }, .{}));
1356 if (rl == .ref) {
1357 return addZirInstTag(mod, scope, src, .elem_ptr, .{
1358 .array = try expr(mod, scope, .ref, node.lhs),
1359 .index = try expr(mod, scope, index_rl, node.index_expr),
1360 });
1361 }
1362 return rlWrap(mod, scope, rl, try addZirInstTag(mod, scope, src, .elem_val, .{
1363 .array = try expr(mod, scope, .none, node.lhs),
1364 .index = try expr(mod, scope, index_rl, node.index_expr),
1365 }));
13311366}
13321367
13331368fn sliceExpr(mod: *Module, scope: *Scope, node: *ast.Node.Slice) InnerError!*zir.Inst {
......@@ -1819,12 +1854,8 @@ fn forExpr(
18191854 break :blk index_ptr;
18201855 };
18211856 const array_ptr = try expr(mod, &for_scope.base, .ref, for_node.array_expr);
1822 _ = try addZIRUnOp(mod, &for_scope.base, for_node.array_expr.firstToken(), .ensure_indexable, array_ptr);
18231857 const cond_src = tree.token_locs[for_node.array_expr.firstToken()].start;
1824 const len_ptr = try addZIRInst(mod, &for_scope.base, cond_src, zir.Inst.FieldPtr, .{
1825 .object_ptr = array_ptr,
1826 .field_name = try addZIRInst(mod, &for_scope.base, cond_src, zir.Inst.Str, .{ .bytes = "len" }, .{}),
1827 }, .{});
1858 const len = try addZIRUnOp(mod, &for_scope.base, cond_src, .indexable_ptr_len, array_ptr);
18281859
18291860 var loop_scope: Scope.GenZIR = .{
18301861 .parent = &for_scope.base,
......@@ -1845,7 +1876,6 @@ fn forExpr(
18451876
18461877 // check condition i < array_expr.len
18471878 const index = try addZIRUnOp(mod, &cond_scope.base, cond_src, .deref, index_ptr);
1848 const len = try addZIRUnOp(mod, &cond_scope.base, cond_src, .deref, len_ptr);
18491879 const cond = try addZIRBinOp(mod, &cond_scope.base, cond_src, .cmp_lt, index, len);
18501880
18511881 const condbr = try addZIRInstSpecial(mod, &cond_scope.base, for_src, zir.Inst.CondBr, .{
......@@ -2328,8 +2358,9 @@ fn identifier(mod: *Module, scope: *Scope, rl: ResultLoc, ident: *ast.Node.OneTo
23282358 .local_ptr => {
23292359 const local_ptr = s.cast(Scope.LocalPtr).?;
23302360 if (mem.eql(u8, local_ptr.name, ident_name)) {
2331 // TODO remove all callsites to rlWrapPtr
2332 return rlWrapPtr(mod, scope, rl, local_ptr.ptr);
2361 if (rl == .ref) return local_ptr.ptr;
2362 const loaded = try addZIRUnOp(mod, scope, src, .deref, local_ptr.ptr);
2363 return rlWrap(mod, scope, rl, loaded);
23332364 }
23342365 s = local_ptr.parent;
23352366 },
......@@ -2747,6 +2778,8 @@ fn builtinCall(mod: *Module, scope: *Scope, rl: ResultLoc, call: *ast.Node.Built
27472778 return setEvalBranchQuota(mod, scope, call);
27482779 } else if (mem.eql(u8, builtin_name, "@compileLog")) {
27492780 return compileLog(mod, scope, call);
2781 } else if (mem.eql(u8, builtin_name, "@field")) {
2782 return namedField(mod, scope, rl, call);
27502783 } else {
27512784 return mod.failTok(scope, call.builtin_token, "invalid builtin function: '{s}'", .{builtin_name});
27522785 }
......@@ -3119,6 +3152,28 @@ fn rlWrapPtr(mod: *Module, scope: *Scope, rl: ResultLoc, ptr: *zir.Inst) InnerEr
31193152 return rlWrap(mod, scope, rl, try addZIRUnOp(mod, scope, ptr.src, .deref, ptr));
31203153}
31213154
3155pub fn addZirInstTag(
3156 mod: *Module,
3157 scope: *Scope,
3158 src: usize,
3159 comptime tag: zir.Inst.Tag,
3160 positionals: std.meta.fieldInfo(tag.Type(), .positionals).field_type,
3161) !*zir.Inst {
3162 const gen_zir = scope.getGenZIR();
3163 try gen_zir.instructions.ensureCapacity(mod.gpa, gen_zir.instructions.items.len + 1);
3164 const inst = try gen_zir.arena.create(tag.Type());
3165 inst.* = .{
3166 .base = .{
3167 .tag = tag,
3168 .src = src,
3169 },
3170 .positionals = positionals,
3171 .kw_args = .{},
3172 };
3173 gen_zir.instructions.appendAssumeCapacity(&inst.base);
3174 return &inst.base;
3175}
3176
31223177pub fn addZIRInstSpecial(
31233178 mod: *Module,
31243179 scope: *Scope,
src/zir.zig+43-17
......@@ -47,6 +47,10 @@ pub const Inst = struct {
4747 array_type,
4848 /// Create an array type with sentinel
4949 array_type_sentinel,
50 /// Given a pointer to an indexable object, returns the len property. This is
51 /// used by for loops. This instruction also emits a for-loop specific instruction
52 /// if the indexable object is not indexable.
53 indexable_ptr_len,
5054 /// Function parameter value. These must be first in a function's main block,
5155 /// in respective order with the parameters.
5256 arg,
......@@ -142,13 +146,13 @@ pub const Inst = struct {
142146 div,
143147 /// Given a pointer to an array, slice, or pointer, returns a pointer to the element at
144148 /// the provided index.
145 elemptr,
149 elem_ptr,
150 /// Given an array, slice, or pointer, returns the element at the provided index.
151 elem_val,
146152 /// Emits a compile error if the operand is not `void`.
147153 ensure_result_used,
148154 /// Emits a compile error if an error is ignored.
149155 ensure_result_non_error,
150 /// Emits a compile error if operand cannot be indexed.
151 ensure_indexable,
152156 /// Create a `E!T` type.
153157 error_union_type,
154158 /// Create an error set.
......@@ -156,8 +160,17 @@ pub const Inst = struct {
156160 /// Export the provided Decl as the provided name in the compilation's output object file.
157161 @"export",
158162 /// Given a pointer to a struct or object that contains virtual fields, returns a pointer
159 /// to the named field.
160 fieldptr,
163 /// to the named field. The field name is a []const u8. Used by a.b syntax.
164 field_ptr,
165 /// Given a struct or object that contains virtual fields, returns the named field.
166 /// The field name is a []const u8. Used by a.b syntax.
167 field_val,
168 /// Given a pointer to a struct or object that contains virtual fields, returns a pointer
169 /// to the named field. The field name is a comptime instruction. Used by @field.
170 field_ptr_named,
171 /// Given a struct or object that contains virtual fields, returns the named field.
172 /// The field name is a comptime instruction. Used by @field.
173 field_val_named,
161174 /// Convert a larger float type to any other float type, possibly causing a loss of precision.
162175 floatcast,
163176 /// Declare a function body.
......@@ -361,7 +374,6 @@ pub const Inst = struct {
361374 .ptrtoint,
362375 .ensure_result_used,
363376 .ensure_result_non_error,
364 .ensure_indexable,
365377 .bitcast_result_ptr,
366378 .ref,
367379 .bitcast_ref,
......@@ -391,6 +403,7 @@ pub const Inst = struct {
391403 .bitnot,
392404 .import,
393405 .set_eval_branch_quota,
406 .indexable_ptr_len,
394407 => UnOp,
395408
396409 .add,
......@@ -452,14 +465,15 @@ pub const Inst = struct {
452465 .str => Str,
453466 .int => Int,
454467 .inttype => IntType,
455 .fieldptr => FieldPtr,
468 .field_ptr, .field_val => Field,
469 .field_ptr_named, .field_val_named => FieldNamed,
456470 .@"asm" => Asm,
457471 .@"fn" => Fn,
458472 .@"export" => Export,
459473 .param_type => ParamType,
460474 .primitive => Primitive,
461475 .fntype => FnType,
462 .elemptr => ElemPtr,
476 .elem_ptr, .elem_val => Elem,
463477 .condbr => CondBr,
464478 .ptr_type => PtrType,
465479 .enum_literal => EnumLiteral,
......@@ -490,6 +504,7 @@ pub const Inst = struct {
490504 .array_mul,
491505 .array_type,
492506 .array_type_sentinel,
507 .indexable_ptr_len,
493508 .arg,
494509 .as,
495510 .@"asm",
......@@ -523,13 +538,16 @@ pub const Inst = struct {
523538 .declval,
524539 .deref,
525540 .div,
526 .elemptr,
541 .elem_ptr,
542 .elem_val,
527543 .ensure_result_used,
528544 .ensure_result_non_error,
529 .ensure_indexable,
530545 .@"export",
531546 .floatcast,
532 .fieldptr,
547 .field_ptr,
548 .field_val,
549 .field_ptr_named,
550 .field_val_named,
533551 .@"fn",
534552 .fntype,
535553 .int,
......@@ -823,12 +841,21 @@ pub const Inst = struct {
823841 kw_args: struct {},
824842 };
825843
826 pub const FieldPtr = struct {
827 pub const base_tag = Tag.fieldptr;
844 pub const Field = struct {
828845 base: Inst,
829846
830847 positionals: struct {
831 object_ptr: *Inst,
848 object: *Inst,
849 field_name: []const u8,
850 },
851 kw_args: struct {},
852 };
853
854 pub const FieldNamed = struct {
855 base: Inst,
856
857 positionals: struct {
858 object: *Inst,
832859 field_name: *Inst,
833860 },
834861 kw_args: struct {},
......@@ -1000,12 +1027,11 @@ pub const Inst = struct {
10001027 };
10011028 };
10021029
1003 pub const ElemPtr = struct {
1004 pub const base_tag = Tag.elemptr;
1030 pub const Elem = struct {
10051031 base: Inst,
10061032
10071033 positionals: struct {
1008 array_ptr: *Inst,
1034 array: *Inst,
10091035 index: *Inst,
10101036 },
10111037 kw_args: struct {},
src/zir_sema.zig+99-171
......@@ -43,8 +43,8 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!
4343 .inferred_alloc_mut,
4444 ),
4545 .arg => return analyzeInstArg(mod, scope, old_inst.castTag(.arg).?),
46 .bitcast_ref => return analyzeInstBitCastRef(mod, scope, old_inst.castTag(.bitcast_ref).?),
47 .bitcast_result_ptr => return analyzeInstBitCastResultPtr(mod, scope, old_inst.castTag(.bitcast_result_ptr).?),
46 .bitcast_ref => return bitCastRef(mod, scope, old_inst.castTag(.bitcast_ref).?),
47 .bitcast_result_ptr => return bitCastResultPtr(mod, scope, old_inst.castTag(.bitcast_result_ptr).?),
4848 .block => return analyzeInstBlock(mod, scope, old_inst.castTag(.block).?, false),
4949 .block_comptime => return analyzeInstBlock(mod, scope, old_inst.castTag(.block_comptime).?, true),
5050 .block_flat => return analyzeInstBlockFlat(mod, scope, old_inst.castTag(.block_flat).?, false),
......@@ -52,7 +52,7 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!
5252 .@"break" => return analyzeInstBreak(mod, scope, old_inst.castTag(.@"break").?),
5353 .breakpoint => return analyzeInstBreakpoint(mod, scope, old_inst.castTag(.breakpoint).?),
5454 .breakvoid => return analyzeInstBreakVoid(mod, scope, old_inst.castTag(.breakvoid).?),
55 .call => return analyzeInstCall(mod, scope, old_inst.castTag(.call).?),
55 .call => return call(mod, scope, old_inst.castTag(.call).?),
5656 .coerce_result_block_ptr => return analyzeInstCoerceResultBlockPtr(mod, scope, old_inst.castTag(.coerce_result_block_ptr).?),
5757 .coerce_result_ptr => return analyzeInstCoerceResultPtr(mod, scope, old_inst.castTag(.coerce_result_ptr).?),
5858 .coerce_to_ptr_elem => return analyzeInstCoerceToPtrElem(mod, scope, old_inst.castTag(.coerce_to_ptr_elem).?),
......@@ -60,13 +60,13 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!
6060 .compilelog => return analyzeInstCompileLog(mod, scope, old_inst.castTag(.compilelog).?),
6161 .@"const" => return analyzeInstConst(mod, scope, old_inst.castTag(.@"const").?),
6262 .dbg_stmt => return analyzeInstDbgStmt(mod, scope, old_inst.castTag(.dbg_stmt).?),
63 .declref => return analyzeInstDeclRef(mod, scope, old_inst.castTag(.declref).?),
63 .declref => return declRef(mod, scope, old_inst.castTag(.declref).?),
6464 .declref_str => return analyzeInstDeclRefStr(mod, scope, old_inst.castTag(.declref_str).?),
65 .declval => return analyzeInstDeclVal(mod, scope, old_inst.castTag(.declval).?),
65 .declval => return declVal(mod, scope, old_inst.castTag(.declval).?),
6666 .ensure_result_used => return analyzeInstEnsureResultUsed(mod, scope, old_inst.castTag(.ensure_result_used).?),
6767 .ensure_result_non_error => return analyzeInstEnsureResultNonError(mod, scope, old_inst.castTag(.ensure_result_non_error).?),
68 .ensure_indexable => return analyzeInstEnsureIndexable(mod, scope, old_inst.castTag(.ensure_indexable).?),
69 .ref => return analyzeInstRef(mod, scope, old_inst.castTag(.ref).?),
68 .indexable_ptr_len => return indexablePtrLen(mod, scope, old_inst.castTag(.indexable_ptr_len).?),
69 .ref => return ref(mod, scope, old_inst.castTag(.ref).?),
7070 .resolve_inferred_alloc => return analyzeInstResolveInferredAlloc(mod, scope, old_inst.castTag(.resolve_inferred_alloc).?),
7171 .ret_ptr => return analyzeInstRetPtr(mod, scope, old_inst.castTag(.ret_ptr).?),
7272 .ret_type => return analyzeInstRetType(mod, scope, old_inst.castTag(.ret_type).?),
......@@ -88,7 +88,10 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!
8888 .loop => return analyzeInstLoop(mod, scope, old_inst.castTag(.loop).?),
8989 .param_type => return analyzeInstParamType(mod, scope, old_inst.castTag(.param_type).?),
9090 .ptrtoint => return analyzeInstPtrToInt(mod, scope, old_inst.castTag(.ptrtoint).?),
91 .fieldptr => return analyzeInstFieldPtr(mod, scope, old_inst.castTag(.fieldptr).?),
91 .field_ptr => return fieldPtr(mod, scope, old_inst.castTag(.field_ptr).?),
92 .field_val => return fieldVal(mod, scope, old_inst.castTag(.field_val).?),
93 .field_ptr_named => return fieldPtrNamed(mod, scope, old_inst.castTag(.field_ptr_named).?),
94 .field_val_named => return fieldValNamed(mod, scope, old_inst.castTag(.field_val_named).?),
9295 .deref => return analyzeInstDeref(mod, scope, old_inst.castTag(.deref).?),
9396 .as => return analyzeInstAs(mod, scope, old_inst.castTag(.as).?),
9497 .@"asm" => return analyzeInstAsm(mod, scope, old_inst.castTag(.@"asm").?),
......@@ -103,7 +106,8 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!
103106 .intcast => return analyzeInstIntCast(mod, scope, old_inst.castTag(.intcast).?),
104107 .bitcast => return analyzeInstBitCast(mod, scope, old_inst.castTag(.bitcast).?),
105108 .floatcast => return analyzeInstFloatCast(mod, scope, old_inst.castTag(.floatcast).?),
106 .elemptr => return analyzeInstElemPtr(mod, scope, old_inst.castTag(.elemptr).?),
109 .elem_ptr => return elemPtr(mod, scope, old_inst.castTag(.elem_ptr).?),
110 .elem_val => return elemVal(mod, scope, old_inst.castTag(.elem_val).?),
107111 .add => return analyzeInstArithmetic(mod, scope, old_inst.castTag(.add).?),
108112 .addwrap => return analyzeInstArithmetic(mod, scope, old_inst.castTag(.addwrap).?),
109113 .sub => return analyzeInstArithmetic(mod, scope, old_inst.castTag(.sub).?),
......@@ -281,16 +285,16 @@ fn analyzeInstCoerceResultBlockPtr(
281285 return mod.fail(scope, inst.base.src, "TODO implement analyzeInstCoerceResultBlockPtr", .{});
282286}
283287
284fn analyzeInstBitCastRef(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {
288fn bitCastRef(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {
285289 const tracy = trace(@src());
286290 defer tracy.end();
287 return mod.fail(scope, inst.base.src, "TODO implement analyzeInstBitCastRef", .{});
291 return mod.fail(scope, inst.base.src, "TODO implement zir_sema.bitCastRef", .{});
288292}
289293
290fn analyzeInstBitCastResultPtr(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {
294fn bitCastResultPtr(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {
291295 const tracy = trace(@src());
292296 defer tracy.end();
293 return mod.fail(scope, inst.base.src, "TODO implement analyzeInstBitCastResultPtr", .{});
297 return mod.fail(scope, inst.base.src, "TODO implement zir_sema.bitCastResultPtr", .{});
294298}
295299
296300fn analyzeInstCoerceResultPtr(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst {
......@@ -318,21 +322,12 @@ fn analyzeInstRetPtr(mod: *Module, scope: *Scope, inst: *zir.Inst.NoOp) InnerErr
318322 return mod.addNoOp(b, inst.base.src, ptr_type, .alloc);
319323}
320324
321fn analyzeInstRef(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {
325fn ref(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {
322326 const tracy = trace(@src());
323327 defer tracy.end();
324 const operand = try resolveInst(mod, scope, inst.positionals.operand);
325 const ptr_type = try mod.simplePtrType(scope, inst.base.src, operand.ty, false, .One);
326
327 if (operand.value()) |val| {
328 return mod.constInst(scope, inst.base.src, .{
329 .ty = ptr_type,
330 .val = try Value.Tag.ref_val.create(scope.arena(), val),
331 });
332 }
333328
334 const b = try mod.requireRuntimeBlock(scope, inst.base.src);
335 return mod.addUnOp(b, inst.base.src, ptr_type, .ref, operand);
329 const operand = try resolveInst(mod, scope, inst.positionals.operand);
330 return mod.analyzeRef(scope, inst.base.src, operand);
336331}
337332
338333fn analyzeInstRetType(mod: *Module, scope: *Scope, inst: *zir.Inst.NoOp) InnerError!*Inst {
......@@ -364,19 +359,34 @@ fn analyzeInstEnsureResultNonError(mod: *Module, scope: *Scope, inst: *zir.Inst.
364359 }
365360}
366361
367fn analyzeInstEnsureIndexable(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {
362fn indexablePtrLen(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {
368363 const tracy = trace(@src());
369364 defer tracy.end();
370 const operand = try resolveInst(mod, scope, inst.positionals.operand);
371 const elem_ty = operand.ty.elemType();
372 if (elem_ty.isIndexable()) {
373 return mod.constVoid(scope, operand.src);
374 } else {
375 // TODO error notes
376 // error: type '{}' does not support indexing
377 // note: for loop operand must be an array, a slice or a tuple
378 return mod.fail(scope, operand.src, "for loop operand must be an array, a slice or a tuple", .{});
365
366 const array_ptr = try resolveInst(mod, scope, inst.positionals.operand);
367 const elem_ty = array_ptr.ty.elemType();
368 if (!elem_ty.isIndexable()) {
369 const msg = msg: {
370 const msg = try mod.errMsg(
371 scope,
372 inst.base.src,
373 "type '{}' does not support indexing",
374 .{elem_ty},
375 );
376 errdefer msg.destroy(mod.gpa);
377 try mod.errNote(
378 scope,
379 inst.base.src,
380 msg,
381 "for loop operand must be an array, slice, tuple, or vector",
382 .{},
383 );
384 break :msg msg;
385 };
386 return mod.failWithOwnedErrorMsg(scope, msg);
379387 }
388 const result_ptr = try mod.namedFieldPtr(scope, inst.base.src, array_ptr, "len", inst.base.src);
389 return mod.analyzeDeref(scope, inst.base.src, result_ptr, result_ptr.src);
380390}
381391
382392fn analyzeInstAlloc(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst {
......@@ -826,21 +836,19 @@ fn analyzeInstDeclRefStr(mod: *Module, scope: *Scope, inst: *zir.Inst.DeclRefStr
826836 return mod.analyzeDeclRefByName(scope, inst.base.src, decl_name);
827837}
828838
829fn analyzeInstDeclRef(mod: *Module, scope: *Scope, inst: *zir.Inst.DeclRef) InnerError!*Inst {
839fn declRef(mod: *Module, scope: *Scope, inst: *zir.Inst.DeclRef) InnerError!*Inst {
830840 const tracy = trace(@src());
831841 defer tracy.end();
832842 return mod.analyzeDeclRef(scope, inst.base.src, inst.positionals.decl);
833843}
834844
835fn analyzeInstDeclVal(mod: *Module, scope: *Scope, inst: *zir.Inst.DeclVal) InnerError!*Inst {
845fn declVal(mod: *Module, scope: *Scope, inst: *zir.Inst.DeclVal) InnerError!*Inst {
836846 const tracy = trace(@src());
837847 defer tracy.end();
838 const decl_ref = try mod.analyzeDeclRef(scope, inst.base.src, inst.positionals.decl);
839 // TODO look into avoiding the call to analyzeDeref here
840 return mod.analyzeDeref(scope, inst.base.src, decl_ref, inst.base.src);
848 return mod.analyzeDeclVal(scope, inst.base.src, inst.positionals.decl);
841849}
842850
843fn analyzeInstCall(mod: *Module, scope: *Scope, inst: *zir.Inst.Call) InnerError!*Inst {
851fn call(mod: *Module, scope: *Scope, inst: *zir.Inst.Call) InnerError!*Inst {
844852 const tracy = trace(@src());
845853 defer tracy.end();
846854
......@@ -1093,7 +1101,7 @@ fn analyzeInstErrorSet(mod: *Module, scope: *Scope, inst: *zir.Inst.ErrorSet) In
10931101 .val = Value.initPayload(&payload.base),
10941102 });
10951103 payload.data.decl = new_decl;
1096 return mod.analyzeDeclRef(scope, inst.base.src, new_decl);
1104 return mod.analyzeDeclVal(scope, inst.base.src, new_decl);
10971105}
10981106
10991107fn analyzeInstMergeErrorSets(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst {
......@@ -1293,108 +1301,46 @@ fn analyzeInstPtrToInt(mod: *Module, scope: *Scope, ptrtoint: *zir.Inst.UnOp) In
12931301 return mod.addUnOp(b, ptrtoint.base.src, ty, .ptrtoint, ptr);
12941302}
12951303
1296fn analyzeInstFieldPtr(mod: *Module, scope: *Scope, fieldptr: *zir.Inst.FieldPtr) InnerError!*Inst {
1304fn fieldVal(mod: *Module, scope: *Scope, inst: *zir.Inst.Field) InnerError!*Inst {
12971305 const tracy = trace(@src());
12981306 defer tracy.end();
1299 const object_ptr = try resolveInst(mod, scope, fieldptr.positionals.object_ptr);
1300 const field_name = try resolveConstString(mod, scope, fieldptr.positionals.field_name);
13011307
1302 const elem_ty = switch (object_ptr.ty.zigTypeTag()) {
1303 .Pointer => object_ptr.ty.elemType(),
1304 else => return mod.fail(scope, fieldptr.positionals.object_ptr.src, "expected pointer, found '{}'", .{object_ptr.ty}),
1305 };
1306 switch (elem_ty.zigTypeTag()) {
1307 .Array => {
1308 if (mem.eql(u8, field_name, "len")) {
1309 return mod.constInst(scope, fieldptr.base.src, .{
1310 .ty = Type.initTag(.single_const_pointer_to_comptime_int),
1311 .val = try Value.Tag.ref_val.create(
1312 scope.arena(),
1313 try Value.Tag.int_u64.create(scope.arena(), elem_ty.arrayLen()),
1314 ),
1315 });
1316 } else {
1317 return mod.fail(
1318 scope,
1319 fieldptr.positionals.field_name.src,
1320 "no member named '{s}' in '{}'",
1321 .{ field_name, elem_ty },
1322 );
1323 }
1324 },
1325 .Pointer => {
1326 const ptr_child = elem_ty.elemType();
1327 switch (ptr_child.zigTypeTag()) {
1328 .Array => {
1329 if (mem.eql(u8, field_name, "len")) {
1330 return mod.constInst(scope, fieldptr.base.src, .{
1331 .ty = Type.initTag(.single_const_pointer_to_comptime_int),
1332 .val = try Value.Tag.ref_val.create(
1333 scope.arena(),
1334 try Value.Tag.int_u64.create(scope.arena(), ptr_child.arrayLen()),
1335 ),
1336 });
1337 } else {
1338 return mod.fail(
1339 scope,
1340 fieldptr.positionals.field_name.src,
1341 "no member named '{s}' in '{}'",
1342 .{ field_name, elem_ty },
1343 );
1344 }
1345 },
1346 else => {},
1347 }
1348 },
1349 .Type => {
1350 _ = try mod.resolveConstValue(scope, object_ptr);
1351 const result = try mod.analyzeDeref(scope, fieldptr.base.src, object_ptr, object_ptr.src);
1352 const val = result.value().?;
1353 const child_type = try val.toType(scope.arena());
1354 switch (child_type.zigTypeTag()) {
1355 .ErrorSet => {
1356 // TODO resolve inferred error sets
1357 const entry = if (val.castTag(.error_set)) |payload|
1358 (payload.data.fields.getEntry(field_name) orelse
1359 return mod.fail(scope, fieldptr.base.src, "no error named '{s}' in '{}'", .{ field_name, child_type })).*
1360 else
1361 try mod.getErrorValue(field_name);
1362
1363 const result_type = if (child_type.tag() == .anyerror)
1364 try Type.Tag.error_set_single.create(scope.arena(), entry.key)
1365 else
1366 child_type;
1367
1368 return mod.constInst(scope, fieldptr.base.src, .{
1369 .ty = try mod.simplePtrType(scope, fieldptr.base.src, result_type, false, .One),
1370 .val = try Value.Tag.ref_val.create(
1371 scope.arena(),
1372 try Value.Tag.@"error".create(scope.arena(), .{
1373 .name = entry.key,
1374 .value = entry.value,
1375 }),
1376 ),
1377 });
1378 },
1379 .Struct => {
1380 const container_scope = child_type.getContainerScope();
1381 if (mod.lookupDeclName(&container_scope.base, field_name)) |decl| {
1382 // TODO if !decl.is_pub and inDifferentFiles() "{} is private"
1383 return mod.analyzeDeclRef(scope, fieldptr.base.src, decl);
1384 }
1308 const object = try resolveInst(mod, scope, inst.positionals.object);
1309 const field_name = inst.positionals.field_name;
1310 const object_ptr = try mod.analyzeRef(scope, inst.base.src, object);
1311 const result_ptr = try mod.namedFieldPtr(scope, inst.base.src, object_ptr, field_name, inst.base.src);
1312 return mod.analyzeDeref(scope, inst.base.src, result_ptr, result_ptr.src);
1313}
13851314
1386 if (container_scope.file_scope == mod.root_scope) {
1387 return mod.fail(scope, fieldptr.base.src, "root source file has no member called '{s}'", .{field_name});
1388 } else {
1389 return mod.fail(scope, fieldptr.base.src, "container '{}' has no member called '{s}'", .{ child_type, field_name });
1390 }
1391 },
1392 else => return mod.fail(scope, fieldptr.base.src, "type '{}' does not support field access", .{child_type}),
1393 }
1394 },
1395 else => {},
1396 }
1397 return mod.fail(scope, fieldptr.base.src, "type '{}' does not support field access", .{elem_ty});
1315fn fieldPtr(mod: *Module, scope: *Scope, inst: *zir.Inst.Field) InnerError!*Inst {
1316 const tracy = trace(@src());
1317 defer tracy.end();
1318
1319 const object_ptr = try resolveInst(mod, scope, inst.positionals.object);
1320 const field_name = inst.positionals.field_name;
1321 return mod.namedFieldPtr(scope, inst.base.src, object_ptr, field_name, inst.base.src);
1322}
1323
1324fn fieldValNamed(mod: *Module, scope: *Scope, inst: *zir.Inst.FieldNamed) InnerError!*Inst {
1325 const tracy = trace(@src());
1326 defer tracy.end();
1327
1328 const object = try resolveInst(mod, scope, inst.positionals.object);
1329 const field_name = try resolveConstString(mod, scope, inst.positionals.field_name);
1330 const fsrc = inst.positionals.field_name.src;
1331 const object_ptr = try mod.analyzeRef(scope, inst.base.src, object);
1332 const result_ptr = try mod.namedFieldPtr(scope, inst.base.src, object_ptr, field_name, fsrc);
1333 return mod.analyzeDeref(scope, inst.base.src, result_ptr, result_ptr.src);
1334}
1335
1336fn fieldPtrNamed(mod: *Module, scope: *Scope, inst: *zir.Inst.FieldNamed) InnerError!*Inst {
1337 const tracy = trace(@src());
1338 defer tracy.end();
1339
1340 const object_ptr = try resolveInst(mod, scope, inst.positionals.object);
1341 const field_name = try resolveConstString(mod, scope, inst.positionals.field_name);
1342 const fsrc = inst.positionals.field_name.src;
1343 return mod.namedFieldPtr(scope, inst.base.src, object_ptr, field_name, fsrc);
13981344}
13991345
14001346fn analyzeInstIntCast(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) InnerError!*Inst {
......@@ -1481,42 +1427,24 @@ fn analyzeInstFloatCast(mod: *Module, scope: *Scope, inst: *zir.Inst.BinOp) Inne
14811427 return mod.fail(scope, inst.base.src, "TODO implement analyze widen or shorten float", .{});
14821428}
14831429
1484fn analyzeInstElemPtr(mod: *Module, scope: *Scope, inst: *zir.Inst.ElemPtr) InnerError!*Inst {
1430fn elemVal(mod: *Module, scope: *Scope, inst: *zir.Inst.Elem) InnerError!*Inst {
14851431 const tracy = trace(@src());
14861432 defer tracy.end();
1487 const array_ptr = try resolveInst(mod, scope, inst.positionals.array_ptr);
1488 const uncasted_index = try resolveInst(mod, scope, inst.positionals.index);
1489 const elem_index = try mod.coerce(scope, Type.initTag(.usize), uncasted_index);
14901433
1491 const elem_ty = switch (array_ptr.ty.zigTypeTag()) {
1492 .Pointer => array_ptr.ty.elemType(),
1493 else => return mod.fail(scope, inst.positionals.array_ptr.src, "expected pointer, found '{}'", .{array_ptr.ty}),
1494 };
1495 if (!elem_ty.isIndexable()) {
1496 return mod.fail(scope, inst.base.src, "array access of non-array type '{}'", .{elem_ty});
1497 }
1498
1499 if (elem_ty.isSinglePointer() and elem_ty.elemType().zigTypeTag() == .Array) {
1500 // we have to deref the ptr operand to get the actual array pointer
1501 const array_ptr_deref = try mod.analyzeDeref(scope, inst.base.src, array_ptr, inst.positionals.array_ptr.src);
1502 if (array_ptr_deref.value()) |array_ptr_val| {
1503 if (elem_index.value()) |index_val| {
1504 // Both array pointer and index are compile-time known.
1505 const index_u64 = index_val.toUnsignedInt();
1506 // @intCast here because it would have been impossible to construct a value that
1507 // required a larger index.
1508 const elem_ptr = try array_ptr_val.elemPtr(scope.arena(), @intCast(usize, index_u64));
1509 const pointee_type = elem_ty.elemType().elemType();
1434 const array = try resolveInst(mod, scope, inst.positionals.array);
1435 const array_ptr = try mod.analyzeRef(scope, inst.base.src, array);
1436 const elem_index = try resolveInst(mod, scope, inst.positionals.index);
1437 const result_ptr = try mod.elemPtr(scope, inst.base.src, array_ptr, elem_index);
1438 return mod.analyzeDeref(scope, inst.base.src, result_ptr, result_ptr.src);
1439}
15101440
1511 return mod.constInst(scope, inst.base.src, .{
1512 .ty = try Type.Tag.single_const_pointer.create(scope.arena(), pointee_type),
1513 .val = elem_ptr,
1514 });
1515 }
1516 }
1517 }
1441fn elemPtr(mod: *Module, scope: *Scope, inst: *zir.Inst.Elem) InnerError!*Inst {
1442 const tracy = trace(@src());
1443 defer tracy.end();
15181444
1519 return mod.fail(scope, inst.base.src, "TODO implement more analyze elemptr", .{});
1445 const array_ptr = try resolveInst(mod, scope, inst.positionals.array);
1446 const elem_index = try resolveInst(mod, scope, inst.positionals.index);
1447 return mod.elemPtr(scope, inst.base.src, array_ptr, elem_index);
15201448}
15211449
15221450fn analyzeInstSlice(mod: *Module, scope: *Scope, inst: *zir.Inst.Slice) InnerError!*Inst {
test/stage2/aarch64.zig+1-1
......@@ -80,7 +80,7 @@ pub fn addCases(ctx: *TestContext) !void {
8080 }
8181
8282 {
83 var case = ctx.exe("hello world", linux_aarch64);
83 var case = ctx.exe("linux_aarch64 hello world", linux_aarch64);
8484 // Regular old hello world
8585 case.addCompareOutput(
8686 \\export fn _start() noreturn {
test/stage2/arm.zig+1-1
......@@ -8,7 +8,7 @@ const linux_arm = std.zig.CrossTarget{
88
99pub fn addCases(ctx: *TestContext) !void {
1010 {
11 var case = ctx.exe("hello world", linux_arm);
11 var case = ctx.exe("linux_arm hello world", linux_arm);
1212 // Regular old hello world
1313 case.addCompareOutput(
1414 \\export fn _start() noreturn {
test/stage2/llvm.zig+1-1
......@@ -29,7 +29,7 @@ pub fn addCases(ctx: *TestContext) !void {
2929 }
3030
3131 {
32 var case = ctx.exeUsingLlvmBackend("hello world", linux_x64);
32 var case = ctx.exeUsingLlvmBackend("llvm hello world", linux_x64);
3333
3434 case.addCompareOutput(
3535 \\extern fn puts(s: [*:0]const u8) c_int;
test/stage2/test.zig+1-1
......@@ -231,7 +231,7 @@ pub fn addCases(ctx: *TestContext) !void {
231231 }
232232
233233 {
234 var case = ctx.exe("hello world", linux_riscv64);
234 var case = ctx.exe("riscv64 hello world", linux_riscv64);
235235 // Regular old hello world
236236 case.addCompareOutput(
237237 \\export fn _start() noreturn {