| ... | ... | @@ -1424,6 +1424,80 @@ static IrInstruction *ir_gen_assign_op(IrBuilder *irb, Scope *scope, AstNode *no |
| 1424 | 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 | 1501 | static IrInstruction *ir_gen_bin_op(IrBuilder *irb, Scope *scope, AstNode *node) { |
| 1428 | 1502 | assert(node->type == NodeTypeBinOpExpr); |
| 1429 | 1503 | |
| ... | ... | @@ -1466,10 +1540,9 @@ static IrInstruction *ir_gen_bin_op(IrBuilder *irb, Scope *scope, AstNode *node) |
| 1466 | 1540 | case BinOpTypeAssignBoolOr: |
| 1467 | 1541 | return ir_gen_assign_op(irb, scope, node, IrBinOpBoolOr); |
| 1468 | 1542 | case BinOpTypeBoolOr: |
| 1543 | return ir_gen_bool_or(irb, scope, node); |
| 1469 | 1544 | case BinOpTypeBoolAnd: |
| 1470 | | // note: this is not a direct mapping to IrBinOpBoolOr/And |
| 1471 | | // because of the control flow |
| 1472 | | zig_panic("TODO gen IR for bool or/and"); |
| 1545 | return ir_gen_bool_and(irb, scope, node); |
| 1473 | 1546 | case BinOpTypeCmpEq: |
| 1474 | 1547 | return ir_gen_bin_op_id(irb, scope, node, IrBinOpCmpEq); |
| 1475 | 1548 | case BinOpTypeCmpNotEq: |
| ... | ... | @@ -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 | 8339 | //static LLVMValueRef gen_assign_expr(CodeGen *g, AstNode *node) { |
| 8324 | 8340 | // assert(node->type == NodeTypeBinOpExpr); |
| 8325 | 8341 | // |