| ... | ... | @@ -218,6 +218,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionAsm *) { |
| 218 | 218 | return IrInstructionIdAsm; |
| 219 | 219 | } |
| 220 | 220 | |
| 221 | static constexpr IrInstructionId ir_instruction_id(IrInstructionCompileVar *) { |
| 222 | return IrInstructionIdCompileVar; |
| 223 | } |
| 224 | |
| 221 | 225 | template<typename T> |
| 222 | 226 | static T *ir_create_instruction(IrExecutable *exec, AstNode *source_node) { |
| 223 | 227 | T *special_instruction = allocate<T>(1); |
| ... | ... | @@ -507,14 +511,6 @@ static IrInstruction *ir_build_field_ptr(IrBuilder *irb, AstNode *source_node, |
| 507 | 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 | 514 | static IrInstruction *ir_build_read_field(IrBuilder *irb, AstNode *source_node, |
| 519 | 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 | 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 | 526 | static IrInstruction *ir_build_struct_field_ptr(IrBuilder *irb, AstNode *source_node, |
| 539 | 527 | IrInstruction *struct_ptr, TypeStructField *field) |
| 540 | 528 | { |
| ... | ... | @@ -861,6 +849,15 @@ static IrInstruction *ir_build_asm_from(IrBuilder *irb, IrInstruction *old_instr |
| 861 | 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 | 861 | static void ir_gen_defers_for_block(IrBuilder *irb, BlockContext *inner_block, BlockContext *outer_block, |
| 865 | 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 | 1333 | |
| 1337 | 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 | 1345 | case BuiltinFnIdMemcpy: |
| 1340 | 1346 | case BuiltinFnIdMemset: |
| 1341 | 1347 | case BuiltinFnIdSizeof: |
| ... | ... | @@ -1350,7 +1356,6 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, AstNode *node) { |
| 1350 | 1356 | case BuiltinFnIdCInclude: |
| 1351 | 1357 | case BuiltinFnIdCDefine: |
| 1352 | 1358 | case BuiltinFnIdCUndef: |
| 1353 | | case BuiltinFnIdCompileVar: |
| 1354 | 1359 | case BuiltinFnIdCompileErr: |
| 1355 | 1360 | case BuiltinFnIdConstEval: |
| 1356 | 1361 | case BuiltinFnIdCtz: |
| ... | ... | @@ -1410,14 +1415,15 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, AstNode *node) { |
| 1410 | 1415 | IrBasicBlock *else_block = ir_build_basic_block(irb, "Else"); |
| 1411 | 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 | 1421 | ir_set_cursor_at_end(irb, then_block); |
| 1416 | 1422 | IrInstruction *then_expr_result = ir_gen_node(irb, then_node, node->block_context); |
| 1417 | 1423 | if (then_expr_result == irb->codegen->invalid_instruction) |
| 1418 | 1424 | return then_expr_result; |
| 1419 | 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 | 1428 | ir_set_cursor_at_end(irb, else_block); |
| 1423 | 1429 | IrInstruction *else_expr_result; |
| ... | ... | @@ -1429,7 +1435,7 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, AstNode *node) { |
| 1429 | 1435 | else_expr_result = ir_build_const_void(irb, node); |
| 1430 | 1436 | } |
| 1431 | 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 | 1440 | ir_set_cursor_at_end(irb, endif_block); |
| 1435 | 1441 | IrInstruction **incoming_values = allocate<IrInstruction *>(2); |
| ... | ... | @@ -2281,7 +2287,19 @@ static TypeTableEntry *ir_analyze_const_usize(IrAnalyze *ira, IrInstruction *ins |
| 2281 | 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 | 2303 | if (type_value == ira->codegen->invalid_instruction) |
| 2286 | 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 | 2312 | return ira->codegen->builtin_types.entry_invalid; |
| 2295 | 2313 | } |
| 2296 | 2314 | |
| 2297 | | ConstExprValue *const_val = &type_value->static_value; |
| 2298 | | if (const_val->special == ConstValSpecialRuntime) { |
| 2299 | | add_node_error(ira->codegen, type_value->source_node, |
| 2300 | | buf_sprintf("unable to evaluate constant expression")); |
| 2315 | ConstExprValue *const_val = ir_resolve_const(ira, type_value); |
| 2316 | if (!const_val) |
| 2301 | 2317 | return ira->codegen->builtin_types.entry_invalid; |
| 2302 | | } |
| 2303 | 2318 | |
| 2304 | 2319 | return const_val->data.x_type; |
| 2305 | 2320 | } |
| 2306 | 2321 | |
| 2307 | | static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value) { |
| 2308 | | if (value->static_value.special != ConstValSpecialStatic) { |
| 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; |
| 2322 | static TypeTableEntry *ir_resolve_type(IrAnalyze *ira, IrInstruction *type_value) { |
| 2323 | return ir_resolve_type_lval(ira, type_value, LValPurposeNone); |
| 2335 | 2324 | } |
| 2336 | 2325 | |
| 2337 | 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 | 2336 | return nullptr; |
| 2348 | 2337 | } |
| 2349 | 2338 | |
| 2350 | | ConstExprValue *const_val = &fn_value->static_value; |
| 2351 | | if (const_val->special == ConstValSpecialRuntime) { |
| 2352 | | add_node_error(ira->codegen, fn_value->source_node, |
| 2353 | | buf_sprintf("unable to evaluate constant expression")); |
| 2339 | ConstExprValue *const_val = ir_resolve_const(ira, fn_value); |
| 2340 | if (!const_val) |
| 2354 | 2341 | return nullptr; |
| 2355 | | } |
| 2356 | 2342 | |
| 2357 | 2343 | return const_val->data.x_fn; |
| 2358 | 2344 | } |
| ... | ... | @@ -2654,6 +2640,69 @@ static IrInstruction *ir_get_casted_value(IrAnalyze *ira, IrInstruction *value, |
| 2654 | 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 | 2706 | static TypeTableEntry *ir_analyze_instruction_return(IrAnalyze *ira, |
| 2658 | 2707 | IrInstructionReturn *return_instruction) |
| 2659 | 2708 | { |
| ... | ... | @@ -3528,29 +3577,33 @@ static TypeTableEntry *ir_analyze_instruction_br(IrAnalyze *ira, IrInstructionBr |
| 3528 | 3577 | } |
| 3529 | 3578 | |
| 3530 | 3579 | static TypeTableEntry *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructionCondBr *cond_br_instruction) { |
| 3531 | | TypeTableEntry *bool_type = ira->codegen->builtin_types.entry_bool; |
| 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); |
| 3580 | IrInstruction *condition = cond_br_instruction->condition->other; |
| 3535 | 3581 | |
| 3536 | 3582 | // TODO detect backward jumps |
| 3537 | | if (condition->static_value.special != ConstValSpecialRuntime) { |
| 3538 | | IrBasicBlock *old_dest_block = condition->static_value.data.x_bool ? |
| 3583 | |
| 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 | 3590 | cond_br_instruction->then_block : cond_br_instruction->else_block; |
| 3540 | 3591 | |
| 3541 | 3592 | if (cond_br_instruction->is_inline || old_dest_block->ref_count == 1) { |
| 3542 | 3593 | ir_inline_bb(ira, old_dest_block); |
| 3543 | 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 | 3603 | IrBasicBlock *new_then_block = ir_get_new_bb(ira, cond_br_instruction->then_block); |
| 3552 | 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 | 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 | 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 | 4405 | static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) { |
| 4259 | 4406 | switch (instruction->id) { |
| 4260 | 4407 | case IrInstructionIdInvalid: |
| ... | ... | @@ -4305,12 +4452,15 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 4305 | 4452 | return ir_analyze_instruction_slice_type(ira, (IrInstructionSliceType *)instruction); |
| 4306 | 4453 | case IrInstructionIdAsm: |
| 4307 | 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 | 4459 | case IrInstructionIdSwitchBr: |
| 4309 | 4460 | case IrInstructionIdCast: |
| 4310 | 4461 | case IrInstructionIdContainerInitList: |
| 4311 | 4462 | case IrInstructionIdContainerInitFields: |
| 4312 | 4463 | case IrInstructionIdStructFieldPtr: |
| 4313 | | case IrInstructionIdArrayType: |
| 4314 | 4464 | zig_panic("TODO analyze more instructions"); |
| 4315 | 4465 | } |
| 4316 | 4466 | zig_unreachable(); |
| ... | ... | @@ -4414,6 +4564,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 4414 | 4564 | case IrInstructionIdStructFieldPtr: |
| 4415 | 4565 | case IrInstructionIdArrayType: |
| 4416 | 4566 | case IrInstructionIdSliceType: |
| 4567 | case IrInstructionIdCompileVar: |
| 4417 | 4568 | return false; |
| 4418 | 4569 | case IrInstructionIdAsm: |
| 4419 | 4570 | { |
| ... | ... | @@ -5180,43 +5331,6 @@ IrInstruction *ir_exec_const_result(IrExecutable *exec) { |
| 5180 | 5331 | // case BuiltinFnIdCUndef: |
| 5181 | 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 | 5334 | // case BuiltinFnIdConstEval: |
| 5221 | 5335 | // { |
| 5222 | 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 | 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 | 7722 | //static size_t get_conditional_defer_count(BlockContext *inner_block, BlockContext *outer_block) { |
| 7656 | 7723 | // size_t result = 0; |
| 7657 | 7724 | // while (inner_block != outer_block) { |
| ... | ... | @@ -9572,3 +9639,97 @@ static void analyze_goto_pass2(CodeGen *g, ImportTableEntry *import, AstNode *no |
| 9572 | 9639 | // LLVMPositionBuilderAtEnd(g->builder, basic_block); |
| 9573 | 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 | //} |