authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-10-23 01:33:23-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-10-23 01:33:23-04:00
log44d6f8ffd8eac02747fa0f915b925bb2112570dd
treec639d5e548cf25e01255226821dc0245509e71de
parentd7a2b05a813a7badf0606726c9a4b1423befd437

IR supports variable assignment


5 files changed, 106 insertions(+), 68 deletions(-)

src/all_types.hpp+6
......@@ -1645,4 +1645,10 @@ struct IrInstructionUnreachable {
16451645 IrInstruction base;
16461646};
16471647
1648enum LValPurpose {
1649 LValPurposeNone,
1650 LValPurposeAssign,
1651 LValPurposeAddressOf,
1652};
1653
16481654#endif
src/analyze.cpp-5
......@@ -2700,11 +2700,6 @@ static TypeTableEntry *analyze_slice_expr(CodeGen *g, ImportTableEntry *import,
27002700 return return_type;
27012701}
27022702
2703enum LValPurpose {
2704 LValPurposeAssign,
2705 LValPurposeAddressOf,
2706};
2707
27082703static TypeTableEntry *analyze_array_access_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
27092704 AstNode *node, LValPurpose purpose)
27102705{
src/codegen.cpp+5
......@@ -2808,6 +2808,9 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,
28082808 if (!type_has_bits(var->type))
28092809 return nullptr;
28102810
2811 if (var->ref_count == 0)
2812 return nullptr;
2813
28112814 IrInstruction *init_value = decl_var_instruction->init_value;
28122815
28132816 bool have_init_expr = false;
......@@ -4348,6 +4351,8 @@ static void do_code_gen(CodeGen *g) {
43484351 if (!type_has_bits(var->type)) {
43494352 continue;
43504353 }
4354 if (var->ref_count == 0)
4355 continue;
43514356
43524357 if (var->block_context->node->type == NodeTypeFnDef) {
43534358 assert(var->gen_arg_index != SIZE_MAX);
src/ir.cpp+85-62
......@@ -24,7 +24,7 @@ struct IrAnalyze {
2424};
2525
2626static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, BlockContext *scope);
27static IrInstruction *ir_gen_lvalue(IrBuilder *irb, AstNode *node, BlockContext *scope);
27static IrInstruction *ir_gen_lvalue(IrBuilder *irb, AstNode *node, BlockContext *scope, LValPurpose purpose);
2828
2929static void ir_instruction_append(IrBasicBlock *basic_block, IrInstruction *instruction) {
3030 assert(basic_block);
......@@ -293,37 +293,6 @@ static IrInstruction *ir_build_const_generic_fn(IrBuilder *irb, AstNode *source_
293293 return &const_instruction->base;
294294}
295295
296static IrInstruction *ir_build_const_ptr(IrBuilder *irb, AstNode *source_node, ConstExprValue *pointee) {
297 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node);
298 const_instruction->base.static_value.ok = true;
299 const_instruction->base.static_value.data.x_ptr.len = 1;
300 const_instruction->base.static_value.data.x_ptr.is_c_str = false;
301 const_instruction->base.static_value.data.x_ptr.ptr = allocate<ConstExprValue *>(1);
302 const_instruction->base.static_value.data.x_ptr.ptr[0] = pointee;
303 return &const_instruction->base;
304}
305
306static IrInstruction *ir_build_const_ptr_from(IrBuilder *irb, IrInstruction *old_instruction,
307 ConstExprValue *pointee)
308{
309 IrInstruction *new_instruction = ir_build_const_ptr(irb, old_instruction->source_node, pointee);
310 ir_link_new_instruction(new_instruction, old_instruction);
311 return new_instruction;
312}
313
314static IrInstruction *ir_build_const(IrBuilder *irb, AstNode *source_node, ConstExprValue *value) {
315 IrInstructionConst *instruction = ir_build_instruction<IrInstructionConst>(irb, source_node);
316 instruction->base.static_value = *value;
317 instruction->base.static_value.ok = true;
318 return &instruction->base;
319}
320
321static IrInstruction *ir_build_const_from(IrBuilder *irb, IrInstruction *old_instruction, ConstExprValue *value) {
322 IrInstruction *new_instruction = ir_build_const(irb, old_instruction->source_node, value);
323 ir_link_new_instruction(new_instruction, old_instruction);
324 return new_instruction;
325}
326
327296static IrInstruction *ir_build_bin_op(IrBuilder *irb, AstNode *source_node, IrBinOp op_id,
328297 IrInstruction *op1, IrInstruction *op2)
329298{
......@@ -515,6 +484,14 @@ static IrInstruction *ir_build_store_ptr(IrBuilder *irb, AstNode *source_node,
515484 return &instruction->base;
516485}
517486
487static IrInstruction *ir_build_store_ptr_from(IrBuilder *irb, IrInstruction *old_instruction,
488 IrInstruction *ptr, IrInstruction *value)
489{
490 IrInstruction *new_instruction = ir_build_store_ptr(irb, old_instruction->source_node, ptr, value);
491 ir_link_new_instruction(new_instruction, old_instruction);
492 return new_instruction;
493}
494
518495static IrInstruction *ir_build_var_decl(IrBuilder *irb, AstNode *source_node,
519496 VariableTableEntry *var, IrInstruction *var_type, IrInstruction *init_value)
520497{
......@@ -688,8 +665,21 @@ static IrInstruction *ir_gen_bin_op_id(IrBuilder *irb, AstNode *node, IrBinOp op
688665 return ir_build_bin_op(irb, node, op_id, op1, op2);
689666}
690667
668static IrInstruction *ir_gen_assign(IrBuilder *irb, AstNode *node) {
669 IrInstruction *lvalue = ir_gen_lvalue(irb, node->data.bin_op_expr.op1, node->block_context, LValPurposeAssign);
670 if (lvalue == irb->codegen->invalid_instruction)
671 return lvalue;
672
673 IrInstruction *rvalue = ir_gen_node(irb, node->data.bin_op_expr.op2, node->block_context);
674 if (rvalue == irb->codegen->invalid_instruction)
675 return rvalue;
676
677 ir_build_store_ptr(irb, node, lvalue, rvalue);
678 return ir_build_const_void(irb, node);
679}
680
691681static IrInstruction *ir_gen_assign_op(IrBuilder *irb, AstNode *node, IrBinOp op_id) {
692 IrInstruction *lvalue = ir_gen_lvalue(irb, node->data.bin_op_expr.op1, node->block_context);
682 IrInstruction *lvalue = ir_gen_lvalue(irb, node->data.bin_op_expr.op1, node->block_context, LValPurposeAssign);
693683 if (lvalue == irb->codegen->invalid_instruction)
694684 return lvalue;
695685 IrInstruction *op1 = ir_build_load_ptr(irb, node->data.bin_op_expr.op1, lvalue);
......@@ -709,7 +699,7 @@ static IrInstruction *ir_gen_bin_op(IrBuilder *irb, AstNode *node) {
709699 case BinOpTypeInvalid:
710700 zig_unreachable();
711701 case BinOpTypeAssign:
712 zig_panic("TODO gen IR for assignment");
702 return ir_gen_assign(irb, node);
713703 case BinOpTypeAssignTimes:
714704 return ir_gen_assign_op(irb, node, IrBinOpMult);
715705 case BinOpTypeAssignTimesWrap:
......@@ -809,9 +799,9 @@ static IrInstruction *ir_gen_num_lit(IrBuilder *irb, AstNode *node) {
809799}
810800
811801static IrInstruction *ir_gen_decl_ref(IrBuilder *irb, AstNode *source_node, AstNode *decl_node,
812 bool pointer_only, BlockContext *scope)
802 LValPurpose lval, BlockContext *scope)
813803{
814 resolve_top_level_decl(irb->codegen, decl_node, pointer_only);
804 resolve_top_level_decl(irb->codegen, decl_node, lval);
815805 TopLevelDecl *tld = get_as_top_level_decl(decl_node);
816806 if (tld->resolution == TldResolutionInvalid)
817807 return irb->codegen->invalid_instruction;
......@@ -843,27 +833,33 @@ static IrInstruction *ir_gen_decl_ref(IrBuilder *irb, AstNode *source_node, AstN
843833 }
844834}
845835
846static IrInstruction *ir_gen_symbol(IrBuilder *irb, AstNode *node, bool pointer_only) {
836static IrInstruction *ir_gen_symbol(IrBuilder *irb, AstNode *node, LValPurpose lval) {
847837 assert(node->type == NodeTypeSymbol);
848838
849 if (node->data.symbol_expr.override_type_entry)
850 return ir_build_const_type(irb, node, node->data.symbol_expr.override_type_entry);
839 if (node->data.symbol_expr.override_type_entry) {
840 zig_panic("TODO have parseh directly generate IR");
841 }
851842
852843 Buf *variable_name = node->data.symbol_expr.symbol;
853844
854845 auto primitive_table_entry = irb->codegen->primitive_type_table.maybe_get(variable_name);
855 if (primitive_table_entry)
846 if (primitive_table_entry) {
856847 return ir_build_const_type(irb, node, primitive_table_entry->value);
848 }
857849
858850 VariableTableEntry *var = find_variable(irb->codegen, node->block_context, variable_name);
859851 if (var) {
860852 IrInstruction *var_ptr = ir_build_var_ptr(irb, node, var);
861 return ir_build_load_ptr(irb, node, var_ptr);
853 if (lval != LValPurposeNone)
854 return var_ptr;
855 else
856 return ir_build_load_ptr(irb, node, var_ptr);
862857 }
863858
864859 AstNode *decl_node = find_decl(node->block_context, variable_name);
865 if (decl_node)
866 return ir_gen_decl_ref(irb, node, decl_node, pointer_only, node->block_context);
860 if (decl_node) {
861 return ir_gen_decl_ref(irb, node, decl_node, lval, node->block_context);
862 }
867863
868864 if (node->owner->any_imports_failed) {
869865 // skip the error message since we had a failing import in this file
......@@ -1144,9 +1140,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, AstNode *node) {
11441140 return ir_build_const_void(irb, node);
11451141}
11461142
1147static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockContext *block_context,
1148 bool pointer_only)
1149{
1143static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockContext *block_context, LValPurpose lval) {
11501144 assert(block_context);
11511145 node->block_context = block_context;
11521146
......@@ -1158,7 +1152,7 @@ static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockCont
11581152 case NodeTypeNumberLiteral:
11591153 return ir_gen_num_lit(irb, node);
11601154 case NodeTypeSymbol:
1161 return ir_gen_symbol(irb, node, pointer_only);
1155 return ir_gen_symbol(irb, node, lval);
11621156 case NodeTypeFnCallExpr:
11631157 return ir_gen_fn_call(irb, node);
11641158 case NodeTypeIfBoolExpr:
......@@ -1215,16 +1209,15 @@ static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockCont
12151209}
12161210
12171211static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, BlockContext *scope) {
1218 bool pointer_only_no = false;
1219 return ir_gen_node_extra(irb, node, scope, pointer_only_no);
1212 return ir_gen_node_extra(irb, node, scope, LValPurposeNone);
12201213}
12211214
1222static IrInstruction *ir_gen_lvalue(IrBuilder *irb, AstNode *node, BlockContext *scope) {
1215static IrInstruction *ir_gen_lvalue(IrBuilder *irb, AstNode *node, BlockContext *scope, LValPurpose lval) {
12231216 assert(scope);
12241217 node->block_context = scope;
12251218 switch (node->type) {
12261219 case NodeTypeSymbol:
1227 zig_panic("TODO symbol lvalue");
1220 return ir_gen_symbol(irb, node, lval);
12281221 case NodeTypeArrayAccessExpr:
12291222 zig_panic("TODO array access lvalue");
12301223 case NodeTypeFieldAccessExpr:
......@@ -1281,7 +1274,7 @@ static IrInstruction *ir_gen_lvalue(IrBuilder *irb, AstNode *node, BlockContext
12811274}
12821275
12831276static IrInstruction *ir_gen_add_return(CodeGen *g, AstNode *node, BlockContext *scope,
1284 IrExecutable *ir_executable, bool add_return, bool pointer_only)
1277 IrExecutable *ir_executable, bool add_return, LValPurpose lval)
12851278{
12861279 assert(node->owner);
12871280
......@@ -1295,7 +1288,7 @@ static IrInstruction *ir_gen_add_return(CodeGen *g, AstNode *node, BlockContext
12951288 // Entry block gets a reference because we enter it to begin.
12961289 ir_ref_bb(irb->current_basic_block);
12971290
1298 IrInstruction *result = ir_gen_node_extra(irb, node, scope, pointer_only);
1291 IrInstruction *result = ir_gen_node_extra(irb, node, scope, lval);
12991292 assert(result);
13001293
13011294 if (result == g->invalid_instruction)
......@@ -1309,8 +1302,7 @@ static IrInstruction *ir_gen_add_return(CodeGen *g, AstNode *node, BlockContext
13091302
13101303IrInstruction *ir_gen(CodeGen *codegen, AstNode *node, BlockContext *scope, IrExecutable *ir_executable) {
13111304 bool add_return_no = false;
1312 bool pointer_only_no = false;
1313 return ir_gen_add_return(codegen, node, scope, ir_executable, add_return_no, pointer_only_no);
1305 return ir_gen_add_return(codegen, node, scope, ir_executable, add_return_no, LValPurposeNone);
13141306}
13151307
13161308IrInstruction *ir_gen_fn(CodeGen *codegn, FnTableEntry *fn_entry) {
......@@ -1324,8 +1316,7 @@ IrInstruction *ir_gen_fn(CodeGen *codegn, FnTableEntry *fn_entry) {
13241316 BlockContext *scope = fn_def_node->data.fn_def.block_context;
13251317
13261318 bool add_return_yes = true;
1327 bool pointer_only_no = false;
1328 return ir_gen_add_return(codegn, body_node, scope, ir_executable, add_return_yes, pointer_only_no);
1319 return ir_gen_add_return(codegn, body_node, scope, ir_executable, add_return_yes, LValPurposeNone);
13291320}
13301321
13311322/*
......@@ -1620,6 +1611,11 @@ static IrBasicBlock *ir_get_new_bb(IrAnalyze *ira, IrBasicBlock *old_bb) {
16201611 return ir_build_bb_from(&ira->new_irb, old_bb);
16211612}
16221613
1614static ConstExprValue *ir_get_out_val(IrInstruction *instruction) {
1615 instruction->other = instruction;
1616 return &instruction->static_value;
1617}
1618
16231619static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr,
16241620 IrInstruction *dest_type, IrInstruction *value)
16251621{
......@@ -1972,8 +1968,7 @@ static TypeTableEntry *ir_analyze_bin_op_bool(IrAnalyze *ira, IrInstructionBinOp
19721968 ConstExprValue *op1_val = &casted_op1->static_value;
19731969 ConstExprValue *op2_val = &casted_op2->static_value;
19741970 if (op1_val->ok && op2_val->ok) {
1975 ConstExprValue *out_val = &bin_op_instruction->base.static_value;
1976 bin_op_instruction->base.other = &bin_op_instruction->base;
1971 ConstExprValue *out_val = ir_get_out_val(&bin_op_instruction->base);
19771972
19781973 assert(op1->type_entry->id == TypeTableEntryIdBool);
19791974 assert(op2->type_entry->id == TypeTableEntryIdBool);
......@@ -3909,7 +3904,13 @@ static TypeTableEntry *ir_analyze_instruction_var_ptr(IrAnalyze *ira, IrInstruct
39093904 ConstExprValue *mem_slot = &ira->exec_context.mem_slot_list[var->mem_slot_index];
39103905 TypeTableEntry *ptr_type = get_pointer_to_type(ira->codegen, var_ptr_instruction->var->type, false);
39113906 if (mem_slot->ok) {
3912 ir_build_const_ptr_from(&ira->new_irb, &var_ptr_instruction->base, mem_slot);
3907 ConstExprValue *out_val = ir_get_out_val(&var_ptr_instruction->base);
3908
3909 out_val->ok = true;
3910 out_val->data.x_ptr.len = 1;
3911 out_val->data.x_ptr.is_c_str = false;
3912 out_val->data.x_ptr.ptr = allocate<ConstExprValue *>(1);
3913 out_val->data.x_ptr.ptr[0] = mem_slot;
39133914 return ptr_type;
39143915 }
39153916
......@@ -3927,7 +3928,8 @@ static TypeTableEntry *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstruc
39273928 if (ptr->static_value.ok) {
39283929 ConstExprValue *pointee = ptr->static_value.data.x_ptr.ptr[0];
39293930 if (pointee->ok) {
3930 ir_build_const_from(&ira->new_irb, &load_ptr_instruction->base, pointee);
3931 ConstExprValue *out_val = ir_get_out_val(&load_ptr_instruction->base);
3932 *out_val = *pointee;
39313933 return child_type;
39323934 }
39333935 }
......@@ -3941,6 +3943,27 @@ static TypeTableEntry *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstruc
39413943 }
39423944}
39433945
3946static TypeTableEntry *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstructionStorePtr *store_ptr_instruction) {
3947 IrInstruction *ptr = store_ptr_instruction->ptr->other;
3948 IrInstruction *value = store_ptr_instruction->value->other;
3949
3950 TypeTableEntry *child_type = ptr->type_entry->data.pointer.child_type;
3951 IrInstruction *casted_value = ir_get_casted_value(ira, value, child_type);
3952 if (casted_value == ira->codegen->invalid_instruction)
3953 return ira->codegen->builtin_types.entry_invalid;
3954
3955 if (ptr->static_value.ok && casted_value->static_value.ok) {
3956 ConstExprValue *dest_val = ptr->static_value.data.x_ptr.ptr[0];
3957 if (dest_val->ok) {
3958 *dest_val = casted_value->static_value;
3959 return ira->codegen->builtin_types.entry_void;
3960 }
3961 }
3962
3963 ir_build_store_ptr_from(&ira->new_irb, &store_ptr_instruction->base, ptr, casted_value);
3964 return ira->codegen->builtin_types.entry_void;
3965}
3966
39443967static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
39453968 switch (instruction->id) {
39463969 case IrInstructionIdInvalid:
......@@ -3958,7 +3981,7 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
39583981 case IrInstructionIdLoadPtr:
39593982 return ir_analyze_instruction_load_ptr(ira, (IrInstructionLoadPtr *)instruction);
39603983 case IrInstructionIdStorePtr:
3961 zig_panic("TODO store ptr");
3984 return ir_analyze_instruction_store_ptr(ira, (IrInstructionStorePtr *)instruction);
39623985 case IrInstructionIdFieldPtr:
39633986 zig_panic("TODO field ptr");
39643987 case IrInstructionIdElemPtr:
src/ir_print.cpp+10-1
......@@ -326,6 +326,13 @@ static void ir_print_load_ptr(IrPrint *irp, IrInstructionLoadPtr *instruction) {
326326 ir_print_other_instruction(irp, instruction->ptr);
327327}
328328
329static void ir_print_store_ptr(IrPrint *irp, IrInstructionStorePtr *instruction) {
330 fprintf(irp->f, "*");
331 ir_print_other_instruction(irp, instruction->ptr);
332 fprintf(irp->f, " = ");
333 ir_print_other_instruction(irp, instruction->value);
334}
335
329336static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
330337 ir_print_prefix(irp, instruction);
331338 switch (instruction->id) {
......@@ -382,8 +389,10 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
382389 case IrInstructionIdLoadPtr:
383390 ir_print_load_ptr(irp, (IrInstructionLoadPtr *)instruction);
384391 break;
385 case IrInstructionIdSwitchBr:
386392 case IrInstructionIdStorePtr:
393 ir_print_store_ptr(irp, (IrInstructionStorePtr *)instruction);
394 break;
395 case IrInstructionIdSwitchBr:
387396 case IrInstructionIdFieldPtr:
388397 zig_panic("TODO print more IR instructions");
389398 }