| ... | @@ -2,6 +2,7 @@ | ... | @@ -2,6 +2,7 @@ |
| 2 | #include "error.hpp" | 2 | #include "error.hpp" |
| 3 | #include "eval.hpp" | 3 | #include "eval.hpp" |
| 4 | #include "ir.hpp" | 4 | #include "ir.hpp" |
| | 5 | #include "ir_print.hpp" |
| 5 | | 6 | |
| 6 | struct IrExecContext { | 7 | struct IrExecContext { |
| 7 | ConstExprValue *mem_slot_list; | 8 | ConstExprValue *mem_slot_list; |
| ... | @@ -32,6 +33,7 @@ struct IrAnalyze { | ... | @@ -32,6 +33,7 @@ struct IrAnalyze { |
| 32 | static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, BlockContext *scope); | 33 | static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, BlockContext *scope); |
| 33 | static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockContext *block_context, | 34 | static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockContext *block_context, |
| 34 | LValPurpose lval); | 35 | LValPurpose lval); |
| | 36 | static TypeTableEntry *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *instruction); |
| 35 | | 37 | |
| 36 | static void ir_instruction_append(IrBasicBlock *basic_block, IrInstruction *instruction) { | 38 | static void ir_instruction_append(IrBasicBlock *basic_block, IrInstruction *instruction) { |
| 37 | assert(basic_block); | 39 | assert(basic_block); |
| ... | @@ -127,6 +129,14 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionFieldPtr *) { | ... | @@ -127,6 +129,14 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionFieldPtr *) { |
| 127 | return IrInstructionIdFieldPtr; | 129 | return IrInstructionIdFieldPtr; |
| 128 | } | 130 | } |
| 129 | | 131 | |
| | 132 | static constexpr IrInstructionId ir_instruction_id(IrInstructionStructFieldPtr *) { |
| | 133 | return IrInstructionIdStructFieldPtr; |
| | 134 | } |
| | 135 | |
| | 136 | static constexpr IrInstructionId ir_instruction_id(IrInstructionReadField *) { |
| | 137 | return IrInstructionIdReadField; |
| | 138 | } |
| | 139 | |
| 130 | static constexpr IrInstructionId ir_instruction_id(IrInstructionElemPtr *) { | 140 | static constexpr IrInstructionId ir_instruction_id(IrInstructionElemPtr *) { |
| 131 | return IrInstructionIdElemPtr; | 141 | return IrInstructionIdElemPtr; |
| 132 | } | 142 | } |
| ... | @@ -167,6 +177,18 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionUnreachable *) { | ... | @@ -167,6 +177,18 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionUnreachable *) { |
| 167 | return IrInstructionIdUnreachable; | 177 | return IrInstructionIdUnreachable; |
| 168 | } | 178 | } |
| 169 | | 179 | |
| | 180 | static constexpr IrInstructionId ir_instruction_id(IrInstructionTypeOf *) { |
| | 181 | return IrInstructionIdTypeOf; |
| | 182 | } |
| | 183 | |
| | 184 | static constexpr IrInstructionId ir_instruction_id(IrInstructionToPtrType *) { |
| | 185 | return IrInstructionIdToPtrType; |
| | 186 | } |
| | 187 | |
| | 188 | static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrTypeChild *) { |
| | 189 | return IrInstructionIdPtrTypeChild; |
| | 190 | } |
| | 191 | |
| 170 | template<typename T> | 192 | template<typename T> |
| 171 | static T *ir_create_instruction(IrExecutable *exec, AstNode *source_node) { | 193 | static T *ir_create_instruction(IrExecutable *exec, AstNode *source_node) { |
| 172 | T *special_instruction = allocate<T>(1); | 194 | T *special_instruction = allocate<T>(1); |
| ... | @@ -256,6 +278,14 @@ static IrInstruction *ir_build_const_void(IrBuilder *irb, AstNode *source_node) | ... | @@ -256,6 +278,14 @@ static IrInstruction *ir_build_const_void(IrBuilder *irb, AstNode *source_node) |
| 256 | return &const_instruction->base; | 278 | return &const_instruction->base; |
| 257 | } | 279 | } |
| 258 | | 280 | |
| | 281 | static IrInstruction *ir_build_const_undefined(IrBuilder *irb, AstNode *source_node) { |
| | 282 | IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node); |
| | 283 | const_instruction->base.static_value.ok = true; |
| | 284 | const_instruction->base.static_value.special = ConstValSpecialUndef; |
| | 285 | const_instruction->base.type_entry = irb->codegen->builtin_types.entry_undef; |
| | 286 | return &const_instruction->base; |
| | 287 | } |
| | 288 | |
| 259 | static IrInstruction *ir_build_const_bignum(IrBuilder *irb, AstNode *source_node, BigNum *bignum) { | 289 | static IrInstruction *ir_build_const_bignum(IrBuilder *irb, AstNode *source_node, BigNum *bignum) { |
| 260 | IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node); | 290 | IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node); |
| 261 | const_instruction->base.type_entry = (bignum->kind == BigNumKindInt) ? | 291 | const_instruction->base.type_entry = (bignum->kind == BigNumKindInt) ? |
| ... | @@ -265,6 +295,14 @@ static IrInstruction *ir_build_const_bignum(IrBuilder *irb, AstNode *source_node | ... | @@ -265,6 +295,14 @@ static IrInstruction *ir_build_const_bignum(IrBuilder *irb, AstNode *source_node |
| 265 | return &const_instruction->base; | 295 | return &const_instruction->base; |
| 266 | } | 296 | } |
| 267 | | 297 | |
| | 298 | static IrInstruction *ir_build_const_usize(IrBuilder *irb, AstNode *source_node, uint64_t value) { |
| | 299 | IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node); |
| | 300 | const_instruction->base.type_entry = irb->codegen->builtin_types.entry_usize; |
| | 301 | const_instruction->base.static_value.ok = true; |
| | 302 | bignum_init_unsigned(&const_instruction->base.static_value.data.x_bignum, value); |
| | 303 | return &const_instruction->base; |
| | 304 | } |
| | 305 | |
| 268 | static IrInstruction *ir_create_const_type(IrBuilder *irb, AstNode *source_node, TypeTableEntry *type_entry) { | 306 | static IrInstruction *ir_create_const_type(IrBuilder *irb, AstNode *source_node, TypeTableEntry *type_entry) { |
| 269 | IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(irb->exec, source_node); | 307 | IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(irb->exec, source_node); |
| 270 | const_instruction->base.type_entry = irb->codegen->builtin_types.entry_type; | 308 | const_instruction->base.type_entry = irb->codegen->builtin_types.entry_type; |
| ... | @@ -356,6 +394,67 @@ static IrInstruction *ir_build_elem_ptr_from(IrBuilder *irb, IrInstruction *old_ | ... | @@ -356,6 +394,67 @@ static IrInstruction *ir_build_elem_ptr_from(IrBuilder *irb, IrInstruction *old_ |
| 356 | return new_instruction; | 394 | return new_instruction; |
| 357 | } | 395 | } |
| 358 | | 396 | |
| | 397 | static IrInstruction *ir_build_field_ptr(IrBuilder *irb, AstNode *source_node, |
| | 398 | IrInstruction *container_ptr, Buf *field_name) |
| | 399 | { |
| | 400 | IrInstructionFieldPtr *instruction = ir_build_instruction<IrInstructionFieldPtr>(irb, source_node); |
| | 401 | instruction->container_ptr = container_ptr; |
| | 402 | instruction->field_name = field_name; |
| | 403 | |
| | 404 | ir_ref_instruction(container_ptr); |
| | 405 | |
| | 406 | return &instruction->base; |
| | 407 | } |
| | 408 | |
| | 409 | //static IrInstruction *ir_build_field_ptr_from(IrBuilder *irb, IrInstruction *old_instruction, |
| | 410 | // IrInstruction *container_ptr, Buf *field_name) |
| | 411 | //{ |
| | 412 | // IrInstruction *new_instruction = ir_build_field_ptr(irb, old_instruction->source_node, container_ptr, field_name); |
| | 413 | // ir_link_new_instruction(new_instruction, old_instruction); |
| | 414 | // return new_instruction; |
| | 415 | //} |
| | 416 | |
| | 417 | static IrInstruction *ir_build_read_field(IrBuilder *irb, AstNode *source_node, |
| | 418 | IrInstruction *container_ptr, Buf *field_name) |
| | 419 | { |
| | 420 | IrInstructionReadField *instruction = ir_build_instruction<IrInstructionReadField>(irb, source_node); |
| | 421 | instruction->container_ptr = container_ptr; |
| | 422 | instruction->field_name = field_name; |
| | 423 | |
| | 424 | ir_ref_instruction(container_ptr); |
| | 425 | |
| | 426 | return &instruction->base; |
| | 427 | } |
| | 428 | |
| | 429 | //static IrInstruction *ir_build_read_field_from(IrBuilder *irb, IrInstruction *old_instruction, |
| | 430 | // IrInstruction *container_ptr, Buf *field_name) |
| | 431 | //{ |
| | 432 | // IrInstruction *new_instruction = ir_build_read_field(irb, old_instruction->source_node, container_ptr, field_name); |
| | 433 | // ir_link_new_instruction(new_instruction, old_instruction); |
| | 434 | // return new_instruction; |
| | 435 | //} |
| | 436 | |
| | 437 | static IrInstruction *ir_build_struct_field_ptr(IrBuilder *irb, AstNode *source_node, |
| | 438 | IrInstruction *struct_ptr, TypeStructField *field) |
| | 439 | { |
| | 440 | IrInstructionStructFieldPtr *instruction = ir_build_instruction<IrInstructionStructFieldPtr>(irb, source_node); |
| | 441 | instruction->struct_ptr = struct_ptr; |
| | 442 | instruction->field = field; |
| | 443 | |
| | 444 | ir_ref_instruction(struct_ptr); |
| | 445 | |
| | 446 | return &instruction->base; |
| | 447 | } |
| | 448 | |
| | 449 | static IrInstruction *ir_build_struct_field_ptr_from(IrBuilder *irb, IrInstruction *old_instruction, |
| | 450 | IrInstruction *struct_ptr, TypeStructField *type_struct_field) |
| | 451 | { |
| | 452 | IrInstruction *new_instruction = ir_build_struct_field_ptr(irb, old_instruction->source_node, |
| | 453 | struct_ptr, type_struct_field); |
| | 454 | ir_link_new_instruction(new_instruction, old_instruction); |
| | 455 | return new_instruction; |
| | 456 | } |
| | 457 | |
| 359 | static IrInstruction *ir_build_call(IrBuilder *irb, AstNode *source_node, | 458 | static IrInstruction *ir_build_call(IrBuilder *irb, AstNode *source_node, |
| 360 | IrInstruction *fn, size_t arg_count, IrInstruction **args) | 459 | IrInstruction *fn, size_t arg_count, IrInstruction **args) |
| 361 | { | 460 | { |
| ... | @@ -564,6 +663,33 @@ static IrInstruction *ir_build_load_ptr_from(IrBuilder *irb, IrInstruction *old_ | ... | @@ -564,6 +663,33 @@ static IrInstruction *ir_build_load_ptr_from(IrBuilder *irb, IrInstruction *old_ |
| 564 | return new_instruction; | 663 | return new_instruction; |
| 565 | } | 664 | } |
| 566 | | 665 | |
| | 666 | static IrInstruction *ir_build_typeof(IrBuilder *irb, AstNode *source_node, IrInstruction *value) { |
| | 667 | IrInstructionTypeOf *instruction = ir_build_instruction<IrInstructionTypeOf>(irb, source_node); |
| | 668 | instruction->value = value; |
| | 669 | |
| | 670 | ir_ref_instruction(value); |
| | 671 | |
| | 672 | return &instruction->base; |
| | 673 | } |
| | 674 | |
| | 675 | static IrInstruction *ir_build_to_ptr_type(IrBuilder *irb, AstNode *source_node, IrInstruction *value) { |
| | 676 | IrInstructionToPtrType *instruction = ir_build_instruction<IrInstructionToPtrType>(irb, source_node); |
| | 677 | instruction->value = value; |
| | 678 | |
| | 679 | ir_ref_instruction(value); |
| | 680 | |
| | 681 | return &instruction->base; |
| | 682 | } |
| | 683 | |
| | 684 | static IrInstruction *ir_build_ptr_type_child(IrBuilder *irb, AstNode *source_node, IrInstruction *value) { |
| | 685 | IrInstructionPtrTypeChild *instruction = ir_build_instruction<IrInstructionPtrTypeChild>(irb, source_node); |
| | 686 | instruction->value = value; |
| | 687 | |
| | 688 | ir_ref_instruction(value); |
| | 689 | |
| | 690 | return &instruction->base; |
| | 691 | } |
| | 692 | |
| 567 | //static size_t get_conditional_defer_count(BlockContext *inner_block, BlockContext *outer_block) { | 693 | //static size_t get_conditional_defer_count(BlockContext *inner_block, BlockContext *outer_block) { |
| 568 | // size_t result = 0; | 694 | // size_t result = 0; |
| 569 | // while (inner_block != outer_block) { | 695 | // while (inner_block != outer_block) { |
| ... | @@ -648,11 +774,11 @@ static void ir_set_cursor_at_end(IrBuilder *irb, IrBasicBlock *basic_block) { | ... | @@ -648,11 +774,11 @@ static void ir_set_cursor_at_end(IrBuilder *irb, IrBasicBlock *basic_block) { |
| 648 | irb->current_basic_block = basic_block; | 774 | irb->current_basic_block = basic_block; |
| 649 | } | 775 | } |
| 650 | | 776 | |
| 651 | static VariableTableEntry *add_local_var(CodeGen *codegen, AstNode *node, Buf *name, | 777 | static VariableTableEntry *add_local_var(CodeGen *codegen, AstNode *node, BlockContext *scope, |
| 652 | bool is_const, bool is_shadowable) | 778 | Buf *name, bool is_const, bool is_shadowable) |
| 653 | { | 779 | { |
| 654 | VariableTableEntry *variable_entry = allocate<VariableTableEntry>(1); | 780 | VariableTableEntry *variable_entry = allocate<VariableTableEntry>(1); |
| 655 | variable_entry->block_context = node->block_context; | 781 | variable_entry->block_context = scope; |
| 656 | variable_entry->import = node->owner; | 782 | variable_entry->import = node->owner; |
| 657 | variable_entry->shadowable = is_shadowable; | 783 | variable_entry->shadowable = is_shadowable; |
| 658 | variable_entry->mem_slot_index = SIZE_MAX; | 784 | variable_entry->mem_slot_index = SIZE_MAX; |
| ... | @@ -686,6 +812,7 @@ static VariableTableEntry *add_local_var(CodeGen *codegen, AstNode *node, Buf *n | ... | @@ -686,6 +812,7 @@ static VariableTableEntry *add_local_var(CodeGen *codegen, AstNode *node, Buf *n |
| 686 | | 812 | |
| 687 | node->block_context->var_table.put(&variable_entry->name, variable_entry); | 813 | node->block_context->var_table.put(&variable_entry->name, variable_entry); |
| 688 | } else { | 814 | } else { |
| | 815 | assert(is_shadowable); |
| 689 | // TODO replace _anon with @anon and make sure all tests still pass | 816 | // TODO replace _anon with @anon and make sure all tests still pass |
| 690 | buf_init_from_str(&variable_entry->name, "_anon"); | 817 | buf_init_from_str(&variable_entry->name, "_anon"); |
| 691 | } | 818 | } |
| ... | @@ -697,10 +824,10 @@ static VariableTableEntry *add_local_var(CodeGen *codegen, AstNode *node, Buf *n | ... | @@ -697,10 +824,10 @@ static VariableTableEntry *add_local_var(CodeGen *codegen, AstNode *node, Buf *n |
| 697 | } | 824 | } |
| 698 | | 825 | |
| 699 | // Set name to nullptr to make the variable anonymous (not visible to programmer). | 826 | // Set name to nullptr to make the variable anonymous (not visible to programmer). |
| 700 | static VariableTableEntry *ir_add_local_var(IrBuilder *irb, AstNode *node, Buf *name, | 827 | static VariableTableEntry *ir_add_local_var(IrBuilder *irb, AstNode *node, BlockContext *scope, Buf *name, |
| 701 | bool is_const, bool is_shadowable) | 828 | bool is_const, bool is_shadowable) |
| 702 | { | 829 | { |
| 703 | VariableTableEntry *var = add_local_var(irb->codegen, node, name, is_const, is_shadowable); | 830 | VariableTableEntry *var = add_local_var(irb->codegen, node, scope, name, is_const, is_shadowable); |
| 704 | var->mem_slot_index = exec_next_mem_slot(irb->exec); | 831 | var->mem_slot_index = exec_next_mem_slot(irb->exec); |
| 705 | return var; | 832 | return var; |
| 706 | } | 833 | } |
| ... | @@ -963,6 +1090,23 @@ static IrInstruction *ir_gen_array_access(IrBuilder *irb, AstNode *node, LValPur | ... | @@ -963,6 +1090,23 @@ static IrInstruction *ir_gen_array_access(IrBuilder *irb, AstNode *node, LValPur |
| 963 | return ir_build_load_ptr(irb, node, ptr_instruction); | 1090 | return ir_build_load_ptr(irb, node, ptr_instruction); |
| 964 | } | 1091 | } |
| 965 | | 1092 | |
| | 1093 | static IrInstruction *ir_gen_field_access(IrBuilder *irb, AstNode *node, LValPurpose lval) { |
| | 1094 | assert(node->type == NodeTypeFieldAccessExpr); |
| | 1095 | |
| | 1096 | AstNode *container_ref_node = node->data.field_access_expr.struct_expr; |
| | 1097 | Buf *field_name = node->data.field_access_expr.field_name; |
| | 1098 | |
| | 1099 | IrInstruction *container_ref_instruction = ir_gen_node(irb, container_ref_node, node->block_context); |
| | 1100 | if (container_ref_instruction == irb->codegen->invalid_instruction) |
| | 1101 | return container_ref_instruction; |
| | 1102 | |
| | 1103 | if (lval == LValPurposeNone) { |
| | 1104 | return ir_build_read_field(irb, node, container_ref_instruction, field_name); |
| | 1105 | } else { |
| | 1106 | return ir_build_field_ptr(irb, node, container_ref_instruction, field_name); |
| | 1107 | } |
| | 1108 | } |
| | 1109 | |
| 966 | static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, AstNode *node) { | 1110 | static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, AstNode *node) { |
| 967 | assert(node->type == NodeTypeFnCallExpr); | 1111 | assert(node->type == NodeTypeFnCallExpr); |
| 968 | | 1112 | |
| ... | @@ -990,6 +1134,12 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, AstNode *node) { | ... | @@ -990,6 +1134,12 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, AstNode *node) { |
| 990 | | 1134 | |
| 991 | if (builtin_fn->id == BuiltinFnIdUnreachable) { | 1135 | if (builtin_fn->id == BuiltinFnIdUnreachable) { |
| 992 | return ir_build_unreachable(irb, node); | 1136 | return ir_build_unreachable(irb, node); |
| | 1137 | } else if (builtin_fn->id == BuiltinFnIdTypeof) { |
| | 1138 | AstNode *arg_node = node->data.fn_call_expr.params.at(0); |
| | 1139 | IrInstruction *arg = ir_gen_node(irb, arg_node, node->block_context); |
| | 1140 | if (arg == irb->codegen->invalid_instruction) |
| | 1141 | return arg; |
| | 1142 | return ir_build_typeof(irb, node, arg); |
| 993 | } | 1143 | } |
| 994 | | 1144 | |
| 995 | IrInstruction **args = allocate<IrInstruction *>(actual_param_count); | 1145 | IrInstruction **args = allocate<IrInstruction *>(actual_param_count); |
| ... | @@ -1183,7 +1333,8 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, AstNode *node) { | ... | @@ -1183,7 +1333,8 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, AstNode *node) { |
| 1183 | bool is_shadowable = false; | 1333 | bool is_shadowable = false; |
| 1184 | bool is_const = variable_declaration->is_const; | 1334 | bool is_const = variable_declaration->is_const; |
| 1185 | bool is_extern = variable_declaration->is_extern; | 1335 | bool is_extern = variable_declaration->is_extern; |
| 1186 | VariableTableEntry *var = ir_add_local_var(irb, node, variable_declaration->symbol, is_const, is_shadowable); | 1336 | VariableTableEntry *var = ir_add_local_var(irb, node, node->block_context, |
| | 1337 | variable_declaration->symbol, is_const, is_shadowable); |
| 1187 | | 1338 | |
| 1188 | if (!is_extern && !variable_declaration->expr) { | 1339 | if (!is_extern && !variable_declaration->expr) { |
| 1189 | var->type = irb->codegen->builtin_types.entry_invalid; | 1340 | var->type = irb->codegen->builtin_types.entry_invalid; |
| ... | @@ -1232,6 +1383,102 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, AstNode *node) { | ... | @@ -1232,6 +1383,102 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, AstNode *node) { |
| 1232 | return ir_build_const_void(irb, node); | 1383 | return ir_build_const_void(irb, node); |
| 1233 | } | 1384 | } |
| 1234 | | 1385 | |
| | 1386 | static IrInstruction *ir_gen_for_expr(IrBuilder *irb, AstNode *node) { |
| | 1387 | assert(node->type == NodeTypeForExpr); |
| | 1388 | |
| | 1389 | BlockContext *parent_scope = node->block_context; |
| | 1390 | |
| | 1391 | AstNode *array_node = node->data.for_expr.array_expr; |
| | 1392 | AstNode *elem_node = node->data.for_expr.elem_node; |
| | 1393 | AstNode *index_node = node->data.for_expr.index_node; |
| | 1394 | AstNode *body_node = node->data.for_expr.body; |
| | 1395 | |
| | 1396 | if (!elem_node) { |
| | 1397 | add_node_error(irb->codegen, node, buf_sprintf("for loop expression missing element parameter")); |
| | 1398 | return irb->codegen->invalid_instruction; |
| | 1399 | } |
| | 1400 | assert(elem_node->type == NodeTypeSymbol); |
| | 1401 | |
| | 1402 | IrInstruction *array_val = ir_gen_node(irb, array_node, parent_scope); |
| | 1403 | if (array_val == irb->codegen->invalid_instruction) |
| | 1404 | return array_val; |
| | 1405 | |
| | 1406 | IrInstruction *array_type = ir_build_typeof(irb, array_node, array_val); |
| | 1407 | IrInstruction *pointer_type = ir_build_to_ptr_type(irb, array_node, array_type); |
| | 1408 | IrInstruction *elem_var_type; |
| | 1409 | if (node->data.for_expr.elem_is_ptr) { |
| | 1410 | elem_var_type = pointer_type; |
| | 1411 | } else { |
| | 1412 | elem_var_type = ir_build_ptr_type_child(irb, elem_node, pointer_type); |
| | 1413 | } |
| | 1414 | |
| | 1415 | BlockContext *child_scope = new_block_context(node, parent_scope); |
| | 1416 | child_scope->parent_loop_node = node; |
| | 1417 | elem_node->block_context = child_scope; |
| | 1418 | |
| | 1419 | // TODO make it an error to write to element variable or i variable. |
| | 1420 | |
| | 1421 | Buf *elem_var_name = elem_node->data.symbol_expr.symbol; |
| | 1422 | node->data.for_expr.elem_var = ir_add_local_var(irb, elem_node, child_scope, elem_var_name, false, false); |
| | 1423 | IrInstruction *undefined_value = ir_build_const_undefined(irb, elem_node); |
| | 1424 | ir_build_var_decl(irb, elem_node, node->data.for_expr.elem_var, elem_var_type, undefined_value); |
| | 1425 | IrInstruction *elem_var_ptr = ir_build_var_ptr(irb, node, node->data.for_expr.elem_var); |
| | 1426 | |
| | 1427 | if (index_node) { |
| | 1428 | Buf *index_var_name = index_node->data.symbol_expr.symbol; |
| | 1429 | index_node->block_context = child_scope; |
| | 1430 | node->data.for_expr.index_var = ir_add_local_var(irb, index_node, child_scope, index_var_name, false, false); |
| | 1431 | } else { |
| | 1432 | node->data.for_expr.index_var = ir_add_local_var(irb, node, child_scope, nullptr, false, true); |
| | 1433 | } |
| | 1434 | IrInstruction *usize = ir_build_const_type(irb, node, irb->codegen->builtin_types.entry_usize); |
| | 1435 | IrInstruction *zero = ir_build_const_usize(irb, node, 0); |
| | 1436 | IrInstruction *one = ir_build_const_usize(irb, node, 1); |
| | 1437 | ir_build_var_decl(irb, index_node, node->data.for_expr.index_var, usize, zero); |
| | 1438 | IrInstruction *index_ptr = ir_build_var_ptr(irb, node, node->data.for_expr.index_var); |
| | 1439 | |
| | 1440 | |
| | 1441 | IrBasicBlock *cond_block = ir_build_basic_block(irb, "ForCond"); |
| | 1442 | IrBasicBlock *body_block = ir_build_basic_block(irb, "ForBody"); |
| | 1443 | IrBasicBlock *end_block = ir_build_basic_block(irb, "ForEnd"); |
| | 1444 | IrBasicBlock *continue_block = ir_build_basic_block(irb, "ForContinue"); |
| | 1445 | |
| | 1446 | IrInstruction *len_val = ir_build_read_field(irb, node, array_val, irb->codegen->len_buf); |
| | 1447 | ir_build_br(irb, node, cond_block); |
| | 1448 | |
| | 1449 | ir_set_cursor_at_end(irb, cond_block); |
| | 1450 | IrInstruction *index_val = ir_build_load_ptr(irb, node, index_ptr); |
| | 1451 | IrInstruction *cond = ir_build_bin_op(irb, node, IrBinOpCmpLessThan, index_val, len_val); |
| | 1452 | ir_build_cond_br(irb, node, cond, body_block, end_block); |
| | 1453 | |
| | 1454 | ir_set_cursor_at_end(irb, body_block); |
| | 1455 | IrInstruction *elem_ptr = ir_build_elem_ptr(irb, node, array_val, index_val); |
| | 1456 | IrInstruction *elem_val; |
| | 1457 | if (node->data.for_expr.elem_is_ptr) { |
| | 1458 | elem_val = elem_ptr; |
| | 1459 | } else { |
| | 1460 | elem_val = ir_build_load_ptr(irb, node, elem_ptr); |
| | 1461 | } |
| | 1462 | ir_build_store_ptr(irb, node, elem_var_ptr, elem_val); |
| | 1463 | |
| | 1464 | irb->break_block_stack.append(end_block); |
| | 1465 | irb->continue_block_stack.append(continue_block); |
| | 1466 | ir_gen_node(irb, body_node, child_scope); |
| | 1467 | irb->break_block_stack.pop(); |
| | 1468 | irb->continue_block_stack.pop(); |
| | 1469 | |
| | 1470 | ir_build_br(irb, node, continue_block); |
| | 1471 | |
| | 1472 | ir_set_cursor_at_end(irb, continue_block); |
| | 1473 | IrInstruction *new_index_val = ir_build_bin_op(irb, node, IrBinOpAdd, index_val, one); |
| | 1474 | ir_build_store_ptr(irb, node, index_ptr, new_index_val); |
| | 1475 | ir_build_br(irb, node, cond_block); |
| | 1476 | |
| | 1477 | ir_set_cursor_at_end(irb, end_block); |
| | 1478 | return ir_build_const_void(irb, node); |
| | 1479 | |
| | 1480 | } |
| | 1481 | |
| 1235 | static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockContext *block_context, | 1482 | static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockContext *block_context, |
| 1236 | LValPurpose lval) | 1483 | LValPurpose lval) |
| 1237 | { | 1484 | { |
| ... | @@ -1259,16 +1506,18 @@ static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockCont | ... | @@ -1259,16 +1506,18 @@ static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockCont |
| 1259 | return ir_gen_var_decl(irb, node); | 1506 | return ir_gen_var_decl(irb, node); |
| 1260 | case NodeTypeWhileExpr: | 1507 | case NodeTypeWhileExpr: |
| 1261 | return ir_gen_while_expr(irb, node); | 1508 | return ir_gen_while_expr(irb, node); |
| | 1509 | case NodeTypeForExpr: |
| | 1510 | return ir_gen_for_expr(irb, node); |
| 1262 | case NodeTypeArrayAccessExpr: | 1511 | case NodeTypeArrayAccessExpr: |
| 1263 | return ir_gen_array_access(irb, node, lval); | 1512 | return ir_gen_array_access(irb, node, lval); |
| 1264 | case NodeTypeReturnExpr: | 1513 | case NodeTypeReturnExpr: |
| 1265 | return ir_gen_return(irb, node); | 1514 | return ir_gen_return(irb, node); |
| | 1515 | case NodeTypeFieldAccessExpr: |
| | 1516 | return ir_gen_field_access(irb, node, lval); |
| 1266 | case NodeTypeUnwrapErrorExpr: | 1517 | case NodeTypeUnwrapErrorExpr: |
| 1267 | case NodeTypeDefer: | 1518 | case NodeTypeDefer: |
| 1268 | case NodeTypeSliceExpr: | 1519 | case NodeTypeSliceExpr: |
| 1269 | case NodeTypeFieldAccessExpr: | | |
| 1270 | case NodeTypeIfVarExpr: | 1520 | case NodeTypeIfVarExpr: |
| 1271 | case NodeTypeForExpr: | | |
| 1272 | case NodeTypeAsmExpr: | 1521 | case NodeTypeAsmExpr: |
| 1273 | case NodeTypeGoto: | 1522 | case NodeTypeGoto: |
| 1274 | case NodeTypeBreak: | 1523 | case NodeTypeBreak: |
| ... | @@ -1587,6 +1836,12 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira, | ... | @@ -1587,6 +1836,12 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira, |
| 1587 | } | 1836 | } |
| 1588 | } | 1837 | } |
| 1589 | | 1838 | |
| | 1839 | // implicit undefined literal to anything |
| | 1840 | if (actual_type->id == TypeTableEntryIdUndefLit) { |
| | 1841 | return ImplicitCastMatchResultYes; |
| | 1842 | } |
| | 1843 | |
| | 1844 | |
| 1590 | return ImplicitCastMatchResultNo; | 1845 | return ImplicitCastMatchResultNo; |
| 1591 | } | 1846 | } |
| 1592 | | 1847 | |
| ... | @@ -1661,6 +1916,45 @@ static ConstExprValue *ir_get_out_val(IrInstruction *instruction) { | ... | @@ -1661,6 +1916,45 @@ static ConstExprValue *ir_get_out_val(IrInstruction *instruction) { |
| 1661 | return &instruction->static_value; | 1916 | return &instruction->static_value; |
| 1662 | } | 1917 | } |
| 1663 | | 1918 | |
| | 1919 | static TypeTableEntry *ir_analyze_void(IrAnalyze *ira, IrInstruction *instruction) { |
| | 1920 | ConstExprValue *const_val = ir_get_out_val(instruction); |
| | 1921 | const_val->ok = true; |
| | 1922 | return ira->codegen->builtin_types.entry_void; |
| | 1923 | } |
| | 1924 | |
| | 1925 | static TypeTableEntry *ir_analyze_const_usize(IrAnalyze *ira, IrInstruction *instruction, uint64_t value, |
| | 1926 | bool depends_on_compile_var) |
| | 1927 | { |
| | 1928 | ConstExprValue *const_val = ir_get_out_val(instruction); |
| | 1929 | const_val->ok = true; |
| | 1930 | const_val->depends_on_compile_var = depends_on_compile_var; |
| | 1931 | bignum_init_unsigned(&const_val->data.x_bignum, value); |
| | 1932 | return ira->codegen->builtin_types.entry_usize; |
| | 1933 | } |
| | 1934 | |
| | 1935 | static TypeTableEntry *ir_resolve_type(IrAnalyze *ira, IrInstruction *type_value) { |
| | 1936 | if (type_value == ira->codegen->invalid_instruction) |
| | 1937 | return ira->codegen->builtin_types.entry_invalid; |
| | 1938 | |
| | 1939 | if (type_value->type_entry->id == TypeTableEntryIdInvalid) |
| | 1940 | return ira->codegen->builtin_types.entry_invalid; |
| | 1941 | |
| | 1942 | if (type_value->type_entry->id != TypeTableEntryIdMetaType) { |
| | 1943 | add_node_error(ira->codegen, type_value->source_node, |
| | 1944 | buf_sprintf("expected type 'type', found '%s'", buf_ptr(&type_value->type_entry->name))); |
| | 1945 | return ira->codegen->builtin_types.entry_invalid; |
| | 1946 | } |
| | 1947 | |
| | 1948 | ConstExprValue *const_val = &type_value->static_value; |
| | 1949 | if (!const_val->ok) { |
| | 1950 | add_node_error(ira->codegen, type_value->source_node, |
| | 1951 | buf_sprintf("unable to evaluate constant expression")); |
| | 1952 | return ira->codegen->builtin_types.entry_invalid; |
| | 1953 | } |
| | 1954 | |
| | 1955 | return const_val->data.x_type; |
| | 1956 | } |
| | 1957 | |
| 1664 | static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr, | 1958 | static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr, |
| 1665 | IrInstruction *dest_type, IrInstruction *value) | 1959 | IrInstruction *dest_type, IrInstruction *value) |
| 1666 | { | 1960 | { |
| ... | @@ -1911,6 +2205,11 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -1911,6 +2205,11 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 1911 | return ir_resolve_cast(ira, source_instr, value, dest_type, CastOpEnumToInt, false); | 2205 | return ir_resolve_cast(ira, source_instr, value, dest_type, CastOpEnumToInt, false); |
| 1912 | } | 2206 | } |
| 1913 | | 2207 | |
| | 2208 | // explicit cast from undefined to anything |
| | 2209 | if (actual_type->id == TypeTableEntryIdUndefLit) { |
| | 2210 | return ir_resolve_cast(ira, source_instr, value, dest_type, CastOpNoop, false); |
| | 2211 | } |
| | 2212 | |
| 1914 | add_node_error(ira->codegen, source_instr->source_node, | 2213 | add_node_error(ira->codegen, source_instr->source_node, |
| 1915 | buf_sprintf("invalid cast from type '%s' to '%s'", | 2214 | buf_sprintf("invalid cast from type '%s' to '%s'", |
| 1916 | buf_ptr(&actual_type->name), | 2215 | buf_ptr(&actual_type->name), |
| ... | @@ -1918,26 +2217,6 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -1918,26 +2217,6 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 1918 | return ira->codegen->invalid_instruction; | 2217 | return ira->codegen->invalid_instruction; |
| 1919 | } | 2218 | } |
| 1920 | | 2219 | |
| 1921 | static TypeTableEntry *ir_get_canonical_type(IrAnalyze *ira, IrInstruction *type_value) { | | |
| 1922 | if (type_value == ira->codegen->invalid_instruction) | | |
| 1923 | return ira->codegen->builtin_types.entry_invalid; | | |
| 1924 | | | |
| 1925 | if (type_value->type_entry->id == TypeTableEntryIdInvalid) | | |
| 1926 | return ira->codegen->builtin_types.entry_invalid; | | |
| 1927 | | | |
| 1928 | if (type_value->type_entry->id != TypeTableEntryIdMetaType) { | | |
| 1929 | add_node_error(ira->codegen, type_value->source_node, buf_sprintf("expected type, found expression")); | | |
| 1930 | return ira->codegen->builtin_types.entry_invalid; | | |
| 1931 | } | | |
| 1932 | | | |
| 1933 | if (!type_value->static_value.ok) { | | |
| 1934 | add_node_error(ira->codegen, type_value->source_node, buf_sprintf("unable to evaluate constant expression")); | | |
| 1935 | return ira->codegen->builtin_types.entry_invalid; | | |
| 1936 | } | | |
| 1937 | | | |
| 1938 | return get_underlying_type(type_value->static_value.data.x_type); | | |
| 1939 | } | | |
| 1940 | | | |
| 1941 | static IrInstruction *ir_get_casted_value(IrAnalyze *ira, IrInstruction *value, TypeTableEntry *expected_type) { | 2220 | static IrInstruction *ir_get_casted_value(IrAnalyze *ira, IrInstruction *value, TypeTableEntry *expected_type) { |
| 1942 | assert(value); | 2221 | assert(value); |
| 1943 | assert(value != ira->codegen->invalid_instruction); | 2222 | assert(value != ira->codegen->invalid_instruction); |
| ... | @@ -1976,14 +2255,22 @@ static IrInstruction *ir_get_casted_value(IrAnalyze *ira, IrInstruction *value, | ... | @@ -1976,14 +2255,22 @@ static IrInstruction *ir_get_casted_value(IrAnalyze *ira, IrInstruction *value, |
| 1976 | static TypeTableEntry *ir_analyze_instruction_return(IrAnalyze *ira, | 2255 | static TypeTableEntry *ir_analyze_instruction_return(IrAnalyze *ira, |
| 1977 | IrInstructionReturn *return_instruction) | 2256 | IrInstructionReturn *return_instruction) |
| 1978 | { | 2257 | { |
| 1979 | IrInstruction *value = ir_get_casted_value(ira, return_instruction->value->other, ira->explicit_return_type); | 2258 | IrInstruction *value = return_instruction->value->other; |
| 1980 | if (value == ira->codegen->invalid_instruction) | 2259 | if (value == ira->codegen->invalid_instruction) { |
| 1981 | return ira->codegen->builtin_types.entry_invalid; | 2260 | ir_finish_bb(ira); |
| | 2261 | return ira->codegen->builtin_types.entry_unreachable; |
| | 2262 | } |
| 1982 | ira->implicit_return_type_list.append(value); | 2263 | ira->implicit_return_type_list.append(value); |
| 1983 | | 2264 | |
| 1984 | IrInstruction *new_instruction = ir_build_return_from(&ira->new_irb, &return_instruction->base, value); | 2265 | IrInstruction *casted_value = ir_get_casted_value(ira, value, ira->explicit_return_type); |
| | 2266 | if (casted_value == ira->codegen->invalid_instruction) { |
| | 2267 | ir_finish_bb(ira); |
| | 2268 | return ira->codegen->builtin_types.entry_unreachable; |
| | 2269 | } |
| | 2270 | |
| | 2271 | ir_build_return_from(&ira->new_irb, &return_instruction->base, casted_value); |
| 1985 | ir_finish_bb(ira); | 2272 | ir_finish_bb(ira); |
| 1986 | return new_instruction->type_entry; | 2273 | return ira->codegen->builtin_types.entry_unreachable; |
| 1987 | } | 2274 | } |
| 1988 | | 2275 | |
| 1989 | static TypeTableEntry *ir_analyze_instruction_const(IrAnalyze *ira, IrInstructionConst *const_instruction) { | 2276 | static TypeTableEntry *ir_analyze_instruction_const(IrAnalyze *ira, IrInstructionConst *const_instruction) { |
| ... | @@ -2354,6 +2641,10 @@ static TypeTableEntry *ir_analyze_instruction_bin_op(IrAnalyze *ira, IrInstructi | ... | @@ -2354,6 +2641,10 @@ static TypeTableEntry *ir_analyze_instruction_bin_op(IrAnalyze *ira, IrInstructi |
| 2354 | } | 2641 | } |
| 2355 | | 2642 | |
| 2356 | static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstructionDeclVar *decl_var_instruction) { | 2643 | static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstructionDeclVar *decl_var_instruction) { |
| | 2644 | IrInstruction *init_value = decl_var_instruction->init_value->other; |
| | 2645 | if (init_value->type_entry->id == TypeTableEntryIdInvalid) |
| | 2646 | return init_value->type_entry; |
| | 2647 | |
| 2357 | VariableTableEntry *var = decl_var_instruction->var; | 2648 | VariableTableEntry *var = decl_var_instruction->var; |
| 2358 | AstNodeVariableDeclaration *variable_declaration = &var->decl_node->data.variable_declaration; | 2649 | AstNodeVariableDeclaration *variable_declaration = &var->decl_node->data.variable_declaration; |
| 2359 | bool is_export = (variable_declaration->top_level_decl.visib_mod == VisibModExport); | 2650 | bool is_export = (variable_declaration->top_level_decl.visib_mod == VisibModExport); |
| ... | @@ -2365,13 +2656,12 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc | ... | @@ -2365,13 +2656,12 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc |
| 2365 | IrInstruction *var_type = nullptr; | 2656 | IrInstruction *var_type = nullptr; |
| 2366 | if (decl_var_instruction->var_type != nullptr) { | 2657 | if (decl_var_instruction->var_type != nullptr) { |
| 2367 | var_type = decl_var_instruction->var_type->other; | 2658 | var_type = decl_var_instruction->var_type->other; |
| 2368 | TypeTableEntry *proposed_type = ir_get_canonical_type(ira, var_type); | 2659 | TypeTableEntry *proposed_type = ir_resolve_type(ira, var_type); |
| 2369 | explicit_type = validate_var_type(ira->codegen, var_type->source_node, proposed_type); | 2660 | explicit_type = validate_var_type(ira->codegen, var_type->source_node, proposed_type); |
| 2370 | if (explicit_type->id == TypeTableEntryIdInvalid) | 2661 | if (explicit_type->id == TypeTableEntryIdInvalid) |
| 2371 | return explicit_type; | 2662 | return explicit_type; |
| 2372 | } | 2663 | } |
| 2373 | | 2664 | |
| 2374 | IrInstruction *init_value = decl_var_instruction->init_value->other; | | |
| 2375 | IrInstruction *casted_init_value = ir_get_casted_value(ira, init_value, explicit_type); | 2665 | IrInstruction *casted_init_value = ir_get_casted_value(ira, init_value, explicit_type); |
| 2376 | TypeTableEntry *result_type = get_underlying_type(casted_init_value->type_entry); | 2666 | TypeTableEntry *result_type = get_underlying_type(casted_init_value->type_entry); |
| 2377 | switch (result_type->id) { | 2667 | switch (result_type->id) { |
| ... | @@ -2423,7 +2713,7 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc | ... | @@ -2423,7 +2713,7 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc |
| 2423 | } | 2713 | } |
| 2424 | | 2714 | |
| 2425 | var->type = result_type; | 2715 | var->type = result_type; |
| 2426 | assert(var->type != nullptr); // should have been caught by the parser | 2716 | assert(var->type); |
| 2427 | | 2717 | |
| 2428 | ConstExprValue *mem_slot = &ira->exec_context.mem_slot_list[var->mem_slot_index]; | 2718 | ConstExprValue *mem_slot = &ira->exec_context.mem_slot_list[var->mem_slot_index]; |
| 2429 | *mem_slot = casted_init_value->static_value; | 2719 | *mem_slot = casted_init_value->static_value; |
| ... | @@ -3480,44 +3770,6 @@ static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructio | ... | @@ -3480,44 +3770,6 @@ static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructio |
| 3480 | // return g->builtin_types.entry_invalid; | 3770 | // return g->builtin_types.entry_invalid; |
| 3481 | // } | 3771 | // } |
| 3482 | // } | 3772 | // } |
| 3483 | // case BuiltinFnIdTypeof: | | |
| 3484 | // { | | |
| 3485 | // AstNode *expr_node = node->data.fn_call_expr.params.at(0); | | |
| 3486 | // TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, expr_node); | | |
| 3487 | // | | |
| 3488 | // switch (type_entry->id) { | | |
| 3489 | // case TypeTableEntryIdInvalid: | | |
| 3490 | // return type_entry; | | |
| 3491 | // case TypeTableEntryIdNumLitFloat: | | |
| 3492 | // case TypeTableEntryIdNumLitInt: | | |
| 3493 | // case TypeTableEntryIdUndefLit: | | |
| 3494 | // case TypeTableEntryIdNullLit: | | |
| 3495 | // case TypeTableEntryIdNamespace: | | |
| 3496 | // case TypeTableEntryIdBlock: | | |
| 3497 | // case TypeTableEntryIdGenericFn: | | |
| 3498 | // case TypeTableEntryIdVar: | | |
| 3499 | // add_node_error(g, expr_node, | | |
| 3500 | // buf_sprintf("type '%s' not eligible for @typeOf", buf_ptr(&type_entry->name))); | | |
| 3501 | // return g->builtin_types.entry_invalid; | | |
| 3502 | // case TypeTableEntryIdMetaType: | | |
| 3503 | // case TypeTableEntryIdVoid: | | |
| 3504 | // case TypeTableEntryIdBool: | | |
| 3505 | // case TypeTableEntryIdUnreachable: | | |
| 3506 | // case TypeTableEntryIdInt: | | |
| 3507 | // case TypeTableEntryIdFloat: | | |
| 3508 | // case TypeTableEntryIdPointer: | | |
| 3509 | // case TypeTableEntryIdArray: | | |
| 3510 | // case TypeTableEntryIdStruct: | | |
| 3511 | // case TypeTableEntryIdMaybe: | | |
| 3512 | // case TypeTableEntryIdErrorUnion: | | |
| 3513 | // case TypeTableEntryIdPureError: | | |
| 3514 | // case TypeTableEntryIdEnum: | | |
| 3515 | // case TypeTableEntryIdUnion: | | |
| 3516 | // case TypeTableEntryIdFn: | | |
| 3517 | // case TypeTableEntryIdTypeDecl: | | |
| 3518 | // return resolve_expr_const_val_as_type(g, node, type_entry, false); | | |
| 3519 | // } | | |
| 3520 | // } | | |
| 3521 | // case BuiltinFnIdCInclude: | 3773 | // case BuiltinFnIdCInclude: |
| 3522 | // { | 3774 | // { |
| 3523 | // if (!context->c_import_buf) { | 3775 | // if (!context->c_import_buf) { |
| ... | @@ -3867,8 +4119,10 @@ static TypeTableEntry *ir_analyze_instruction_br(IrAnalyze *ira, IrInstructionBr | ... | @@ -3867,8 +4119,10 @@ static TypeTableEntry *ir_analyze_instruction_br(IrAnalyze *ira, IrInstructionBr |
| 3867 | static TypeTableEntry *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructionCondBr *cond_br_instruction) { | 4119 | static TypeTableEntry *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructionCondBr *cond_br_instruction) { |
| 3868 | TypeTableEntry *bool_type = ira->codegen->builtin_types.entry_bool; | 4120 | TypeTableEntry *bool_type = ira->codegen->builtin_types.entry_bool; |
| 3869 | IrInstruction *condition = ir_get_casted_value(ira, cond_br_instruction->condition->other, bool_type); | 4121 | IrInstruction *condition = ir_get_casted_value(ira, cond_br_instruction->condition->other, bool_type); |
| 3870 | if (condition == ira->codegen->invalid_instruction) | 4122 | if (condition == ira->codegen->invalid_instruction) { |
| 3871 | return ira->codegen->builtin_types.entry_invalid; | 4123 | ir_finish_bb(ira); |
| | 4124 | return ira->codegen->builtin_types.entry_unreachable; |
| | 4125 | } |
| 3872 | | 4126 | |
| 3873 | // TODO detect backward jumps | 4127 | // TODO detect backward jumps |
| 3874 | if (condition->static_value.ok) { | 4128 | if (condition->static_value.ok) { |
| ... | @@ -3892,6 +4146,7 @@ static TypeTableEntry *ir_analyze_instruction_builtin_call(IrAnalyze *ira, | ... | @@ -3892,6 +4146,7 @@ static TypeTableEntry *ir_analyze_instruction_builtin_call(IrAnalyze *ira, |
| 3892 | switch (builtin_call_instruction->fn->id) { | 4146 | switch (builtin_call_instruction->fn->id) { |
| 3893 | case BuiltinFnIdInvalid: | 4147 | case BuiltinFnIdInvalid: |
| 3894 | case BuiltinFnIdUnreachable: | 4148 | case BuiltinFnIdUnreachable: |
| | 4149 | case BuiltinFnIdTypeof: |
| 3895 | zig_unreachable(); | 4150 | zig_unreachable(); |
| 3896 | case BuiltinFnIdMemcpy: | 4151 | case BuiltinFnIdMemcpy: |
| 3897 | case BuiltinFnIdMemset: | 4152 | case BuiltinFnIdMemset: |
| ... | @@ -3900,7 +4155,6 @@ static TypeTableEntry *ir_analyze_instruction_builtin_call(IrAnalyze *ira, | ... | @@ -3900,7 +4155,6 @@ static TypeTableEntry *ir_analyze_instruction_builtin_call(IrAnalyze *ira, |
| 3900 | case BuiltinFnIdMaxValue: | 4155 | case BuiltinFnIdMaxValue: |
| 3901 | case BuiltinFnIdMinValue: | 4156 | case BuiltinFnIdMinValue: |
| 3902 | case BuiltinFnIdMemberCount: | 4157 | case BuiltinFnIdMemberCount: |
| 3903 | case BuiltinFnIdTypeof: | | |
| 3904 | case BuiltinFnIdAddWithOverflow: | 4158 | case BuiltinFnIdAddWithOverflow: |
| 3905 | case BuiltinFnIdSubWithOverflow: | 4159 | case BuiltinFnIdSubWithOverflow: |
| 3906 | case BuiltinFnIdMulWithOverflow: | 4160 | case BuiltinFnIdMulWithOverflow: |
| ... | @@ -3938,9 +4192,9 @@ static TypeTableEntry *ir_analyze_instruction_builtin_call(IrAnalyze *ira, | ... | @@ -3938,9 +4192,9 @@ static TypeTableEntry *ir_analyze_instruction_builtin_call(IrAnalyze *ira, |
| 3938 | static TypeTableEntry *ir_analyze_instruction_unreachable(IrAnalyze *ira, | 4192 | static TypeTableEntry *ir_analyze_instruction_unreachable(IrAnalyze *ira, |
| 3939 | IrInstructionUnreachable *unreachable_instruction) | 4193 | IrInstructionUnreachable *unreachable_instruction) |
| 3940 | { | 4194 | { |
| 3941 | IrInstruction *new_instruction = ir_build_unreachable_from(&ira->new_irb, &unreachable_instruction->base); | 4195 | ir_build_unreachable_from(&ira->new_irb, &unreachable_instruction->base); |
| 3942 | ir_finish_bb(ira); | 4196 | ir_finish_bb(ira); |
| 3943 | return new_instruction->type_entry; | 4197 | return ira->codegen->builtin_types.entry_unreachable; |
| 3944 | } | 4198 | } |
| 3945 | | 4199 | |
| 3946 | static TypeTableEntry *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPhi *phi_instruction) { | 4200 | static TypeTableEntry *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPhi *phi_instruction) { |
| ... | @@ -3997,7 +4251,10 @@ static TypeTableEntry *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionP | ... | @@ -3997,7 +4251,10 @@ static TypeTableEntry *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionP |
| 3997 | | 4251 | |
| 3998 | static TypeTableEntry *ir_analyze_instruction_var_ptr(IrAnalyze *ira, IrInstructionVarPtr *var_ptr_instruction) { | 4252 | static TypeTableEntry *ir_analyze_instruction_var_ptr(IrAnalyze *ira, IrInstructionVarPtr *var_ptr_instruction) { |
| 3999 | VariableTableEntry *var = var_ptr_instruction->var; | 4253 | VariableTableEntry *var = var_ptr_instruction->var; |
| 4000 | TypeTableEntry *ptr_type = get_pointer_to_type(ira->codegen, var_ptr_instruction->var->type, false); | 4254 | if (var->type->id == TypeTableEntryIdInvalid) |
| | 4255 | return var->type; |
| | 4256 | |
| | 4257 | TypeTableEntry *ptr_type = get_pointer_to_type(ira->codegen, var->type, false); |
| 4001 | // TODO once the anlayze code is fully ported over to IR we won't need this SIZE_MAX thing. | 4258 | // TODO once the anlayze code is fully ported over to IR we won't need this SIZE_MAX thing. |
| 4002 | if (var->mem_slot_index != SIZE_MAX) { | 4259 | if (var->mem_slot_index != SIZE_MAX) { |
| 4003 | ConstExprValue *mem_slot = &ira->exec_context.mem_slot_list[var->mem_slot_index]; | 4260 | ConstExprValue *mem_slot = &ira->exec_context.mem_slot_list[var->mem_slot_index]; |
| ... | @@ -4057,6 +4314,159 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc | ... | @@ -4057,6 +4314,159 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc |
| 4057 | return return_type; | 4314 | return return_type; |
| 4058 | } | 4315 | } |
| 4059 | | 4316 | |
| | 4317 | static TypeTableEntry *ir_analyze_container_member_access_inner(IrAnalyze *ira, |
| | 4318 | TypeTableEntry *bare_struct_type, Buf *field_name, IrInstructionFieldPtr *field_ptr_instruction, |
| | 4319 | TypeTableEntry *container_type) |
| | 4320 | { |
| | 4321 | if (!is_slice(bare_struct_type)) { |
| | 4322 | BlockContext *container_block_context = get_container_block_context(bare_struct_type); |
| | 4323 | assert(container_block_context); |
| | 4324 | auto entry = container_block_context->decl_table.maybe_get(field_name); |
| | 4325 | AstNode *fn_decl_node = entry ? entry->value : nullptr; |
| | 4326 | if (fn_decl_node && fn_decl_node->type == NodeTypeFnProto) { |
| | 4327 | zig_panic("TODO member function call"); |
| | 4328 | } |
| | 4329 | } |
| | 4330 | add_node_error(ira->codegen, field_ptr_instruction->base.source_node, |
| | 4331 | buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name), buf_ptr(&bare_struct_type->name))); |
| | 4332 | return ira->codegen->builtin_types.entry_invalid; |
| | 4333 | } |
| | 4334 | |
| | 4335 | |
| | 4336 | static TypeTableEntry *ir_analyze_container_member_access(IrAnalyze *ira, Buf *field_name, |
| | 4337 | IrInstructionFieldPtr *field_ptr_instruction, TypeTableEntry *container_type) |
| | 4338 | { |
| | 4339 | IrInstruction *container_ptr = field_ptr_instruction->container_ptr->other; |
| | 4340 | TypeTableEntry *bare_type = container_ref_type(container_type); |
| | 4341 | if (!type_is_complete(bare_type)) { |
| | 4342 | resolve_container_type(ira->codegen, bare_type); |
| | 4343 | } |
| | 4344 | |
| | 4345 | if (bare_type->id == TypeTableEntryIdStruct) { |
| | 4346 | TypeStructField *field = find_struct_type_field(bare_type, field_name); |
| | 4347 | if (field) { |
| | 4348 | ir_build_struct_field_ptr_from(&ira->new_irb, &field_ptr_instruction->base, container_ptr, field); |
| | 4349 | return get_pointer_to_type(ira->codegen, field->type_entry, false); |
| | 4350 | } else { |
| | 4351 | return ir_analyze_container_member_access_inner(ira, bare_type, field_name, |
| | 4352 | field_ptr_instruction, container_type); |
| | 4353 | } |
| | 4354 | } else if (bare_type->id == TypeTableEntryIdEnum) { |
| | 4355 | zig_panic("TODO enum field ptr"); |
| | 4356 | } else if (bare_type->id == TypeTableEntryIdUnion) { |
| | 4357 | zig_panic("TODO"); |
| | 4358 | } else { |
| | 4359 | zig_unreachable(); |
| | 4360 | } |
| | 4361 | } |
| | 4362 | |
| | 4363 | static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstructionFieldPtr *field_ptr_instruction) { |
| | 4364 | IrInstruction *container_ptr = field_ptr_instruction->container_ptr->other; |
| | 4365 | Buf *field_name = field_ptr_instruction->field_name; |
| | 4366 | |
| | 4367 | TypeTableEntry *container_type = container_ptr->type_entry; |
| | 4368 | if (container_type->id == TypeTableEntryIdInvalid) { |
| | 4369 | return container_type; |
| | 4370 | } else if (is_container_ref(container_type)) { |
| | 4371 | return ir_analyze_container_member_access(ira, field_name, field_ptr_instruction, container_type); |
| | 4372 | } else if (container_type->id == TypeTableEntryIdArray) { |
| | 4373 | if (buf_eql_str(field_name, "len")) { |
| | 4374 | add_node_error(ira->codegen, field_ptr_instruction->base.source_node, |
| | 4375 | buf_sprintf("pointer to array length not available")); |
| | 4376 | return ira->codegen->builtin_types.entry_invalid; |
| | 4377 | } else { |
| | 4378 | add_node_error(ira->codegen, field_ptr_instruction->base.source_node, |
| | 4379 | buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name), |
| | 4380 | buf_ptr(&container_type->name))); |
| | 4381 | return ira->codegen->builtin_types.entry_invalid; |
| | 4382 | } |
| | 4383 | } else if (container_type->id == TypeTableEntryIdMetaType) { |
| | 4384 | TypeTableEntry *child_type = ir_resolve_type(ira, container_ptr); |
| | 4385 | |
| | 4386 | if (child_type->id == TypeTableEntryIdInvalid) { |
| | 4387 | return ira->codegen->builtin_types.entry_invalid; |
| | 4388 | } else if (child_type->id == TypeTableEntryIdEnum) { |
| | 4389 | zig_panic("TODO enum type field"); |
| | 4390 | } else if (child_type->id == TypeTableEntryIdStruct) { |
| | 4391 | zig_panic("TODO struct type field"); |
| | 4392 | } else if (child_type->id == TypeTableEntryIdPureError) { |
| | 4393 | zig_panic("TODO error type field"); |
| | 4394 | } else if (child_type->id == TypeTableEntryIdInt) { |
| | 4395 | zig_panic("TODO integer type field"); |
| | 4396 | } else { |
| | 4397 | add_node_error(ira->codegen, field_ptr_instruction->base.source_node, |
| | 4398 | buf_sprintf("type '%s' does not support field access", buf_ptr(&container_type->name))); |
| | 4399 | return ira->codegen->builtin_types.entry_invalid; |
| | 4400 | } |
| | 4401 | } else if (container_type->id == TypeTableEntryIdNamespace) { |
| | 4402 | zig_panic("TODO namespace field access"); |
| | 4403 | } else { |
| | 4404 | add_node_error(ira->codegen, field_ptr_instruction->base.source_node, |
| | 4405 | buf_sprintf("type '%s' does not support field access", buf_ptr(&container_type->name))); |
| | 4406 | return ira->codegen->builtin_types.entry_invalid; |
| | 4407 | } |
| | 4408 | } |
| | 4409 | |
| | 4410 | static TypeTableEntry *ir_analyze_read_field_as_ptr_load(IrAnalyze *ira, |
| | 4411 | IrInstructionReadField *read_field_instruction) |
| | 4412 | { |
| | 4413 | IrInstruction *old_field_ptr_inst = ir_build_field_ptr(&ira->old_irb, read_field_instruction->base.source_node, |
| | 4414 | read_field_instruction->container_ptr, read_field_instruction->field_name); |
| | 4415 | IrInstruction *old_load_ptr_inst = ir_build_load_ptr(&ira->old_irb, read_field_instruction->base.source_node, |
| | 4416 | old_field_ptr_inst); |
| | 4417 | ir_analyze_instruction(ira, old_field_ptr_inst); |
| | 4418 | TypeTableEntry *result_type = ir_analyze_instruction(ira, old_load_ptr_inst); |
| | 4419 | read_field_instruction->base.other = old_load_ptr_inst->other; |
| | 4420 | return result_type; |
| | 4421 | } |
| | 4422 | |
| | 4423 | static TypeTableEntry *ir_analyze_instruction_read_field(IrAnalyze *ira, |
| | 4424 | IrInstructionReadField *read_field_instruction) |
| | 4425 | { |
| | 4426 | IrInstruction *container_ptr = read_field_instruction->container_ptr->other; |
| | 4427 | Buf *field_name = read_field_instruction->field_name; |
| | 4428 | |
| | 4429 | TypeTableEntry *container_type = container_ptr->type_entry; |
| | 4430 | if (container_type->id == TypeTableEntryIdInvalid) { |
| | 4431 | return container_type; |
| | 4432 | } else if (is_container_ref(container_type)) { |
| | 4433 | return ir_analyze_read_field_as_ptr_load(ira, read_field_instruction); |
| | 4434 | } else if (container_type->id == TypeTableEntryIdArray) { |
| | 4435 | if (buf_eql_str(field_name, "len")) { |
| | 4436 | return ir_analyze_const_usize(ira, &read_field_instruction->base, container_type->data.array.len, false); |
| | 4437 | } else { |
| | 4438 | add_node_error(ira->codegen, read_field_instruction->base.source_node, |
| | 4439 | buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name), |
| | 4440 | buf_ptr(&container_type->name))); |
| | 4441 | return ira->codegen->builtin_types.entry_invalid; |
| | 4442 | } |
| | 4443 | } else if (container_type->id == TypeTableEntryIdMetaType) { |
| | 4444 | TypeTableEntry *child_type = ir_resolve_type(ira, container_ptr); |
| | 4445 | |
| | 4446 | if (child_type->id == TypeTableEntryIdInvalid) { |
| | 4447 | return ira->codegen->builtin_types.entry_invalid; |
| | 4448 | } else if (child_type->id == TypeTableEntryIdEnum) { |
| | 4449 | zig_panic("TODO enum type field"); |
| | 4450 | } else if (child_type->id == TypeTableEntryIdStruct) { |
| | 4451 | zig_panic("TODO struct type field"); |
| | 4452 | } else if (child_type->id == TypeTableEntryIdPureError) { |
| | 4453 | zig_panic("TODO error type field"); |
| | 4454 | } else if (child_type->id == TypeTableEntryIdInt) { |
| | 4455 | zig_panic("TODO integer type field"); |
| | 4456 | } else { |
| | 4457 | add_node_error(ira->codegen, read_field_instruction->base.source_node, |
| | 4458 | buf_sprintf("type '%s' does not support field access", buf_ptr(&container_type->name))); |
| | 4459 | return ira->codegen->builtin_types.entry_invalid; |
| | 4460 | } |
| | 4461 | } else if (container_type->id == TypeTableEntryIdNamespace) { |
| | 4462 | zig_panic("TODO namespace field access"); |
| | 4463 | } else { |
| | 4464 | add_node_error(ira->codegen, read_field_instruction->base.source_node, |
| | 4465 | buf_sprintf("type '%s' does not support field access", buf_ptr(&container_type->name))); |
| | 4466 | return ira->codegen->builtin_types.entry_invalid; |
| | 4467 | } |
| | 4468 | } |
| | 4469 | |
| 4060 | static TypeTableEntry *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstructionLoadPtr *load_ptr_instruction) { | 4470 | static TypeTableEntry *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstructionLoadPtr *load_ptr_instruction) { |
| 4061 | IrInstruction *ptr = load_ptr_instruction->ptr->other; | 4471 | IrInstruction *ptr = load_ptr_instruction->ptr->other; |
| 4062 | TypeTableEntry *type_entry = ptr->type_entry; | 4472 | TypeTableEntry *type_entry = ptr->type_entry; |
| ... | @@ -4084,7 +4494,12 @@ static TypeTableEntry *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstruc | ... | @@ -4084,7 +4494,12 @@ static TypeTableEntry *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstruc |
| 4084 | | 4494 | |
| 4085 | static TypeTableEntry *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstructionStorePtr *store_ptr_instruction) { | 4495 | static TypeTableEntry *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstructionStorePtr *store_ptr_instruction) { |
| 4086 | IrInstruction *ptr = store_ptr_instruction->ptr->other; | 4496 | IrInstruction *ptr = store_ptr_instruction->ptr->other; |
| | 4497 | if (ptr->type_entry->id == TypeTableEntryIdInvalid) |
| | 4498 | return ptr->type_entry; |
| | 4499 | |
| 4087 | IrInstruction *value = store_ptr_instruction->value->other; | 4500 | IrInstruction *value = store_ptr_instruction->value->other; |
| | 4501 | if (value->type_entry->id == TypeTableEntryIdInvalid) |
| | 4502 | return value->type_entry; |
| 4088 | | 4503 | |
| 4089 | TypeTableEntry *child_type = ptr->type_entry->data.pointer.child_type; | 4504 | TypeTableEntry *child_type = ptr->type_entry->data.pointer.child_type; |
| 4090 | IrInstruction *casted_value = ir_get_casted_value(ira, value, child_type); | 4505 | IrInstruction *casted_value = ir_get_casted_value(ira, value, child_type); |
| ... | @@ -4095,7 +4510,7 @@ static TypeTableEntry *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstru | ... | @@ -4095,7 +4510,7 @@ static TypeTableEntry *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstru |
| 4095 | ConstExprValue *dest_val = ptr->static_value.data.x_ptr.ptr[0]; | 4510 | ConstExprValue *dest_val = ptr->static_value.data.x_ptr.ptr[0]; |
| 4096 | if (dest_val->ok) { | 4511 | if (dest_val->ok) { |
| 4097 | *dest_val = casted_value->static_value; | 4512 | *dest_val = casted_value->static_value; |
| 4098 | return ira->codegen->builtin_types.entry_void; | 4513 | return ir_analyze_void(ira, &store_ptr_instruction->base); |
| 4099 | } | 4514 | } |
| 4100 | } | 4515 | } |
| 4101 | | 4516 | |
| ... | @@ -4120,13 +4535,108 @@ static TypeTableEntry *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstru | ... | @@ -4120,13 +4535,108 @@ static TypeTableEntry *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstru |
| 4120 | } | 4535 | } |
| 4121 | new_ptr_inst->type_entry = ptr->type_entry; | 4536 | new_ptr_inst->type_entry = ptr->type_entry; |
| 4122 | ir_build_store_ptr(&ira->new_irb, store_ptr_instruction->base.source_node, new_ptr_inst, casted_value); | 4537 | ir_build_store_ptr(&ira->new_irb, store_ptr_instruction->base.source_node, new_ptr_inst, casted_value); |
| 4123 | return ira->codegen->builtin_types.entry_void; | 4538 | return ir_analyze_void(ira, &store_ptr_instruction->base); |
| 4124 | } | 4539 | } |
| 4125 | | 4540 | |
| 4126 | ir_build_store_ptr_from(&ira->new_irb, &store_ptr_instruction->base, ptr, casted_value); | 4541 | ir_build_store_ptr_from(&ira->new_irb, &store_ptr_instruction->base, ptr, casted_value); |
| 4127 | return ira->codegen->builtin_types.entry_void; | 4542 | return ira->codegen->builtin_types.entry_void; |
| 4128 | } | 4543 | } |
| 4129 | | 4544 | |
| | 4545 | static TypeTableEntry *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructionTypeOf *typeof_instruction) { |
| | 4546 | IrInstruction *expr_value = typeof_instruction->value->other; |
| | 4547 | TypeTableEntry *type_entry = expr_value->type_entry; |
| | 4548 | switch (type_entry->id) { |
| | 4549 | case TypeTableEntryIdInvalid: |
| | 4550 | return type_entry; |
| | 4551 | case TypeTableEntryIdVar: |
| | 4552 | add_node_error(ira->codegen, expr_value->source_node, |
| | 4553 | buf_sprintf("type '%s' not eligible for @typeOf", buf_ptr(&type_entry->name))); |
| | 4554 | return ira->codegen->builtin_types.entry_invalid; |
| | 4555 | case TypeTableEntryIdNumLitFloat: |
| | 4556 | case TypeTableEntryIdNumLitInt: |
| | 4557 | case TypeTableEntryIdUndefLit: |
| | 4558 | case TypeTableEntryIdNullLit: |
| | 4559 | case TypeTableEntryIdNamespace: |
| | 4560 | case TypeTableEntryIdBlock: |
| | 4561 | case TypeTableEntryIdGenericFn: |
| | 4562 | case TypeTableEntryIdMetaType: |
| | 4563 | case TypeTableEntryIdVoid: |
| | 4564 | case TypeTableEntryIdBool: |
| | 4565 | case TypeTableEntryIdUnreachable: |
| | 4566 | case TypeTableEntryIdInt: |
| | 4567 | case TypeTableEntryIdFloat: |
| | 4568 | case TypeTableEntryIdPointer: |
| | 4569 | case TypeTableEntryIdArray: |
| | 4570 | case TypeTableEntryIdStruct: |
| | 4571 | case TypeTableEntryIdMaybe: |
| | 4572 | case TypeTableEntryIdErrorUnion: |
| | 4573 | case TypeTableEntryIdPureError: |
| | 4574 | case TypeTableEntryIdEnum: |
| | 4575 | case TypeTableEntryIdUnion: |
| | 4576 | case TypeTableEntryIdFn: |
| | 4577 | case TypeTableEntryIdTypeDecl: |
| | 4578 | { |
| | 4579 | ConstExprValue *out_val = ir_get_out_val(&typeof_instruction->base); |
| | 4580 | out_val->ok = true; |
| | 4581 | // TODO depends_on_compile_var should be set based on whether the type of the expression |
| | 4582 | // depends_on_compile_var. but we currently don't have a thing to tell us if the type of |
| | 4583 | // something depends on a compile var |
| | 4584 | out_val->data.x_type = type_entry; |
| | 4585 | |
| | 4586 | return ira->codegen->builtin_types.entry_type; |
| | 4587 | } |
| | 4588 | } |
| | 4589 | |
| | 4590 | zig_unreachable(); |
| | 4591 | } |
| | 4592 | |
| | 4593 | static TypeTableEntry *ir_analyze_instruction_to_ptr_type(IrAnalyze *ira, |
| | 4594 | IrInstructionToPtrType *to_ptr_type_instruction) |
| | 4595 | { |
| | 4596 | IrInstruction *type_value = to_ptr_type_instruction->value->other; |
| | 4597 | TypeTableEntry *type_entry = ir_resolve_type(ira, type_value); |
| | 4598 | if (type_entry->id == TypeTableEntryIdInvalid) |
| | 4599 | return type_entry; |
| | 4600 | |
| | 4601 | TypeTableEntry *ptr_type; |
| | 4602 | if (type_entry->id == TypeTableEntryIdArray) { |
| | 4603 | ptr_type = get_pointer_to_type(ira->codegen, type_entry->data.array.child_type, false); |
| | 4604 | } else if (is_slice(type_entry)) { |
| | 4605 | ptr_type = type_entry->data.structure.fields[0].type_entry; |
| | 4606 | } else { |
| | 4607 | add_node_error(ira->codegen, to_ptr_type_instruction->base.source_node, |
| | 4608 | buf_sprintf("expected array type, found '%s'", buf_ptr(&type_entry->name))); |
| | 4609 | return ira->codegen->builtin_types.entry_invalid; |
| | 4610 | } |
| | 4611 | |
| | 4612 | ConstExprValue *out_val = ir_get_out_val(&to_ptr_type_instruction->base); |
| | 4613 | out_val->ok = true; |
| | 4614 | out_val->depends_on_compile_var = type_value->static_value.depends_on_compile_var; |
| | 4615 | out_val->data.x_type = ptr_type; |
| | 4616 | return ira->codegen->builtin_types.entry_type; |
| | 4617 | } |
| | 4618 | |
| | 4619 | static TypeTableEntry *ir_analyze_instruction_ptr_type_child(IrAnalyze *ira, |
| | 4620 | IrInstructionPtrTypeChild *ptr_type_child_instruction) |
| | 4621 | { |
| | 4622 | IrInstruction *type_value = ptr_type_child_instruction->value->other; |
| | 4623 | TypeTableEntry *type_entry = ir_resolve_type(ira, type_value); |
| | 4624 | if (type_entry->id == TypeTableEntryIdInvalid) |
| | 4625 | return type_entry; |
| | 4626 | |
| | 4627 | if (type_entry->id != TypeTableEntryIdPointer) { |
| | 4628 | add_node_error(ira->codegen, ptr_type_child_instruction->base.source_node, |
| | 4629 | buf_sprintf("expected pointer type, found '%s'", buf_ptr(&type_entry->name))); |
| | 4630 | return ira->codegen->builtin_types.entry_invalid; |
| | 4631 | } |
| | 4632 | |
| | 4633 | ConstExprValue *out_val = ir_get_out_val(&ptr_type_child_instruction->base); |
| | 4634 | out_val->ok = true; |
| | 4635 | out_val->depends_on_compile_var = type_value->static_value.depends_on_compile_var; |
| | 4636 | out_val->data.x_type = type_entry->data.pointer.child_type; |
| | 4637 | return ira->codegen->builtin_types.entry_type; |
| | 4638 | } |
| | 4639 | |
| 4130 | static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) { | 4640 | static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) { |
| 4131 | switch (instruction->id) { | 4641 | switch (instruction->id) { |
| 4132 | case IrInstructionIdInvalid: | 4642 | case IrInstructionIdInvalid: |
| ... | @@ -4145,12 +4655,14 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi | ... | @@ -4145,12 +4655,14 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 4145 | return ir_analyze_instruction_load_ptr(ira, (IrInstructionLoadPtr *)instruction); | 4655 | return ir_analyze_instruction_load_ptr(ira, (IrInstructionLoadPtr *)instruction); |
| 4146 | case IrInstructionIdStorePtr: | 4656 | case IrInstructionIdStorePtr: |
| 4147 | return ir_analyze_instruction_store_ptr(ira, (IrInstructionStorePtr *)instruction); | 4657 | return ir_analyze_instruction_store_ptr(ira, (IrInstructionStorePtr *)instruction); |
| 4148 | case IrInstructionIdFieldPtr: | | |
| 4149 | zig_panic("TODO field ptr"); | | |
| 4150 | case IrInstructionIdElemPtr: | 4658 | case IrInstructionIdElemPtr: |
| 4151 | return ir_analyze_instruction_elem_ptr(ira, (IrInstructionElemPtr *)instruction); | 4659 | return ir_analyze_instruction_elem_ptr(ira, (IrInstructionElemPtr *)instruction); |
| 4152 | case IrInstructionIdVarPtr: | 4660 | case IrInstructionIdVarPtr: |
| 4153 | return ir_analyze_instruction_var_ptr(ira, (IrInstructionVarPtr *)instruction); | 4661 | return ir_analyze_instruction_var_ptr(ira, (IrInstructionVarPtr *)instruction); |
| | 4662 | case IrInstructionIdFieldPtr: |
| | 4663 | return ir_analyze_instruction_field_ptr(ira, (IrInstructionFieldPtr *)instruction); |
| | 4664 | case IrInstructionIdReadField: |
| | 4665 | return ir_analyze_instruction_read_field(ira, (IrInstructionReadField *)instruction); |
| 4154 | case IrInstructionIdCall: | 4666 | case IrInstructionIdCall: |
| 4155 | return ir_analyze_instruction_call(ira, (IrInstructionCall *)instruction); | 4667 | return ir_analyze_instruction_call(ira, (IrInstructionCall *)instruction); |
| 4156 | case IrInstructionIdBr: | 4668 | case IrInstructionIdBr: |
| ... | @@ -4163,10 +4675,17 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi | ... | @@ -4163,10 +4675,17 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 4163 | return ir_analyze_instruction_unreachable(ira, (IrInstructionUnreachable *)instruction); | 4675 | return ir_analyze_instruction_unreachable(ira, (IrInstructionUnreachable *)instruction); |
| 4164 | case IrInstructionIdPhi: | 4676 | case IrInstructionIdPhi: |
| 4165 | return ir_analyze_instruction_phi(ira, (IrInstructionPhi *)instruction); | 4677 | return ir_analyze_instruction_phi(ira, (IrInstructionPhi *)instruction); |
| | 4678 | case IrInstructionIdTypeOf: |
| | 4679 | return ir_analyze_instruction_typeof(ira, (IrInstructionTypeOf *)instruction); |
| | 4680 | case IrInstructionIdToPtrType: |
| | 4681 | return ir_analyze_instruction_to_ptr_type(ira, (IrInstructionToPtrType *)instruction); |
| | 4682 | case IrInstructionIdPtrTypeChild: |
| | 4683 | return ir_analyze_instruction_ptr_type_child(ira, (IrInstructionPtrTypeChild *)instruction); |
| 4166 | case IrInstructionIdSwitchBr: | 4684 | case IrInstructionIdSwitchBr: |
| 4167 | case IrInstructionIdCast: | 4685 | case IrInstructionIdCast: |
| 4168 | case IrInstructionIdContainerInitList: | 4686 | case IrInstructionIdContainerInitList: |
| 4169 | case IrInstructionIdContainerInitFields: | 4687 | case IrInstructionIdContainerInitFields: |
| | 4688 | case IrInstructionIdStructFieldPtr: |
| 4170 | zig_panic("TODO analyze more instructions"); | 4689 | zig_panic("TODO analyze more instructions"); |
| 4171 | } | 4690 | } |
| 4172 | zig_unreachable(); | 4691 | zig_unreachable(); |
| ... | @@ -4175,8 +4694,13 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi | ... | @@ -4175,8 +4694,13 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 4175 | static TypeTableEntry *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *instruction) { | 4694 | static TypeTableEntry *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *instruction) { |
| 4176 | TypeTableEntry *instruction_type = ir_analyze_instruction_nocast(ira, instruction); | 4695 | TypeTableEntry *instruction_type = ir_analyze_instruction_nocast(ira, instruction); |
| 4177 | instruction->type_entry = instruction_type; | 4696 | instruction->type_entry = instruction_type; |
| 4178 | if (instruction->other) | 4697 | if (instruction->other) { |
| 4179 | instruction->other->type_entry = instruction_type; | 4698 | instruction->other->type_entry = instruction_type; |
| | 4699 | } else { |
| | 4700 | assert(instruction_type->id == TypeTableEntryIdInvalid || |
| | 4701 | instruction_type->id == TypeTableEntryIdUnreachable); |
| | 4702 | instruction->other = instruction; |
| | 4703 | } |
| 4180 | return instruction_type; | 4704 | return instruction_type; |
| 4181 | } | 4705 | } |
| 4182 | | 4706 | |
| ... | @@ -4209,6 +4733,11 @@ TypeTableEntry *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutabl | ... | @@ -4209,6 +4733,11 @@ TypeTableEntry *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutabl |
| 4209 | | 4733 | |
| 4210 | while (ira->block_queue_index < ira->old_bb_queue.length) { | 4734 | while (ira->block_queue_index < ira->old_bb_queue.length) { |
| 4211 | IrInstruction *old_instruction = ira->old_irb.current_basic_block->instruction_list.at(ira->instruction_index); | 4735 | IrInstruction *old_instruction = ira->old_irb.current_basic_block->instruction_list.at(ira->instruction_index); |
| | 4736 | |
| | 4737 | fprintf(stderr, "===%zu====", old_instruction->debug_id); |
| | 4738 | ir_print(stderr, ira->new_irb.exec, 4); |
| | 4739 | fprintf(stderr, "========"); |
| | 4740 | |
| 4212 | if (old_instruction->ref_count == 0 && !ir_has_side_effects(old_instruction)) { | 4741 | if (old_instruction->ref_count == 0 && !ir_has_side_effects(old_instruction)) { |
| 4213 | ira->instruction_index += 1; | 4742 | ira->instruction_index += 1; |
| 4214 | continue; | 4743 | continue; |
| ... | @@ -4299,6 +4828,11 @@ bool ir_has_side_effects(IrInstruction *instruction) { | ... | @@ -4299,6 +4828,11 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 4299 | case IrInstructionIdFieldPtr: | 4828 | case IrInstructionIdFieldPtr: |
| 4300 | case IrInstructionIdElemPtr: | 4829 | case IrInstructionIdElemPtr: |
| 4301 | case IrInstructionIdVarPtr: | 4830 | case IrInstructionIdVarPtr: |
| | 4831 | case IrInstructionIdTypeOf: |
| | 4832 | case IrInstructionIdToPtrType: |
| | 4833 | case IrInstructionIdPtrTypeChild: |
| | 4834 | case IrInstructionIdReadField: |
| | 4835 | case IrInstructionIdStructFieldPtr: |
| 4302 | return false; | 4836 | return false; |
| 4303 | case IrInstructionIdBuiltinCall: | 4837 | case IrInstructionIdBuiltinCall: |
| 4304 | return ir_builtin_call_has_side_effects((IrInstructionBuiltinCall *)instruction); | 4838 | return ir_builtin_call_has_side_effects((IrInstructionBuiltinCall *)instruction); |