| ... | @@ -1424,6 +1424,80 @@ static IrInstruction *ir_gen_assign_op(IrBuilder *irb, Scope *scope, AstNode *no | ... | @@ -1424,6 +1424,80 @@ static IrInstruction *ir_gen_assign_op(IrBuilder *irb, Scope *scope, AstNode *no |
| 1424 | return ir_build_const_void(irb, scope, node); | 1424 | return ir_build_const_void(irb, scope, node); |
| 1425 | } | 1425 | } |
| 1426 | | 1426 | |
| | 1427 | static IrInstruction *ir_gen_bool_or(IrBuilder *irb, Scope *scope, AstNode *node) { |
| | 1428 | assert(node->type == NodeTypeBinOpExpr); |
| | 1429 | |
| | 1430 | bool is_inline = ir_should_inline(irb); |
| | 1431 | |
| | 1432 | IrInstruction *val1 = ir_gen_node(irb, node->data.bin_op_expr.op1, scope); |
| | 1433 | if (val1 == irb->codegen->invalid_instruction) |
| | 1434 | return irb->codegen->invalid_instruction; |
| | 1435 | IrBasicBlock *post_val1_block = irb->current_basic_block; |
| | 1436 | |
| | 1437 | // block for when val1 == false |
| | 1438 | IrBasicBlock *false_block = ir_build_basic_block(irb, "BoolOrFalse"); |
| | 1439 | // block for when val1 == true (don't even evaluate the second part) |
| | 1440 | IrBasicBlock *true_block = ir_build_basic_block(irb, "BoolOrTrue"); |
| | 1441 | |
| | 1442 | ir_build_cond_br(irb, scope, node, val1, true_block, false_block, is_inline); |
| | 1443 | |
| | 1444 | ir_set_cursor_at_end(irb, false_block); |
| | 1445 | IrInstruction *val2 = ir_gen_node(irb, node->data.bin_op_expr.op2, scope); |
| | 1446 | if (val2 == irb->codegen->invalid_instruction) |
| | 1447 | return irb->codegen->invalid_instruction; |
| | 1448 | IrBasicBlock *post_val2_block = irb->current_basic_block; |
| | 1449 | |
| | 1450 | ir_build_br(irb, scope, node, true_block, is_inline); |
| | 1451 | |
| | 1452 | ir_set_cursor_at_end(irb, true_block); |
| | 1453 | |
| | 1454 | IrInstruction **incoming_values = allocate<IrInstruction *>(2); |
| | 1455 | incoming_values[0] = val1; |
| | 1456 | incoming_values[1] = val2; |
| | 1457 | IrBasicBlock **incoming_blocks = allocate<IrBasicBlock *>(2); |
| | 1458 | incoming_blocks[0] = post_val1_block; |
| | 1459 | incoming_blocks[1] = post_val2_block; |
| | 1460 | |
| | 1461 | return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values); |
| | 1462 | } |
| | 1463 | |
| | 1464 | static IrInstruction *ir_gen_bool_and(IrBuilder *irb, Scope *scope, AstNode *node) { |
| | 1465 | assert(node->type == NodeTypeBinOpExpr); |
| | 1466 | |
| | 1467 | bool is_inline = ir_should_inline(irb); |
| | 1468 | |
| | 1469 | IrInstruction *val1 = ir_gen_node(irb, node->data.bin_op_expr.op1, scope); |
| | 1470 | if (val1 == irb->codegen->invalid_instruction) |
| | 1471 | return irb->codegen->invalid_instruction; |
| | 1472 | IrBasicBlock *post_val1_block = irb->current_basic_block; |
| | 1473 | |
| | 1474 | // block for when val1 == true |
| | 1475 | IrBasicBlock *true_block = ir_build_basic_block(irb, "BoolAndTrue"); |
| | 1476 | // block for when val1 == false (don't even evaluate the second part) |
| | 1477 | IrBasicBlock *false_block = ir_build_basic_block(irb, "BoolAndFalse"); |
| | 1478 | |
| | 1479 | ir_build_cond_br(irb, scope, node, val1, true_block, false_block, is_inline); |
| | 1480 | |
| | 1481 | ir_set_cursor_at_end(irb, true_block); |
| | 1482 | IrInstruction *val2 = ir_gen_node(irb, node->data.bin_op_expr.op2, scope); |
| | 1483 | if (val2 == irb->codegen->invalid_instruction) |
| | 1484 | return irb->codegen->invalid_instruction; |
| | 1485 | IrBasicBlock *post_val2_block = irb->current_basic_block; |
| | 1486 | |
| | 1487 | ir_build_br(irb, scope, node, false_block, is_inline); |
| | 1488 | |
| | 1489 | ir_set_cursor_at_end(irb, false_block); |
| | 1490 | |
| | 1491 | IrInstruction **incoming_values = allocate<IrInstruction *>(2); |
| | 1492 | incoming_values[0] = val1; |
| | 1493 | incoming_values[1] = val2; |
| | 1494 | IrBasicBlock **incoming_blocks = allocate<IrBasicBlock *>(2); |
| | 1495 | incoming_blocks[0] = post_val1_block; |
| | 1496 | incoming_blocks[1] = post_val2_block; |
| | 1497 | |
| | 1498 | return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values); |
| | 1499 | } |
| | 1500 | |
| 1427 | static IrInstruction *ir_gen_bin_op(IrBuilder *irb, Scope *scope, AstNode *node) { | 1501 | static IrInstruction *ir_gen_bin_op(IrBuilder *irb, Scope *scope, AstNode *node) { |
| 1428 | assert(node->type == NodeTypeBinOpExpr); | 1502 | assert(node->type == NodeTypeBinOpExpr); |
| 1429 | | 1503 | |
| ... | @@ -1466,10 +1540,9 @@ static IrInstruction *ir_gen_bin_op(IrBuilder *irb, Scope *scope, AstNode *node) | ... | @@ -1466,10 +1540,9 @@ static IrInstruction *ir_gen_bin_op(IrBuilder *irb, Scope *scope, AstNode *node) |
| 1466 | case BinOpTypeAssignBoolOr: | 1540 | case BinOpTypeAssignBoolOr: |
| 1467 | return ir_gen_assign_op(irb, scope, node, IrBinOpBoolOr); | 1541 | return ir_gen_assign_op(irb, scope, node, IrBinOpBoolOr); |
| 1468 | case BinOpTypeBoolOr: | 1542 | case BinOpTypeBoolOr: |
| | 1543 | return ir_gen_bool_or(irb, scope, node); |
| 1469 | case BinOpTypeBoolAnd: | 1544 | case BinOpTypeBoolAnd: |
| 1470 | // note: this is not a direct mapping to IrBinOpBoolOr/And | 1545 | return ir_gen_bool_and(irb, scope, node); |
| 1471 | // because of the control flow | | |
| 1472 | zig_panic("TODO gen IR for bool or/and"); | | |
| 1473 | case BinOpTypeCmpEq: | 1546 | case BinOpTypeCmpEq: |
| 1474 | return ir_gen_bin_op_id(irb, scope, node, IrBinOpCmpEq); | 1547 | return ir_gen_bin_op_id(irb, scope, node, IrBinOpCmpEq); |
| 1475 | case BinOpTypeCmpNotEq: | 1548 | case BinOpTypeCmpNotEq: |
| ... | @@ -8263,63 +8336,6 @@ bool ir_has_side_effects(IrInstruction *instruction) { | ... | @@ -8263,63 +8336,6 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 8263 | // | 8336 | // |
| 8264 | // | 8337 | // |
| 8265 | // | 8338 | // |
| 8266 | //static LLVMValueRef gen_bool_and_expr(CodeGen *g, AstNode *node) { | | |
| 8267 | // assert(node->type == NodeTypeBinOpExpr); | | |
| 8268 | // | | |
| 8269 | // LLVMValueRef val1 = gen_expr(g, node->data.bin_op_expr.op1); | | |
| 8270 | // LLVMBasicBlockRef post_val1_block = LLVMGetInsertBlock(g->builder); | | |
| 8271 | // | | |
| 8272 | // // block for when val1 == true | | |
| 8273 | // LLVMBasicBlockRef true_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "BoolAndTrue"); | | |
| 8274 | // // block for when val1 == false (don't even evaluate the second part) | | |
| 8275 | // LLVMBasicBlockRef false_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "BoolAndFalse"); | | |
| 8276 | // | | |
| 8277 | // LLVMBuildCondBr(g->builder, val1, true_block, false_block); | | |
| 8278 | // | | |
| 8279 | // LLVMPositionBuilderAtEnd(g->builder, true_block); | | |
| 8280 | // LLVMValueRef val2 = gen_expr(g, node->data.bin_op_expr.op2); | | |
| 8281 | // LLVMBasicBlockRef post_val2_block = LLVMGetInsertBlock(g->builder); | | |
| 8282 | // | | |
| 8283 | // LLVMBuildBr(g->builder, false_block); | | |
| 8284 | // | | |
| 8285 | // LLVMPositionBuilderAtEnd(g->builder, false_block); | | |
| 8286 | // LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMInt1Type(), ""); | | |
| 8287 | // LLVMValueRef incoming_values[2] = {val1, val2}; | | |
| 8288 | // LLVMBasicBlockRef incoming_blocks[2] = {post_val1_block, post_val2_block}; | | |
| 8289 | // LLVMAddIncoming(phi, incoming_values, incoming_blocks, 2); | | |
| 8290 | // | | |
| 8291 | // return phi; | | |
| 8292 | //} | | |
| 8293 | // | | |
| 8294 | //static LLVMValueRef gen_bool_or_expr(CodeGen *g, AstNode *expr_node) { | | |
| 8295 | // assert(expr_node->type == NodeTypeBinOpExpr); | | |
| 8296 | // | | |
| 8297 | // LLVMValueRef val1 = gen_expr(g, expr_node->data.bin_op_expr.op1); | | |
| 8298 | // LLVMBasicBlockRef post_val1_block = LLVMGetInsertBlock(g->builder); | | |
| 8299 | // | | |
| 8300 | // // block for when val1 == false | | |
| 8301 | // LLVMBasicBlockRef false_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "BoolOrFalse"); | | |
| 8302 | // // block for when val1 == true (don't even evaluate the second part) | | |
| 8303 | // LLVMBasicBlockRef true_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "BoolOrTrue"); | | |
| 8304 | // | | |
| 8305 | // LLVMBuildCondBr(g->builder, val1, true_block, false_block); | | |
| 8306 | // | | |
| 8307 | // LLVMPositionBuilderAtEnd(g->builder, false_block); | | |
| 8308 | // LLVMValueRef val2 = gen_expr(g, expr_node->data.bin_op_expr.op2); | | |
| 8309 | // | | |
| 8310 | // LLVMBasicBlockRef post_val2_block = LLVMGetInsertBlock(g->builder); | | |
| 8311 | // | | |
| 8312 | // LLVMBuildBr(g->builder, true_block); | | |
| 8313 | // | | |
| 8314 | // LLVMPositionBuilderAtEnd(g->builder, true_block); | | |
| 8315 | // LLVMValueRef phi = LLVMBuildPhi(g->builder, LLVMInt1Type(), ""); | | |
| 8316 | // LLVMValueRef incoming_values[2] = {val1, val2}; | | |
| 8317 | // LLVMBasicBlockRef incoming_blocks[2] = {post_val1_block, post_val2_block}; | | |
| 8318 | // LLVMAddIncoming(phi, incoming_values, incoming_blocks, 2); | | |
| 8319 | // | | |
| 8320 | // return phi; | | |
| 8321 | //} | | |
| 8322 | // | | |
| 8323 | //static LLVMValueRef gen_assign_expr(CodeGen *g, AstNode *node) { | 8339 | //static LLVMValueRef gen_assign_expr(CodeGen *g, AstNode *node) { |
| 8324 | // assert(node->type == NodeTypeBinOpExpr); | 8340 | // assert(node->type == NodeTypeBinOpExpr); |
| 8325 | // | 8341 | // |