| ... | ... | @@ -41,6 +41,8 @@ fn_block: ?*GenZir = null, |
| 41 | 41 | /// Maps string table indexes to the first `@import` ZIR instruction |
| 42 | 42 | /// that uses this string as the operand. |
| 43 | 43 | imports: std.AutoArrayHashMapUnmanaged(u32, Ast.TokenIndex) = .{}, |
| 44 | /// Used for temporary storage when building payloads. |
| 45 | scratch: std.ArrayListUnmanaged(u32) = .{}, |
| 44 | 46 | |
| 45 | 47 | const InnerError = error{ OutOfMemory, AnalysisFail }; |
| 46 | 48 | |
| ... | ... | @@ -53,16 +55,30 @@ fn addExtra(astgen: *AstGen, extra: anytype) Allocator.Error!u32 { |
| 53 | 55 | fn addExtraAssumeCapacity(astgen: *AstGen, extra: anytype) u32 { |
| 54 | 56 | const fields = std.meta.fields(@TypeOf(extra)); |
| 55 | 57 | const result = @intCast(u32, astgen.extra.items.len); |
| 58 | astgen.extra.items.len += fields.len; |
| 59 | setExtra(astgen, result, extra); |
| 60 | return result; |
| 61 | } |
| 62 | |
| 63 | fn setExtra(astgen: *AstGen, index: usize, extra: anytype) void { |
| 64 | const fields = std.meta.fields(@TypeOf(extra)); |
| 65 | var i = index; |
| 56 | 66 | inline for (fields) |field| { |
| 57 | | astgen.extra.appendAssumeCapacity(switch (field.field_type) { |
| 67 | astgen.extra.items[i] = switch (field.field_type) { |
| 58 | 68 | u32 => @field(extra, field.name), |
| 59 | 69 | Zir.Inst.Ref => @enumToInt(@field(extra, field.name)), |
| 60 | 70 | i32 => @bitCast(u32, @field(extra, field.name)), |
| 61 | 71 | Zir.Inst.Call.Flags => @bitCast(u32, @field(extra, field.name)), |
| 62 | 72 | Zir.Inst.SwitchBlock.Bits => @bitCast(u32, @field(extra, field.name)), |
| 63 | 73 | else => @compileError("bad field type"), |
| 64 | | }); |
| 74 | }; |
| 75 | i += 1; |
| 65 | 76 | } |
| 77 | } |
| 78 | |
| 79 | fn reserveExtra(astgen: *AstGen, size: usize) Allocator.Error!u32 { |
| 80 | const result = @intCast(u32, astgen.extra.items.len); |
| 81 | try astgen.extra.resize(astgen.gpa, result + size); |
| 66 | 82 | return result; |
| 67 | 83 | } |
| 68 | 84 | |
| ... | ... | @@ -101,6 +117,7 @@ pub fn generate(gpa: *Allocator, tree: Ast) Allocator.Error!Zir { |
| 101 | 117 | |
| 102 | 118 | var top_scope: Scope.Top = .{}; |
| 103 | 119 | |
| 120 | var gz_instructions: std.ArrayListUnmanaged(Zir.Inst.Index) = .{}; |
| 104 | 121 | var gen_scope: GenZir = .{ |
| 105 | 122 | .force_comptime = true, |
| 106 | 123 | .in_defer = false, |
| ... | ... | @@ -109,8 +126,10 @@ pub fn generate(gpa: *Allocator, tree: Ast) Allocator.Error!Zir { |
| 109 | 126 | .decl_node_index = 0, |
| 110 | 127 | .decl_line = 0, |
| 111 | 128 | .astgen = &astgen, |
| 129 | .instructions = &gz_instructions, |
| 130 | .instructions_top = 0, |
| 112 | 131 | }; |
| 113 | | defer gen_scope.instructions.deinit(gpa); |
| 132 | defer gz_instructions.deinit(gpa); |
| 114 | 133 | |
| 115 | 134 | const container_decl: Ast.full.ContainerDecl = .{ |
| 116 | 135 | .layout_token = null, |
| ... | ... | @@ -184,6 +203,7 @@ pub fn deinit(astgen: *AstGen, gpa: *Allocator) void { |
| 184 | 203 | astgen.string_bytes.deinit(gpa); |
| 185 | 204 | astgen.compile_errors.deinit(gpa); |
| 186 | 205 | astgen.imports.deinit(gpa); |
| 206 | astgen.scratch.deinit(gpa); |
| 187 | 207 | } |
| 188 | 208 | |
| 189 | 209 | pub const ResultLoc = union(enum) { |
| ... | ... | @@ -1024,12 +1044,12 @@ fn suspendExpr( |
| 1024 | 1044 | } |
| 1025 | 1045 | assert(body_node != 0); |
| 1026 | 1046 | |
| 1027 | | const suspend_inst = try gz.addBlock(.suspend_block, node); |
| 1047 | const suspend_inst = try gz.makeBlockInst(.suspend_block, node); |
| 1028 | 1048 | try gz.instructions.append(gpa, suspend_inst); |
| 1029 | 1049 | |
| 1030 | 1050 | var suspend_scope = gz.makeSubBlock(scope); |
| 1031 | 1051 | suspend_scope.suspend_node = node; |
| 1032 | | defer suspend_scope.instructions.deinit(gpa); |
| 1052 | defer suspend_scope.unstack(); |
| 1033 | 1053 | |
| 1034 | 1054 | const body_result = try expr(&suspend_scope, &suspend_scope.base, .none, body_node); |
| 1035 | 1055 | if (!gz.refIsNoReturn(body_result)) { |
| ... | ... | @@ -1084,7 +1104,6 @@ fn fnProtoExpr( |
| 1084 | 1104 | fn_proto: Ast.full.FnProto, |
| 1085 | 1105 | ) InnerError!Zir.Inst.Ref { |
| 1086 | 1106 | const astgen = gz.astgen; |
| 1087 | | const gpa = astgen.gpa; |
| 1088 | 1107 | const tree = astgen.tree; |
| 1089 | 1108 | const token_tags = tree.tokens.items(.tag); |
| 1090 | 1109 | |
| ... | ... | @@ -1130,14 +1149,14 @@ fn fnProtoExpr( |
| 1130 | 1149 | const param_type_node = param.type_expr; |
| 1131 | 1150 | assert(param_type_node != 0); |
| 1132 | 1151 | var param_gz = gz.makeSubBlock(scope); |
| 1133 | | defer param_gz.instructions.deinit(gpa); |
| 1152 | defer param_gz.unstack(); |
| 1134 | 1153 | const param_type = try expr(&param_gz, scope, coerced_type_rl, param_type_node); |
| 1135 | 1154 | const param_inst_expected = @intCast(u32, astgen.instructions.len + 1); |
| 1136 | 1155 | _ = try param_gz.addBreak(.break_inline, param_inst_expected, param_type); |
| 1137 | 1156 | const main_tokens = tree.nodes.items(.main_token); |
| 1138 | 1157 | const name_token = param.name_token orelse main_tokens[param_type_node]; |
| 1139 | 1158 | const tag: Zir.Inst.Tag = if (is_comptime) .param_comptime else .param; |
| 1140 | | const param_inst = try gz.addParam(tag, name_token, param_name, param_gz.instructions.items); |
| 1159 | const param_inst = try gz.addParam(&param_gz, tag, name_token, param_name); |
| 1141 | 1160 | assert(param_inst_expected == param_inst); |
| 1142 | 1161 | } |
| 1143 | 1162 | } |
| ... | ... | @@ -1172,16 +1191,16 @@ fn fnProtoExpr( |
| 1172 | 1191 | return astgen.failTok(maybe_bang, "function prototype may not have inferred error set", .{}); |
| 1173 | 1192 | } |
| 1174 | 1193 | var ret_gz = gz.makeSubBlock(scope); |
| 1175 | | defer ret_gz.instructions.deinit(gpa); |
| 1194 | defer ret_gz.unstack(); |
| 1176 | 1195 | const ret_ty = try expr(&ret_gz, scope, coerced_type_rl, fn_proto.ast.return_type); |
| 1177 | 1196 | const ret_br = try ret_gz.addBreak(.break_inline, 0, ret_ty); |
| 1178 | 1197 | |
| 1179 | 1198 | const result = try gz.addFunc(.{ |
| 1180 | 1199 | .src_node = fn_proto.ast.proto_node, |
| 1181 | 1200 | .param_block = 0, |
| 1182 | | .ret_ty = ret_gz.instructions.items, |
| 1201 | .ret_gz = &ret_gz, |
| 1183 | 1202 | .ret_br = ret_br, |
| 1184 | | .body = &[0]Zir.Inst.Index{}, |
| 1203 | .body_gz = null, |
| 1185 | 1204 | .cc = cc, |
| 1186 | 1205 | .align_inst = align_inst, |
| 1187 | 1206 | .lib_name = 0, |
| ... | ... | @@ -1307,18 +1326,18 @@ fn arrayInitExprRlNone( |
| 1307 | 1326 | tag: Zir.Inst.Tag, |
| 1308 | 1327 | ) InnerError!Zir.Inst.Ref { |
| 1309 | 1328 | const astgen = gz.astgen; |
| 1310 | | const gpa = astgen.gpa; |
| 1311 | | const elem_list = try gpa.alloc(Zir.Inst.Ref, elements.len); |
| 1312 | | defer gpa.free(elem_list); |
| 1313 | 1329 | |
| 1314 | | for (elements) |elem_init, i| { |
| 1315 | | elem_list[i] = try expr(gz, scope, .none, elem_init); |
| 1316 | | } |
| 1317 | | const init_inst = try gz.addPlNode(tag, node, Zir.Inst.MultiOp{ |
| 1318 | | .operands_len = @intCast(u32, elem_list.len), |
| 1330 | const payload_index = try addExtra(astgen, Zir.Inst.MultiOp{ |
| 1331 | .operands_len = @intCast(u32, elements.len), |
| 1319 | 1332 | }); |
| 1320 | | try astgen.appendRefs(elem_list); |
| 1321 | | return init_inst; |
| 1333 | var extra_index = try reserveExtra(astgen, elements.len); |
| 1334 | |
| 1335 | for (elements) |elem_init| { |
| 1336 | const elem_ref = try expr(gz, scope, .none, elem_init); |
| 1337 | astgen.extra.items[extra_index] = @enumToInt(elem_ref); |
| 1338 | extra_index += 1; |
| 1339 | } |
| 1340 | return try gz.addPlNodePayloadIndex(tag, node, payload_index); |
| 1322 | 1341 | } |
| 1323 | 1342 | |
| 1324 | 1343 | fn arrayInitExprRlTy( |
| ... | ... | @@ -1330,21 +1349,19 @@ fn arrayInitExprRlTy( |
| 1330 | 1349 | tag: Zir.Inst.Tag, |
| 1331 | 1350 | ) InnerError!Zir.Inst.Ref { |
| 1332 | 1351 | const astgen = gz.astgen; |
| 1333 | | const gpa = astgen.gpa; |
| 1334 | 1352 | |
| 1335 | | const elem_list = try gpa.alloc(Zir.Inst.Ref, elements.len); |
| 1336 | | defer gpa.free(elem_list); |
| 1353 | const payload_index = try addExtra(astgen, Zir.Inst.MultiOp{ |
| 1354 | .operands_len = @intCast(u32, elements.len), |
| 1355 | }); |
| 1356 | var extra_index = try reserveExtra(astgen, elements.len); |
| 1337 | 1357 | |
| 1338 | 1358 | const elem_rl: ResultLoc = .{ .ty = elem_ty_inst }; |
| 1339 | | |
| 1340 | | for (elements) |elem_init, i| { |
| 1341 | | elem_list[i] = try expr(gz, scope, elem_rl, elem_init); |
| 1359 | for (elements) |elem_init| { |
| 1360 | const elem_ref = try expr(gz, scope, elem_rl, elem_init); |
| 1361 | astgen.extra.items[extra_index] = @enumToInt(elem_ref); |
| 1362 | extra_index += 1; |
| 1342 | 1363 | } |
| 1343 | | const init_inst = try gz.addPlNode(tag, node, Zir.Inst.MultiOp{ |
| 1344 | | .operands_len = @intCast(u32, elem_list.len), |
| 1345 | | }); |
| 1346 | | try astgen.appendRefs(elem_list); |
| 1347 | | return init_inst; |
| 1364 | return try gz.addPlNodePayloadIndex(tag, node, payload_index); |
| 1348 | 1365 | } |
| 1349 | 1366 | |
| 1350 | 1367 | fn arrayInitExprRlPtr( |
| ... | ... | @@ -1361,7 +1378,7 @@ fn arrayInitExprRlPtr( |
| 1361 | 1378 | } |
| 1362 | 1379 | |
| 1363 | 1380 | var as_scope = try gz.makeCoercionScope(scope, array_ty, result_ptr); |
| 1364 | | defer as_scope.instructions.deinit(gz.astgen.gpa); |
| 1381 | defer as_scope.unstack(); |
| 1365 | 1382 | |
| 1366 | 1383 | const result = try arrayInitExprRlPtrInner(&as_scope, scope, node, as_scope.rl_ptr, elements); |
| 1367 | 1384 | return as_scope.finishCoercion(gz, rl, node, result, array_ty); |
| ... | ... | @@ -1375,23 +1392,22 @@ fn arrayInitExprRlPtrInner( |
| 1375 | 1392 | elements: []const Ast.Node.Index, |
| 1376 | 1393 | ) InnerError!Zir.Inst.Ref { |
| 1377 | 1394 | const astgen = gz.astgen; |
| 1378 | | const gpa = astgen.gpa; |
| 1379 | 1395 | |
| 1380 | | const elem_ptr_list = try gpa.alloc(Zir.Inst.Index, elements.len); |
| 1381 | | defer gpa.free(elem_ptr_list); |
| 1396 | const payload_index = try addExtra(astgen, Zir.Inst.Block{ |
| 1397 | .body_len = @intCast(u32, elements.len), |
| 1398 | }); |
| 1399 | var extra_index = try reserveExtra(astgen, elements.len); |
| 1382 | 1400 | |
| 1383 | 1401 | for (elements) |elem_init, i| { |
| 1384 | 1402 | const elem_ptr = try gz.addPlNode(.elem_ptr_imm, elem_init, Zir.Inst.ElemPtrImm{ |
| 1385 | 1403 | .ptr = result_ptr, |
| 1386 | 1404 | .index = @intCast(u32, i), |
| 1387 | 1405 | }); |
| 1388 | | elem_ptr_list[i] = refToIndex(elem_ptr).?; |
| 1406 | astgen.extra.items[extra_index] = refToIndex(elem_ptr).?; |
| 1407 | extra_index += 1; |
| 1389 | 1408 | _ = try expr(gz, scope, .{ .ptr = elem_ptr }, elem_init); |
| 1390 | 1409 | } |
| 1391 | | _ = try gz.addPlNode(.validate_array_init, node, Zir.Inst.Block{ |
| 1392 | | .body_len = @intCast(u32, elem_ptr_list.len), |
| 1393 | | }); |
| 1394 | | try astgen.extra.appendSlice(gpa, elem_ptr_list); |
| 1410 | _ = try gz.addPlNodePayloadIndex(.validate_array_init, node, payload_index); |
| 1395 | 1411 | return .void_value; |
| 1396 | 1412 | } |
| 1397 | 1413 | |
| ... | ... | @@ -1505,30 +1521,25 @@ fn structInitExprRlNone( |
| 1505 | 1521 | tag: Zir.Inst.Tag, |
| 1506 | 1522 | ) InnerError!Zir.Inst.Ref { |
| 1507 | 1523 | const astgen = gz.astgen; |
| 1508 | | const gpa = astgen.gpa; |
| 1509 | 1524 | const tree = astgen.tree; |
| 1510 | 1525 | |
| 1511 | | const fields_list = try gpa.alloc(Zir.Inst.StructInitAnon.Item, struct_init.ast.fields.len); |
| 1512 | | defer gpa.free(fields_list); |
| 1526 | const payload_index = try addExtra(astgen, Zir.Inst.StructInitAnon{ |
| 1527 | .fields_len = @intCast(u32, struct_init.ast.fields.len), |
| 1528 | }); |
| 1529 | const field_size = @typeInfo(Zir.Inst.StructInitAnon.Item).Struct.fields.len; |
| 1530 | var extra_index: usize = try reserveExtra(astgen, struct_init.ast.fields.len * field_size); |
| 1513 | 1531 | |
| 1514 | | for (struct_init.ast.fields) |field_init, i| { |
| 1532 | for (struct_init.ast.fields) |field_init| { |
| 1515 | 1533 | const name_token = tree.firstToken(field_init) - 2; |
| 1516 | 1534 | const str_index = try astgen.identAsString(name_token); |
| 1517 | | |
| 1518 | | fields_list[i] = .{ |
| 1535 | setExtra(astgen, extra_index, Zir.Inst.StructInitAnon.Item{ |
| 1519 | 1536 | .field_name = str_index, |
| 1520 | 1537 | .init = try expr(gz, scope, .none, field_init), |
| 1521 | | }; |
| 1522 | | } |
| 1523 | | const init_inst = try gz.addPlNode(tag, node, Zir.Inst.StructInitAnon{ |
| 1524 | | .fields_len = @intCast(u32, fields_list.len), |
| 1525 | | }); |
| 1526 | | try astgen.extra.ensureUnusedCapacity(gpa, fields_list.len * |
| 1527 | | @typeInfo(Zir.Inst.StructInitAnon.Item).Struct.fields.len); |
| 1528 | | for (fields_list) |field| { |
| 1529 | | _ = gz.astgen.addExtraAssumeCapacity(field); |
| 1538 | }); |
| 1539 | extra_index += field_size; |
| 1530 | 1540 | } |
| 1531 | | return init_inst; |
| 1541 | |
| 1542 | return try gz.addPlNodePayloadIndex(tag, node, payload_index); |
| 1532 | 1543 | } |
| 1533 | 1544 | |
| 1534 | 1545 | fn structInitExprRlPtr( |
| ... | ... | @@ -1545,7 +1556,7 @@ fn structInitExprRlPtr( |
| 1545 | 1556 | const ty_inst = try typeExpr(gz, scope, struct_init.ast.type_expr); |
| 1546 | 1557 | |
| 1547 | 1558 | var as_scope = try gz.makeCoercionScope(scope, ty_inst, result_ptr); |
| 1548 | | defer as_scope.instructions.deinit(gz.astgen.gpa); |
| 1559 | defer as_scope.unstack(); |
| 1549 | 1560 | |
| 1550 | 1561 | const result = try structInitExprRlPtrInner(&as_scope, scope, node, struct_init, as_scope.rl_ptr); |
| 1551 | 1562 | return as_scope.finishCoercion(gz, rl, node, result, ty_inst); |
| ... | ... | @@ -1559,26 +1570,26 @@ fn structInitExprRlPtrInner( |
| 1559 | 1570 | result_ptr: Zir.Inst.Ref, |
| 1560 | 1571 | ) InnerError!Zir.Inst.Ref { |
| 1561 | 1572 | const astgen = gz.astgen; |
| 1562 | | const gpa = astgen.gpa; |
| 1563 | 1573 | const tree = astgen.tree; |
| 1564 | 1574 | |
| 1565 | | const field_ptr_list = try gpa.alloc(Zir.Inst.Index, struct_init.ast.fields.len); |
| 1566 | | defer gpa.free(field_ptr_list); |
| 1575 | const payload_index = try addExtra(astgen, Zir.Inst.Block{ |
| 1576 | .body_len = @intCast(u32, struct_init.ast.fields.len), |
| 1577 | }); |
| 1578 | var extra_index = try reserveExtra(astgen, struct_init.ast.fields.len); |
| 1567 | 1579 | |
| 1568 | | for (struct_init.ast.fields) |field_init, i| { |
| 1580 | for (struct_init.ast.fields) |field_init| { |
| 1569 | 1581 | const name_token = tree.firstToken(field_init) - 2; |
| 1570 | 1582 | const str_index = try astgen.identAsString(name_token); |
| 1571 | 1583 | const field_ptr = try gz.addPlNode(.field_ptr, field_init, Zir.Inst.Field{ |
| 1572 | 1584 | .lhs = result_ptr, |
| 1573 | 1585 | .field_name_start = str_index, |
| 1574 | 1586 | }); |
| 1575 | | field_ptr_list[i] = refToIndex(field_ptr).?; |
| 1587 | astgen.extra.items[extra_index] = refToIndex(field_ptr).?; |
| 1588 | extra_index += 1; |
| 1576 | 1589 | _ = try expr(gz, scope, .{ .ptr = field_ptr }, field_init); |
| 1577 | 1590 | } |
| 1578 | | _ = try gz.addPlNode(.validate_struct_init, node, Zir.Inst.Block{ |
| 1579 | | .body_len = @intCast(u32, field_ptr_list.len), |
| 1580 | | }); |
| 1581 | | try astgen.extra.appendSlice(gpa, field_ptr_list); |
| 1591 | |
| 1592 | _ = try gz.addPlNodePayloadIndex(.validate_struct_init, node, payload_index); |
| 1582 | 1593 | return Zir.Inst.Ref.void_value; |
| 1583 | 1594 | } |
| 1584 | 1595 | |
| ... | ... | @@ -1591,34 +1602,29 @@ fn structInitExprRlTy( |
| 1591 | 1602 | tag: Zir.Inst.Tag, |
| 1592 | 1603 | ) InnerError!Zir.Inst.Ref { |
| 1593 | 1604 | const astgen = gz.astgen; |
| 1594 | | const gpa = astgen.gpa; |
| 1595 | 1605 | const tree = astgen.tree; |
| 1596 | 1606 | |
| 1597 | | const fields_list = try gpa.alloc(Zir.Inst.StructInit.Item, struct_init.ast.fields.len); |
| 1598 | | defer gpa.free(fields_list); |
| 1607 | const payload_index = try addExtra(astgen, Zir.Inst.StructInit{ |
| 1608 | .fields_len = @intCast(u32, struct_init.ast.fields.len), |
| 1609 | }); |
| 1610 | const field_size = @typeInfo(Zir.Inst.StructInit.Item).Struct.fields.len; |
| 1611 | var extra_index: usize = try reserveExtra(astgen, struct_init.ast.fields.len * field_size); |
| 1599 | 1612 | |
| 1600 | | for (struct_init.ast.fields) |field_init, i| { |
| 1613 | for (struct_init.ast.fields) |field_init| { |
| 1601 | 1614 | const name_token = tree.firstToken(field_init) - 2; |
| 1602 | 1615 | const str_index = try astgen.identAsString(name_token); |
| 1603 | | |
| 1604 | 1616 | const field_ty_inst = try gz.addPlNode(.field_type, field_init, Zir.Inst.FieldType{ |
| 1605 | 1617 | .container_type = ty_inst, |
| 1606 | 1618 | .name_start = str_index, |
| 1607 | 1619 | }); |
| 1608 | | fields_list[i] = .{ |
| 1620 | setExtra(astgen, extra_index, Zir.Inst.StructInit.Item{ |
| 1609 | 1621 | .field_type = refToIndex(field_ty_inst).?, |
| 1610 | 1622 | .init = try expr(gz, scope, .{ .ty = field_ty_inst }, field_init), |
| 1611 | | }; |
| 1612 | | } |
| 1613 | | const init_inst = try gz.addPlNode(tag, node, Zir.Inst.StructInit{ |
| 1614 | | .fields_len = @intCast(u32, fields_list.len), |
| 1615 | | }); |
| 1616 | | try astgen.extra.ensureUnusedCapacity(gpa, fields_list.len * |
| 1617 | | @typeInfo(Zir.Inst.StructInit.Item).Struct.fields.len); |
| 1618 | | for (fields_list) |field| { |
| 1619 | | _ = gz.astgen.addExtraAssumeCapacity(field); |
| 1623 | }); |
| 1624 | extra_index += field_size; |
| 1620 | 1625 | } |
| 1621 | | return init_inst; |
| 1626 | |
| 1627 | return try gz.addPlNodePayloadIndex(tag, node, payload_index); |
| 1622 | 1628 | } |
| 1623 | 1629 | |
| 1624 | 1630 | /// This calls expr in a comptime scope, and is intended to be called as a helper function. |
| ... | ... | @@ -1871,7 +1877,7 @@ fn labeledBlockExpr( |
| 1871 | 1877 | |
| 1872 | 1878 | // Reserve the Block ZIR instruction index so that we can put it into the GenZir struct |
| 1873 | 1879 | // so that break statements can reference it. |
| 1874 | | const block_inst = try gz.addBlock(zir_tag, block_node); |
| 1880 | const block_inst = try gz.makeBlockInst(zir_tag, block_node); |
| 1875 | 1881 | try gz.instructions.append(astgen.gpa, block_inst); |
| 1876 | 1882 | |
| 1877 | 1883 | var block_scope = gz.makeSubBlock(parent_scope); |
| ... | ... | @@ -1880,7 +1886,7 @@ fn labeledBlockExpr( |
| 1880 | 1886 | .block_inst = block_inst, |
| 1881 | 1887 | }; |
| 1882 | 1888 | block_scope.setBreakResultLoc(rl); |
| 1883 | | defer block_scope.instructions.deinit(astgen.gpa); |
| 1889 | defer block_scope.unstack(); |
| 1884 | 1890 | defer block_scope.labeled_breaks.deinit(astgen.gpa); |
| 1885 | 1891 | defer block_scope.labeled_store_to_block_ptr_list.deinit(astgen.gpa); |
| 1886 | 1892 | |
| ... | ... | @@ -2485,7 +2491,6 @@ fn varDecl( |
| 2485 | 2491 | ) InnerError!*Scope { |
| 2486 | 2492 | try emitDbgNode(gz, node); |
| 2487 | 2493 | const astgen = gz.astgen; |
| 2488 | | const gpa = astgen.gpa; |
| 2489 | 2494 | const tree = astgen.tree; |
| 2490 | 2495 | const token_tags = tree.tokens.items(.tag); |
| 2491 | 2496 | const main_tokens = tree.nodes.items(.main_token); |
| ... | ... | @@ -2546,7 +2551,9 @@ fn varDecl( |
| 2546 | 2551 | // Detect whether the initialization expression actually uses the |
| 2547 | 2552 | // result location pointer. |
| 2548 | 2553 | var init_scope = gz.makeSubBlock(scope); |
| 2549 | | defer init_scope.instructions.deinit(gpa); |
| 2554 | // we may add more instructions to gz before stacking init_scope |
| 2555 | init_scope.instructions_top = GenZir.unstacked_top; |
| 2556 | defer init_scope.unstack(); |
| 2550 | 2557 | |
| 2551 | 2558 | var resolve_inferred_alloc: Zir.Inst.Ref = .none; |
| 2552 | 2559 | var opt_type_inst: Zir.Inst.Ref = .none; |
| ... | ... | @@ -2554,6 +2561,7 @@ fn varDecl( |
| 2554 | 2561 | const type_inst = try typeExpr(gz, &init_scope.base, var_decl.ast.type_node); |
| 2555 | 2562 | opt_type_inst = type_inst; |
| 2556 | 2563 | if (align_inst == .none) { |
| 2564 | init_scope.instructions_top = gz.instructions.items.len; |
| 2557 | 2565 | init_scope.rl_ptr = try init_scope.addUnNode(.alloc, type_inst, node); |
| 2558 | 2566 | } else { |
| 2559 | 2567 | init_scope.rl_ptr = try gz.addAllocExtended(.{ |
| ... | ... | @@ -2563,19 +2571,24 @@ fn varDecl( |
| 2563 | 2571 | .is_const = true, |
| 2564 | 2572 | .is_comptime = false, |
| 2565 | 2573 | }); |
| 2574 | init_scope.instructions_top = gz.instructions.items.len; |
| 2566 | 2575 | } |
| 2567 | 2576 | init_scope.rl_ty_inst = type_inst; |
| 2568 | 2577 | } else { |
| 2569 | | const alloc = if (align_inst == .none) |
| 2570 | | try init_scope.addNode(.alloc_inferred, node) |
| 2571 | | else |
| 2572 | | try gz.addAllocExtended(.{ |
| 2578 | const alloc = if (align_inst == .none) alloc: { |
| 2579 | init_scope.instructions_top = gz.instructions.items.len; |
| 2580 | break :alloc try init_scope.addNode(.alloc_inferred, node); |
| 2581 | } else alloc: { |
| 2582 | const ref = try gz.addAllocExtended(.{ |
| 2573 | 2583 | .node = node, |
| 2574 | 2584 | .type_inst = .none, |
| 2575 | 2585 | .align_inst = align_inst, |
| 2576 | 2586 | .is_const = true, |
| 2577 | 2587 | .is_comptime = false, |
| 2578 | 2588 | }); |
| 2589 | init_scope.instructions_top = gz.instructions.items.len; |
| 2590 | break :alloc ref; |
| 2591 | }; |
| 2579 | 2592 | resolve_inferred_alloc = alloc; |
| 2580 | 2593 | init_scope.rl_ptr = alloc; |
| 2581 | 2594 | } |
| ... | ... | @@ -2585,20 +2598,24 @@ fn varDecl( |
| 2585 | 2598 | const zir_tags = astgen.instructions.items(.tag); |
| 2586 | 2599 | const zir_datas = astgen.instructions.items(.data); |
| 2587 | 2600 | |
| 2588 | | const parent_zir = &gz.instructions; |
| 2589 | 2601 | if (align_inst == .none and init_scope.rvalue_rl_count == 1) { |
| 2590 | 2602 | // Result location pointer not used. We don't need an alloc for this |
| 2591 | 2603 | // const local, and type inference becomes trivial. |
| 2592 | | // Move the init_scope instructions into the parent scope, eliding |
| 2593 | | // the alloc instruction and the store_to_block_ptr instruction. |
| 2594 | | try parent_zir.ensureUnusedCapacity(gpa, init_scope.instructions.items.len); |
| 2595 | | for (init_scope.instructions.items) |src_inst| { |
| 2604 | // Implicitly move the init_scope instructions into the parent scope, |
| 2605 | // then elide the alloc instruction and the store_to_block_ptr instruction. |
| 2606 | var src = init_scope.instructions_top; |
| 2607 | var dst = src; |
| 2608 | init_scope.instructions_top = GenZir.unstacked_top; |
| 2609 | while (src < gz.instructions.items.len) : (src += 1) { |
| 2610 | const src_inst = gz.instructions.items[src]; |
| 2596 | 2611 | if (indexToRef(src_inst) == init_scope.rl_ptr) continue; |
| 2597 | 2612 | if (zir_tags[src_inst] == .store_to_block_ptr) { |
| 2598 | 2613 | if (zir_datas[src_inst].bin.lhs == init_scope.rl_ptr) continue; |
| 2599 | 2614 | } |
| 2600 | | parent_zir.appendAssumeCapacity(src_inst); |
| 2615 | gz.instructions.items[dst] = src_inst; |
| 2616 | dst += 1; |
| 2601 | 2617 | } |
| 2618 | gz.instructions.items.len = dst; |
| 2602 | 2619 | |
| 2603 | 2620 | const sub_scope = try block_arena.create(Scope.LocalVal); |
| 2604 | 2621 | sub_scope.* = .{ |
| ... | ... | @@ -2613,11 +2630,13 @@ fn varDecl( |
| 2613 | 2630 | } |
| 2614 | 2631 | // The initialization expression took advantage of the result location |
| 2615 | 2632 | // of the const local. In this case we will create an alloc and a LocalPtr for it. |
| 2616 | | // Move the init_scope instructions into the parent scope, swapping |
| 2633 | // Implicitly move the init_scope instructions into the parent scope, then swap |
| 2617 | 2634 | // store_to_block_ptr for store_to_inferred_ptr. |
| 2618 | | const expected_len = parent_zir.items.len + init_scope.instructions.items.len; |
| 2619 | | try parent_zir.ensureTotalCapacity(gpa, expected_len); |
| 2620 | | for (init_scope.instructions.items) |src_inst| { |
| 2635 | |
| 2636 | var src = init_scope.instructions_top; |
| 2637 | init_scope.instructions_top = GenZir.unstacked_top; |
| 2638 | while (src < gz.instructions.items.len) : (src += 1) { |
| 2639 | const src_inst = gz.instructions.items[src]; |
| 2621 | 2640 | if (zir_tags[src_inst] == .store_to_block_ptr) { |
| 2622 | 2641 | if (zir_datas[src_inst].bin.lhs == init_scope.rl_ptr) { |
| 2623 | 2642 | if (var_decl.ast.type_node != 0) { |
| ... | ... | @@ -2627,9 +2646,7 @@ fn varDecl( |
| 2627 | 2646 | } |
| 2628 | 2647 | } |
| 2629 | 2648 | } |
| 2630 | | parent_zir.appendAssumeCapacity(src_inst); |
| 2631 | 2649 | } |
| 2632 | | assert(parent_zir.items.len == expected_len); |
| 2633 | 2650 | if (resolve_inferred_alloc != .none) { |
| 2634 | 2651 | _ = try gz.addUnNode(.resolve_inferred_alloc, resolve_inferred_alloc, node); |
| 2635 | 2652 | } |
| ... | ... | @@ -2994,38 +3011,116 @@ fn arrayTypeSentinel(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.I |
| 2994 | 3011 | return rvalue(gz, rl, result, node); |
| 2995 | 3012 | } |
| 2996 | 3013 | |
| 2997 | | const WipDecls = struct { |
| 2998 | | decl_index: usize = 0, |
| 2999 | | cur_bit_bag: u32 = 0, |
| 3000 | | bit_bag: ArrayListUnmanaged(u32) = .{}, |
| 3001 | | payload: ArrayListUnmanaged(u32) = .{}, |
| 3014 | const WipMembers = struct { |
| 3015 | payload: *ArrayListUnmanaged(u32), |
| 3016 | payload_top: usize, |
| 3017 | decls_start: u32, |
| 3018 | decls_end: u32, |
| 3019 | field_bits_start: u32, |
| 3020 | fields_start: u32, |
| 3021 | fields_end: u32, |
| 3022 | decl_index: u32 = 0, |
| 3023 | field_index: u32 = 0, |
| 3024 | |
| 3025 | const Self = @This(); |
| 3026 | /// struct, union, enum, and opaque decls all use same 4 bits per decl |
| 3027 | const bits_per_decl = 4; |
| 3028 | const decls_per_u32 = 32 / bits_per_decl; |
| 3029 | /// struct, union, enum, and opaque decls all have maximum size of 10 u32 slots |
| 3030 | /// (4 for src_hash + line + name + value + align + link_section + address_space) |
| 3031 | const max_decl_size = 10; |
| 3032 | |
| 3033 | pub fn init(gpa: *Allocator, payload: *ArrayListUnmanaged(u32), decl_count: u32, field_count: u32, comptime bits_per_field: u32, comptime max_field_size: u32) Allocator.Error!Self { |
| 3034 | const payload_top = @intCast(u32, payload.items.len); |
| 3035 | const decls_start = payload_top + (decl_count + decls_per_u32 - 1) / decls_per_u32; |
| 3036 | const field_bits_start = decls_start + decl_count * max_decl_size; |
| 3037 | const fields_start = field_bits_start + if (bits_per_field > 0) blk: { |
| 3038 | const fields_per_u32 = 32 / bits_per_field; |
| 3039 | break :blk (field_count + fields_per_u32 - 1) / fields_per_u32; |
| 3040 | } else 0; |
| 3041 | const payload_end = fields_start + field_count * max_field_size; |
| 3042 | try payload.resize(gpa, payload_end); |
| 3043 | return Self{ |
| 3044 | .payload = payload, |
| 3045 | .payload_top = payload_top, |
| 3046 | .decls_start = decls_start, |
| 3047 | .field_bits_start = field_bits_start, |
| 3048 | .fields_start = fields_start, |
| 3049 | .decls_end = decls_start, |
| 3050 | .fields_end = fields_start, |
| 3051 | }; |
| 3052 | } |
| 3002 | 3053 | |
| 3003 | | const bits_per_field = 4; |
| 3004 | | const fields_per_u32 = 32 / bits_per_field; |
| 3005 | | |
| 3006 | | fn next( |
| 3007 | | wip_decls: *WipDecls, |
| 3008 | | gpa: *Allocator, |
| 3009 | | is_pub: bool, |
| 3010 | | is_export: bool, |
| 3011 | | has_align: bool, |
| 3012 | | has_section_or_addrspace: bool, |
| 3013 | | ) Allocator.Error!void { |
| 3014 | | if (wip_decls.decl_index % fields_per_u32 == 0 and wip_decls.decl_index != 0) { |
| 3015 | | try wip_decls.bit_bag.append(gpa, wip_decls.cur_bit_bag); |
| 3016 | | wip_decls.cur_bit_bag = 0; |
| 3017 | | } |
| 3018 | | wip_decls.cur_bit_bag = (wip_decls.cur_bit_bag >> bits_per_field) | |
| 3054 | pub fn nextDecl(self: *Self, is_pub: bool, is_export: bool, has_align: bool, has_section_or_addrspace: bool) void { |
| 3055 | const index = self.payload_top + self.decl_index / decls_per_u32; |
| 3056 | assert(index < self.decls_start); |
| 3057 | const bit_bag: u32 = if (self.decl_index % decls_per_u32 == 0) 0 else self.payload.items[index]; |
| 3058 | self.payload.items[index] = (bit_bag >> bits_per_decl) | |
| 3019 | 3059 | (@as(u32, @boolToInt(is_pub)) << 28) | |
| 3020 | 3060 | (@as(u32, @boolToInt(is_export)) << 29) | |
| 3021 | 3061 | (@as(u32, @boolToInt(has_align)) << 30) | |
| 3022 | 3062 | (@as(u32, @boolToInt(has_section_or_addrspace)) << 31); |
| 3023 | | wip_decls.decl_index += 1; |
| 3063 | self.decl_index += 1; |
| 3064 | } |
| 3065 | |
| 3066 | pub fn nextField(self: *Self, comptime bits_per_field: u32, bits: [bits_per_field]bool) void { |
| 3067 | const fields_per_u32 = 32 / bits_per_field; |
| 3068 | const index = self.field_bits_start + self.field_index / fields_per_u32; |
| 3069 | assert(index < self.fields_start); |
| 3070 | var bit_bag: u32 = if (self.field_index % fields_per_u32 == 0) 0 else self.payload.items[index]; |
| 3071 | bit_bag >>= bits_per_field; |
| 3072 | comptime var i = 0; |
| 3073 | inline while (i < bits_per_field) : (i += 1) { |
| 3074 | bit_bag |= @as(u32, @boolToInt(bits[i])) << (32 - bits_per_field + i); |
| 3075 | } |
| 3076 | self.payload.items[index] = bit_bag; |
| 3077 | self.field_index += 1; |
| 3078 | } |
| 3079 | |
| 3080 | pub fn appendToDecl(self: *Self, data: u32) void { |
| 3081 | assert(self.decls_end < self.field_bits_start); |
| 3082 | self.payload.items[self.decls_end] = data; |
| 3083 | self.decls_end += 1; |
| 3084 | } |
| 3085 | |
| 3086 | pub fn appendToDeclSlice(self: *Self, data: []const u32) void { |
| 3087 | assert(self.decls_end + data.len <= self.field_bits_start); |
| 3088 | mem.copy(u32, self.payload.items[self.decls_end..], data); |
| 3089 | self.decls_end += @intCast(u32, data.len); |
| 3090 | } |
| 3091 | |
| 3092 | pub fn appendToField(self: *Self, data: u32) void { |
| 3093 | assert(self.fields_end < self.payload.items.len); |
| 3094 | self.payload.items[self.fields_end] = data; |
| 3095 | self.fields_end += 1; |
| 3096 | } |
| 3097 | |
| 3098 | pub fn finishBits(self: *Self, comptime bits_per_field: u32) void { |
| 3099 | const empty_decl_slots = decls_per_u32 - (self.decl_index % decls_per_u32); |
| 3100 | if (self.decl_index > 0 and empty_decl_slots < decls_per_u32) { |
| 3101 | const index = self.payload_top + self.decl_index / decls_per_u32; |
| 3102 | self.payload.items[index] >>= @intCast(u5, empty_decl_slots * bits_per_decl); |
| 3103 | } |
| 3104 | if (bits_per_field > 0) { |
| 3105 | const fields_per_u32 = 32 / bits_per_field; |
| 3106 | const empty_field_slots = fields_per_u32 - (self.field_index % fields_per_u32); |
| 3107 | if (self.field_index > 0 and empty_field_slots < fields_per_u32) { |
| 3108 | const index = self.field_bits_start + self.field_index / fields_per_u32; |
| 3109 | self.payload.items[index] >>= @intCast(u5, empty_field_slots * bits_per_field); |
| 3110 | } |
| 3111 | } |
| 3112 | } |
| 3113 | |
| 3114 | pub fn declsSlice(self: *Self) []u32 { |
| 3115 | return self.payload.items[self.payload_top..self.decls_end]; |
| 3116 | } |
| 3117 | |
| 3118 | pub fn fieldsSlice(self: *Self) []u32 { |
| 3119 | return self.payload.items[self.field_bits_start..self.fields_end]; |
| 3024 | 3120 | } |
| 3025 | 3121 | |
| 3026 | | fn deinit(wip_decls: *WipDecls, gpa: *Allocator) void { |
| 3027 | | wip_decls.bit_bag.deinit(gpa); |
| 3028 | | wip_decls.payload.deinit(gpa); |
| 3122 | pub fn deinit(self: *Self) void { |
| 3123 | self.payload.items.len = self.payload_top; |
| 3029 | 3124 | } |
| 3030 | 3125 | }; |
| 3031 | 3126 | |
| ... | ... | @@ -3033,12 +3128,11 @@ fn fnDecl( |
| 3033 | 3128 | astgen: *AstGen, |
| 3034 | 3129 | gz: *GenZir, |
| 3035 | 3130 | scope: *Scope, |
| 3036 | | wip_decls: *WipDecls, |
| 3131 | wip_members: *WipMembers, |
| 3037 | 3132 | decl_node: Ast.Node.Index, |
| 3038 | 3133 | body_node: Ast.Node.Index, |
| 3039 | 3134 | fn_proto: Ast.full.FnProto, |
| 3040 | 3135 | ) InnerError!void { |
| 3041 | | const gpa = astgen.gpa; |
| 3042 | 3136 | const tree = astgen.tree; |
| 3043 | 3137 | const token_tags = tree.tokens.items(.tag); |
| 3044 | 3138 | |
| ... | ... | @@ -3048,7 +3142,7 @@ fn fnDecl( |
| 3048 | 3142 | |
| 3049 | 3143 | // We insert this at the beginning so that its instruction index marks the |
| 3050 | 3144 | // start of the top level declaration. |
| 3051 | | const block_inst = try gz.addBlock(.block_inline, fn_proto.ast.proto_node); |
| 3145 | const block_inst = try gz.makeBlockInst(.block_inline, fn_proto.ast.proto_node); |
| 3052 | 3146 | |
| 3053 | 3147 | var decl_gz: GenZir = .{ |
| 3054 | 3148 | .force_comptime = true, |
| ... | ... | @@ -3057,8 +3151,10 @@ fn fnDecl( |
| 3057 | 3151 | .decl_line = gz.calcLine(decl_node), |
| 3058 | 3152 | .parent = scope, |
| 3059 | 3153 | .astgen = astgen, |
| 3154 | .instructions = gz.instructions, |
| 3155 | .instructions_top = gz.instructions.items.len, |
| 3060 | 3156 | }; |
| 3061 | | defer decl_gz.instructions.deinit(gpa); |
| 3157 | defer decl_gz.unstack(); |
| 3062 | 3158 | |
| 3063 | 3159 | var fn_gz: GenZir = .{ |
| 3064 | 3160 | .force_comptime = false, |
| ... | ... | @@ -3067,8 +3163,10 @@ fn fnDecl( |
| 3067 | 3163 | .decl_line = decl_gz.decl_line, |
| 3068 | 3164 | .parent = &decl_gz.base, |
| 3069 | 3165 | .astgen = astgen, |
| 3166 | .instructions = gz.instructions, |
| 3167 | .instructions_top = GenZir.unstacked_top, |
| 3070 | 3168 | }; |
| 3071 | | defer fn_gz.instructions.deinit(gpa); |
| 3169 | defer fn_gz.unstack(); |
| 3072 | 3170 | |
| 3073 | 3171 | // TODO: support noinline |
| 3074 | 3172 | const is_pub = fn_proto.visib_token != null; |
| ... | ... | @@ -3085,7 +3183,7 @@ fn fnDecl( |
| 3085 | 3183 | break :blk token_tags[maybe_inline_token] == .keyword_inline; |
| 3086 | 3184 | }; |
| 3087 | 3185 | const has_section_or_addrspace = fn_proto.ast.section_expr != 0 or fn_proto.ast.addrspace_expr != 0; |
| 3088 | | try wip_decls.next(gpa, is_pub, is_export, fn_proto.ast.align_expr != 0, has_section_or_addrspace); |
| 3186 | wip_members.nextDecl(is_pub, is_export, fn_proto.ast.align_expr != 0, has_section_or_addrspace); |
| 3089 | 3187 | |
| 3090 | 3188 | var params_scope = &fn_gz.base; |
| 3091 | 3189 | const is_var_args = is_var_args: { |
| ... | ... | @@ -3134,7 +3232,7 @@ fn fnDecl( |
| 3134 | 3232 | const param_type_node = param.type_expr; |
| 3135 | 3233 | assert(param_type_node != 0); |
| 3136 | 3234 | var param_gz = decl_gz.makeSubBlock(scope); |
| 3137 | | defer param_gz.instructions.deinit(gpa); |
| 3235 | defer param_gz.unstack(); |
| 3138 | 3236 | const param_type = try expr(&param_gz, params_scope, coerced_type_rl, param_type_node); |
| 3139 | 3237 | const param_inst_expected = @intCast(u32, astgen.instructions.len + 1); |
| 3140 | 3238 | _ = try param_gz.addBreak(.break_inline, param_inst_expected, param_type); |
| ... | ... | @@ -3142,7 +3240,7 @@ fn fnDecl( |
| 3142 | 3240 | const main_tokens = tree.nodes.items(.main_token); |
| 3143 | 3241 | const name_token = param.name_token orelse main_tokens[param_type_node]; |
| 3144 | 3242 | const tag: Zir.Inst.Tag = if (is_comptime) .param_comptime else .param; |
| 3145 | | const param_inst = try decl_gz.addParam(tag, name_token, param_name, param_gz.instructions.items); |
| 3243 | const param_inst = try decl_gz.addParam(&param_gz, tag, name_token, param_name); |
| 3146 | 3244 | assert(param_inst_expected == param_inst); |
| 3147 | 3245 | break :param indexToRef(param_inst); |
| 3148 | 3246 | }; |
| ... | ... | @@ -3207,7 +3305,7 @@ fn fnDecl( |
| 3207 | 3305 | }; |
| 3208 | 3306 | |
| 3209 | 3307 | var ret_gz = decl_gz.makeSubBlock(params_scope); |
| 3210 | | defer ret_gz.instructions.deinit(gpa); |
| 3308 | defer ret_gz.unstack(); |
| 3211 | 3309 | const ret_ty = try expr(&ret_gz, params_scope, coerced_type_rl, fn_proto.ast.return_type); |
| 3212 | 3310 | const ret_br = try ret_gz.addBreak(.break_inline, 0, ret_ty); |
| 3213 | 3311 | |
| ... | ... | @@ -3220,10 +3318,10 @@ fn fnDecl( |
| 3220 | 3318 | } |
| 3221 | 3319 | break :func try decl_gz.addFunc(.{ |
| 3222 | 3320 | .src_node = decl_node, |
| 3223 | | .ret_ty = ret_gz.instructions.items, |
| 3321 | .ret_gz = &ret_gz, |
| 3224 | 3322 | .ret_br = ret_br, |
| 3225 | 3323 | .param_block = block_inst, |
| 3226 | | .body = &[0]Zir.Inst.Index{}, |
| 3324 | .body_gz = null, |
| 3227 | 3325 | .cc = cc, |
| 3228 | 3326 | .align_inst = .none, // passed in the per-decl data |
| 3229 | 3327 | .lib_name = lib_name, |
| ... | ... | @@ -3237,6 +3335,9 @@ fn fnDecl( |
| 3237 | 3335 | return astgen.failTok(fn_proto.ast.fn_token, "non-extern function is variadic", .{}); |
| 3238 | 3336 | } |
| 3239 | 3337 | |
| 3338 | // as a scope, fn_gz encloses ret_gz, but for instruction list, fn_gz stacks on ret_gz |
| 3339 | fn_gz.instructions_top = ret_gz.instructions.items.len; |
| 3340 | |
| 3240 | 3341 | const prev_fn_block = astgen.fn_block; |
| 3241 | 3342 | astgen.fn_block = &fn_gz; |
| 3242 | 3343 | defer astgen.fn_block = prev_fn_block; |
| ... | ... | @@ -3250,14 +3351,7 @@ fn fnDecl( |
| 3250 | 3351 | _ = try expr(&fn_gz, params_scope, .none, body_node); |
| 3251 | 3352 | try checkUsed(gz, &fn_gz.base, params_scope); |
| 3252 | 3353 | |
| 3253 | | const need_implicit_ret = blk: { |
| 3254 | | if (fn_gz.instructions.items.len == 0) |
| 3255 | | break :blk true; |
| 3256 | | const last = fn_gz.instructions.items[fn_gz.instructions.items.len - 1]; |
| 3257 | | const zir_tags = astgen.instructions.items(.tag); |
| 3258 | | break :blk !zir_tags[last].isNoReturn(); |
| 3259 | | }; |
| 3260 | | if (need_implicit_ret) { |
| 3354 | if (!fn_gz.endsWithNoReturn()) { |
| 3261 | 3355 | // Since we are adding the return instruction here, we must handle the coercion. |
| 3262 | 3356 | // We do this by using the `ret_coerce` instruction. |
| 3263 | 3357 | _ = try fn_gz.addUnTok(.ret_coerce, .void_value, tree.lastToken(body_node)); |
| ... | ... | @@ -3268,9 +3362,9 @@ fn fnDecl( |
| 3268 | 3362 | .lbrace_line = lbrace_line, |
| 3269 | 3363 | .lbrace_column = lbrace_column, |
| 3270 | 3364 | .param_block = block_inst, |
| 3271 | | .ret_ty = ret_gz.instructions.items, |
| 3365 | .ret_gz = &ret_gz, |
| 3272 | 3366 | .ret_br = ret_br, |
| 3273 | | .body = fn_gz.instructions.items, |
| 3367 | .body_gz = &fn_gz, |
| 3274 | 3368 | .cc = cc, |
| 3275 | 3369 | .align_inst = .none, // passed in the per-decl data |
| 3276 | 3370 | .lib_name = lib_name, |
| ... | ... | @@ -3282,29 +3376,27 @@ fn fnDecl( |
| 3282 | 3376 | }; |
| 3283 | 3377 | |
| 3284 | 3378 | // We add this at the end so that its instruction index marks the end range |
| 3285 | | // of the top level declaration. |
| 3379 | // of the top level declaration. addFunc already unstacked fn_gz and ret_gz. |
| 3286 | 3380 | _ = try decl_gz.addBreak(.break_inline, block_inst, func_inst); |
| 3287 | 3381 | try decl_gz.setBlockBody(block_inst); |
| 3288 | 3382 | |
| 3289 | | try wip_decls.payload.ensureUnusedCapacity(gpa, 10); |
| 3290 | 3383 | { |
| 3291 | 3384 | const contents_hash = std.zig.hashSrc(tree.getNodeSource(decl_node)); |
| 3292 | 3385 | const casted = @bitCast([4]u32, contents_hash); |
| 3293 | | wip_decls.payload.appendSliceAssumeCapacity(&casted); |
| 3386 | wip_members.appendToDeclSlice(&casted); |
| 3294 | 3387 | } |
| 3295 | 3388 | { |
| 3296 | 3389 | const line_delta = decl_gz.decl_line - gz.decl_line; |
| 3297 | | wip_decls.payload.appendAssumeCapacity(line_delta); |
| 3390 | wip_members.appendToDecl(line_delta); |
| 3298 | 3391 | } |
| 3299 | | wip_decls.payload.appendAssumeCapacity(fn_name_str_index); |
| 3300 | | wip_decls.payload.appendAssumeCapacity(block_inst); |
| 3392 | wip_members.appendToDecl(fn_name_str_index); |
| 3393 | wip_members.appendToDecl(block_inst); |
| 3301 | 3394 | if (align_inst != .none) { |
| 3302 | | wip_decls.payload.appendAssumeCapacity(@enumToInt(align_inst)); |
| 3395 | wip_members.appendToDecl(@enumToInt(align_inst)); |
| 3303 | 3396 | } |
| 3304 | | |
| 3305 | 3397 | if (has_section_or_addrspace) { |
| 3306 | | wip_decls.payload.appendAssumeCapacity(@enumToInt(section_inst)); |
| 3307 | | wip_decls.payload.appendAssumeCapacity(@enumToInt(addrspace_inst)); |
| 3398 | wip_members.appendToDecl(@enumToInt(section_inst)); |
| 3399 | wip_members.appendToDecl(@enumToInt(addrspace_inst)); |
| 3308 | 3400 | } |
| 3309 | 3401 | } |
| 3310 | 3402 | |
| ... | ... | @@ -3312,18 +3404,17 @@ fn globalVarDecl( |
| 3312 | 3404 | astgen: *AstGen, |
| 3313 | 3405 | gz: *GenZir, |
| 3314 | 3406 | scope: *Scope, |
| 3315 | | wip_decls: *WipDecls, |
| 3407 | wip_members: *WipMembers, |
| 3316 | 3408 | node: Ast.Node.Index, |
| 3317 | 3409 | var_decl: Ast.full.VarDecl, |
| 3318 | 3410 | ) InnerError!void { |
| 3319 | | const gpa = astgen.gpa; |
| 3320 | 3411 | const tree = astgen.tree; |
| 3321 | 3412 | const token_tags = tree.tokens.items(.tag); |
| 3322 | 3413 | |
| 3323 | 3414 | const is_mutable = token_tags[var_decl.ast.mut_token] == .keyword_var; |
| 3324 | 3415 | // We do this at the beginning so that the instruction index marks the range start |
| 3325 | 3416 | // of the top level declaration. |
| 3326 | | const block_inst = try gz.addBlock(.block_inline, node); |
| 3417 | const block_inst = try gz.makeBlockInst(.block_inline, node); |
| 3327 | 3418 | |
| 3328 | 3419 | const name_token = var_decl.ast.mut_token + 1; |
| 3329 | 3420 | const name_str_index = try astgen.identAsString(name_token); |
| ... | ... | @@ -3336,8 +3427,10 @@ fn globalVarDecl( |
| 3336 | 3427 | .force_comptime = true, |
| 3337 | 3428 | .in_defer = false, |
| 3338 | 3429 | .anon_name_strategy = .parent, |
| 3430 | .instructions = gz.instructions, |
| 3431 | .instructions_top = gz.instructions.items.len, |
| 3339 | 3432 | }; |
| 3340 | | defer block_scope.instructions.deinit(gpa); |
| 3433 | defer block_scope.unstack(); |
| 3341 | 3434 | |
| 3342 | 3435 | const is_pub = var_decl.visib_token != null; |
| 3343 | 3436 | const is_export = blk: { |
| ... | ... | @@ -3358,7 +3451,7 @@ fn globalVarDecl( |
| 3358 | 3451 | break :inst try comptimeExpr(&block_scope, &block_scope.base, .{ .ty = .const_slice_u8_type }, var_decl.ast.section_node); |
| 3359 | 3452 | }; |
| 3360 | 3453 | const has_section_or_addrspace = section_inst != .none or addrspace_inst != .none; |
| 3361 | | try wip_decls.next(gpa, is_pub, is_export, align_inst != .none, has_section_or_addrspace); |
| 3454 | wip_members.nextDecl(is_pub, is_export, align_inst != .none, has_section_or_addrspace); |
| 3362 | 3455 | |
| 3363 | 3456 | const is_threadlocal = if (var_decl.threadlocal_token) |tok| blk: { |
| 3364 | 3457 | if (!is_mutable) { |
| ... | ... | @@ -3436,24 +3529,23 @@ fn globalVarDecl( |
| 3436 | 3529 | _ = try block_scope.addBreak(.break_inline, block_inst, var_inst); |
| 3437 | 3530 | try block_scope.setBlockBody(block_inst); |
| 3438 | 3531 | |
| 3439 | | try wip_decls.payload.ensureUnusedCapacity(gpa, 10); |
| 3440 | 3532 | { |
| 3441 | 3533 | const contents_hash = std.zig.hashSrc(tree.getNodeSource(node)); |
| 3442 | 3534 | const casted = @bitCast([4]u32, contents_hash); |
| 3443 | | wip_decls.payload.appendSliceAssumeCapacity(&casted); |
| 3535 | wip_members.appendToDeclSlice(&casted); |
| 3444 | 3536 | } |
| 3445 | 3537 | { |
| 3446 | 3538 | const line_delta = block_scope.decl_line - gz.decl_line; |
| 3447 | | wip_decls.payload.appendAssumeCapacity(line_delta); |
| 3539 | wip_members.appendToDecl(line_delta); |
| 3448 | 3540 | } |
| 3449 | | wip_decls.payload.appendAssumeCapacity(name_str_index); |
| 3450 | | wip_decls.payload.appendAssumeCapacity(block_inst); |
| 3541 | wip_members.appendToDecl(name_str_index); |
| 3542 | wip_members.appendToDecl(block_inst); |
| 3451 | 3543 | if (align_inst != .none) { |
| 3452 | | wip_decls.payload.appendAssumeCapacity(@enumToInt(align_inst)); |
| 3544 | wip_members.appendToDecl(@enumToInt(align_inst)); |
| 3453 | 3545 | } |
| 3454 | 3546 | if (has_section_or_addrspace) { |
| 3455 | | wip_decls.payload.appendAssumeCapacity(@enumToInt(section_inst)); |
| 3456 | | wip_decls.payload.appendAssumeCapacity(@enumToInt(addrspace_inst)); |
| 3547 | wip_members.appendToDecl(@enumToInt(section_inst)); |
| 3548 | wip_members.appendToDecl(@enumToInt(addrspace_inst)); |
| 3457 | 3549 | } |
| 3458 | 3550 | } |
| 3459 | 3551 | |
| ... | ... | @@ -3461,18 +3553,17 @@ fn comptimeDecl( |
| 3461 | 3553 | astgen: *AstGen, |
| 3462 | 3554 | gz: *GenZir, |
| 3463 | 3555 | scope: *Scope, |
| 3464 | | wip_decls: *WipDecls, |
| 3556 | wip_members: *WipMembers, |
| 3465 | 3557 | node: Ast.Node.Index, |
| 3466 | 3558 | ) InnerError!void { |
| 3467 | | const gpa = astgen.gpa; |
| 3468 | 3559 | const tree = astgen.tree; |
| 3469 | 3560 | const node_datas = tree.nodes.items(.data); |
| 3470 | 3561 | const body_node = node_datas[node].lhs; |
| 3471 | 3562 | |
| 3472 | 3563 | // Up top so the ZIR instruction index marks the start range of this |
| 3473 | 3564 | // top-level declaration. |
| 3474 | | const block_inst = try gz.addBlock(.block_inline, node); |
| 3475 | | try wip_decls.next(gpa, false, false, false, false); |
| 3565 | const block_inst = try gz.makeBlockInst(.block_inline, node); |
| 3566 | wip_members.nextDecl(false, false, false, false); |
| 3476 | 3567 | |
| 3477 | 3568 | var decl_block: GenZir = .{ |
| 3478 | 3569 | .force_comptime = true, |
| ... | ... | @@ -3481,37 +3572,37 @@ fn comptimeDecl( |
| 3481 | 3572 | .decl_line = gz.calcLine(node), |
| 3482 | 3573 | .parent = scope, |
| 3483 | 3574 | .astgen = astgen, |
| 3575 | .instructions = gz.instructions, |
| 3576 | .instructions_top = gz.instructions.items.len, |
| 3484 | 3577 | }; |
| 3485 | | defer decl_block.instructions.deinit(gpa); |
| 3578 | defer decl_block.unstack(); |
| 3486 | 3579 | |
| 3487 | 3580 | const block_result = try expr(&decl_block, &decl_block.base, .none, body_node); |
| 3488 | | if (decl_block.instructions.items.len == 0 or !decl_block.refIsNoReturn(block_result)) { |
| 3581 | if (decl_block.isEmpty() or !decl_block.refIsNoReturn(block_result)) { |
| 3489 | 3582 | _ = try decl_block.addBreak(.break_inline, block_inst, .void_value); |
| 3490 | 3583 | } |
| 3491 | 3584 | try decl_block.setBlockBody(block_inst); |
| 3492 | 3585 | |
| 3493 | | try wip_decls.payload.ensureUnusedCapacity(gpa, 7); |
| 3494 | 3586 | { |
| 3495 | 3587 | const contents_hash = std.zig.hashSrc(tree.getNodeSource(node)); |
| 3496 | 3588 | const casted = @bitCast([4]u32, contents_hash); |
| 3497 | | wip_decls.payload.appendSliceAssumeCapacity(&casted); |
| 3589 | wip_members.appendToDeclSlice(&casted); |
| 3498 | 3590 | } |
| 3499 | 3591 | { |
| 3500 | 3592 | const line_delta = decl_block.decl_line - gz.decl_line; |
| 3501 | | wip_decls.payload.appendAssumeCapacity(line_delta); |
| 3593 | wip_members.appendToDecl(line_delta); |
| 3502 | 3594 | } |
| 3503 | | wip_decls.payload.appendAssumeCapacity(0); |
| 3504 | | wip_decls.payload.appendAssumeCapacity(block_inst); |
| 3595 | wip_members.appendToDecl(0); |
| 3596 | wip_members.appendToDecl(block_inst); |
| 3505 | 3597 | } |
| 3506 | 3598 | |
| 3507 | 3599 | fn usingnamespaceDecl( |
| 3508 | 3600 | astgen: *AstGen, |
| 3509 | 3601 | gz: *GenZir, |
| 3510 | 3602 | scope: *Scope, |
| 3511 | | wip_decls: *WipDecls, |
| 3603 | wip_members: *WipMembers, |
| 3512 | 3604 | node: Ast.Node.Index, |
| 3513 | 3605 | ) InnerError!void { |
| 3514 | | const gpa = astgen.gpa; |
| 3515 | 3606 | const tree = astgen.tree; |
| 3516 | 3607 | const node_datas = tree.nodes.items(.data); |
| 3517 | 3608 | |
| ... | ... | @@ -3524,8 +3615,8 @@ fn usingnamespaceDecl( |
| 3524 | 3615 | }; |
| 3525 | 3616 | // Up top so the ZIR instruction index marks the start range of this |
| 3526 | 3617 | // top-level declaration. |
| 3527 | | const block_inst = try gz.addBlock(.block_inline, node); |
| 3528 | | try wip_decls.next(gpa, is_pub, true, false, false); |
| 3618 | const block_inst = try gz.makeBlockInst(.block_inline, node); |
| 3619 | wip_members.nextDecl(is_pub, true, false, false); |
| 3529 | 3620 | |
| 3530 | 3621 | var decl_block: GenZir = .{ |
| 3531 | 3622 | .force_comptime = true, |
| ... | ... | @@ -3534,44 +3625,44 @@ fn usingnamespaceDecl( |
| 3534 | 3625 | .decl_line = gz.calcLine(node), |
| 3535 | 3626 | .parent = scope, |
| 3536 | 3627 | .astgen = astgen, |
| 3628 | .instructions = gz.instructions, |
| 3629 | .instructions_top = gz.instructions.items.len, |
| 3537 | 3630 | }; |
| 3538 | | defer decl_block.instructions.deinit(gpa); |
| 3631 | defer decl_block.unstack(); |
| 3539 | 3632 | |
| 3540 | 3633 | const namespace_inst = try typeExpr(&decl_block, &decl_block.base, type_expr); |
| 3541 | 3634 | _ = try decl_block.addBreak(.break_inline, block_inst, namespace_inst); |
| 3542 | 3635 | try decl_block.setBlockBody(block_inst); |
| 3543 | 3636 | |
| 3544 | | try wip_decls.payload.ensureUnusedCapacity(gpa, 7); |
| 3545 | 3637 | { |
| 3546 | 3638 | const contents_hash = std.zig.hashSrc(tree.getNodeSource(node)); |
| 3547 | 3639 | const casted = @bitCast([4]u32, contents_hash); |
| 3548 | | wip_decls.payload.appendSliceAssumeCapacity(&casted); |
| 3640 | wip_members.appendToDeclSlice(&casted); |
| 3549 | 3641 | } |
| 3550 | 3642 | { |
| 3551 | 3643 | const line_delta = decl_block.decl_line - gz.decl_line; |
| 3552 | | wip_decls.payload.appendAssumeCapacity(line_delta); |
| 3644 | wip_members.appendToDecl(line_delta); |
| 3553 | 3645 | } |
| 3554 | | wip_decls.payload.appendAssumeCapacity(0); |
| 3555 | | wip_decls.payload.appendAssumeCapacity(block_inst); |
| 3646 | wip_members.appendToDecl(0); |
| 3647 | wip_members.appendToDecl(block_inst); |
| 3556 | 3648 | } |
| 3557 | 3649 | |
| 3558 | 3650 | fn testDecl( |
| 3559 | 3651 | astgen: *AstGen, |
| 3560 | 3652 | gz: *GenZir, |
| 3561 | 3653 | scope: *Scope, |
| 3562 | | wip_decls: *WipDecls, |
| 3654 | wip_members: *WipMembers, |
| 3563 | 3655 | node: Ast.Node.Index, |
| 3564 | 3656 | ) InnerError!void { |
| 3565 | | const gpa = astgen.gpa; |
| 3566 | 3657 | const tree = astgen.tree; |
| 3567 | 3658 | const node_datas = tree.nodes.items(.data); |
| 3568 | 3659 | const body_node = node_datas[node].rhs; |
| 3569 | 3660 | |
| 3570 | 3661 | // Up top so the ZIR instruction index marks the start range of this |
| 3571 | 3662 | // top-level declaration. |
| 3572 | | const block_inst = try gz.addBlock(.block_inline, node); |
| 3663 | const block_inst = try gz.makeBlockInst(.block_inline, node); |
| 3573 | 3664 | |
| 3574 | | try wip_decls.next(gpa, false, false, false, false); |
| 3665 | wip_members.nextDecl(false, false, false, false); |
| 3575 | 3666 | |
| 3576 | 3667 | var decl_block: GenZir = .{ |
| 3577 | 3668 | .force_comptime = true, |
| ... | ... | @@ -3580,8 +3671,10 @@ fn testDecl( |
| 3580 | 3671 | .decl_line = gz.calcLine(node), |
| 3581 | 3672 | .parent = scope, |
| 3582 | 3673 | .astgen = astgen, |
| 3674 | .instructions = gz.instructions, |
| 3675 | .instructions_top = gz.instructions.items.len, |
| 3583 | 3676 | }; |
| 3584 | | defer decl_block.instructions.deinit(gpa); |
| 3677 | defer decl_block.unstack(); |
| 3585 | 3678 | |
| 3586 | 3679 | const test_name: u32 = blk: { |
| 3587 | 3680 | const main_tokens = tree.nodes.items(.main_token); |
| ... | ... | @@ -3602,8 +3695,10 @@ fn testDecl( |
| 3602 | 3695 | .decl_line = decl_block.decl_line, |
| 3603 | 3696 | .parent = &decl_block.base, |
| 3604 | 3697 | .astgen = astgen, |
| 3698 | .instructions = decl_block.instructions, |
| 3699 | .instructions_top = decl_block.instructions.items.len, |
| 3605 | 3700 | }; |
| 3606 | | defer fn_block.instructions.deinit(gpa); |
| 3701 | defer fn_block.unstack(); |
| 3607 | 3702 | |
| 3608 | 3703 | const prev_fn_block = astgen.fn_block; |
| 3609 | 3704 | astgen.fn_block = &fn_block; |
| ... | ... | @@ -3616,7 +3711,7 @@ fn testDecl( |
| 3616 | 3711 | const lbrace_column = @intCast(u32, astgen.source_column); |
| 3617 | 3712 | |
| 3618 | 3713 | const block_result = try expr(&fn_block, &fn_block.base, .none, body_node); |
| 3619 | | if (fn_block.instructions.items.len == 0 or !fn_block.refIsNoReturn(block_result)) { |
| 3714 | if (fn_block.isEmpty() or !fn_block.refIsNoReturn(block_result)) { |
| 3620 | 3715 | // Since we are adding the return instruction here, we must handle the coercion. |
| 3621 | 3716 | // We do this by using the `ret_coerce` instruction. |
| 3622 | 3717 | _ = try fn_block.addUnTok(.ret_coerce, .void_value, tree.lastToken(body_node)); |
| ... | ... | @@ -3627,9 +3722,9 @@ fn testDecl( |
| 3627 | 3722 | .lbrace_line = lbrace_line, |
| 3628 | 3723 | .lbrace_column = lbrace_column, |
| 3629 | 3724 | .param_block = block_inst, |
| 3630 | | .ret_ty = &.{}, |
| 3725 | .ret_gz = null, |
| 3631 | 3726 | .ret_br = 0, |
| 3632 | | .body = fn_block.instructions.items, |
| 3727 | .body_gz = &fn_block, |
| 3633 | 3728 | .cc = .none, |
| 3634 | 3729 | .align_inst = .none, |
| 3635 | 3730 | .lib_name = 0, |
| ... | ... | @@ -3642,18 +3737,17 @@ fn testDecl( |
| 3642 | 3737 | _ = try decl_block.addBreak(.break_inline, block_inst, func_inst); |
| 3643 | 3738 | try decl_block.setBlockBody(block_inst); |
| 3644 | 3739 | |
| 3645 | | try wip_decls.payload.ensureUnusedCapacity(gpa, 7); |
| 3646 | 3740 | { |
| 3647 | 3741 | const contents_hash = std.zig.hashSrc(tree.getNodeSource(node)); |
| 3648 | 3742 | const casted = @bitCast([4]u32, contents_hash); |
| 3649 | | wip_decls.payload.appendSliceAssumeCapacity(&casted); |
| 3743 | wip_members.appendToDeclSlice(&casted); |
| 3650 | 3744 | } |
| 3651 | 3745 | { |
| 3652 | 3746 | const line_delta = decl_block.decl_line - gz.decl_line; |
| 3653 | | wip_decls.payload.appendAssumeCapacity(line_delta); |
| 3747 | wip_members.appendToDecl(line_delta); |
| 3654 | 3748 | } |
| 3655 | | wip_decls.payload.appendAssumeCapacity(test_name); |
| 3656 | | wip_decls.payload.appendAssumeCapacity(block_inst); |
| 3749 | wip_members.appendToDecl(test_name); |
| 3750 | wip_members.appendToDecl(block_inst); |
| 3657 | 3751 | } |
| 3658 | 3752 | |
| 3659 | 3753 | fn structDeclInner( |
| ... | ... | @@ -3681,7 +3775,6 @@ fn structDeclInner( |
| 3681 | 3775 | const gpa = astgen.gpa; |
| 3682 | 3776 | const tree = astgen.tree; |
| 3683 | 3777 | const node_tags = tree.nodes.items(.tag); |
| 3684 | | const node_datas = tree.nodes.items(.data); |
| 3685 | 3778 | |
| 3686 | 3779 | var namespace: Scope.Namespace = .{ |
| 3687 | 3780 | .parent = scope, |
| ... | ... | @@ -3701,162 +3794,28 @@ fn structDeclInner( |
| 3701 | 3794 | .astgen = astgen, |
| 3702 | 3795 | .force_comptime = true, |
| 3703 | 3796 | .in_defer = false, |
| 3797 | .instructions = gz.instructions, |
| 3798 | .instructions_top = gz.instructions.items.len, |
| 3704 | 3799 | }; |
| 3705 | | defer block_scope.instructions.deinit(gpa); |
| 3706 | | |
| 3707 | | try astgen.scanDecls(&namespace, container_decl.ast.members); |
| 3708 | | |
| 3709 | | var wip_decls: WipDecls = .{}; |
| 3710 | | defer wip_decls.deinit(gpa); |
| 3800 | defer block_scope.unstack(); |
| 3711 | 3801 | |
| 3712 | | // We don't know which members are fields until we iterate, so cannot do |
| 3713 | | // an accurate ensureTotalCapacity yet. |
| 3714 | | var fields_data = ArrayListUnmanaged(u32){}; |
| 3715 | | defer fields_data.deinit(gpa); |
| 3802 | const decl_count = try astgen.scanDecls(&namespace, container_decl.ast.members); |
| 3803 | const field_count = @intCast(u32, container_decl.ast.members.len - decl_count); |
| 3716 | 3804 | |
| 3717 | 3805 | const bits_per_field = 4; |
| 3718 | | const fields_per_u32 = 32 / bits_per_field; |
| 3719 | | // We only need this if there are greater than fields_per_u32 fields. |
| 3720 | | var bit_bag = ArrayListUnmanaged(u32){}; |
| 3721 | | defer bit_bag.deinit(gpa); |
| 3806 | const max_field_size = 4; |
| 3807 | var wip_members = try WipMembers.init(gpa, &astgen.scratch, decl_count, field_count, bits_per_field, max_field_size); |
| 3808 | defer wip_members.deinit(); |
| 3722 | 3809 | |
| 3723 | 3810 | var known_has_bits = false; |
| 3724 | | var cur_bit_bag: u32 = 0; |
| 3725 | | var field_index: usize = 0; |
| 3726 | 3811 | for (container_decl.ast.members) |member_node| { |
| 3727 | | const member = switch (node_tags[member_node]) { |
| 3728 | | .container_field_init => tree.containerFieldInit(member_node), |
| 3729 | | .container_field_align => tree.containerFieldAlign(member_node), |
| 3730 | | .container_field => tree.containerField(member_node), |
| 3731 | | |
| 3732 | | .fn_decl => { |
| 3733 | | const fn_proto = node_datas[member_node].lhs; |
| 3734 | | const body = node_datas[member_node].rhs; |
| 3735 | | switch (node_tags[fn_proto]) { |
| 3736 | | .fn_proto_simple => { |
| 3737 | | var params: [1]Ast.Node.Index = undefined; |
| 3738 | | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProtoSimple(&params, fn_proto)) catch |err| switch (err) { |
| 3739 | | error.OutOfMemory => return error.OutOfMemory, |
| 3740 | | error.AnalysisFail => {}, |
| 3741 | | }; |
| 3742 | | continue; |
| 3743 | | }, |
| 3744 | | .fn_proto_multi => { |
| 3745 | | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProtoMulti(fn_proto)) catch |err| switch (err) { |
| 3746 | | error.OutOfMemory => return error.OutOfMemory, |
| 3747 | | error.AnalysisFail => {}, |
| 3748 | | }; |
| 3749 | | continue; |
| 3750 | | }, |
| 3751 | | .fn_proto_one => { |
| 3752 | | var params: [1]Ast.Node.Index = undefined; |
| 3753 | | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProtoOne(&params, fn_proto)) catch |err| switch (err) { |
| 3754 | | error.OutOfMemory => return error.OutOfMemory, |
| 3755 | | error.AnalysisFail => {}, |
| 3756 | | }; |
| 3757 | | continue; |
| 3758 | | }, |
| 3759 | | .fn_proto => { |
| 3760 | | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProto(fn_proto)) catch |err| switch (err) { |
| 3761 | | error.OutOfMemory => return error.OutOfMemory, |
| 3762 | | error.AnalysisFail => {}, |
| 3763 | | }; |
| 3764 | | continue; |
| 3765 | | }, |
| 3766 | | else => unreachable, |
| 3767 | | } |
| 3768 | | }, |
| 3769 | | .fn_proto_simple => { |
| 3770 | | var params: [1]Ast.Node.Index = undefined; |
| 3771 | | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProtoSimple(&params, member_node)) catch |err| switch (err) { |
| 3772 | | error.OutOfMemory => return error.OutOfMemory, |
| 3773 | | error.AnalysisFail => {}, |
| 3774 | | }; |
| 3775 | | continue; |
| 3776 | | }, |
| 3777 | | .fn_proto_multi => { |
| 3778 | | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProtoMulti(member_node)) catch |err| switch (err) { |
| 3779 | | error.OutOfMemory => return error.OutOfMemory, |
| 3780 | | error.AnalysisFail => {}, |
| 3781 | | }; |
| 3782 | | continue; |
| 3783 | | }, |
| 3784 | | .fn_proto_one => { |
| 3785 | | var params: [1]Ast.Node.Index = undefined; |
| 3786 | | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProtoOne(&params, member_node)) catch |err| switch (err) { |
| 3787 | | error.OutOfMemory => return error.OutOfMemory, |
| 3788 | | error.AnalysisFail => {}, |
| 3789 | | }; |
| 3790 | | continue; |
| 3791 | | }, |
| 3792 | | .fn_proto => { |
| 3793 | | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProto(member_node)) catch |err| switch (err) { |
| 3794 | | error.OutOfMemory => return error.OutOfMemory, |
| 3795 | | error.AnalysisFail => {}, |
| 3796 | | }; |
| 3797 | | continue; |
| 3798 | | }, |
| 3799 | | |
| 3800 | | .global_var_decl => { |
| 3801 | | astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.globalVarDecl(member_node)) catch |err| switch (err) { |
| 3802 | | error.OutOfMemory => return error.OutOfMemory, |
| 3803 | | error.AnalysisFail => {}, |
| 3804 | | }; |
| 3805 | | continue; |
| 3806 | | }, |
| 3807 | | .local_var_decl => { |
| 3808 | | astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.localVarDecl(member_node)) catch |err| switch (err) { |
| 3809 | | error.OutOfMemory => return error.OutOfMemory, |
| 3810 | | error.AnalysisFail => {}, |
| 3811 | | }; |
| 3812 | | continue; |
| 3813 | | }, |
| 3814 | | .simple_var_decl => { |
| 3815 | | astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.simpleVarDecl(member_node)) catch |err| switch (err) { |
| 3816 | | error.OutOfMemory => return error.OutOfMemory, |
| 3817 | | error.AnalysisFail => {}, |
| 3818 | | }; |
| 3819 | | continue; |
| 3820 | | }, |
| 3821 | | .aligned_var_decl => { |
| 3822 | | astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.alignedVarDecl(member_node)) catch |err| switch (err) { |
| 3823 | | error.OutOfMemory => return error.OutOfMemory, |
| 3824 | | error.AnalysisFail => {}, |
| 3825 | | }; |
| 3826 | | continue; |
| 3827 | | }, |
| 3828 | | |
| 3829 | | .@"comptime" => { |
| 3830 | | astgen.comptimeDecl(gz, &namespace.base, &wip_decls, member_node) catch |err| switch (err) { |
| 3831 | | error.OutOfMemory => return error.OutOfMemory, |
| 3832 | | error.AnalysisFail => {}, |
| 3833 | | }; |
| 3834 | | continue; |
| 3835 | | }, |
| 3836 | | .@"usingnamespace" => { |
| 3837 | | astgen.usingnamespaceDecl(gz, &namespace.base, &wip_decls, member_node) catch |err| switch (err) { |
| 3838 | | error.OutOfMemory => return error.OutOfMemory, |
| 3839 | | error.AnalysisFail => {}, |
| 3840 | | }; |
| 3841 | | continue; |
| 3842 | | }, |
| 3843 | | .test_decl => { |
| 3844 | | astgen.testDecl(gz, &namespace.base, &wip_decls, member_node) catch |err| switch (err) { |
| 3845 | | error.OutOfMemory => return error.OutOfMemory, |
| 3846 | | error.AnalysisFail => {}, |
| 3847 | | }; |
| 3848 | | continue; |
| 3849 | | }, |
| 3850 | | else => unreachable, |
| 3812 | const member = switch (try containerMember(gz, &namespace.base, &wip_members, member_node)) { |
| 3813 | .decl => continue, |
| 3814 | .field => |field| field, |
| 3851 | 3815 | }; |
| 3852 | | if (field_index % fields_per_u32 == 0 and field_index != 0) { |
| 3853 | | try bit_bag.append(gpa, cur_bit_bag); |
| 3854 | | cur_bit_bag = 0; |
| 3855 | | } |
| 3856 | | try fields_data.ensureUnusedCapacity(gpa, 4); |
| 3857 | 3816 | |
| 3858 | 3817 | const field_name = try astgen.identAsString(member.ast.name_token); |
| 3859 | | fields_data.appendAssumeCapacity(field_name); |
| 3818 | wip_members.appendToField(field_name); |
| 3860 | 3819 | |
| 3861 | 3820 | if (member.ast.type_expr == 0) { |
| 3862 | 3821 | return astgen.failTok(member.ast.name_token, "struct field missing type", .{}); |
| ... | ... | @@ -3866,7 +3825,7 @@ fn structDeclInner( |
| 3866 | 3825 | .none |
| 3867 | 3826 | else |
| 3868 | 3827 | try typeExpr(&block_scope, &namespace.base, member.ast.type_expr); |
| 3869 | | fields_data.appendAssumeCapacity(@enumToInt(field_type)); |
| 3828 | wip_members.appendToField(@enumToInt(field_type)); |
| 3870 | 3829 | |
| 3871 | 3830 | known_has_bits = known_has_bits or nodeImpliesRuntimeBits(tree, member.ast.type_expr); |
| 3872 | 3831 | |
| ... | ... | @@ -3874,79 +3833,47 @@ fn structDeclInner( |
| 3874 | 3833 | const have_value = member.ast.value_expr != 0; |
| 3875 | 3834 | const is_comptime = member.comptime_token != null; |
| 3876 | 3835 | const unused = false; |
| 3877 | | cur_bit_bag = (cur_bit_bag >> bits_per_field) | |
| 3878 | | (@as(u32, @boolToInt(have_align)) << 28) | |
| 3879 | | (@as(u32, @boolToInt(have_value)) << 29) | |
| 3880 | | (@as(u32, @boolToInt(is_comptime)) << 30) | |
| 3881 | | (@as(u32, @boolToInt(unused)) << 31); |
| 3836 | wip_members.nextField(bits_per_field, .{ have_align, have_value, is_comptime, unused }); |
| 3882 | 3837 | |
| 3883 | 3838 | if (have_align) { |
| 3884 | 3839 | const align_inst = try expr(&block_scope, &namespace.base, align_rl, member.ast.align_expr); |
| 3885 | | fields_data.appendAssumeCapacity(@enumToInt(align_inst)); |
| 3840 | wip_members.appendToField(@enumToInt(align_inst)); |
| 3886 | 3841 | } |
| 3887 | 3842 | if (have_value) { |
| 3888 | 3843 | const rl: ResultLoc = if (field_type == .none) .none else .{ .ty = field_type }; |
| 3889 | 3844 | |
| 3890 | 3845 | const default_inst = try expr(&block_scope, &namespace.base, rl, member.ast.value_expr); |
| 3891 | | fields_data.appendAssumeCapacity(@enumToInt(default_inst)); |
| 3846 | wip_members.appendToField(@enumToInt(default_inst)); |
| 3892 | 3847 | } else if (member.comptime_token) |comptime_token| { |
| 3893 | 3848 | return astgen.failTok(comptime_token, "comptime field without default initialization value", .{}); |
| 3894 | 3849 | } |
| 3895 | | |
| 3896 | | field_index += 1; |
| 3897 | | } |
| 3898 | | { |
| 3899 | | const empty_slot_count = fields_per_u32 - (field_index % fields_per_u32); |
| 3900 | | if (empty_slot_count < fields_per_u32) { |
| 3901 | | cur_bit_bag >>= @intCast(u5, empty_slot_count * bits_per_field); |
| 3902 | | } |
| 3903 | | } |
| 3904 | | { |
| 3905 | | const empty_slot_count = WipDecls.fields_per_u32 - (wip_decls.decl_index % WipDecls.fields_per_u32); |
| 3906 | | if (empty_slot_count < WipDecls.fields_per_u32) { |
| 3907 | | wip_decls.cur_bit_bag >>= @intCast(u5, empty_slot_count * WipDecls.bits_per_field); |
| 3908 | | } |
| 3909 | 3850 | } |
| 3910 | 3851 | |
| 3911 | | if (block_scope.instructions.items.len != 0) { |
| 3852 | if (!block_scope.isEmpty()) { |
| 3912 | 3853 | _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value); |
| 3913 | 3854 | } |
| 3914 | 3855 | |
| 3856 | const body = block_scope.instructionsSlice(); |
| 3857 | |
| 3915 | 3858 | try gz.setStruct(decl_inst, .{ |
| 3916 | 3859 | .src_node = node, |
| 3917 | 3860 | .layout = layout, |
| 3918 | | .body_len = @intCast(u32, block_scope.instructions.items.len), |
| 3919 | | .fields_len = @intCast(u32, field_index), |
| 3920 | | .decls_len = @intCast(u32, wip_decls.decl_index), |
| 3861 | .body_len = @intCast(u32, body.len), |
| 3862 | .fields_len = field_count, |
| 3863 | .decls_len = decl_count, |
| 3921 | 3864 | .known_has_bits = known_has_bits, |
| 3922 | 3865 | }); |
| 3923 | 3866 | |
| 3924 | | // zig fmt: off |
| 3925 | | try astgen.extra.ensureUnusedCapacity(gpa, |
| 3926 | | bit_bag.items.len + |
| 3927 | | @boolToInt(wip_decls.decl_index != 0) + |
| 3928 | | wip_decls.payload.items.len + |
| 3929 | | block_scope.instructions.items.len + |
| 3930 | | wip_decls.bit_bag.items.len + |
| 3931 | | @boolToInt(field_index != 0) + |
| 3932 | | fields_data.items.len |
| 3933 | | ); |
| 3934 | | // zig fmt: on |
| 3935 | | |
| 3936 | | astgen.extra.appendSliceAssumeCapacity(wip_decls.bit_bag.items); // Likely empty. |
| 3937 | | if (wip_decls.decl_index != 0) { |
| 3938 | | astgen.extra.appendAssumeCapacity(wip_decls.cur_bit_bag); |
| 3939 | | } |
| 3940 | | astgen.extra.appendSliceAssumeCapacity(wip_decls.payload.items); |
| 3941 | | |
| 3942 | | astgen.extra.appendSliceAssumeCapacity(block_scope.instructions.items); |
| 3943 | | |
| 3944 | | astgen.extra.appendSliceAssumeCapacity(bit_bag.items); // Likely empty. |
| 3945 | | if (field_index != 0) { |
| 3946 | | astgen.extra.appendAssumeCapacity(cur_bit_bag); |
| 3947 | | } |
| 3948 | | astgen.extra.appendSliceAssumeCapacity(fields_data.items); |
| 3867 | wip_members.finishBits(bits_per_field); |
| 3868 | const decls_slice = wip_members.declsSlice(); |
| 3869 | const fields_slice = wip_members.fieldsSlice(); |
| 3870 | try astgen.extra.ensureUnusedCapacity(gpa, decls_slice.len + body.len + fields_slice.len); |
| 3871 | astgen.extra.appendSliceAssumeCapacity(decls_slice); |
| 3872 | astgen.extra.appendSliceAssumeCapacity(body); |
| 3873 | astgen.extra.appendSliceAssumeCapacity(fields_slice); |
| 3949 | 3874 | |
| 3875 | block_scope.unstack(); |
| 3876 | try gz.addNamespaceCaptures(&namespace); |
| 3950 | 3877 | return indexToRef(decl_inst); |
| 3951 | 3878 | } |
| 3952 | 3879 | |
| ... | ... | @@ -3965,7 +3892,6 @@ fn unionDeclInner( |
| 3965 | 3892 | const gpa = astgen.gpa; |
| 3966 | 3893 | const tree = astgen.tree; |
| 3967 | 3894 | const node_tags = tree.nodes.items(.tag); |
| 3968 | | const node_datas = tree.nodes.items(.data); |
| 3969 | 3895 | |
| 3970 | 3896 | var namespace: Scope.Namespace = .{ |
| 3971 | 3897 | .parent = scope, |
| ... | ... | @@ -3985,192 +3911,54 @@ fn unionDeclInner( |
| 3985 | 3911 | .astgen = astgen, |
| 3986 | 3912 | .force_comptime = true, |
| 3987 | 3913 | .in_defer = false, |
| 3914 | .instructions = gz.instructions, |
| 3915 | .instructions_top = gz.instructions.items.len, |
| 3988 | 3916 | }; |
| 3989 | | defer block_scope.instructions.deinit(gpa); |
| 3917 | defer block_scope.unstack(); |
| 3990 | 3918 | |
| 3991 | | try astgen.scanDecls(&namespace, members); |
| 3919 | const decl_count = try astgen.scanDecls(&namespace, members); |
| 3920 | const field_count = @intCast(u32, members.len - decl_count); |
| 3992 | 3921 | |
| 3993 | 3922 | const arg_inst: Zir.Inst.Ref = if (arg_node != 0) |
| 3994 | 3923 | try typeExpr(&block_scope, &namespace.base, arg_node) |
| 3995 | 3924 | else |
| 3996 | 3925 | .none; |
| 3997 | 3926 | |
| 3998 | | var wip_decls: WipDecls = .{}; |
| 3999 | | defer wip_decls.deinit(gpa); |
| 4000 | | |
| 4001 | | // We don't know which members are fields until we iterate, so cannot do |
| 4002 | | // an accurate ensureTotalCapacity yet. |
| 4003 | | var fields_data = ArrayListUnmanaged(u32){}; |
| 4004 | | defer fields_data.deinit(gpa); |
| 4005 | | |
| 4006 | 3927 | const bits_per_field = 4; |
| 4007 | | const fields_per_u32 = 32 / bits_per_field; |
| 4008 | | // We only need this if there are greater than fields_per_u32 fields. |
| 4009 | | var bit_bag = ArrayListUnmanaged(u32){}; |
| 4010 | | defer bit_bag.deinit(gpa); |
| 3928 | const max_field_size = 4; |
| 3929 | var wip_members = try WipMembers.init(gpa, &astgen.scratch, decl_count, field_count, bits_per_field, max_field_size); |
| 3930 | defer wip_members.deinit(); |
| 4011 | 3931 | |
| 4012 | | var cur_bit_bag: u32 = 0; |
| 4013 | | var field_index: usize = 0; |
| 4014 | 3932 | for (members) |member_node| { |
| 4015 | | const member = switch (node_tags[member_node]) { |
| 4016 | | .container_field_init => tree.containerFieldInit(member_node), |
| 4017 | | .container_field_align => tree.containerFieldAlign(member_node), |
| 4018 | | .container_field => tree.containerField(member_node), |
| 4019 | | |
| 4020 | | .fn_decl => { |
| 4021 | | const fn_proto = node_datas[member_node].lhs; |
| 4022 | | const body = node_datas[member_node].rhs; |
| 4023 | | switch (node_tags[fn_proto]) { |
| 4024 | | .fn_proto_simple => { |
| 4025 | | var params: [1]Ast.Node.Index = undefined; |
| 4026 | | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProtoSimple(&params, fn_proto)) catch |err| switch (err) { |
| 4027 | | error.OutOfMemory => return error.OutOfMemory, |
| 4028 | | error.AnalysisFail => {}, |
| 4029 | | }; |
| 4030 | | continue; |
| 4031 | | }, |
| 4032 | | .fn_proto_multi => { |
| 4033 | | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProtoMulti(fn_proto)) catch |err| switch (err) { |
| 4034 | | error.OutOfMemory => return error.OutOfMemory, |
| 4035 | | error.AnalysisFail => {}, |
| 4036 | | }; |
| 4037 | | continue; |
| 4038 | | }, |
| 4039 | | .fn_proto_one => { |
| 4040 | | var params: [1]Ast.Node.Index = undefined; |
| 4041 | | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProtoOne(&params, fn_proto)) catch |err| switch (err) { |
| 4042 | | error.OutOfMemory => return error.OutOfMemory, |
| 4043 | | error.AnalysisFail => {}, |
| 4044 | | }; |
| 4045 | | continue; |
| 4046 | | }, |
| 4047 | | .fn_proto => { |
| 4048 | | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProto(fn_proto)) catch |err| switch (err) { |
| 4049 | | error.OutOfMemory => return error.OutOfMemory, |
| 4050 | | error.AnalysisFail => {}, |
| 4051 | | }; |
| 4052 | | continue; |
| 4053 | | }, |
| 4054 | | else => unreachable, |
| 4055 | | } |
| 4056 | | }, |
| 4057 | | .fn_proto_simple => { |
| 4058 | | var params: [1]Ast.Node.Index = undefined; |
| 4059 | | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProtoSimple(&params, member_node)) catch |err| switch (err) { |
| 4060 | | error.OutOfMemory => return error.OutOfMemory, |
| 4061 | | error.AnalysisFail => {}, |
| 4062 | | }; |
| 4063 | | continue; |
| 4064 | | }, |
| 4065 | | .fn_proto_multi => { |
| 4066 | | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProtoMulti(member_node)) catch |err| switch (err) { |
| 4067 | | error.OutOfMemory => return error.OutOfMemory, |
| 4068 | | error.AnalysisFail => {}, |
| 4069 | | }; |
| 4070 | | continue; |
| 4071 | | }, |
| 4072 | | .fn_proto_one => { |
| 4073 | | var params: [1]Ast.Node.Index = undefined; |
| 4074 | | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProtoOne(&params, member_node)) catch |err| switch (err) { |
| 4075 | | error.OutOfMemory => return error.OutOfMemory, |
| 4076 | | error.AnalysisFail => {}, |
| 4077 | | }; |
| 4078 | | continue; |
| 4079 | | }, |
| 4080 | | .fn_proto => { |
| 4081 | | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProto(member_node)) catch |err| switch (err) { |
| 4082 | | error.OutOfMemory => return error.OutOfMemory, |
| 4083 | | error.AnalysisFail => {}, |
| 4084 | | }; |
| 4085 | | continue; |
| 4086 | | }, |
| 4087 | | |
| 4088 | | .global_var_decl => { |
| 4089 | | astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.globalVarDecl(member_node)) catch |err| switch (err) { |
| 4090 | | error.OutOfMemory => return error.OutOfMemory, |
| 4091 | | error.AnalysisFail => {}, |
| 4092 | | }; |
| 4093 | | continue; |
| 4094 | | }, |
| 4095 | | .local_var_decl => { |
| 4096 | | astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.localVarDecl(member_node)) catch |err| switch (err) { |
| 4097 | | error.OutOfMemory => return error.OutOfMemory, |
| 4098 | | error.AnalysisFail => {}, |
| 4099 | | }; |
| 4100 | | continue; |
| 4101 | | }, |
| 4102 | | .simple_var_decl => { |
| 4103 | | astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.simpleVarDecl(member_node)) catch |err| switch (err) { |
| 4104 | | error.OutOfMemory => return error.OutOfMemory, |
| 4105 | | error.AnalysisFail => {}, |
| 4106 | | }; |
| 4107 | | continue; |
| 4108 | | }, |
| 4109 | | .aligned_var_decl => { |
| 4110 | | astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.alignedVarDecl(member_node)) catch |err| switch (err) { |
| 4111 | | error.OutOfMemory => return error.OutOfMemory, |
| 4112 | | error.AnalysisFail => {}, |
| 4113 | | }; |
| 4114 | | continue; |
| 4115 | | }, |
| 4116 | | |
| 4117 | | .@"comptime" => { |
| 4118 | | astgen.comptimeDecl(gz, &namespace.base, &wip_decls, member_node) catch |err| switch (err) { |
| 4119 | | error.OutOfMemory => return error.OutOfMemory, |
| 4120 | | error.AnalysisFail => {}, |
| 4121 | | }; |
| 4122 | | continue; |
| 4123 | | }, |
| 4124 | | .@"usingnamespace" => { |
| 4125 | | astgen.usingnamespaceDecl(gz, &namespace.base, &wip_decls, member_node) catch |err| switch (err) { |
| 4126 | | error.OutOfMemory => return error.OutOfMemory, |
| 4127 | | error.AnalysisFail => {}, |
| 4128 | | }; |
| 4129 | | continue; |
| 4130 | | }, |
| 4131 | | .test_decl => { |
| 4132 | | astgen.testDecl(gz, &namespace.base, &wip_decls, member_node) catch |err| switch (err) { |
| 4133 | | error.OutOfMemory => return error.OutOfMemory, |
| 4134 | | error.AnalysisFail => {}, |
| 4135 | | }; |
| 4136 | | continue; |
| 4137 | | }, |
| 4138 | | else => unreachable, |
| 3933 | const member = switch (try containerMember(gz, &namespace.base, &wip_members, member_node)) { |
| 3934 | .decl => continue, |
| 3935 | .field => |field| field, |
| 4139 | 3936 | }; |
| 4140 | | if (field_index % fields_per_u32 == 0 and field_index != 0) { |
| 4141 | | try bit_bag.append(gpa, cur_bit_bag); |
| 4142 | | cur_bit_bag = 0; |
| 4143 | | } |
| 4144 | 3937 | if (member.comptime_token) |comptime_token| { |
| 4145 | 3938 | return astgen.failTok(comptime_token, "union fields cannot be marked comptime", .{}); |
| 4146 | 3939 | } |
| 4147 | | try fields_data.ensureUnusedCapacity(gpa, 4); |
| 4148 | 3940 | |
| 4149 | 3941 | const field_name = try astgen.identAsString(member.ast.name_token); |
| 4150 | | fields_data.appendAssumeCapacity(field_name); |
| 3942 | wip_members.appendToField(field_name); |
| 4151 | 3943 | |
| 4152 | 3944 | const have_type = member.ast.type_expr != 0; |
| 4153 | 3945 | const have_align = member.ast.align_expr != 0; |
| 4154 | 3946 | const have_value = member.ast.value_expr != 0; |
| 4155 | 3947 | const unused = false; |
| 4156 | | cur_bit_bag = (cur_bit_bag >> bits_per_field) | |
| 4157 | | (@as(u32, @boolToInt(have_type)) << 28) | |
| 4158 | | (@as(u32, @boolToInt(have_align)) << 29) | |
| 4159 | | (@as(u32, @boolToInt(have_value)) << 30) | |
| 4160 | | (@as(u32, @boolToInt(unused)) << 31); |
| 3948 | wip_members.nextField(bits_per_field, .{ have_type, have_align, have_value, unused }); |
| 4161 | 3949 | |
| 4162 | 3950 | if (have_type) { |
| 4163 | 3951 | const field_type: Zir.Inst.Ref = if (node_tags[member.ast.type_expr] == .@"anytype") |
| 4164 | 3952 | .none |
| 4165 | 3953 | else |
| 4166 | 3954 | try typeExpr(&block_scope, &namespace.base, member.ast.type_expr); |
| 4167 | | fields_data.appendAssumeCapacity(@enumToInt(field_type)); |
| 3955 | wip_members.appendToField(@enumToInt(field_type)); |
| 4168 | 3956 | } else if (arg_inst == .none and !have_auto_enum) { |
| 4169 | 3957 | return astgen.failNode(member_node, "union field missing type", .{}); |
| 4170 | 3958 | } |
| 4171 | 3959 | if (have_align) { |
| 4172 | 3960 | const align_inst = try expr(&block_scope, &block_scope.base, .{ .ty = .u32_type }, member.ast.align_expr); |
| 4173 | | fields_data.appendAssumeCapacity(@enumToInt(align_inst)); |
| 3961 | wip_members.appendToField(@enumToInt(align_inst)); |
| 4174 | 3962 | } |
| 4175 | 3963 | if (have_value) { |
| 4176 | 3964 | if (arg_inst == .none) { |
| ... | ... | @@ -4202,65 +3990,39 @@ fn unionDeclInner( |
| 4202 | 3990 | ); |
| 4203 | 3991 | } |
| 4204 | 3992 | const tag_value = try expr(&block_scope, &block_scope.base, .{ .ty = arg_inst }, member.ast.value_expr); |
| 4205 | | fields_data.appendAssumeCapacity(@enumToInt(tag_value)); |
| 3993 | wip_members.appendToField(@enumToInt(tag_value)); |
| 4206 | 3994 | } |
| 4207 | | |
| 4208 | | field_index += 1; |
| 4209 | 3995 | } |
| 4210 | | if (field_index == 0) { |
| 3996 | if (field_count == 0) { |
| 4211 | 3997 | return astgen.failNode(node, "union declarations must have at least one tag", .{}); |
| 4212 | 3998 | } |
| 4213 | | { |
| 4214 | | const empty_slot_count = fields_per_u32 - (field_index % fields_per_u32); |
| 4215 | | if (empty_slot_count < fields_per_u32) { |
| 4216 | | cur_bit_bag >>= @intCast(u5, empty_slot_count * bits_per_field); |
| 4217 | | } |
| 4218 | | } |
| 4219 | | { |
| 4220 | | const empty_slot_count = WipDecls.fields_per_u32 - (wip_decls.decl_index % WipDecls.fields_per_u32); |
| 4221 | | if (empty_slot_count < WipDecls.fields_per_u32) { |
| 4222 | | wip_decls.cur_bit_bag >>= @intCast(u5, empty_slot_count * WipDecls.bits_per_field); |
| 4223 | | } |
| 4224 | | } |
| 4225 | 3999 | |
| 4226 | | if (block_scope.instructions.items.len != 0) { |
| 4000 | if (!block_scope.isEmpty()) { |
| 4227 | 4001 | _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value); |
| 4228 | 4002 | } |
| 4229 | 4003 | |
| 4004 | const body = block_scope.instructionsSlice(); |
| 4005 | |
| 4230 | 4006 | try gz.setUnion(decl_inst, .{ |
| 4231 | 4007 | .src_node = node, |
| 4232 | 4008 | .layout = layout, |
| 4233 | 4009 | .tag_type = arg_inst, |
| 4234 | | .body_len = @intCast(u32, block_scope.instructions.items.len), |
| 4235 | | .fields_len = @intCast(u32, field_index), |
| 4236 | | .decls_len = @intCast(u32, wip_decls.decl_index), |
| 4010 | .body_len = @intCast(u32, body.len), |
| 4011 | .fields_len = field_count, |
| 4012 | .decls_len = decl_count, |
| 4237 | 4013 | .auto_enum_tag = have_auto_enum, |
| 4238 | 4014 | }); |
| 4239 | 4015 | |
| 4240 | | // zig fmt: off |
| 4241 | | try astgen.extra.ensureUnusedCapacity(gpa, |
| 4242 | | bit_bag.items.len + |
| 4243 | | @boolToInt(wip_decls.decl_index != 0) + |
| 4244 | | wip_decls.payload.items.len + |
| 4245 | | block_scope.instructions.items.len + |
| 4246 | | wip_decls.bit_bag.items.len + |
| 4247 | | 1 + // cur_bit_bag |
| 4248 | | fields_data.items.len |
| 4249 | | ); |
| 4250 | | // zig fmt: on |
| 4251 | | |
| 4252 | | astgen.extra.appendSliceAssumeCapacity(wip_decls.bit_bag.items); // Likely empty. |
| 4253 | | if (wip_decls.decl_index != 0) { |
| 4254 | | astgen.extra.appendAssumeCapacity(wip_decls.cur_bit_bag); |
| 4255 | | } |
| 4256 | | astgen.extra.appendSliceAssumeCapacity(wip_decls.payload.items); |
| 4257 | | |
| 4258 | | astgen.extra.appendSliceAssumeCapacity(block_scope.instructions.items); |
| 4259 | | |
| 4260 | | astgen.extra.appendSliceAssumeCapacity(bit_bag.items); // Likely empty. |
| 4261 | | astgen.extra.appendAssumeCapacity(cur_bit_bag); |
| 4262 | | astgen.extra.appendSliceAssumeCapacity(fields_data.items); |
| 4016 | wip_members.finishBits(bits_per_field); |
| 4017 | const decls_slice = wip_members.declsSlice(); |
| 4018 | const fields_slice = wip_members.fieldsSlice(); |
| 4019 | try astgen.extra.ensureUnusedCapacity(gpa, decls_slice.len + body.len + fields_slice.len); |
| 4020 | astgen.extra.appendSliceAssumeCapacity(decls_slice); |
| 4021 | astgen.extra.appendSliceAssumeCapacity(body); |
| 4022 | astgen.extra.appendSliceAssumeCapacity(fields_slice); |
| 4263 | 4023 | |
| 4024 | block_scope.unstack(); |
| 4025 | try gz.addNamespaceCaptures(&namespace); |
| 4264 | 4026 | return indexToRef(decl_inst); |
| 4265 | 4027 | } |
| 4266 | 4028 | |
| ... | ... | @@ -4276,7 +4038,6 @@ fn containerDecl( |
| 4276 | 4038 | const tree = astgen.tree; |
| 4277 | 4039 | const token_tags = tree.tokens.items(.tag); |
| 4278 | 4040 | const node_tags = tree.nodes.items(.tag); |
| 4279 | | const node_datas = tree.nodes.items(.data); |
| 4280 | 4041 | |
| 4281 | 4042 | const prev_fn_block = astgen.fn_block; |
| 4282 | 4043 | astgen.fn_block = null; |
| ... | ... | @@ -4430,172 +4191,39 @@ fn containerDecl( |
| 4430 | 4191 | .astgen = astgen, |
| 4431 | 4192 | .force_comptime = true, |
| 4432 | 4193 | .in_defer = false, |
| 4194 | .instructions = gz.instructions, |
| 4195 | .instructions_top = gz.instructions.items.len, |
| 4433 | 4196 | }; |
| 4434 | | defer block_scope.instructions.deinit(gpa); |
| 4197 | defer block_scope.unstack(); |
| 4435 | 4198 | |
| 4436 | | try astgen.scanDecls(&namespace, container_decl.ast.members); |
| 4199 | _ = try astgen.scanDecls(&namespace, container_decl.ast.members); |
| 4437 | 4200 | |
| 4438 | 4201 | const arg_inst: Zir.Inst.Ref = if (container_decl.ast.arg != 0) |
| 4439 | 4202 | try comptimeExpr(&block_scope, &namespace.base, .{ .ty = .type_type }, container_decl.ast.arg) |
| 4440 | 4203 | else |
| 4441 | 4204 | .none; |
| 4442 | 4205 | |
| 4443 | | var wip_decls: WipDecls = .{}; |
| 4444 | | defer wip_decls.deinit(gpa); |
| 4445 | | |
| 4446 | | var fields_data = ArrayListUnmanaged(u32){}; |
| 4447 | | defer fields_data.deinit(gpa); |
| 4448 | | |
| 4449 | | try fields_data.ensureTotalCapacity(gpa, counts.total_fields + counts.values); |
| 4450 | | |
| 4451 | | // We only need this if there are greater than 32 fields. |
| 4452 | | var bit_bag = ArrayListUnmanaged(u32){}; |
| 4453 | | defer bit_bag.deinit(gpa); |
| 4206 | const bits_per_field = 1; |
| 4207 | const max_field_size = 2; |
| 4208 | var wip_members = try WipMembers.init(gpa, &astgen.scratch, @intCast(u32, counts.decls), @intCast(u32, counts.total_fields), bits_per_field, max_field_size); |
| 4209 | defer wip_members.deinit(); |
| 4454 | 4210 | |
| 4455 | | var cur_bit_bag: u32 = 0; |
| 4456 | | var field_index: usize = 0; |
| 4457 | 4211 | for (container_decl.ast.members) |member_node| { |
| 4458 | 4212 | if (member_node == counts.nonexhaustive_node) |
| 4459 | 4213 | continue; |
| 4460 | | const member = switch (node_tags[member_node]) { |
| 4461 | | .container_field_init => tree.containerFieldInit(member_node), |
| 4462 | | .container_field_align => tree.containerFieldAlign(member_node), |
| 4463 | | .container_field => tree.containerField(member_node), |
| 4464 | | |
| 4465 | | .fn_decl => { |
| 4466 | | const fn_proto = node_datas[member_node].lhs; |
| 4467 | | const body = node_datas[member_node].rhs; |
| 4468 | | switch (node_tags[fn_proto]) { |
| 4469 | | .fn_proto_simple => { |
| 4470 | | var params: [1]Ast.Node.Index = undefined; |
| 4471 | | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProtoSimple(&params, fn_proto)) catch |err| switch (err) { |
| 4472 | | error.OutOfMemory => return error.OutOfMemory, |
| 4473 | | error.AnalysisFail => {}, |
| 4474 | | }; |
| 4475 | | continue; |
| 4476 | | }, |
| 4477 | | .fn_proto_multi => { |
| 4478 | | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProtoMulti(fn_proto)) catch |err| switch (err) { |
| 4479 | | error.OutOfMemory => return error.OutOfMemory, |
| 4480 | | error.AnalysisFail => {}, |
| 4481 | | }; |
| 4482 | | continue; |
| 4483 | | }, |
| 4484 | | .fn_proto_one => { |
| 4485 | | var params: [1]Ast.Node.Index = undefined; |
| 4486 | | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProtoOne(&params, fn_proto)) catch |err| switch (err) { |
| 4487 | | error.OutOfMemory => return error.OutOfMemory, |
| 4488 | | error.AnalysisFail => {}, |
| 4489 | | }; |
| 4490 | | continue; |
| 4491 | | }, |
| 4492 | | .fn_proto => { |
| 4493 | | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProto(fn_proto)) catch |err| switch (err) { |
| 4494 | | error.OutOfMemory => return error.OutOfMemory, |
| 4495 | | error.AnalysisFail => {}, |
| 4496 | | }; |
| 4497 | | continue; |
| 4498 | | }, |
| 4499 | | else => unreachable, |
| 4500 | | } |
| 4501 | | }, |
| 4502 | | .fn_proto_simple => { |
| 4503 | | var params: [1]Ast.Node.Index = undefined; |
| 4504 | | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProtoSimple(&params, member_node)) catch |err| switch (err) { |
| 4505 | | error.OutOfMemory => return error.OutOfMemory, |
| 4506 | | error.AnalysisFail => {}, |
| 4507 | | }; |
| 4508 | | continue; |
| 4509 | | }, |
| 4510 | | .fn_proto_multi => { |
| 4511 | | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProtoMulti(member_node)) catch |err| switch (err) { |
| 4512 | | error.OutOfMemory => return error.OutOfMemory, |
| 4513 | | error.AnalysisFail => {}, |
| 4514 | | }; |
| 4515 | | continue; |
| 4516 | | }, |
| 4517 | | .fn_proto_one => { |
| 4518 | | var params: [1]Ast.Node.Index = undefined; |
| 4519 | | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProtoOne(&params, member_node)) catch |err| switch (err) { |
| 4520 | | error.OutOfMemory => return error.OutOfMemory, |
| 4521 | | error.AnalysisFail => {}, |
| 4522 | | }; |
| 4523 | | continue; |
| 4524 | | }, |
| 4525 | | .fn_proto => { |
| 4526 | | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProto(member_node)) catch |err| switch (err) { |
| 4527 | | error.OutOfMemory => return error.OutOfMemory, |
| 4528 | | error.AnalysisFail => {}, |
| 4529 | | }; |
| 4530 | | continue; |
| 4531 | | }, |
| 4532 | | |
| 4533 | | .global_var_decl => { |
| 4534 | | astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.globalVarDecl(member_node)) catch |err| switch (err) { |
| 4535 | | error.OutOfMemory => return error.OutOfMemory, |
| 4536 | | error.AnalysisFail => {}, |
| 4537 | | }; |
| 4538 | | continue; |
| 4539 | | }, |
| 4540 | | .local_var_decl => { |
| 4541 | | astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.localVarDecl(member_node)) catch |err| switch (err) { |
| 4542 | | error.OutOfMemory => return error.OutOfMemory, |
| 4543 | | error.AnalysisFail => {}, |
| 4544 | | }; |
| 4545 | | continue; |
| 4546 | | }, |
| 4547 | | .simple_var_decl => { |
| 4548 | | astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.simpleVarDecl(member_node)) catch |err| switch (err) { |
| 4549 | | error.OutOfMemory => return error.OutOfMemory, |
| 4550 | | error.AnalysisFail => {}, |
| 4551 | | }; |
| 4552 | | continue; |
| 4553 | | }, |
| 4554 | | .aligned_var_decl => { |
| 4555 | | astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.alignedVarDecl(member_node)) catch |err| switch (err) { |
| 4556 | | error.OutOfMemory => return error.OutOfMemory, |
| 4557 | | error.AnalysisFail => {}, |
| 4558 | | }; |
| 4559 | | continue; |
| 4560 | | }, |
| 4561 | | |
| 4562 | | .@"comptime" => { |
| 4563 | | astgen.comptimeDecl(gz, &namespace.base, &wip_decls, member_node) catch |err| switch (err) { |
| 4564 | | error.OutOfMemory => return error.OutOfMemory, |
| 4565 | | error.AnalysisFail => {}, |
| 4566 | | }; |
| 4567 | | continue; |
| 4568 | | }, |
| 4569 | | .@"usingnamespace" => { |
| 4570 | | astgen.usingnamespaceDecl(gz, &namespace.base, &wip_decls, member_node) catch |err| switch (err) { |
| 4571 | | error.OutOfMemory => return error.OutOfMemory, |
| 4572 | | error.AnalysisFail => {}, |
| 4573 | | }; |
| 4574 | | continue; |
| 4575 | | }, |
| 4576 | | .test_decl => { |
| 4577 | | astgen.testDecl(gz, &namespace.base, &wip_decls, member_node) catch |err| switch (err) { |
| 4578 | | error.OutOfMemory => return error.OutOfMemory, |
| 4579 | | error.AnalysisFail => {}, |
| 4580 | | }; |
| 4581 | | continue; |
| 4582 | | }, |
| 4583 | | else => unreachable, |
| 4214 | const member = switch (try containerMember(gz, &namespace.base, &wip_members, member_node)) { |
| 4215 | .decl => continue, |
| 4216 | .field => |field| field, |
| 4584 | 4217 | }; |
| 4585 | | if (field_index % 32 == 0 and field_index != 0) { |
| 4586 | | try bit_bag.append(gpa, cur_bit_bag); |
| 4587 | | cur_bit_bag = 0; |
| 4588 | | } |
| 4589 | 4218 | assert(member.comptime_token == null); |
| 4590 | 4219 | assert(member.ast.type_expr == 0); |
| 4591 | 4220 | assert(member.ast.align_expr == 0); |
| 4592 | 4221 | |
| 4593 | 4222 | const field_name = try astgen.identAsString(member.ast.name_token); |
| 4594 | | fields_data.appendAssumeCapacity(field_name); |
| 4223 | wip_members.appendToField(field_name); |
| 4595 | 4224 | |
| 4596 | 4225 | const have_value = member.ast.value_expr != 0; |
| 4597 | | cur_bit_bag = (cur_bit_bag >> 1) | |
| 4598 | | (@as(u32, @boolToInt(have_value)) << 31); |
| 4226 | wip_members.nextField(bits_per_field, .{have_value}); |
| 4599 | 4227 | |
| 4600 | 4228 | if (have_value) { |
| 4601 | 4229 | if (arg_inst == .none) { |
| ... | ... | @@ -4613,60 +4241,35 @@ fn containerDecl( |
| 4613 | 4241 | ); |
| 4614 | 4242 | } |
| 4615 | 4243 | const tag_value_inst = try expr(&block_scope, &namespace.base, .{ .ty = arg_inst }, member.ast.value_expr); |
| 4616 | | fields_data.appendAssumeCapacity(@enumToInt(tag_value_inst)); |
| 4617 | | } |
| 4618 | | |
| 4619 | | field_index += 1; |
| 4620 | | } |
| 4621 | | { |
| 4622 | | const empty_slot_count = 32 - (field_index % 32); |
| 4623 | | if (empty_slot_count < 32) { |
| 4624 | | cur_bit_bag >>= @intCast(u5, empty_slot_count); |
| 4625 | | } |
| 4626 | | } |
| 4627 | | { |
| 4628 | | const empty_slot_count = WipDecls.fields_per_u32 - (wip_decls.decl_index % WipDecls.fields_per_u32); |
| 4629 | | if (empty_slot_count < WipDecls.fields_per_u32) { |
| 4630 | | wip_decls.cur_bit_bag >>= @intCast(u5, empty_slot_count * WipDecls.bits_per_field); |
| 4244 | wip_members.appendToField(@enumToInt(tag_value_inst)); |
| 4631 | 4245 | } |
| 4632 | 4246 | } |
| 4633 | 4247 | |
| 4634 | | if (block_scope.instructions.items.len != 0) { |
| 4248 | if (!block_scope.isEmpty()) { |
| 4635 | 4249 | _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value); |
| 4636 | 4250 | } |
| 4637 | 4251 | |
| 4252 | const body = block_scope.instructionsSlice(); |
| 4253 | |
| 4638 | 4254 | try gz.setEnum(decl_inst, .{ |
| 4639 | 4255 | .src_node = node, |
| 4640 | 4256 | .nonexhaustive = nonexhaustive, |
| 4641 | 4257 | .tag_type = arg_inst, |
| 4642 | | .body_len = @intCast(u32, block_scope.instructions.items.len), |
| 4643 | | .fields_len = @intCast(u32, field_index), |
| 4644 | | .decls_len = @intCast(u32, wip_decls.decl_index), |
| 4258 | .body_len = @intCast(u32, body.len), |
| 4259 | .fields_len = @intCast(u32, counts.total_fields), |
| 4260 | .decls_len = @intCast(u32, counts.decls), |
| 4645 | 4261 | }); |
| 4646 | 4262 | |
| 4647 | | // zig fmt: off |
| 4648 | | try astgen.extra.ensureUnusedCapacity(gpa, |
| 4649 | | bit_bag.items.len + |
| 4650 | | @boolToInt(wip_decls.decl_index != 0) + |
| 4651 | | wip_decls.payload.items.len + |
| 4652 | | block_scope.instructions.items.len + |
| 4653 | | wip_decls.bit_bag.items.len + |
| 4654 | | 1 + // cur_bit_bag |
| 4655 | | fields_data.items.len |
| 4656 | | ); |
| 4657 | | // zig fmt: on |
| 4658 | | |
| 4659 | | astgen.extra.appendSliceAssumeCapacity(wip_decls.bit_bag.items); // Likely empty. |
| 4660 | | if (wip_decls.decl_index != 0) { |
| 4661 | | astgen.extra.appendAssumeCapacity(wip_decls.cur_bit_bag); |
| 4662 | | } |
| 4663 | | astgen.extra.appendSliceAssumeCapacity(wip_decls.payload.items); |
| 4664 | | |
| 4665 | | astgen.extra.appendSliceAssumeCapacity(block_scope.instructions.items); |
| 4666 | | astgen.extra.appendSliceAssumeCapacity(bit_bag.items); // Likely empty. |
| 4667 | | astgen.extra.appendAssumeCapacity(cur_bit_bag); |
| 4668 | | astgen.extra.appendSliceAssumeCapacity(fields_data.items); |
| 4263 | wip_members.finishBits(bits_per_field); |
| 4264 | const decls_slice = wip_members.declsSlice(); |
| 4265 | const fields_slice = wip_members.fieldsSlice(); |
| 4266 | try astgen.extra.ensureUnusedCapacity(gpa, decls_slice.len + body.len + fields_slice.len); |
| 4267 | astgen.extra.appendSliceAssumeCapacity(decls_slice); |
| 4268 | astgen.extra.appendSliceAssumeCapacity(body); |
| 4269 | astgen.extra.appendSliceAssumeCapacity(fields_slice); |
| 4669 | 4270 | |
| 4271 | block_scope.unstack(); |
| 4272 | try gz.addNamespaceCaptures(&namespace); |
| 4670 | 4273 | return rvalue(gz, rl, indexToRef(decl_inst), node); |
| 4671 | 4274 | }, |
| 4672 | 4275 | .keyword_opaque => { |
| ... | ... | @@ -4682,166 +4285,155 @@ fn containerDecl( |
| 4682 | 4285 | }; |
| 4683 | 4286 | defer namespace.deinit(gpa); |
| 4684 | 4287 | |
| 4685 | | try astgen.scanDecls(&namespace, container_decl.ast.members); |
| 4288 | const decl_count = try astgen.scanDecls(&namespace, container_decl.ast.members); |
| 4686 | 4289 | |
| 4687 | | var wip_decls: WipDecls = .{}; |
| 4688 | | defer wip_decls.deinit(gpa); |
| 4290 | var wip_members = try WipMembers.init(gpa, &astgen.scratch, decl_count, 0, 0, 0); |
| 4291 | defer wip_members.deinit(); |
| 4689 | 4292 | |
| 4690 | 4293 | for (container_decl.ast.members) |member_node| { |
| 4691 | | switch (node_tags[member_node]) { |
| 4692 | | .container_field_init, .container_field_align, .container_field => {}, |
| 4693 | | |
| 4694 | | .fn_decl => { |
| 4695 | | const fn_proto = node_datas[member_node].lhs; |
| 4696 | | const body = node_datas[member_node].rhs; |
| 4697 | | switch (node_tags[fn_proto]) { |
| 4698 | | .fn_proto_simple => { |
| 4699 | | var params: [1]Ast.Node.Index = undefined; |
| 4700 | | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProtoSimple(&params, fn_proto)) catch |err| switch (err) { |
| 4701 | | error.OutOfMemory => return error.OutOfMemory, |
| 4702 | | error.AnalysisFail => {}, |
| 4703 | | }; |
| 4704 | | continue; |
| 4705 | | }, |
| 4706 | | .fn_proto_multi => { |
| 4707 | | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProtoMulti(fn_proto)) catch |err| switch (err) { |
| 4708 | | error.OutOfMemory => return error.OutOfMemory, |
| 4709 | | error.AnalysisFail => {}, |
| 4710 | | }; |
| 4711 | | continue; |
| 4712 | | }, |
| 4713 | | .fn_proto_one => { |
| 4714 | | var params: [1]Ast.Node.Index = undefined; |
| 4715 | | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProtoOne(&params, fn_proto)) catch |err| switch (err) { |
| 4716 | | error.OutOfMemory => return error.OutOfMemory, |
| 4717 | | error.AnalysisFail => {}, |
| 4718 | | }; |
| 4719 | | continue; |
| 4720 | | }, |
| 4721 | | .fn_proto => { |
| 4722 | | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, body, tree.fnProto(fn_proto)) catch |err| switch (err) { |
| 4723 | | error.OutOfMemory => return error.OutOfMemory, |
| 4724 | | error.AnalysisFail => {}, |
| 4725 | | }; |
| 4726 | | continue; |
| 4727 | | }, |
| 4728 | | else => unreachable, |
| 4729 | | } |
| 4730 | | }, |
| 4731 | | .fn_proto_simple => { |
| 4732 | | var params: [1]Ast.Node.Index = undefined; |
| 4733 | | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProtoSimple(&params, member_node)) catch |err| switch (err) { |
| 4734 | | error.OutOfMemory => return error.OutOfMemory, |
| 4735 | | error.AnalysisFail => {}, |
| 4736 | | }; |
| 4737 | | continue; |
| 4738 | | }, |
| 4739 | | .fn_proto_multi => { |
| 4740 | | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProtoMulti(member_node)) catch |err| switch (err) { |
| 4741 | | error.OutOfMemory => return error.OutOfMemory, |
| 4742 | | error.AnalysisFail => {}, |
| 4743 | | }; |
| 4744 | | continue; |
| 4745 | | }, |
| 4746 | | .fn_proto_one => { |
| 4747 | | var params: [1]Ast.Node.Index = undefined; |
| 4748 | | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProtoOne(&params, member_node)) catch |err| switch (err) { |
| 4749 | | error.OutOfMemory => return error.OutOfMemory, |
| 4750 | | error.AnalysisFail => {}, |
| 4751 | | }; |
| 4752 | | continue; |
| 4753 | | }, |
| 4754 | | .fn_proto => { |
| 4755 | | astgen.fnDecl(gz, &namespace.base, &wip_decls, member_node, 0, tree.fnProto(member_node)) catch |err| switch (err) { |
| 4756 | | error.OutOfMemory => return error.OutOfMemory, |
| 4757 | | error.AnalysisFail => {}, |
| 4758 | | }; |
| 4759 | | continue; |
| 4760 | | }, |
| 4761 | | |
| 4762 | | .global_var_decl => { |
| 4763 | | astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.globalVarDecl(member_node)) catch |err| switch (err) { |
| 4764 | | error.OutOfMemory => return error.OutOfMemory, |
| 4765 | | error.AnalysisFail => {}, |
| 4766 | | }; |
| 4767 | | continue; |
| 4768 | | }, |
| 4769 | | .local_var_decl => { |
| 4770 | | astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.localVarDecl(member_node)) catch |err| switch (err) { |
| 4771 | | error.OutOfMemory => return error.OutOfMemory, |
| 4772 | | error.AnalysisFail => {}, |
| 4773 | | }; |
| 4774 | | continue; |
| 4775 | | }, |
| 4776 | | .simple_var_decl => { |
| 4777 | | astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.simpleVarDecl(member_node)) catch |err| switch (err) { |
| 4778 | | error.OutOfMemory => return error.OutOfMemory, |
| 4779 | | error.AnalysisFail => {}, |
| 4780 | | }; |
| 4781 | | continue; |
| 4782 | | }, |
| 4783 | | .aligned_var_decl => { |
| 4784 | | astgen.globalVarDecl(gz, &namespace.base, &wip_decls, member_node, tree.alignedVarDecl(member_node)) catch |err| switch (err) { |
| 4785 | | error.OutOfMemory => return error.OutOfMemory, |
| 4786 | | error.AnalysisFail => {}, |
| 4787 | | }; |
| 4788 | | continue; |
| 4789 | | }, |
| 4790 | | |
| 4791 | | .@"comptime" => { |
| 4792 | | astgen.comptimeDecl(gz, &namespace.base, &wip_decls, member_node) catch |err| switch (err) { |
| 4793 | | error.OutOfMemory => return error.OutOfMemory, |
| 4794 | | error.AnalysisFail => {}, |
| 4795 | | }; |
| 4796 | | continue; |
| 4797 | | }, |
| 4798 | | .@"usingnamespace" => { |
| 4799 | | astgen.usingnamespaceDecl(gz, &namespace.base, &wip_decls, member_node) catch |err| switch (err) { |
| 4800 | | error.OutOfMemory => return error.OutOfMemory, |
| 4801 | | error.AnalysisFail => {}, |
| 4802 | | }; |
| 4803 | | continue; |
| 4804 | | }, |
| 4805 | | .test_decl => { |
| 4806 | | astgen.testDecl(gz, &namespace.base, &wip_decls, member_node) catch |err| switch (err) { |
| 4807 | | error.OutOfMemory => return error.OutOfMemory, |
| 4808 | | error.AnalysisFail => {}, |
| 4809 | | }; |
| 4810 | | continue; |
| 4811 | | }, |
| 4812 | | else => unreachable, |
| 4813 | | } |
| 4814 | | } |
| 4815 | | { |
| 4816 | | const empty_slot_count = WipDecls.fields_per_u32 - (wip_decls.decl_index % WipDecls.fields_per_u32); |
| 4817 | | if (empty_slot_count < WipDecls.fields_per_u32) { |
| 4818 | | wip_decls.cur_bit_bag >>= @intCast(u5, empty_slot_count * WipDecls.bits_per_field); |
| 4819 | | } |
| 4294 | _ = try containerMember(gz, &namespace.base, &wip_members, member_node); |
| 4820 | 4295 | } |
| 4821 | 4296 | |
| 4822 | 4297 | try gz.setOpaque(decl_inst, .{ |
| 4823 | 4298 | .src_node = node, |
| 4824 | | .decls_len = @intCast(u32, wip_decls.decl_index), |
| 4299 | .decls_len = decl_count, |
| 4825 | 4300 | }); |
| 4826 | 4301 | |
| 4827 | | // zig fmt: off |
| 4828 | | try astgen.extra.ensureUnusedCapacity(gpa, |
| 4829 | | wip_decls.bit_bag.items.len + |
| 4830 | | @boolToInt(wip_decls.decl_index != 0) + |
| 4831 | | wip_decls.payload.items.len |
| 4832 | | ); |
| 4833 | | // zig fmt: on |
| 4302 | wip_members.finishBits(0); |
| 4303 | const decls_slice = wip_members.declsSlice(); |
| 4304 | try astgen.extra.ensureUnusedCapacity(gpa, decls_slice.len); |
| 4305 | astgen.extra.appendSliceAssumeCapacity(decls_slice); |
| 4834 | 4306 | |
| 4835 | | astgen.extra.appendSliceAssumeCapacity(wip_decls.bit_bag.items); // Likely empty. |
| 4836 | | if (wip_decls.decl_index != 0) { |
| 4837 | | astgen.extra.appendAssumeCapacity(wip_decls.cur_bit_bag); |
| 4307 | try gz.addNamespaceCaptures(&namespace); |
| 4308 | return rvalue(gz, rl, indexToRef(decl_inst), node); |
| 4309 | }, |
| 4310 | else => unreachable, |
| 4311 | } |
| 4312 | } |
| 4313 | |
| 4314 | const ContainerMemberResult = union(enum) { decl, field: Ast.full.ContainerField }; |
| 4315 | |
| 4316 | fn containerMember( |
| 4317 | gz: *GenZir, |
| 4318 | scope: *Scope, |
| 4319 | wip_members: *WipMembers, |
| 4320 | member_node: Ast.Node.Index, |
| 4321 | ) InnerError!ContainerMemberResult { |
| 4322 | const astgen = gz.astgen; |
| 4323 | const tree = astgen.tree; |
| 4324 | const node_tags = tree.nodes.items(.tag); |
| 4325 | const node_datas = tree.nodes.items(.data); |
| 4326 | switch (node_tags[member_node]) { |
| 4327 | .container_field_init => return ContainerMemberResult{ .field = tree.containerFieldInit(member_node) }, |
| 4328 | .container_field_align => return ContainerMemberResult{ .field = tree.containerFieldAlign(member_node) }, |
| 4329 | .container_field => return ContainerMemberResult{ .field = tree.containerField(member_node) }, |
| 4330 | |
| 4331 | .fn_decl => { |
| 4332 | const fn_proto = node_datas[member_node].lhs; |
| 4333 | const body = node_datas[member_node].rhs; |
| 4334 | switch (node_tags[fn_proto]) { |
| 4335 | .fn_proto_simple => { |
| 4336 | var params: [1]Ast.Node.Index = undefined; |
| 4337 | astgen.fnDecl(gz, scope, wip_members, member_node, body, tree.fnProtoSimple(&params, fn_proto)) catch |err| switch (err) { |
| 4338 | error.OutOfMemory => return error.OutOfMemory, |
| 4339 | error.AnalysisFail => {}, |
| 4340 | }; |
| 4341 | }, |
| 4342 | .fn_proto_multi => { |
| 4343 | astgen.fnDecl(gz, scope, wip_members, member_node, body, tree.fnProtoMulti(fn_proto)) catch |err| switch (err) { |
| 4344 | error.OutOfMemory => return error.OutOfMemory, |
| 4345 | error.AnalysisFail => {}, |
| 4346 | }; |
| 4347 | }, |
| 4348 | .fn_proto_one => { |
| 4349 | var params: [1]Ast.Node.Index = undefined; |
| 4350 | astgen.fnDecl(gz, scope, wip_members, member_node, body, tree.fnProtoOne(&params, fn_proto)) catch |err| switch (err) { |
| 4351 | error.OutOfMemory => return error.OutOfMemory, |
| 4352 | error.AnalysisFail => {}, |
| 4353 | }; |
| 4354 | }, |
| 4355 | .fn_proto => { |
| 4356 | astgen.fnDecl(gz, scope, wip_members, member_node, body, tree.fnProto(fn_proto)) catch |err| switch (err) { |
| 4357 | error.OutOfMemory => return error.OutOfMemory, |
| 4358 | error.AnalysisFail => {}, |
| 4359 | }; |
| 4360 | }, |
| 4361 | else => unreachable, |
| 4838 | 4362 | } |
| 4839 | | astgen.extra.appendSliceAssumeCapacity(wip_decls.payload.items); |
| 4363 | }, |
| 4364 | .fn_proto_simple => { |
| 4365 | var params: [1]Ast.Node.Index = undefined; |
| 4366 | astgen.fnDecl(gz, scope, wip_members, member_node, 0, tree.fnProtoSimple(&params, member_node)) catch |err| switch (err) { |
| 4367 | error.OutOfMemory => return error.OutOfMemory, |
| 4368 | error.AnalysisFail => {}, |
| 4369 | }; |
| 4370 | }, |
| 4371 | .fn_proto_multi => { |
| 4372 | astgen.fnDecl(gz, scope, wip_members, member_node, 0, tree.fnProtoMulti(member_node)) catch |err| switch (err) { |
| 4373 | error.OutOfMemory => return error.OutOfMemory, |
| 4374 | error.AnalysisFail => {}, |
| 4375 | }; |
| 4376 | }, |
| 4377 | .fn_proto_one => { |
| 4378 | var params: [1]Ast.Node.Index = undefined; |
| 4379 | astgen.fnDecl(gz, scope, wip_members, member_node, 0, tree.fnProtoOne(&params, member_node)) catch |err| switch (err) { |
| 4380 | error.OutOfMemory => return error.OutOfMemory, |
| 4381 | error.AnalysisFail => {}, |
| 4382 | }; |
| 4383 | }, |
| 4384 | .fn_proto => { |
| 4385 | astgen.fnDecl(gz, scope, wip_members, member_node, 0, tree.fnProto(member_node)) catch |err| switch (err) { |
| 4386 | error.OutOfMemory => return error.OutOfMemory, |
| 4387 | error.AnalysisFail => {}, |
| 4388 | }; |
| 4389 | }, |
| 4840 | 4390 | |
| 4841 | | return rvalue(gz, rl, indexToRef(decl_inst), node); |
| 4391 | .global_var_decl => { |
| 4392 | astgen.globalVarDecl(gz, scope, wip_members, member_node, tree.globalVarDecl(member_node)) catch |err| switch (err) { |
| 4393 | error.OutOfMemory => return error.OutOfMemory, |
| 4394 | error.AnalysisFail => {}, |
| 4395 | }; |
| 4396 | }, |
| 4397 | .local_var_decl => { |
| 4398 | astgen.globalVarDecl(gz, scope, wip_members, member_node, tree.localVarDecl(member_node)) catch |err| switch (err) { |
| 4399 | error.OutOfMemory => return error.OutOfMemory, |
| 4400 | error.AnalysisFail => {}, |
| 4401 | }; |
| 4402 | }, |
| 4403 | .simple_var_decl => { |
| 4404 | astgen.globalVarDecl(gz, scope, wip_members, member_node, tree.simpleVarDecl(member_node)) catch |err| switch (err) { |
| 4405 | error.OutOfMemory => return error.OutOfMemory, |
| 4406 | error.AnalysisFail => {}, |
| 4407 | }; |
| 4408 | }, |
| 4409 | .aligned_var_decl => { |
| 4410 | astgen.globalVarDecl(gz, scope, wip_members, member_node, tree.alignedVarDecl(member_node)) catch |err| switch (err) { |
| 4411 | error.OutOfMemory => return error.OutOfMemory, |
| 4412 | error.AnalysisFail => {}, |
| 4413 | }; |
| 4414 | }, |
| 4415 | |
| 4416 | .@"comptime" => { |
| 4417 | astgen.comptimeDecl(gz, scope, wip_members, member_node) catch |err| switch (err) { |
| 4418 | error.OutOfMemory => return error.OutOfMemory, |
| 4419 | error.AnalysisFail => {}, |
| 4420 | }; |
| 4421 | }, |
| 4422 | .@"usingnamespace" => { |
| 4423 | astgen.usingnamespaceDecl(gz, scope, wip_members, member_node) catch |err| switch (err) { |
| 4424 | error.OutOfMemory => return error.OutOfMemory, |
| 4425 | error.AnalysisFail => {}, |
| 4426 | }; |
| 4427 | }, |
| 4428 | .test_decl => { |
| 4429 | astgen.testDecl(gz, scope, wip_members, member_node) catch |err| switch (err) { |
| 4430 | error.OutOfMemory => return error.OutOfMemory, |
| 4431 | error.AnalysisFail => {}, |
| 4432 | }; |
| 4842 | 4433 | }, |
| 4843 | 4434 | else => unreachable, |
| 4844 | 4435 | } |
| 4436 | return .decl; |
| 4845 | 4437 | } |
| 4846 | 4438 | |
| 4847 | 4439 | fn errorSetDecl(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index) InnerError!Zir.Inst.Ref { |
| ... | ... | @@ -4851,20 +4443,18 @@ fn errorSetDecl(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index) InnerError!Zir |
| 4851 | 4443 | const main_tokens = tree.nodes.items(.main_token); |
| 4852 | 4444 | const token_tags = tree.tokens.items(.tag); |
| 4853 | 4445 | |
| 4854 | | var field_names: std.ArrayListUnmanaged(u32) = .{}; |
| 4855 | | defer field_names.deinit(gpa); |
| 4856 | | |
| 4446 | const payload_index = try reserveExtra(astgen, @typeInfo(Zir.Inst.ErrorSetDecl).Struct.fields.len); |
| 4447 | var fields_len: usize = 0; |
| 4857 | 4448 | { |
| 4858 | 4449 | const error_token = main_tokens[node]; |
| 4859 | 4450 | var tok_i = error_token + 2; |
| 4860 | | var field_i: usize = 0; |
| 4861 | 4451 | while (true) : (tok_i += 1) { |
| 4862 | 4452 | switch (token_tags[tok_i]) { |
| 4863 | 4453 | .doc_comment, .comma => {}, |
| 4864 | 4454 | .identifier => { |
| 4865 | 4455 | const str_index = try astgen.identAsString(tok_i); |
| 4866 | | try field_names.append(gpa, str_index); |
| 4867 | | field_i += 1; |
| 4456 | try astgen.extra.append(gpa, str_index); |
| 4457 | fields_len += 1; |
| 4868 | 4458 | }, |
| 4869 | 4459 | .r_brace => break, |
| 4870 | 4460 | else => unreachable, |
| ... | ... | @@ -4872,10 +4462,10 @@ fn errorSetDecl(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index) InnerError!Zir |
| 4872 | 4462 | } |
| 4873 | 4463 | } |
| 4874 | 4464 | |
| 4875 | | const result = try gz.addPlNode(.error_set_decl, node, Zir.Inst.ErrorSetDecl{ |
| 4876 | | .fields_len = @intCast(u32, field_names.items.len), |
| 4465 | setExtra(astgen, payload_index, Zir.Inst.ErrorSetDecl{ |
| 4466 | .fields_len = @intCast(u32, fields_len), |
| 4877 | 4467 | }); |
| 4878 | | try astgen.extra.appendSlice(gpa, field_names.items); |
| 4468 | const result = try gz.addPlNodePayloadIndex(.error_set_decl, node, payload_index); |
| 4879 | 4469 | return rvalue(gz, rl, result, node); |
| 4880 | 4470 | } |
| 4881 | 4471 | |
| ... | ... | @@ -4896,7 +4486,7 @@ fn tryExpr( |
| 4896 | 4486 | |
| 4897 | 4487 | var block_scope = parent_gz.makeSubBlock(scope); |
| 4898 | 4488 | block_scope.setBreakResultLoc(rl); |
| 4899 | | defer block_scope.instructions.deinit(astgen.gpa); |
| 4489 | defer block_scope.unstack(); |
| 4900 | 4490 | |
| 4901 | 4491 | const operand_rl: ResultLoc = switch (block_scope.break_result_loc) { |
| 4902 | 4492 | .ref => .ref, |
| ... | ... | @@ -4916,12 +4506,13 @@ fn tryExpr( |
| 4916 | 4506 | const cond = try block_scope.addUnNode(err_ops[0], operand, node); |
| 4917 | 4507 | const condbr = try block_scope.addCondBr(.condbr, node); |
| 4918 | 4508 | |
| 4919 | | const block = try parent_gz.addBlock(.block, node); |
| 4920 | | try parent_gz.instructions.append(astgen.gpa, block); |
| 4509 | const block = try parent_gz.makeBlockInst(.block, node); |
| 4921 | 4510 | try block_scope.setBlockBody(block); |
| 4511 | // block_scope unstacked now, can add new instructions to parent_gz |
| 4512 | try parent_gz.instructions.append(astgen.gpa, block); |
| 4922 | 4513 | |
| 4923 | 4514 | var then_scope = parent_gz.makeSubBlock(scope); |
| 4924 | | defer then_scope.instructions.deinit(astgen.gpa); |
| 4515 | defer then_scope.unstack(); |
| 4925 | 4516 | |
| 4926 | 4517 | block_scope.break_count += 1; |
| 4927 | 4518 | // This could be a pointer or value depending on `err_ops[2]`. |
| ... | ... | @@ -4931,8 +4522,9 @@ fn tryExpr( |
| 4931 | 4522 | else => try rvalue(&then_scope, block_scope.break_result_loc, unwrapped_payload, node), |
| 4932 | 4523 | }; |
| 4933 | 4524 | |
| 4525 | // else_scope will be stacked on then_scope as both are stacked on parent_gz |
| 4934 | 4526 | var else_scope = parent_gz.makeSubBlock(scope); |
| 4935 | | defer else_scope.instructions.deinit(astgen.gpa); |
| 4527 | defer else_scope.unstack(); |
| 4936 | 4528 | |
| 4937 | 4529 | const err_code = try else_scope.addUnNode(err_ops[1], operand, node); |
| 4938 | 4530 | try genDefers(&else_scope, &fn_block.base, scope, .{ .both = err_code }); |
| ... | ... | @@ -4972,7 +4564,7 @@ fn orelseCatchExpr( |
| 4972 | 4564 | |
| 4973 | 4565 | var block_scope = parent_gz.makeSubBlock(scope); |
| 4974 | 4566 | block_scope.setBreakResultLoc(rl); |
| 4975 | | defer block_scope.instructions.deinit(astgen.gpa); |
| 4567 | defer block_scope.unstack(); |
| 4976 | 4568 | |
| 4977 | 4569 | const operand_rl: ResultLoc = switch (block_scope.break_result_loc) { |
| 4978 | 4570 | .ref => .ref, |
| ... | ... | @@ -4987,12 +4579,13 @@ fn orelseCatchExpr( |
| 4987 | 4579 | const cond = try block_scope.addUnNode(cond_op, operand, node); |
| 4988 | 4580 | const condbr = try block_scope.addCondBr(.condbr, node); |
| 4989 | 4581 | |
| 4990 | | const block = try parent_gz.addBlock(.block, node); |
| 4991 | | try parent_gz.instructions.append(astgen.gpa, block); |
| 4582 | const block = try parent_gz.makeBlockInst(.block, node); |
| 4992 | 4583 | try block_scope.setBlockBody(block); |
| 4584 | // block_scope unstacked now, can add new instructions to parent_gz |
| 4585 | try parent_gz.instructions.append(astgen.gpa, block); |
| 4993 | 4586 | |
| 4994 | 4587 | var then_scope = parent_gz.makeSubBlock(scope); |
| 4995 | | defer then_scope.instructions.deinit(astgen.gpa); |
| 4588 | defer then_scope.unstack(); |
| 4996 | 4589 | |
| 4997 | 4590 | // This could be a pointer or value depending on `unwrap_op`. |
| 4998 | 4591 | const unwrapped_payload = try then_scope.addUnNode(unwrap_op, operand, node); |
| ... | ... | @@ -5002,7 +4595,7 @@ fn orelseCatchExpr( |
| 5002 | 4595 | }; |
| 5003 | 4596 | |
| 5004 | 4597 | var else_scope = parent_gz.makeSubBlock(scope); |
| 5005 | | defer else_scope.instructions.deinit(astgen.gpa); |
| 4598 | defer else_scope.unstack(); |
| 5006 | 4599 | |
| 5007 | 4600 | var err_val_scope: Scope.LocalVal = undefined; |
| 5008 | 4601 | const else_sub_scope = blk: { |
| ... | ... | @@ -5049,6 +4642,7 @@ fn orelseCatchExpr( |
| 5049 | 4642 | ); |
| 5050 | 4643 | } |
| 5051 | 4644 | |
| 4645 | /// Supports `else_scope` stacked on `then_scope` stacked on `block_scope`. Unstacks `else_scope` then `then_scope`. |
| 5052 | 4646 | fn finishThenElseBlock( |
| 5053 | 4647 | parent_gz: *GenZir, |
| 5054 | 4648 | rl: ResultLoc, |
| ... | ... | @@ -5067,33 +4661,33 @@ fn finishThenElseBlock( |
| 5067 | 4661 | // We now have enough information to decide whether the result instruction should |
| 5068 | 4662 | // be communicated via result location pointer or break instructions. |
| 5069 | 4663 | const strat = rl.strategy(block_scope); |
| 4664 | // else_scope may be stacked on then_scope, so check for no-return on then_scope manually |
| 4665 | const tags = parent_gz.astgen.instructions.items(.tag); |
| 4666 | const then_slice = then_scope.instructionsSliceUpto(else_scope); |
| 4667 | const then_no_return = then_slice.len > 0 and tags[then_slice[then_slice.len - 1]].isNoReturn(); |
| 4668 | const else_no_return = else_scope.endsWithNoReturn(); |
| 4669 | |
| 5070 | 4670 | switch (strat.tag) { |
| 5071 | 4671 | .break_void => { |
| 5072 | | if (!then_scope.endsWithNoReturn()) { |
| 5073 | | _ = try then_scope.addBreak(break_tag, then_break_block, .void_value); |
| 5074 | | } |
| 5075 | | if (!else_scope.endsWithNoReturn()) { |
| 5076 | | _ = try else_scope.addBreak(break_tag, main_block, .void_value); |
| 5077 | | } |
| 4672 | const then_break = if (!then_no_return) try then_scope.makeBreak(break_tag, then_break_block, .void_value) else 0; |
| 4673 | const else_break = if (!else_no_return) try else_scope.makeBreak(break_tag, main_block, .void_value) else 0; |
| 5078 | 4674 | assert(!strat.elide_store_to_block_ptr_instructions); |
| 5079 | | try setCondBrPayload(condbr, cond, then_scope, else_scope); |
| 4675 | try setCondBrPayload(condbr, cond, then_scope, then_break, else_scope, else_break); |
| 5080 | 4676 | return indexToRef(main_block); |
| 5081 | 4677 | }, |
| 5082 | 4678 | .break_operand => { |
| 5083 | | if (!then_scope.endsWithNoReturn()) { |
| 5084 | | _ = try then_scope.addBreak(break_tag, then_break_block, then_result); |
| 5085 | | } |
| 5086 | | if (else_result != .none) { |
| 5087 | | if (!else_scope.endsWithNoReturn()) { |
| 5088 | | _ = try else_scope.addBreak(break_tag, main_block, else_result); |
| 5089 | | } |
| 5090 | | } else { |
| 5091 | | _ = try else_scope.addBreak(break_tag, main_block, .void_value); |
| 5092 | | } |
| 4679 | const then_break = if (!then_no_return) try then_scope.makeBreak(break_tag, then_break_block, then_result) else 0; |
| 4680 | const else_break = if (else_result == .none) |
| 4681 | try else_scope.makeBreak(break_tag, main_block, .void_value) |
| 4682 | else if (!else_no_return) |
| 4683 | try else_scope.makeBreak(break_tag, main_block, else_result) |
| 4684 | else |
| 4685 | 0; |
| 4686 | |
| 5093 | 4687 | if (strat.elide_store_to_block_ptr_instructions) { |
| 5094 | | try setCondBrPayloadElideBlockStorePtr(condbr, cond, then_scope, else_scope, block_scope.rl_ptr); |
| 4688 | try setCondBrPayloadElideBlockStorePtr(condbr, cond, then_scope, then_break, else_scope, else_break, block_scope.rl_ptr); |
| 5095 | 4689 | } else { |
| 5096 | | try setCondBrPayload(condbr, cond, then_scope, else_scope); |
| 4690 | try setCondBrPayload(condbr, cond, then_scope, then_break, else_scope, else_break); |
| 5097 | 4691 | } |
| 5098 | 4692 | const block_ref = indexToRef(main_block); |
| 5099 | 4693 | switch (rl) { |
| ... | ... | @@ -5221,7 +4815,7 @@ fn boolBinOp( |
| 5221 | 4815 | const bool_br = try gz.addBoolBr(zir_tag, lhs); |
| 5222 | 4816 | |
| 5223 | 4817 | var rhs_scope = gz.makeSubBlock(scope); |
| 5224 | | defer rhs_scope.instructions.deinit(gz.astgen.gpa); |
| 4818 | defer rhs_scope.unstack(); |
| 5225 | 4819 | const rhs = try expr(&rhs_scope, &rhs_scope.base, bool_rl, node_datas[node].rhs); |
| 5226 | 4820 | if (!gz.refIsNoReturn(rhs)) { |
| 5227 | 4821 | _ = try rhs_scope.addBreak(.break_inline, bool_br, rhs); |
| ... | ... | @@ -5245,7 +4839,7 @@ fn ifExpr( |
| 5245 | 4839 | |
| 5246 | 4840 | var block_scope = parent_gz.makeSubBlock(scope); |
| 5247 | 4841 | block_scope.setBreakResultLoc(rl); |
| 5248 | | defer block_scope.instructions.deinit(astgen.gpa); |
| 4842 | defer block_scope.unstack(); |
| 5249 | 4843 | |
| 5250 | 4844 | const payload_is_ref = if (if_full.payload_token) |payload_token| |
| 5251 | 4845 | token_tags[payload_token] == .asterisk |
| ... | ... | @@ -5283,12 +4877,13 @@ fn ifExpr( |
| 5283 | 4877 | |
| 5284 | 4878 | const condbr = try block_scope.addCondBr(.condbr, node); |
| 5285 | 4879 | |
| 5286 | | const block = try parent_gz.addBlock(.block, node); |
| 5287 | | try parent_gz.instructions.append(astgen.gpa, block); |
| 4880 | const block = try parent_gz.makeBlockInst(.block, node); |
| 5288 | 4881 | try block_scope.setBlockBody(block); |
| 4882 | // block_scope unstacked now, can add new instructions to parent_gz |
| 4883 | try parent_gz.instructions.append(astgen.gpa, block); |
| 5289 | 4884 | |
| 5290 | 4885 | var then_scope = parent_gz.makeSubBlock(scope); |
| 5291 | | defer then_scope.instructions.deinit(astgen.gpa); |
| 4886 | defer then_scope.unstack(); |
| 5292 | 4887 | |
| 5293 | 4888 | var payload_val_scope: Scope.LocalVal = undefined; |
| 5294 | 4889 | |
| ... | ... | @@ -5354,7 +4949,7 @@ fn ifExpr( |
| 5354 | 4949 | // instructions or not. |
| 5355 | 4950 | |
| 5356 | 4951 | var else_scope = parent_gz.makeSubBlock(scope); |
| 5357 | | defer else_scope.instructions.deinit(astgen.gpa); |
| 4952 | defer else_scope.unstack(); |
| 5358 | 4953 | |
| 5359 | 4954 | const else_node = if_full.ast.else_expr; |
| 5360 | 4955 | const else_info: struct { |
| ... | ... | @@ -5417,52 +5012,70 @@ fn ifExpr( |
| 5417 | 5012 | ); |
| 5418 | 5013 | } |
| 5419 | 5014 | |
| 5015 | /// Supports `else_scope` stacked on `then_scope`. Unstacks `else_scope` then `then_scope`. |
| 5420 | 5016 | fn setCondBrPayload( |
| 5421 | 5017 | condbr: Zir.Inst.Index, |
| 5422 | 5018 | cond: Zir.Inst.Ref, |
| 5423 | 5019 | then_scope: *GenZir, |
| 5020 | then_break: Zir.Inst.Index, |
| 5424 | 5021 | else_scope: *GenZir, |
| 5022 | else_break: Zir.Inst.Index, |
| 5425 | 5023 | ) !void { |
| 5024 | defer then_scope.unstack(); |
| 5025 | defer else_scope.unstack(); |
| 5426 | 5026 | const astgen = then_scope.astgen; |
| 5427 | | |
| 5027 | const then_body = then_scope.instructionsSliceUpto(else_scope); |
| 5028 | const else_body = else_scope.instructionsSlice(); |
| 5029 | const then_body_len = @intCast(u32, then_body.len + @boolToInt(then_break != 0)); |
| 5030 | const else_body_len = @intCast(u32, else_body.len + @boolToInt(else_break != 0)); |
| 5428 | 5031 | try astgen.extra.ensureUnusedCapacity(astgen.gpa, @typeInfo(Zir.Inst.CondBr).Struct.fields.len + |
| 5429 | | then_scope.instructions.items.len + else_scope.instructions.items.len); |
| 5032 | then_body_len + else_body_len); |
| 5430 | 5033 | |
| 5431 | 5034 | const zir_datas = astgen.instructions.items(.data); |
| 5432 | 5035 | zir_datas[condbr].pl_node.payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.CondBr{ |
| 5433 | 5036 | .condition = cond, |
| 5434 | | .then_body_len = @intCast(u32, then_scope.instructions.items.len), |
| 5435 | | .else_body_len = @intCast(u32, else_scope.instructions.items.len), |
| 5037 | .then_body_len = then_body_len, |
| 5038 | .else_body_len = else_body_len, |
| 5436 | 5039 | }); |
| 5437 | | astgen.extra.appendSliceAssumeCapacity(then_scope.instructions.items); |
| 5438 | | astgen.extra.appendSliceAssumeCapacity(else_scope.instructions.items); |
| 5040 | astgen.extra.appendSliceAssumeCapacity(then_body); |
| 5041 | if (then_break != 0) astgen.extra.appendAssumeCapacity(then_break); |
| 5042 | astgen.extra.appendSliceAssumeCapacity(else_body); |
| 5043 | if (else_break != 0) astgen.extra.appendAssumeCapacity(else_break); |
| 5439 | 5044 | } |
| 5440 | 5045 | |
| 5046 | /// Supports `else_scope` stacked on `then_scope`. Unstacks `else_scope` then `then_scope`. |
| 5441 | 5047 | fn setCondBrPayloadElideBlockStorePtr( |
| 5442 | 5048 | condbr: Zir.Inst.Index, |
| 5443 | 5049 | cond: Zir.Inst.Ref, |
| 5444 | 5050 | then_scope: *GenZir, |
| 5051 | then_break: Zir.Inst.Index, |
| 5445 | 5052 | else_scope: *GenZir, |
| 5053 | else_break: Zir.Inst.Index, |
| 5446 | 5054 | block_ptr: Zir.Inst.Ref, |
| 5447 | 5055 | ) !void { |
| 5056 | defer then_scope.unstack(); |
| 5057 | defer else_scope.unstack(); |
| 5448 | 5058 | const astgen = then_scope.astgen; |
| 5449 | | |
| 5059 | const then_body = then_scope.instructionsSliceUpto(else_scope); |
| 5060 | const else_body = else_scope.instructionsSlice(); |
| 5061 | const then_body_len = @intCast(u32, then_body.len + @boolToInt(then_break != 0)); |
| 5062 | const else_body_len = @intCast(u32, else_body.len + @boolToInt(else_break != 0)); |
| 5450 | 5063 | try astgen.extra.ensureUnusedCapacity(astgen.gpa, @typeInfo(Zir.Inst.CondBr).Struct.fields.len + |
| 5451 | | then_scope.instructions.items.len + else_scope.instructions.items.len); |
| 5064 | then_body_len + else_body_len); |
| 5452 | 5065 | |
| 5453 | 5066 | const zir_tags = astgen.instructions.items(.tag); |
| 5454 | 5067 | const zir_datas = astgen.instructions.items(.data); |
| 5455 | 5068 | |
| 5456 | 5069 | const condbr_pl = astgen.addExtraAssumeCapacity(Zir.Inst.CondBr{ |
| 5457 | 5070 | .condition = cond, |
| 5458 | | .then_body_len = @intCast(u32, then_scope.instructions.items.len), |
| 5459 | | .else_body_len = @intCast(u32, else_scope.instructions.items.len), |
| 5071 | .then_body_len = then_body_len, |
| 5072 | .else_body_len = else_body_len, |
| 5460 | 5073 | }); |
| 5461 | 5074 | zir_datas[condbr].pl_node.payload_index = condbr_pl; |
| 5462 | 5075 | const then_body_len_index = condbr_pl + 1; |
| 5463 | 5076 | const else_body_len_index = condbr_pl + 2; |
| 5464 | 5077 | |
| 5465 | | for (then_scope.instructions.items) |src_inst| { |
| 5078 | for (then_body) |src_inst| { |
| 5466 | 5079 | if (zir_tags[src_inst] == .store_to_block_ptr) { |
| 5467 | 5080 | if (zir_datas[src_inst].bin.lhs == block_ptr) { |
| 5468 | 5081 | astgen.extra.items[then_body_len_index] -= 1; |
| ... | ... | @@ -5471,7 +5084,8 @@ fn setCondBrPayloadElideBlockStorePtr( |
| 5471 | 5084 | } |
| 5472 | 5085 | astgen.extra.appendAssumeCapacity(src_inst); |
| 5473 | 5086 | } |
| 5474 | | for (else_scope.instructions.items) |src_inst| { |
| 5087 | if (then_break != 0) astgen.extra.appendAssumeCapacity(then_break); |
| 5088 | for (else_body) |src_inst| { |
| 5475 | 5089 | if (zir_tags[src_inst] == .store_to_block_ptr) { |
| 5476 | 5090 | if (zir_datas[src_inst].bin.lhs == block_ptr) { |
| 5477 | 5091 | astgen.extra.items[else_body_len_index] -= 1; |
| ... | ... | @@ -5480,6 +5094,7 @@ fn setCondBrPayloadElideBlockStorePtr( |
| 5480 | 5094 | } |
| 5481 | 5095 | astgen.extra.appendAssumeCapacity(src_inst); |
| 5482 | 5096 | } |
| 5097 | if (else_break != 0) astgen.extra.appendAssumeCapacity(else_break); |
| 5483 | 5098 | } |
| 5484 | 5099 | |
| 5485 | 5100 | fn whileExpr( |
| ... | ... | @@ -5499,17 +5114,17 @@ fn whileExpr( |
| 5499 | 5114 | |
| 5500 | 5115 | const is_inline = parent_gz.force_comptime or while_full.inline_token != null; |
| 5501 | 5116 | const loop_tag: Zir.Inst.Tag = if (is_inline) .block_inline else .loop; |
| 5502 | | const loop_block = try parent_gz.addBlock(loop_tag, node); |
| 5117 | const loop_block = try parent_gz.makeBlockInst(loop_tag, node); |
| 5503 | 5118 | try parent_gz.instructions.append(astgen.gpa, loop_block); |
| 5504 | 5119 | |
| 5505 | 5120 | var loop_scope = parent_gz.makeSubBlock(scope); |
| 5506 | 5121 | loop_scope.setBreakResultLoc(rl); |
| 5507 | | defer loop_scope.instructions.deinit(astgen.gpa); |
| 5122 | defer loop_scope.unstack(); |
| 5508 | 5123 | defer loop_scope.labeled_breaks.deinit(astgen.gpa); |
| 5509 | 5124 | defer loop_scope.labeled_store_to_block_ptr_list.deinit(astgen.gpa); |
| 5510 | 5125 | |
| 5511 | 5126 | var continue_scope = parent_gz.makeSubBlock(&loop_scope.base); |
| 5512 | | defer continue_scope.instructions.deinit(astgen.gpa); |
| 5127 | defer continue_scope.unstack(); |
| 5513 | 5128 | |
| 5514 | 5129 | const payload_is_ref = if (while_full.payload_token) |payload_token| |
| 5515 | 5130 | token_tags[payload_token] == .asterisk |
| ... | ... | @@ -5548,15 +5163,19 @@ fn whileExpr( |
| 5548 | 5163 | const condbr_tag: Zir.Inst.Tag = if (is_inline) .condbr_inline else .condbr; |
| 5549 | 5164 | const condbr = try continue_scope.addCondBr(condbr_tag, node); |
| 5550 | 5165 | const block_tag: Zir.Inst.Tag = if (is_inline) .block_inline else .block; |
| 5551 | | const cond_block = try loop_scope.addBlock(block_tag, node); |
| 5552 | | try loop_scope.instructions.append(astgen.gpa, cond_block); |
| 5166 | const cond_block = try loop_scope.makeBlockInst(block_tag, node); |
| 5553 | 5167 | try continue_scope.setBlockBody(cond_block); |
| 5168 | // continue_scope unstacked now, can add new instructions to loop_scope |
| 5169 | try loop_scope.instructions.append(astgen.gpa, cond_block); |
| 5554 | 5170 | |
| 5171 | // make scope now but don't stack on parent_gz until loop_scope |
| 5172 | // gets unstacked after cont_expr is emitted and added below |
| 5555 | 5173 | var then_scope = parent_gz.makeSubBlock(&continue_scope.base); |
| 5556 | | defer then_scope.instructions.deinit(astgen.gpa); |
| 5174 | then_scope.instructions_top = GenZir.unstacked_top; |
| 5175 | defer then_scope.unstack(); |
| 5557 | 5176 | |
| 5177 | var payload_inst: Zir.Inst.Index = 0; |
| 5558 | 5178 | var payload_val_scope: Scope.LocalVal = undefined; |
| 5559 | | |
| 5560 | 5179 | const then_sub_scope = s: { |
| 5561 | 5180 | if (while_full.error_token != null) { |
| 5562 | 5181 | if (while_full.payload_token) |payload_token| { |
| ... | ... | @@ -5564,7 +5183,8 @@ fn whileExpr( |
| 5564 | 5183 | .err_union_payload_unsafe_ptr |
| 5565 | 5184 | else |
| 5566 | 5185 | .err_union_payload_unsafe; |
| 5567 | | const payload_inst = try then_scope.addUnNode(tag, cond.inst, node); |
| 5186 | // will add this instruction to then_scope.instructions below |
| 5187 | payload_inst = try then_scope.makeUnNode(tag, cond.inst, node); |
| 5568 | 5188 | const ident_token = if (payload_is_ref) payload_token + 1 else payload_token; |
| 5569 | 5189 | const ident_bytes = tree.tokenSlice(ident_token); |
| 5570 | 5190 | if (mem.eql(u8, "_", ident_bytes)) |
| ... | ... | @@ -5576,7 +5196,7 @@ fn whileExpr( |
| 5576 | 5196 | .parent = &then_scope.base, |
| 5577 | 5197 | .gen_zir = &then_scope, |
| 5578 | 5198 | .name = ident_name, |
| 5579 | | .inst = payload_inst, |
| 5199 | .inst = indexToRef(payload_inst), |
| 5580 | 5200 | .token_src = payload_token, |
| 5581 | 5201 | .id_cat = .@"capture", |
| 5582 | 5202 | }; |
| ... | ... | @@ -5590,7 +5210,8 @@ fn whileExpr( |
| 5590 | 5210 | .optional_payload_unsafe_ptr |
| 5591 | 5211 | else |
| 5592 | 5212 | .optional_payload_unsafe; |
| 5593 | | const payload_inst = try then_scope.addUnNode(tag, cond.inst, node); |
| 5213 | // will add this instruction to then_scope.instructions below |
| 5214 | payload_inst = try then_scope.makeUnNode(tag, cond.inst, node); |
| 5594 | 5215 | const ident_name = try astgen.identAsString(ident_token); |
| 5595 | 5216 | const ident_bytes = tree.tokenSlice(ident_token); |
| 5596 | 5217 | if (mem.eql(u8, "_", ident_bytes)) |
| ... | ... | @@ -5600,7 +5221,7 @@ fn whileExpr( |
| 5600 | 5221 | .parent = &then_scope.base, |
| 5601 | 5222 | .gen_zir = &then_scope, |
| 5602 | 5223 | .name = ident_name, |
| 5603 | | .inst = payload_inst, |
| 5224 | .inst = indexToRef(payload_inst), |
| 5604 | 5225 | .token_src = ident_token, |
| 5605 | 5226 | .id_cat = .@"capture", |
| 5606 | 5227 | }; |
| ... | ... | @@ -5630,6 +5251,9 @@ fn whileExpr( |
| 5630 | 5251 | }); |
| 5631 | 5252 | } |
| 5632 | 5253 | |
| 5254 | // done adding instructions to loop_scope, can now stack then_scope |
| 5255 | then_scope.instructions_top = then_scope.instructions.items.len; |
| 5256 | if (payload_inst != 0) try then_scope.instructions.append(astgen.gpa, payload_inst); |
| 5633 | 5257 | const then_result = try expr(&then_scope, then_sub_scope, loop_scope.break_result_loc, while_full.ast.then_expr); |
| 5634 | 5258 | if (!then_scope.endsWithNoReturn()) { |
| 5635 | 5259 | loop_scope.break_count += 1; |
| ... | ... | @@ -5637,7 +5261,7 @@ fn whileExpr( |
| 5637 | 5261 | try checkUsed(parent_gz, &then_scope.base, then_sub_scope); |
| 5638 | 5262 | |
| 5639 | 5263 | var else_scope = parent_gz.makeSubBlock(&continue_scope.base); |
| 5640 | | defer else_scope.instructions.deinit(astgen.gpa); |
| 5264 | defer else_scope.unstack(); |
| 5641 | 5265 | |
| 5642 | 5266 | const else_node = while_full.ast.else_expr; |
| 5643 | 5267 | const else_info: struct { |
| ... | ... | @@ -5650,7 +5274,7 @@ fn whileExpr( |
| 5650 | 5274 | .err_union_code_ptr |
| 5651 | 5275 | else |
| 5652 | 5276 | .err_union_code; |
| 5653 | | const payload_inst = try else_scope.addUnNode(tag, cond.inst, node); |
| 5277 | const else_payload_inst = try else_scope.addUnNode(tag, cond.inst, node); |
| 5654 | 5278 | const ident_name = try astgen.identAsString(error_token); |
| 5655 | 5279 | const ident_bytes = tree.tokenSlice(error_token); |
| 5656 | 5280 | if (mem.eql(u8, ident_bytes, "_")) |
| ... | ... | @@ -5660,7 +5284,7 @@ fn whileExpr( |
| 5660 | 5284 | .parent = &else_scope.base, |
| 5661 | 5285 | .gen_zir = &else_scope, |
| 5662 | 5286 | .name = ident_name, |
| 5663 | | .inst = payload_inst, |
| 5287 | .inst = else_payload_inst, |
| 5664 | 5288 | .token_src = error_token, |
| 5665 | 5289 | .id_cat = .@"capture", |
| 5666 | 5290 | }; |
| ... | ... | @@ -5742,17 +5366,17 @@ fn forExpr( |
| 5742 | 5366 | }; |
| 5743 | 5367 | |
| 5744 | 5368 | const loop_tag: Zir.Inst.Tag = if (is_inline) .block_inline else .loop; |
| 5745 | | const loop_block = try parent_gz.addBlock(loop_tag, node); |
| 5369 | const loop_block = try parent_gz.makeBlockInst(loop_tag, node); |
| 5746 | 5370 | try parent_gz.instructions.append(astgen.gpa, loop_block); |
| 5747 | 5371 | |
| 5748 | 5372 | var loop_scope = parent_gz.makeSubBlock(scope); |
| 5749 | 5373 | loop_scope.setBreakResultLoc(rl); |
| 5750 | | defer loop_scope.instructions.deinit(astgen.gpa); |
| 5374 | defer loop_scope.unstack(); |
| 5751 | 5375 | defer loop_scope.labeled_breaks.deinit(astgen.gpa); |
| 5752 | 5376 | defer loop_scope.labeled_store_to_block_ptr_list.deinit(astgen.gpa); |
| 5753 | 5377 | |
| 5754 | 5378 | var cond_scope = parent_gz.makeSubBlock(&loop_scope.base); |
| 5755 | | defer cond_scope.instructions.deinit(astgen.gpa); |
| 5379 | defer cond_scope.unstack(); |
| 5756 | 5380 | |
| 5757 | 5381 | // check condition i < array_expr.len |
| 5758 | 5382 | const index = try cond_scope.addUnNode(.load, index_ptr, for_full.ast.cond_expr); |
| ... | ... | @@ -5764,9 +5388,10 @@ fn forExpr( |
| 5764 | 5388 | const condbr_tag: Zir.Inst.Tag = if (is_inline) .condbr_inline else .condbr; |
| 5765 | 5389 | const condbr = try cond_scope.addCondBr(condbr_tag, node); |
| 5766 | 5390 | const block_tag: Zir.Inst.Tag = if (is_inline) .block_inline else .block; |
| 5767 | | const cond_block = try loop_scope.addBlock(block_tag, node); |
| 5768 | | try loop_scope.instructions.append(astgen.gpa, cond_block); |
| 5391 | const cond_block = try loop_scope.makeBlockInst(block_tag, node); |
| 5769 | 5392 | try cond_scope.setBlockBody(cond_block); |
| 5393 | // cond_block unstacked now, can add new instructions to loop_scope |
| 5394 | try loop_scope.instructions.append(astgen.gpa, cond_block); |
| 5770 | 5395 | |
| 5771 | 5396 | // Increment the index variable. |
| 5772 | 5397 | const index_2 = try loop_scope.addUnNode(.load, index_ptr, for_full.ast.cond_expr); |
| ... | ... | @@ -5789,7 +5414,7 @@ fn forExpr( |
| 5789 | 5414 | } |
| 5790 | 5415 | |
| 5791 | 5416 | var then_scope = parent_gz.makeSubBlock(&cond_scope.base); |
| 5792 | | defer then_scope.instructions.deinit(astgen.gpa); |
| 5417 | defer then_scope.unstack(); |
| 5793 | 5418 | |
| 5794 | 5419 | var payload_val_scope: Scope.LocalVal = undefined; |
| 5795 | 5420 | var index_scope: Scope.LocalPtr = undefined; |
| ... | ... | @@ -5851,7 +5476,7 @@ fn forExpr( |
| 5851 | 5476 | try checkUsed(parent_gz, &then_scope.base, then_sub_scope); |
| 5852 | 5477 | |
| 5853 | 5478 | var else_scope = parent_gz.makeSubBlock(&cond_scope.base); |
| 5854 | | defer else_scope.instructions.deinit(astgen.gpa); |
| 5479 | defer else_scope.unstack(); |
| 5855 | 5480 | |
| 5856 | 5481 | const else_node = for_full.ast.else_expr; |
| 5857 | 5482 | const else_info: struct { |
| ... | ... | @@ -6030,27 +5655,29 @@ fn switchExpr( |
| 6030 | 5655 | const cond_ty_inst = try parent_gz.addUnNode(.typeof, cond, operand_node); |
| 6031 | 5656 | const item_rl: ResultLoc = .{ .ty = cond_ty_inst }; |
| 6032 | 5657 | |
| 6033 | | // These contain the data that goes into the `extra` array for the SwitchBlock/SwitchBlockMulti. |
| 6034 | | // This is the optional else prong body. |
| 6035 | | var special_case_payload = ArrayListUnmanaged(u32){}; |
| 6036 | | defer special_case_payload.deinit(gpa); |
| 6037 | | // This is all the scalar cases. |
| 6038 | | var scalar_cases_payload = ArrayListUnmanaged(u32){}; |
| 6039 | | defer scalar_cases_payload.deinit(gpa); |
| 6040 | | // Same deal, but this is only the `extra` data for the multi cases. |
| 6041 | | var multi_cases_payload = ArrayListUnmanaged(u32){}; |
| 6042 | | defer multi_cases_payload.deinit(gpa); |
| 5658 | // This contains the data that goes into the `extra` array for the SwitchBlock/SwitchBlockMulti, |
| 5659 | // except the first cases_nodes.len slots are a table that indexes payloads later in the array, with |
| 5660 | // the special case index coming first, then scalar_case_len indexes, then multi_cases_len indexes |
| 5661 | const payloads = &astgen.scratch; |
| 5662 | const scratch_top = astgen.scratch.items.len; |
| 5663 | const case_table_start = scratch_top; |
| 5664 | const scalar_case_table = case_table_start + @boolToInt(special_prong != .none); |
| 5665 | const multi_case_table = scalar_case_table + scalar_cases_len; |
| 5666 | const case_table_end = multi_case_table + multi_cases_len; |
| 5667 | try astgen.scratch.resize(gpa, case_table_end); |
| 5668 | defer astgen.scratch.items.len = scratch_top; |
| 6043 | 5669 | |
| 6044 | 5670 | var block_scope = parent_gz.makeSubBlock(scope); |
| 5671 | // block_scope not used for collecting instructions |
| 5672 | block_scope.instructions_top = GenZir.unstacked_top; |
| 6045 | 5673 | block_scope.setBreakResultLoc(rl); |
| 6046 | | defer block_scope.instructions.deinit(gpa); |
| 6047 | 5674 | |
| 6048 | 5675 | // This gets added to the parent block later, after the item expressions. |
| 6049 | | const switch_block = try parent_gz.addBlock(.switch_block, switch_node); |
| 5676 | const switch_block = try parent_gz.makeBlockInst(.switch_block, switch_node); |
| 6050 | 5677 | |
| 6051 | 5678 | // We re-use this same scope for all cases, including the special prong, if any. |
| 6052 | 5679 | var case_scope = parent_gz.makeSubBlock(&block_scope.base); |
| 6053 | | defer case_scope.instructions.deinit(gpa); |
| 5680 | case_scope.instructions_top = GenZir.unstacked_top; |
| 6054 | 5681 | |
| 6055 | 5682 | // In this pass we generate all the item and prong expressions. |
| 6056 | 5683 | var multi_case_index: u32 = 0; |
| ... | ... | @@ -6062,21 +5689,12 @@ fn switchExpr( |
| 6062 | 5689 | else => unreachable, |
| 6063 | 5690 | }; |
| 6064 | 5691 | |
| 6065 | | // Reset the scope. |
| 6066 | | case_scope.instructions.shrinkRetainingCapacity(0); |
| 6067 | | |
| 6068 | 5692 | const is_multi_case = case.ast.values.len > 1 or |
| 6069 | 5693 | (case.ast.values.len == 1 and node_tags[case.ast.values[0]] == .switch_range); |
| 6070 | 5694 | |
| 5695 | var capture_inst: Zir.Inst.Index = 0; |
| 6071 | 5696 | var capture_val_scope: Scope.LocalVal = undefined; |
| 6072 | 5697 | const sub_scope = blk: { |
| 6073 | | const capture_index = if (is_multi_case) ci: { |
| 6074 | | multi_case_index += 1; |
| 6075 | | break :ci multi_case_index - 1; |
| 6076 | | } else ci: { |
| 6077 | | scalar_case_index += 1; |
| 6078 | | break :ci scalar_case_index - 1; |
| 6079 | | }; |
| 6080 | 5698 | const payload_token = case.payload_token orelse break :blk &case_scope.base; |
| 6081 | 5699 | const ident = if (token_tags[payload_token] == .asterisk) |
| 6082 | 5700 | payload_token + 1 |
| ... | ... | @@ -6089,19 +5707,20 @@ fn switchExpr( |
| 6089 | 5707 | } |
| 6090 | 5708 | break :blk &case_scope.base; |
| 6091 | 5709 | } |
| 6092 | | const capture = if (case_node == special_node) capture: { |
| 5710 | if (case_node == special_node) { |
| 6093 | 5711 | const capture_tag: Zir.Inst.Tag = if (is_ptr) |
| 6094 | 5712 | .switch_capture_else_ref |
| 6095 | 5713 | else |
| 6096 | 5714 | .switch_capture_else; |
| 6097 | | break :capture try case_scope.add(.{ |
| 5715 | capture_inst = @intCast(Zir.Inst.Index, astgen.instructions.len); |
| 5716 | try astgen.instructions.append(gpa, .{ |
| 6098 | 5717 | .tag = capture_tag, |
| 6099 | 5718 | .data = .{ .switch_capture = .{ |
| 6100 | 5719 | .switch_inst = switch_block, |
| 6101 | 5720 | .prong_index = undefined, |
| 6102 | 5721 | } }, |
| 6103 | 5722 | }); |
| 6104 | | } else capture: { |
| 5723 | } else { |
| 6105 | 5724 | const is_multi_case_bits: u2 = @boolToInt(is_multi_case); |
| 6106 | 5725 | const is_ptr_bits: u2 = @boolToInt(is_ptr); |
| 6107 | 5726 | const capture_tag: Zir.Inst.Tag = switch ((is_multi_case_bits << 1) | is_ptr_bits) { |
| ... | ... | @@ -6110,30 +5729,33 @@ fn switchExpr( |
| 6110 | 5729 | 0b10 => .switch_capture_multi, |
| 6111 | 5730 | 0b11 => .switch_capture_multi_ref, |
| 6112 | 5731 | }; |
| 6113 | | break :capture try case_scope.add(.{ |
| 5732 | const capture_index = if (is_multi_case) multi_case_index else scalar_case_index; |
| 5733 | capture_inst = @intCast(Zir.Inst.Index, astgen.instructions.len); |
| 5734 | try astgen.instructions.append(gpa, .{ |
| 6114 | 5735 | .tag = capture_tag, |
| 6115 | 5736 | .data = .{ .switch_capture = .{ |
| 6116 | 5737 | .switch_inst = switch_block, |
| 6117 | 5738 | .prong_index = capture_index, |
| 6118 | 5739 | } }, |
| 6119 | 5740 | }); |
| 6120 | | }; |
| 5741 | } |
| 6121 | 5742 | const capture_name = try astgen.identAsString(ident); |
| 6122 | 5743 | capture_val_scope = .{ |
| 6123 | 5744 | .parent = &case_scope.base, |
| 6124 | 5745 | .gen_zir = &case_scope, |
| 6125 | 5746 | .name = capture_name, |
| 6126 | | .inst = capture, |
| 5747 | .inst = indexToRef(capture_inst), |
| 6127 | 5748 | .token_src = payload_token, |
| 6128 | 5749 | .id_cat = .@"capture", |
| 6129 | 5750 | }; |
| 6130 | 5751 | break :blk &capture_val_scope.base; |
| 6131 | 5752 | }; |
| 6132 | 5753 | |
| 6133 | | if (is_multi_case) { |
| 6134 | | // items_len, ranges_len, body_len |
| 6135 | | const header_index = multi_cases_payload.items.len; |
| 6136 | | try multi_cases_payload.resize(gpa, multi_cases_payload.items.len + 3); |
| 5754 | const header_index = @intCast(u32, payloads.items.len); |
| 5755 | const body_len_index = if (is_multi_case) blk: { |
| 5756 | payloads.items[multi_case_table + multi_case_index] = header_index; |
| 5757 | multi_case_index += 1; |
| 5758 | try payloads.resize(gpa, header_index + 3); // items_len, ranges_len, body_len |
| 6137 | 5759 | |
| 6138 | 5760 | // items |
| 6139 | 5761 | var items_len: u32 = 0; |
| ... | ... | @@ -6142,7 +5764,7 @@ fn switchExpr( |
| 6142 | 5764 | items_len += 1; |
| 6143 | 5765 | |
| 6144 | 5766 | const item_inst = try comptimeExpr(parent_gz, scope, item_rl, item_node); |
| 6145 | | try multi_cases_payload.append(gpa, @enumToInt(item_inst)); |
| 5767 | try payloads.append(gpa, @enumToInt(item_inst)); |
| 6146 | 5768 | } |
| 6147 | 5769 | |
| 6148 | 5770 | // ranges |
| ... | ... | @@ -6153,47 +5775,44 @@ fn switchExpr( |
| 6153 | 5775 | |
| 6154 | 5776 | const first = try comptimeExpr(parent_gz, scope, item_rl, node_datas[range].lhs); |
| 6155 | 5777 | const last = try comptimeExpr(parent_gz, scope, item_rl, node_datas[range].rhs); |
| 6156 | | try multi_cases_payload.appendSlice(gpa, &[_]u32{ |
| 5778 | try payloads.appendSlice(gpa, &[_]u32{ |
| 6157 | 5779 | @enumToInt(first), @enumToInt(last), |
| 6158 | 5780 | }); |
| 6159 | 5781 | } |
| 6160 | 5782 | |
| 6161 | | const case_result = try expr(&case_scope, sub_scope, block_scope.break_result_loc, case.ast.target_expr); |
| 6162 | | try checkUsed(parent_gz, &case_scope.base, sub_scope); |
| 6163 | | if (!parent_gz.refIsNoReturn(case_result)) { |
| 6164 | | block_scope.break_count += 1; |
| 6165 | | _ = try case_scope.addBreak(.@"break", switch_block, case_result); |
| 6166 | | } |
| 6167 | | |
| 6168 | | multi_cases_payload.items[header_index + 0] = items_len; |
| 6169 | | multi_cases_payload.items[header_index + 1] = ranges_len; |
| 6170 | | multi_cases_payload.items[header_index + 2] = @intCast(u32, case_scope.instructions.items.len); |
| 6171 | | try multi_cases_payload.appendSlice(gpa, case_scope.instructions.items); |
| 6172 | | } else if (case_node == special_node) { |
| 6173 | | const case_result = try expr(&case_scope, sub_scope, block_scope.break_result_loc, case.ast.target_expr); |
| 6174 | | try checkUsed(parent_gz, &case_scope.base, sub_scope); |
| 6175 | | if (!parent_gz.refIsNoReturn(case_result)) { |
| 6176 | | block_scope.break_count += 1; |
| 6177 | | _ = try case_scope.addBreak(.@"break", switch_block, case_result); |
| 6178 | | } |
| 6179 | | try special_case_payload.ensureUnusedCapacity(gpa, 1 + // body_len |
| 6180 | | case_scope.instructions.items.len); |
| 6181 | | special_case_payload.appendAssumeCapacity(@intCast(u32, case_scope.instructions.items.len)); |
| 6182 | | special_case_payload.appendSliceAssumeCapacity(case_scope.instructions.items); |
| 6183 | | } else { |
| 5783 | payloads.items[header_index] = items_len; |
| 5784 | payloads.items[header_index + 1] = ranges_len; |
| 5785 | break :blk header_index + 2; |
| 5786 | } else if (case_node == special_node) blk: { |
| 5787 | payloads.items[case_table_start] = header_index; |
| 5788 | try payloads.resize(gpa, header_index + 1); // body_len |
| 5789 | break :blk header_index; |
| 5790 | } else blk: { |
| 5791 | payloads.items[scalar_case_table + scalar_case_index] = header_index; |
| 5792 | scalar_case_index += 1; |
| 5793 | try payloads.resize(gpa, header_index + 2); // item, body_len |
| 6184 | 5794 | const item_node = case.ast.values[0]; |
| 6185 | 5795 | const item_inst = try comptimeExpr(parent_gz, scope, item_rl, item_node); |
| 5796 | payloads.items[header_index] = @enumToInt(item_inst); |
| 5797 | break :blk header_index + 1; |
| 5798 | }; |
| 5799 | |
| 5800 | { |
| 5801 | // temporarily stack case_scope on parent_gz |
| 5802 | case_scope.instructions_top = parent_gz.instructions.items.len; |
| 5803 | defer case_scope.unstack(); |
| 5804 | |
| 5805 | if (capture_inst != 0) try case_scope.instructions.append(gpa, capture_inst); |
| 6186 | 5806 | const case_result = try expr(&case_scope, sub_scope, block_scope.break_result_loc, case.ast.target_expr); |
| 6187 | 5807 | try checkUsed(parent_gz, &case_scope.base, sub_scope); |
| 6188 | 5808 | if (!parent_gz.refIsNoReturn(case_result)) { |
| 6189 | 5809 | block_scope.break_count += 1; |
| 6190 | 5810 | _ = try case_scope.addBreak(.@"break", switch_block, case_result); |
| 6191 | 5811 | } |
| 6192 | | try scalar_cases_payload.ensureUnusedCapacity(gpa, 2 + // item + body_len |
| 6193 | | case_scope.instructions.items.len); |
| 6194 | | scalar_cases_payload.appendAssumeCapacity(@enumToInt(item_inst)); |
| 6195 | | scalar_cases_payload.appendAssumeCapacity(@intCast(u32, case_scope.instructions.items.len)); |
| 6196 | | scalar_cases_payload.appendSliceAssumeCapacity(case_scope.instructions.items); |
| 5812 | |
| 5813 | const case_slice = case_scope.instructionsSlice(); |
| 5814 | payloads.items[body_len_index] = @intCast(u32, case_slice.len); |
| 5815 | try payloads.appendSlice(gpa, case_slice); |
| 6197 | 5816 | } |
| 6198 | 5817 | } |
| 6199 | 5818 | // Now that the item expressions are generated we can add this. |
| ... | ... | @@ -6201,9 +5820,7 @@ fn switchExpr( |
| 6201 | 5820 | |
| 6202 | 5821 | try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.SwitchBlock).Struct.fields.len + |
| 6203 | 5822 | @boolToInt(multi_cases_len != 0) + |
| 6204 | | special_case_payload.items.len + |
| 6205 | | scalar_cases_payload.items.len + |
| 6206 | | multi_cases_payload.items.len); |
| 5823 | payloads.items.len - case_table_end); |
| 6207 | 5824 | |
| 6208 | 5825 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.SwitchBlock{ |
| 6209 | 5826 | .operand = cond, |
| ... | ... | @@ -6216,105 +5833,59 @@ fn switchExpr( |
| 6216 | 5833 | }, |
| 6217 | 5834 | }); |
| 6218 | 5835 | |
| 6219 | | const zir_datas = astgen.instructions.items(.data); |
| 6220 | | const zir_tags = astgen.instructions.items(.tag); |
| 6221 | | |
| 6222 | | zir_datas[switch_block].pl_node.payload_index = payload_index; |
| 6223 | | |
| 6224 | 5836 | if (multi_cases_len != 0) { |
| 6225 | 5837 | astgen.extra.appendAssumeCapacity(multi_cases_len); |
| 6226 | 5838 | } |
| 6227 | 5839 | |
| 6228 | | const strat = rl.strategy(&block_scope); |
| 6229 | | switch (strat.tag) { |
| 6230 | | .break_operand => { |
| 6231 | | // Switch expressions return `true` for `nodeMayNeedMemoryLocation` thus |
| 6232 | | // `elide_store_to_block_ptr_instructions` will either be true, |
| 6233 | | // or all prongs are noreturn. |
| 6234 | | if (!strat.elide_store_to_block_ptr_instructions) { |
| 6235 | | astgen.extra.appendSliceAssumeCapacity(special_case_payload.items); |
| 6236 | | astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items); |
| 6237 | | astgen.extra.appendSliceAssumeCapacity(multi_cases_payload.items); |
| 6238 | | return indexToRef(switch_block); |
| 6239 | | } |
| 5840 | const zir_datas = astgen.instructions.items(.data); |
| 5841 | const zir_tags = astgen.instructions.items(.tag); |
| 6240 | 5842 | |
| 6241 | | // There will necessarily be a store_to_block_ptr for |
| 6242 | | // all prongs, except for prongs that ended with a noreturn instruction. |
| 6243 | | // Elide all the `store_to_block_ptr` instructions. |
| 5843 | zir_datas[switch_block].pl_node.payload_index = payload_index; |
| 6244 | 5844 | |
| 6245 | | // The break instructions need to have their operands coerced if the |
| 6246 | | // switch's result location is a `ty`. In this case we overwrite the |
| 6247 | | // `store_to_block_ptr` instruction with an `as` instruction and repurpose |
| 6248 | | // it as the break operand. |
| 5845 | const strat = rl.strategy(&block_scope); |
| 5846 | for (payloads.items[case_table_start..case_table_end]) |start_index, i| { |
| 5847 | var body_len_index = start_index; |
| 5848 | var end_index = start_index; |
| 5849 | const table_index = case_table_start + i; |
| 5850 | if (table_index < scalar_case_table) { |
| 5851 | end_index += 1; |
| 5852 | } else if (table_index < multi_case_table) { |
| 5853 | body_len_index += 1; |
| 5854 | end_index += 2; |
| 5855 | } else { |
| 5856 | body_len_index += 2; |
| 5857 | const items_len = payloads.items[start_index]; |
| 5858 | const ranges_len = payloads.items[start_index + 1]; |
| 5859 | end_index += 3 + items_len + 2 * ranges_len; |
| 5860 | } |
| 6249 | 5861 | |
| 6250 | | var extra_index: usize = 0; |
| 6251 | | if (special_prong != .none) special_prong: { |
| 6252 | | const body_len_index = extra_index; |
| 6253 | | const body_len = special_case_payload.items[extra_index]; |
| 6254 | | extra_index += 1; |
| 6255 | | if (body_len < 2) { |
| 6256 | | extra_index += body_len; |
| 6257 | | astgen.extra.appendSliceAssumeCapacity(special_case_payload.items[0..extra_index]); |
| 6258 | | break :special_prong; |
| 6259 | | } |
| 6260 | | extra_index += body_len - 2; |
| 6261 | | const store_inst = special_case_payload.items[extra_index]; |
| 6262 | | if (zir_tags[store_inst] != .store_to_block_ptr or |
| 6263 | | zir_datas[store_inst].bin.lhs != block_scope.rl_ptr) |
| 6264 | | { |
| 6265 | | extra_index += 2; |
| 6266 | | astgen.extra.appendSliceAssumeCapacity(special_case_payload.items[0..extra_index]); |
| 6267 | | break :special_prong; |
| 6268 | | } |
| 6269 | | assert(zir_datas[store_inst].bin.lhs == block_scope.rl_ptr); |
| 6270 | | if (block_scope.rl_ty_inst != .none) { |
| 6271 | | extra_index += 1; |
| 6272 | | const break_inst = special_case_payload.items[extra_index]; |
| 6273 | | extra_index += 1; |
| 6274 | | astgen.extra.appendSliceAssumeCapacity(special_case_payload.items[0..extra_index]); |
| 6275 | | zir_tags[store_inst] = .as; |
| 6276 | | zir_datas[store_inst].bin = .{ |
| 6277 | | .lhs = block_scope.rl_ty_inst, |
| 6278 | | .rhs = zir_datas[break_inst].@"break".operand, |
| 6279 | | }; |
| 6280 | | zir_datas[break_inst].@"break".operand = indexToRef(store_inst); |
| 6281 | | } else { |
| 6282 | | special_case_payload.items[body_len_index] -= 1; |
| 6283 | | astgen.extra.appendSliceAssumeCapacity(special_case_payload.items[0..extra_index]); |
| 6284 | | extra_index += 1; |
| 6285 | | astgen.extra.appendAssumeCapacity(special_case_payload.items[extra_index]); |
| 6286 | | extra_index += 1; |
| 6287 | | } |
| 6288 | | } else { |
| 6289 | | astgen.extra.appendSliceAssumeCapacity(special_case_payload.items[0..extra_index]); |
| 6290 | | } |
| 6291 | | extra_index = 0; |
| 6292 | | var scalar_i: u32 = 0; |
| 6293 | | while (scalar_i < scalar_cases_len) : (scalar_i += 1) { |
| 6294 | | const start_index = extra_index; |
| 6295 | | extra_index += 1; |
| 6296 | | const body_len_index = extra_index; |
| 6297 | | const body_len = scalar_cases_payload.items[extra_index]; |
| 6298 | | extra_index += 1; |
| 6299 | | if (body_len < 2) { |
| 6300 | | extra_index += body_len; |
| 6301 | | astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items[start_index..extra_index]); |
| 6302 | | continue; |
| 6303 | | } |
| 6304 | | extra_index += body_len - 2; |
| 6305 | | const store_inst = scalar_cases_payload.items[extra_index]; |
| 5862 | const body_len = payloads.items[body_len_index]; |
| 5863 | end_index += body_len; |
| 5864 | |
| 5865 | switch (strat.tag) { |
| 5866 | .break_operand => blk: { |
| 5867 | // Switch expressions return `true` for `nodeMayNeedMemoryLocation` thus |
| 5868 | // `elide_store_to_block_ptr_instructions` will either be true, |
| 5869 | // or all prongs are noreturn. |
| 5870 | if (!strat.elide_store_to_block_ptr_instructions) |
| 5871 | break :blk; |
| 5872 | |
| 5873 | // There will necessarily be a store_to_block_ptr for |
| 5874 | // all prongs, except for prongs that ended with a noreturn instruction. |
| 5875 | // Elide all the `store_to_block_ptr` instructions. |
| 5876 | |
| 5877 | // The break instructions need to have their operands coerced if the |
| 5878 | // switch's result location is a `ty`. In this case we overwrite the |
| 5879 | // `store_to_block_ptr` instruction with an `as` instruction and repurpose |
| 5880 | // it as the break operand. |
| 5881 | if (body_len < 2) |
| 5882 | break :blk; |
| 5883 | const store_inst = payloads.items[end_index - 2]; |
| 6306 | 5884 | if (zir_tags[store_inst] != .store_to_block_ptr or |
| 6307 | 5885 | zir_datas[store_inst].bin.lhs != block_scope.rl_ptr) |
| 6308 | | { |
| 6309 | | extra_index += 2; |
| 6310 | | astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items[start_index..extra_index]); |
| 6311 | | continue; |
| 6312 | | } |
| 5886 | break :blk; |
| 5887 | const break_inst = payloads.items[end_index - 1]; |
| 6313 | 5888 | if (block_scope.rl_ty_inst != .none) { |
| 6314 | | extra_index += 1; |
| 6315 | | const break_inst = scalar_cases_payload.items[extra_index]; |
| 6316 | | extra_index += 1; |
| 6317 | | astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items[start_index..extra_index]); |
| 6318 | 5889 | zir_tags[store_inst] = .as; |
| 6319 | 5890 | zir_datas[store_inst].bin = .{ |
| 6320 | 5891 | .lhs = block_scope.rl_ty_inst, |
| ... | ... | @@ -6322,125 +5893,30 @@ fn switchExpr( |
| 6322 | 5893 | }; |
| 6323 | 5894 | zir_datas[break_inst].@"break".operand = indexToRef(store_inst); |
| 6324 | 5895 | } else { |
| 6325 | | scalar_cases_payload.items[body_len_index] -= 1; |
| 6326 | | astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items[start_index..extra_index]); |
| 6327 | | extra_index += 1; |
| 6328 | | astgen.extra.appendAssumeCapacity(scalar_cases_payload.items[extra_index]); |
| 6329 | | extra_index += 1; |
| 6330 | | } |
| 6331 | | } |
| 6332 | | extra_index = 0; |
| 6333 | | var multi_i: u32 = 0; |
| 6334 | | while (multi_i < multi_cases_len) : (multi_i += 1) { |
| 6335 | | const start_index = extra_index; |
| 6336 | | const items_len = multi_cases_payload.items[extra_index]; |
| 6337 | | extra_index += 1; |
| 6338 | | const ranges_len = multi_cases_payload.items[extra_index]; |
| 6339 | | extra_index += 1; |
| 6340 | | const body_len_index = extra_index; |
| 6341 | | const body_len = multi_cases_payload.items[extra_index]; |
| 6342 | | extra_index += 1; |
| 6343 | | extra_index += items_len; |
| 6344 | | extra_index += 2 * ranges_len; |
| 6345 | | if (body_len < 2) { |
| 6346 | | extra_index += body_len; |
| 6347 | | astgen.extra.appendSliceAssumeCapacity(multi_cases_payload.items[start_index..extra_index]); |
| 6348 | | continue; |
| 6349 | | } |
| 6350 | | extra_index += body_len - 2; |
| 6351 | | const store_inst = multi_cases_payload.items[extra_index]; |
| 6352 | | if (zir_tags[store_inst] != .store_to_block_ptr or |
| 6353 | | zir_datas[store_inst].bin.lhs != block_scope.rl_ptr) |
| 6354 | | { |
| 6355 | | extra_index += 2; |
| 6356 | | astgen.extra.appendSliceAssumeCapacity(multi_cases_payload.items[start_index..extra_index]); |
| 5896 | payloads.items[body_len_index] -= 1; |
| 5897 | astgen.extra.appendSliceAssumeCapacity(payloads.items[start_index .. end_index - 2]); |
| 5898 | astgen.extra.appendAssumeCapacity(break_inst); |
| 6357 | 5899 | continue; |
| 6358 | 5900 | } |
| 6359 | | if (block_scope.rl_ty_inst != .none) { |
| 6360 | | extra_index += 1; |
| 6361 | | const break_inst = multi_cases_payload.items[extra_index]; |
| 6362 | | extra_index += 1; |
| 6363 | | astgen.extra.appendSliceAssumeCapacity(multi_cases_payload.items[start_index..extra_index]); |
| 6364 | | zir_tags[store_inst] = .as; |
| 6365 | | zir_datas[store_inst].bin = .{ |
| 6366 | | .lhs = block_scope.rl_ty_inst, |
| 6367 | | .rhs = zir_datas[break_inst].@"break".operand, |
| 6368 | | }; |
| 6369 | | zir_datas[break_inst].@"break".operand = indexToRef(store_inst); |
| 6370 | | } else { |
| 6371 | | assert(zir_datas[store_inst].bin.lhs == block_scope.rl_ptr); |
| 6372 | | multi_cases_payload.items[body_len_index] -= 1; |
| 6373 | | astgen.extra.appendSliceAssumeCapacity(multi_cases_payload.items[start_index..extra_index]); |
| 6374 | | extra_index += 1; |
| 6375 | | astgen.extra.appendAssumeCapacity(multi_cases_payload.items[extra_index]); |
| 6376 | | extra_index += 1; |
| 6377 | | } |
| 6378 | | } |
| 6379 | | |
| 6380 | | const block_ref = indexToRef(switch_block); |
| 6381 | | switch (rl) { |
| 6382 | | .ref => return block_ref, |
| 6383 | | else => return rvalue(parent_gz, rl, block_ref, switch_node), |
| 6384 | | } |
| 6385 | | }, |
| 6386 | | .break_void => { |
| 6387 | | assert(!strat.elide_store_to_block_ptr_instructions); |
| 6388 | | astgen.extra.appendSliceAssumeCapacity(special_case_payload.items); |
| 6389 | | astgen.extra.appendSliceAssumeCapacity(scalar_cases_payload.items); |
| 6390 | | astgen.extra.appendSliceAssumeCapacity(multi_cases_payload.items); |
| 6391 | | // Modify all the terminating instruction tags to become `break` variants. |
| 6392 | | var extra_index: usize = payload_index; |
| 6393 | | extra_index += 2; |
| 6394 | | extra_index += @boolToInt(multi_cases_len != 0); |
| 6395 | | if (special_prong != .none) { |
| 6396 | | const body_len = astgen.extra.items[extra_index]; |
| 6397 | | extra_index += 1; |
| 6398 | | const body = astgen.extra.items[extra_index..][0..body_len]; |
| 6399 | | extra_index += body_len; |
| 6400 | | const last = body[body.len - 1]; |
| 6401 | | if (zir_tags[last] == .@"break" and |
| 6402 | | zir_datas[last].@"break".block_inst == switch_block) |
| 6403 | | { |
| 6404 | | zir_datas[last].@"break".operand = .void_value; |
| 6405 | | } |
| 6406 | | } |
| 6407 | | var scalar_i: u32 = 0; |
| 6408 | | while (scalar_i < scalar_cases_len) : (scalar_i += 1) { |
| 6409 | | extra_index += 1; |
| 6410 | | const body_len = astgen.extra.items[extra_index]; |
| 6411 | | extra_index += 1; |
| 6412 | | const body = astgen.extra.items[extra_index..][0..body_len]; |
| 6413 | | extra_index += body_len; |
| 6414 | | const last = body[body.len - 1]; |
| 6415 | | if (zir_tags[last] == .@"break" and |
| 6416 | | zir_datas[last].@"break".block_inst == switch_block) |
| 6417 | | { |
| 6418 | | zir_datas[last].@"break".operand = .void_value; |
| 6419 | | } |
| 6420 | | } |
| 6421 | | var multi_i: u32 = 0; |
| 6422 | | while (multi_i < multi_cases_len) : (multi_i += 1) { |
| 6423 | | const items_len = astgen.extra.items[extra_index]; |
| 6424 | | extra_index += 1; |
| 6425 | | const ranges_len = astgen.extra.items[extra_index]; |
| 6426 | | extra_index += 1; |
| 6427 | | const body_len = astgen.extra.items[extra_index]; |
| 6428 | | extra_index += 1; |
| 6429 | | extra_index += items_len; |
| 6430 | | extra_index += 2 * ranges_len; |
| 6431 | | const body = astgen.extra.items[extra_index..][0..body_len]; |
| 6432 | | extra_index += body_len; |
| 6433 | | const last = body[body.len - 1]; |
| 6434 | | if (zir_tags[last] == .@"break" and |
| 6435 | | zir_datas[last].@"break".block_inst == switch_block) |
| 5901 | }, |
| 5902 | .break_void => { |
| 5903 | assert(!strat.elide_store_to_block_ptr_instructions); |
| 5904 | const last_inst = payloads.items[end_index - 1]; |
| 5905 | if (zir_tags[last_inst] == .@"break" and |
| 5906 | zir_datas[last_inst].@"break".block_inst == switch_block) |
| 6436 | 5907 | { |
| 6437 | | zir_datas[last].@"break".operand = .void_value; |
| 5908 | zir_datas[last_inst].@"break".operand = .void_value; |
| 6438 | 5909 | } |
| 6439 | | } |
| 5910 | }, |
| 5911 | } |
| 6440 | 5912 | |
| 6441 | | return indexToRef(switch_block); |
| 6442 | | }, |
| 5913 | astgen.extra.appendSliceAssumeCapacity(payloads.items[start_index..end_index]); |
| 6443 | 5914 | } |
| 5915 | |
| 5916 | const block_ref = indexToRef(switch_block); |
| 5917 | if (strat.tag == .break_operand and strat.elide_store_to_block_ptr_instructions and rl != .ref) |
| 5918 | return rvalue(parent_gz, rl, block_ref, switch_node); |
| 5919 | return block_ref; |
| 6444 | 5920 | } |
| 6445 | 5921 | |
| 6446 | 5922 | fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref { |
| ... | ... | @@ -6519,13 +5995,13 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref |
| 6519 | 5995 | const condbr = try gz.addCondBr(.condbr, node); |
| 6520 | 5996 | |
| 6521 | 5997 | var then_scope = gz.makeSubBlock(scope); |
| 6522 | | defer then_scope.instructions.deinit(astgen.gpa); |
| 5998 | defer then_scope.unstack(); |
| 6523 | 5999 | |
| 6524 | 6000 | try genDefers(&then_scope, defer_outer, scope, .normal_only); |
| 6525 | 6001 | try then_scope.addRet(rl, operand, node); |
| 6526 | 6002 | |
| 6527 | 6003 | var else_scope = gz.makeSubBlock(scope); |
| 6528 | | defer else_scope.instructions.deinit(astgen.gpa); |
| 6004 | defer else_scope.unstack(); |
| 6529 | 6005 | |
| 6530 | 6006 | const which_ones: DefersToEmit = if (!defer_counts.need_err_code) .both_sans_err else .{ |
| 6531 | 6007 | .both = try else_scope.addUnNode(.err_union_code, result, node), |
| ... | ... | @@ -6533,7 +6009,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref |
| 6533 | 6009 | try genDefers(&else_scope, defer_outer, scope, which_ones); |
| 6534 | 6010 | try else_scope.addRet(rl, operand, node); |
| 6535 | 6011 | |
| 6536 | | try setCondBrPayload(condbr, is_non_err, &then_scope, &else_scope); |
| 6012 | try setCondBrPayload(condbr, is_non_err, &then_scope, 0, &else_scope, 0); |
| 6537 | 6013 | |
| 6538 | 6014 | return Zir.Inst.Ref.unreachable_value; |
| 6539 | 6015 | }, |
| ... | ... | @@ -6559,25 +6035,25 @@ fn identifier( |
| 6559 | 6035 | if (mem.eql(u8, ident_name_raw, "_")) { |
| 6560 | 6036 | return astgen.failNode(ident, "'_' used as an identifier without @\"_\" syntax", .{}); |
| 6561 | 6037 | } |
| 6562 | | const ident_name = try astgen.identifierTokenString(ident_token); |
| 6563 | 6038 | |
| 6039 | // if not @"" syntax, just use raw token slice |
| 6564 | 6040 | if (ident_name_raw[0] != '@') { |
| 6565 | | if (primitives.get(ident_name)) |zir_const_ref| { |
| 6041 | if (primitives.get(ident_name_raw)) |zir_const_ref| { |
| 6566 | 6042 | return rvalue(gz, rl, zir_const_ref, ident); |
| 6567 | 6043 | } |
| 6568 | 6044 | |
| 6569 | | if (ident_name.len >= 2) integer: { |
| 6570 | | const first_c = ident_name[0]; |
| 6045 | if (ident_name_raw.len >= 2) integer: { |
| 6046 | const first_c = ident_name_raw[0]; |
| 6571 | 6047 | if (first_c == 'i' or first_c == 'u') { |
| 6572 | 6048 | const signedness: std.builtin.Signedness = switch (first_c == 'i') { |
| 6573 | 6049 | true => .signed, |
| 6574 | 6050 | false => .unsigned, |
| 6575 | 6051 | }; |
| 6576 | | const bit_count = std.fmt.parseInt(u16, ident_name[1..], 10) catch |err| switch (err) { |
| 6052 | const bit_count = std.fmt.parseInt(u16, ident_name_raw[1..], 10) catch |err| switch (err) { |
| 6577 | 6053 | error.Overflow => return astgen.failNode( |
| 6578 | 6054 | ident, |
| 6579 | 6055 | "primitive integer type '{s}' exceeds maximum bit width of 65535", |
| 6580 | | .{ident_name}, |
| 6056 | .{ident_name_raw}, |
| 6581 | 6057 | ), |
| 6582 | 6058 | error.InvalidCharacter => break :integer, |
| 6583 | 6059 | }; |
| ... | ... | @@ -6630,6 +6106,7 @@ fn identifier( |
| 6630 | 6106 | |
| 6631 | 6107 | // Can't close over a runtime variable |
| 6632 | 6108 | if (num_namespaces_out != 0 and !local_ptr.maybe_comptime) { |
| 6109 | const ident_name = try astgen.identifierTokenString(ident_token); |
| 6633 | 6110 | return astgen.failNodeNotes(ident, "mutable '{s}' not accessible from here", .{ident_name}, &.{ |
| 6634 | 6111 | try astgen.errNoteTok(local_ptr.token_src, "declared mutable here", .{}), |
| 6635 | 6112 | try astgen.errNoteNode(capturing_namespace.?.node, "crosses namespace boundary here", .{}), |
| ... | ... | @@ -6677,6 +6154,7 @@ fn identifier( |
| 6677 | 6154 | .top => break, |
| 6678 | 6155 | }; |
| 6679 | 6156 | if (found_already == null) { |
| 6157 | const ident_name = try astgen.identifierTokenString(ident_token); |
| 6680 | 6158 | return astgen.failNode(ident, "use of undeclared identifier '{s}'", .{ident_name}); |
| 6681 | 6159 | } |
| 6682 | 6160 | |
| ... | ... | @@ -6712,9 +6190,15 @@ fn tunnelThroughClosure( |
| 6712 | 6190 | // already has one for this value. |
| 6713 | 6191 | const gop = try ns.?.captures.getOrPut(gpa, refToIndex(value).?); |
| 6714 | 6192 | if (!gop.found_existing) { |
| 6715 | | // Make a new capture for this value |
| 6716 | | const capture_ref = try ns.?.declaring_gz.?.addUnTok(.closure_capture, value, token); |
| 6717 | | gop.value_ptr.* = refToIndex(capture_ref).?; |
| 6193 | // Make a new capture for this value but don't add it to the declaring_gz yet |
| 6194 | try gz.astgen.instructions.append(gz.astgen.gpa, .{ |
| 6195 | .tag = .closure_capture, |
| 6196 | .data = .{ .un_tok = .{ |
| 6197 | .operand = value, |
| 6198 | .src_tok = ns.?.declaring_gz.?.tokenIndexToRelative(token), |
| 6199 | } }, |
| 6200 | }); |
| 6201 | gop.value_ptr.* = @intCast(Zir.Inst.Index, gz.astgen.instructions.len - 1); |
| 6718 | 6202 | } |
| 6719 | 6203 | |
| 6720 | 6204 | // Add an instruction to get the value from the closure into |
| ... | ... | @@ -7155,10 +6639,8 @@ fn asRlPtr( |
| 7155 | 6639 | operand_node: Ast.Node.Index, |
| 7156 | 6640 | dest_type: Zir.Inst.Ref, |
| 7157 | 6641 | ) InnerError!Zir.Inst.Ref { |
| 7158 | | const astgen = parent_gz.astgen; |
| 7159 | | |
| 7160 | 6642 | var as_scope = try parent_gz.makeCoercionScope(scope, dest_type, result_ptr); |
| 7161 | | defer as_scope.instructions.deinit(astgen.gpa); |
| 6643 | defer as_scope.unstack(); |
| 7162 | 6644 | |
| 7163 | 6645 | const result = try reachableExpr(&as_scope, &as_scope.base, .{ .block_ptr = &as_scope }, operand_node, src_node); |
| 7164 | 6646 | return as_scope.finishCoercion(parent_gz, rl, operand_node, result, dest_type); |
| ... | ... | @@ -7196,13 +6678,18 @@ fn typeOf( |
| 7196 | 6678 | const result = try gz.addUnNode(.typeof, expr_result, node); |
| 7197 | 6679 | return rvalue(gz, rl, result, node); |
| 7198 | 6680 | } |
| 7199 | | const arena = gz.astgen.arena; |
| 7200 | | var items = try arena.alloc(Zir.Inst.Ref, params.len); |
| 7201 | | for (params) |param, param_i| { |
| 7202 | | items[param_i] = try reachableExpr(gz, scope, .none, param, node); |
| 6681 | |
| 6682 | const payload_index = try addExtra(gz.astgen, Zir.Inst.NodeMultiOp{ |
| 6683 | .src_node = gz.nodeIndexToRelative(node), |
| 6684 | }); |
| 6685 | var extra_index = try reserveExtra(gz.astgen, params.len); |
| 6686 | for (params) |param| { |
| 6687 | const param_ref = try reachableExpr(gz, scope, .none, param, node); |
| 6688 | gz.astgen.extra.items[extra_index] = @enumToInt(param_ref); |
| 6689 | extra_index += 1; |
| 7203 | 6690 | } |
| 7204 | 6691 | |
| 7205 | | const result = try gz.addExtendedMultiOp(.typeof_peer, node, items); |
| 6692 | const result = try gz.addExtendedMultiOpPayloadIndex(.typeof_peer, payload_index, params.len); |
| 7206 | 6693 | return rvalue(gz, rl, result, node); |
| 7207 | 6694 | } |
| 7208 | 6695 | |
| ... | ... | @@ -7259,12 +6746,16 @@ fn builtinCall( |
| 7259 | 6746 | return rvalue(gz, rl, result, node); |
| 7260 | 6747 | }, |
| 7261 | 6748 | .compile_log => { |
| 7262 | | const arg_refs = try astgen.gpa.alloc(Zir.Inst.Ref, params.len); |
| 7263 | | defer astgen.gpa.free(arg_refs); |
| 7264 | | |
| 7265 | | for (params) |param, i| arg_refs[i] = try expr(gz, scope, .none, param); |
| 7266 | | |
| 7267 | | const result = try gz.addExtendedMultiOp(.compile_log, node, arg_refs); |
| 6749 | const payload_index = try addExtra(gz.astgen, Zir.Inst.NodeMultiOp{ |
| 6750 | .src_node = gz.nodeIndexToRelative(node), |
| 6751 | }); |
| 6752 | var extra_index = try reserveExtra(gz.astgen, params.len); |
| 6753 | for (params) |param| { |
| 6754 | const param_ref = try expr(gz, scope, .none, param); |
| 6755 | astgen.extra.items[extra_index] = @enumToInt(param_ref); |
| 6756 | extra_index += 1; |
| 6757 | } |
| 6758 | const result = try gz.addExtendedMultiOpPayloadIndex(.compile_log,payload_index, params.len); |
| 7268 | 6759 | return rvalue(gz, rl, result, node); |
| 7269 | 6760 | }, |
| 7270 | 6761 | .field => { |
| ... | ... | @@ -7921,14 +7412,15 @@ fn cImport( |
| 7921 | 7412 | var block_scope = gz.makeSubBlock(scope); |
| 7922 | 7413 | block_scope.force_comptime = true; |
| 7923 | 7414 | block_scope.c_import = true; |
| 7924 | | defer block_scope.instructions.deinit(gpa); |
| 7415 | defer block_scope.unstack(); |
| 7925 | 7416 | |
| 7926 | | const block_inst = try gz.addBlock(.c_import, node); |
| 7417 | const block_inst = try gz.makeBlockInst(.c_import, node); |
| 7927 | 7418 | const block_result = try expr(&block_scope, &block_scope.base, .none, body_node); |
| 7928 | 7419 | if (!gz.refIsNoReturn(block_result)) { |
| 7929 | 7420 | _ = try block_scope.addBreak(.break_inline, block_inst, .void_value); |
| 7930 | 7421 | } |
| 7931 | 7422 | try block_scope.setBlockBody(block_inst); |
| 7423 | // block_scope unstacked now, can add new instructions to gz |
| 7932 | 7424 | try gz.instructions.append(gpa, block_inst); |
| 7933 | 7425 | |
| 7934 | 7426 | return indexToRef(block_inst); |
| ... | ... | @@ -7974,22 +7466,6 @@ fn callExpr( |
| 7974 | 7466 | const astgen = gz.astgen; |
| 7975 | 7467 | |
| 7976 | 7468 | const callee = try calleeExpr(gz, scope, call.ast.fn_expr); |
| 7977 | | |
| 7978 | | // A large proportion of calls have 5 or less arguments, due to this preventing allocations |
| 7979 | | // for calls with few arguments has a sizeable effect on the aggregated runtime of this function |
| 7980 | | var arg_buffer: [5]Zir.Inst.Ref = undefined; |
| 7981 | | const args: []Zir.Inst.Ref = if (call.ast.params.len <= arg_buffer.len) |
| 7982 | | arg_buffer[0..call.ast.params.len] |
| 7983 | | else |
| 7984 | | try astgen.gpa.alloc(Zir.Inst.Ref, call.ast.params.len); |
| 7985 | | defer if (call.ast.params.len > arg_buffer.len) astgen.gpa.free(args); |
| 7986 | | |
| 7987 | | for (call.ast.params) |param_node, i| { |
| 7988 | | // Parameters are always temporary values, they have no |
| 7989 | | // meaningful result location. Sema will coerce them. |
| 7990 | | args[i] = try expr(gz, scope, .none, param_node); |
| 7991 | | } |
| 7992 | | |
| 7993 | 7469 | const modifier: std.builtin.CallOptions.Modifier = blk: { |
| 7994 | 7470 | if (gz.force_comptime) { |
| 7995 | 7471 | break :blk .compile_time; |
| ... | ... | @@ -8002,7 +7478,28 @@ fn callExpr( |
| 8002 | 7478 | } |
| 8003 | 7479 | break :blk .auto; |
| 8004 | 7480 | }; |
| 8005 | | const call_inst = try gz.addCall(modifier, callee, args, node); |
| 7481 | |
| 7482 | assert(callee != .none); |
| 7483 | assert(node != 0); |
| 7484 | |
| 7485 | const payload_index = try addExtra(astgen, Zir.Inst.Call{ |
| 7486 | .callee = callee, |
| 7487 | .flags = .{ |
| 7488 | .packed_modifier = @intCast(Zir.Inst.Call.Flags.PackedModifier, @enumToInt(modifier)), |
| 7489 | .args_len = @intCast(Zir.Inst.Call.Flags.PackedArgsLen, call.ast.params.len), |
| 7490 | }, |
| 7491 | }); |
| 7492 | var extra_index = try reserveExtra(astgen, call.ast.params.len); |
| 7493 | |
| 7494 | for (call.ast.params) |param_node| { |
| 7495 | // Parameters are always temporary values, they have no |
| 7496 | // meaningful result location. Sema will coerce them. |
| 7497 | const arg_ref = try expr(gz, scope, .none, param_node); |
| 7498 | astgen.extra.items[extra_index] = @enumToInt(arg_ref); |
| 7499 | extra_index += 1; |
| 7500 | } |
| 7501 | |
| 7502 | const call_inst = try gz.addPlNodePayloadIndex(.call, node, payload_index); |
| 8006 | 7503 | return rvalue(gz, rl, call_inst, node); // TODO function call with result location |
| 8007 | 7504 | } |
| 8008 | 7505 | |
| ... | ... | @@ -8747,6 +8244,7 @@ fn nodeImpliesRuntimeBits(tree: *const Ast, start_node: Ast.Node.Index) bool { |
| 8747 | 8244 | /// result locations must call this function on their result. |
| 8748 | 8245 | /// As an example, if the `ResultLoc` is `ptr`, it will write the result to the pointer. |
| 8749 | 8246 | /// If the `ResultLoc` is `ty`, it will coerce the result to the type. |
| 8247 | /// Assumes nothing stacked on `gz`. |
| 8750 | 8248 | fn rvalue( |
| 8751 | 8249 | gz: *GenZir, |
| 8752 | 8250 | rl: ResultLoc, |
| ... | ... | @@ -9326,7 +8824,7 @@ const Scope = struct { |
| 9326 | 8824 | |
| 9327 | 8825 | /// Map from the raw captured value to the instruction |
| 9328 | 8826 | /// ref of the capture for decls in this namespace |
| 9329 | | captures: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .{}, |
| 8827 | captures: std.AutoArrayHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .{}, |
| 9330 | 8828 | |
| 9331 | 8829 | pub fn deinit(self: *Namespace, gpa: *Allocator) void { |
| 9332 | 8830 | self.decls.deinit(gpa); |
| ... | ... | @@ -9359,9 +8857,12 @@ const GenZir = struct { |
| 9359 | 8857 | parent: *Scope, |
| 9360 | 8858 | /// All `GenZir` scopes for the same ZIR share this. |
| 9361 | 8859 | astgen: *AstGen, |
| 9362 | | /// Keeps track of the list of instructions in this scope only. Indexes |
| 9363 | | /// to instructions in `astgen`. |
| 9364 | | instructions: ArrayListUnmanaged(Zir.Inst.Index) = .{}, |
| 8860 | /// Keeps track of the list of instructions in this scope. Possibly shared. |
| 8861 | /// Indexes to instructions in `astgen`. |
| 8862 | instructions: *ArrayListUnmanaged(Zir.Inst.Index), |
| 8863 | /// A sub-block may share its instructions ArrayList with containing GenZir, |
| 8864 | /// if use is strictly nested. This saves prior size of list for unstacking. |
| 8865 | instructions_top: usize, |
| 9365 | 8866 | label: ?Label = null, |
| 9366 | 8867 | break_block: Zir.Inst.Index = 0, |
| 9367 | 8868 | continue_block: Zir.Inst.Index = 0, |
| ... | ... | @@ -9397,6 +8898,36 @@ const GenZir = struct { |
| 9397 | 8898 | /// Keys are the raw instruction index, values are the closure_capture instruction. |
| 9398 | 8899 | captures: std.AutoHashMapUnmanaged(Zir.Inst.Index, Zir.Inst.Index) = .{}, |
| 9399 | 8900 | |
| 8901 | const unstacked_top = std.math.maxInt(usize); |
| 8902 | /// Call unstack before adding any new instructions to containing GenZir. |
| 8903 | fn unstack(self: *GenZir) void { |
| 8904 | if (self.instructions_top != unstacked_top) { |
| 8905 | self.instructions.items.len = self.instructions_top; |
| 8906 | self.instructions_top = unstacked_top; |
| 8907 | } |
| 8908 | } |
| 8909 | |
| 8910 | fn isEmpty(self: *const GenZir) bool { |
| 8911 | return (self.instructions_top == unstacked_top) or |
| 8912 | (self.instructions.items.len == self.instructions_top); |
| 8913 | } |
| 8914 | |
| 8915 | fn instructionsSlice(self: *const GenZir) []Zir.Inst.Index { |
| 8916 | return if (self.instructions_top == unstacked_top) |
| 8917 | &[0]Zir.Inst.Index{} |
| 8918 | else |
| 8919 | self.instructions.items[self.instructions_top..]; |
| 8920 | } |
| 8921 | |
| 8922 | fn instructionsSliceUpto(self: *const GenZir, stacked_gz: *GenZir) []Zir.Inst.Index { |
| 8923 | return if (self.instructions_top == unstacked_top) |
| 8924 | &[0]Zir.Inst.Index{} |
| 8925 | else if (self.instructions == stacked_gz.instructions and stacked_gz.instructions_top != unstacked_top) |
| 8926 | self.instructions.items[self.instructions_top..stacked_gz.instructions_top] |
| 8927 | else |
| 8928 | self.instructions.items[self.instructions_top..]; |
| 8929 | } |
| 8930 | |
| 9400 | 8931 | fn makeSubBlock(gz: *GenZir, scope: *Scope) GenZir { |
| 9401 | 8932 | return .{ |
| 9402 | 8933 | .force_comptime = gz.force_comptime, |
| ... | ... | @@ -9408,6 +8939,8 @@ const GenZir = struct { |
| 9408 | 8939 | .astgen = gz.astgen, |
| 9409 | 8940 | .suspend_node = gz.suspend_node, |
| 9410 | 8941 | .nosuspend_node = gz.nosuspend_node, |
| 8942 | .instructions = gz.instructions, |
| 8943 | .instructions_top = gz.instructions.items.len, |
| 9411 | 8944 | }; |
| 9412 | 8945 | } |
| 9413 | 8946 | |
| ... | ... | @@ -9421,12 +8954,13 @@ const GenZir = struct { |
| 9421 | 8954 | // result location. If it does, elide the coerce_result_ptr instruction |
| 9422 | 8955 | // as well as the store instruction, instead passing the result as an rvalue. |
| 9423 | 8956 | var as_scope = parent_gz.makeSubBlock(scope); |
| 9424 | | errdefer as_scope.instructions.deinit(parent_gz.astgen.gpa); |
| 8957 | errdefer as_scope.unstack(); |
| 9425 | 8958 | as_scope.rl_ptr = try as_scope.addBin(.coerce_result_ptr, dest_type, result_ptr); |
| 9426 | 8959 | |
| 9427 | 8960 | return as_scope; |
| 9428 | 8961 | } |
| 9429 | 8962 | |
| 8963 | /// Assumes `as_scope` is stacked immediately on top of `parent_gz`. Unstacks `as_scope`. |
| 9430 | 8964 | fn finishCoercion( |
| 9431 | 8965 | as_scope: *GenZir, |
| 9432 | 8966 | parent_gz: *GenZir, |
| ... | ... | @@ -9434,25 +8968,32 @@ const GenZir = struct { |
| 9434 | 8968 | src_node: Ast.Node.Index, |
| 9435 | 8969 | result: Zir.Inst.Ref, |
| 9436 | 8970 | dest_type: Zir.Inst.Ref, |
| 9437 | | ) !Zir.Inst.Ref { |
| 8971 | ) InnerError!Zir.Inst.Ref { |
| 8972 | assert(as_scope.instructions == parent_gz.instructions); |
| 9438 | 8973 | const astgen = as_scope.astgen; |
| 9439 | | const parent_zir = &parent_gz.instructions; |
| 9440 | 8974 | if (as_scope.rvalue_rl_count == 1) { |
| 9441 | 8975 | // Busted! This expression didn't actually need a pointer. |
| 9442 | 8976 | const zir_tags = astgen.instructions.items(.tag); |
| 9443 | 8977 | const zir_datas = astgen.instructions.items(.data); |
| 9444 | | try parent_zir.ensureUnusedCapacity(astgen.gpa, as_scope.instructions.items.len); |
| 9445 | | for (as_scope.instructions.items) |src_inst| { |
| 8978 | var src: usize = as_scope.instructions_top; |
| 8979 | var dst: usize = src; |
| 8980 | while (src < as_scope.instructions.items.len) : (src += 1) { |
| 8981 | const src_inst = as_scope.instructions.items[src]; |
| 9446 | 8982 | if (indexToRef(src_inst) == as_scope.rl_ptr) continue; |
| 9447 | 8983 | if (zir_tags[src_inst] == .store_to_block_ptr) { |
| 9448 | 8984 | if (zir_datas[src_inst].bin.lhs == as_scope.rl_ptr) continue; |
| 9449 | 8985 | } |
| 9450 | | parent_zir.appendAssumeCapacity(src_inst); |
| 8986 | as_scope.instructions.items[dst] = src_inst; |
| 8987 | dst += 1; |
| 9451 | 8988 | } |
| 8989 | parent_gz.instructions.items.len -= src - dst; |
| 8990 | as_scope.instructions_top = GenZir.unstacked_top; |
| 8991 | // as_scope now unstacked, can add new instructions to parent_gz |
| 9452 | 8992 | const casted_result = try parent_gz.addBin(.as, dest_type, result); |
| 9453 | 8993 | return rvalue(parent_gz, rl, casted_result, src_node); |
| 9454 | 8994 | } else { |
| 9455 | | try parent_zir.appendSlice(astgen.gpa, as_scope.instructions.items); |
| 8995 | // implicitly move all as_scope instructions to parent_gz |
| 8996 | as_scope.instructions_top = GenZir.unstacked_top; |
| 9456 | 8997 | return result; |
| 9457 | 8998 | } |
| 9458 | 8999 | } |
| ... | ... | @@ -9463,9 +9004,10 @@ const GenZir = struct { |
| 9463 | 9004 | used: bool = false, |
| 9464 | 9005 | }; |
| 9465 | 9006 | |
| 9007 | /// Assumes nothing stacked on `gz`. |
| 9466 | 9008 | fn endsWithNoReturn(gz: GenZir) bool { |
| 9009 | if (gz.isEmpty()) return false; |
| 9467 | 9010 | const tags = gz.astgen.instructions.items(.tag); |
| 9468 | | if (gz.instructions.items.len == 0) return false; |
| 9469 | 9011 | const last_inst = gz.instructions.items[gz.instructions.items.len - 1]; |
| 9470 | 9012 | return tags[last_inst].isNoReturn(); |
| 9471 | 9013 | } |
| ... | ... | @@ -9535,41 +9077,46 @@ const GenZir = struct { |
| 9535 | 9077 | } |
| 9536 | 9078 | } |
| 9537 | 9079 | |
| 9538 | | fn setBoolBrBody(gz: GenZir, inst: Zir.Inst.Index) !void { |
| 9080 | /// Assumes nothing stacked on `gz`. Unstacks `gz`. |
| 9081 | fn setBoolBrBody(gz: *GenZir, inst: Zir.Inst.Index) !void { |
| 9539 | 9082 | const gpa = gz.astgen.gpa; |
| 9540 | | try gz.astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Block).Struct.fields.len + |
| 9541 | | gz.instructions.items.len); |
| 9083 | const body = gz.instructionsSlice(); |
| 9084 | try gz.astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Block).Struct.fields.len + body.len); |
| 9542 | 9085 | const zir_datas = gz.astgen.instructions.items(.data); |
| 9543 | 9086 | zir_datas[inst].bool_br.payload_index = gz.astgen.addExtraAssumeCapacity( |
| 9544 | | Zir.Inst.Block{ .body_len = @intCast(u32, gz.instructions.items.len) }, |
| 9087 | Zir.Inst.Block{ .body_len = @intCast(u32, body.len) }, |
| 9545 | 9088 | ); |
| 9546 | | gz.astgen.extra.appendSliceAssumeCapacity(gz.instructions.items); |
| 9089 | gz.astgen.extra.appendSliceAssumeCapacity(body); |
| 9090 | gz.unstack(); |
| 9547 | 9091 | } |
| 9548 | 9092 | |
| 9549 | | fn setBlockBody(gz: GenZir, inst: Zir.Inst.Index) !void { |
| 9093 | /// Assumes nothing stacked on `gz`. Unstacks `gz`. |
| 9094 | fn setBlockBody(gz: *GenZir, inst: Zir.Inst.Index) !void { |
| 9550 | 9095 | const gpa = gz.astgen.gpa; |
| 9551 | | try gz.astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Block).Struct.fields.len + |
| 9552 | | gz.instructions.items.len); |
| 9096 | const body = gz.instructionsSlice(); |
| 9097 | try gz.astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Block).Struct.fields.len + body.len); |
| 9553 | 9098 | const zir_datas = gz.astgen.instructions.items(.data); |
| 9554 | 9099 | zir_datas[inst].pl_node.payload_index = gz.astgen.addExtraAssumeCapacity( |
| 9555 | | Zir.Inst.Block{ .body_len = @intCast(u32, gz.instructions.items.len) }, |
| 9100 | Zir.Inst.Block{ .body_len = @intCast(u32, body.len) }, |
| 9556 | 9101 | ); |
| 9557 | | gz.astgen.extra.appendSliceAssumeCapacity(gz.instructions.items); |
| 9102 | gz.astgen.extra.appendSliceAssumeCapacity(body); |
| 9103 | gz.unstack(); |
| 9558 | 9104 | } |
| 9559 | 9105 | |
| 9560 | 9106 | /// Same as `setBlockBody` except we don't copy instructions which are |
| 9561 | 9107 | /// `store_to_block_ptr` instructions with lhs set to .none. |
| 9562 | | fn setBlockBodyEliding(gz: GenZir, inst: Zir.Inst.Index) !void { |
| 9108 | /// Assumes nothing stacked on `gz`. Unstacks `gz`. |
| 9109 | fn setBlockBodyEliding(gz: *GenZir, inst: Zir.Inst.Index) !void { |
| 9563 | 9110 | const gpa = gz.astgen.gpa; |
| 9564 | | try gz.astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Block).Struct.fields.len + |
| 9565 | | gz.instructions.items.len); |
| 9111 | const body = gz.instructionsSlice(); |
| 9112 | try gz.astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Block).Struct.fields.len + body.len); |
| 9566 | 9113 | const zir_datas = gz.astgen.instructions.items(.data); |
| 9567 | 9114 | const zir_tags = gz.astgen.instructions.items(.tag); |
| 9568 | 9115 | const block_pl_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Block{ |
| 9569 | | .body_len = @intCast(u32, gz.instructions.items.len), |
| 9116 | .body_len = @intCast(u32, body.len), |
| 9570 | 9117 | }); |
| 9571 | 9118 | zir_datas[inst].pl_node.payload_index = block_pl_index; |
| 9572 | | for (gz.instructions.items) |sub_inst| { |
| 9119 | for (body) |sub_inst| { |
| 9573 | 9120 | if (zir_tags[sub_inst] == .store_to_block_ptr and |
| 9574 | 9121 | zir_datas[sub_inst].bin.lhs == .none) |
| 9575 | 9122 | { |
| ... | ... | @@ -9579,15 +9126,17 @@ const GenZir = struct { |
| 9579 | 9126 | } |
| 9580 | 9127 | gz.astgen.extra.appendAssumeCapacity(sub_inst); |
| 9581 | 9128 | } |
| 9129 | gz.unstack(); |
| 9582 | 9130 | } |
| 9583 | 9131 | |
| 9132 | /// Supports `body_gz` stacked on `ret_gz` stacked on `gz`. Unstacks `body_gz` and `ret_gz`. |
| 9584 | 9133 | fn addFunc(gz: *GenZir, args: struct { |
| 9585 | 9134 | src_node: Ast.Node.Index, |
| 9586 | 9135 | lbrace_line: u32 = 0, |
| 9587 | 9136 | lbrace_column: u32 = 0, |
| 9588 | | body: []const Zir.Inst.Index, |
| 9137 | body_gz: ?*GenZir, |
| 9589 | 9138 | param_block: Zir.Inst.Index, |
| 9590 | | ret_ty: []const Zir.Inst.Index, |
| 9139 | ret_gz: ?*GenZir, |
| 9591 | 9140 | ret_br: Zir.Inst.Index, |
| 9592 | 9141 | cc: Zir.Inst.Ref, |
| 9593 | 9142 | align_inst: Zir.Inst.Ref, |
| ... | ... | @@ -9601,12 +9150,13 @@ const GenZir = struct { |
| 9601 | 9150 | const astgen = gz.astgen; |
| 9602 | 9151 | const gpa = astgen.gpa; |
| 9603 | 9152 | |
| 9604 | | try gz.instructions.ensureUnusedCapacity(gpa, 1); |
| 9605 | 9153 | try astgen.instructions.ensureUnusedCapacity(gpa, 1); |
| 9606 | 9154 | |
| 9155 | var body: []Zir.Inst.Index = &[0]Zir.Inst.Index{}; |
| 9156 | var ret_ty: []Zir.Inst.Index = &[0]Zir.Inst.Index{}; |
| 9607 | 9157 | var src_locs_buffer: [3]u32 = undefined; |
| 9608 | 9158 | var src_locs: []u32 = src_locs_buffer[0..0]; |
| 9609 | | if (args.body.len != 0) { |
| 9159 | if (args.body_gz) |body_gz| { |
| 9610 | 9160 | const tree = astgen.tree; |
| 9611 | 9161 | const node_tags = tree.nodes.items(.tag); |
| 9612 | 9162 | const node_datas = tree.nodes.items(.data); |
| ... | ... | @@ -9624,6 +9174,13 @@ const GenZir = struct { |
| 9624 | 9174 | src_locs_buffer[1] = rbrace_line; |
| 9625 | 9175 | src_locs_buffer[2] = columns; |
| 9626 | 9176 | src_locs = &src_locs_buffer; |
| 9177 | |
| 9178 | body = body_gz.instructionsSlice(); |
| 9179 | if (args.ret_gz) |ret_gz| |
| 9180 | ret_ty = ret_gz.instructionsSliceUpto(body_gz); |
| 9181 | } else { |
| 9182 | if (args.ret_gz) |ret_gz| |
| 9183 | ret_ty = ret_gz.instructionsSlice(); |
| 9627 | 9184 | } |
| 9628 | 9185 | |
| 9629 | 9186 | if (args.cc != .none or args.lib_name != 0 or |
| ... | ... | @@ -9633,7 +9190,7 @@ const GenZir = struct { |
| 9633 | 9190 | try astgen.extra.ensureUnusedCapacity( |
| 9634 | 9191 | gpa, |
| 9635 | 9192 | @typeInfo(Zir.Inst.ExtendedFunc).Struct.fields.len + |
| 9636 | | args.ret_ty.len + args.body.len + src_locs.len + |
| 9193 | ret_ty.len + body.len + src_locs.len + |
| 9637 | 9194 | @boolToInt(args.lib_name != 0) + |
| 9638 | 9195 | @boolToInt(args.align_inst != .none) + |
| 9639 | 9196 | @boolToInt(args.cc != .none), |
| ... | ... | @@ -9641,8 +9198,8 @@ const GenZir = struct { |
| 9641 | 9198 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.ExtendedFunc{ |
| 9642 | 9199 | .src_node = gz.nodeIndexToRelative(args.src_node), |
| 9643 | 9200 | .param_block = args.param_block, |
| 9644 | | .ret_body_len = @intCast(u32, args.ret_ty.len), |
| 9645 | | .body_len = @intCast(u32, args.body.len), |
| 9201 | .ret_body_len = @intCast(u32, ret_ty.len), |
| 9202 | .body_len = @intCast(u32, body.len), |
| 9646 | 9203 | }); |
| 9647 | 9204 | if (args.lib_name != 0) { |
| 9648 | 9205 | astgen.extra.appendAssumeCapacity(args.lib_name); |
| ... | ... | @@ -9653,9 +9210,13 @@ const GenZir = struct { |
| 9653 | 9210 | if (args.align_inst != .none) { |
| 9654 | 9211 | astgen.extra.appendAssumeCapacity(@enumToInt(args.align_inst)); |
| 9655 | 9212 | } |
| 9656 | | astgen.extra.appendSliceAssumeCapacity(args.ret_ty); |
| 9657 | | astgen.extra.appendSliceAssumeCapacity(args.body); |
| 9213 | astgen.extra.appendSliceAssumeCapacity(ret_ty); |
| 9214 | astgen.extra.appendSliceAssumeCapacity(body); |
| 9658 | 9215 | astgen.extra.appendSliceAssumeCapacity(src_locs); |
| 9216 | // order is important when unstacking |
| 9217 | if (args.body_gz) |body_gz| body_gz.unstack(); |
| 9218 | if (args.ret_gz) |ret_gz| ret_gz.unstack(); |
| 9219 | try gz.instructions.ensureUnusedCapacity(gpa, 1); |
| 9659 | 9220 | |
| 9660 | 9221 | const new_index = @intCast(Zir.Inst.Index, astgen.instructions.len); |
| 9661 | 9222 | if (args.ret_br != 0) { |
| ... | ... | @@ -9683,17 +9244,21 @@ const GenZir = struct { |
| 9683 | 9244 | try astgen.extra.ensureUnusedCapacity( |
| 9684 | 9245 | gpa, |
| 9685 | 9246 | @typeInfo(Zir.Inst.Func).Struct.fields.len + |
| 9686 | | args.ret_ty.len + args.body.len + src_locs.len, |
| 9247 | ret_ty.len + body.len + src_locs.len, |
| 9687 | 9248 | ); |
| 9688 | 9249 | |
| 9689 | 9250 | const payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.Func{ |
| 9690 | 9251 | .param_block = args.param_block, |
| 9691 | | .ret_body_len = @intCast(u32, args.ret_ty.len), |
| 9692 | | .body_len = @intCast(u32, args.body.len), |
| 9252 | .ret_body_len = @intCast(u32, ret_ty.len), |
| 9253 | .body_len = @intCast(u32, body.len), |
| 9693 | 9254 | }); |
| 9694 | | astgen.extra.appendSliceAssumeCapacity(args.ret_ty); |
| 9695 | | astgen.extra.appendSliceAssumeCapacity(args.body); |
| 9255 | astgen.extra.appendSliceAssumeCapacity(ret_ty); |
| 9256 | astgen.extra.appendSliceAssumeCapacity(body); |
| 9696 | 9257 | astgen.extra.appendSliceAssumeCapacity(src_locs); |
| 9258 | // order is important when unstacking |
| 9259 | if (args.body_gz) |body_gz| body_gz.unstack(); |
| 9260 | if (args.ret_gz) |ret_gz| ret_gz.unstack(); |
| 9261 | try gz.instructions.ensureUnusedCapacity(gpa, 1); |
| 9697 | 9262 | |
| 9698 | 9263 | const tag: Zir.Inst.Tag = if (args.is_inferred_error) .func_inferred else .func; |
| 9699 | 9264 | const new_index = @intCast(Zir.Inst.Index, astgen.instructions.len); |
| ... | ... | @@ -9765,44 +9330,6 @@ const GenZir = struct { |
| 9765 | 9330 | return indexToRef(new_index); |
| 9766 | 9331 | } |
| 9767 | 9332 | |
| 9768 | | fn addCall( |
| 9769 | | gz: *GenZir, |
| 9770 | | modifier: std.builtin.CallOptions.Modifier, |
| 9771 | | callee: Zir.Inst.Ref, |
| 9772 | | args: []const Zir.Inst.Ref, |
| 9773 | | /// Absolute node index. This function does the conversion to offset from Decl. |
| 9774 | | src_node: Ast.Node.Index, |
| 9775 | | ) !Zir.Inst.Ref { |
| 9776 | | assert(callee != .none); |
| 9777 | | assert(src_node != 0); |
| 9778 | | const gpa = gz.astgen.gpa; |
| 9779 | | const Call = Zir.Inst.Call; |
| 9780 | | try gz.instructions.ensureUnusedCapacity(gpa, 1); |
| 9781 | | try gz.astgen.instructions.ensureUnusedCapacity(gpa, 1); |
| 9782 | | try gz.astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Call).Struct.fields.len + |
| 9783 | | args.len); |
| 9784 | | |
| 9785 | | const payload_index = gz.astgen.addExtraAssumeCapacity(Call{ |
| 9786 | | .callee = callee, |
| 9787 | | .flags = .{ |
| 9788 | | .packed_modifier = @intCast(Call.Flags.PackedModifier, @enumToInt(modifier)), |
| 9789 | | .args_len = @intCast(Call.Flags.PackedArgsLen, args.len), |
| 9790 | | }, |
| 9791 | | }); |
| 9792 | | gz.astgen.appendRefsAssumeCapacity(args); |
| 9793 | | |
| 9794 | | const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len); |
| 9795 | | gz.astgen.instructions.appendAssumeCapacity(.{ |
| 9796 | | .tag = .call, |
| 9797 | | .data = .{ .pl_node = .{ |
| 9798 | | .src_node = gz.nodeIndexToRelative(src_node), |
| 9799 | | .payload_index = payload_index, |
| 9800 | | } }, |
| 9801 | | }); |
| 9802 | | gz.instructions.appendAssumeCapacity(new_index); |
| 9803 | | return indexToRef(new_index); |
| 9804 | | } |
| 9805 | | |
| 9806 | 9333 | /// Note that this returns a `Zir.Inst.Index` not a ref. |
| 9807 | 9334 | /// Leaves the `payload_index` field undefined. |
| 9808 | 9335 | fn addBoolBr( |
| ... | ... | @@ -9878,6 +9405,25 @@ const GenZir = struct { |
| 9878 | 9405 | }); |
| 9879 | 9406 | } |
| 9880 | 9407 | |
| 9408 | fn makeUnNode( |
| 9409 | gz: *GenZir, |
| 9410 | tag: Zir.Inst.Tag, |
| 9411 | operand: Zir.Inst.Ref, |
| 9412 | /// Absolute node index. This function does the conversion to offset from Decl. |
| 9413 | src_node: Ast.Node.Index, |
| 9414 | ) !Zir.Inst.Index { |
| 9415 | assert(operand != .none); |
| 9416 | const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len); |
| 9417 | try gz.astgen.instructions.append(gz.astgen.gpa, .{ |
| 9418 | .tag = tag, |
| 9419 | .data = .{ .un_node = .{ |
| 9420 | .operand = operand, |
| 9421 | .src_node = gz.nodeIndexToRelative(src_node), |
| 9422 | } }, |
| 9423 | }); |
| 9424 | return new_index; |
| 9425 | } |
| 9426 | |
| 9881 | 9427 | fn addPlNode( |
| 9882 | 9428 | gz: *GenZir, |
| 9883 | 9429 | tag: Zir.Inst.Tag, |
| ... | ... | @@ -9902,25 +9448,43 @@ const GenZir = struct { |
| 9902 | 9448 | return indexToRef(new_index); |
| 9903 | 9449 | } |
| 9904 | 9450 | |
| 9451 | fn addPlNodePayloadIndex( |
| 9452 | gz: *GenZir, |
| 9453 | tag: Zir.Inst.Tag, |
| 9454 | /// Absolute node index. This function does the conversion to offset from Decl. |
| 9455 | src_node: Ast.Node.Index, |
| 9456 | payload_index: u32, |
| 9457 | ) !Zir.Inst.Ref { |
| 9458 | return try gz.add(.{ |
| 9459 | .tag = tag, |
| 9460 | .data = .{ .pl_node = .{ |
| 9461 | .src_node = gz.nodeIndexToRelative(src_node), |
| 9462 | .payload_index = payload_index, |
| 9463 | } }, |
| 9464 | }); |
| 9465 | } |
| 9466 | |
| 9467 | /// Supports `param_gz` stacked on `gz`. Assumes nothing stacked on `param_gz`. Unstacks `param_gz`. |
| 9905 | 9468 | fn addParam( |
| 9906 | 9469 | gz: *GenZir, |
| 9470 | param_gz: *GenZir, |
| 9907 | 9471 | tag: Zir.Inst.Tag, |
| 9908 | 9472 | /// Absolute token index. This function does the conversion to Decl offset. |
| 9909 | 9473 | abs_tok_index: Ast.TokenIndex, |
| 9910 | 9474 | name: u32, |
| 9911 | | body: []const u32, |
| 9912 | 9475 | ) !Zir.Inst.Index { |
| 9913 | 9476 | const gpa = gz.astgen.gpa; |
| 9914 | | try gz.instructions.ensureUnusedCapacity(gpa, 1); |
| 9477 | const param_body = param_gz.instructionsSlice(); |
| 9915 | 9478 | try gz.astgen.instructions.ensureUnusedCapacity(gpa, 1); |
| 9916 | 9479 | try gz.astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.Param).Struct.fields.len + |
| 9917 | | body.len); |
| 9480 | param_body.len); |
| 9918 | 9481 | |
| 9919 | 9482 | const payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Param{ |
| 9920 | 9483 | .name = name, |
| 9921 | | .body_len = @intCast(u32, body.len), |
| 9484 | .body_len = @intCast(u32, param_body.len), |
| 9922 | 9485 | }); |
| 9923 | | gz.astgen.extra.appendSliceAssumeCapacity(body); |
| 9486 | gz.astgen.extra.appendSliceAssumeCapacity(param_body); |
| 9487 | param_gz.unstack(); |
| 9924 | 9488 | |
| 9925 | 9489 | const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len); |
| 9926 | 9490 | gz.astgen.instructions.appendAssumeCapacity(.{ |
| ... | ... | @@ -9991,6 +9555,30 @@ const GenZir = struct { |
| 9991 | 9555 | return indexToRef(new_index); |
| 9992 | 9556 | } |
| 9993 | 9557 | |
| 9558 | fn addExtendedMultiOpPayloadIndex( |
| 9559 | gz: *GenZir, |
| 9560 | opcode: Zir.Inst.Extended, |
| 9561 | payload_index: u32, |
| 9562 | trailing_len: usize, |
| 9563 | ) !Zir.Inst.Ref { |
| 9564 | const astgen = gz.astgen; |
| 9565 | const gpa = astgen.gpa; |
| 9566 | |
| 9567 | try gz.instructions.ensureUnusedCapacity(gpa, 1); |
| 9568 | try astgen.instructions.ensureUnusedCapacity(gpa, 1); |
| 9569 | const new_index = @intCast(Zir.Inst.Index, astgen.instructions.len); |
| 9570 | astgen.instructions.appendAssumeCapacity(.{ |
| 9571 | .tag = .extended, |
| 9572 | .data = .{ .extended = .{ |
| 9573 | .opcode = opcode, |
| 9574 | .small = @intCast(u16, trailing_len), |
| 9575 | .operand = payload_index, |
| 9576 | } }, |
| 9577 | }); |
| 9578 | gz.instructions.appendAssumeCapacity(new_index); |
| 9579 | return indexToRef(new_index); |
| 9580 | } |
| 9581 | |
| 9994 | 9582 | fn addUnTok( |
| 9995 | 9583 | gz: *GenZir, |
| 9996 | 9584 | tag: Zir.Inst.Tag, |
| ... | ... | @@ -10039,6 +9627,23 @@ const GenZir = struct { |
| 10039 | 9627 | }); |
| 10040 | 9628 | } |
| 10041 | 9629 | |
| 9630 | fn makeBreak( |
| 9631 | gz: *GenZir, |
| 9632 | tag: Zir.Inst.Tag, |
| 9633 | break_block: Zir.Inst.Index, |
| 9634 | operand: Zir.Inst.Ref, |
| 9635 | ) !Zir.Inst.Index { |
| 9636 | const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len); |
| 9637 | try gz.astgen.instructions.append(gz.astgen.gpa, .{ |
| 9638 | .tag = tag, |
| 9639 | .data = .{ .@"break" = .{ |
| 9640 | .block_inst = break_block, |
| 9641 | .operand = operand, |
| 9642 | } }, |
| 9643 | }); |
| 9644 | return new_index; |
| 9645 | } |
| 9646 | |
| 10042 | 9647 | fn addBin( |
| 10043 | 9648 | gz: *GenZir, |
| 10044 | 9649 | tag: Zir.Inst.Tag, |
| ... | ... | @@ -10227,7 +9832,7 @@ const GenZir = struct { |
| 10227 | 9832 | /// Note that this returns a `Zir.Inst.Index` not a ref. |
| 10228 | 9833 | /// Does *not* append the block instruction to the scope. |
| 10229 | 9834 | /// Leaves the `payload_index` field undefined. |
| 10230 | | fn addBlock(gz: *GenZir, tag: Zir.Inst.Tag, node: Ast.Node.Index) !Zir.Inst.Index { |
| 9835 | fn makeBlockInst(gz: *GenZir, tag: Zir.Inst.Tag, node: Ast.Node.Index) !Zir.Inst.Index { |
| 10231 | 9836 | const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len); |
| 10232 | 9837 | const gpa = gz.astgen.gpa; |
| 10233 | 9838 | try gz.astgen.instructions.append(gpa, .{ |
| ... | ... | @@ -10464,6 +10069,15 @@ const GenZir = struct { |
| 10464 | 10069 | else => unreachable, |
| 10465 | 10070 | } |
| 10466 | 10071 | } |
| 10072 | |
| 10073 | fn addNamespaceCaptures(gz: *GenZir, namespace: *Scope.Namespace) !void { |
| 10074 | if (namespace.captures.count() > 0) { |
| 10075 | try gz.instructions.ensureUnusedCapacity(gz.astgen.gpa, namespace.captures.count()); |
| 10076 | for (namespace.captures.values()) |capture| { |
| 10077 | gz.instructions.appendAssumeCapacity(capture); |
| 10078 | } |
| 10079 | } |
| 10080 | } |
| 10467 | 10081 | }; |
| 10468 | 10082 | |
| 10469 | 10083 | /// This can only be for short-lived references; the memory becomes invalidated |
| ... | ... | @@ -10581,12 +10195,13 @@ fn advanceSourceCursor(astgen: *AstGen, source: []const u8, end: usize) void { |
| 10581 | 10195 | astgen.source_column = column; |
| 10582 | 10196 | } |
| 10583 | 10197 | |
| 10584 | | fn scanDecls(astgen: *AstGen, namespace: *Scope.Namespace, members: []const Ast.Node.Index) !void { |
| 10198 | fn scanDecls(astgen: *AstGen, namespace: *Scope.Namespace, members: []const Ast.Node.Index) !u32 { |
| 10585 | 10199 | const gpa = astgen.gpa; |
| 10586 | 10200 | const tree = astgen.tree; |
| 10587 | 10201 | const node_tags = tree.nodes.items(.tag); |
| 10588 | 10202 | const main_tokens = tree.nodes.items(.main_token); |
| 10589 | 10203 | const token_tags = tree.tokens.items(.tag); |
| 10204 | var decl_count: u32 = 0; |
| 10590 | 10205 | for (members) |member_node| { |
| 10591 | 10206 | const name_token = switch (node_tags[member_node]) { |
| 10592 | 10207 | .fn_proto_simple, |
| ... | ... | @@ -10597,9 +10212,13 @@ fn scanDecls(astgen: *AstGen, namespace: *Scope.Namespace, members: []const Ast. |
| 10597 | 10212 | .local_var_decl, |
| 10598 | 10213 | .simple_var_decl, |
| 10599 | 10214 | .aligned_var_decl, |
| 10600 | | => main_tokens[member_node] + 1, |
| 10215 | => blk: { |
| 10216 | decl_count += 1; |
| 10217 | break :blk main_tokens[member_node] + 1; |
| 10218 | }, |
| 10601 | 10219 | |
| 10602 | 10220 | .fn_decl => blk: { |
| 10221 | decl_count += 1; |
| 10603 | 10222 | const ident = main_tokens[member_node] + 1; |
| 10604 | 10223 | if (token_tags[ident] != .identifier) { |
| 10605 | 10224 | switch (astgen.failNode(member_node, "missing function name", .{})) { |
| ... | ... | @@ -10610,6 +10229,11 @@ fn scanDecls(astgen: *AstGen, namespace: *Scope.Namespace, members: []const Ast. |
| 10610 | 10229 | break :blk ident; |
| 10611 | 10230 | }, |
| 10612 | 10231 | |
| 10232 | .@"comptime", .@"usingnamespace", .test_decl => { |
| 10233 | decl_count += 1; |
| 10234 | continue; |
| 10235 | }, |
| 10236 | |
| 10613 | 10237 | else => continue, |
| 10614 | 10238 | }; |
| 10615 | 10239 | |
| ... | ... | @@ -10643,4 +10267,5 @@ fn scanDecls(astgen: *AstGen, namespace: *Scope.Namespace, members: []const Ast. |
| 10643 | 10267 | } |
| 10644 | 10268 | gop.value_ptr.* = member_node; |
| 10645 | 10269 | } |
| 10270 | return decl_count; |
| 10646 | 10271 | } |