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 {
13301330 LLVMValueRef err_name_table;
13311331
13321332 IrInstruction *invalid_instruction;
1333 Buf *len_buf;
13331334};
13341335
13351336struct VariableTableEntry {
......@@ -1428,6 +1429,8 @@ enum IrInstructionId {
14281429 IrInstructionIdLoadPtr,
14291430 IrInstructionIdStorePtr,
14301431 IrInstructionIdFieldPtr,
1432 IrInstructionIdStructFieldPtr,
1433 IrInstructionIdReadField,
14311434 IrInstructionIdElemPtr,
14321435 IrInstructionIdVarPtr,
14331436 IrInstructionIdCall,
......@@ -1438,6 +1441,9 @@ enum IrInstructionId {
14381441 IrInstructionIdContainerInitList,
14391442 IrInstructionIdContainerInitFields,
14401443 IrInstructionIdUnreachable,
1444 IrInstructionIdTypeOf,
1445 IrInstructionIdToPtrType,
1446 IrInstructionIdPtrTypeChild,
14411447};
14421448
14431449struct IrInstruction {
......@@ -1573,8 +1579,22 @@ struct IrInstructionStorePtr {
15731579struct IrInstructionFieldPtr {
15741580 IrInstruction base;
15751581
1582 IrInstruction *container_ptr;
1583 Buf *field_name;
1584};
1585
1586struct IrInstructionStructFieldPtr {
1587 IrInstruction base;
1588
15761589 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;
15781598};
15791599
15801600struct IrInstructionElemPtr {
......@@ -1648,6 +1668,24 @@ struct IrInstructionUnreachable {
16481668 IrInstruction base;
16491669};
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
16511689enum LValPurpose {
16521690 LValPurposeNone,
16531691 LValPurposeAssign,
src/analyze.cpp+8-71
......@@ -192,7 +192,7 @@ static BlockContext **get_container_block_context_ptr(TypeTableEntry *type_entry
192192 zig_unreachable();
193193}
194194
195static BlockContext *get_container_block_context(TypeTableEntry *type_entry) {
195BlockContext *get_container_block_context(TypeTableEntry *type_entry) {
196196 return *get_container_block_context_ptr(type_entry);
197197}
198198
......@@ -217,7 +217,7 @@ static size_t bits_needed_for_unsigned(uint64_t x) {
217217 }
218218}
219219
220static bool type_is_complete(TypeTableEntry *type_entry) {
220bool type_is_complete(TypeTableEntry *type_entry) {
221221 switch (type_entry->id) {
222222 case TypeTableEntryIdInvalid:
223223 case TypeTableEntryIdVar:
......@@ -2422,7 +2422,7 @@ VariableTableEntry *find_variable(CodeGen *g, BlockContext *orig_context, Buf *n
24222422 return nullptr;
24232423}
24242424
2425static TypeEnumField *find_enum_type_field(TypeTableEntry *enum_type, Buf *name) {
2425TypeEnumField *find_enum_type_field(TypeTableEntry *enum_type, Buf *name) {
24262426 for (uint32_t i = 0; i < enum_type->data.enumeration.src_field_count; i += 1) {
24272427 TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[i];
24282428 if (buf_eql_buf(type_enum_field->name, name)) {
......@@ -2493,7 +2493,7 @@ static TypeTableEntry *analyze_enum_value_expr(CodeGen *g, ImportTableEntry *imp
24932493 return enum_type;
24942494}
24952495
2496static TypeStructField *find_struct_type_field(TypeTableEntry *type_entry, Buf *name) {
2496TypeStructField *find_struct_type_field(TypeTableEntry *type_entry, Buf *name) {
24972497 assert(type_entry->id == TypeTableEntryIdStruct);
24982498 assert(type_entry->data.structure.complete);
24992499 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) {
25392539 zig_unreachable();
25402540}
25412541
2542static bool is_container_ref(TypeTableEntry *type_entry) {
2542bool is_container_ref(TypeTableEntry *type_entry) {
25432543 return (type_entry->id == TypeTableEntryIdPointer) ?
25442544 is_container(type_entry->data.pointer.child_type) : is_container(type_entry);
25452545}
25462546
2547static TypeTableEntry *container_ref_type(TypeTableEntry *type_entry) {
2547TypeTableEntry *container_ref_type(TypeTableEntry *type_entry) {
25482548 assert(is_container_ref(type_entry));
25492549 return (type_entry->id == TypeTableEntryIdPointer) ?
25502550 type_entry->data.pointer.child_type : type_entry;
25512551}
25522552
2553static void resolve_container_type(CodeGen *g, TypeTableEntry *type_entry) {
2553void resolve_container_type(CodeGen *g, TypeTableEntry *type_entry) {
25542554 switch (type_entry->id) {
25552555 case TypeTableEntryIdStruct:
25562556 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,
40344034 return expr_return_type;
40354035}
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
41004037static TypeTableEntry *analyze_break_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
41014038 TypeTableEntry *expected_type, AstNode *node)
41024039{
......@@ -5294,7 +5231,7 @@ static TypeTableEntry *analyze_expression_pointer_only(CodeGen *g, ImportTableEn
52945231 return_type = analyze_while_expr(g, import, context, expected_type, node);
52955232 break;
52965233 case NodeTypeForExpr:
5297 return_type = analyze_for_expr(g, import, context, expected_type, node);
5234 zig_panic("moved to ir.cpp");
52985235 break;
52995236 case NodeTypeArrayType:
53005237 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
5050 AstNode **child_nodes, TypeTableEntry **child_types, size_t child_count);
5151
5252
53
53// TODO move these over, these used to be static
5454bool types_match_const_cast_only(TypeTableEntry *expected_type, TypeTableEntry *actual_type);
5555VariableTableEntry *find_variable(CodeGen *g, BlockContext *orig_context, Buf *name);
5656AstNode *find_decl(BlockContext *context, Buf *name);
......@@ -59,5 +59,12 @@ TopLevelDecl *get_as_top_level_decl(AstNode *node);
5959void mark_impure_fn(CodeGen *g, BlockContext *context, AstNode *node);
6060bool type_is_codegen_pointer(TypeTableEntry *type);
6161TypeTableEntry *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
6370#endif
src/codegen.cpp+23-85
......@@ -66,6 +66,8 @@ CodeGen *codegen_create(Buf *root_source_dir, const ZigTarget *target) {
6666 g->is_test_build = false;
6767 g->want_h_file = true;
6868
69 g->len_buf = buf_create_from_str("len");
70
6971 // the error.Ok value
7072 g->error_decls.append(nullptr);
7173
......@@ -2940,12 +2942,29 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
29402942 }
29412943}
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
29432958static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, IrInstruction *instruction) {
29442959 set_debug_source_node(g, instruction->source_node);
29452960
29462961 switch (instruction->id) {
29472962 case IrInstructionIdInvalid:
29482963 case IrInstructionIdConst:
2964 case IrInstructionIdTypeOf:
2965 case IrInstructionIdToPtrType:
2966 case IrInstructionIdPtrTypeChild:
2967 case IrInstructionIdFieldPtr:
29492968 zig_unreachable();
29502969 case IrInstructionIdReturn:
29512970 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);
......@@ -2973,12 +2992,14 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
29732992 return ir_render_elem_ptr(g, executable, (IrInstructionElemPtr *)instruction);
29742993 case IrInstructionIdCall:
29752994 return ir_render_call(g, executable, (IrInstructionCall *)instruction);
2995 case IrInstructionIdStructFieldPtr:
2996 return ir_render_struct_field_ptr(g, executable, (IrInstructionStructFieldPtr *)instruction);
29762997 case IrInstructionIdSwitchBr:
29772998 case IrInstructionIdPhi:
29782999 case IrInstructionIdBuiltinCall:
29793000 case IrInstructionIdContainerInitList:
29803001 case IrInstructionIdContainerInitFields:
2981 case IrInstructionIdFieldPtr:
3002 case IrInstructionIdReadField:
29823003 zig_panic("TODO render more IR instructions to LLVM");
29833004 }
29843005 zig_unreachable();
......@@ -3284,89 +3305,6 @@ static LLVMValueRef gen_while_expr(CodeGen *g, AstNode *node) {
32843305 return nullptr;
32853306}
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
33703308//static LLVMValueRef gen_break(CodeGen *g, AstNode *node) {
33713309// assert(node->type == NodeTypeBreak);
33723310// LLVMBasicBlockRef dest_block = g->break_block_stack.last();
......@@ -3773,7 +3711,7 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {
37733711 case NodeTypeWhileExpr:
37743712 return gen_while_expr(g, node);
37753713 case NodeTypeForExpr:
3776 return gen_for_expr(g, node);
3714 zig_panic("moved to ir render");
37773715 case NodeTypeAsmExpr:
37783716 return gen_asm_expr(g, node);
37793717 case NodeTypeSymbol:
src/ir.cpp+619-85
......@@ -2,6 +2,7 @@
22#include "error.hpp"
33#include "eval.hpp"
44#include "ir.hpp"
5#include "ir_print.hpp"
56
67struct IrExecContext {
78 ConstExprValue *mem_slot_list;
......@@ -32,6 +33,7 @@ struct IrAnalyze {
3233static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, BlockContext *scope);
3334static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockContext *block_context,
3435 LValPurpose lval);
36static TypeTableEntry *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *instruction);
3537
3638static void ir_instruction_append(IrBasicBlock *basic_block, IrInstruction *instruction) {
3739 assert(basic_block);
......@@ -127,6 +129,14 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionFieldPtr *) {
127129 return IrInstructionIdFieldPtr;
128130}
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
130140static constexpr IrInstructionId ir_instruction_id(IrInstructionElemPtr *) {
131141 return IrInstructionIdElemPtr;
132142}
......@@ -167,6 +177,18 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionUnreachable *) {
167177 return IrInstructionIdUnreachable;
168178}
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
170192template<typename T>
171193static T *ir_create_instruction(IrExecutable *exec, AstNode *source_node) {
172194 T *special_instruction = allocate<T>(1);
......@@ -256,6 +278,14 @@ static IrInstruction *ir_build_const_void(IrBuilder *irb, AstNode *source_node)
256278 return &const_instruction->base;
257279}
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
259289static IrInstruction *ir_build_const_bignum(IrBuilder *irb, AstNode *source_node, BigNum *bignum) {
260290 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node);
261291 const_instruction->base.type_entry = (bignum->kind == BigNumKindInt) ?
......@@ -265,6 +295,14 @@ static IrInstruction *ir_build_const_bignum(IrBuilder *irb, AstNode *source_node
265295 return &const_instruction->base;
266296}
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
268306static IrInstruction *ir_create_const_type(IrBuilder *irb, AstNode *source_node, TypeTableEntry *type_entry) {
269307 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(irb->exec, source_node);
270308 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_
356394 return new_instruction;
357395}
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
359458static IrInstruction *ir_build_call(IrBuilder *irb, AstNode *source_node,
360459 IrInstruction *fn, size_t arg_count, IrInstruction **args)
361460{
......@@ -564,6 +663,33 @@ static IrInstruction *ir_build_load_ptr_from(IrBuilder *irb, IrInstruction *old_
564663 return new_instruction;
565664}
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
567693//static size_t get_conditional_defer_count(BlockContext *inner_block, BlockContext *outer_block) {
568694// size_t result = 0;
569695// while (inner_block != outer_block) {
......@@ -648,11 +774,11 @@ static void ir_set_cursor_at_end(IrBuilder *irb, IrBasicBlock *basic_block) {
648774 irb->current_basic_block = basic_block;
649775}
650776
651static VariableTableEntry *add_local_var(CodeGen *codegen, AstNode *node, Buf *name,
652 bool is_const, bool is_shadowable)
777static VariableTableEntry *add_local_var(CodeGen *codegen, AstNode *node, BlockContext *scope,
778 Buf *name, bool is_const, bool is_shadowable)
653779{
654780 VariableTableEntry *variable_entry = allocate<VariableTableEntry>(1);
655 variable_entry->block_context = node->block_context;
781 variable_entry->block_context = scope;
656782 variable_entry->import = node->owner;
657783 variable_entry->shadowable = is_shadowable;
658784 variable_entry->mem_slot_index = SIZE_MAX;
......@@ -686,6 +812,7 @@ static VariableTableEntry *add_local_var(CodeGen *codegen, AstNode *node, Buf *n
686812
687813 node->block_context->var_table.put(&variable_entry->name, variable_entry);
688814 } else {
815 assert(is_shadowable);
689816 // TODO replace _anon with @anon and make sure all tests still pass
690817 buf_init_from_str(&variable_entry->name, "_anon");
691818 }
......@@ -697,10 +824,10 @@ static VariableTableEntry *add_local_var(CodeGen *codegen, AstNode *node, Buf *n
697824}
698825
699826// 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,
701828 bool is_const, bool is_shadowable)
702829{
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);
704831 var->mem_slot_index = exec_next_mem_slot(irb->exec);
705832 return var;
706833}
......@@ -963,6 +1090,23 @@ static IrInstruction *ir_gen_array_access(IrBuilder *irb, AstNode *node, LValPur
9631090 return ir_build_load_ptr(irb, node, ptr_instruction);
9641091}
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
9661110static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, AstNode *node) {
9671111 assert(node->type == NodeTypeFnCallExpr);
9681112
......@@ -990,6 +1134,12 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, AstNode *node) {
9901134
9911135 if (builtin_fn->id == BuiltinFnIdUnreachable) {
9921136 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);
9931143 }
9941144
9951145 IrInstruction **args = allocate<IrInstruction *>(actual_param_count);
......@@ -1183,7 +1333,8 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, AstNode *node) {
11831333 bool is_shadowable = false;
11841334 bool is_const = variable_declaration->is_const;
11851335 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
11881339 if (!is_extern && !variable_declaration->expr) {
11891340 var->type = irb->codegen->builtin_types.entry_invalid;
......@@ -1232,6 +1383,102 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, AstNode *node) {
12321383 return ir_build_const_void(irb, node);
12331384}
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
12351482static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockContext *block_context,
12361483 LValPurpose lval)
12371484{
......@@ -1259,16 +1506,18 @@ static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockCont
12591506 return ir_gen_var_decl(irb, node);
12601507 case NodeTypeWhileExpr:
12611508 return ir_gen_while_expr(irb, node);
1509 case NodeTypeForExpr:
1510 return ir_gen_for_expr(irb, node);
12621511 case NodeTypeArrayAccessExpr:
12631512 return ir_gen_array_access(irb, node, lval);
12641513 case NodeTypeReturnExpr:
12651514 return ir_gen_return(irb, node);
1515 case NodeTypeFieldAccessExpr:
1516 return ir_gen_field_access(irb, node, lval);
12661517 case NodeTypeUnwrapErrorExpr:
12671518 case NodeTypeDefer:
12681519 case NodeTypeSliceExpr:
1269 case NodeTypeFieldAccessExpr:
12701520 case NodeTypeIfVarExpr:
1271 case NodeTypeForExpr:
12721521 case NodeTypeAsmExpr:
12731522 case NodeTypeGoto:
12741523 case NodeTypeBreak:
......@@ -1587,6 +1836,12 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira,
15871836 }
15881837 }
15891838
1839 // implicit undefined literal to anything
1840 if (actual_type->id == TypeTableEntryIdUndefLit) {
1841 return ImplicitCastMatchResultYes;
1842 }
1843
1844
15901845 return ImplicitCastMatchResultNo;
15911846}
15921847
......@@ -1661,6 +1916,45 @@ static ConstExprValue *ir_get_out_val(IrInstruction *instruction) {
16611916 return &instruction->static_value;
16621917}
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
16641958static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr,
16651959 IrInstruction *dest_type, IrInstruction *value)
16661960{
......@@ -1911,6 +2205,11 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
19112205 return ir_resolve_cast(ira, source_instr, value, dest_type, CastOpEnumToInt, false);
19122206 }
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
19142213 add_node_error(ira->codegen, source_instr->source_node,
19152214 buf_sprintf("invalid cast from type '%s' to '%s'",
19162215 buf_ptr(&actual_type->name),
......@@ -1918,26 +2217,6 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
19182217 return ira->codegen->invalid_instruction;
19192218}
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
19412220static IrInstruction *ir_get_casted_value(IrAnalyze *ira, IrInstruction *value, TypeTableEntry *expected_type) {
19422221 assert(value);
19432222 assert(value != ira->codegen->invalid_instruction);
......@@ -1976,14 +2255,22 @@ static IrInstruction *ir_get_casted_value(IrAnalyze *ira, IrInstruction *value,
19762255static TypeTableEntry *ir_analyze_instruction_return(IrAnalyze *ira,
19772256 IrInstructionReturn *return_instruction)
19782257{
1979 IrInstruction *value = ir_get_casted_value(ira, return_instruction->value->other, ira->explicit_return_type);
1980 if (value == ira->codegen->invalid_instruction)
1981 return ira->codegen->builtin_types.entry_invalid;
2258 IrInstruction *value = return_instruction->value->other;
2259 if (value == ira->codegen->invalid_instruction) {
2260 ir_finish_bb(ira);
2261 return ira->codegen->builtin_types.entry_unreachable;
2262 }
19822263 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);
19852272 ir_finish_bb(ira);
1986 return new_instruction->type_entry;
2273 return ira->codegen->builtin_types.entry_unreachable;
19872274}
19882275
19892276static TypeTableEntry *ir_analyze_instruction_const(IrAnalyze *ira, IrInstructionConst *const_instruction) {
......@@ -2354,6 +2641,10 @@ static TypeTableEntry *ir_analyze_instruction_bin_op(IrAnalyze *ira, IrInstructi
23542641}
23552642
23562643static 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
23572648 VariableTableEntry *var = decl_var_instruction->var;
23582649 AstNodeVariableDeclaration *variable_declaration = &var->decl_node->data.variable_declaration;
23592650 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
23652656 IrInstruction *var_type = nullptr;
23662657 if (decl_var_instruction->var_type != nullptr) {
23672658 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);
23692660 explicit_type = validate_var_type(ira->codegen, var_type->source_node, proposed_type);
23702661 if (explicit_type->id == TypeTableEntryIdInvalid)
23712662 return explicit_type;
23722663 }
23732664
2374 IrInstruction *init_value = decl_var_instruction->init_value->other;
23752665 IrInstruction *casted_init_value = ir_get_casted_value(ira, init_value, explicit_type);
23762666 TypeTableEntry *result_type = get_underlying_type(casted_init_value->type_entry);
23772667 switch (result_type->id) {
......@@ -2423,7 +2713,7 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc
24232713 }
24242714
24252715 var->type = result_type;
2426 assert(var->type != nullptr); // should have been caught by the parser
2716 assert(var->type);
24272717
24282718 ConstExprValue *mem_slot = &ira->exec_context.mem_slot_list[var->mem_slot_index];
24292719 *mem_slot = casted_init_value->static_value;
......@@ -3480,44 +3770,6 @@ static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructio
34803770// return g->builtin_types.entry_invalid;
34813771// }
34823772// }
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// }
35213773// case BuiltinFnIdCInclude:
35223774// {
35233775// if (!context->c_import_buf) {
......@@ -3867,8 +4119,10 @@ static TypeTableEntry *ir_analyze_instruction_br(IrAnalyze *ira, IrInstructionBr
38674119static TypeTableEntry *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructionCondBr *cond_br_instruction) {
38684120 TypeTableEntry *bool_type = ira->codegen->builtin_types.entry_bool;
38694121 IrInstruction *condition = ir_get_casted_value(ira, cond_br_instruction->condition->other, bool_type);
3870 if (condition == ira->codegen->invalid_instruction)
3871 return ira->codegen->builtin_types.entry_invalid;
4122 if (condition == ira->codegen->invalid_instruction) {
4123 ir_finish_bb(ira);
4124 return ira->codegen->builtin_types.entry_unreachable;
4125 }
38724126
38734127 // TODO detect backward jumps
38744128 if (condition->static_value.ok) {
......@@ -3892,6 +4146,7 @@ static TypeTableEntry *ir_analyze_instruction_builtin_call(IrAnalyze *ira,
38924146 switch (builtin_call_instruction->fn->id) {
38934147 case BuiltinFnIdInvalid:
38944148 case BuiltinFnIdUnreachable:
4149 case BuiltinFnIdTypeof:
38954150 zig_unreachable();
38964151 case BuiltinFnIdMemcpy:
38974152 case BuiltinFnIdMemset:
......@@ -3900,7 +4155,6 @@ static TypeTableEntry *ir_analyze_instruction_builtin_call(IrAnalyze *ira,
39004155 case BuiltinFnIdMaxValue:
39014156 case BuiltinFnIdMinValue:
39024157 case BuiltinFnIdMemberCount:
3903 case BuiltinFnIdTypeof:
39044158 case BuiltinFnIdAddWithOverflow:
39054159 case BuiltinFnIdSubWithOverflow:
39064160 case BuiltinFnIdMulWithOverflow:
......@@ -3938,9 +4192,9 @@ static TypeTableEntry *ir_analyze_instruction_builtin_call(IrAnalyze *ira,
39384192static TypeTableEntry *ir_analyze_instruction_unreachable(IrAnalyze *ira,
39394193 IrInstructionUnreachable *unreachable_instruction)
39404194{
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);
39424196 ir_finish_bb(ira);
3943 return new_instruction->type_entry;
4197 return ira->codegen->builtin_types.entry_unreachable;
39444198}
39454199
39464200static TypeTableEntry *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPhi *phi_instruction) {
......@@ -3997,7 +4251,10 @@ static TypeTableEntry *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionP
39974251
39984252static TypeTableEntry *ir_analyze_instruction_var_ptr(IrAnalyze *ira, IrInstructionVarPtr *var_ptr_instruction) {
39994253 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);
40014258 // TODO once the anlayze code is fully ported over to IR we won't need this SIZE_MAX thing.
40024259 if (var->mem_slot_index != SIZE_MAX) {
40034260 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
40574314 return return_type;
40584315}
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
40604470static TypeTableEntry *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstructionLoadPtr *load_ptr_instruction) {
40614471 IrInstruction *ptr = load_ptr_instruction->ptr->other;
40624472 TypeTableEntry *type_entry = ptr->type_entry;
......@@ -4084,7 +4494,12 @@ static TypeTableEntry *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstruc
40844494
40854495static TypeTableEntry *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstructionStorePtr *store_ptr_instruction) {
40864496 IrInstruction *ptr = store_ptr_instruction->ptr->other;
4497 if (ptr->type_entry->id == TypeTableEntryIdInvalid)
4498 return ptr->type_entry;
4499
40874500 IrInstruction *value = store_ptr_instruction->value->other;
4501 if (value->type_entry->id == TypeTableEntryIdInvalid)
4502 return value->type_entry;
40884503
40894504 TypeTableEntry *child_type = ptr->type_entry->data.pointer.child_type;
40904505 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
40954510 ConstExprValue *dest_val = ptr->static_value.data.x_ptr.ptr[0];
40964511 if (dest_val->ok) {
40974512 *dest_val = casted_value->static_value;
4098 return ira->codegen->builtin_types.entry_void;
4513 return ir_analyze_void(ira, &store_ptr_instruction->base);
40994514 }
41004515 }
41014516
......@@ -4120,13 +4535,108 @@ static TypeTableEntry *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstru
41204535 }
41214536 new_ptr_inst->type_entry = ptr->type_entry;
41224537 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);
41244539 }
41254540
41264541 ir_build_store_ptr_from(&ira->new_irb, &store_ptr_instruction->base, ptr, casted_value);
41274542 return ira->codegen->builtin_types.entry_void;
41284543}
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
41304640static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
41314641 switch (instruction->id) {
41324642 case IrInstructionIdInvalid:
......@@ -4145,12 +4655,14 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
41454655 return ir_analyze_instruction_load_ptr(ira, (IrInstructionLoadPtr *)instruction);
41464656 case IrInstructionIdStorePtr:
41474657 return ir_analyze_instruction_store_ptr(ira, (IrInstructionStorePtr *)instruction);
4148 case IrInstructionIdFieldPtr:
4149 zig_panic("TODO field ptr");
41504658 case IrInstructionIdElemPtr:
41514659 return ir_analyze_instruction_elem_ptr(ira, (IrInstructionElemPtr *)instruction);
41524660 case IrInstructionIdVarPtr:
41534661 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);
41544666 case IrInstructionIdCall:
41554667 return ir_analyze_instruction_call(ira, (IrInstructionCall *)instruction);
41564668 case IrInstructionIdBr:
......@@ -4163,10 +4675,17 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
41634675 return ir_analyze_instruction_unreachable(ira, (IrInstructionUnreachable *)instruction);
41644676 case IrInstructionIdPhi:
41654677 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);
41664684 case IrInstructionIdSwitchBr:
41674685 case IrInstructionIdCast:
41684686 case IrInstructionIdContainerInitList:
41694687 case IrInstructionIdContainerInitFields:
4688 case IrInstructionIdStructFieldPtr:
41704689 zig_panic("TODO analyze more instructions");
41714690 }
41724691 zig_unreachable();
......@@ -4175,8 +4694,13 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
41754694static TypeTableEntry *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *instruction) {
41764695 TypeTableEntry *instruction_type = ir_analyze_instruction_nocast(ira, instruction);
41774696 instruction->type_entry = instruction_type;
4178 if (instruction->other)
4697 if (instruction->other) {
41794698 instruction->other->type_entry = instruction_type;
4699 } else {
4700 assert(instruction_type->id == TypeTableEntryIdInvalid ||
4701 instruction_type->id == TypeTableEntryIdUnreachable);
4702 instruction->other = instruction;
4703 }
41804704 return instruction_type;
41814705}
41824706
......@@ -4209,6 +4733,11 @@ TypeTableEntry *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutabl
42094733
42104734 while (ira->block_queue_index < ira->old_bb_queue.length) {
42114735 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
42124741 if (old_instruction->ref_count == 0 && !ir_has_side_effects(old_instruction)) {
42134742 ira->instruction_index += 1;
42144743 continue;
......@@ -4299,6 +4828,11 @@ bool ir_has_side_effects(IrInstruction *instruction) {
42994828 case IrInstructionIdFieldPtr:
43004829 case IrInstructionIdElemPtr:
43014830 case IrInstructionIdVarPtr:
4831 case IrInstructionIdTypeOf:
4832 case IrInstructionIdToPtrType:
4833 case IrInstructionIdPtrTypeChild:
4834 case IrInstructionIdReadField:
4835 case IrInstructionIdStructFieldPtr:
43024836 return false;
43034837 case IrInstructionIdBuiltinCall:
43044838 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) {
2222}
2323
2424static 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 }
2535 switch (type_entry->id) {
2636 case TypeTableEntryIdInvalid:
2737 zig_unreachable();
......@@ -343,6 +353,43 @@ static void ir_print_store_ptr(IrPrint *irp, IrInstructionStorePtr *instruction)
343353 ir_print_other_instruction(irp, instruction->value);
344354}
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
346393static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
347394 ir_print_prefix(irp, instruction);
348395 switch (instruction->id) {
......@@ -402,8 +449,25 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
402449 case IrInstructionIdStorePtr:
403450 ir_print_store_ptr(irp, (IrInstructionStorePtr *)instruction);
404451 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;
406461 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:
407471 zig_panic("TODO print more IR instructions");
408472 }
409473 fprintf(irp->f, "\n");