authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-10-16 02:19:01-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-10-16 02:19:01-04:00
logac6d1674e3384bacd6893191feaf814a23d24b08
tree644fc69b51f3800aa3f1a693bf04ef1f8fdb9afd
parentce3c52471dd8a86e429ea037f4344b243723eb74

IR working for if statements


7 files changed, 1017 insertions(+), 487 deletions(-)

src/all_types.hpp+26
......@@ -1411,6 +1411,8 @@ struct IrBasicBlock {
14111411 IrBasicBlock *other;
14121412 const char *name_hint;
14131413 size_t debug_id;
1414 size_t ref_count;
1415 LLVMBasicBlockRef llvm_block;
14141416};
14151417
14161418enum IrInstructionId {
......@@ -1428,6 +1430,9 @@ enum IrInstructionId {
14281430 IrInstructionIdConst,
14291431 IrInstructionIdReturn,
14301432 IrInstructionIdCast,
1433 IrInstructionIdContainerInitList,
1434 IrInstructionIdContainerInitFields,
1435 IrInstructionIdUnreachable,
14311436};
14321437
14331438struct IrInstruction {
......@@ -1586,4 +1591,25 @@ struct IrInstructionCast {
15861591 LLVMValueRef tmp_ptr;
15871592};
15881593
1594struct IrInstructionContainerInitList {
1595 IrInstruction base;
1596
1597 IrInstruction *container_type;
1598 size_t item_count;
1599 IrInstruction **items;
1600};
1601
1602struct IrInstructionContainerInitFields {
1603 IrInstruction base;
1604
1605 IrInstruction *container_type;
1606 size_t field_count;
1607 Buf **field_names;
1608 IrInstruction **field_values;
1609};
1610
1611struct IrInstructionUnreachable {
1612 IrInstruction base;
1613};
1614
15891615#endif
src/analyze.cpp+1-189
......@@ -29,7 +29,6 @@ static TypeTableEntry *analyze_error_literal_expr(CodeGen *g, ImportTableEntry *
2929 BlockContext *context, AstNode *node, Buf *err_name);
3030static TypeTableEntry *analyze_block_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
3131 TypeTableEntry *expected_type, AstNode *node);
32static TypeTableEntry *resolve_expr_const_val_as_void(CodeGen *g, AstNode *node);
3332static TypeTableEntry *resolve_expr_const_val_as_fn(CodeGen *g, AstNode *node, FnTableEntry *fn,
3433 bool depends_on_compile_var);
3534static TypeTableEntry *resolve_expr_const_val_as_generic_fn(CodeGen *g, AstNode *node,
......@@ -2386,187 +2385,6 @@ static TypeStructField *find_struct_type_field(TypeTableEntry *type_entry, Buf *
23862385 return nullptr;
23872386}
23882387
2389static const char *err_container_init_syntax_name(ContainerInitKind kind) {
2390 switch (kind) {
2391 case ContainerInitKindStruct:
2392 return "struct";
2393 case ContainerInitKindArray:
2394 return "array";
2395 }
2396 zig_unreachable();
2397}
2398
2399static TypeTableEntry *analyze_container_init_expr(CodeGen *g, ImportTableEntry *import,
2400 BlockContext *context, AstNode *node)
2401{
2402 assert(node->type == NodeTypeContainerInitExpr);
2403
2404 AstNodeContainerInitExpr *container_init_expr = &node->data.container_init_expr;
2405
2406 ContainerInitKind kind = container_init_expr->kind;
2407
2408 if (container_init_expr->type->type == NodeTypeFieldAccessExpr) {
2409 container_init_expr->type->data.field_access_expr.container_init_expr_node = node;
2410 }
2411
2412 TypeTableEntry *container_meta_type = analyze_expression(g, import, context, nullptr,
2413 container_init_expr->type);
2414
2415 if (container_meta_type->id == TypeTableEntryIdInvalid) {
2416 return g->builtin_types.entry_invalid;
2417 }
2418
2419 if (node->data.container_init_expr.enum_type) {
2420 get_resolved_expr(node)->const_val = get_resolved_expr(container_init_expr->type)->const_val;
2421 return node->data.container_init_expr.enum_type;
2422 }
2423
2424 TypeTableEntry *container_type = resolve_type(g, container_init_expr->type);
2425
2426 if (container_type->id == TypeTableEntryIdInvalid) {
2427 return container_type;
2428 } else if (container_type->id == TypeTableEntryIdStruct &&
2429 !container_type->data.structure.is_slice &&
2430 (kind == ContainerInitKindStruct || (kind == ContainerInitKindArray &&
2431 container_init_expr->entries.length == 0)))
2432 {
2433 StructValExprCodeGen *codegen = &container_init_expr->resolved_struct_val_expr;
2434 codegen->type_entry = container_type;
2435 codegen->source_node = node;
2436
2437
2438 size_t expr_field_count = container_init_expr->entries.length;
2439 size_t actual_field_count = container_type->data.structure.src_field_count;
2440
2441 AstNode *non_const_expr_culprit = nullptr;
2442
2443 size_t *field_use_counts = allocate<size_t>(actual_field_count);
2444 ConstExprValue *const_val = &get_resolved_expr(node)->const_val;
2445 const_val->ok = true;
2446 const_val->data.x_struct.fields = allocate<ConstExprValue*>(actual_field_count);
2447 for (size_t i = 0; i < expr_field_count; i += 1) {
2448 AstNode *val_field_node = container_init_expr->entries.at(i);
2449 assert(val_field_node->type == NodeTypeStructValueField);
2450
2451 val_field_node->block_context = context;
2452
2453 TypeStructField *type_field = find_struct_type_field(container_type,
2454 val_field_node->data.struct_val_field.name);
2455
2456 if (!type_field) {
2457 add_node_error(g, val_field_node,
2458 buf_sprintf("no member named '%s' in '%s'",
2459 buf_ptr(val_field_node->data.struct_val_field.name), buf_ptr(&container_type->name)));
2460 continue;
2461 }
2462
2463 if (type_field->type_entry->id == TypeTableEntryIdInvalid) {
2464 return g->builtin_types.entry_invalid;
2465 }
2466
2467 size_t field_index = type_field->src_index;
2468 field_use_counts[field_index] += 1;
2469 if (field_use_counts[field_index] > 1) {
2470 add_node_error(g, val_field_node, buf_sprintf("duplicate field"));
2471 continue;
2472 }
2473
2474 val_field_node->data.struct_val_field.type_struct_field = type_field;
2475
2476 analyze_expression(g, import, context, type_field->type_entry,
2477 val_field_node->data.struct_val_field.expr);
2478
2479 if (const_val->ok) {
2480 ConstExprValue *field_val =
2481 &get_resolved_expr(val_field_node->data.struct_val_field.expr)->const_val;
2482 if (field_val->ok) {
2483 const_val->data.x_struct.fields[field_index] = field_val;
2484 const_val->depends_on_compile_var = const_val->depends_on_compile_var || field_val->depends_on_compile_var;
2485 } else {
2486 const_val->ok = false;
2487 non_const_expr_culprit = val_field_node->data.struct_val_field.expr;
2488 }
2489 }
2490 }
2491 if (!const_val->ok) {
2492 assert(non_const_expr_culprit);
2493 if (context->fn_entry) {
2494 context->fn_entry->struct_val_expr_alloca_list.append(codegen);
2495 } else {
2496 add_node_error(g, non_const_expr_culprit, buf_sprintf("unable to evaluate constant expression"));
2497 }
2498 }
2499
2500 for (size_t i = 0; i < actual_field_count; i += 1) {
2501 if (field_use_counts[i] == 0) {
2502 add_node_error(g, node,
2503 buf_sprintf("missing field: '%s'", buf_ptr(container_type->data.structure.fields[i].name)));
2504 }
2505 }
2506 return container_type;
2507 } else if (container_type->id == TypeTableEntryIdStruct &&
2508 container_type->data.structure.is_slice &&
2509 kind == ContainerInitKindArray)
2510 {
2511 size_t elem_count = container_init_expr->entries.length;
2512
2513 TypeTableEntry *pointer_type = container_type->data.structure.fields[0].type_entry;
2514 assert(pointer_type->id == TypeTableEntryIdPointer);
2515 TypeTableEntry *child_type = pointer_type->data.pointer.child_type;
2516
2517 ConstExprValue *const_val = &get_resolved_expr(node)->const_val;
2518 const_val->ok = true;
2519 const_val->data.x_array.fields = allocate<ConstExprValue*>(elem_count);
2520
2521 for (size_t i = 0; i < elem_count; i += 1) {
2522 AstNode **elem_node = &container_init_expr->entries.at(i);
2523 analyze_expression(g, import, context, child_type, *elem_node);
2524
2525 if (const_val->ok) {
2526 ConstExprValue *elem_const_val = &get_resolved_expr(*elem_node)->const_val;
2527 if (elem_const_val->ok) {
2528 const_val->data.x_array.fields[i] = elem_const_val;
2529 const_val->depends_on_compile_var = const_val->depends_on_compile_var ||
2530 elem_const_val->depends_on_compile_var;
2531 } else {
2532 const_val->ok = false;
2533 }
2534 }
2535 }
2536
2537 TypeTableEntry *fixed_size_array_type = get_array_type(g, child_type, elem_count);
2538
2539 StructValExprCodeGen *codegen = &container_init_expr->resolved_struct_val_expr;
2540 codegen->type_entry = fixed_size_array_type;
2541 codegen->source_node = node;
2542 if (!const_val->ok) {
2543 if (!context->fn_entry) {
2544 add_node_error(g, node,
2545 buf_sprintf("unable to evaluate constant expression"));
2546 } else {
2547 context->fn_entry->struct_val_expr_alloca_list.append(codegen);
2548 }
2549 }
2550
2551 return fixed_size_array_type;
2552 } else if (container_type->id == TypeTableEntryIdArray) {
2553 zig_panic("TODO array container init");
2554 return container_type;
2555 } else if (container_type->id == TypeTableEntryIdVoid) {
2556 if (container_init_expr->entries.length != 0) {
2557 add_node_error(g, node, buf_sprintf("void expression expects no arguments"));
2558 return g->builtin_types.entry_invalid;
2559 } else {
2560 return resolve_expr_const_val_as_void(g, node);
2561 }
2562 } else {
2563 add_node_error(g, node,
2564 buf_sprintf("type '%s' does not support %s initialization syntax",
2565 buf_ptr(&container_type->name), err_container_init_syntax_name(kind)));
2566 return g->builtin_types.entry_invalid;
2567 }
2568}
2569
25702388static bool is_container(TypeTableEntry *type_entry) {
25712389 switch (type_entry->id) {
25722390 case TypeTableEntryIdInvalid:
......@@ -2928,12 +2746,6 @@ static TypeTableEntry *analyze_array_access_expr(CodeGen *g, ImportTableEntry *i
29282746 return return_type;
29292747}
29302748
2931static TypeTableEntry *resolve_expr_const_val_as_void(CodeGen *g, AstNode *node) {
2932 Expr *expr = get_resolved_expr(node);
2933 expr->const_val.ok = true;
2934 return g->builtin_types.entry_void;
2935}
2936
29372749static TypeTableEntry *resolve_expr_const_val_as_type(CodeGen *g, AstNode *node, TypeTableEntry *type,
29382750 bool depends_on_compile_var)
29392751{
......@@ -5331,7 +5143,7 @@ static TypeTableEntry *analyze_expression_pointer_only(CodeGen *g, ImportTableEn
53315143 return_type = analyze_field_access_expr(g, import, context, expected_type, node);
53325144 break;
53335145 case NodeTypeContainerInitExpr:
5334 return_type = analyze_container_init_expr(g, import, context, node);
5146 zig_panic("analyze container init moved to ir.cpp");
53355147 break;
53365148 case NodeTypeNumberLiteral:
53375149 return_type = analyze_number_literal_expr(g, import, context, expected_type, node);
src/codegen.cpp+215-182
......@@ -12,6 +12,7 @@
1212#include "errmsg.hpp"
1313#include "error.hpp"
1414#include "hash_map.hpp"
15#include "ir.hpp"
1516#include "link.hpp"
1617#include "os.hpp"
1718#include "parseh.hpp"
......@@ -513,18 +514,6 @@ static LLVMValueRef gen_truncate(CodeGen *g, AstNode *node) {
513514 return LLVMBuildTrunc(g->builder, src_val, dest_type->type_ref, "");
514515}
515516
516static LLVMValueRef gen_unreachable(CodeGen *g, AstNode *node) {
517 assert(node->type == NodeTypeFnCallExpr);
518
519 if (want_debug_safety(g, node) || g->is_test_build) {
520 gen_debug_safety_crash(g);
521 } else {
522 LLVMBuildUnreachable(g->builder);
523 }
524
525 return nullptr;
526}
527
528517static LLVMValueRef gen_shl_with_overflow(CodeGen *g, AstNode *node) {
529518 assert(node->type == NodeTypeFnCallExpr);
530519
......@@ -711,7 +700,7 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {
711700 case BuiltinFnIdTruncate:
712701 return gen_truncate(g, node);
713702 case BuiltinFnIdUnreachable:
714 return gen_unreachable(g, node);
703 zig_panic("moved to ir render");
715704 case BuiltinFnIdSetFnTest:
716705 case BuiltinFnIdSetFnVisible:
717706 case BuiltinFnIdSetFnStaticEval:
......@@ -1334,154 +1323,6 @@ static LLVMValueRef gen_overflow_shl_op(CodeGen *g, TypeTableEntry *type_entry,
13341323 return result;
13351324}
13361325
1337static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) {
1338 assert(node->type == NodeTypePrefixOpExpr);
1339 assert(node->data.prefix_op_expr.primary_expr);
1340
1341 AstNode *expr_node = node->data.prefix_op_expr.primary_expr;
1342 TypeTableEntry *expr_type = get_expr_type(expr_node);
1343
1344 PrefixOp op = node->data.prefix_op_expr.prefix_op;
1345
1346 switch (op) {
1347 case PrefixOpInvalid:
1348 zig_unreachable();
1349 case PrefixOpNegation:
1350 case PrefixOpNegationWrap:
1351 {
1352 LLVMValueRef expr = gen_expr(g, expr_node);
1353 if (expr_type->id == TypeTableEntryIdFloat) {
1354 return LLVMBuildFNeg(g->builder, expr, "");
1355 } else if (expr_type->id == TypeTableEntryIdInt) {
1356 if (op == PrefixOpNegationWrap) {
1357 return LLVMBuildNeg(g->builder, expr, "");
1358 } else if (want_debug_safety(g, expr_node)) {
1359 LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(expr));
1360 return gen_overflow_op(g, expr_type, AddSubMulSub, zero, expr);
1361 } else if (expr_type->data.integral.is_signed) {
1362 return LLVMBuildNSWNeg(g->builder, expr, "");
1363 } else {
1364 return LLVMBuildNUWNeg(g->builder, expr, "");
1365 }
1366 } else {
1367 zig_unreachable();
1368 }
1369 }
1370 case PrefixOpBoolNot:
1371 {
1372 LLVMValueRef expr = gen_expr(g, expr_node);
1373 LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(expr));
1374 return LLVMBuildICmp(g->builder, LLVMIntEQ, expr, zero, "");
1375 }
1376 case PrefixOpBinNot:
1377 {
1378 LLVMValueRef expr = gen_expr(g, expr_node);
1379 return LLVMBuildNot(g->builder, expr, "");
1380 }
1381 case PrefixOpAddressOf:
1382 case PrefixOpConstAddressOf:
1383 {
1384 TypeTableEntry *lvalue_type;
1385 return gen_lvalue(g, node, expr_node, &lvalue_type);
1386 }
1387
1388 case PrefixOpDereference:
1389 {
1390 LLVMValueRef expr = gen_expr(g, expr_node);
1391 assert(expr_type->id == TypeTableEntryIdPointer);
1392 if (!type_has_bits(expr_type)) {
1393 return nullptr;
1394 } else {
1395 TypeTableEntry *child_type = expr_type->data.pointer.child_type;
1396 return get_handle_value(g, expr, child_type);
1397 }
1398 }
1399 case PrefixOpMaybe:
1400 {
1401 zig_panic("TODO codegen PrefixOpMaybe");
1402 }
1403 case PrefixOpError:
1404 {
1405 zig_panic("TODO codegen PrefixOpError");
1406 }
1407 case PrefixOpUnwrapError:
1408 {
1409 LLVMValueRef expr_val = gen_expr(g, expr_node);
1410 TypeTableEntry *expr_type = get_expr_type(expr_node);
1411 assert(expr_type->id == TypeTableEntryIdErrorUnion);
1412 TypeTableEntry *child_type = expr_type->data.error.child_type;
1413
1414 if (want_debug_safety(g, node)) {
1415 LLVMValueRef err_val;
1416 if (type_has_bits(child_type)) {
1417 LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, expr_val, 0, "");
1418 err_val = LLVMBuildLoad(g->builder, err_val_ptr, "");
1419 } else {
1420 err_val = expr_val;
1421 }
1422 LLVMValueRef zero = LLVMConstNull(g->err_tag_type->type_ref);
1423 LLVMValueRef cond_val = LLVMBuildICmp(g->builder, LLVMIntEQ, err_val, zero, "");
1424 LLVMBasicBlockRef err_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "UnwrapErrError");
1425 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "UnwrapErrOk");
1426 LLVMBuildCondBr(g->builder, cond_val, ok_block, err_block);
1427
1428 LLVMPositionBuilderAtEnd(g->builder, err_block);
1429 gen_debug_safety_crash(g);
1430
1431 LLVMPositionBuilderAtEnd(g->builder, ok_block);
1432 }
1433
1434 if (type_has_bits(child_type)) {
1435 LLVMValueRef child_val_ptr = LLVMBuildStructGEP(g->builder, expr_val, 1, "");
1436 return get_handle_value(g, child_val_ptr, child_type);
1437 } else {
1438 return nullptr;
1439 }
1440 }
1441 case PrefixOpUnwrapMaybe:
1442 {
1443 LLVMValueRef expr_val = gen_expr(g, expr_node);
1444
1445 TypeTableEntry *expr_type = get_expr_type(expr_node);
1446 assert(expr_type->id == TypeTableEntryIdMaybe);
1447 TypeTableEntry *child_type = expr_type->data.maybe.child_type;
1448
1449 if (want_debug_safety(g, node)) {
1450 LLVMValueRef cond_val;
1451 if (child_type->id == TypeTableEntryIdPointer ||
1452 child_type->id == TypeTableEntryIdFn)
1453 {
1454 cond_val = LLVMBuildICmp(g->builder, LLVMIntNE, expr_val,
1455 LLVMConstNull(child_type->type_ref), "");
1456 } else {
1457 LLVMValueRef maybe_null_ptr = LLVMBuildStructGEP(g->builder, expr_val, 1, "");
1458 cond_val = LLVMBuildLoad(g->builder, maybe_null_ptr, "");
1459 }
1460
1461 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "UnwrapMaybeOk");
1462 LLVMBasicBlockRef null_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "UnwrapMaybeNull");
1463 LLVMBuildCondBr(g->builder, cond_val, ok_block, null_block);
1464
1465 LLVMPositionBuilderAtEnd(g->builder, null_block);
1466 gen_debug_safety_crash(g);
1467
1468 LLVMPositionBuilderAtEnd(g->builder, ok_block);
1469 }
1470
1471
1472 if (child_type->id == TypeTableEntryIdPointer ||
1473 child_type->id == TypeTableEntryIdFn)
1474 {
1475 return expr_val;
1476 } else {
1477 LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, expr_val, 0, "");
1478 return get_handle_value(g, maybe_field_ptr, child_type);
1479 }
1480 }
1481 }
1482 zig_unreachable();
1483}
1484
14851326static LLVMValueRef gen_div(CodeGen *g, AstNode *source_node, LLVMValueRef val1, LLVMValueRef val2,
14861327 TypeTableEntry *type_entry, bool exact)
14871328{
......@@ -2468,8 +2309,20 @@ static LLVMValueRef gen_if_var_expr(CodeGen *g, AstNode *node) {
24682309 return nullptr;
24692310}
24702311
2312static LLVMValueRef ir_llvm_value(CodeGen *g, IrInstruction *instruction) {
2313 if (!type_has_bits(instruction->type_entry))
2314 return nullptr;
2315 if (!instruction->llvm_value) {
2316 assert(instruction->static_value.ok);
2317 assert(instruction->type_entry);
2318 instruction->llvm_value = gen_const_val(g, instruction->type_entry, &instruction->static_value);
2319 assert(instruction->llvm_value);
2320 }
2321 return instruction->llvm_value;
2322}
2323
24712324static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrInstructionReturn *return_instruction) {
2472 LLVMBuildRet(g->builder, return_instruction->value->llvm_value);
2325 LLVMBuildRet(g->builder, ir_llvm_value(g, return_instruction->value));
24732326 return nullptr;
24742327}
24752328
......@@ -2488,8 +2341,8 @@ static LLVMValueRef ir_render_bin_op_bool(CodeGen *g, IrExecutable *executable,
24882341 IrInstructionBinOp *bin_op_instruction)
24892342{
24902343 IrBinOp op_id = bin_op_instruction->op_id;
2491 LLVMValueRef op1 = bin_op_instruction->op1->llvm_value;
2492 LLVMValueRef op2 = bin_op_instruction->op2->llvm_value;
2344 LLVMValueRef op1 = ir_llvm_value(g, bin_op_instruction->op1);
2345 LLVMValueRef op2 = ir_llvm_value(g, bin_op_instruction->op2);
24932346 if (op_id == IrBinOpBoolOr) {
24942347 return LLVMBuildOr(g->builder, op1, op2, "");
24952348 } else if (op_id == IrBinOpBoolAnd) {
......@@ -2508,18 +2361,21 @@ static LLVMValueRef ir_render_bin_op_add(CodeGen *g, IrExecutable *executable,
25082361
25092362 assert(op1->type_entry == op2->type_entry);
25102363
2364 LLVMValueRef op1_value = ir_llvm_value(g, op1);
2365 LLVMValueRef op2_value = ir_llvm_value(g, op2);
2366
25112367 if (op1->type_entry->id == TypeTableEntryIdFloat) {
2512 return LLVMBuildFAdd(g->builder, op1->llvm_value, op2->llvm_value, "");
2368 return LLVMBuildFAdd(g->builder, op1_value, op2_value, "");
25132369 } else if (op1->type_entry->id == TypeTableEntryIdInt) {
25142370 bool is_wrapping = (op_id == IrBinOpAddWrap);
25152371 if (is_wrapping) {
2516 return LLVMBuildAdd(g->builder, op1->llvm_value, op2->llvm_value, "");
2372 return LLVMBuildAdd(g->builder, op1_value, op2_value, "");
25172373 } else if (ir_want_debug_safety(g, &bin_op_instruction->base)) {
2518 return gen_overflow_op(g, op1->type_entry, AddSubMulAdd, op1->llvm_value, op2->llvm_value);
2374 return gen_overflow_op(g, op1->type_entry, AddSubMulAdd, op1_value, op2_value);
25192375 } else if (op1->type_entry->data.integral.is_signed) {
2520 return LLVMBuildNSWAdd(g->builder, op1->llvm_value, op2->llvm_value, "");
2376 return LLVMBuildNSWAdd(g->builder, op1_value, op2_value, "");
25212377 } else {
2522 return LLVMBuildNUWAdd(g->builder, op1->llvm_value, op2->llvm_value, "");
2378 return LLVMBuildNUWAdd(g->builder, op1_value, op2_value, "");
25232379 }
25242380 } else {
25252381 zig_unreachable();
......@@ -2570,7 +2426,7 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
25702426{
25712427 TypeTableEntry *actual_type = cast_instruction->value->type_entry;
25722428 TypeTableEntry *wanted_type = cast_instruction->base.type_entry;
2573 LLVMValueRef expr_val = cast_instruction->value->llvm_value;
2429 LLVMValueRef expr_val = ir_llvm_value(g, cast_instruction->value);
25742430 assert(expr_val);
25752431
25762432 switch (cast_instruction->cast_op) {
......@@ -2792,13 +2648,176 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
27922648 zig_unreachable();
27932649}
27942650
2651static LLVMValueRef ir_render_unreachable(CodeGen *g, IrExecutable *executable,
2652 IrInstructionUnreachable *unreachable_instruction)
2653{
2654 if (ir_want_debug_safety(g, &unreachable_instruction->base) || g->is_test_build) {
2655 gen_debug_safety_crash(g);
2656 } else {
2657 LLVMBuildUnreachable(g->builder);
2658 }
2659 return nullptr;
2660}
2661
2662static LLVMValueRef ir_render_cond_br(CodeGen *g, IrExecutable *executable,
2663 IrInstructionCondBr *cond_br_instruction)
2664{
2665 LLVMBuildCondBr(g->builder,
2666 ir_llvm_value(g, cond_br_instruction->condition),
2667 cond_br_instruction->then_block->llvm_block,
2668 cond_br_instruction->else_block->llvm_block);
2669 return nullptr;
2670}
2671
2672static LLVMValueRef ir_render_br(CodeGen *g, IrExecutable *executable, IrInstructionBr *br_instruction) {
2673 LLVMBuildBr(g->builder, br_instruction->dest_block->llvm_block);
2674 return nullptr;
2675}
2676
2677static LLVMValueRef ir_render_un_op(CodeGen *g, IrExecutable *executable, IrInstructionUnOp *un_op_instruction) {
2678 IrUnOp op_id = un_op_instruction->op_id;
2679 LLVMValueRef expr = ir_llvm_value(g, un_op_instruction->value);
2680 TypeTableEntry *expr_type = un_op_instruction->value->type_entry;
2681
2682 switch (op_id) {
2683 case IrUnOpInvalid:
2684 zig_unreachable();
2685 case IrUnOpNegation:
2686 case IrUnOpNegationWrap:
2687 {
2688 if (expr_type->id == TypeTableEntryIdFloat) {
2689 return LLVMBuildFNeg(g->builder, expr, "");
2690 } else if (expr_type->id == TypeTableEntryIdInt) {
2691 if (op_id == IrUnOpNegationWrap) {
2692 return LLVMBuildNeg(g->builder, expr, "");
2693 } else if (ir_want_debug_safety(g, &un_op_instruction->base)) {
2694 LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(expr));
2695 return gen_overflow_op(g, expr_type, AddSubMulSub, zero, expr);
2696 } else if (expr_type->data.integral.is_signed) {
2697 return LLVMBuildNSWNeg(g->builder, expr, "");
2698 } else {
2699 return LLVMBuildNUWNeg(g->builder, expr, "");
2700 }
2701 } else {
2702 zig_unreachable();
2703 }
2704 }
2705 case IrUnOpBoolNot:
2706 {
2707 LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(expr));
2708 return LLVMBuildICmp(g->builder, LLVMIntEQ, expr, zero, "");
2709 }
2710 case IrUnOpBinNot:
2711 return LLVMBuildNot(g->builder, expr, "");
2712 case IrUnOpAddressOf:
2713 case IrUnOpConstAddressOf:
2714 zig_panic("TODO address of codegen");
2715 //{
2716 // TypeTableEntry *lvalue_type;
2717 // return gen_lvalue(g, node, expr_node, &lvalue_type);
2718 //}
2719 case IrUnOpDereference:
2720 {
2721 assert(expr_type->id == TypeTableEntryIdPointer);
2722 if (!type_has_bits(expr_type)) {
2723 return nullptr;
2724 } else {
2725 TypeTableEntry *child_type = expr_type->data.pointer.child_type;
2726 return get_handle_value(g, expr, child_type);
2727 }
2728 }
2729 case IrUnOpError:
2730 {
2731 zig_panic("TODO codegen PrefixOpError");
2732 }
2733 case IrUnOpMaybe:
2734 {
2735 zig_panic("TODO codegen PrefixOpMaybe");
2736 }
2737 case IrUnOpUnwrapError:
2738 {
2739 assert(expr_type->id == TypeTableEntryIdErrorUnion);
2740 TypeTableEntry *child_type = expr_type->data.error.child_type;
2741
2742 if (ir_want_debug_safety(g, &un_op_instruction->base)) {
2743 LLVMValueRef err_val;
2744 if (type_has_bits(child_type)) {
2745 LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, expr, 0, "");
2746 err_val = LLVMBuildLoad(g->builder, err_val_ptr, "");
2747 } else {
2748 err_val = expr;
2749 }
2750 LLVMValueRef zero = LLVMConstNull(g->err_tag_type->type_ref);
2751 LLVMValueRef cond_val = LLVMBuildICmp(g->builder, LLVMIntEQ, err_val, zero, "");
2752 LLVMBasicBlockRef err_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "UnwrapErrError");
2753 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "UnwrapErrOk");
2754 LLVMBuildCondBr(g->builder, cond_val, ok_block, err_block);
2755
2756 LLVMPositionBuilderAtEnd(g->builder, err_block);
2757 gen_debug_safety_crash(g);
2758
2759 LLVMPositionBuilderAtEnd(g->builder, ok_block);
2760 }
2761
2762 if (type_has_bits(child_type)) {
2763 LLVMValueRef child_val_ptr = LLVMBuildStructGEP(g->builder, expr, 1, "");
2764 return get_handle_value(g, child_val_ptr, child_type);
2765 } else {
2766 return nullptr;
2767 }
2768 }
2769 case IrUnOpUnwrapMaybe:
2770 {
2771 assert(expr_type->id == TypeTableEntryIdMaybe);
2772 TypeTableEntry *child_type = expr_type->data.maybe.child_type;
2773
2774 if (ir_want_debug_safety(g, &un_op_instruction->base)) {
2775 LLVMValueRef cond_val;
2776 if (child_type->id == TypeTableEntryIdPointer ||
2777 child_type->id == TypeTableEntryIdFn)
2778 {
2779 cond_val = LLVMBuildICmp(g->builder, LLVMIntNE, expr,
2780 LLVMConstNull(child_type->type_ref), "");
2781 } else {
2782 LLVMValueRef maybe_null_ptr = LLVMBuildStructGEP(g->builder, expr, 1, "");
2783 cond_val = LLVMBuildLoad(g->builder, maybe_null_ptr, "");
2784 }
2785
2786 LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "UnwrapMaybeOk");
2787 LLVMBasicBlockRef null_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "UnwrapMaybeNull");
2788 LLVMBuildCondBr(g->builder, cond_val, ok_block, null_block);
2789
2790 LLVMPositionBuilderAtEnd(g->builder, null_block);
2791 gen_debug_safety_crash(g);
2792
2793 LLVMPositionBuilderAtEnd(g->builder, ok_block);
2794 }
2795
2796
2797 if (child_type->id == TypeTableEntryIdPointer ||
2798 child_type->id == TypeTableEntryIdFn)
2799 {
2800 return expr;
2801 } else {
2802 LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, expr, 0, "");
2803 return get_handle_value(g, maybe_field_ptr, child_type);
2804 }
2805 }
2806 case IrUnOpErrorReturn:
2807 case IrUnOpMaybeReturn:
2808 zig_panic("TODO codegen more un ops");
2809 }
2810
2811 zig_unreachable();
2812}
2813
27952814static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, IrInstruction *instruction) {
27962815 set_debug_source_node(g, instruction->source_node);
2816
27972817 switch (instruction->id) {
27982818 case IrInstructionIdInvalid:
2799 zig_unreachable();
28002819 case IrInstructionIdConst:
2801 return gen_const_val(g, instruction->type_entry, &instruction->static_value);
2820 zig_unreachable();
28022821 case IrInstructionIdReturn:
28032822 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);
28042823 case IrInstructionIdLoadVar:
......@@ -2807,14 +2826,21 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
28072826 return ir_render_bin_op(g, executable, (IrInstructionBinOp *)instruction);
28082827 case IrInstructionIdCast:
28092828 return ir_render_cast(g, executable, (IrInstructionCast *)instruction);
2829 case IrInstructionIdUnreachable:
2830 return ir_render_unreachable(g, executable, (IrInstructionUnreachable *)instruction);
28102831 case IrInstructionIdCondBr:
2832 return ir_render_cond_br(g, executable, (IrInstructionCondBr *)instruction);
28112833 case IrInstructionIdBr:
2834 return ir_render_br(g, executable, (IrInstructionBr *)instruction);
2835 case IrInstructionIdUnOp:
2836 return ir_render_un_op(g, executable, (IrInstructionUnOp *)instruction);
28122837 case IrInstructionIdSwitchBr:
28132838 case IrInstructionIdPhi:
28142839 case IrInstructionIdStoreVar:
28152840 case IrInstructionIdCall:
28162841 case IrInstructionIdBuiltinCall:
2817 case IrInstructionIdUnOp:
2842 case IrInstructionIdContainerInitList:
2843 case IrInstructionIdContainerInitFields:
28182844 zig_panic("TODO render more IR instructions to LLVM");
28192845 }
28202846 zig_unreachable();
......@@ -2826,8 +2852,14 @@ static void ir_render(CodeGen *g, FnTableEntry *fn_entry) {
28262852 assert(executable->basic_block_list.length > 0);
28272853 for (size_t block_i = 0; block_i < executable->basic_block_list.length; block_i += 1) {
28282854 IrBasicBlock *current_block = executable->basic_block_list.at(block_i);
2855 if (current_block->ref_count == 0)
2856 continue;
2857 assert(current_block->llvm_block);
2858 LLVMPositionBuilderAtEnd(g->builder, current_block->llvm_block);
28292859 for (size_t instr_i = 0; instr_i < current_block->instruction_list.length; instr_i += 1) {
28302860 IrInstruction *instruction = current_block->instruction_list.at(instr_i);
2861 if (instruction->ref_count == 0 && !ir_has_side_effects(instruction))
2862 continue;
28312863 instruction->llvm_value = ir_render_instruction(g, executable, instruction);
28322864 }
28332865 }
......@@ -3622,7 +3654,7 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {
36223654 case NodeTypeVariableDeclaration:
36233655 return gen_var_decl_expr(g, node);
36243656 case NodeTypePrefixOpExpr:
3625 return gen_prefix_op_expr(g, node);
3657 zig_panic("moved to ir render");
36263658 case NodeTypeFnCallExpr:
36273659 return gen_fn_call_expr(g, node);
36283660 case NodeTypeArrayAccessExpr:
......@@ -4018,14 +4050,15 @@ static void generate_error_name_table(CodeGen *g) {
40184050 LLVMSetUnnamedAddr(g->err_name_table, true);
40194051}
40204052
4021static void build_label_blocks(CodeGen *g, FnTableEntry *fn) {
4022 LLVMBasicBlockRef entry_block = LLVMAppendBasicBlock(fn->fn_value, "entry");
4023 for (size_t i = 0; i < fn->all_labels.length; i += 1) {
4024 LabelTableEntry *label = fn->all_labels.at(i);
4025 Buf *name = label->decl_node->data.label.name;
4026 label->basic_block = LLVMAppendBasicBlock(fn->fn_value, buf_ptr(name));
4053static void build_all_basic_blocks(CodeGen *g, FnTableEntry *fn) {
4054 IrExecutable *executable = &fn->analyzed_executable;
4055 assert(executable->basic_block_list.length > 0);
4056 for (size_t block_i = 0; block_i < executable->basic_block_list.length; block_i += 1) {
4057 IrBasicBlock *bb = executable->basic_block_list.at(block_i);
4058 bb->llvm_block = LLVMAppendBasicBlock(fn->fn_value, bb->name_hint);
40274059 }
4028 LLVMPositionBuilderAtEnd(g->builder, entry_block);
4060 IrBasicBlock *entry_bb = executable->basic_block_list.at(0);
4061 LLVMPositionBuilderAtEnd(g->builder, entry_bb->llvm_block);
40294062}
40304063
40314064static void gen_global_var(CodeGen *g, VariableTableEntry *var, LLVMValueRef init_val,
......@@ -4252,7 +4285,7 @@ static void do_code_gen(CodeGen *g) {
42524285 assert(proto_node->type == NodeTypeFnProto);
42534286 AstNodeFnProto *fn_proto = &proto_node->data.fn_proto;
42544287
4255 build_label_blocks(g, fn_table_entry);
4288 build_all_basic_blocks(g, fn_table_entry);
42564289
42574290
42584291 // Set up debug info for blocks
src/ir.cpp+659-50
......@@ -40,6 +40,29 @@ static size_t exec_next_debug_id(IrExecutable *exec) {
4040 return result;
4141}
4242
43static void ir_link_new_instruction(IrInstruction *new_instruction, IrInstruction *old_instruction) {
44 new_instruction->other = old_instruction;
45 old_instruction->other = new_instruction;
46}
47
48static void ir_link_new_bb(IrBasicBlock *new_bb, IrBasicBlock *old_bb) {
49 new_bb->other = old_bb;
50 old_bb->other = new_bb;
51}
52
53static void ir_ref_bb(IrBasicBlock *bb) {
54 bb->ref_count += 1;
55}
56
57static void ir_unref_bb(IrBasicBlock *bb) {
58 bb->ref_count -= 1;
59 assert(bb->ref_count != SIZE_MAX);
60}
61
62static void ir_ref_instruction(IrInstruction *instruction) {
63 instruction->ref_count += 1;
64}
65
4366static IrBasicBlock *ir_build_basic_block(IrBuilder *irb, const char *name_hint) {
4467 IrBasicBlock *result = allocate<IrBasicBlock>(1);
4568 result->name_hint = name_hint;
......@@ -48,10 +71,20 @@ static IrBasicBlock *ir_build_basic_block(IrBuilder *irb, const char *name_hint)
4871 return result;
4972}
5073
74static IrBasicBlock *ir_build_bb_from(IrBuilder *irb, IrBasicBlock *other_bb) {
75 IrBasicBlock *new_bb = ir_build_basic_block(irb, other_bb->name_hint);
76 ir_link_new_bb(new_bb, other_bb);
77 return new_bb;
78}
79
5180static constexpr IrInstructionId ir_instruction_id(IrInstructionCondBr *) {
5281 return IrInstructionIdCondBr;
5382}
5483
84static constexpr IrInstructionId ir_instruction_id(IrInstructionBr *) {
85 return IrInstructionIdBr;
86}
87
5588static constexpr IrInstructionId ir_instruction_id(IrInstructionSwitchBr *) {
5689 return IrInstructionIdSwitchBr;
5790}
......@@ -96,8 +129,16 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCast *) {
96129 return IrInstructionIdCast;
97130}
98131
99static constexpr IrInstructionId ir_instruction_id(IrInstructionBr *) {
100 return IrInstructionIdBr;
132static constexpr IrInstructionId ir_instruction_id(IrInstructionContainerInitList *) {
133 return IrInstructionIdContainerInitList;
134}
135
136static constexpr IrInstructionId ir_instruction_id(IrInstructionContainerInitFields *) {
137 return IrInstructionIdContainerInitFields;
138}
139
140static constexpr IrInstructionId ir_instruction_id(IrInstructionUnreachable *) {
141 return IrInstructionIdUnreachable;
101142}
102143
103144template<typename T>
......@@ -123,6 +164,10 @@ static IrInstruction *ir_build_cast(IrBuilder *irb, AstNode *source_node, IrInst
123164 cast_instruction->dest_type = dest_type;
124165 cast_instruction->value = value;
125166 cast_instruction->cast_op = cast_op;
167
168 ir_ref_instruction(dest_type);
169 ir_ref_instruction(value);
170
126171 return &cast_instruction->base;
127172}
128173
......@@ -135,19 +180,44 @@ static IrInstruction *ir_build_cond_br(IrBuilder *irb, AstNode *source_node, IrI
135180 cond_br_instruction->condition = condition;
136181 cond_br_instruction->then_block = then_block;
137182 cond_br_instruction->else_block = else_block;
183
184 ir_ref_instruction(condition);
185 ir_ref_bb(then_block);
186 ir_ref_bb(else_block);
187
138188 return &cond_br_instruction->base;
139189}
140190
191static IrInstruction *ir_build_cond_br_from(IrBuilder *irb, IrInstruction *old_instruction,
192 IrInstruction *condition, IrBasicBlock *then_block, IrBasicBlock *else_block)
193{
194 IrInstruction *new_instruction = ir_build_cond_br(irb, old_instruction->source_node,
195 condition, then_block, else_block);
196 ir_link_new_instruction(new_instruction, old_instruction);
197 return new_instruction;
198}
199
141200static IrInstruction *ir_build_return(IrBuilder *irb, AstNode *source_node, IrInstruction *return_value) {
142201 IrInstructionReturn *return_instruction = ir_build_instruction<IrInstructionReturn>(irb, source_node);
143202 return_instruction->base.type_entry = irb->codegen->builtin_types.entry_unreachable;
144203 return_instruction->base.static_value.ok = true;
145204 return_instruction->value = return_value;
205
206 ir_ref_instruction(return_value);
207
146208 return &return_instruction->base;
147209}
148210
149static IrInstruction *ir_build_const(IrBuilder *irb, AstNode *source_node, TypeTableEntry *type_entry) {
150 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node);
211static IrInstruction *ir_build_return_from(IrBuilder *irb, IrInstruction *old_instruction,
212 IrInstruction *return_value)
213{
214 IrInstruction *new_instruction = ir_build_return(irb, old_instruction->source_node, return_value);
215 ir_link_new_instruction(new_instruction, old_instruction);
216 return new_instruction;
217}
218
219static IrInstruction *ir_create_const(IrBuilder *irb, AstNode *source_node, TypeTableEntry *type_entry) {
220 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(irb->exec, source_node);
151221 const_instruction->base.type_entry = type_entry;
152222 const_instruction->base.static_value.ok = true;
153223 return &const_instruction->base;
......@@ -206,9 +276,21 @@ static IrInstruction *ir_build_bin_op(IrBuilder *irb, AstNode *source_node, IrBi
206276 bin_op_instruction->op_id = op_id;
207277 bin_op_instruction->op1 = op1;
208278 bin_op_instruction->op2 = op2;
279
280 ir_ref_instruction(op1);
281 ir_ref_instruction(op2);
282
209283 return &bin_op_instruction->base;
210284}
211285
286static IrInstruction *ir_build_bin_op_from(IrBuilder *irb, IrInstruction *old_instruction, IrBinOp op_id,
287 IrInstruction *op1, IrInstruction *op2)
288{
289 IrInstruction *new_instruction = ir_build_bin_op(irb, old_instruction->source_node, op_id, op1, op2);
290 ir_link_new_instruction(new_instruction, old_instruction);
291 return new_instruction;
292}
293
212294static IrInstruction *ir_build_load_var(IrBuilder *irb, AstNode *source_node, VariableTableEntry *var) {
213295 IrInstructionLoadVar *load_var_instruction = ir_build_instruction<IrInstructionLoadVar>(irb, source_node);
214296 load_var_instruction->base.type_entry = var->type;
......@@ -216,6 +298,15 @@ static IrInstruction *ir_build_load_var(IrBuilder *irb, AstNode *source_node, Va
216298 return &load_var_instruction->base;
217299}
218300
301static IrInstruction *ir_build_load_var_from(IrBuilder *irb, IrInstruction *old_instruction,
302 VariableTableEntry *var)
303{
304 IrInstruction *new_instruction = ir_build_load_var(irb, old_instruction->source_node, var);
305 ir_link_new_instruction(new_instruction, old_instruction);
306 return new_instruction;
307
308}
309
219310static IrInstruction *ir_build_call(IrBuilder *irb, AstNode *source_node,
220311 IrInstruction *fn, size_t arg_count, IrInstruction **args)
221312{
......@@ -223,6 +314,12 @@ static IrInstruction *ir_build_call(IrBuilder *irb, AstNode *source_node,
223314 call_instruction->fn = fn;
224315 call_instruction->arg_count = arg_count;
225316 call_instruction->args = args;
317
318 ir_ref_instruction(fn);
319 for (size_t i = 0; i < arg_count; i += 1) {
320 ir_ref_instruction(args[i]);
321 }
322
226323 return &call_instruction->base;
227324}
228325
......@@ -232,6 +329,11 @@ static IrInstruction *ir_build_builtin_call(IrBuilder *irb, AstNode *source_node
232329 IrInstructionBuiltinCall *call_instruction = ir_build_instruction<IrInstructionBuiltinCall>(irb, source_node);
233330 call_instruction->fn = fn;
234331 call_instruction->args = args;
332
333 for (size_t i = 0; i < fn->param_count; i += 1) {
334 ir_ref_instruction(args[i]);
335 }
336
235337 return &call_instruction->base;
236338}
237339
......@@ -242,22 +344,105 @@ static IrInstruction *ir_build_phi(IrBuilder *irb, AstNode *source_node,
242344 phi_instruction->incoming_count = incoming_count;
243345 phi_instruction->incoming_blocks = incoming_blocks;
244346 phi_instruction->incoming_values = incoming_values;
347
348 for (size_t i = 0; i < incoming_count; i += 1) {
349 ir_ref_instruction(incoming_values[i]);
350 }
351
245352 return &phi_instruction->base;
246353}
247354
355static IrInstruction *ir_build_phi_from(IrBuilder *irb, IrInstruction *old_instruction,
356 size_t incoming_count, IrBasicBlock **incoming_blocks, IrInstruction **incoming_values)
357{
358 IrInstruction *new_instruction = ir_build_phi(irb, old_instruction->source_node,
359 incoming_count, incoming_blocks, incoming_values);
360 ir_link_new_instruction(new_instruction, old_instruction);
361 return new_instruction;
362}
363
248364static IrInstruction *ir_build_br(IrBuilder *irb, AstNode *source_node, IrBasicBlock *dest_block) {
249365 IrInstructionBr *br_instruction = ir_build_instruction<IrInstructionBr>(irb, source_node);
250366 br_instruction->dest_block = dest_block;
367
368 ir_ref_bb(dest_block);
369
251370 return &br_instruction->base;
252371}
253372
373static IrInstruction *ir_build_br_from(IrBuilder *irb, IrInstruction *old_instruction, IrBasicBlock *dest_block) {
374 IrInstruction *new_instruction = ir_build_br(irb, old_instruction->source_node, dest_block);
375 ir_link_new_instruction(new_instruction, old_instruction);
376 return new_instruction;
377}
378
254379static IrInstruction *ir_build_un_op(IrBuilder *irb, AstNode *source_node, IrUnOp op_id, IrInstruction *value) {
255380 IrInstructionUnOp *br_instruction = ir_build_instruction<IrInstructionUnOp>(irb, source_node);
256381 br_instruction->op_id = op_id;
257382 br_instruction->value = value;
383
384 ir_ref_instruction(value);
385
258386 return &br_instruction->base;
259387}
260388
389static IrInstruction *ir_build_un_op_from(IrBuilder *irb, IrInstruction *old_instruction,
390 IrUnOp op_id, IrInstruction *value)
391{
392 IrInstruction *new_instruction = ir_build_un_op(irb, old_instruction->source_node, op_id, value);
393 ir_link_new_instruction(new_instruction, old_instruction);
394 return new_instruction;
395}
396
397static IrInstruction *ir_build_container_init_list(IrBuilder *irb, AstNode *source_node,
398 IrInstruction *container_type, size_t item_count, IrInstruction **items)
399{
400 IrInstructionContainerInitList *container_init_list_instruction =
401 ir_build_instruction<IrInstructionContainerInitList>(irb, source_node);
402 container_init_list_instruction->container_type = container_type;
403 container_init_list_instruction->item_count = item_count;
404 container_init_list_instruction->items = items;
405
406 ir_ref_instruction(container_type);
407 for (size_t i = 0; i < item_count; i += 1) {
408 ir_ref_instruction(items[i]);
409 }
410
411 return &container_init_list_instruction->base;
412}
413
414static IrInstruction *ir_build_container_init_fields(IrBuilder *irb, AstNode *source_node,
415 IrInstruction *container_type, size_t field_count, Buf **field_names, IrInstruction **field_values)
416{
417 IrInstructionContainerInitFields *container_init_fields_instruction =
418 ir_build_instruction<IrInstructionContainerInitFields>(irb, source_node);
419 container_init_fields_instruction->container_type = container_type;
420 container_init_fields_instruction->field_count = field_count;
421 container_init_fields_instruction->field_names = field_names;
422 container_init_fields_instruction->field_values = field_values;
423
424 ir_ref_instruction(container_type);
425 for (size_t i = 0; i < field_count; i += 1) {
426 ir_ref_instruction(field_values[i]);
427 }
428
429 return &container_init_fields_instruction->base;
430}
431
432static IrInstruction *ir_build_unreachable(IrBuilder *irb, AstNode *source_node) {
433 IrInstructionUnreachable *unreachable_instruction =
434 ir_build_instruction<IrInstructionUnreachable>(irb, source_node);
435 unreachable_instruction->base.static_value.ok = true;
436 unreachable_instruction->base.type_entry = irb->codegen->builtin_types.entry_unreachable;
437 return &unreachable_instruction->base;
438}
439
440static IrInstruction *ir_build_unreachable_from(IrBuilder *irb, IrInstruction *old_instruction) {
441 IrInstruction *new_instruction = ir_build_unreachable(irb, old_instruction->source_node);
442 ir_link_new_instruction(new_instruction, old_instruction);
443 return new_instruction;
444}
445
261446
262447//static size_t get_conditional_defer_count(BlockContext *inner_block, BlockContext *outer_block) {
263448// size_t result = 0;
......@@ -524,6 +709,10 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, AstNode *node) {
524709
525710 builtin_fn->ref_count += 1;
526711
712 if (builtin_fn->id == BuiltinFnIdUnreachable) {
713 return ir_build_unreachable(irb, node);
714 }
715
527716 IrInstruction **args = allocate<IrInstruction *>(actual_param_count);
528717 for (size_t i = 0; i < actual_param_count; i += 1) {
529718 AstNode *arg_node = node->data.fn_call_expr.params.at(i);
......@@ -649,6 +838,51 @@ static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, AstNode *node) {
649838 zig_unreachable();
650839}
651840
841static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, AstNode *node) {
842 assert(node->type == NodeTypeContainerInitExpr);
843
844 AstNodeContainerInitExpr *container_init_expr = &node->data.container_init_expr;
845 ContainerInitKind kind = container_init_expr->kind;
846
847 IrInstruction *container_type = ir_gen_node(irb, container_init_expr->type, node->block_context);
848 if (container_type == irb->codegen->invalid_instruction)
849 return container_type;
850
851 if (kind == ContainerInitKindStruct) {
852 size_t field_count = container_init_expr->entries.length;
853 IrInstruction **values = allocate<IrInstruction *>(field_count);
854 Buf **names = allocate<Buf *>(field_count);
855 for (size_t i = 0; i < field_count; i += 1) {
856 AstNode *entry_node = container_init_expr->entries.at(i);
857 assert(entry_node->type == NodeTypeStructValueField);
858
859 Buf *name = entry_node->data.struct_val_field.name;
860 AstNode *expr_node = entry_node->data.struct_val_field.expr;
861 IrInstruction *expr_value = ir_gen_node(irb, expr_node, node->block_context);
862 if (expr_value == irb->codegen->invalid_instruction)
863 return expr_value;
864
865 names[i] = name;
866 values[i] = expr_value;
867 }
868 return ir_build_container_init_fields(irb, node, container_type, field_count, names, values);
869 } else if (kind == ContainerInitKindArray) {
870 size_t item_count = container_init_expr->entries.length;
871 IrInstruction **values = allocate<IrInstruction *>(item_count);
872 for (size_t i = 0; i < item_count; i += 1) {
873 AstNode *expr_node = container_init_expr->entries.at(i);
874 IrInstruction *expr_value = ir_gen_node(irb, expr_node, node->block_context);
875 if (expr_value == irb->codegen->invalid_instruction)
876 return expr_value;
877
878 values[i] = expr_value;
879 }
880 return ir_build_container_init_list(irb, node, container_type, item_count, values);
881 } else {
882 zig_unreachable();
883 }
884}
885
652886static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockContext *block_context,
653887 bool pointer_only)
654888{
......@@ -670,6 +904,8 @@ static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockCont
670904 return ir_gen_if_bool_expr(irb, node);
671905 case NodeTypePrefixOpExpr:
672906 return ir_gen_prefix_op_expr(irb, node);
907 case NodeTypeContainerInitExpr:
908 return ir_gen_container_init_expr(irb, node);
673909 case NodeTypeUnwrapErrorExpr:
674910 case NodeTypeReturnExpr:
675911 case NodeTypeDefer:
......@@ -685,7 +921,6 @@ static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockCont
685921 case NodeTypeBreak:
686922 case NodeTypeContinue:
687923 case NodeTypeLabel:
688 case NodeTypeContainerInitExpr:
689924 case NodeTypeSwitchExpr:
690925 case NodeTypeBoolLiteral:
691926 case NodeTypeStringLiteral:
......@@ -733,6 +968,8 @@ static IrInstruction *ir_gen_add_return(CodeGen *g, AstNode *node, BlockContext
733968 irb->exec = ir_executable;
734969
735970 irb->current_basic_block = ir_build_basic_block(irb, "Entry");
971 // Entry block gets a reference because we enter it to begin.
972 ir_ref_bb(irb->current_basic_block);
736973
737974 IrInstruction *result = ir_gen_node_extra(irb, node, scope, pointer_only);
738975 assert(result);
......@@ -767,11 +1004,6 @@ IrInstruction *ir_gen_fn(CodeGen *codegn, FnTableEntry *fn_entry) {
7671004 return ir_gen_add_return(codegn, body_node, scope, ir_executable, add_return_yes, pointer_only_no);
7681005}
7691006
770static void ir_link_new(IrInstruction *new_instruction, IrInstruction *old_instruction) {
771 new_instruction->other = old_instruction;
772 old_instruction->other = new_instruction;
773}
774
7751007/*
7761008static void analyze_goto_pass2(CodeGen *g, ImportTableEntry *import, AstNode *node) {
7771009 assert(node->type == NodeTypeGoto);
......@@ -1033,7 +1265,7 @@ static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_inst
10331265 TypeTableEntry *wanted_type = dest_type->static_value.data.x_type;
10341266
10351267 if (value->static_value.ok) {
1036 IrInstruction *result = ir_build_const(&ira->new_irb, source_instr->source_node, wanted_type);
1268 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->source_node, wanted_type);
10371269 eval_const_expr_implicit_cast(cast_op, &value->static_value, value->type_entry,
10381270 &result->static_value, wanted_type);
10391271 return result;
......@@ -1058,6 +1290,12 @@ static bool is_u8(TypeTableEntry *type) {
10581290 !type->data.integral.is_signed && type->data.integral.bit_count == 8;
10591291}
10601292
1293static IrBasicBlock *ir_get_new_bb(IrAnalyze *ira, IrBasicBlock *old_bb) {
1294 if (old_bb->other)
1295 return old_bb->other;
1296 return ir_build_bb_from(&ira->new_irb, old_bb);
1297}
1298
10611299static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr,
10621300 IrInstruction *dest_type, IrInstruction *value)
10631301{
......@@ -1365,10 +1603,7 @@ static TypeTableEntry *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructi
13651603 return ira->codegen->builtin_types.entry_invalid;
13661604 }
13671605
1368 ir_link_new(ir_build_return(&ira->new_irb, return_instruction->base.source_node, value),
1369 &return_instruction->base);
1370
1371 return ira->codegen->builtin_types.entry_unreachable;
1606 return ir_build_return_from(&ira->new_irb, &return_instruction->base, value)->type_entry;
13721607}
13731608
13741609static TypeTableEntry *ir_analyze_instruction_const(IrAnalyze *ira, IrInstructionConst *const_instruction) {
......@@ -1411,8 +1646,7 @@ static TypeTableEntry *ir_analyze_bin_op_bool(IrAnalyze *ira, IrInstructionBinOp
14111646 return bool_type;
14121647 }
14131648
1414 ir_link_new(ir_build_bin_op(&ira->new_irb, bin_op_instruction->base.source_node,
1415 bin_op_instruction->op_id, op1->other, op2->other), &bin_op_instruction->base);
1649 ir_build_bin_op_from(&ira->new_irb, &bin_op_instruction->base, bin_op_instruction->op_id, op1->other, op2->other);
14161650
14171651 return bool_type;
14181652}
......@@ -1481,8 +1715,7 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp
14811715
14821716 zig_panic("TODO interpret bin_op_cmp");
14831717
1484 ir_link_new(ir_build_bin_op(&ira->new_irb, bin_op_instruction->base.source_node,
1485 op_id, op1->other, op2->other), &bin_op_instruction->base);
1718 ir_build_bin_op_from(&ira->new_irb, &bin_op_instruction->base, op_id, op1->other, op2->other);
14861719
14871720 return ira->codegen->builtin_types.entry_bool;
14881721}
......@@ -1639,8 +1872,7 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
16391872
16401873 }
16411874
1642 ir_link_new(ir_build_bin_op(&ira->new_irb, bin_op_instruction->base.source_node,
1643 op_id, op1->other, op2->other), &bin_op_instruction->base);
1875 ir_build_bin_op_from(&ira->new_irb, &bin_op_instruction->base, op_id, op1->other, op2->other);
16441876
16451877 return resolved_type;
16461878}
......@@ -1684,8 +1916,7 @@ static TypeTableEntry *ir_analyze_instruction_bin_op(IrAnalyze *ira, IrInstructi
16841916}
16851917
16861918static TypeTableEntry *ir_analyze_instruction_load_var(IrAnalyze *ira, IrInstructionLoadVar *load_var_instruction) {
1687 ir_link_new(ir_build_load_var(&ira->new_irb, load_var_instruction->base.source_node,
1688 load_var_instruction->var), &load_var_instruction->base);
1919 ir_build_load_var_from(&ira->new_irb, &load_var_instruction->base, load_var_instruction->var);
16891920 return load_var_instruction->var->type;
16901921}
16911922
......@@ -1709,15 +1940,14 @@ static TypeTableEntry *ir_analyze_instruction_call(IrAnalyze *ira, IrInstruction
17091940 if (cast_instruction == ira->codegen->invalid_instruction)
17101941 return ira->codegen->builtin_types.entry_invalid;
17111942
1712 ir_link_new(cast_instruction, &call_instruction->base);
1943 ir_link_new_instruction(cast_instruction, &call_instruction->base);
17131944 return cast_instruction->type_entry;
17141945 } else {
17151946 zig_panic("TODO analyze more fn call types");
17161947 }
17171948 } else {
1718 //ir_link_new(ir_build_call(&ira->new_irb, call_instruction->base.source_node,
1719 // call_instruction->fn, call_instruction->arg_count, call_instruction->args),
1720 // &call_instruction->base);
1949 //ir_build_call_from(&ira->new_irb, &call_instruction->base,
1950 // call_instruction->fn, call_instruction->arg_count, call_instruction->args);
17211951
17221952 zig_panic("TODO analyze fn call");
17231953 }
......@@ -1726,7 +1956,7 @@ static TypeTableEntry *ir_analyze_instruction_call(IrAnalyze *ira, IrInstruction
17261956static TypeTableEntry *ir_analyze_unary_bool_not(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) {
17271957 TypeTableEntry *bool_type = ira->codegen->builtin_types.entry_bool;
17281958
1729 IrInstruction *casted_value = ir_get_casted_value(ira, un_op_instruction->value, bool_type);
1959 IrInstruction *casted_value = ir_get_casted_value(ira, un_op_instruction->value->other, bool_type);
17301960 if (casted_value == ira->codegen->invalid_instruction)
17311961 return ira->codegen->builtin_types.entry_invalid;
17321962
......@@ -1739,9 +1969,7 @@ static TypeTableEntry *ir_analyze_unary_bool_not(IrAnalyze *ira, IrInstructionUn
17391969 return bool_type;
17401970 }
17411971
1742 IrInstruction *new_instruction = ir_build_un_op(&ira->new_irb, un_op_instruction->base.source_node,
1743 IrUnOpBoolNot, casted_value);
1744 ir_link_new(new_instruction, &un_op_instruction->base);
1972 ir_build_un_op_from(&ira->new_irb, &un_op_instruction->base, IrUnOpBoolNot, casted_value);
17451973
17461974 return bool_type;
17471975}
......@@ -2924,8 +3152,6 @@ static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructio
29243152// return analyze_compile_err(g, import, context, node);
29253153// case BuiltinFnIdIntType:
29263154// return analyze_int_type(g, import, context, node);
2927// case BuiltinFnIdUnreachable:
2928// return g->builtin_types.entry_unreachable;
29293155// case BuiltinFnIdSetFnTest:
29303156// return analyze_set_fn_test(g, import, context, node);
29313157// case BuiltinFnIdSetFnNoInline:
......@@ -2940,6 +3166,300 @@ static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructio
29403166// zig_unreachable();
29413167//}
29423168
3169//static TypeTableEntry *analyze_container_init_expr(CodeGen *g, ImportTableEntry *import,
3170// BlockContext *context, AstNode *node)
3171//{
3172// assert(node->type == NodeTypeContainerInitExpr);
3173//
3174// AstNodeContainerInitExpr *container_init_expr = &node->data.container_init_expr;
3175//
3176// ContainerInitKind kind = container_init_expr->kind;
3177//
3178// if (container_init_expr->type->type == NodeTypeFieldAccessExpr) {
3179// container_init_expr->type->data.field_access_expr.container_init_expr_node = node;
3180// }
3181//
3182// TypeTableEntry *container_meta_type = analyze_expression(g, import, context, nullptr,
3183// container_init_expr->type);
3184//
3185// if (container_meta_type->id == TypeTableEntryIdInvalid) {
3186// return g->builtin_types.entry_invalid;
3187// }
3188//
3189// if (node->data.container_init_expr.enum_type) {
3190// get_resolved_expr(node)->const_val = get_resolved_expr(container_init_expr->type)->const_val;
3191// return node->data.container_init_expr.enum_type;
3192// }
3193//
3194// TypeTableEntry *container_type = resolve_type(g, container_init_expr->type);
3195//
3196// if (container_type->id == TypeTableEntryIdInvalid) {
3197// return container_type;
3198// } else if (container_type->id == TypeTableEntryIdStruct &&
3199// !container_type->data.structure.is_slice &&
3200// (kind == ContainerInitKindStruct || (kind == ContainerInitKindArray &&
3201// container_init_expr->entries.length == 0)))
3202// {
3203// StructValExprCodeGen *codegen = &container_init_expr->resolved_struct_val_expr;
3204// codegen->type_entry = container_type;
3205// codegen->source_node = node;
3206//
3207//
3208// size_t expr_field_count = container_init_expr->entries.length;
3209// size_t actual_field_count = container_type->data.structure.src_field_count;
3210//
3211// AstNode *non_const_expr_culprit = nullptr;
3212//
3213// size_t *field_use_counts = allocate<size_t>(actual_field_count);
3214// ConstExprValue *const_val = &get_resolved_expr(node)->const_val;
3215// const_val->ok = true;
3216// const_val->data.x_struct.fields = allocate<ConstExprValue*>(actual_field_count);
3217// for (size_t i = 0; i < expr_field_count; i += 1) {
3218// AstNode *val_field_node = container_init_expr->entries.at(i);
3219// assert(val_field_node->type == NodeTypeStructValueField);
3220//
3221// val_field_node->block_context = context;
3222//
3223// TypeStructField *type_field = find_struct_type_field(container_type,
3224// val_field_node->data.struct_val_field.name);
3225//
3226// if (!type_field) {
3227// add_node_error(g, val_field_node,
3228// buf_sprintf("no member named '%s' in '%s'",
3229// buf_ptr(val_field_node->data.struct_val_field.name), buf_ptr(&container_type->name)));
3230// continue;
3231// }
3232//
3233// if (type_field->type_entry->id == TypeTableEntryIdInvalid) {
3234// return g->builtin_types.entry_invalid;
3235// }
3236//
3237// size_t field_index = type_field->src_index;
3238// field_use_counts[field_index] += 1;
3239// if (field_use_counts[field_index] > 1) {
3240// add_node_error(g, val_field_node, buf_sprintf("duplicate field"));
3241// continue;
3242// }
3243//
3244// val_field_node->data.struct_val_field.type_struct_field = type_field;
3245//
3246// analyze_expression(g, import, context, type_field->type_entry,
3247// val_field_node->data.struct_val_field.expr);
3248//
3249// if (const_val->ok) {
3250// ConstExprValue *field_val =
3251// &get_resolved_expr(val_field_node->data.struct_val_field.expr)->const_val;
3252// if (field_val->ok) {
3253// const_val->data.x_struct.fields[field_index] = field_val;
3254// const_val->depends_on_compile_var = const_val->depends_on_compile_var || field_val->depends_on_compile_var;
3255// } else {
3256// const_val->ok = false;
3257// non_const_expr_culprit = val_field_node->data.struct_val_field.expr;
3258// }
3259// }
3260// }
3261// if (!const_val->ok) {
3262// assert(non_const_expr_culprit);
3263// if (context->fn_entry) {
3264// context->fn_entry->struct_val_expr_alloca_list.append(codegen);
3265// } else {
3266// add_node_error(g, non_const_expr_culprit, buf_sprintf("unable to evaluate constant expression"));
3267// }
3268// }
3269//
3270// for (size_t i = 0; i < actual_field_count; i += 1) {
3271// if (field_use_counts[i] == 0) {
3272// add_node_error(g, node,
3273// buf_sprintf("missing field: '%s'", buf_ptr(container_type->data.structure.fields[i].name)));
3274// }
3275// }
3276// return container_type;
3277// } else if (container_type->id == TypeTableEntryIdStruct &&
3278// container_type->data.structure.is_slice &&
3279// kind == ContainerInitKindArray)
3280// {
3281// size_t elem_count = container_init_expr->entries.length;
3282//
3283// TypeTableEntry *pointer_type = container_type->data.structure.fields[0].type_entry;
3284// assert(pointer_type->id == TypeTableEntryIdPointer);
3285// TypeTableEntry *child_type = pointer_type->data.pointer.child_type;
3286//
3287// ConstExprValue *const_val = &get_resolved_expr(node)->const_val;
3288// const_val->ok = true;
3289// const_val->data.x_array.fields = allocate<ConstExprValue*>(elem_count);
3290//
3291// for (size_t i = 0; i < elem_count; i += 1) {
3292// AstNode **elem_node = &container_init_expr->entries.at(i);
3293// analyze_expression(g, import, context, child_type, *elem_node);
3294//
3295// if (const_val->ok) {
3296// ConstExprValue *elem_const_val = &get_resolved_expr(*elem_node)->const_val;
3297// if (elem_const_val->ok) {
3298// const_val->data.x_array.fields[i] = elem_const_val;
3299// const_val->depends_on_compile_var = const_val->depends_on_compile_var ||
3300// elem_const_val->depends_on_compile_var;
3301// } else {
3302// const_val->ok = false;
3303// }
3304// }
3305// }
3306//
3307// TypeTableEntry *fixed_size_array_type = get_array_type(g, child_type, elem_count);
3308//
3309// StructValExprCodeGen *codegen = &container_init_expr->resolved_struct_val_expr;
3310// codegen->type_entry = fixed_size_array_type;
3311// codegen->source_node = node;
3312// if (!const_val->ok) {
3313// if (!context->fn_entry) {
3314// add_node_error(g, node,
3315// buf_sprintf("unable to evaluate constant expression"));
3316// } else {
3317// context->fn_entry->struct_val_expr_alloca_list.append(codegen);
3318// }
3319// }
3320//
3321// return fixed_size_array_type;
3322// } else if (container_type->id == TypeTableEntryIdArray) {
3323// zig_panic("TODO array container init");
3324// return container_type;
3325// } else if (container_type->id == TypeTableEntryIdVoid) {
3326// if (container_init_expr->entries.length != 0) {
3327// add_node_error(g, node, buf_sprintf("void expression expects no arguments"));
3328// return g->builtin_types.entry_invalid;
3329// } else {
3330// return resolve_expr_const_val_as_void(g, node);
3331// }
3332// } else {
3333// add_node_error(g, node,
3334// buf_sprintf("type '%s' does not support %s initialization syntax",
3335// buf_ptr(&container_type->name), err_container_init_syntax_name(kind)));
3336// return g->builtin_types.entry_invalid;
3337// }
3338//}
3339
3340static TypeTableEntry *ir_analyze_instruction_br(IrAnalyze *ira, IrInstructionBr *br_instruction) {
3341 IrBasicBlock *old_dest_block = br_instruction->dest_block;
3342 IrBasicBlock *new_bb = ir_get_new_bb(ira, old_dest_block);
3343 ir_build_br_from(&ira->new_irb, &br_instruction->base, new_bb);
3344 return ira->codegen->builtin_types.entry_unreachable;
3345}
3346
3347static TypeTableEntry *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructionCondBr *cond_br_instruction) {
3348 TypeTableEntry *bool_type = ira->codegen->builtin_types.entry_bool;
3349 IrInstruction *condition = ir_get_casted_value(ira, cond_br_instruction->condition->other, bool_type);
3350 if (condition == ira->codegen->invalid_instruction)
3351 return ira->codegen->builtin_types.entry_invalid;
3352
3353 if (condition->static_value.ok) {
3354 IrBasicBlock *old_dest_block;
3355 IrBasicBlock *old_ignored_block;
3356 if (condition->static_value.data.x_bool) {
3357 old_dest_block = cond_br_instruction->then_block;
3358 old_ignored_block = cond_br_instruction->else_block;
3359 } else {
3360 old_dest_block = cond_br_instruction->else_block;
3361 old_ignored_block = cond_br_instruction->then_block;
3362 }
3363 ir_unref_bb(old_ignored_block);
3364 IrBasicBlock *new_bb = ir_get_new_bb(ira, old_dest_block);
3365 ir_build_br_from(&ira->new_irb, &cond_br_instruction->base, new_bb);
3366 return ira->codegen->builtin_types.entry_unreachable;
3367 }
3368
3369 IrBasicBlock *new_then_block = ir_get_new_bb(ira, cond_br_instruction->then_block);
3370 IrBasicBlock *new_else_block = ir_get_new_bb(ira, cond_br_instruction->else_block);
3371 ir_build_cond_br_from(&ira->new_irb, &cond_br_instruction->base, condition, new_then_block, new_else_block);
3372 return ira->codegen->builtin_types.entry_unreachable;
3373}
3374
3375static TypeTableEntry *ir_analyze_instruction_builtin_call(IrAnalyze *ira,
3376 IrInstructionBuiltinCall *builtin_call_instruction)
3377{
3378 switch (builtin_call_instruction->fn->id) {
3379 case BuiltinFnIdInvalid:
3380 case BuiltinFnIdUnreachable:
3381 zig_unreachable();
3382 case BuiltinFnIdMemcpy:
3383 case BuiltinFnIdMemset:
3384 case BuiltinFnIdSizeof:
3385 case BuiltinFnIdAlignof:
3386 case BuiltinFnIdMaxValue:
3387 case BuiltinFnIdMinValue:
3388 case BuiltinFnIdMemberCount:
3389 case BuiltinFnIdTypeof:
3390 case BuiltinFnIdAddWithOverflow:
3391 case BuiltinFnIdSubWithOverflow:
3392 case BuiltinFnIdMulWithOverflow:
3393 case BuiltinFnIdShlWithOverflow:
3394 case BuiltinFnIdCInclude:
3395 case BuiltinFnIdCDefine:
3396 case BuiltinFnIdCUndef:
3397 case BuiltinFnIdCompileVar:
3398 case BuiltinFnIdCompileErr:
3399 case BuiltinFnIdConstEval:
3400 case BuiltinFnIdCtz:
3401 case BuiltinFnIdClz:
3402 case BuiltinFnIdImport:
3403 case BuiltinFnIdCImport:
3404 case BuiltinFnIdErrName:
3405 case BuiltinFnIdBreakpoint:
3406 case BuiltinFnIdReturnAddress:
3407 case BuiltinFnIdFrameAddress:
3408 case BuiltinFnIdEmbedFile:
3409 case BuiltinFnIdCmpExchange:
3410 case BuiltinFnIdFence:
3411 case BuiltinFnIdDivExact:
3412 case BuiltinFnIdTruncate:
3413 case BuiltinFnIdIntType:
3414 case BuiltinFnIdSetFnTest:
3415 case BuiltinFnIdSetFnVisible:
3416 case BuiltinFnIdSetFnStaticEval:
3417 case BuiltinFnIdSetFnNoInline:
3418 case BuiltinFnIdSetDebugSafety:
3419 zig_panic("TODO analyze more builtin functions");
3420 }
3421 zig_unreachable();
3422}
3423
3424static TypeTableEntry *ir_analyze_instruction_unreachable(IrAnalyze *ira,
3425 IrInstructionUnreachable *unreachable_instruction)
3426{
3427 return ir_build_unreachable_from(&ira->new_irb, &unreachable_instruction->base)->type_entry;
3428}
3429
3430static TypeTableEntry *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPhi *phi_instruction) {
3431 ZigList<IrBasicBlock*> new_incoming_blocks = {0};
3432 ZigList<IrInstruction*> new_incoming_values = {0};
3433
3434 for (size_t i = 0; i < phi_instruction->incoming_count; i += 1) {
3435 IrBasicBlock *predecessor = phi_instruction->incoming_blocks[i];
3436 if (predecessor->ref_count == 0)
3437 continue;
3438
3439 assert(predecessor->other);
3440 new_incoming_blocks.append(predecessor->other);
3441
3442 IrInstruction *old_value = phi_instruction->incoming_values[i];
3443 assert(old_value);
3444 new_incoming_values.append(old_value->other);
3445 }
3446 assert(new_incoming_blocks.length != 0);
3447
3448 if (new_incoming_blocks.length == 1) {
3449 IrInstruction *first_value = new_incoming_values.at(0);
3450 phi_instruction->base.other = first_value;
3451 return first_value->type_entry;
3452 }
3453
3454 TypeTableEntry *resolved_type = ir_resolve_peer_types(ira, &phi_instruction->base,
3455 new_incoming_values.items, new_incoming_values.length);
3456 if (resolved_type->id == TypeTableEntryIdInvalid)
3457 return resolved_type;
3458
3459 ir_build_phi_from(&ira->new_irb, &phi_instruction->base, new_incoming_blocks.length,
3460 new_incoming_blocks.items, new_incoming_values.items);
3461 return resolved_type;
3462}
29433463
29443464static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
29453465 switch (instruction->id) {
......@@ -2957,13 +3477,21 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
29573477 return ir_analyze_instruction_load_var(ira, (IrInstructionLoadVar *)instruction);
29583478 case IrInstructionIdCall:
29593479 return ir_analyze_instruction_call(ira, (IrInstructionCall *)instruction);
2960 case IrInstructionIdCondBr:
29613480 case IrInstructionIdBr:
2962 case IrInstructionIdSwitchBr:
3481 return ir_analyze_instruction_br(ira, (IrInstructionBr *)instruction);
3482 case IrInstructionIdCondBr:
3483 return ir_analyze_instruction_cond_br(ira, (IrInstructionCondBr *)instruction);
3484 case IrInstructionIdBuiltinCall:
3485 return ir_analyze_instruction_builtin_call(ira, (IrInstructionBuiltinCall *)instruction);
3486 case IrInstructionIdUnreachable:
3487 return ir_analyze_instruction_unreachable(ira, (IrInstructionUnreachable *)instruction);
29633488 case IrInstructionIdPhi:
3489 return ir_analyze_instruction_phi(ira, (IrInstructionPhi *)instruction);
3490 case IrInstructionIdSwitchBr:
29643491 case IrInstructionIdStoreVar:
2965 case IrInstructionIdBuiltinCall:
29663492 case IrInstructionIdCast:
3493 case IrInstructionIdContainerInitList:
3494 case IrInstructionIdContainerInitFields:
29673495 zig_panic("TODO analyze more instructions");
29683496 }
29693497 zig_unreachable();
......@@ -3000,25 +3528,106 @@ TypeTableEntry *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutabl
30003528 ira->exec_context.var_slot_list = allocate<IrVarSlot>(ira->exec_context.var_slot_count);
30013529
30023530 TypeTableEntry *return_type = ira->codegen->builtin_types.entry_void;
3531 for (size_t bb_i = 0; bb_i < ira->old_irb.exec->basic_block_list.length; bb_i += 1) {
3532 ira->old_irb.current_basic_block = ira->old_irb.exec->basic_block_list.at(bb_i);
3533 if (ira->old_irb.current_basic_block->ref_count == 0)
3534 continue;
30033535
3004 ira->new_irb.current_basic_block = ir_build_basic_block(&ira->new_irb, "Entry");
3005 ira->old_irb.current_basic_block = ira->old_irb.exec->basic_block_list.at(0);
3006
3007 ira->new_irb.current_basic_block->other = ira->old_irb.current_basic_block;
3008 ira->old_irb.current_basic_block->other = ira->new_irb.current_basic_block;
3536 ira->new_irb.current_basic_block = ir_get_new_bb(ira, ira->old_irb.current_basic_block);
30093537
3538 return_type = ira->codegen->builtin_types.entry_void;
30103539
3011 for (size_t i = 0; i < ira->old_irb.current_basic_block->instruction_list.length; i += 1) {
3012 IrInstruction *instruction = ira->old_irb.current_basic_block->instruction_list.at(i);
3013 if (return_type->id == TypeTableEntryIdUnreachable) {
3014 add_node_error(ira->codegen, first_executing_node(instruction->source_node),
3015 buf_sprintf("unreachable code"));
3016 break;
3540 for (size_t instr_i = 0; instr_i < ira->old_irb.current_basic_block->instruction_list.length; instr_i += 1) {
3541 IrInstruction *instruction = ira->old_irb.current_basic_block->instruction_list.at(instr_i);
3542 if (return_type->id == TypeTableEntryIdUnreachable) {
3543 // TODO
3544 //add_node_error(ira->codegen, first_executing_node(instruction->source_node),
3545 // buf_sprintf("unreachable code"));
3546 break;
3547 }
3548 bool is_last = (instr_i == ira->old_irb.current_basic_block->instruction_list.length - 1);
3549 TypeTableEntry *passed_expected_type = is_last ? expected_type : nullptr;
3550 return_type = ir_analyze_instruction(ira, instruction, passed_expected_type);
30173551 }
3018 bool is_last = (i == ira->old_irb.current_basic_block->instruction_list.length - 1);
3019 TypeTableEntry *passed_expected_type = is_last ? expected_type : nullptr;
3020 return_type = ir_analyze_instruction(ira, instruction, passed_expected_type);
30213552 }
30223553
3554 // Give entry block a ref
3555 ir_ref_bb(ira->new_irb.exec->basic_block_list.at(0));
3556
30233557 return return_type;
30243558}
3559
3560static bool ir_builtin_call_has_side_effects(IrInstructionBuiltinCall *call_instruction) {
3561 switch (call_instruction->fn->id) {
3562 case BuiltinFnIdInvalid:
3563 zig_unreachable();
3564 case BuiltinFnIdMemcpy:
3565 case BuiltinFnIdMemset:
3566 case BuiltinFnIdAddWithOverflow:
3567 case BuiltinFnIdSubWithOverflow:
3568 case BuiltinFnIdMulWithOverflow:
3569 case BuiltinFnIdShlWithOverflow:
3570 case BuiltinFnIdCInclude:
3571 case BuiltinFnIdCDefine:
3572 case BuiltinFnIdCUndef:
3573 case BuiltinFnIdImport:
3574 case BuiltinFnIdCImport:
3575 case BuiltinFnIdBreakpoint:
3576 case BuiltinFnIdEmbedFile:
3577 case BuiltinFnIdCmpExchange:
3578 case BuiltinFnIdFence:
3579 case BuiltinFnIdUnreachable:
3580 case BuiltinFnIdSetFnTest:
3581 case BuiltinFnIdSetFnVisible:
3582 case BuiltinFnIdSetFnStaticEval:
3583 case BuiltinFnIdSetFnNoInline:
3584 case BuiltinFnIdSetDebugSafety:
3585 return true;
3586 case BuiltinFnIdSizeof:
3587 case BuiltinFnIdAlignof:
3588 case BuiltinFnIdMaxValue:
3589 case BuiltinFnIdMinValue:
3590 case BuiltinFnIdMemberCount:
3591 case BuiltinFnIdTypeof:
3592 case BuiltinFnIdCompileVar:
3593 case BuiltinFnIdCompileErr:
3594 case BuiltinFnIdConstEval:
3595 case BuiltinFnIdCtz:
3596 case BuiltinFnIdClz:
3597 case BuiltinFnIdErrName:
3598 case BuiltinFnIdReturnAddress:
3599 case BuiltinFnIdFrameAddress:
3600 case BuiltinFnIdDivExact:
3601 case BuiltinFnIdTruncate:
3602 case BuiltinFnIdIntType:
3603 return false;
3604 }
3605 zig_unreachable();
3606}
3607
3608bool ir_has_side_effects(IrInstruction *instruction) {
3609 switch (instruction->id) {
3610 case IrInstructionIdInvalid:
3611 zig_unreachable();
3612 case IrInstructionIdBr:
3613 case IrInstructionIdCondBr:
3614 case IrInstructionIdSwitchBr:
3615 case IrInstructionIdStoreVar:
3616 case IrInstructionIdCall:
3617 case IrInstructionIdReturn:
3618 case IrInstructionIdUnreachable:
3619 return true;
3620 case IrInstructionIdPhi:
3621 case IrInstructionIdUnOp:
3622 case IrInstructionIdBinOp:
3623 case IrInstructionIdLoadVar:
3624 case IrInstructionIdConst:
3625 case IrInstructionIdCast:
3626 case IrInstructionIdContainerInitList:
3627 case IrInstructionIdContainerInitFields:
3628 return false;
3629 case IrInstructionIdBuiltinCall:
3630 return ir_builtin_call_has_side_effects((IrInstructionBuiltinCall *)instruction);
3631 }
3632 zig_unreachable();
3633}
src/ir.hpp+2
......@@ -16,4 +16,6 @@ IrInstruction *ir_gen_fn(CodeGen *g, FnTableEntry *fn_entry);
1616TypeTableEntry *ir_analyze(CodeGen *g, IrExecutable *old_executable, IrExecutable *new_executable,
1717 TypeTableEntry *expected_type);
1818
19bool ir_has_side_effects(IrInstruction *instruction);
20
1921#endif
src/ir_print.cpp+105-55
......@@ -1,3 +1,4 @@
1#include "ir.hpp"
12#include "ir_print.hpp"
23
34struct IrPrint {
......@@ -14,49 +15,46 @@ static void ir_print_indent(IrPrint *irp) {
1415
1516static void ir_print_prefix(IrPrint *irp, IrInstruction *instruction) {
1617 ir_print_indent(irp);
17 fprintf(irp->f, "#%-3zu| ", instruction->debug_id);
18 const char *type_name = instruction->type_entry ? buf_ptr(&instruction->type_entry->name) : "(unknown)";
19 const char *ref_count = ir_has_side_effects(instruction) ?
20 "-" : buf_ptr(buf_sprintf("%zu", instruction->ref_count));
21 fprintf(irp->f, "#%-3zu| %-12s| %-2s| ", instruction->debug_id, type_name, ref_count);
1822}
1923
20static void ir_print_return(IrPrint *irp, IrInstructionReturn *return_instruction) {
21 ir_print_prefix(irp, &return_instruction->base);
22 assert(return_instruction->value);
23 fprintf(irp->f, "return #%zu\n", return_instruction->value->debug_id);
24}
25
26static void ir_print_const(IrPrint *irp, IrInstructionConst *const_instruction) {
27 ir_print_prefix(irp, &const_instruction->base);
28 TypeTableEntry *type_entry = const_instruction->base.type_entry;
29 fprintf(irp->f, "%s ", buf_ptr(&type_entry->name));
24static void ir_print_const_instruction(IrPrint *irp, IrInstruction *instruction) {
25 TypeTableEntry *type_entry = instruction->type_entry;
3026 switch (type_entry->id) {
3127 case TypeTableEntryIdInvalid:
3228 zig_unreachable();
3329 case TypeTableEntryIdVoid:
34 fprintf(irp->f, "%s\n", "void");
30 fprintf(irp->f, "{}");
3531 break;
3632 case TypeTableEntryIdNumLitFloat:
37 fprintf(irp->f, "%f\n", const_instruction->base.static_value.data.x_bignum.data.x_float);
33 fprintf(irp->f, "%f", instruction->static_value.data.x_bignum.data.x_float);
3834 break;
3935 case TypeTableEntryIdNumLitInt:
4036 {
41 BigNum *bignum = &const_instruction->base.static_value.data.x_bignum;
37 BigNum *bignum = &instruction->static_value.data.x_bignum;
4238 const char *negative_str = bignum->is_negative ? "-" : "";
43 fprintf(irp->f, "%s%llu\n", negative_str, bignum->data.x_uint);
39 fprintf(irp->f, "%s%llu", negative_str, bignum->data.x_uint);
4440 break;
4541 }
4642 case TypeTableEntryIdMetaType:
47 fprintf(irp->f, "%s\n", buf_ptr(&const_instruction->base.static_value.data.x_type->name));
43 fprintf(irp->f, "%s", buf_ptr(&instruction->static_value.data.x_type->name));
4844 break;
4945 case TypeTableEntryIdInt:
5046 {
51 BigNum *bignum = &const_instruction->base.static_value.data.x_bignum;
47 BigNum *bignum = &instruction->static_value.data.x_bignum;
5248 assert(bignum->kind == BigNumKindInt);
5349 const char *negative_str = bignum->is_negative ? "-" : "";
54 fprintf(irp->f, "%s%llu\n", negative_str, bignum->data.x_uint);
50 fprintf(irp->f, "%s%llu", negative_str, bignum->data.x_uint);
5551 }
5652 break;
53 case TypeTableEntryIdUnreachable:
54 fprintf(irp->f, "@unreachable()");
55 break;
5756 case TypeTableEntryIdVar:
5857 case TypeTableEntryIdBool:
59 case TypeTableEntryIdUnreachable:
6058 case TypeTableEntryIdFloat:
6159 case TypeTableEntryIdPointer:
6260 case TypeTableEntryIdArray:
......@@ -77,6 +75,27 @@ static void ir_print_const(IrPrint *irp, IrInstructionConst *const_instruction)
7775 }
7876}
7977
78static void ir_print_other_instruction(IrPrint *irp, IrInstruction *instruction) {
79 if (instruction->static_value.ok) {
80 ir_print_const_instruction(irp, instruction);
81 } else {
82 fprintf(irp->f, "#%zu", instruction->debug_id);
83 }
84}
85
86static void ir_print_other_block(IrPrint *irp, IrBasicBlock *bb) {
87 fprintf(irp->f, "$%s_%zu", bb->name_hint, bb->debug_id);
88}
89
90static void ir_print_return(IrPrint *irp, IrInstructionReturn *return_instruction) {
91 assert(return_instruction->value);
92 fprintf(irp->f, "return ");
93 ir_print_other_instruction(irp, return_instruction->value);
94}
95
96static void ir_print_const(IrPrint *irp, IrInstructionConst *const_instruction) {
97 ir_print_const_instruction(irp, &const_instruction->base);
98}
8099
81100static const char *ir_bin_op_id_str(IrBinOp op_id) {
82101 switch (op_id) {
......@@ -169,87 +188,108 @@ static const char *ir_un_op_id_str(IrUnOp op_id) {
169188}
170189
171190static void ir_print_un_op(IrPrint *irp, IrInstructionUnOp *un_op_instruction) {
172 ir_print_prefix(irp, &un_op_instruction->base);
173 fprintf(irp->f, "%s #%zu\n",
174 ir_un_op_id_str(un_op_instruction->op_id),
175 un_op_instruction->value->debug_id);
191 fprintf(irp->f, "%s ", ir_un_op_id_str(un_op_instruction->op_id));
192 ir_print_other_instruction(irp, un_op_instruction->value);
176193}
177194
178195static void ir_print_bin_op(IrPrint *irp, IrInstructionBinOp *bin_op_instruction) {
179 ir_print_prefix(irp, &bin_op_instruction->base);
180 fprintf(irp->f, "#%zu %s #%zu\n",
181 bin_op_instruction->op1->debug_id,
182 ir_bin_op_id_str(bin_op_instruction->op_id),
183 bin_op_instruction->op2->debug_id);
196 ir_print_other_instruction(irp, bin_op_instruction->op1);
197 fprintf(irp->f, " %s ", ir_bin_op_id_str(bin_op_instruction->op_id));
198 ir_print_other_instruction(irp, bin_op_instruction->op2);
184199}
185200
186201static void ir_print_load_var(IrPrint *irp, IrInstructionLoadVar *load_var_instruction) {
187 ir_print_prefix(irp, &load_var_instruction->base);
188 fprintf(irp->f, "%s\n",
189 buf_ptr(&load_var_instruction->var->name));
202 fprintf(irp->f, "%s", buf_ptr(&load_var_instruction->var->name));
190203}
191204
192205static void ir_print_cast(IrPrint *irp, IrInstructionCast *cast_instruction) {
193 ir_print_prefix(irp, &cast_instruction->base);
194 fprintf(irp->f, "cast #%zu to #%zu\n",
195 cast_instruction->value->debug_id,
196 cast_instruction->dest_type->debug_id);
206 fprintf(irp->f, "cast ");
207 ir_print_other_instruction(irp, cast_instruction->value);
208 fprintf(irp->f, " to ");
209 ir_print_other_instruction(irp, cast_instruction->dest_type);
197210}
198211
199212static void ir_print_call(IrPrint *irp, IrInstructionCall *call_instruction) {
200 ir_print_prefix(irp, &call_instruction->base);
201 fprintf(irp->f, "#%zu(", call_instruction->fn->debug_id);
213 ir_print_other_instruction(irp, call_instruction->fn);
214 fprintf(irp->f, "(");
202215 for (size_t i = 0; i < call_instruction->arg_count; i += 1) {
203216 IrInstruction *arg = call_instruction->args[i];
204217 if (i != 0)
205218 fprintf(irp->f, ", ");
206 fprintf(irp->f, "#%zu", arg->debug_id);
219 ir_print_other_instruction(irp, arg);
207220 }
208 fprintf(irp->f, ")\n");
221 fprintf(irp->f, ")");
209222}
210223
211224static void ir_print_builtin_call(IrPrint *irp, IrInstructionBuiltinCall *call_instruction) {
212 ir_print_prefix(irp, &call_instruction->base);
213225 fprintf(irp->f, "@%s(", buf_ptr(&call_instruction->fn->name));
214226 for (size_t i = 0; i < call_instruction->fn->param_count; i += 1) {
215227 IrInstruction *arg = call_instruction->args[i];
216228 if (i != 0)
217229 fprintf(irp->f, ", ");
218 fprintf(irp->f, "#%zu", arg->debug_id);
230 ir_print_other_instruction(irp, arg);
219231 }
220 fprintf(irp->f, ")\n");
232 fprintf(irp->f, ")");
221233}
222234
223235
224236static void ir_print_cond_br(IrPrint *irp, IrInstructionCondBr *cond_br_instruction) {
225 ir_print_prefix(irp, &cond_br_instruction->base);
226 fprintf(irp->f, "if #%zu then $%s_%zu else $%s_%zu\n",
227 cond_br_instruction->condition->debug_id,
228 cond_br_instruction->then_block->name_hint, cond_br_instruction->then_block->debug_id,
229 cond_br_instruction->else_block->name_hint, cond_br_instruction->else_block->debug_id);
237 fprintf(irp->f, "if (");
238 ir_print_other_instruction(irp, cond_br_instruction->condition);
239 fprintf(irp->f, ") ");
240 ir_print_other_block(irp, cond_br_instruction->then_block);
241 fprintf(irp->f, " else ");
242 ir_print_other_block(irp, cond_br_instruction->else_block);
230243}
231244
232245static void ir_print_br(IrPrint *irp, IrInstructionBr *br_instruction) {
233 ir_print_prefix(irp, &br_instruction->base);
234 fprintf(irp->f, "goto $%s_%zu\n",
235 br_instruction->dest_block->name_hint, br_instruction->dest_block->debug_id);
246 fprintf(irp->f, "goto ");
247 ir_print_other_block(irp, br_instruction->dest_block);
236248}
237249
238250static void ir_print_phi(IrPrint *irp, IrInstructionPhi *phi_instruction) {
239 ir_print_prefix(irp, &phi_instruction->base);
240251 for (size_t i = 0; i < phi_instruction->incoming_count; i += 1) {
241252 IrBasicBlock *incoming_block = phi_instruction->incoming_blocks[i];
242253 IrInstruction *incoming_value = phi_instruction->incoming_values[i];
243254 if (i != 0)
244255 fprintf(irp->f, " ");
245 fprintf(irp->f, "$%s_%zu:#%zu",
246 incoming_block->name_hint, incoming_block->debug_id,
247 incoming_value->debug_id);
256 ir_print_other_block(irp, incoming_block);
257 fprintf(irp->f, ":");
258 ir_print_other_instruction(irp, incoming_value);
248259 }
249 fprintf(irp->f, "\n");
260}
261
262static void ir_print_container_init_list(IrPrint *irp, IrInstructionContainerInitList *instruction) {
263 ir_print_other_instruction(irp, instruction->container_type);
264 fprintf(irp->f, "{");
265 for (size_t i = 0; i < instruction->item_count; i += 1) {
266 IrInstruction *item = instruction->items[i];
267 if (i != 0)
268 fprintf(irp->f, ", ");
269 ir_print_other_instruction(irp, item);
270 }
271 fprintf(irp->f, "}");
272}
273
274static void ir_print_container_init_fields(IrPrint *irp, IrInstructionContainerInitFields *instruction) {
275 ir_print_other_instruction(irp, instruction->container_type);
276 fprintf(irp->f, "{");
277 for (size_t i = 0; i < instruction->field_count; i += 1) {
278 Buf *name = instruction->field_names[i];
279 IrInstruction *field_value = instruction->field_values[i];
280 const char *comma = (i == 0) ? "" : ", ";
281 fprintf(irp->f, "%s.%s = ", comma, buf_ptr(name));
282 ir_print_other_instruction(irp, field_value);
283 }
284 fprintf(irp->f, "}");
285}
286
287static void ir_print_unreachable(IrPrint *irp, IrInstructionUnreachable *instruction) {
288 fprintf(irp->f, "unreachable");
250289}
251290
252291static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
292 ir_print_prefix(irp, instruction);
253293 switch (instruction->id) {
254294 case IrInstructionIdInvalid:
255295 zig_unreachable();
......@@ -286,10 +326,20 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
286326 case IrInstructionIdPhi:
287327 ir_print_phi(irp, (IrInstructionPhi *)instruction);
288328 break;
329 case IrInstructionIdContainerInitList:
330 ir_print_container_init_list(irp, (IrInstructionContainerInitList *)instruction);
331 break;
332 case IrInstructionIdContainerInitFields:
333 ir_print_container_init_fields(irp, (IrInstructionContainerInitFields *)instruction);
334 break;
335 case IrInstructionIdUnreachable:
336 ir_print_unreachable(irp, (IrInstructionUnreachable *)instruction);
337 break;
289338 case IrInstructionIdSwitchBr:
290339 case IrInstructionIdStoreVar:
291340 zig_panic("TODO print more IR instructions");
292341 }
342 fprintf(irp->f, "\n");
293343}
294344
295345void ir_print(FILE *f, IrExecutable *executable, int indent_size) {
src/parser.cpp+9-11
......@@ -1912,14 +1912,11 @@ static AstNode *ast_parse_label(ParseContext *pc, size_t *token_index, bool mand
19121912 return node;
19131913}
19141914
1915//static AstNode *ast_create_void_expr(ParseContext *pc, Token *token) {
1916// AstNode *node = ast_create_node(pc, NodeTypeContainerInitExpr, token);
1917// node->data.container_init_expr.type = ast_create_node(pc, NodeTypeSymbol, token);
1918// node->data.container_init_expr.kind = ContainerInitKindArray;
1919// node->data.container_init_expr.type->data.symbol_expr.symbol = pc->void_buf;
1920// normalize_parent_ptrs(node);
1921// return node;
1922//}
1915static AstNode *ast_create_void_expr(ParseContext *pc, Token *token) {
1916 AstNode *node = ast_create_node(pc, NodeTypeBlock, token);
1917 normalize_parent_ptrs(node);
1918 return node;
1919}
19231920
19241921/*
19251922Block : token(LBrace) list(option(Statement), token(Semicolon)) token(RBrace)
......@@ -1961,12 +1958,13 @@ static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mand
19611958 semicolon_expected = !statement_node;
19621959 if (!statement_node) {
19631960 statement_node = ast_parse_non_block_expr(pc, token_index, false);
1961 if (!statement_node) {
1962 statement_node = ast_create_void_expr(pc, last_token);
1963 }
19641964 }
19651965 }
19661966 }
1967 if (statement_node) {
1968 node->data.block.statements.append(statement_node);
1969 }
1967 node->data.block.statements.append(statement_node);
19701968
19711969 last_token = &pc->tokens->at(*token_index);
19721970 if (last_token->id == TokenIdRBrace) {