| ... | @@ -2194,6 +2194,48 @@ static IrInstruction *ir_gen_bool_and(IrBuilder *irb, Scope *scope, AstNode *nod | ... | @@ -2194,6 +2194,48 @@ static IrInstruction *ir_gen_bool_and(IrBuilder *irb, Scope *scope, AstNode *nod |
| 2194 | return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values); | 2194 | return ir_build_phi(irb, scope, node, 2, incoming_blocks, incoming_values); |
| 2195 | } | 2195 | } |
| 2196 | | 2196 | |
| | 2197 | static IrInstruction *ir_gen_maybe_ok_or(IrBuilder *irb, Scope *parent_scope, AstNode *node) { |
| | 2198 | assert(node->type == NodeTypeBinOpExpr); |
| | 2199 | |
| | 2200 | AstNode *op1_node = node->data.bin_op_expr.op1; |
| | 2201 | AstNode *op2_node = node->data.bin_op_expr.op2; |
| | 2202 | |
| | 2203 | bool is_inline = ir_should_inline(irb); |
| | 2204 | |
| | 2205 | IrInstruction *maybe_ptr = ir_gen_node_extra(irb, op1_node, parent_scope, LValPurposeAddressOf); |
| | 2206 | if (maybe_ptr == irb->codegen->invalid_instruction) |
| | 2207 | return irb->codegen->invalid_instruction; |
| | 2208 | |
| | 2209 | IrInstruction *is_non_null = ir_build_test_null(irb, parent_scope, node, maybe_ptr); |
| | 2210 | |
| | 2211 | IrBasicBlock *ok_block = ir_build_basic_block(irb, parent_scope, "MaybeNonNull"); |
| | 2212 | IrBasicBlock *null_block = ir_build_basic_block(irb, parent_scope, "MaybeNull"); |
| | 2213 | IrBasicBlock *end_block = ir_build_basic_block(irb, parent_scope, "MaybeEnd"); |
| | 2214 | ir_build_cond_br(irb, parent_scope, node, is_non_null, ok_block, null_block, is_inline); |
| | 2215 | |
| | 2216 | ir_set_cursor_at_end(irb, null_block); |
| | 2217 | IrInstruction *null_result = ir_gen_node(irb, op2_node, parent_scope); |
| | 2218 | if (null_result == irb->codegen->invalid_instruction) |
| | 2219 | return irb->codegen->invalid_instruction; |
| | 2220 | IrBasicBlock *after_null_block = irb->current_basic_block; |
| | 2221 | ir_build_br(irb, parent_scope, node, end_block, is_inline); |
| | 2222 | |
| | 2223 | ir_set_cursor_at_end(irb, ok_block); |
| | 2224 | IrInstruction *unwrapped_ptr = ir_build_unwrap_maybe(irb, parent_scope, node, maybe_ptr, false); |
| | 2225 | IrInstruction *unwrapped_payload = ir_build_load_ptr(irb, parent_scope, node, unwrapped_ptr); |
| | 2226 | IrBasicBlock *after_ok_block = irb->current_basic_block; |
| | 2227 | ir_build_br(irb, parent_scope, node, end_block, is_inline); |
| | 2228 | |
| | 2229 | ir_set_cursor_at_end(irb, end_block); |
| | 2230 | IrInstruction **incoming_values = allocate<IrInstruction *>(2); |
| | 2231 | incoming_values[0] = null_result; |
| | 2232 | incoming_values[1] = unwrapped_payload; |
| | 2233 | IrBasicBlock **incoming_blocks = allocate<IrBasicBlock *>(2); |
| | 2234 | incoming_blocks[0] = after_null_block; |
| | 2235 | incoming_blocks[1] = after_ok_block; |
| | 2236 | return ir_build_phi(irb, parent_scope, node, 2, incoming_blocks, incoming_values); |
| | 2237 | } |
| | 2238 | |
| 2197 | static IrInstruction *ir_gen_bin_op(IrBuilder *irb, Scope *scope, AstNode *node) { | 2239 | static IrInstruction *ir_gen_bin_op(IrBuilder *irb, Scope *scope, AstNode *node) { |
| 2198 | assert(node->type == NodeTypeBinOpExpr); | 2240 | assert(node->type == NodeTypeBinOpExpr); |
| 2199 | | 2241 | |
| ... | @@ -2284,7 +2326,7 @@ static IrInstruction *ir_gen_bin_op(IrBuilder *irb, Scope *scope, AstNode *node) | ... | @@ -2284,7 +2326,7 @@ static IrInstruction *ir_gen_bin_op(IrBuilder *irb, Scope *scope, AstNode *node) |
| 2284 | case BinOpTypeArrayMult: | 2326 | case BinOpTypeArrayMult: |
| 2285 | return ir_gen_bin_op_id(irb, scope, node, IrBinOpArrayMult); | 2327 | return ir_gen_bin_op_id(irb, scope, node, IrBinOpArrayMult); |
| 2286 | case BinOpTypeUnwrapMaybe: | 2328 | case BinOpTypeUnwrapMaybe: |
| 2287 | zig_panic("TODO gen IR for unwrap maybe binary operation"); | 2329 | return ir_gen_maybe_ok_or(irb, scope, node); |
| 2288 | } | 2330 | } |
| 2289 | zig_unreachable(); | 2331 | zig_unreachable(); |
| 2290 | } | 2332 | } |