authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-10-30 02:46:16-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-10-30 02:46:16-04:00
log1a0111d4c36578b64d8532724afd9be9ca61d3d1
treeb8a24f50ff129c1e147665645bbdf544dc075367
parent56cdaff9e71c10eb9c4dd130ee2516acacc1c13f

*WIP*


6 files changed, 762 insertions(+), 244 deletions(-)

src/all_types.hpp+39-1
...@@ -1330,6 +1330,7 @@ struct CodeGen {...@@ -1330,6 +1330,7 @@ struct CodeGen {
1330 LLVMValueRef err_name_table;1330 LLVMValueRef err_name_table;
13311331
1332 IrInstruction *invalid_instruction;1332 IrInstruction *invalid_instruction;
1333 Buf *len_buf;
1333};1334};
13341335
1335struct VariableTableEntry {1336struct VariableTableEntry {
...@@ -1428,6 +1429,8 @@ enum IrInstructionId {...@@ -1428,6 +1429,8 @@ enum IrInstructionId {
1428 IrInstructionIdLoadPtr,1429 IrInstructionIdLoadPtr,
1429 IrInstructionIdStorePtr,1430 IrInstructionIdStorePtr,
1430 IrInstructionIdFieldPtr,1431 IrInstructionIdFieldPtr,
1432 IrInstructionIdStructFieldPtr,
1433 IrInstructionIdReadField,
1431 IrInstructionIdElemPtr,1434 IrInstructionIdElemPtr,
1432 IrInstructionIdVarPtr,1435 IrInstructionIdVarPtr,
1433 IrInstructionIdCall,1436 IrInstructionIdCall,
...@@ -1438,6 +1441,9 @@ enum IrInstructionId {...@@ -1438,6 +1441,9 @@ enum IrInstructionId {
1438 IrInstructionIdContainerInitList,1441 IrInstructionIdContainerInitList,
1439 IrInstructionIdContainerInitFields,1442 IrInstructionIdContainerInitFields,
1440 IrInstructionIdUnreachable,1443 IrInstructionIdUnreachable,
1444 IrInstructionIdTypeOf,
1445 IrInstructionIdToPtrType,
1446 IrInstructionIdPtrTypeChild,
1441};1447};
14421448
1443struct IrInstruction {1449struct IrInstruction {
...@@ -1573,8 +1579,22 @@ struct IrInstructionStorePtr {...@@ -1573,8 +1579,22 @@ struct IrInstructionStorePtr {
1573struct IrInstructionFieldPtr {1579struct IrInstructionFieldPtr {
1574 IrInstruction base;1580 IrInstruction base;
15751581
1582 IrInstruction *container_ptr;
1583 Buf *field_name;
1584};
1585
1586struct IrInstructionStructFieldPtr {
1587 IrInstruction base;
1588
1576 IrInstruction *struct_ptr;1589 IrInstruction *struct_ptr;
1577 Buf field_name;1590 TypeStructField *field;
1591};
1592
1593struct IrInstructionReadField {
1594 IrInstruction base;
1595
1596 IrInstruction *container_ptr;
1597 Buf *field_name;
1578};1598};
15791599
1580struct IrInstructionElemPtr {1600struct IrInstructionElemPtr {
...@@ -1648,6 +1668,24 @@ struct IrInstructionUnreachable {...@@ -1648,6 +1668,24 @@ struct IrInstructionUnreachable {
1648 IrInstruction base;1668 IrInstruction base;
1649};1669};
16501670
1671struct IrInstructionTypeOf {
1672 IrInstruction base;
1673
1674 IrInstruction *value;
1675};
1676
1677struct IrInstructionToPtrType {
1678 IrInstruction base;
1679
1680 IrInstruction *value;
1681};
1682
1683struct IrInstructionPtrTypeChild {
1684 IrInstruction base;
1685
1686 IrInstruction *value;
1687};
1688
1651enum LValPurpose {1689enum LValPurpose {
1652 LValPurposeNone,1690 LValPurposeNone,
1653 LValPurposeAssign,1691 LValPurposeAssign,
src/analyze.cpp+8-71
...@@ -192,7 +192,7 @@ static BlockContext **get_container_block_context_ptr(TypeTableEntry *type_entry...@@ -192,7 +192,7 @@ static BlockContext **get_container_block_context_ptr(TypeTableEntry *type_entry
192 zig_unreachable();192 zig_unreachable();
193}193}
194194
195static BlockContext *get_container_block_context(TypeTableEntry *type_entry) {195BlockContext *get_container_block_context(TypeTableEntry *type_entry) {
196 return *get_container_block_context_ptr(type_entry);196 return *get_container_block_context_ptr(type_entry);
197}197}
198198
...@@ -217,7 +217,7 @@ static size_t bits_needed_for_unsigned(uint64_t x) {...@@ -217,7 +217,7 @@ static size_t bits_needed_for_unsigned(uint64_t x) {
217 }217 }
218}218}
219219
220static bool type_is_complete(TypeTableEntry *type_entry) {220bool type_is_complete(TypeTableEntry *type_entry) {
221 switch (type_entry->id) {221 switch (type_entry->id) {
222 case TypeTableEntryIdInvalid:222 case TypeTableEntryIdInvalid:
223 case TypeTableEntryIdVar:223 case TypeTableEntryIdVar:
...@@ -2422,7 +2422,7 @@ VariableTableEntry *find_variable(CodeGen *g, BlockContext *orig_context, Buf *n...@@ -2422,7 +2422,7 @@ VariableTableEntry *find_variable(CodeGen *g, BlockContext *orig_context, Buf *n
2422 return nullptr;2422 return nullptr;
2423}2423}
24242424
2425static TypeEnumField *find_enum_type_field(TypeTableEntry *enum_type, Buf *name) {2425TypeEnumField *find_enum_type_field(TypeTableEntry *enum_type, Buf *name) {
2426 for (uint32_t i = 0; i < enum_type->data.enumeration.src_field_count; i += 1) {2426 for (uint32_t i = 0; i < enum_type->data.enumeration.src_field_count; i += 1) {
2427 TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[i];2427 TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[i];
2428 if (buf_eql_buf(type_enum_field->name, name)) {2428 if (buf_eql_buf(type_enum_field->name, name)) {
...@@ -2493,7 +2493,7 @@ static TypeTableEntry *analyze_enum_value_expr(CodeGen *g, ImportTableEntry *imp...@@ -2493,7 +2493,7 @@ static TypeTableEntry *analyze_enum_value_expr(CodeGen *g, ImportTableEntry *imp
2493 return enum_type;2493 return enum_type;
2494}2494}
24952495
2496static TypeStructField *find_struct_type_field(TypeTableEntry *type_entry, Buf *name) {2496TypeStructField *find_struct_type_field(TypeTableEntry *type_entry, Buf *name) {
2497 assert(type_entry->id == TypeTableEntryIdStruct);2497 assert(type_entry->id == TypeTableEntryIdStruct);
2498 assert(type_entry->data.structure.complete);2498 assert(type_entry->data.structure.complete);
2499 for (uint32_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) {2499 for (uint32_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) {
...@@ -2539,18 +2539,18 @@ static bool is_container(TypeTableEntry *type_entry) {...@@ -2539,18 +2539,18 @@ static bool is_container(TypeTableEntry *type_entry) {
2539 zig_unreachable();2539 zig_unreachable();
2540}2540}
25412541
2542static bool is_container_ref(TypeTableEntry *type_entry) {2542bool is_container_ref(TypeTableEntry *type_entry) {
2543 return (type_entry->id == TypeTableEntryIdPointer) ?2543 return (type_entry->id == TypeTableEntryIdPointer) ?
2544 is_container(type_entry->data.pointer.child_type) : is_container(type_entry);2544 is_container(type_entry->data.pointer.child_type) : is_container(type_entry);
2545}2545}
25462546
2547static TypeTableEntry *container_ref_type(TypeTableEntry *type_entry) {2547TypeTableEntry *container_ref_type(TypeTableEntry *type_entry) {
2548 assert(is_container_ref(type_entry));2548 assert(is_container_ref(type_entry));
2549 return (type_entry->id == TypeTableEntryIdPointer) ?2549 return (type_entry->id == TypeTableEntryIdPointer) ?
2550 type_entry->data.pointer.child_type : type_entry;2550 type_entry->data.pointer.child_type : type_entry;
2551}2551}
25522552
2553static void resolve_container_type(CodeGen *g, TypeTableEntry *type_entry) {2553void resolve_container_type(CodeGen *g, TypeTableEntry *type_entry) {
2554 switch (type_entry->id) {2554 switch (type_entry->id) {
2555 case TypeTableEntryIdStruct:2555 case TypeTableEntryIdStruct:
2556 resolve_struct_type(g, type_entry->data.structure.decl_node->owner, type_entry);2556 resolve_struct_type(g, type_entry->data.structure.decl_node->owner, type_entry);
...@@ -4034,69 +4034,6 @@ static TypeTableEntry *analyze_while_expr(CodeGen *g, ImportTableEntry *import,...@@ -4034,69 +4034,6 @@ static TypeTableEntry *analyze_while_expr(CodeGen *g, ImportTableEntry *import,
4034 return expr_return_type;4034 return expr_return_type;
4035}4035}
40364036
4037static TypeTableEntry *analyze_for_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
4038 TypeTableEntry *expected_type, AstNode *node)
4039{
4040 assert(node->type == NodeTypeForExpr);
4041
4042 AstNode *array_node = node->data.for_expr.array_expr;
4043 TypeTableEntry *array_type = analyze_expression(g, import, context, nullptr, array_node);
4044 TypeTableEntry *child_type;
4045 if (array_type->id == TypeTableEntryIdInvalid) {
4046 child_type = array_type;
4047 } else if (array_type->id == TypeTableEntryIdArray) {
4048 child_type = array_type->data.array.child_type;
4049 } else if (array_type->id == TypeTableEntryIdStruct &&
4050 array_type->data.structure.is_slice)
4051 {
4052 TypeTableEntry *pointer_type = array_type->data.structure.fields[0].type_entry;
4053 assert(pointer_type->id == TypeTableEntryIdPointer);
4054 child_type = pointer_type->data.pointer.child_type;
4055 } else {
4056 add_node_error(g, node,
4057 buf_sprintf("iteration over non array type '%s'", buf_ptr(&array_type->name)));
4058 child_type = g->builtin_types.entry_invalid;
4059 }
4060
4061 TypeTableEntry *var_type;
4062 if (child_type->id != TypeTableEntryIdInvalid && node->data.for_expr.elem_is_ptr) {
4063 var_type = get_pointer_to_type(g, child_type, false);
4064 } else {
4065 var_type = child_type;
4066 }
4067
4068 BlockContext *child_context = new_block_context(node, context);
4069 child_context->parent_loop_node = node;
4070
4071 AstNode *elem_var_node = node->data.for_expr.elem_node;
4072 if (!elem_var_node) {
4073 add_node_error(g, node->data.for_expr.body,
4074 buf_sprintf("for loop expression missing element parameter"));
4075 return g->builtin_types.entry_invalid;
4076 }
4077
4078 elem_var_node->block_context = child_context;
4079 Buf *elem_var_name = elem_var_node->data.symbol_expr.symbol;
4080 node->data.for_expr.elem_var = add_local_var(g, elem_var_node, import, child_context, elem_var_name,
4081 var_type, true, nullptr);
4082
4083 AstNode *index_var_node = node->data.for_expr.index_node;
4084 if (index_var_node) {
4085 Buf *index_var_name = index_var_node->data.symbol_expr.symbol;
4086 index_var_node->block_context = child_context;
4087 node->data.for_expr.index_var = add_local_var(g, index_var_node, import, child_context, index_var_name,
4088 g->builtin_types.entry_usize, true, nullptr);
4089 } else {
4090 node->data.for_expr.index_var = add_local_var(g, node, import, child_context, nullptr,
4091 g->builtin_types.entry_usize, true, nullptr);
4092 }
4093
4094 analyze_expression(g, import, child_context, g->builtin_types.entry_void, node->data.for_expr.body);
4095
4096
4097 return g->builtin_types.entry_void;
4098}
4099
4100static TypeTableEntry *analyze_break_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,4037static TypeTableEntry *analyze_break_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
4101 TypeTableEntry *expected_type, AstNode *node)4038 TypeTableEntry *expected_type, AstNode *node)
4102{4039{
...@@ -5294,7 +5231,7 @@ static TypeTableEntry *analyze_expression_pointer_only(CodeGen *g, ImportTableEn...@@ -5294,7 +5231,7 @@ static TypeTableEntry *analyze_expression_pointer_only(CodeGen *g, ImportTableEn
5294 return_type = analyze_while_expr(g, import, context, expected_type, node);5231 return_type = analyze_while_expr(g, import, context, expected_type, node);
5295 break;5232 break;
5296 case NodeTypeForExpr:5233 case NodeTypeForExpr:
5297 return_type = analyze_for_expr(g, import, context, expected_type, node);5234 zig_panic("moved to ir.cpp");
5298 break;5235 break;
5299 case NodeTypeArrayType:5236 case NodeTypeArrayType:
5300 return_type = analyze_array_type(g, import, context, expected_type, node);5237 return_type = analyze_array_type(g, import, context, expected_type, node);
src/analyze.hpp+8-1
...@@ -50,7 +50,7 @@ TypeTableEntry *resolve_peer_type_compatibility(CodeGen *g, ImportTableEntry *im...@@ -50,7 +50,7 @@ TypeTableEntry *resolve_peer_type_compatibility(CodeGen *g, ImportTableEntry *im
50 AstNode **child_nodes, TypeTableEntry **child_types, size_t child_count);50 AstNode **child_nodes, TypeTableEntry **child_types, size_t child_count);
5151
5252
5353// TODO move these over, these used to be static
54bool types_match_const_cast_only(TypeTableEntry *expected_type, TypeTableEntry *actual_type);54bool types_match_const_cast_only(TypeTableEntry *expected_type, TypeTableEntry *actual_type);
55VariableTableEntry *find_variable(CodeGen *g, BlockContext *orig_context, Buf *name);55VariableTableEntry *find_variable(CodeGen *g, BlockContext *orig_context, Buf *name);
56AstNode *find_decl(BlockContext *context, Buf *name);56AstNode *find_decl(BlockContext *context, Buf *name);
...@@ -59,5 +59,12 @@ TopLevelDecl *get_as_top_level_decl(AstNode *node);...@@ -59,5 +59,12 @@ TopLevelDecl *get_as_top_level_decl(AstNode *node);
59void mark_impure_fn(CodeGen *g, BlockContext *context, AstNode *node);59void mark_impure_fn(CodeGen *g, BlockContext *context, AstNode *node);
60bool type_is_codegen_pointer(TypeTableEntry *type);60bool type_is_codegen_pointer(TypeTableEntry *type);
61TypeTableEntry *validate_var_type(CodeGen *g, AstNode *source_node, TypeTableEntry *type_entry);61TypeTableEntry *validate_var_type(CodeGen *g, AstNode *source_node, TypeTableEntry *type_entry);
62TypeTableEntry *container_ref_type(TypeTableEntry *type_entry);
63bool type_is_complete(TypeTableEntry *type_entry);
64void resolve_container_type(CodeGen *g, TypeTableEntry *type_entry);
65TypeStructField *find_struct_type_field(TypeTableEntry *type_entry, Buf *name);
66BlockContext *get_container_block_context(TypeTableEntry *type_entry);
67TypeEnumField *find_enum_type_field(TypeTableEntry *enum_type, Buf *name);
68bool is_container_ref(TypeTableEntry *type_entry);
6269
63#endif70#endif
src/codegen.cpp+23-85
...@@ -66,6 +66,8 @@ CodeGen *codegen_create(Buf *root_source_dir, const ZigTarget *target) {...@@ -66,6 +66,8 @@ CodeGen *codegen_create(Buf *root_source_dir, const ZigTarget *target) {
66 g->is_test_build = false;66 g->is_test_build = false;
67 g->want_h_file = true;67 g->want_h_file = true;
6868
69 g->len_buf = buf_create_from_str("len");
70
69 // the error.Ok value71 // the error.Ok value
70 g->error_decls.append(nullptr);72 g->error_decls.append(nullptr);
7173
...@@ -2940,12 +2942,29 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr...@@ -2940,12 +2942,29 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
2940 }2942 }
2941}2943}
29422944
2945static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executable,
2946 IrInstructionStructFieldPtr *instruction)
2947{
2948 LLVMValueRef struct_ptr = ir_llvm_value(g, instruction->struct_ptr);
2949 TypeStructField *field = instruction->field;
2950
2951 if (!type_has_bits(field->type_entry))
2952 return nullptr;
2953
2954 assert(field->gen_index != SIZE_MAX);
2955 return LLVMBuildStructGEP(g->builder, struct_ptr, field->gen_index, "");
2956}
2957
2943static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, IrInstruction *instruction) {2958static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, IrInstruction *instruction) {
2944 set_debug_source_node(g, instruction->source_node);2959 set_debug_source_node(g, instruction->source_node);
29452960
2946 switch (instruction->id) {2961 switch (instruction->id) {
2947 case IrInstructionIdInvalid:2962 case IrInstructionIdInvalid:
2948 case IrInstructionIdConst:2963 case IrInstructionIdConst:
2964 case IrInstructionIdTypeOf:
2965 case IrInstructionIdToPtrType:
2966 case IrInstructionIdPtrTypeChild:
2967 case IrInstructionIdFieldPtr:
2949 zig_unreachable();2968 zig_unreachable();
2950 case IrInstructionIdReturn:2969 case IrInstructionIdReturn:
2951 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);2970 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);
...@@ -2973,12 +2992,14 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -2973,12 +2992,14 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
2973 return ir_render_elem_ptr(g, executable, (IrInstructionElemPtr *)instruction);2992 return ir_render_elem_ptr(g, executable, (IrInstructionElemPtr *)instruction);
2974 case IrInstructionIdCall:2993 case IrInstructionIdCall:
2975 return ir_render_call(g, executable, (IrInstructionCall *)instruction);2994 return ir_render_call(g, executable, (IrInstructionCall *)instruction);
2995 case IrInstructionIdStructFieldPtr:
2996 return ir_render_struct_field_ptr(g, executable, (IrInstructionStructFieldPtr *)instruction);
2976 case IrInstructionIdSwitchBr:2997 case IrInstructionIdSwitchBr:
2977 case IrInstructionIdPhi:2998 case IrInstructionIdPhi:
2978 case IrInstructionIdBuiltinCall:2999 case IrInstructionIdBuiltinCall:
2979 case IrInstructionIdContainerInitList:3000 case IrInstructionIdContainerInitList:
2980 case IrInstructionIdContainerInitFields:3001 case IrInstructionIdContainerInitFields:
2981 case IrInstructionIdFieldPtr:3002 case IrInstructionIdReadField:
2982 zig_panic("TODO render more IR instructions to LLVM");3003 zig_panic("TODO render more IR instructions to LLVM");
2983 }3004 }
2984 zig_unreachable();3005 zig_unreachable();
...@@ -3284,89 +3305,6 @@ static LLVMValueRef gen_while_expr(CodeGen *g, AstNode *node) {...@@ -3284,89 +3305,6 @@ static LLVMValueRef gen_while_expr(CodeGen *g, AstNode *node) {
3284 return nullptr;3305 return nullptr;
3285}3306}
32863307
3287static LLVMValueRef gen_for_expr(CodeGen *g, AstNode *node) {
3288 assert(node->type == NodeTypeForExpr);
3289 assert(node->data.for_expr.array_expr);
3290 assert(node->data.for_expr.body);
3291
3292 zig_panic("TODO IR for loop");
3293 //VariableTableEntry *elem_var = node->data.for_expr.elem_var;
3294 //assert(elem_var);
3295
3296 //TypeTableEntry *array_type = get_expr_type(node->data.for_expr.array_expr);
3297
3298 //VariableTableEntry *index_var = node->data.for_expr.index_var;
3299 //assert(index_var);
3300 //LLVMValueRef index_ptr = index_var->value_ref;
3301 //LLVMValueRef one_const = LLVMConstInt(g->builtin_types.entry_usize->type_ref, 1, false);
3302
3303 //LLVMBasicBlockRef cond_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "ForCond");
3304 //LLVMBasicBlockRef body_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "ForBody");
3305 //LLVMBasicBlockRef end_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "ForEnd");
3306 //LLVMBasicBlockRef continue_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "ForContinue");
3307
3308 //LLVMValueRef array_val = gen_array_base_ptr(g, node->data.for_expr.array_expr);
3309 //set_debug_source_node(g, node);
3310 //LLVMBuildStore(g->builder, LLVMConstNull(index_var->type->type_ref), index_ptr);
3311
3312 //gen_var_debug_decl(g, index_var);
3313
3314 //LLVMValueRef len_val;
3315 //TypeTableEntry *child_type;
3316 //if (array_type->id == TypeTableEntryIdArray) {
3317 // len_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref,
3318 // array_type->data.array.len, false);
3319 // child_type = array_type->data.array.child_type;
3320 //} else if (array_type->id == TypeTableEntryIdStruct) {
3321 // assert(array_type->data.structure.is_slice);
3322 // TypeTableEntry *child_ptr_type = array_type->data.structure.fields[0].type_entry;
3323 // assert(child_ptr_type->id == TypeTableEntryIdPointer);
3324 // child_type = child_ptr_type->data.pointer.child_type;
3325 // size_t len_index = array_type->data.structure.fields[1].gen_index;
3326 // assert(len_index != SIZE_MAX);
3327 // LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, array_val, len_index, "");
3328 // len_val = LLVMBuildLoad(g->builder, len_field_ptr, "");
3329 //} else {
3330 // zig_unreachable();
3331 //}
3332 //LLVMBuildBr(g->builder, cond_block);
3333
3334 //LLVMPositionBuilderAtEnd(g->builder, cond_block);
3335 //LLVMValueRef index_val = LLVMBuildLoad(g->builder, index_ptr, "");
3336 //LLVMValueRef cond = LLVMBuildICmp(g->builder, LLVMIntSLT, index_val, len_val, "");
3337 //LLVMBuildCondBr(g->builder, cond, body_block, end_block);
3338
3339 //LLVMPositionBuilderAtEnd(g->builder, body_block);
3340 //LLVMValueRef elem_ptr = gen_array_elem_ptr(g, node, array_val, array_type, index_val);
3341
3342 //LLVMValueRef elem_val;
3343 //if (node->data.for_expr.elem_is_ptr) {
3344 // elem_val = elem_ptr;
3345 //} else {
3346 // elem_val = handle_is_ptr(child_type) ? elem_ptr : LLVMBuildLoad(g->builder, elem_ptr, "");
3347 //}
3348 //gen_assign_raw(g, node, BinOpTypeAssign, elem_var->value_ref, elem_val, elem_var->type, child_type);
3349 //gen_var_debug_decl(g, elem_var);
3350 //g->break_block_stack.append(end_block);
3351 //g->continue_block_stack.append(continue_block);
3352 //gen_expr(g, node->data.for_expr.body);
3353 //g->break_block_stack.pop();
3354 //g->continue_block_stack.pop();
3355 //if (get_expr_type(node->data.for_expr.body)->id != TypeTableEntryIdUnreachable) {
3356 // set_debug_source_node(g, node);
3357 // LLVMBuildBr(g->builder, continue_block);
3358 //}
3359
3360 //LLVMPositionBuilderAtEnd(g->builder, continue_block);
3361 //set_debug_source_node(g, node);
3362 //LLVMValueRef new_index_val = LLVMBuildNSWAdd(g->builder, index_val, one_const, "");
3363 //LLVMBuildStore(g->builder, new_index_val, index_ptr);
3364 //LLVMBuildBr(g->builder, cond_block);
3365
3366 //LLVMPositionBuilderAtEnd(g->builder, end_block);
3367 //return nullptr;
3368}
3369
3370//static LLVMValueRef gen_break(CodeGen *g, AstNode *node) {3308//static LLVMValueRef gen_break(CodeGen *g, AstNode *node) {
3371// assert(node->type == NodeTypeBreak);3309// assert(node->type == NodeTypeBreak);
3372// LLVMBasicBlockRef dest_block = g->break_block_stack.last();3310// LLVMBasicBlockRef dest_block = g->break_block_stack.last();
...@@ -3773,7 +3711,7 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {...@@ -3773,7 +3711,7 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {
3773 case NodeTypeWhileExpr:3711 case NodeTypeWhileExpr:
3774 return gen_while_expr(g, node);3712 return gen_while_expr(g, node);
3775 case NodeTypeForExpr:3713 case NodeTypeForExpr:
3776 return gen_for_expr(g, node);3714 zig_panic("moved to ir render");
3777 case NodeTypeAsmExpr:3715 case NodeTypeAsmExpr:
3778 return gen_asm_expr(g, node);3716 return gen_asm_expr(g, node);
3779 case NodeTypeSymbol:3717 case NodeTypeSymbol:
src/ir.cpp+619-85
...@@ -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"
56
6struct IrExecContext {7struct IrExecContext {
7 ConstExprValue *mem_slot_list;8 ConstExprValue *mem_slot_list;
...@@ -32,6 +33,7 @@ struct IrAnalyze {...@@ -32,6 +33,7 @@ struct IrAnalyze {
32static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, BlockContext *scope);33static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, BlockContext *scope);
33static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockContext *block_context,34static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockContext *block_context,
34 LValPurpose lval);35 LValPurpose lval);
36static TypeTableEntry *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *instruction);
3537
36static void ir_instruction_append(IrBasicBlock *basic_block, IrInstruction *instruction) {38static 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}
129131
132static constexpr IrInstructionId ir_instruction_id(IrInstructionStructFieldPtr *) {
133 return IrInstructionIdStructFieldPtr;
134}
135
136static constexpr IrInstructionId ir_instruction_id(IrInstructionReadField *) {
137 return IrInstructionIdReadField;
138}
139
130static constexpr IrInstructionId ir_instruction_id(IrInstructionElemPtr *) {140static 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}
169179
180static constexpr IrInstructionId ir_instruction_id(IrInstructionTypeOf *) {
181 return IrInstructionIdTypeOf;
182}
183
184static constexpr IrInstructionId ir_instruction_id(IrInstructionToPtrType *) {
185 return IrInstructionIdToPtrType;
186}
187
188static constexpr IrInstructionId ir_instruction_id(IrInstructionPtrTypeChild *) {
189 return IrInstructionIdPtrTypeChild;
190}
191
170template<typename T>192template<typename T>
171static T *ir_create_instruction(IrExecutable *exec, AstNode *source_node) {193static 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}
258280
281static 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
259static IrInstruction *ir_build_const_bignum(IrBuilder *irb, AstNode *source_node, BigNum *bignum) {289static 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}
267297
298static 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
268static IrInstruction *ir_create_const_type(IrBuilder *irb, AstNode *source_node, TypeTableEntry *type_entry) {306static 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}
358396
397static 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
417static 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
437static 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
449static 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
359static IrInstruction *ir_build_call(IrBuilder *irb, AstNode *source_node,458static 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}
566665
666static 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
675static 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
684static 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}
650776
651static VariableTableEntry *add_local_var(CodeGen *codegen, AstNode *node, Buf *name,777static 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
686812
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 pass816 // 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}
698825
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).
700static VariableTableEntry *ir_add_local_var(IrBuilder *irb, AstNode *node, Buf *name,827static 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}
9651092
1093static 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
966static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, AstNode *node) {1110static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, AstNode *node) {
967 assert(node->type == NodeTypeFnCallExpr);1111 assert(node->type == NodeTypeFnCallExpr);
9681112
...@@ -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) {
9901134
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 }
9941144
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);
11871338
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}
12341385
1386static 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
1235static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockContext *block_context,1482static 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 }
15891838
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}
15921847
...@@ -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}
16631918
1919static 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
1925static 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
1935static 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
1664static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr,1958static 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 }
19132207
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}
19202219
1921static 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
1941static IrInstruction *ir_get_casted_value(IrAnalyze *ira, IrInstruction *value, TypeTableEntry *expected_type) {2220static 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,
1976static TypeTableEntry *ir_analyze_instruction_return(IrAnalyze *ira,2255static 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);
19832264
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}
19882275
1989static TypeTableEntry *ir_analyze_instruction_const(IrAnalyze *ira, IrInstructionConst *const_instruction) {2276static 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}
23552642
2356static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstructionDeclVar *decl_var_instruction) {2643static 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 }
23732664
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 }
24242714
2425 var->type = result_type;2715 var->type = result_type;
2426 assert(var->type != nullptr); // should have been caught by the parser2716 assert(var->type);
24272717
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
3867static TypeTableEntry *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructionCondBr *cond_br_instruction) {4119static 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 }
38724126
3873 // TODO detect backward jumps4127 // 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,
3938static TypeTableEntry *ir_analyze_instruction_unreachable(IrAnalyze *ira,4192static 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}
39454199
3946static TypeTableEntry *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPhi *phi_instruction) {4200static 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
39974251
3998static TypeTableEntry *ir_analyze_instruction_var_ptr(IrAnalyze *ira, IrInstructionVarPtr *var_ptr_instruction) {4252static 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}
40594316
4317static 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
4336static 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
4363static 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
4410static 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
4423static 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
4060static TypeTableEntry *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstructionLoadPtr *load_ptr_instruction) {4470static 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
40844494
4085static TypeTableEntry *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstructionStorePtr *store_ptr_instruction) {4495static 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;
40884503
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 }
41014516
...@@ -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 }
41254540
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}
41294544
4545static 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
4593static 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
4619static 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
4130static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {4640static 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
4175static TypeTableEntry *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *instruction) {4694static 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}
41824706
...@@ -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
42094733
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);
src/ir_print.cpp+65-1
...@@ -22,6 +22,16 @@ static void ir_print_prefix(IrPrint *irp, IrInstruction *instruction) {...@@ -22,6 +22,16 @@ static void ir_print_prefix(IrPrint *irp, IrInstruction *instruction) {
22}22}
2323
24static void ir_print_const_value(IrPrint *irp, TypeTableEntry *type_entry, ConstExprValue *const_val) {24static void ir_print_const_value(IrPrint *irp, TypeTableEntry *type_entry, ConstExprValue *const_val) {
25 switch (const_val->special) {
26 case ConstValSpecialUndef:
27 fprintf(irp->f, "undefined");
28 return;
29 case ConstValSpecialZeroes:
30 fprintf(irp->f, "zeroes");
31 return;
32 case ConstValSpecialOther:
33 break;
34 }
25 switch (type_entry->id) {35 switch (type_entry->id) {
26 case TypeTableEntryIdInvalid:36 case TypeTableEntryIdInvalid:
27 zig_unreachable();37 zig_unreachable();
...@@ -343,6 +353,43 @@ static void ir_print_store_ptr(IrPrint *irp, IrInstructionStorePtr *instruction)...@@ -343,6 +353,43 @@ static void ir_print_store_ptr(IrPrint *irp, IrInstructionStorePtr *instruction)
343 ir_print_other_instruction(irp, instruction->value);353 ir_print_other_instruction(irp, instruction->value);
344}354}
345355
356static void ir_print_typeof(IrPrint *irp, IrInstructionTypeOf *instruction) {
357 fprintf(irp->f, "@typeOf(");
358 ir_print_other_instruction(irp, instruction->value);
359 fprintf(irp->f, ")");
360}
361
362static void ir_print_to_ptr_type(IrPrint *irp, IrInstructionToPtrType *instruction) {
363 fprintf(irp->f, "@toPtrType(");
364 ir_print_other_instruction(irp, instruction->value);
365 fprintf(irp->f, ")");
366}
367
368static void ir_print_ptr_type_child(IrPrint *irp, IrInstructionPtrTypeChild *instruction) {
369 fprintf(irp->f, "@ptrTypeChild(");
370 ir_print_other_instruction(irp, instruction->value);
371 fprintf(irp->f, ")");
372}
373
374static void ir_print_field_ptr(IrPrint *irp, IrInstructionFieldPtr *instruction) {
375 fprintf(irp->f, "@FieldPtr(&");
376 ir_print_other_instruction(irp, instruction->container_ptr);
377 fprintf(irp->f, ".%s", buf_ptr(instruction->field_name));
378 fprintf(irp->f, ")");
379}
380
381static void ir_print_read_field(IrPrint *irp, IrInstructionReadField *instruction) {
382 ir_print_other_instruction(irp, instruction->container_ptr);
383 fprintf(irp->f, ".%s", buf_ptr(instruction->field_name));
384}
385
386static void ir_print_struct_field_ptr(IrPrint *irp, IrInstructionStructFieldPtr *instruction) {
387 fprintf(irp->f, "@StructFieldPtr(&");
388 ir_print_other_instruction(irp, instruction->struct_ptr);
389 fprintf(irp->f, ".%s", buf_ptr(instruction->field->name));
390 fprintf(irp->f, ")");
391}
392
346static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {393static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
347 ir_print_prefix(irp, instruction);394 ir_print_prefix(irp, instruction);
348 switch (instruction->id) {395 switch (instruction->id) {
...@@ -402,8 +449,25 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -402,8 +449,25 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
402 case IrInstructionIdStorePtr:449 case IrInstructionIdStorePtr:
403 ir_print_store_ptr(irp, (IrInstructionStorePtr *)instruction);450 ir_print_store_ptr(irp, (IrInstructionStorePtr *)instruction);
404 break;451 break;
405 case IrInstructionIdSwitchBr:452 case IrInstructionIdTypeOf:
453 ir_print_typeof(irp, (IrInstructionTypeOf *)instruction);
454 break;
455 case IrInstructionIdToPtrType:
456 ir_print_to_ptr_type(irp, (IrInstructionToPtrType *)instruction);
457 break;
458 case IrInstructionIdPtrTypeChild:
459 ir_print_ptr_type_child(irp, (IrInstructionPtrTypeChild *)instruction);
460 break;
406 case IrInstructionIdFieldPtr:461 case IrInstructionIdFieldPtr:
462 ir_print_field_ptr(irp, (IrInstructionFieldPtr *)instruction);
463 break;
464 case IrInstructionIdReadField:
465 ir_print_read_field(irp, (IrInstructionReadField *)instruction);
466 break;
467 case IrInstructionIdStructFieldPtr:
468 ir_print_struct_field_ptr(irp, (IrInstructionStructFieldPtr *)instruction);
469 break;
470 case IrInstructionIdSwitchBr:
407 zig_panic("TODO print more IR instructions");471 zig_panic("TODO print more IR instructions");
408 }472 }
409 fprintf(irp->f, "\n");473 fprintf(irp->f, "\n");