| ... | @@ -45,6 +45,17 @@ fn_block: ?*GenZir = null, | ... | @@ -45,6 +45,17 @@ fn_block: ?*GenZir = null, |
| 45 | imports: std.AutoArrayHashMapUnmanaged(u32, Ast.TokenIndex) = .{}, | 45 | imports: std.AutoArrayHashMapUnmanaged(u32, Ast.TokenIndex) = .{}, |
| 46 | /// Used for temporary storage when building payloads. | 46 | /// Used for temporary storage when building payloads. |
| 47 | scratch: std.ArrayListUnmanaged(u32) = .{}, | 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 | const InnerError = error{ OutOfMemory, AnalysisFail }; | 60 | const InnerError = error{ OutOfMemory, AnalysisFail }; |
| 50 | | 61 | |
| ... | @@ -199,6 +210,7 @@ pub fn deinit(astgen: *AstGen, gpa: Allocator) void { | ... | @@ -199,6 +210,7 @@ pub fn deinit(astgen: *AstGen, gpa: Allocator) void { |
| 199 | astgen.compile_errors.deinit(gpa); | 210 | astgen.compile_errors.deinit(gpa); |
| 200 | astgen.imports.deinit(gpa); | 211 | astgen.imports.deinit(gpa); |
| 201 | astgen.scratch.deinit(gpa); | 212 | astgen.scratch.deinit(gpa); |
| | 213 | astgen.ref_table.deinit(gpa); |
| 202 | } | 214 | } |
| 203 | | 215 | |
| 204 | pub const ResultLoc = union(enum) { | 216 | pub const ResultLoc = union(enum) { |
| ... | @@ -4216,11 +4228,12 @@ fn structDeclInner( | ... | @@ -4216,11 +4228,12 @@ fn structDeclInner( |
| 4216 | } | 4228 | } |
| 4217 | | 4229 | |
| 4218 | const body = block_scope.instructionsSlice(); | 4230 | const body = block_scope.instructionsSlice(); |
| | 4231 | const body_len = astgen.countBodyLenAfterFixups(body); |
| 4219 | | 4232 | |
| 4220 | try gz.setStruct(decl_inst, .{ | 4233 | try gz.setStruct(decl_inst, .{ |
| 4221 | .src_node = node, | 4234 | .src_node = node, |
| 4222 | .layout = layout, | 4235 | .layout = layout, |
| 4223 | .body_len = @intCast(u32, body.len), | 4236 | .body_len = body_len, |
| 4224 | .fields_len = field_count, | 4237 | .fields_len = field_count, |
| 4225 | .decls_len = decl_count, | 4238 | .decls_len = decl_count, |
| 4226 | .known_non_opv = known_non_opv, | 4239 | .known_non_opv = known_non_opv, |
| ... | @@ -4230,9 +4243,9 @@ fn structDeclInner( | ... | @@ -4230,9 +4243,9 @@ fn structDeclInner( |
| 4230 | wip_members.finishBits(bits_per_field); | 4243 | wip_members.finishBits(bits_per_field); |
| 4231 | const decls_slice = wip_members.declsSlice(); | 4244 | const decls_slice = wip_members.declsSlice(); |
| 4232 | const fields_slice = wip_members.fieldsSlice(); | 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 | astgen.extra.appendSliceAssumeCapacity(decls_slice); | 4247 | astgen.extra.appendSliceAssumeCapacity(decls_slice); |
| 4235 | astgen.extra.appendSliceAssumeCapacity(body); | 4248 | astgen.appendBodyWithFixups(body); |
| 4236 | astgen.extra.appendSliceAssumeCapacity(fields_slice); | 4249 | astgen.extra.appendSliceAssumeCapacity(fields_slice); |
| 4237 | | 4250 | |
| 4238 | block_scope.unstack(); | 4251 | block_scope.unstack(); |
| ... | @@ -4364,12 +4377,13 @@ fn unionDeclInner( | ... | @@ -4364,12 +4377,13 @@ fn unionDeclInner( |
| 4364 | } | 4377 | } |
| 4365 | | 4378 | |
| 4366 | const body = block_scope.instructionsSlice(); | 4379 | const body = block_scope.instructionsSlice(); |
| | 4380 | const body_len = astgen.countBodyLenAfterFixups(body); |
| 4367 | | 4381 | |
| 4368 | try gz.setUnion(decl_inst, .{ | 4382 | try gz.setUnion(decl_inst, .{ |
| 4369 | .src_node = node, | 4383 | .src_node = node, |
| 4370 | .layout = layout, | 4384 | .layout = layout, |
| 4371 | .tag_type = arg_inst, | 4385 | .tag_type = arg_inst, |
| 4372 | .body_len = @intCast(u32, body.len), | 4386 | .body_len = body_len, |
| 4373 | .fields_len = field_count, | 4387 | .fields_len = field_count, |
| 4374 | .decls_len = decl_count, | 4388 | .decls_len = decl_count, |
| 4375 | .auto_enum_tag = have_auto_enum, | 4389 | .auto_enum_tag = have_auto_enum, |
| ... | @@ -4378,9 +4392,9 @@ fn unionDeclInner( | ... | @@ -4378,9 +4392,9 @@ fn unionDeclInner( |
| 4378 | wip_members.finishBits(bits_per_field); | 4392 | wip_members.finishBits(bits_per_field); |
| 4379 | const decls_slice = wip_members.declsSlice(); | 4393 | const decls_slice = wip_members.declsSlice(); |
| 4380 | const fields_slice = wip_members.fieldsSlice(); | 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 | astgen.extra.appendSliceAssumeCapacity(decls_slice); | 4396 | astgen.extra.appendSliceAssumeCapacity(decls_slice); |
| 4383 | astgen.extra.appendSliceAssumeCapacity(body); | 4397 | astgen.appendBodyWithFixups(body); |
| 4384 | astgen.extra.appendSliceAssumeCapacity(fields_slice); | 4398 | astgen.extra.appendSliceAssumeCapacity(fields_slice); |
| 4385 | | 4399 | |
| 4386 | block_scope.unstack(); | 4400 | block_scope.unstack(); |
| ... | @@ -4616,12 +4630,13 @@ fn containerDecl( | ... | @@ -4616,12 +4630,13 @@ fn containerDecl( |
| 4616 | } | 4630 | } |
| 4617 | | 4631 | |
| 4618 | const body = block_scope.instructionsSlice(); | 4632 | const body = block_scope.instructionsSlice(); |
| | 4633 | const body_len = astgen.countBodyLenAfterFixups(body); |
| 4619 | | 4634 | |
| 4620 | try gz.setEnum(decl_inst, .{ | 4635 | try gz.setEnum(decl_inst, .{ |
| 4621 | .src_node = node, | 4636 | .src_node = node, |
| 4622 | .nonexhaustive = nonexhaustive, | 4637 | .nonexhaustive = nonexhaustive, |
| 4623 | .tag_type = arg_inst, | 4638 | .tag_type = arg_inst, |
| 4624 | .body_len = @intCast(u32, body.len), | 4639 | .body_len = body_len, |
| 4625 | .fields_len = @intCast(u32, counts.total_fields), | 4640 | .fields_len = @intCast(u32, counts.total_fields), |
| 4626 | .decls_len = @intCast(u32, counts.decls), | 4641 | .decls_len = @intCast(u32, counts.decls), |
| 4627 | }); | 4642 | }); |
| ... | @@ -4629,9 +4644,9 @@ fn containerDecl( | ... | @@ -4629,9 +4644,9 @@ fn containerDecl( |
| 4629 | wip_members.finishBits(bits_per_field); | 4644 | wip_members.finishBits(bits_per_field); |
| 4630 | const decls_slice = wip_members.declsSlice(); | 4645 | const decls_slice = wip_members.declsSlice(); |
| 4631 | const fields_slice = wip_members.fieldsSlice(); | 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 | astgen.extra.appendSliceAssumeCapacity(decls_slice); | 4648 | astgen.extra.appendSliceAssumeCapacity(decls_slice); |
| 4634 | astgen.extra.appendSliceAssumeCapacity(body); | 4649 | astgen.appendBodyWithFixups(body); |
| 4635 | astgen.extra.appendSliceAssumeCapacity(fields_slice); | 4650 | astgen.extra.appendSliceAssumeCapacity(fields_slice); |
| 4636 | | 4651 | |
| 4637 | block_scope.unstack(); | 4652 | block_scope.unstack(); |
| ... | @@ -5403,10 +5418,12 @@ fn setCondBrPayload( | ... | @@ -5403,10 +5418,12 @@ fn setCondBrPayload( |
| 5403 | const astgen = then_scope.astgen; | 5418 | const astgen = then_scope.astgen; |
| 5404 | const then_body = then_scope.instructionsSliceUpto(else_scope); | 5419 | const then_body = then_scope.instructionsSliceUpto(else_scope); |
| 5405 | const else_body = else_scope.instructionsSlice(); | 5420 | const else_body = else_scope.instructionsSlice(); |
| 5406 | const then_body_len = @intCast(u32, then_body.len + @boolToInt(then_break != 0)); | 5421 | const then_body_len = astgen.countBodyLenAfterFixups(then_body) + @boolToInt(then_break != 0); |
| 5407 | const else_body_len = @intCast(u32, else_body.len + @boolToInt(else_break != 0)); | 5422 | const else_body_len = astgen.countBodyLenAfterFixups(else_body) + @boolToInt(else_break != 0); |
| 5408 | try astgen.extra.ensureUnusedCapacity(astgen.gpa, @typeInfo(Zir.Inst.CondBr).Struct.fields.len + | 5423 | try astgen.extra.ensureUnusedCapacity( |
| 5409 | then_body_len + else_body_len); | 5424 | astgen.gpa, |
| | 5425 | @typeInfo(Zir.Inst.CondBr).Struct.fields.len + then_body_len + else_body_len, |
| | 5426 | ); |
| 5410 | | 5427 | |
| 5411 | const zir_datas = astgen.instructions.items(.data); | 5428 | const zir_datas = astgen.instructions.items(.data); |
| 5412 | zir_datas[condbr].pl_node.payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.CondBr{ | 5429 | zir_datas[condbr].pl_node.payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.CondBr{ |
| ... | @@ -5414,9 +5431,9 @@ fn setCondBrPayload( | ... | @@ -5414,9 +5431,9 @@ fn setCondBrPayload( |
| 5414 | .then_body_len = then_body_len, | 5431 | .then_body_len = then_body_len, |
| 5415 | .else_body_len = else_body_len, | 5432 | .else_body_len = else_body_len, |
| 5416 | }); | 5433 | }); |
| 5417 | astgen.extra.appendSliceAssumeCapacity(then_body); | 5434 | astgen.appendBodyWithFixups(then_body); |
| 5418 | if (then_break != 0) astgen.extra.appendAssumeCapacity(then_break); | 5435 | if (then_break != 0) astgen.extra.appendAssumeCapacity(then_break); |
| 5419 | astgen.extra.appendSliceAssumeCapacity(else_body); | 5436 | astgen.appendBodyWithFixups(else_body); |
| 5420 | if (else_break != 0) astgen.extra.appendAssumeCapacity(else_break); | 5437 | if (else_break != 0) astgen.extra.appendAssumeCapacity(else_break); |
| 5421 | } | 5438 | } |
| 5422 | | 5439 | |
| ... | @@ -5437,10 +5454,12 @@ fn setCondBrPayloadElideBlockStorePtr( | ... | @@ -5437,10 +5454,12 @@ fn setCondBrPayloadElideBlockStorePtr( |
| 5437 | const else_body = else_scope.instructionsSlice(); | 5454 | const else_body = else_scope.instructionsSlice(); |
| 5438 | const has_then_break = then_break != 0; | 5455 | const has_then_break = then_break != 0; |
| 5439 | const has_else_break = else_break != 0; | 5456 | const has_else_break = else_break != 0; |
| 5440 | const then_body_len = @intCast(u32, then_body.len + @boolToInt(has_then_break)); | 5457 | const then_body_len = astgen.countBodyLenAfterFixups(then_body) + @boolToInt(has_then_break); |
| 5441 | const else_body_len = @intCast(u32, else_body.len + @boolToInt(has_else_break)); | 5458 | const else_body_len = astgen.countBodyLenAfterFixups(else_body) + @boolToInt(has_else_break); |
| 5442 | try astgen.extra.ensureUnusedCapacity(astgen.gpa, @typeInfo(Zir.Inst.CondBr).Struct.fields.len + | 5459 | try astgen.extra.ensureUnusedCapacity( |
| 5443 | then_body_len + else_body_len); | 5460 | astgen.gpa, |
| | 5461 | @typeInfo(Zir.Inst.CondBr).Struct.fields.len + then_body_len + else_body_len, |
| | 5462 | ); |
| 5444 | | 5463 | |
| 5445 | const zir_tags = astgen.instructions.items(.tag); | 5464 | const zir_tags = astgen.instructions.items(.tag); |
| 5446 | const zir_datas = astgen.instructions.items(.data); | 5465 | const zir_datas = astgen.instructions.items(.data); |
| ... | @@ -5475,7 +5494,7 @@ fn setCondBrPayloadElideBlockStorePtr( | ... | @@ -5475,7 +5494,7 @@ fn setCondBrPayloadElideBlockStorePtr( |
| 5475 | continue; | 5494 | continue; |
| 5476 | } | 5495 | } |
| 5477 | } | 5496 | } |
| 5478 | astgen.extra.appendAssumeCapacity(src_inst); | 5497 | appendPossiblyRefdBodyInst(astgen, &astgen.extra, src_inst); |
| 5479 | } | 5498 | } |
| 5480 | if (has_then_break) astgen.extra.appendAssumeCapacity(then_break); | 5499 | if (has_then_break) astgen.extra.appendAssumeCapacity(then_break); |
| 5481 | | 5500 | |
| ... | @@ -5495,7 +5514,7 @@ fn setCondBrPayloadElideBlockStorePtr( | ... | @@ -5495,7 +5514,7 @@ fn setCondBrPayloadElideBlockStorePtr( |
| 5495 | continue; | 5514 | continue; |
| 5496 | } | 5515 | } |
| 5497 | } | 5516 | } |
| 5498 | astgen.extra.appendAssumeCapacity(src_inst); | 5517 | appendPossiblyRefdBodyInst(astgen, &astgen.extra, src_inst); |
| 5499 | } | 5518 | } |
| 5500 | if (has_else_break) astgen.extra.appendAssumeCapacity(else_break); | 5519 | if (has_else_break) astgen.extra.appendAssumeCapacity(else_break); |
| 5501 | } | 5520 | } |
| ... | @@ -6249,8 +6268,10 @@ fn switchExpr( | ... | @@ -6249,8 +6268,10 @@ fn switchExpr( |
| 6249 | } | 6268 | } |
| 6250 | | 6269 | |
| 6251 | const case_slice = case_scope.instructionsSlice(); | 6270 | const case_slice = case_scope.instructionsSlice(); |
| 6252 | payloads.items[body_len_index] = @intCast(u32, case_slice.len); | 6271 | const body_len = astgen.countBodyLenAfterFixups(case_slice); |
| 6253 | try payloads.appendSlice(gpa, 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 | // Now that the item expressions are generated we can add this. | 6277 | // Now that the item expressions are generated we can add this. |
| ... | @@ -7043,10 +7064,11 @@ fn typeOf( | ... | @@ -7043,10 +7064,11 @@ fn typeOf( |
| 7043 | node: Ast.Node.Index, | 7064 | node: Ast.Node.Index, |
| 7044 | args: []const Ast.Node.Index, | 7065 | args: []const Ast.Node.Index, |
| 7045 | ) InnerError!Zir.Inst.Ref { | 7066 | ) InnerError!Zir.Inst.Ref { |
| | 7067 | const astgen = gz.astgen; |
| 7046 | if (args.len < 1) { | 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 | if (args.len == 1) { | 7072 | if (args.len == 1) { |
| 7051 | const typeof_inst = try gz.makeBlockInst(.typeof_builtin, node); | 7073 | const typeof_inst = try gz.makeBlockInst(.typeof_builtin, node); |
| 7052 | | 7074 | |
| ... | @@ -7065,7 +7087,7 @@ fn typeOf( | ... | @@ -7065,7 +7087,7 @@ fn typeOf( |
| 7065 | return rvalue(gz, rl, indexToRef(typeof_inst), node); | 7087 | return rvalue(gz, rl, indexToRef(typeof_inst), node); |
| 7066 | } | 7088 | } |
| 7067 | const payload_size: u32 = std.meta.fields(Zir.Inst.TypeOfPeer).len; | 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 | var args_index = payload_index + payload_size; | 7091 | var args_index = payload_index + payload_size; |
| 7070 | | 7092 | |
| 7071 | const typeof_inst = try gz.addExtendedMultiOpPayloadIndex(.typeof_peer, payload_index, args.len); | 7093 | const typeof_inst = try gz.addExtendedMultiOpPayloadIndex(.typeof_peer, payload_index, args.len); |
| ... | @@ -7075,17 +7097,19 @@ fn typeOf( | ... | @@ -7075,17 +7097,19 @@ fn typeOf( |
| 7075 | | 7097 | |
| 7076 | for (args) |arg, i| { | 7098 | for (args) |arg, i| { |
| 7077 | const param_ref = try reachableExpr(&typeof_scope, &typeof_scope.base, .none, arg, node); | 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 | _ = try typeof_scope.addBreak(.break_inline, refToIndex(typeof_inst).?, .void_value); | 7102 | _ = try typeof_scope.addBreak(.break_inline, refToIndex(typeof_inst).?, .void_value); |
| 7081 | | 7103 | |
| 7082 | const body = typeof_scope.instructionsSlice(); | 7104 | const body = typeof_scope.instructionsSlice(); |
| 7083 | gz.astgen.setExtra(payload_index, Zir.Inst.TypeOfPeer{ | 7105 | const body_len = astgen.countBodyLenAfterFixups(body); |
| 7084 | .body_len = @intCast(u32, body.len), | 7106 | astgen.setExtra(payload_index, Zir.Inst.TypeOfPeer{ |
| 7085 | .body_index = @intCast(u32, gz.astgen.extra.items.len), | 7107 | .body_len = @intCast(u32, body_len), |
| | 7108 | .body_index = @intCast(u32, astgen.extra.items.len), |
| 7086 | .src_node = gz.nodeIndexToRelative(node), | 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 | typeof_scope.unstack(); | 7113 | typeof_scope.unstack(); |
| 7090 | | 7114 | |
| 7091 | return rvalue(gz, rl, typeof_inst, node); | 7115 | return rvalue(gz, rl, typeof_inst, node); |
| ... | @@ -9032,9 +9056,22 @@ fn rvalue( | ... | @@ -9032,9 +9056,22 @@ fn rvalue( |
| 9032 | }, | 9056 | }, |
| 9033 | .ref => { | 9057 | .ref => { |
| 9034 | // We need a pointer but we have a value. | 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 | const src_token = tree.firstToken(src_node); | 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 | .ty => |ty_inst| { | 9076 | .ty => |ty_inst| { |
| 9040 | // Quickly eliminate some common, unnecessary type coercion. | 9077 | // Quickly eliminate some common, unnecessary type coercion. |
| ... | @@ -9976,43 +10013,58 @@ const GenZir = struct { | ... | @@ -9976,43 +10013,58 @@ const GenZir = struct { |
| 9976 | | 10013 | |
| 9977 | /// Assumes nothing stacked on `gz`. Unstacks `gz`. | 10014 | /// Assumes nothing stacked on `gz`. Unstacks `gz`. |
| 9978 | fn setBoolBrBody(gz: *GenZir, inst: Zir.Inst.Index) !void { | 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 | const body = gz.instructionsSlice(); | 10018 | const body = gz.instructionsSlice(); |
| 9981 | try gz.astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Block).Struct.fields.len + body.len); | 10019 | const body_len = astgen.countBodyLenAfterFixups(body); |
| 9982 | const zir_datas = gz.astgen.instructions.items(.data); | 10020 | try astgen.extra.ensureUnusedCapacity( |
| 9983 | zir_datas[inst].bool_br.payload_index = gz.astgen.addExtraAssumeCapacity( | 10021 | gpa, |
| 9984 | Zir.Inst.Block{ .body_len = @intCast(u32, body.len) }, | 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 | gz.unstack(); | 10029 | gz.unstack(); |
| 9988 | } | 10030 | } |
| 9989 | | 10031 | |
| 9990 | /// Assumes nothing stacked on `gz`. Unstacks `gz`. | 10032 | /// Assumes nothing stacked on `gz`. Unstacks `gz`. |
| 9991 | fn setBlockBody(gz: *GenZir, inst: Zir.Inst.Index) !void { | 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 | const body = gz.instructionsSlice(); | 10036 | const body = gz.instructionsSlice(); |
| 9994 | try gz.astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Block).Struct.fields.len + body.len); | 10037 | const body_len = astgen.countBodyLenAfterFixups(body); |
| 9995 | const zir_datas = gz.astgen.instructions.items(.data); | 10038 | try astgen.extra.ensureUnusedCapacity( |
| 9996 | zir_datas[inst].pl_node.payload_index = gz.astgen.addExtraAssumeCapacity( | 10039 | gpa, |
| 9997 | Zir.Inst.Block{ .body_len = @intCast(u32, body.len) }, | 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 | gz.unstack(); | 10047 | gz.unstack(); |
| 10001 | } | 10048 | } |
| 10002 | | 10049 | |
| 10003 | /// Assumes nothing stacked on `gz`. Unstacks `gz`. | 10050 | /// Assumes nothing stacked on `gz`. Unstacks `gz`. |
| 10004 | fn setTryBody(gz: *GenZir, inst: Zir.Inst.Index, operand: Zir.Inst.Ref) !void { | 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 | const body = gz.instructionsSlice(); | 10054 | const body = gz.instructionsSlice(); |
| 10007 | try gz.astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Try).Struct.fields.len + body.len); | 10055 | const body_len = astgen.countBodyLenAfterFixups(body); |
| 10008 | const zir_datas = gz.astgen.instructions.items(.data); | 10056 | try astgen.extra.ensureUnusedCapacity( |
| 10009 | zir_datas[inst].pl_node.payload_index = gz.astgen.addExtraAssumeCapacity( | 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 | Zir.Inst.Try{ | 10062 | Zir.Inst.Try{ |
| 10011 | .operand = operand, | 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 | gz.unstack(); | 10068 | gz.unstack(); |
| 10017 | } | 10069 | } |
| 10018 | | 10070 | |
| ... | @@ -10089,6 +10141,7 @@ const GenZir = struct { | ... | @@ -10089,6 +10141,7 @@ const GenZir = struct { |
| 10089 | if (args.ret_gz) |ret_gz| | 10141 | if (args.ret_gz) |ret_gz| |
| 10090 | ret_body = ret_gz.instructionsSlice(); | 10142 | ret_body = ret_gz.instructionsSlice(); |
| 10091 | } | 10143 | } |
| | 10144 | const body_len = astgen.countBodyLenAfterFixups(body); |
| 10092 | | 10145 | |
| 10093 | if (args.cc_ref != .none or args.lib_name != 0 or | 10146 | if (args.cc_ref != .none or args.lib_name != 0 or |
| 10094 | args.is_var_args or args.is_test or args.is_extern or | 10147 | args.is_var_args or args.is_test or args.is_extern or |
| ... | @@ -10114,13 +10167,13 @@ const GenZir = struct { | ... | @@ -10114,13 +10167,13 @@ const GenZir = struct { |
| 10114 | fancyFnExprExtraLen(section_body, args.section_ref) + | 10167 | fancyFnExprExtraLen(section_body, args.section_ref) + |
| 10115 | fancyFnExprExtraLen(cc_body, args.cc_ref) + | 10168 | fancyFnExprExtraLen(cc_body, args.cc_ref) + |
| 10116 | fancyFnExprExtraLen(ret_body, ret_ref) + | 10169 | fancyFnExprExtraLen(ret_body, ret_ref) + |
| 10117 | body.len + src_locs.len + | 10170 | body_len + src_locs.len + |
| 10118 | @boolToInt(args.lib_name != 0) + | 10171 | @boolToInt(args.lib_name != 0) + |
| 10119 | @boolToInt(args.noalias_bits != 0), | 10172 | @boolToInt(args.noalias_bits != 0), |
| 10120 | ); | 10173 | ); |
| 10121 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.FuncFancy{ | 10174 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.FuncFancy{ |
| 10122 | .param_block = args.param_block, | 10175 | .param_block = args.param_block, |
| 10123 | .body_len = @intCast(u32, body.len), | 10176 | .body_len = body_len, |
| 10124 | .bits = .{ | 10177 | .bits = .{ |
| 10125 | .is_var_args = args.is_var_args, | 10178 | .is_var_args = args.is_var_args, |
| 10126 | .is_inferred_error = args.is_inferred_error, | 10179 | .is_inferred_error = args.is_inferred_error, |
| ... | @@ -10187,7 +10240,7 @@ const GenZir = struct { | ... | @@ -10187,7 +10240,7 @@ const GenZir = struct { |
| 10187 | astgen.extra.appendAssumeCapacity(args.noalias_bits); | 10240 | astgen.extra.appendAssumeCapacity(args.noalias_bits); |
| 10188 | } | 10241 | } |
| 10189 | | 10242 | |
| 10190 | astgen.extra.appendSliceAssumeCapacity(body); | 10243 | astgen.appendBodyWithFixups(body); |
| 10191 | astgen.extra.appendSliceAssumeCapacity(src_locs); | 10244 | astgen.extra.appendSliceAssumeCapacity(src_locs); |
| 10192 | | 10245 | |
| 10193 | // Order is important when unstacking. | 10246 | // Order is important when unstacking. |
| ... | @@ -10214,9 +10267,9 @@ const GenZir = struct { | ... | @@ -10214,9 +10267,9 @@ const GenZir = struct { |
| 10214 | } else { | 10267 | } else { |
| 10215 | try astgen.extra.ensureUnusedCapacity( | 10268 | try astgen.extra.ensureUnusedCapacity( |
| 10216 | gpa, | 10269 | gpa, |
| 10217 | @typeInfo(Zir.Inst.Func).Struct.fields.len + | 10270 | @typeInfo(Zir.Inst.Func).Struct.fields.len + 1 + |
| 10218 | @maximum(ret_body.len, @boolToInt(ret_ref != .none)) + | 10271 | @maximum(ret_body.len, @boolToInt(ret_ref != .none)) + |
| 10219 | body.len + src_locs.len, | 10272 | body_len + src_locs.len, |
| 10220 | ); | 10273 | ); |
| 10221 | const ret_body_len = if (ret_body.len != 0) | 10274 | const ret_body_len = if (ret_body.len != 0) |
| 10222 | @intCast(u32, ret_body.len) | 10275 | @intCast(u32, ret_body.len) |
| ... | @@ -10226,7 +10279,7 @@ const GenZir = struct { | ... | @@ -10226,7 +10279,7 @@ const GenZir = struct { |
| 10226 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.Func{ | 10279 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.Func{ |
| 10227 | .param_block = args.param_block, | 10280 | .param_block = args.param_block, |
| 10228 | .ret_body_len = ret_body_len, | 10281 | .ret_body_len = ret_body_len, |
| 10229 | .body_len = @intCast(u32, body.len), | 10282 | .body_len = body_len, |
| 10230 | }); | 10283 | }); |
| 10231 | const zir_datas = astgen.instructions.items(.data); | 10284 | const zir_datas = astgen.instructions.items(.data); |
| 10232 | if (ret_body.len != 0) { | 10285 | if (ret_body.len != 0) { |
| ... | @@ -10235,7 +10288,7 @@ const GenZir = struct { | ... | @@ -10235,7 +10288,7 @@ const GenZir = struct { |
| 10235 | } else if (ret_ref != .none) { | 10288 | } else if (ret_ref != .none) { |
| 10236 | astgen.extra.appendAssumeCapacity(@enumToInt(ret_ref)); | 10289 | astgen.extra.appendAssumeCapacity(@enumToInt(ret_ref)); |
| 10237 | } | 10290 | } |
| 10238 | astgen.extra.appendSliceAssumeCapacity(body); | 10291 | astgen.appendBodyWithFixups(body); |
| 10239 | astgen.extra.appendSliceAssumeCapacity(src_locs); | 10292 | astgen.extra.appendSliceAssumeCapacity(src_locs); |
| 10240 | | 10293 | |
| 10241 | // Order is important when unstacking. | 10294 | // Order is important when unstacking. |
| ... | @@ -10593,6 +10646,26 @@ const GenZir = struct { | ... | @@ -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 | fn addStrTok( | 10669 | fn addStrTok( |
| 10597 | gz: *GenZir, | 10670 | gz: *GenZir, |
| 10598 | tag: Zir.Inst.Tag, | 10671 | tag: Zir.Inst.Tag, |
| ... | @@ -11337,3 +11410,42 @@ fn isInferred(astgen: *AstGen, ref: Zir.Inst.Ref) bool { | ... | @@ -11337,3 +11410,42 @@ fn isInferred(astgen: *AstGen, ref: Zir.Inst.Ref) bool { |
| 11337 | else => false, | 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 | } |