diff options
| author | Andrew Kelley <superjoe30@gmail.com> | 2016-11-21 03:08:24 -0500 |
|---|---|---|
| committer | Andrew Kelley <superjoe30@gmail.com> | 2016-11-21 03:08:24 -0500 |
| commit | 71d95c6597bbca6ef44ba8a2a401c28c19a32bbb (patch) | |
| tree | 01285870db232a793bb25ffbce594515d653fa6f /src/codegen.cpp | |
| parent | b47e2fa0604a5c785d9ed7d16c8086ecf99357f7 (diff) | |
| download | zig-71d95c6597bbca6ef44ba8a2a401c28c19a32bbb.tar.gz zig-71d95c6597bbca6ef44ba8a2a401c28c19a32bbb.zip | |
IR: support unwrap maybe operation
Diffstat (limited to 'src/codegen.cpp')
| -rw-r--r-- | src/codegen.cpp | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/src/codegen.cpp b/src/codegen.cpp index 6ed09db852..661bf8183f 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -1427,7 +1427,56 @@ static LLVMValueRef ir_render_asm(CodeGen *g, IrExecutable *executable, IrInstru return LLVMBuildCall(g->builder, asm_fn, param_values, input_and_output_count, ""); } +// 0 - null, 1 - non null +static LLVMValueRef gen_null_bit(CodeGen *g, TypeTableEntry *ptr_type, LLVMValueRef maybe_ptr) { + assert(ptr_type->id == TypeTableEntryIdPointer); + TypeTableEntry *maybe_type = ptr_type->data.pointer.child_type; + assert(maybe_type->id == TypeTableEntryIdMaybe); + TypeTableEntry *child_type = maybe_type->data.maybe.child_type; + LLVMValueRef maybe_struct_ref = get_handle_value(g, maybe_ptr, maybe_type); + bool maybe_is_ptr = (child_type->id == TypeTableEntryIdPointer || child_type->id == TypeTableEntryIdFn); + if (maybe_is_ptr) { + return LLVMBuildICmp(g->builder, LLVMIntNE, maybe_struct_ref, LLVMConstNull(child_type->type_ref), ""); + } else { + LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, maybe_struct_ref, maybe_null_index, ""); + return LLVMBuildLoad(g->builder, maybe_field_ptr, ""); + } +} + +static LLVMValueRef ir_render_test_null(CodeGen *g, IrExecutable *executable, IrInstructionTestNull *instruction) { + TypeTableEntry *ptr_type = instruction->value->type_entry; + assert(ptr_type->id == TypeTableEntryIdPointer); + return gen_null_bit(g, ptr_type, ir_llvm_value(g, instruction->value)); +} + +static LLVMValueRef ir_render_unwrap_maybe(CodeGen *g, IrExecutable *executable, + IrInstructionUnwrapMaybe *instruction) +{ + TypeTableEntry *ptr_type = instruction->value->type_entry; + assert(ptr_type->id == TypeTableEntryIdPointer); + TypeTableEntry *maybe_type = ptr_type->data.pointer.child_type; + assert(maybe_type->id == TypeTableEntryIdMaybe); + TypeTableEntry *child_type = maybe_type->data.maybe.child_type; + bool maybe_is_ptr = (child_type->id == TypeTableEntryIdPointer || child_type->id == TypeTableEntryIdFn); + LLVMValueRef maybe_ptr = ir_llvm_value(g, instruction->value); + if (ir_want_debug_safety(g, &instruction->base) && instruction->safety_check_on) { + LLVMValueRef nonnull_bit = gen_null_bit(g, ptr_type, maybe_ptr); + LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "UnwrapMaybeOk"); + LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "UnwrapMaybeFail"); + LLVMBuildCondBr(g->builder, nonnull_bit, ok_block, fail_block); + LLVMPositionBuilderAtEnd(g->builder, fail_block); + gen_debug_safety_crash(g); + + LLVMPositionBuilderAtEnd(g->builder, ok_block); + } + if (maybe_is_ptr) { + return maybe_ptr; + } else { + LLVMValueRef maybe_struct_ref = get_handle_value(g, maybe_ptr, maybe_type); + return LLVMBuildStructGEP(g->builder, maybe_struct_ref, maybe_child_index, ""); + } +} static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, IrInstruction *instruction) { set_debug_source_node(g, instruction->source_node); @@ -1476,6 +1525,10 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, return ir_render_struct_field_ptr(g, executable, (IrInstructionStructFieldPtr *)instruction); case IrInstructionIdAsm: return ir_render_asm(g, executable, (IrInstructionAsm *)instruction); + case IrInstructionIdTestNull: + return ir_render_test_null(g, executable, (IrInstructionTestNull *)instruction); + case IrInstructionIdUnwrapMaybe: + return ir_render_unwrap_maybe(g, executable, (IrInstructionUnwrapMaybe *)instruction); case IrInstructionIdSwitchBr: case IrInstructionIdPhi: case IrInstructionIdContainerInitList: |
