| ... | ... | @@ -45,6 +45,17 @@ fn_block: ?*GenZir = null, |
| 45 | 45 | imports: std.AutoArrayHashMapUnmanaged(u32, Ast.TokenIndex) = .{}, |
| 46 | 46 | /// Used for temporary storage when building payloads. |
| 47 | 47 | scratch: std.ArrayListUnmanaged(u32) = .{}, |
| 48 | /// Whenever a `ref` instruction is needed, it is created and saved in this |
| 49 | /// table instead of being immediately appended to the current block body. |
| 50 | /// Then, when the instruction is being added to the parent block (typically from |
| 51 | /// setBlockBody), if it has a ref_table entry, then the ref instruction is added |
| 52 | /// there. This makes sure two properties are upheld: |
| 53 | /// 1. All pointers to the same locals return the same address. This is required |
| 54 | /// to be compliant with the language specification. |
| 55 | /// 2. `ref` instructions will dominate their uses. This is a required property |
| 56 | /// of ZIR. |
| 57 | /// The key is the ref operand; the value is the ref instruction. |
| 58 | ref_table: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .{}, |
| 48 | 59 | |
| 49 | 60 | const InnerError = error{ OutOfMemory, AnalysisFail }; |
| 50 | 61 | |
| ... | ... | @@ -199,6 +210,7 @@ pub fn deinit(astgen: *AstGen, gpa: Allocator) void { |
| 199 | 210 | astgen.compile_errors.deinit(gpa); |
| 200 | 211 | astgen.imports.deinit(gpa); |
| 201 | 212 | astgen.scratch.deinit(gpa); |
| 213 | astgen.ref_table.deinit(gpa); |
| 202 | 214 | } |
| 203 | 215 | |
| 204 | 216 | pub const ResultLoc = union(enum) { |
| ... | ... | @@ -4216,11 +4228,12 @@ fn structDeclInner( |
| 4216 | 4228 | } |
| 4217 | 4229 | |
| 4218 | 4230 | const body = block_scope.instructionsSlice(); |
| 4231 | const body_len = astgen.countBodyLenAfterFixups(body); |
| 4219 | 4232 | |
| 4220 | 4233 | try gz.setStruct(decl_inst, .{ |
| 4221 | 4234 | .src_node = node, |
| 4222 | 4235 | .layout = layout, |
| 4223 | | .body_len = @intCast(u32, body.len), |
| 4236 | .body_len = body_len, |
| 4224 | 4237 | .fields_len = field_count, |
| 4225 | 4238 | .decls_len = decl_count, |
| 4226 | 4239 | .known_non_opv = known_non_opv, |
| ... | ... | @@ -4230,9 +4243,9 @@ fn structDeclInner( |
| 4230 | 4243 | wip_members.finishBits(bits_per_field); |
| 4231 | 4244 | const decls_slice = wip_members.declsSlice(); |
| 4232 | 4245 | const fields_slice = wip_members.fieldsSlice(); |
| 4233 | | try astgen.extra.ensureUnusedCapacity(gpa, decls_slice.len + body.len + fields_slice.len); |
| 4246 | try astgen.extra.ensureUnusedCapacity(gpa, decls_slice.len + body_len + fields_slice.len); |
| 4234 | 4247 | astgen.extra.appendSliceAssumeCapacity(decls_slice); |
| 4235 | | astgen.extra.appendSliceAssumeCapacity(body); |
| 4248 | astgen.appendBodyWithFixups(body); |
| 4236 | 4249 | astgen.extra.appendSliceAssumeCapacity(fields_slice); |
| 4237 | 4250 | |
| 4238 | 4251 | block_scope.unstack(); |
| ... | ... | @@ -4364,12 +4377,13 @@ fn unionDeclInner( |
| 4364 | 4377 | } |
| 4365 | 4378 | |
| 4366 | 4379 | const body = block_scope.instructionsSlice(); |
| 4380 | const body_len = astgen.countBodyLenAfterFixups(body); |
| 4367 | 4381 | |
| 4368 | 4382 | try gz.setUnion(decl_inst, .{ |
| 4369 | 4383 | .src_node = node, |
| 4370 | 4384 | .layout = layout, |
| 4371 | 4385 | .tag_type = arg_inst, |
| 4372 | | .body_len = @intCast(u32, body.len), |
| 4386 | .body_len = body_len, |
| 4373 | 4387 | .fields_len = field_count, |
| 4374 | 4388 | .decls_len = decl_count, |
| 4375 | 4389 | .auto_enum_tag = have_auto_enum, |
| ... | ... | @@ -4378,9 +4392,9 @@ fn unionDeclInner( |
| 4378 | 4392 | wip_members.finishBits(bits_per_field); |
| 4379 | 4393 | const decls_slice = wip_members.declsSlice(); |
| 4380 | 4394 | const fields_slice = wip_members.fieldsSlice(); |
| 4381 | | try astgen.extra.ensureUnusedCapacity(gpa, decls_slice.len + body.len + fields_slice.len); |
| 4395 | try astgen.extra.ensureUnusedCapacity(gpa, decls_slice.len + body_len + fields_slice.len); |
| 4382 | 4396 | astgen.extra.appendSliceAssumeCapacity(decls_slice); |
| 4383 | | astgen.extra.appendSliceAssumeCapacity(body); |
| 4397 | astgen.appendBodyWithFixups(body); |
| 4384 | 4398 | astgen.extra.appendSliceAssumeCapacity(fields_slice); |
| 4385 | 4399 | |
| 4386 | 4400 | block_scope.unstack(); |
| ... | ... | @@ -4616,12 +4630,13 @@ fn containerDecl( |
| 4616 | 4630 | } |
| 4617 | 4631 | |
| 4618 | 4632 | const body = block_scope.instructionsSlice(); |
| 4633 | const body_len = astgen.countBodyLenAfterFixups(body); |
| 4619 | 4634 | |
| 4620 | 4635 | try gz.setEnum(decl_inst, .{ |
| 4621 | 4636 | .src_node = node, |
| 4622 | 4637 | .nonexhaustive = nonexhaustive, |
| 4623 | 4638 | .tag_type = arg_inst, |
| 4624 | | .body_len = @intCast(u32, body.len), |
| 4639 | .body_len = body_len, |
| 4625 | 4640 | .fields_len = @intCast(u32, counts.total_fields), |
| 4626 | 4641 | .decls_len = @intCast(u32, counts.decls), |
| 4627 | 4642 | }); |
| ... | ... | @@ -4629,9 +4644,9 @@ fn containerDecl( |
| 4629 | 4644 | wip_members.finishBits(bits_per_field); |
| 4630 | 4645 | const decls_slice = wip_members.declsSlice(); |
| 4631 | 4646 | const fields_slice = wip_members.fieldsSlice(); |
| 4632 | | try astgen.extra.ensureUnusedCapacity(gpa, decls_slice.len + body.len + fields_slice.len); |
| 4647 | try astgen.extra.ensureUnusedCapacity(gpa, decls_slice.len + body_len + fields_slice.len); |
| 4633 | 4648 | astgen.extra.appendSliceAssumeCapacity(decls_slice); |
| 4634 | | astgen.extra.appendSliceAssumeCapacity(body); |
| 4649 | astgen.appendBodyWithFixups(body); |
| 4635 | 4650 | astgen.extra.appendSliceAssumeCapacity(fields_slice); |
| 4636 | 4651 | |
| 4637 | 4652 | block_scope.unstack(); |
| ... | ... | @@ -5403,10 +5418,12 @@ fn setCondBrPayload( |
| 5403 | 5418 | const astgen = then_scope.astgen; |
| 5404 | 5419 | const then_body = then_scope.instructionsSliceUpto(else_scope); |
| 5405 | 5420 | const else_body = else_scope.instructionsSlice(); |
| 5406 | | const then_body_len = @intCast(u32, then_body.len + @boolToInt(then_break != 0)); |
| 5407 | | const else_body_len = @intCast(u32, else_body.len + @boolToInt(else_break != 0)); |
| 5408 | | try astgen.extra.ensureUnusedCapacity(astgen.gpa, @typeInfo(Zir.Inst.CondBr).Struct.fields.len + |
| 5409 | | then_body_len + else_body_len); |
| 5421 | const then_body_len = astgen.countBodyLenAfterFixups(then_body) + @boolToInt(then_break != 0); |
| 5422 | const else_body_len = astgen.countBodyLenAfterFixups(else_body) + @boolToInt(else_break != 0); |
| 5423 | try astgen.extra.ensureUnusedCapacity( |
| 5424 | astgen.gpa, |
| 5425 | @typeInfo(Zir.Inst.CondBr).Struct.fields.len + then_body_len + else_body_len, |
| 5426 | ); |
| 5410 | 5427 | |
| 5411 | 5428 | const zir_datas = astgen.instructions.items(.data); |
| 5412 | 5429 | zir_datas[condbr].pl_node.payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.CondBr{ |
| ... | ... | @@ -5414,9 +5431,9 @@ fn setCondBrPayload( |
| 5414 | 5431 | .then_body_len = then_body_len, |
| 5415 | 5432 | .else_body_len = else_body_len, |
| 5416 | 5433 | }); |
| 5417 | | astgen.extra.appendSliceAssumeCapacity(then_body); |
| 5434 | astgen.appendBodyWithFixups(then_body); |
| 5418 | 5435 | if (then_break != 0) astgen.extra.appendAssumeCapacity(then_break); |
| 5419 | | astgen.extra.appendSliceAssumeCapacity(else_body); |
| 5436 | astgen.appendBodyWithFixups(else_body); |
| 5420 | 5437 | if (else_break != 0) astgen.extra.appendAssumeCapacity(else_break); |
| 5421 | 5438 | } |
| 5422 | 5439 | |
| ... | ... | @@ -5437,10 +5454,12 @@ fn setCondBrPayloadElideBlockStorePtr( |
| 5437 | 5454 | const else_body = else_scope.instructionsSlice(); |
| 5438 | 5455 | const has_then_break = then_break != 0; |
| 5439 | 5456 | const has_else_break = else_break != 0; |
| 5440 | | const then_body_len = @intCast(u32, then_body.len + @boolToInt(has_then_break)); |
| 5441 | | const else_body_len = @intCast(u32, else_body.len + @boolToInt(has_else_break)); |
| 5442 | | try astgen.extra.ensureUnusedCapacity(astgen.gpa, @typeInfo(Zir.Inst.CondBr).Struct.fields.len + |
| 5443 | | then_body_len + else_body_len); |
| 5457 | const then_body_len = astgen.countBodyLenAfterFixups(then_body) + @boolToInt(has_then_break); |
| 5458 | const else_body_len = astgen.countBodyLenAfterFixups(else_body) + @boolToInt(has_else_break); |
| 5459 | try astgen.extra.ensureUnusedCapacity( |
| 5460 | astgen.gpa, |
| 5461 | @typeInfo(Zir.Inst.CondBr).Struct.fields.len + then_body_len + else_body_len, |
| 5462 | ); |
| 5444 | 5463 | |
| 5445 | 5464 | const zir_tags = astgen.instructions.items(.tag); |
| 5446 | 5465 | const zir_datas = astgen.instructions.items(.data); |
| ... | ... | @@ -5475,7 +5494,7 @@ fn setCondBrPayloadElideBlockStorePtr( |
| 5475 | 5494 | continue; |
| 5476 | 5495 | } |
| 5477 | 5496 | } |
| 5478 | | astgen.extra.appendAssumeCapacity(src_inst); |
| 5497 | appendPossiblyRefdBodyInst(astgen, &astgen.extra, src_inst); |
| 5479 | 5498 | } |
| 5480 | 5499 | if (has_then_break) astgen.extra.appendAssumeCapacity(then_break); |
| 5481 | 5500 | |
| ... | ... | @@ -5495,7 +5514,7 @@ fn setCondBrPayloadElideBlockStorePtr( |
| 5495 | 5514 | continue; |
| 5496 | 5515 | } |
| 5497 | 5516 | } |
| 5498 | | astgen.extra.appendAssumeCapacity(src_inst); |
| 5517 | appendPossiblyRefdBodyInst(astgen, &astgen.extra, src_inst); |
| 5499 | 5518 | } |
| 5500 | 5519 | if (has_else_break) astgen.extra.appendAssumeCapacity(else_break); |
| 5501 | 5520 | } |
| ... | ... | @@ -6249,8 +6268,10 @@ fn switchExpr( |
| 6249 | 6268 | } |
| 6250 | 6269 | |
| 6251 | 6270 | const case_slice = case_scope.instructionsSlice(); |
| 6252 | | payloads.items[body_len_index] = @intCast(u32, case_slice.len); |
| 6253 | | try payloads.appendSlice(gpa, case_slice); |
| 6271 | const body_len = astgen.countBodyLenAfterFixups(case_slice); |
| 6272 | try payloads.ensureUnusedCapacity(gpa, body_len); |
| 6273 | payloads.items[body_len_index] = body_len; |
| 6274 | appendBodyWithFixupsArrayList(astgen, payloads, case_slice); |
| 6254 | 6275 | } |
| 6255 | 6276 | } |
| 6256 | 6277 | // Now that the item expressions are generated we can add this. |
| ... | ... | @@ -7043,10 +7064,11 @@ fn typeOf( |
| 7043 | 7064 | node: Ast.Node.Index, |
| 7044 | 7065 | args: []const Ast.Node.Index, |
| 7045 | 7066 | ) InnerError!Zir.Inst.Ref { |
| 7067 | const astgen = gz.astgen; |
| 7046 | 7068 | if (args.len < 1) { |
| 7047 | | return gz.astgen.failNode(node, "expected at least 1 argument, found 0", .{}); |
| 7069 | return astgen.failNode(node, "expected at least 1 argument, found 0", .{}); |
| 7048 | 7070 | } |
| 7049 | | const gpa = gz.astgen.gpa; |
| 7071 | const gpa = astgen.gpa; |
| 7050 | 7072 | if (args.len == 1) { |
| 7051 | 7073 | const typeof_inst = try gz.makeBlockInst(.typeof_builtin, node); |
| 7052 | 7074 | |
| ... | ... | @@ -7065,7 +7087,7 @@ fn typeOf( |
| 7065 | 7087 | return rvalue(gz, rl, indexToRef(typeof_inst), node); |
| 7066 | 7088 | } |
| 7067 | 7089 | const payload_size: u32 = std.meta.fields(Zir.Inst.TypeOfPeer).len; |
| 7068 | | const payload_index = try reserveExtra(gz.astgen, payload_size + args.len); |
| 7090 | const payload_index = try reserveExtra(astgen, payload_size + args.len); |
| 7069 | 7091 | var args_index = payload_index + payload_size; |
| 7070 | 7092 | |
| 7071 | 7093 | const typeof_inst = try gz.addExtendedMultiOpPayloadIndex(.typeof_peer, payload_index, args.len); |
| ... | ... | @@ -7075,17 +7097,19 @@ fn typeOf( |
| 7075 | 7097 | |
| 7076 | 7098 | for (args) |arg, i| { |
| 7077 | 7099 | const param_ref = try reachableExpr(&typeof_scope, &typeof_scope.base, .none, arg, node); |
| 7078 | | gz.astgen.extra.items[args_index + i] = @enumToInt(param_ref); |
| 7100 | astgen.extra.items[args_index + i] = @enumToInt(param_ref); |
| 7079 | 7101 | } |
| 7080 | 7102 | _ = try typeof_scope.addBreak(.break_inline, refToIndex(typeof_inst).?, .void_value); |
| 7081 | 7103 | |
| 7082 | 7104 | const body = typeof_scope.instructionsSlice(); |
| 7083 | | gz.astgen.setExtra(payload_index, Zir.Inst.TypeOfPeer{ |
| 7084 | | .body_len = @intCast(u32, body.len), |
| 7085 | | .body_index = @intCast(u32, gz.astgen.extra.items.len), |
| 7105 | const body_len = astgen.countBodyLenAfterFixups(body); |
| 7106 | astgen.setExtra(payload_index, Zir.Inst.TypeOfPeer{ |
| 7107 | .body_len = @intCast(u32, body_len), |
| 7108 | .body_index = @intCast(u32, astgen.extra.items.len), |
| 7086 | 7109 | .src_node = gz.nodeIndexToRelative(node), |
| 7087 | 7110 | }); |
| 7088 | | try gz.astgen.extra.appendSlice(gpa, body); |
| 7111 | try astgen.extra.ensureUnusedCapacity(gpa, body_len); |
| 7112 | astgen.appendBodyWithFixups(body); |
| 7089 | 7113 | typeof_scope.unstack(); |
| 7090 | 7114 | |
| 7091 | 7115 | return rvalue(gz, rl, typeof_inst, node); |
| ... | ... | @@ -9032,9 +9056,22 @@ fn rvalue( |
| 9032 | 9056 | }, |
| 9033 | 9057 | .ref => { |
| 9034 | 9058 | // We need a pointer but we have a value. |
| 9035 | | const tree = gz.astgen.tree; |
| 9059 | // Unfortunately it's not quite as simple as directly emitting a ref |
| 9060 | // instruction here because we need subsequent address-of operator on |
| 9061 | // const locals to return the same address. |
| 9062 | const astgen = gz.astgen; |
| 9063 | const tree = astgen.tree; |
| 9036 | 9064 | const src_token = tree.firstToken(src_node); |
| 9037 | | return gz.addUnTok(.ref, result, src_token); |
| 9065 | const result_index = refToIndex(result) orelse |
| 9066 | return gz.addUnTok(.ref, result, src_token); |
| 9067 | const zir_tags = gz.astgen.instructions.items(.tag); |
| 9068 | if (zir_tags[result_index].isParam()) |
| 9069 | return gz.addUnTok(.ref, result, src_token); |
| 9070 | const gop = try astgen.ref_table.getOrPut(astgen.gpa, result_index); |
| 9071 | if (!gop.found_existing) { |
| 9072 | gop.value_ptr.* = try gz.makeUnTok(.ref, result, src_token); |
| 9073 | } |
| 9074 | return indexToRef(gop.value_ptr.*); |
| 9038 | 9075 | }, |
| 9039 | 9076 | .ty => |ty_inst| { |
| 9040 | 9077 | // Quickly eliminate some common, unnecessary type coercion. |
| ... | ... | @@ -9976,43 +10013,58 @@ const GenZir = struct { |
| 9976 | 10013 | |
| 9977 | 10014 | /// Assumes nothing stacked on `gz`. Unstacks `gz`. |
| 9978 | 10015 | fn setBoolBrBody(gz: *GenZir, inst: Zir.Inst.Index) !void { |
| 9979 | | const gpa = gz.astgen.gpa; |
| 10016 | const astgen = gz.astgen; |
| 10017 | const gpa = astgen.gpa; |
| 9980 | 10018 | const body = gz.instructionsSlice(); |
| 9981 | | try gz.astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Block).Struct.fields.len + body.len); |
| 9982 | | const zir_datas = gz.astgen.instructions.items(.data); |
| 9983 | | zir_datas[inst].bool_br.payload_index = gz.astgen.addExtraAssumeCapacity( |
| 9984 | | Zir.Inst.Block{ .body_len = @intCast(u32, body.len) }, |
| 10019 | const body_len = astgen.countBodyLenAfterFixups(body); |
| 10020 | try astgen.extra.ensureUnusedCapacity( |
| 10021 | gpa, |
| 10022 | @typeInfo(Zir.Inst.Block).Struct.fields.len + body_len, |
| 9985 | 10023 | ); |
| 9986 | | gz.astgen.extra.appendSliceAssumeCapacity(body); |
| 10024 | const zir_datas = astgen.instructions.items(.data); |
| 10025 | zir_datas[inst].bool_br.payload_index = astgen.addExtraAssumeCapacity( |
| 10026 | Zir.Inst.Block{ .body_len = body_len }, |
| 10027 | ); |
| 10028 | astgen.appendBodyWithFixups(body); |
| 9987 | 10029 | gz.unstack(); |
| 9988 | 10030 | } |
| 9989 | 10031 | |
| 9990 | 10032 | /// Assumes nothing stacked on `gz`. Unstacks `gz`. |
| 9991 | 10033 | fn setBlockBody(gz: *GenZir, inst: Zir.Inst.Index) !void { |
| 9992 | | const gpa = gz.astgen.gpa; |
| 10034 | const astgen = gz.astgen; |
| 10035 | const gpa = astgen.gpa; |
| 9993 | 10036 | const body = gz.instructionsSlice(); |
| 9994 | | try gz.astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Block).Struct.fields.len + body.len); |
| 9995 | | const zir_datas = gz.astgen.instructions.items(.data); |
| 9996 | | zir_datas[inst].pl_node.payload_index = gz.astgen.addExtraAssumeCapacity( |
| 9997 | | Zir.Inst.Block{ .body_len = @intCast(u32, body.len) }, |
| 10037 | const body_len = astgen.countBodyLenAfterFixups(body); |
| 10038 | try astgen.extra.ensureUnusedCapacity( |
| 10039 | gpa, |
| 10040 | @typeInfo(Zir.Inst.Block).Struct.fields.len + body_len, |
| 10041 | ); |
| 10042 | const zir_datas = astgen.instructions.items(.data); |
| 10043 | zir_datas[inst].pl_node.payload_index = astgen.addExtraAssumeCapacity( |
| 10044 | Zir.Inst.Block{ .body_len = body_len }, |
| 9998 | 10045 | ); |
| 9999 | | gz.astgen.extra.appendSliceAssumeCapacity(body); |
| 10046 | astgen.appendBodyWithFixups(body); |
| 10000 | 10047 | gz.unstack(); |
| 10001 | 10048 | } |
| 10002 | 10049 | |
| 10003 | 10050 | /// Assumes nothing stacked on `gz`. Unstacks `gz`. |
| 10004 | 10051 | fn setTryBody(gz: *GenZir, inst: Zir.Inst.Index, operand: Zir.Inst.Ref) !void { |
| 10005 | | const gpa = gz.astgen.gpa; |
| 10052 | const astgen = gz.astgen; |
| 10053 | const gpa = astgen.gpa; |
| 10006 | 10054 | const body = gz.instructionsSlice(); |
| 10007 | | try gz.astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Try).Struct.fields.len + body.len); |
| 10008 | | const zir_datas = gz.astgen.instructions.items(.data); |
| 10009 | | zir_datas[inst].pl_node.payload_index = gz.astgen.addExtraAssumeCapacity( |
| 10055 | const body_len = astgen.countBodyLenAfterFixups(body); |
| 10056 | try astgen.extra.ensureUnusedCapacity( |
| 10057 | gpa, |
| 10058 | @typeInfo(Zir.Inst.Try).Struct.fields.len + body_len, |
| 10059 | ); |
| 10060 | const zir_datas = astgen.instructions.items(.data); |
| 10061 | zir_datas[inst].pl_node.payload_index = astgen.addExtraAssumeCapacity( |
| 10010 | 10062 | Zir.Inst.Try{ |
| 10011 | 10063 | .operand = operand, |
| 10012 | | .body_len = @intCast(u32, body.len), |
| 10064 | .body_len = body_len, |
| 10013 | 10065 | }, |
| 10014 | 10066 | ); |
| 10015 | | gz.astgen.extra.appendSliceAssumeCapacity(body); |
| 10067 | astgen.appendBodyWithFixups(body); |
| 10016 | 10068 | gz.unstack(); |
| 10017 | 10069 | } |
| 10018 | 10070 | |
| ... | ... | @@ -10089,6 +10141,7 @@ const GenZir = struct { |
| 10089 | 10141 | if (args.ret_gz) |ret_gz| |
| 10090 | 10142 | ret_body = ret_gz.instructionsSlice(); |
| 10091 | 10143 | } |
| 10144 | const body_len = astgen.countBodyLenAfterFixups(body); |
| 10092 | 10145 | |
| 10093 | 10146 | if (args.cc_ref != .none or args.lib_name != 0 or |
| 10094 | 10147 | args.is_var_args or args.is_test or args.is_extern or |
| ... | ... | @@ -10114,13 +10167,13 @@ const GenZir = struct { |
| 10114 | 10167 | fancyFnExprExtraLen(section_body, args.section_ref) + |
| 10115 | 10168 | fancyFnExprExtraLen(cc_body, args.cc_ref) + |
| 10116 | 10169 | fancyFnExprExtraLen(ret_body, ret_ref) + |
| 10117 | | body.len + src_locs.len + |
| 10170 | body_len + src_locs.len + |
| 10118 | 10171 | @boolToInt(args.lib_name != 0) + |
| 10119 | 10172 | @boolToInt(args.noalias_bits != 0), |
| 10120 | 10173 | ); |
| 10121 | 10174 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.FuncFancy{ |
| 10122 | 10175 | .param_block = args.param_block, |
| 10123 | | .body_len = @intCast(u32, body.len), |
| 10176 | .body_len = body_len, |
| 10124 | 10177 | .bits = .{ |
| 10125 | 10178 | .is_var_args = args.is_var_args, |
| 10126 | 10179 | .is_inferred_error = args.is_inferred_error, |
| ... | ... | @@ -10187,7 +10240,7 @@ const GenZir = struct { |
| 10187 | 10240 | astgen.extra.appendAssumeCapacity(args.noalias_bits); |
| 10188 | 10241 | } |
| 10189 | 10242 | |
| 10190 | | astgen.extra.appendSliceAssumeCapacity(body); |
| 10243 | astgen.appendBodyWithFixups(body); |
| 10191 | 10244 | astgen.extra.appendSliceAssumeCapacity(src_locs); |
| 10192 | 10245 | |
| 10193 | 10246 | // Order is important when unstacking. |
| ... | ... | @@ -10214,9 +10267,9 @@ const GenZir = struct { |
| 10214 | 10267 | } else { |
| 10215 | 10268 | try astgen.extra.ensureUnusedCapacity( |
| 10216 | 10269 | gpa, |
| 10217 | | @typeInfo(Zir.Inst.Func).Struct.fields.len + |
| 10270 | @typeInfo(Zir.Inst.Func).Struct.fields.len + 1 + |
| 10218 | 10271 | @maximum(ret_body.len, @boolToInt(ret_ref != .none)) + |
| 10219 | | body.len + src_locs.len, |
| 10272 | body_len + src_locs.len, |
| 10220 | 10273 | ); |
| 10221 | 10274 | const ret_body_len = if (ret_body.len != 0) |
| 10222 | 10275 | @intCast(u32, ret_body.len) |
| ... | ... | @@ -10226,7 +10279,7 @@ const GenZir = struct { |
| 10226 | 10279 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.Func{ |
| 10227 | 10280 | .param_block = args.param_block, |
| 10228 | 10281 | .ret_body_len = ret_body_len, |
| 10229 | | .body_len = @intCast(u32, body.len), |
| 10282 | .body_len = body_len, |
| 10230 | 10283 | }); |
| 10231 | 10284 | const zir_datas = astgen.instructions.items(.data); |
| 10232 | 10285 | if (ret_body.len != 0) { |
| ... | ... | @@ -10235,7 +10288,7 @@ const GenZir = struct { |
| 10235 | 10288 | } else if (ret_ref != .none) { |
| 10236 | 10289 | astgen.extra.appendAssumeCapacity(@enumToInt(ret_ref)); |
| 10237 | 10290 | } |
| 10238 | | astgen.extra.appendSliceAssumeCapacity(body); |
| 10291 | astgen.appendBodyWithFixups(body); |
| 10239 | 10292 | astgen.extra.appendSliceAssumeCapacity(src_locs); |
| 10240 | 10293 | |
| 10241 | 10294 | // Order is important when unstacking. |
| ... | ... | @@ -10593,6 +10646,26 @@ const GenZir = struct { |
| 10593 | 10646 | }); |
| 10594 | 10647 | } |
| 10595 | 10648 | |
| 10649 | fn makeUnTok( |
| 10650 | gz: *GenZir, |
| 10651 | tag: Zir.Inst.Tag, |
| 10652 | operand: Zir.Inst.Ref, |
| 10653 | /// Absolute token index. This function does the conversion to Decl offset. |
| 10654 | abs_tok_index: Ast.TokenIndex, |
| 10655 | ) !Zir.Inst.Index { |
| 10656 | const astgen = gz.astgen; |
| 10657 | const new_index = @intCast(Zir.Inst.Index, astgen.instructions.len); |
| 10658 | assert(operand != .none); |
| 10659 | try astgen.instructions.append(astgen.gpa, .{ |
| 10660 | .tag = tag, |
| 10661 | .data = .{ .un_tok = .{ |
| 10662 | .operand = operand, |
| 10663 | .src_tok = gz.tokenIndexToRelative(abs_tok_index), |
| 10664 | } }, |
| 10665 | }); |
| 10666 | return new_index; |
| 10667 | } |
| 10668 | |
| 10596 | 10669 | fn addStrTok( |
| 10597 | 10670 | gz: *GenZir, |
| 10598 | 10671 | tag: Zir.Inst.Tag, |
| ... | ... | @@ -11337,3 +11410,42 @@ fn isInferred(astgen: *AstGen, ref: Zir.Inst.Ref) bool { |
| 11337 | 11410 | else => false, |
| 11338 | 11411 | }; |
| 11339 | 11412 | } |
| 11413 | |
| 11414 | /// Assumes capacity for body has already been added. Needed capacity taking into |
| 11415 | /// account fixups can be found with `countBodyLenAfterFixups`. |
| 11416 | fn appendBodyWithFixups(astgen: *AstGen, body: []const Zir.Inst.Index) void { |
| 11417 | return appendBodyWithFixupsArrayList(astgen, &astgen.extra, body); |
| 11418 | } |
| 11419 | |
| 11420 | fn appendBodyWithFixupsArrayList( |
| 11421 | astgen: *AstGen, |
| 11422 | list: *std.ArrayListUnmanaged(u32), |
| 11423 | body: []const Zir.Inst.Index, |
| 11424 | ) void { |
| 11425 | for (body) |body_inst| { |
| 11426 | appendPossiblyRefdBodyInst(astgen, list, body_inst); |
| 11427 | } |
| 11428 | } |
| 11429 | |
| 11430 | fn appendPossiblyRefdBodyInst( |
| 11431 | astgen: *AstGen, |
| 11432 | list: *std.ArrayListUnmanaged(u32), |
| 11433 | body_inst: Zir.Inst.Index, |
| 11434 | ) void { |
| 11435 | list.appendAssumeCapacity(body_inst); |
| 11436 | const kv = astgen.ref_table.fetchRemove(body_inst) orelse return; |
| 11437 | const ref_inst = kv.value; |
| 11438 | return appendPossiblyRefdBodyInst(astgen, list, ref_inst); |
| 11439 | } |
| 11440 | |
| 11441 | fn countBodyLenAfterFixups(astgen: *AstGen, body: []const Zir.Inst.Index) u32 { |
| 11442 | var count = body.len; |
| 11443 | for (body) |body_inst| { |
| 11444 | var check_inst = body_inst; |
| 11445 | while (astgen.ref_table.get(check_inst)) |ref_inst| { |
| 11446 | count += 1; |
| 11447 | check_inst = ref_inst; |
| 11448 | } |
| 11449 | } |
| 11450 | return @intCast(u32, count); |
| 11451 | } |