| ... | @@ -218,6 +218,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionAsm *) { | ... | @@ -218,6 +218,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionAsm *) { |
| 218 | return IrInstructionIdAsm; | 218 | return IrInstructionIdAsm; |
| 219 | } | 219 | } |
| 220 | | 220 | |
| | 221 | static constexpr IrInstructionId ir_instruction_id(IrInstructionCompileVar *) { |
| | 222 | return IrInstructionIdCompileVar; |
| | 223 | } |
| | 224 | |
| 221 | template<typename T> | 225 | template<typename T> |
| 222 | static T *ir_create_instruction(IrExecutable *exec, AstNode *source_node) { | 226 | static T *ir_create_instruction(IrExecutable *exec, AstNode *source_node) { |
| 223 | T *special_instruction = allocate<T>(1); | 227 | T *special_instruction = allocate<T>(1); |
| ... | @@ -507,14 +511,6 @@ static IrInstruction *ir_build_field_ptr(IrBuilder *irb, AstNode *source_node, | ... | @@ -507,14 +511,6 @@ static IrInstruction *ir_build_field_ptr(IrBuilder *irb, AstNode *source_node, |
| 507 | return &instruction->base; | 511 | return &instruction->base; |
| 508 | } | 512 | } |
| 509 | | 513 | |
| 510 | //static IrInstruction *ir_build_field_ptr_from(IrBuilder *irb, IrInstruction *old_instruction, | | |
| 511 | // IrInstruction *container_ptr, Buf *field_name) | | |
| 512 | //{ | | |
| 513 | // IrInstruction *new_instruction = ir_build_field_ptr(irb, old_instruction->source_node, container_ptr, field_name); | | |
| 514 | // ir_link_new_instruction(new_instruction, old_instruction); | | |
| 515 | // return new_instruction; | | |
| 516 | //} | | |
| 517 | | | |
| 518 | static IrInstruction *ir_build_read_field(IrBuilder *irb, AstNode *source_node, | 514 | static IrInstruction *ir_build_read_field(IrBuilder *irb, AstNode *source_node, |
| 519 | IrInstruction *container_ptr, Buf *field_name) | 515 | IrInstruction *container_ptr, Buf *field_name) |
| 520 | { | 516 | { |
| ... | @@ -527,14 +523,6 @@ static IrInstruction *ir_build_read_field(IrBuilder *irb, AstNode *source_node, | ... | @@ -527,14 +523,6 @@ static IrInstruction *ir_build_read_field(IrBuilder *irb, AstNode *source_node, |
| 527 | return &instruction->base; | 523 | return &instruction->base; |
| 528 | } | 524 | } |
| 529 | | 525 | |
| 530 | //static IrInstruction *ir_build_read_field_from(IrBuilder *irb, IrInstruction *old_instruction, | | |
| 531 | // IrInstruction *container_ptr, Buf *field_name) | | |
| 532 | //{ | | |
| 533 | // IrInstruction *new_instruction = ir_build_read_field(irb, old_instruction->source_node, container_ptr, field_name); | | |
| 534 | // ir_link_new_instruction(new_instruction, old_instruction); | | |
| 535 | // return new_instruction; | | |
| 536 | //} | | |
| 537 | | | |
| 538 | static IrInstruction *ir_build_struct_field_ptr(IrBuilder *irb, AstNode *source_node, | 526 | static IrInstruction *ir_build_struct_field_ptr(IrBuilder *irb, AstNode *source_node, |
| 539 | IrInstruction *struct_ptr, TypeStructField *field) | 527 | IrInstruction *struct_ptr, TypeStructField *field) |
| 540 | { | 528 | { |
| ... | @@ -861,6 +849,15 @@ static IrInstruction *ir_build_asm_from(IrBuilder *irb, IrInstruction *old_instr | ... | @@ -861,6 +849,15 @@ static IrInstruction *ir_build_asm_from(IrBuilder *irb, IrInstruction *old_instr |
| 861 | return new_instruction; | 849 | return new_instruction; |
| 862 | } | 850 | } |
| 863 | | 851 | |
| | 852 | static IrInstruction *ir_build_compile_var(IrBuilder *irb, AstNode *source_node, IrInstruction *name) { |
| | 853 | IrInstructionCompileVar *instruction = ir_build_instruction<IrInstructionCompileVar>(irb, source_node); |
| | 854 | instruction->name = name; |
| | 855 | |
| | 856 | ir_ref_instruction(name); |
| | 857 | |
| | 858 | return &instruction->base; |
| | 859 | } |
| | 860 | |
| 864 | static void ir_gen_defers_for_block(IrBuilder *irb, BlockContext *inner_block, BlockContext *outer_block, | 861 | static void ir_gen_defers_for_block(IrBuilder *irb, BlockContext *inner_block, BlockContext *outer_block, |
| 865 | bool gen_error_defers, bool gen_maybe_defers) | 862 | bool gen_error_defers, bool gen_maybe_defers) |
| 866 | { | 863 | { |
| ... | @@ -1336,6 +1333,15 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, AstNode *node) { | ... | @@ -1336,6 +1333,15 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, AstNode *node) { |
| 1336 | | 1333 | |
| 1337 | return ir_build_set_debug_safety(irb, node, arg0_value, arg1_value); | 1334 | return ir_build_set_debug_safety(irb, node, arg0_value, arg1_value); |
| 1338 | } | 1335 | } |
| | 1336 | case BuiltinFnIdCompileVar: |
| | 1337 | { |
| | 1338 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); |
| | 1339 | IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, node->block_context); |
| | 1340 | if (arg0_value == irb->codegen->invalid_instruction) |
| | 1341 | return arg0_value; |
| | 1342 | |
| | 1343 | return ir_build_compile_var(irb, node, arg0_value); |
| | 1344 | } |
| 1339 | case BuiltinFnIdMemcpy: | 1345 | case BuiltinFnIdMemcpy: |
| 1340 | case BuiltinFnIdMemset: | 1346 | case BuiltinFnIdMemset: |
| 1341 | case BuiltinFnIdSizeof: | 1347 | case BuiltinFnIdSizeof: |
| ... | @@ -1350,7 +1356,6 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, AstNode *node) { | ... | @@ -1350,7 +1356,6 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, AstNode *node) { |
| 1350 | case BuiltinFnIdCInclude: | 1356 | case BuiltinFnIdCInclude: |
| 1351 | case BuiltinFnIdCDefine: | 1357 | case BuiltinFnIdCDefine: |
| 1352 | case BuiltinFnIdCUndef: | 1358 | case BuiltinFnIdCUndef: |
| 1353 | case BuiltinFnIdCompileVar: | | |
| 1354 | case BuiltinFnIdCompileErr: | 1359 | case BuiltinFnIdCompileErr: |
| 1355 | case BuiltinFnIdConstEval: | 1360 | case BuiltinFnIdConstEval: |
| 1356 | case BuiltinFnIdCtz: | 1361 | case BuiltinFnIdCtz: |
| ... | @@ -1410,14 +1415,15 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, AstNode *node) { | ... | @@ -1410,14 +1415,15 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, AstNode *node) { |
| 1410 | IrBasicBlock *else_block = ir_build_basic_block(irb, "Else"); | 1415 | IrBasicBlock *else_block = ir_build_basic_block(irb, "Else"); |
| 1411 | IrBasicBlock *endif_block = ir_build_basic_block(irb, "EndIf"); | 1416 | IrBasicBlock *endif_block = ir_build_basic_block(irb, "EndIf"); |
| 1412 | | 1417 | |
| 1413 | ir_build_cond_br(irb, condition->source_node, condition, then_block, else_block, false); | 1418 | bool is_inline = (node->block_context->fn_entry == nullptr); |
| | 1419 | ir_build_cond_br(irb, condition->source_node, condition, then_block, else_block, is_inline); |
| 1414 | | 1420 | |
| 1415 | ir_set_cursor_at_end(irb, then_block); | 1421 | ir_set_cursor_at_end(irb, then_block); |
| 1416 | IrInstruction *then_expr_result = ir_gen_node(irb, then_node, node->block_context); | 1422 | IrInstruction *then_expr_result = ir_gen_node(irb, then_node, node->block_context); |
| 1417 | if (then_expr_result == irb->codegen->invalid_instruction) | 1423 | if (then_expr_result == irb->codegen->invalid_instruction) |
| 1418 | return then_expr_result; | 1424 | return then_expr_result; |
| 1419 | IrBasicBlock *after_then_block = irb->current_basic_block; | 1425 | IrBasicBlock *after_then_block = irb->current_basic_block; |
| 1420 | ir_build_br(irb, node, endif_block, false); | 1426 | ir_build_br(irb, node, endif_block, is_inline); |
| 1421 | | 1427 | |
| 1422 | ir_set_cursor_at_end(irb, else_block); | 1428 | ir_set_cursor_at_end(irb, else_block); |
| 1423 | IrInstruction *else_expr_result; | 1429 | IrInstruction *else_expr_result; |
| ... | @@ -1429,7 +1435,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, AstNode *node) { | ... | @@ -1429,7 +1435,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, AstNode *node) { |
| 1429 | else_expr_result = ir_build_const_void(irb, node); | 1435 | else_expr_result = ir_build_const_void(irb, node); |
| 1430 | } | 1436 | } |
| 1431 | IrBasicBlock *after_else_block = irb->current_basic_block; | 1437 | IrBasicBlock *after_else_block = irb->current_basic_block; |
| 1432 | ir_build_br(irb, node, endif_block, false); | 1438 | ir_build_br(irb, node, endif_block, is_inline); |
| 1433 | | 1439 | |
| 1434 | ir_set_cursor_at_end(irb, endif_block); | 1440 | ir_set_cursor_at_end(irb, endif_block); |
| 1435 | IrInstruction **incoming_values = allocate<IrInstruction *>(2); | 1441 | IrInstruction **incoming_values = allocate<IrInstruction *>(2); |
| ... | @@ -2281,7 +2287,19 @@ static TypeTableEntry *ir_analyze_const_usize(IrAnalyze *ira, IrInstruction *ins | ... | @@ -2281,7 +2287,19 @@ static TypeTableEntry *ir_analyze_const_usize(IrAnalyze *ira, IrInstruction *ins |
| 2281 | return ira->codegen->builtin_types.entry_usize; | 2287 | return ira->codegen->builtin_types.entry_usize; |
| 2282 | } | 2288 | } |
| 2283 | | 2289 | |
| 2284 | static TypeTableEntry *ir_resolve_type(IrAnalyze *ira, IrInstruction *type_value) { | 2290 | static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value) { |
| | 2291 | if (value->static_value.special != ConstValSpecialStatic) { |
| | 2292 | add_node_error(ira->codegen, value->source_node, |
| | 2293 | buf_sprintf("unable to evaluate constant expression")); |
| | 2294 | return nullptr; |
| | 2295 | } |
| | 2296 | return &value->static_value; |
| | 2297 | } |
| | 2298 | |
| | 2299 | static TypeTableEntry *ir_resolve_type_lval(IrAnalyze *ira, IrInstruction *type_value, LValPurpose lval) { |
| | 2300 | if (lval != LValPurposeNone) |
| | 2301 | zig_panic("TODO"); |
| | 2302 | |
| 2285 | if (type_value == ira->codegen->invalid_instruction) | 2303 | if (type_value == ira->codegen->invalid_instruction) |
| 2286 | return ira->codegen->builtin_types.entry_invalid; | 2304 | return ira->codegen->builtin_types.entry_invalid; |
| 2287 | | 2305 | |
| ... | @@ -2294,44 +2312,15 @@ static TypeTableEntry *ir_resolve_type(IrAnalyze *ira, IrInstruction *type_value | ... | @@ -2294,44 +2312,15 @@ static TypeTableEntry *ir_resolve_type(IrAnalyze *ira, IrInstruction *type_value |
| 2294 | return ira->codegen->builtin_types.entry_invalid; | 2312 | return ira->codegen->builtin_types.entry_invalid; |
| 2295 | } | 2313 | } |
| 2296 | | 2314 | |
| 2297 | ConstExprValue *const_val = &type_value->static_value; | 2315 | ConstExprValue *const_val = ir_resolve_const(ira, type_value); |
| 2298 | if (const_val->special == ConstValSpecialRuntime) { | 2316 | if (!const_val) |
| 2299 | add_node_error(ira->codegen, type_value->source_node, | | |
| 2300 | buf_sprintf("unable to evaluate constant expression")); | | |
| 2301 | return ira->codegen->builtin_types.entry_invalid; | 2317 | return ira->codegen->builtin_types.entry_invalid; |
| 2302 | } | | |
| 2303 | | 2318 | |
| 2304 | return const_val->data.x_type; | 2319 | return const_val->data.x_type; |
| 2305 | } | 2320 | } |
| 2306 | | 2321 | |
| 2307 | static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value) { | 2322 | static TypeTableEntry *ir_resolve_type(IrAnalyze *ira, IrInstruction *type_value) { |
| 2308 | if (value->static_value.special != ConstValSpecialStatic) { | 2323 | return ir_resolve_type_lval(ira, type_value, LValPurposeNone); |
| 2309 | add_node_error(ira->codegen, value->source_node, | | |
| 2310 | buf_sprintf("unable to evaluate constant expression")); | | |
| 2311 | return nullptr; | | |
| 2312 | } | | |
| 2313 | return &value->static_value; | | |
| 2314 | } | | |
| 2315 | | | |
| 2316 | static bool ir_resolve_bool(IrAnalyze *ira, IrInstruction *bool_value, bool *out) { | | |
| 2317 | if (bool_value == ira->codegen->invalid_instruction) | | |
| 2318 | return false; | | |
| 2319 | | | |
| 2320 | if (bool_value->type_entry->id == TypeTableEntryIdInvalid) | | |
| 2321 | return false; | | |
| 2322 | | | |
| 2323 | if (bool_value->type_entry->id != TypeTableEntryIdBool) { | | |
| 2324 | add_node_error(ira->codegen, bool_value->source_node, | | |
| 2325 | buf_sprintf("expected type 'bool', found '%s'", buf_ptr(&bool_value->type_entry->name))); | | |
| 2326 | return false; | | |
| 2327 | } | | |
| 2328 | | | |
| 2329 | ConstExprValue *const_val = ir_resolve_const(ira, bool_value); | | |
| 2330 | if (!const_val) | | |
| 2331 | return false; | | |
| 2332 | | | |
| 2333 | *out = const_val->data.x_bool; | | |
| 2334 | return true; | | |
| 2335 | } | 2324 | } |
| 2336 | | 2325 | |
| 2337 | static FnTableEntry *ir_resolve_fn(IrAnalyze *ira, IrInstruction *fn_value) { | 2326 | static FnTableEntry *ir_resolve_fn(IrAnalyze *ira, IrInstruction *fn_value) { |
| ... | @@ -2347,12 +2336,9 @@ static FnTableEntry *ir_resolve_fn(IrAnalyze *ira, IrInstruction *fn_value) { | ... | @@ -2347,12 +2336,9 @@ static FnTableEntry *ir_resolve_fn(IrAnalyze *ira, IrInstruction *fn_value) { |
| 2347 | return nullptr; | 2336 | return nullptr; |
| 2348 | } | 2337 | } |
| 2349 | | 2338 | |
| 2350 | ConstExprValue *const_val = &fn_value->static_value; | 2339 | ConstExprValue *const_val = ir_resolve_const(ira, fn_value); |
| 2351 | if (const_val->special == ConstValSpecialRuntime) { | 2340 | if (!const_val) |
| 2352 | add_node_error(ira->codegen, fn_value->source_node, | | |
| 2353 | buf_sprintf("unable to evaluate constant expression")); | | |
| 2354 | return nullptr; | 2341 | return nullptr; |
| 2355 | } | | |
| 2356 | | 2342 | |
| 2357 | return const_val->data.x_fn; | 2343 | return const_val->data.x_fn; |
| 2358 | } | 2344 | } |
| ... | @@ -2654,6 +2640,69 @@ static IrInstruction *ir_get_casted_value(IrAnalyze *ira, IrInstruction *value, | ... | @@ -2654,6 +2640,69 @@ static IrInstruction *ir_get_casted_value(IrAnalyze *ira, IrInstruction *value, |
| 2654 | zig_unreachable(); | 2640 | zig_unreachable(); |
| 2655 | } | 2641 | } |
| 2656 | | 2642 | |
| | 2643 | static bool ir_resolve_usize(IrAnalyze *ira, IrInstruction *value, uint64_t *out) { |
| | 2644 | if (value->type_entry->id == TypeTableEntryIdInvalid) |
| | 2645 | return false; |
| | 2646 | |
| | 2647 | IrInstruction *casted_value = ir_get_casted_value(ira, value, ira->codegen->builtin_types.entry_usize); |
| | 2648 | if (casted_value->type_entry->id == TypeTableEntryIdInvalid) |
| | 2649 | return false; |
| | 2650 | |
| | 2651 | ConstExprValue *const_val = ir_resolve_const(ira, casted_value); |
| | 2652 | if (!const_val) |
| | 2653 | return false; |
| | 2654 | |
| | 2655 | *out = const_val->data.x_bignum.data.x_uint; |
| | 2656 | return true; |
| | 2657 | } |
| | 2658 | |
| | 2659 | static bool ir_resolve_bool(IrAnalyze *ira, IrInstruction *value, bool *out) { |
| | 2660 | if (value->type_entry->id == TypeTableEntryIdInvalid) |
| | 2661 | return false; |
| | 2662 | |
| | 2663 | IrInstruction *casted_value = ir_get_casted_value(ira, value, ira->codegen->builtin_types.entry_bool); |
| | 2664 | if (casted_value->type_entry->id == TypeTableEntryIdInvalid) |
| | 2665 | return false; |
| | 2666 | |
| | 2667 | ConstExprValue *const_val = ir_resolve_const(ira, casted_value); |
| | 2668 | if (!const_val) |
| | 2669 | return false; |
| | 2670 | |
| | 2671 | *out = const_val->data.x_bool; |
| | 2672 | return true; |
| | 2673 | } |
| | 2674 | |
| | 2675 | static Buf *ir_resolve_str(IrAnalyze *ira, IrInstruction *value) { |
| | 2676 | if (value->type_entry->id == TypeTableEntryIdInvalid) |
| | 2677 | return nullptr; |
| | 2678 | |
| | 2679 | TypeTableEntry *str_type = get_slice_type(ira->codegen, ira->codegen->builtin_types.entry_u8, true); |
| | 2680 | IrInstruction *casted_value = ir_get_casted_value(ira, value, str_type); |
| | 2681 | if (casted_value->type_entry->id == TypeTableEntryIdInvalid) |
| | 2682 | return nullptr; |
| | 2683 | |
| | 2684 | ConstExprValue *const_val = ir_resolve_const(ira, casted_value); |
| | 2685 | if (!const_val) |
| | 2686 | return nullptr; |
| | 2687 | |
| | 2688 | ConstExprValue *ptr_field = &const_val->data.x_struct.fields[slice_ptr_index]; |
| | 2689 | ConstExprValue *len_field = &const_val->data.x_struct.fields[slice_len_index]; |
| | 2690 | ConstExprValue *array_val = ptr_field->data.x_ptr.base_ptr; |
| | 2691 | assert(ptr_field->data.x_ptr.index != SIZE_MAX); |
| | 2692 | size_t len = len_field->data.x_bignum.data.x_uint; |
| | 2693 | Buf *result = buf_alloc(); |
| | 2694 | buf_resize(result, len); |
| | 2695 | for (size_t i = 0; i < len; i += 1) { |
| | 2696 | size_t new_index = ptr_field->data.x_ptr.index + i; |
| | 2697 | ConstExprValue *char_val = &array_val->data.x_array.elements[new_index]; |
| | 2698 | uint64_t big_c = char_val->data.x_bignum.data.x_uint; |
| | 2699 | assert(big_c <= UINT8_MAX); |
| | 2700 | uint8_t c = big_c; |
| | 2701 | buf_ptr(result)[i] = c; |
| | 2702 | } |
| | 2703 | return result; |
| | 2704 | } |
| | 2705 | |
| 2657 | static TypeTableEntry *ir_analyze_instruction_return(IrAnalyze *ira, | 2706 | static TypeTableEntry *ir_analyze_instruction_return(IrAnalyze *ira, |
| 2658 | IrInstructionReturn *return_instruction) | 2707 | IrInstructionReturn *return_instruction) |
| 2659 | { | 2708 | { |
| ... | @@ -3528,29 +3577,33 @@ static TypeTableEntry *ir_analyze_instruction_br(IrAnalyze *ira, IrInstructionBr | ... | @@ -3528,29 +3577,33 @@ static TypeTableEntry *ir_analyze_instruction_br(IrAnalyze *ira, IrInstructionBr |
| 3528 | } | 3577 | } |
| 3529 | | 3578 | |
| 3530 | static TypeTableEntry *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructionCondBr *cond_br_instruction) { | 3579 | static TypeTableEntry *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructionCondBr *cond_br_instruction) { |
| 3531 | TypeTableEntry *bool_type = ira->codegen->builtin_types.entry_bool; | 3580 | IrInstruction *condition = cond_br_instruction->condition->other; |
| 3532 | IrInstruction *condition = ir_get_casted_value(ira, cond_br_instruction->condition->other, bool_type); | | |
| 3533 | if (condition == ira->codegen->invalid_instruction) | | |
| 3534 | return ir_finish_anal(ira, ira->codegen->builtin_types.entry_unreachable); | | |
| 3535 | | 3581 | |
| 3536 | // TODO detect backward jumps | 3582 | // TODO detect backward jumps |
| 3537 | if (condition->static_value.special != ConstValSpecialRuntime) { | 3583 | |
| 3538 | IrBasicBlock *old_dest_block = condition->static_value.data.x_bool ? | 3584 | if (cond_br_instruction->is_inline || condition->static_value.special != ConstValSpecialRuntime) { |
| | 3585 | bool cond_is_true; |
| | 3586 | if (!ir_resolve_bool(ira, condition, &cond_is_true)) |
| | 3587 | return ir_finish_anal(ira, ira->codegen->builtin_types.entry_unreachable); |
| | 3588 | |
| | 3589 | IrBasicBlock *old_dest_block = cond_is_true ? |
| 3539 | cond_br_instruction->then_block : cond_br_instruction->else_block; | 3590 | cond_br_instruction->then_block : cond_br_instruction->else_block; |
| 3540 | | 3591 | |
| 3541 | if (cond_br_instruction->is_inline || old_dest_block->ref_count == 1) { | 3592 | if (cond_br_instruction->is_inline || old_dest_block->ref_count == 1) { |
| 3542 | ir_inline_bb(ira, old_dest_block); | 3593 | ir_inline_bb(ira, old_dest_block); |
| 3543 | return ira->codegen->builtin_types.entry_unreachable; | 3594 | return ira->codegen->builtin_types.entry_unreachable; |
| 3544 | } | 3595 | } |
| 3545 | } else if (cond_br_instruction->is_inline) { | | |
| 3546 | add_node_error(ira->codegen, condition->source_node, | | |
| 3547 | buf_sprintf("unable to evaluate constant expression")); | | |
| 3548 | return ir_finish_anal(ira, ira->codegen->builtin_types.entry_unreachable); | | |
| 3549 | } | 3596 | } |
| 3550 | | 3597 | |
| | 3598 | TypeTableEntry *bool_type = ira->codegen->builtin_types.entry_bool; |
| | 3599 | IrInstruction *casted_condition = ir_get_casted_value(ira, condition, bool_type); |
| | 3600 | if (casted_condition == ira->codegen->invalid_instruction) |
| | 3601 | return ir_finish_anal(ira, ira->codegen->builtin_types.entry_unreachable); |
| | 3602 | |
| 3551 | IrBasicBlock *new_then_block = ir_get_new_bb(ira, cond_br_instruction->then_block); | 3603 | IrBasicBlock *new_then_block = ir_get_new_bb(ira, cond_br_instruction->then_block); |
| 3552 | IrBasicBlock *new_else_block = ir_get_new_bb(ira, cond_br_instruction->else_block); | 3604 | IrBasicBlock *new_else_block = ir_get_new_bb(ira, cond_br_instruction->else_block); |
| 3553 | ir_build_cond_br_from(&ira->new_irb, &cond_br_instruction->base, condition, new_then_block, new_else_block, false); | 3605 | ir_build_cond_br_from(&ira->new_irb, &cond_br_instruction->base, |
| | 3606 | casted_condition, new_then_block, new_else_block, false); |
| 3554 | return ir_finish_anal(ira, ira->codegen->builtin_types.entry_unreachable); | 3607 | return ir_finish_anal(ira, ira->codegen->builtin_types.entry_unreachable); |
| 3555 | } | 3608 | } |
| 3556 | | 3609 | |
| ... | @@ -4255,6 +4308,100 @@ static TypeTableEntry *ir_analyze_instruction_asm(IrAnalyze *ira, IrInstructionA | ... | @@ -4255,6 +4308,100 @@ static TypeTableEntry *ir_analyze_instruction_asm(IrAnalyze *ira, IrInstructionA |
| 4255 | return return_type; | 4308 | return return_type; |
| 4256 | } | 4309 | } |
| 4257 | | 4310 | |
| | 4311 | static TypeTableEntry *ir_analyze_instruction_array_type(IrAnalyze *ira, |
| | 4312 | IrInstructionArrayType *array_type_instruction) |
| | 4313 | { |
| | 4314 | IrInstruction *size_value = array_type_instruction->size->other; |
| | 4315 | uint64_t size; |
| | 4316 | if (!ir_resolve_usize(ira, size_value, &size)) |
| | 4317 | return ira->codegen->builtin_types.entry_invalid; |
| | 4318 | |
| | 4319 | IrInstruction *child_type_value = array_type_instruction->child_type->other; |
| | 4320 | TypeTableEntry *child_type = ir_resolve_type(ira, child_type_value); |
| | 4321 | TypeTableEntry *canon_child_type = get_underlying_type(child_type); |
| | 4322 | switch (canon_child_type->id) { |
| | 4323 | case TypeTableEntryIdTypeDecl: |
| | 4324 | zig_unreachable(); |
| | 4325 | case TypeTableEntryIdInvalid: |
| | 4326 | return ira->codegen->builtin_types.entry_invalid; |
| | 4327 | case TypeTableEntryIdVar: |
| | 4328 | case TypeTableEntryIdUnreachable: |
| | 4329 | case TypeTableEntryIdUndefLit: |
| | 4330 | case TypeTableEntryIdNullLit: |
| | 4331 | case TypeTableEntryIdBlock: |
| | 4332 | add_node_error(ira->codegen, array_type_instruction->base.source_node, |
| | 4333 | buf_sprintf("array of type '%s' not allowed", buf_ptr(&child_type->name))); |
| | 4334 | // TODO if this is a typedecl, add error note showing the declaration of the type decl |
| | 4335 | return ira->codegen->builtin_types.entry_invalid; |
| | 4336 | case TypeTableEntryIdMetaType: |
| | 4337 | case TypeTableEntryIdVoid: |
| | 4338 | case TypeTableEntryIdBool: |
| | 4339 | case TypeTableEntryIdInt: |
| | 4340 | case TypeTableEntryIdFloat: |
| | 4341 | case TypeTableEntryIdPointer: |
| | 4342 | case TypeTableEntryIdArray: |
| | 4343 | case TypeTableEntryIdStruct: |
| | 4344 | case TypeTableEntryIdNumLitFloat: |
| | 4345 | case TypeTableEntryIdNumLitInt: |
| | 4346 | case TypeTableEntryIdMaybe: |
| | 4347 | case TypeTableEntryIdErrorUnion: |
| | 4348 | case TypeTableEntryIdPureError: |
| | 4349 | case TypeTableEntryIdEnum: |
| | 4350 | case TypeTableEntryIdUnion: |
| | 4351 | case TypeTableEntryIdFn: |
| | 4352 | case TypeTableEntryIdNamespace: |
| | 4353 | case TypeTableEntryIdGenericFn: |
| | 4354 | { |
| | 4355 | TypeTableEntry *result_type = get_array_type(ira->codegen, child_type, size); |
| | 4356 | bool depends_on_compile_var = child_type_value->static_value.depends_on_compile_var || |
| | 4357 | size_value->static_value.depends_on_compile_var; |
| | 4358 | ConstExprValue *out_val = ir_build_const_from(ira, &array_type_instruction->base, |
| | 4359 | depends_on_compile_var); |
| | 4360 | out_val->data.x_type = result_type; |
| | 4361 | return ira->codegen->builtin_types.entry_type; |
| | 4362 | } |
| | 4363 | } |
| | 4364 | zig_unreachable(); |
| | 4365 | } |
| | 4366 | |
| | 4367 | static TypeTableEntry *ir_analyze_instruction_compile_var(IrAnalyze *ira, |
| | 4368 | IrInstructionCompileVar *compile_var_instruction) |
| | 4369 | { |
| | 4370 | IrInstruction *name_value = compile_var_instruction->name->other; |
| | 4371 | Buf *var_name = ir_resolve_str(ira, name_value); |
| | 4372 | if (!var_name) |
| | 4373 | return ira->codegen->builtin_types.entry_invalid; |
| | 4374 | |
| | 4375 | ConstExprValue *out_val = ir_build_const_from(ira, &compile_var_instruction->base, true); |
| | 4376 | if (buf_eql_str(var_name, "is_big_endian")) { |
| | 4377 | out_val->data.x_bool = ira->codegen->is_big_endian; |
| | 4378 | return ira->codegen->builtin_types.entry_bool; |
| | 4379 | } else if (buf_eql_str(var_name, "is_release")) { |
| | 4380 | out_val->data.x_bool = ira->codegen->is_release_build; |
| | 4381 | return ira->codegen->builtin_types.entry_bool; |
| | 4382 | } else if (buf_eql_str(var_name, "is_test")) { |
| | 4383 | out_val->data.x_bool = ira->codegen->is_test_build; |
| | 4384 | return ira->codegen->builtin_types.entry_bool; |
| | 4385 | } else if (buf_eql_str(var_name, "os")) { |
| | 4386 | out_val->data.x_enum.tag = ira->codegen->target_os_index; |
| | 4387 | return ira->codegen->builtin_types.entry_os_enum; |
| | 4388 | } else if (buf_eql_str(var_name, "arch")) { |
| | 4389 | out_val->data.x_enum.tag = ira->codegen->target_arch_index; |
| | 4390 | return ira->codegen->builtin_types.entry_arch_enum; |
| | 4391 | } else if (buf_eql_str(var_name, "environ")) { |
| | 4392 | out_val->data.x_enum.tag = ira->codegen->target_environ_index; |
| | 4393 | return ira->codegen->builtin_types.entry_environ_enum; |
| | 4394 | } else if (buf_eql_str(var_name, "object_format")) { |
| | 4395 | out_val->data.x_enum.tag = ira->codegen->target_oformat_index; |
| | 4396 | return ira->codegen->builtin_types.entry_oformat_enum; |
| | 4397 | } else { |
| | 4398 | add_node_error(ira->codegen, name_value->source_node, |
| | 4399 | buf_sprintf("unrecognized compile variable: '%s'", buf_ptr(var_name))); |
| | 4400 | return ira->codegen->builtin_types.entry_invalid; |
| | 4401 | } |
| | 4402 | zig_unreachable(); |
| | 4403 | } |
| | 4404 | |
| 4258 | static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) { | 4405 | static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) { |
| 4259 | switch (instruction->id) { | 4406 | switch (instruction->id) { |
| 4260 | case IrInstructionIdInvalid: | 4407 | case IrInstructionIdInvalid: |
| ... | @@ -4305,12 +4452,15 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi | ... | @@ -4305,12 +4452,15 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 4305 | return ir_analyze_instruction_slice_type(ira, (IrInstructionSliceType *)instruction); | 4452 | return ir_analyze_instruction_slice_type(ira, (IrInstructionSliceType *)instruction); |
| 4306 | case IrInstructionIdAsm: | 4453 | case IrInstructionIdAsm: |
| 4307 | return ir_analyze_instruction_asm(ira, (IrInstructionAsm *)instruction); | 4454 | return ir_analyze_instruction_asm(ira, (IrInstructionAsm *)instruction); |
| | 4455 | case IrInstructionIdArrayType: |
| | 4456 | return ir_analyze_instruction_array_type(ira, (IrInstructionArrayType *)instruction); |
| | 4457 | case IrInstructionIdCompileVar: |
| | 4458 | return ir_analyze_instruction_compile_var(ira, (IrInstructionCompileVar *)instruction); |
| 4308 | case IrInstructionIdSwitchBr: | 4459 | case IrInstructionIdSwitchBr: |
| 4309 | case IrInstructionIdCast: | 4460 | case IrInstructionIdCast: |
| 4310 | case IrInstructionIdContainerInitList: | 4461 | case IrInstructionIdContainerInitList: |
| 4311 | case IrInstructionIdContainerInitFields: | 4462 | case IrInstructionIdContainerInitFields: |
| 4312 | case IrInstructionIdStructFieldPtr: | 4463 | case IrInstructionIdStructFieldPtr: |
| 4313 | case IrInstructionIdArrayType: | | |
| 4314 | zig_panic("TODO analyze more instructions"); | 4464 | zig_panic("TODO analyze more instructions"); |
| 4315 | } | 4465 | } |
| 4316 | zig_unreachable(); | 4466 | zig_unreachable(); |
| ... | @@ -4414,6 +4564,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { | ... | @@ -4414,6 +4564,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 4414 | case IrInstructionIdStructFieldPtr: | 4564 | case IrInstructionIdStructFieldPtr: |
| 4415 | case IrInstructionIdArrayType: | 4565 | case IrInstructionIdArrayType: |
| 4416 | case IrInstructionIdSliceType: | 4566 | case IrInstructionIdSliceType: |
| | 4567 | case IrInstructionIdCompileVar: |
| 4417 | return false; | 4568 | return false; |
| 4418 | case IrInstructionIdAsm: | 4569 | case IrInstructionIdAsm: |
| 4419 | { | 4570 | { |
| ... | @@ -5180,43 +5331,6 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) { | ... | @@ -5180,43 +5331,6 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) { |
| 5180 | // case BuiltinFnIdCUndef: | 5331 | // case BuiltinFnIdCUndef: |
| 5181 | // zig_panic("TODO"); | 5332 | // zig_panic("TODO"); |
| 5182 | // | 5333 | // |
| 5183 | // case BuiltinFnIdCompileVar: | | |
| 5184 | // { | | |
| 5185 | // AstNode **str_node = node->data.fn_call_expr.params.at(0)->parent_field; | | |
| 5186 | // | | |
| 5187 | // Buf *var_name = resolve_const_expr_str(g, import, context, str_node); | | |
| 5188 | // if (!var_name) { | | |
| 5189 | // return g->builtin_types.entry_invalid; | | |
| 5190 | // } | | |
| 5191 | // | | |
| 5192 | // ConstExprValue *const_val = &get_resolved_expr(node)->const_val; | | |
| 5193 | // const_val->ok = true; | | |
| 5194 | // const_val->depends_on_compile_var = true; | | |
| 5195 | // | | |
| 5196 | // if (buf_eql_str(var_name, "is_big_endian")) { | | |
| 5197 | // return resolve_expr_const_val_as_bool(g, node, g->is_big_endian, true); | | |
| 5198 | // } else if (buf_eql_str(var_name, "is_release")) { | | |
| 5199 | // return resolve_expr_const_val_as_bool(g, node, g->is_release_build, true); | | |
| 5200 | // } else if (buf_eql_str(var_name, "is_test")) { | | |
| 5201 | // return resolve_expr_const_val_as_bool(g, node, g->is_test_build, true); | | |
| 5202 | // } else if (buf_eql_str(var_name, "os")) { | | |
| 5203 | // const_val->data.x_enum.tag = g->target_os_index; | | |
| 5204 | // return g->builtin_types.entry_os_enum; | | |
| 5205 | // } else if (buf_eql_str(var_name, "arch")) { | | |
| 5206 | // const_val->data.x_enum.tag = g->target_arch_index; | | |
| 5207 | // return g->builtin_types.entry_arch_enum; | | |
| 5208 | // } else if (buf_eql_str(var_name, "environ")) { | | |
| 5209 | // const_val->data.x_enum.tag = g->target_environ_index; | | |
| 5210 | // return g->builtin_types.entry_environ_enum; | | |
| 5211 | // } else if (buf_eql_str(var_name, "object_format")) { | | |
| 5212 | // const_val->data.x_enum.tag = g->target_oformat_index; | | |
| 5213 | // return g->builtin_types.entry_oformat_enum; | | |
| 5214 | // } else { | | |
| 5215 | // add_node_error(g, *str_node, | | |
| 5216 | // buf_sprintf("unrecognized compile variable: '%s'", buf_ptr(var_name))); | | |
| 5217 | // return g->builtin_types.entry_invalid; | | |
| 5218 | // } | | |
| 5219 | // } | | |
| 5220 | // case BuiltinFnIdConstEval: | 5334 | // case BuiltinFnIdConstEval: |
| 5221 | // { | 5335 | // { |
| 5222 | // AstNode **expr_node = node->data.fn_call_expr.params.at(0)->parent_field; | 5336 | // AstNode **expr_node = node->data.fn_call_expr.params.at(0)->parent_field; |
| ... | @@ -7605,53 +7719,6 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) { | ... | @@ -7605,53 +7719,6 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) { |
| 7605 | // } | 7719 | // } |
| 7606 | //} | 7720 | //} |
| 7607 | // | 7721 | // |
| 7608 | //static TypeTableEntry *analyze_array_type(CodeGen *g, ImportTableEntry *import, BlockContext *context, | | |
| 7609 | // TypeTableEntry *expected_type, AstNode *node) | | |
| 7610 | //{ | | |
| 7611 | // AstNode *size_node = node->data.array_type.size; | | |
| 7612 | // | | |
| 7613 | // TypeTableEntry *child_type = analyze_type_expr_pointer_only(g, import, context, | | |
| 7614 | // node->data.array_type.child_type, true); | | |
| 7615 | // | | |
| 7616 | // if (child_type->id == TypeTableEntryIdUnreachable) { | | |
| 7617 | // add_node_error(g, node, buf_create_from_str("array of unreachable not allowed")); | | |
| 7618 | // return g->builtin_types.entry_invalid; | | |
| 7619 | // } else if (child_type->id == TypeTableEntryIdInvalid) { | | |
| 7620 | // return g->builtin_types.entry_invalid; | | |
| 7621 | // } | | |
| 7622 | // | | |
| 7623 | // if (size_node) { | | |
| 7624 | // child_type = analyze_type_expr(g, import, context, node->data.array_type.child_type); | | |
| 7625 | // TypeTableEntry *size_type = analyze_expression(g, import, context, | | |
| 7626 | // g->builtin_types.entry_usize, size_node); | | |
| 7627 | // if (size_type->id == TypeTableEntryIdInvalid) { | | |
| 7628 | // return g->builtin_types.entry_invalid; | | |
| 7629 | // } | | |
| 7630 | // | | |
| 7631 | // ConstExprValue *const_val = &get_resolved_expr(size_node)->const_val; | | |
| 7632 | // if (const_val->ok) { | | |
| 7633 | // if (const_val->data.x_bignum.is_negative) { | | |
| 7634 | // add_node_error(g, size_node, | | |
| 7635 | // buf_sprintf("array size %s is negative", | | |
| 7636 | // buf_ptr(bignum_to_buf(&const_val->data.x_bignum)))); | | |
| 7637 | // return g->builtin_types.entry_invalid; | | |
| 7638 | // } else { | | |
| 7639 | // return resolve_expr_const_val_as_type(g, node, | | |
| 7640 | // get_array_type(g, child_type, const_val->data.x_bignum.data.x_uint), false); | | |
| 7641 | // } | | |
| 7642 | // } else if (context->fn_entry) { | | |
| 7643 | // return resolve_expr_const_val_as_type(g, node, | | |
| 7644 | // get_slice_type(g, child_type, node->data.array_type.is_const), false); | | |
| 7645 | // } else { | | |
| 7646 | // add_node_error(g, first_executing_node(size_node), | | |
| 7647 | // buf_sprintf("unable to evaluate constant expression")); | | |
| 7648 | // return g->builtin_types.entry_invalid; | | |
| 7649 | // } | | |
| 7650 | // } else { | | |
| 7651 | // TypeTableEntry *slice_type = get_slice_type(g, child_type, node->data.array_type.is_const); | | |
| 7652 | // return resolve_expr_const_val_as_type(g, node, slice_type, false); | | |
| 7653 | // } | | |
| 7654 | //} | | |
| 7655 | //static size_t get_conditional_defer_count(BlockContext *inner_block, BlockContext *outer_block) { | 7722 | //static size_t get_conditional_defer_count(BlockContext *inner_block, BlockContext *outer_block) { |
| 7656 | // size_t result = 0; | 7723 | // size_t result = 0; |
| 7657 | // while (inner_block != outer_block) { | 7724 | // while (inner_block != outer_block) { |
| ... | @@ -9572,3 +9639,97 @@ static void analyze_goto_pass2(CodeGen *g, ImportTableEntry *import, AstNode *no | ... | @@ -9572,3 +9639,97 @@ static void analyze_goto_pass2(CodeGen *g, ImportTableEntry *import, AstNode *no |
| 9572 | // LLVMPositionBuilderAtEnd(g->builder, basic_block); | 9639 | // LLVMPositionBuilderAtEnd(g->builder, basic_block); |
| 9573 | // return nullptr; | 9640 | // return nullptr; |
| 9574 | //} | 9641 | //} |
| | 9642 | //static LLVMValueRef gen_overflow_shl_op(CodeGen *g, TypeTableEntry *type_entry, |
| | 9643 | // LLVMValueRef val1, LLVMValueRef val2) |
| | 9644 | //{ |
| | 9645 | // // for unsigned left shifting, we do the wrapping shift, then logically shift |
| | 9646 | // // right the same number of bits |
| | 9647 | // // if the values don't match, we have an overflow |
| | 9648 | // // for signed left shifting we do the same except arithmetic shift right |
| | 9649 | // |
| | 9650 | // assert(type_entry->id == TypeTableEntryIdInt); |
| | 9651 | // |
| | 9652 | // LLVMValueRef result = LLVMBuildShl(g->builder, val1, val2, ""); |
| | 9653 | // LLVMValueRef orig_val; |
| | 9654 | // if (type_entry->data.integral.is_signed) { |
| | 9655 | // orig_val = LLVMBuildAShr(g->builder, result, val2, ""); |
| | 9656 | // } else { |
| | 9657 | // orig_val = LLVMBuildLShr(g->builder, result, val2, ""); |
| | 9658 | // } |
| | 9659 | // LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, val1, orig_val, ""); |
| | 9660 | // |
| | 9661 | // LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "OverflowOk"); |
| | 9662 | // LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "OverflowFail"); |
| | 9663 | // LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block); |
| | 9664 | // |
| | 9665 | // LLVMPositionBuilderAtEnd(g->builder, fail_block); |
| | 9666 | // gen_debug_safety_crash(g); |
| | 9667 | // |
| | 9668 | // LLVMPositionBuilderAtEnd(g->builder, ok_block); |
| | 9669 | // return result; |
| | 9670 | //} |
| | 9671 | // |
| | 9672 | //static LLVMValueRef gen_div(CodeGen *g, AstNode *source_node, LLVMValueRef val1, LLVMValueRef val2, |
| | 9673 | // TypeTableEntry *type_entry, bool exact) |
| | 9674 | //{ |
| | 9675 | // |
| | 9676 | // if (want_debug_safety(g, source_node)) { |
| | 9677 | // LLVMValueRef zero = LLVMConstNull(type_entry->type_ref); |
| | 9678 | // LLVMValueRef is_zero_bit; |
| | 9679 | // if (type_entry->id == TypeTableEntryIdInt) { |
| | 9680 | // is_zero_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, val2, zero, ""); |
| | 9681 | // } else if (type_entry->id == TypeTableEntryIdFloat) { |
| | 9682 | // is_zero_bit = LLVMBuildFCmp(g->builder, LLVMRealOEQ, val2, zero, ""); |
| | 9683 | // } else { |
| | 9684 | // zig_unreachable(); |
| | 9685 | // } |
| | 9686 | // LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "DivZeroOk"); |
| | 9687 | // LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "DivZeroFail"); |
| | 9688 | // LLVMBuildCondBr(g->builder, is_zero_bit, fail_block, ok_block); |
| | 9689 | // |
| | 9690 | // LLVMPositionBuilderAtEnd(g->builder, fail_block); |
| | 9691 | // gen_debug_safety_crash(g); |
| | 9692 | // |
| | 9693 | // LLVMPositionBuilderAtEnd(g->builder, ok_block); |
| | 9694 | // } |
| | 9695 | // |
| | 9696 | // if (type_entry->id == TypeTableEntryIdFloat) { |
| | 9697 | // assert(!exact); |
| | 9698 | // return LLVMBuildFDiv(g->builder, val1, val2, ""); |
| | 9699 | // } |
| | 9700 | // |
| | 9701 | // assert(type_entry->id == TypeTableEntryIdInt); |
| | 9702 | // |
| | 9703 | // if (exact) { |
| | 9704 | // if (want_debug_safety(g, source_node)) { |
| | 9705 | // LLVMValueRef remainder_val; |
| | 9706 | // if (type_entry->data.integral.is_signed) { |
| | 9707 | // remainder_val = LLVMBuildSRem(g->builder, val1, val2, ""); |
| | 9708 | // } else { |
| | 9709 | // remainder_val = LLVMBuildURem(g->builder, val1, val2, ""); |
| | 9710 | // } |
| | 9711 | // LLVMValueRef zero = LLVMConstNull(type_entry->type_ref); |
| | 9712 | // LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, remainder_val, zero, ""); |
| | 9713 | // |
| | 9714 | // LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "DivExactOk"); |
| | 9715 | // LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "DivExactFail"); |
| | 9716 | // LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block); |
| | 9717 | // |
| | 9718 | // LLVMPositionBuilderAtEnd(g->builder, fail_block); |
| | 9719 | // gen_debug_safety_crash(g); |
| | 9720 | // |
| | 9721 | // LLVMPositionBuilderAtEnd(g->builder, ok_block); |
| | 9722 | // } |
| | 9723 | // if (type_entry->data.integral.is_signed) { |
| | 9724 | // return LLVMBuildExactSDiv(g->builder, val1, val2, ""); |
| | 9725 | // } else { |
| | 9726 | // return ZigLLVMBuildExactUDiv(g->builder, val1, val2, ""); |
| | 9727 | // } |
| | 9728 | // } else { |
| | 9729 | // if (type_entry->data.integral.is_signed) { |
| | 9730 | // return LLVMBuildSDiv(g->builder, val1, val2, ""); |
| | 9731 | // } else { |
| | 9732 | // return LLVMBuildUDiv(g->builder, val1, val2, ""); |
| | 9733 | // } |
| | 9734 | // } |
| | 9735 | //} |