authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-10-27 01:08:06-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-10-27 01:08:06-04:00
logbfcd6648e70bfe647b6fea9d6d9a024c4a9169d4
tree2b1c65292a34e10f9324cd0274806a3b76a06a7f
parent44d6f8ffd8eac02747fa0f915b925bb2112570dd

IR can inline loops


6 files changed, 210 insertions(+), 88 deletions(-)

src/all_types.hpp+3
...@@ -1609,6 +1609,9 @@ struct IrInstructionConst {...@@ -1609,6 +1609,9 @@ struct IrInstructionConst {
1609 IrInstruction base;1609 IrInstruction base;
1610};1610};
16111611
1612// When an IrExecutable is not in a function, a return instruction means that
1613// the expression returns with that value, even though a return statement from
1614// an AST perspective is invalid.
1612struct IrInstructionReturn {1615struct IrInstructionReturn {
1613 IrInstruction base;1616 IrInstruction base;
16141617
src/analyze.cpp+1-1
...@@ -5314,7 +5314,7 @@ static void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry) {...@@ -5314,7 +5314,7 @@ static void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry) {
5314 }5314 }
53155315
5316 TypeTableEntry *block_return_type = ir_analyze(g, &fn_table_entry->ir_executable,5316 TypeTableEntry *block_return_type = ir_analyze(g, &fn_table_entry->ir_executable,
5317 &fn_table_entry->analyzed_executable, expected_type);5317 &fn_table_entry->analyzed_executable, expected_type, fn_proto->return_type);
5318 node->data.fn_def.implicit_return_type = block_return_type;5318 node->data.fn_def.implicit_return_type = block_return_type;
53195319
5320 if (g->verbose) {5320 if (g->verbose) {
src/codegen.cpp+45-3
...@@ -2864,6 +2864,48 @@ static LLVMValueRef ir_render_var_ptr(CodeGen *g, IrExecutable *executable, IrIn...@@ -2864,6 +2864,48 @@ static LLVMValueRef ir_render_var_ptr(CodeGen *g, IrExecutable *executable, IrIn
2864 return instruction->var->value_ref;2864 return instruction->var->value_ref;
2865}2865}
28662866
2867static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstructionCall *instruction) {
2868 LLVMValueRef fn_val = ir_llvm_value(g, instruction->fn);
2869 TypeTableEntry *fn_type = instruction->fn->type_entry;
2870 TypeTableEntry *src_return_type = fn_type->data.fn.fn_type_id.return_type;
2871 bool ret_has_bits = type_has_bits(src_return_type);
2872 size_t fn_call_param_count = instruction->arg_count;
2873 bool first_arg_ret = ret_has_bits && handle_is_ptr(src_return_type);
2874 size_t actual_param_count = fn_call_param_count + (first_arg_ret ? 1 : 0);
2875 bool is_var_args = fn_type->data.fn.fn_type_id.is_var_args;
2876 LLVMValueRef *gen_param_values = allocate<LLVMValueRef>(actual_param_count);
2877 size_t gen_param_index = 0;
2878 if (first_arg_ret) {
2879 zig_panic("TODO");
2880 //gen_param_values[gen_param_index] = node->data.fn_call_expr.tmp_ptr;
2881 //gen_param_index += 1;
2882 }
2883 for (size_t call_i = 0; call_i < fn_call_param_count; call_i += 1) {
2884 IrInstruction *param_instruction = instruction->args[call_i];
2885 LLVMValueRef param_value = ir_llvm_value(g, param_instruction);
2886 assert(param_value);
2887 TypeTableEntry *param_type = param_instruction->type_entry;
2888 if (is_var_args || type_has_bits(param_type)) {
2889 gen_param_values[gen_param_index] = param_value;
2890 gen_param_index += 1;
2891 }
2892 }
2893
2894 LLVMValueRef result = ZigLLVMBuildCall(g->builder, fn_val,
2895 gen_param_values, gen_param_index, fn_type->data.fn.calling_convention, "");
2896
2897 if (src_return_type->id == TypeTableEntryIdUnreachable) {
2898 return LLVMBuildUnreachable(g->builder);
2899 } else if (!ret_has_bits) {
2900 return nullptr;
2901 } else if (first_arg_ret) {
2902 zig_panic("TODO");
2903 //return node->data.fn_call_expr.tmp_ptr;
2904 } else {
2905 return result;
2906 }
2907}
2908
2867static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, IrInstruction *instruction) {2909static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, IrInstruction *instruction) {
2868 set_debug_source_node(g, instruction->source_node);2910 set_debug_source_node(g, instruction->source_node);
28692911
...@@ -2891,10 +2933,11 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -2891,10 +2933,11 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
2891 return ir_render_load_ptr(g, executable, (IrInstructionLoadPtr *)instruction);2933 return ir_render_load_ptr(g, executable, (IrInstructionLoadPtr *)instruction);
2892 case IrInstructionIdVarPtr:2934 case IrInstructionIdVarPtr:
2893 return ir_render_var_ptr(g, executable, (IrInstructionVarPtr *)instruction);2935 return ir_render_var_ptr(g, executable, (IrInstructionVarPtr *)instruction);
2936 case IrInstructionIdCall:
2937 return ir_render_call(g, executable, (IrInstructionCall *)instruction);
2894 case IrInstructionIdSwitchBr:2938 case IrInstructionIdSwitchBr:
2895 case IrInstructionIdPhi:2939 case IrInstructionIdPhi:
2896 case IrInstructionIdStorePtr:2940 case IrInstructionIdStorePtr:
2897 case IrInstructionIdCall:
2898 case IrInstructionIdBuiltinCall:2941 case IrInstructionIdBuiltinCall:
2899 case IrInstructionIdContainerInitList:2942 case IrInstructionIdContainerInitList:
2900 case IrInstructionIdContainerInitFields:2943 case IrInstructionIdContainerInitFields:
...@@ -2911,8 +2954,7 @@ static void ir_render(CodeGen *g, FnTableEntry *fn_entry) {...@@ -2911,8 +2954,7 @@ static void ir_render(CodeGen *g, FnTableEntry *fn_entry) {
2911 assert(executable->basic_block_list.length > 0);2954 assert(executable->basic_block_list.length > 0);
2912 for (size_t block_i = 0; block_i < executable->basic_block_list.length; block_i += 1) {2955 for (size_t block_i = 0; block_i < executable->basic_block_list.length; block_i += 1) {
2913 IrBasicBlock *current_block = executable->basic_block_list.at(block_i);2956 IrBasicBlock *current_block = executable->basic_block_list.at(block_i);
2914 if (current_block->ref_count == 0)2957 assert(current_block->ref_count > 0);
2915 continue;
2916 assert(current_block->llvm_block);2958 assert(current_block->llvm_block);
2917 LLVMPositionBuilderAtEnd(g->builder, current_block->llvm_block);2959 LLVMPositionBuilderAtEnd(g->builder, current_block->llvm_block);
2918 for (size_t instr_i = 0; instr_i < current_block->instruction_list.length; instr_i += 1) {2960 for (size_t instr_i = 0; instr_i < current_block->instruction_list.length; instr_i += 1) {
src/ir.cpp+154-82
...@@ -21,6 +21,11 @@ struct IrAnalyze {...@@ -21,6 +21,11 @@ struct IrAnalyze {
21 IrBuilder old_irb;21 IrBuilder old_irb;
22 IrBuilder new_irb;22 IrBuilder new_irb;
23 IrExecContext exec_context;23 IrExecContext exec_context;
24 ZigList<IrBasicBlock *> block_queue;
25 size_t block_queue_index;
26 size_t instruction_index;
27 TypeTableEntry *explicit_return_type;
28 ZigList<IrInstruction *> implicit_return_type_list;
24};29};
2530
26static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, BlockContext *scope);31static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, BlockContext *scope);
...@@ -58,11 +63,6 @@ static void ir_ref_bb(IrBasicBlock *bb) {...@@ -58,11 +63,6 @@ static void ir_ref_bb(IrBasicBlock *bb) {
58 bb->ref_count += 1;63 bb->ref_count += 1;
59}64}
6065
61static void ir_unref_bb(IrBasicBlock *bb) {
62 bb->ref_count -= 1;
63 assert(bb->ref_count != SIZE_MAX);
64}
65
66static void ir_ref_instruction(IrInstruction *instruction) {66static void ir_ref_instruction(IrInstruction *instruction) {
67 instruction->ref_count += 1;67 instruction->ref_count += 1;
68}68}
...@@ -349,6 +349,14 @@ static IrInstruction *ir_build_call(IrBuilder *irb, AstNode *source_node,...@@ -349,6 +349,14 @@ static IrInstruction *ir_build_call(IrBuilder *irb, AstNode *source_node,
349 return &call_instruction->base;349 return &call_instruction->base;
350}350}
351351
352static IrInstruction *ir_build_call_from(IrBuilder *irb, IrInstruction *old_instruction,
353 IrInstruction *fn, size_t arg_count, IrInstruction **args)
354{
355 IrInstruction *new_instruction = ir_build_call(irb, old_instruction->source_node, fn, arg_count, args);
356 ir_link_new_instruction(new_instruction, old_instruction);
357 return new_instruction;
358}
359
352static IrInstruction *ir_build_builtin_call(IrBuilder *irb, AstNode *source_node,360static IrInstruction *ir_build_builtin_call(IrBuilder *irb, AstNode *source_node,
353 BuiltinFnEntry *fn, IrInstruction **args)361 BuiltinFnEntry *fn, IrInstruction **args)
354{362{
...@@ -396,11 +404,11 @@ static IrInstruction *ir_build_br(IrBuilder *irb, AstNode *source_node, IrBasicB...@@ -396,11 +404,11 @@ static IrInstruction *ir_build_br(IrBuilder *irb, AstNode *source_node, IrBasicB
396 return &br_instruction->base;404 return &br_instruction->base;
397}405}
398406
399static IrInstruction *ir_build_br_from(IrBuilder *irb, IrInstruction *old_instruction, IrBasicBlock *dest_block) {407//static IrInstruction *ir_build_br_from(IrBuilder *irb, IrInstruction *old_instruction, IrBasicBlock *dest_block) {
400 IrInstruction *new_instruction = ir_build_br(irb, old_instruction->source_node, dest_block);408// IrInstruction *new_instruction = ir_build_br(irb, old_instruction->source_node, dest_block);
401 ir_link_new_instruction(new_instruction, old_instruction);409// ir_link_new_instruction(new_instruction, old_instruction);
402 return new_instruction;410// return new_instruction;
403}411//}
404412
405static IrInstruction *ir_build_un_op(IrBuilder *irb, AstNode *source_node, IrUnOp op_id, IrInstruction *value) {413static IrInstruction *ir_build_un_op(IrBuilder *irb, AstNode *source_node, IrUnOp op_id, IrInstruction *value) {
406 IrInstructionUnOp *br_instruction = ir_build_instruction<IrInstructionUnOp>(irb, source_node);414 IrInstructionUnOp *br_instruction = ir_build_instruction<IrInstructionUnOp>(irb, source_node);
...@@ -1273,36 +1281,26 @@ static IrInstruction *ir_gen_lvalue(IrBuilder *irb, AstNode *node, BlockContext...@@ -1273,36 +1281,26 @@ static IrInstruction *ir_gen_lvalue(IrBuilder *irb, AstNode *node, BlockContext
1273 zig_unreachable();1281 zig_unreachable();
1274}1282}
12751283
1276static IrInstruction *ir_gen_add_return(CodeGen *g, AstNode *node, BlockContext *scope,1284IrInstruction *ir_gen(CodeGen *codegen, AstNode *node, BlockContext *scope, IrExecutable *ir_executable) {
1277 IrExecutable *ir_executable, bool add_return, LValPurpose lval)
1278{
1279 assert(node->owner);1285 assert(node->owner);
12801286
1281 IrBuilder ir_gen = {0};1287 IrBuilder ir_gen = {0};
1282 IrBuilder *irb = &ir_gen;1288 IrBuilder *irb = &ir_gen;
12831289
1284 irb->codegen = g;1290 irb->codegen = codegen;
1285 irb->exec = ir_executable;1291 irb->exec = ir_executable;
12861292
1287 irb->current_basic_block = ir_build_basic_block(irb, "Entry");1293 irb->current_basic_block = ir_build_basic_block(irb, "Entry");
1288 // Entry block gets a reference because we enter it to begin.1294 // Entry block gets a reference because we enter it to begin.
1289 ir_ref_bb(irb->current_basic_block);1295 ir_ref_bb(irb->current_basic_block);
12901296
1291 IrInstruction *result = ir_gen_node_extra(irb, node, scope, lval);1297 IrInstruction *result = ir_gen_node_extra(irb, node, scope, LValPurposeNone);
1292 assert(result);1298 assert(result);
12931299
1294 if (result == g->invalid_instruction)1300 if (result == codegen->invalid_instruction)
1295 return result;1301 return result;
12961302
1297 if (add_return)1303 return ir_build_return(irb, result->source_node, result);
1298 return ir_build_return(irb, result->source_node, result);
1299
1300 return result;
1301}
1302
1303IrInstruction *ir_gen(CodeGen *codegen, AstNode *node, BlockContext *scope, IrExecutable *ir_executable) {
1304 bool add_return_no = false;
1305 return ir_gen_add_return(codegen, node, scope, ir_executable, add_return_no, LValPurposeNone);
1306}1304}
13071305
1308IrInstruction *ir_gen_fn(CodeGen *codegn, FnTableEntry *fn_entry) {1306IrInstruction *ir_gen_fn(CodeGen *codegn, FnTableEntry *fn_entry) {
...@@ -1315,8 +1313,7 @@ IrInstruction *ir_gen_fn(CodeGen *codegn, FnTableEntry *fn_entry) {...@@ -1315,8 +1313,7 @@ IrInstruction *ir_gen_fn(CodeGen *codegn, FnTableEntry *fn_entry) {
1315 AstNode *body_node = fn_def_node->data.fn_def.body;1313 AstNode *body_node = fn_def_node->data.fn_def.body;
1316 BlockContext *scope = fn_def_node->data.fn_def.block_context;1314 BlockContext *scope = fn_def_node->data.fn_def.block_context;
13171315
1318 bool add_return_yes = true;1316 return ir_gen(codegn, body_node, scope, ir_executable);
1319 return ir_gen_add_return(codegn, body_node, scope, ir_executable, add_return_yes, LValPurposeNone);
1320}1317}
13211318
1322/*1319/*
...@@ -1401,7 +1398,7 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc...@@ -1401,7 +1398,7 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc
1401 return false;1398 return false;
1402}1399}
14031400
1404static TypeTableEntry *ir_determine_peer_types(IrAnalyze *ira, IrInstruction *parent_instruction,1401static TypeTableEntry *ir_determine_peer_types(IrAnalyze *ira, AstNode *source_node,
1405 IrInstruction **instructions, size_t instruction_count)1402 IrInstruction **instructions, size_t instruction_count)
1406{1403{
1407 assert(instruction_count >= 1);1404 assert(instruction_count >= 1);
...@@ -1465,7 +1462,7 @@ static TypeTableEntry *ir_determine_peer_types(IrAnalyze *ira, IrInstruction *pa...@@ -1465,7 +1462,7 @@ static TypeTableEntry *ir_determine_peer_types(IrAnalyze *ira, IrInstruction *pa
1465 return ira->codegen->builtin_types.entry_invalid;1462 return ira->codegen->builtin_types.entry_invalid;
1466 }1463 }
1467 } else {1464 } else {
1468 add_node_error(ira->codegen, parent_instruction->source_node,1465 add_node_error(ira->codegen, source_node,
1469 buf_sprintf("incompatible types: '%s' and '%s'",1466 buf_sprintf("incompatible types: '%s' and '%s'",
1470 buf_ptr(&prev_type->name), buf_ptr(&cur_type->name)));1467 buf_ptr(&prev_type->name), buf_ptr(&cur_type->name)));
14711468
...@@ -1566,10 +1563,10 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira,...@@ -1566,10 +1563,10 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira,
1566 return ImplicitCastMatchResultNo;1563 return ImplicitCastMatchResultNo;
1567}1564}
15681565
1569static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, IrInstruction *parent_instruction,1566static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node,
1570 IrInstruction **instructions, size_t instruction_count)1567 IrInstruction **instructions, size_t instruction_count)
1571{1568{
1572 return ir_determine_peer_types(ira, parent_instruction, instructions, instruction_count);1569 return ir_determine_peer_types(ira, source_node, instructions, instruction_count);
1573}1570}
15741571
1575static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,1572static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
...@@ -1608,9 +1605,29 @@ static bool is_u8(TypeTableEntry *type) {...@@ -1608,9 +1605,29 @@ static bool is_u8(TypeTableEntry *type) {
1608static IrBasicBlock *ir_get_new_bb(IrAnalyze *ira, IrBasicBlock *old_bb) {1605static IrBasicBlock *ir_get_new_bb(IrAnalyze *ira, IrBasicBlock *old_bb) {
1609 if (old_bb->other)1606 if (old_bb->other)
1610 return old_bb->other;1607 return old_bb->other;
1611 return ir_build_bb_from(&ira->new_irb, old_bb);1608 IrBasicBlock *new_bb = ir_build_bb_from(&ira->new_irb, old_bb);
1609 ira->block_queue.append(new_bb);
1610 return new_bb;
1612}1611}
16131612
1613static void ir_finish_bb(IrAnalyze *ira) {
1614 ira->block_queue_index += 1;
1615
1616 if (ira->block_queue_index < ira->block_queue.length) {
1617 IrBasicBlock *old_bb = ira->block_queue.at(ira->block_queue_index);
1618 ira->instruction_index = 0;
1619 ira->new_irb.current_basic_block = ir_get_new_bb(ira, old_bb);
1620 ira->old_irb.current_basic_block = old_bb;
1621 }
1622}
1623
1624static void ir_inline_bb(IrAnalyze *ira, IrBasicBlock *old_bb) {
1625 ira->instruction_index = 0;
1626
1627 ira->old_irb.current_basic_block = old_bb;
1628}
1629
1630
1614static ConstExprValue *ir_get_out_val(IrInstruction *instruction) {1631static ConstExprValue *ir_get_out_val(IrInstruction *instruction) {
1615 instruction->other = instruction;1632 instruction->other = instruction;
1616 return &instruction->static_value;1633 return &instruction->static_value;
...@@ -1942,8 +1959,11 @@ static TypeTableEntry *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructi...@@ -1942,8 +1959,11 @@ static TypeTableEntry *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructi
1942 if (value == ira->codegen->invalid_instruction) {1959 if (value == ira->codegen->invalid_instruction) {
1943 return ira->codegen->builtin_types.entry_invalid;1960 return ira->codegen->builtin_types.entry_invalid;
1944 }1961 }
1962 ira->implicit_return_type_list.append(value);
19451963
1946 return ir_build_return_from(&ira->new_irb, &return_instruction->base, value)->type_entry;1964 IrInstruction *new_instruction = ir_build_return_from(&ira->new_irb, &return_instruction->base, value);
1965 ir_finish_bb(ira);
1966 return new_instruction->type_entry;
1947}1967}
19481968
1949static TypeTableEntry *ir_analyze_instruction_const(IrAnalyze *ira, IrInstructionConst *const_instruction) {1969static TypeTableEntry *ir_analyze_instruction_const(IrAnalyze *ira, IrInstructionConst *const_instruction) {
...@@ -1991,10 +2011,10 @@ static TypeTableEntry *ir_analyze_bin_op_bool(IrAnalyze *ira, IrInstructionBinOp...@@ -1991,10 +2011,10 @@ static TypeTableEntry *ir_analyze_bin_op_bool(IrAnalyze *ira, IrInstructionBinOp
1991}2011}
19922012
1993static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) {2013static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) {
1994 IrInstruction *op1 = bin_op_instruction->op1;2014 IrInstruction *op1 = bin_op_instruction->op1->other;
1995 IrInstruction *op2 = bin_op_instruction->op2;2015 IrInstruction *op2 = bin_op_instruction->op2->other;
1996 IrInstruction *instructions[] = {op1, op2};2016 IrInstruction *instructions[] = {op1, op2};
1997 TypeTableEntry *resolved_type = ir_resolve_peer_types(ira, &bin_op_instruction->base, instructions, 2);2017 TypeTableEntry *resolved_type = ir_resolve_peer_types(ira, bin_op_instruction->base.source_node, instructions, 2);
1998 if (resolved_type->id == TypeTableEntryIdInvalid)2018 if (resolved_type->id == TypeTableEntryIdInvalid)
1999 return resolved_type;2019 return resolved_type;
2000 IrBinOp op_id = bin_op_instruction->op_id;2020 IrBinOp op_id = bin_op_instruction->op_id;
...@@ -2052,9 +2072,60 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp...@@ -2052,9 +2072,60 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp
2052 zig_unreachable();2072 zig_unreachable();
2053 }2073 }
20542074
2055 zig_panic("TODO interpret bin_op_cmp");2075 IrInstruction *casted_op1 = ir_get_casted_value(ira, op1, resolved_type);
2076 if (casted_op1 == ira->codegen->invalid_instruction)
2077 return ira->codegen->builtin_types.entry_invalid;
2078
2079 IrInstruction *casted_op2 = ir_get_casted_value(ira, op2, resolved_type);
2080 if (casted_op2 == ira->codegen->invalid_instruction)
2081 return ira->codegen->builtin_types.entry_invalid;
2082
2083 ConstExprValue *op1_val = &casted_op1->static_value;
2084 ConstExprValue *op2_val = &casted_op2->static_value;
2085 if (op1_val->ok && op2_val->ok) {
2086 bool type_can_gt_lt_cmp = (resolved_type->id == TypeTableEntryIdNumLitFloat ||
2087 resolved_type->id == TypeTableEntryIdNumLitInt ||
2088 resolved_type->id == TypeTableEntryIdFloat ||
2089 resolved_type->id == TypeTableEntryIdInt);
2090 bool answer;
2091 if (type_can_gt_lt_cmp) {
2092 bool (*bignum_cmp)(BigNum *, BigNum *);
2093 if (op_id == IrBinOpCmpEq) {
2094 bignum_cmp = bignum_cmp_eq;
2095 } else if (op_id == IrBinOpCmpNotEq) {
2096 bignum_cmp = bignum_cmp_neq;
2097 } else if (op_id == IrBinOpCmpLessThan) {
2098 bignum_cmp = bignum_cmp_lt;
2099 } else if (op_id == IrBinOpCmpGreaterThan) {
2100 bignum_cmp = bignum_cmp_gt;
2101 } else if (op_id == IrBinOpCmpLessOrEq) {
2102 bignum_cmp = bignum_cmp_lte;
2103 } else if (op_id == IrBinOpCmpGreaterOrEq) {
2104 bignum_cmp = bignum_cmp_gte;
2105 } else {
2106 zig_unreachable();
2107 }
20562108
2057 ir_build_bin_op_from(&ira->new_irb, &bin_op_instruction->base, op_id, op1->other, op2->other);2109 answer = bignum_cmp(&op1_val->data.x_bignum, &op2_val->data.x_bignum);
2110 } else {
2111 bool are_equal = const_values_equal(op1_val, op2_val, resolved_type);
2112 if (op_id == IrBinOpCmpEq) {
2113 answer = are_equal;
2114 } else if (op_id == IrBinOpCmpNotEq) {
2115 answer = !are_equal;
2116 } else {
2117 zig_unreachable();
2118 }
2119 }
2120
2121 ConstExprValue *out_val = ir_get_out_val(&bin_op_instruction->base);
2122 out_val->ok = true;
2123 out_val->depends_on_compile_var = op1_val->depends_on_compile_var || op2_val->depends_on_compile_var;
2124 out_val->data.x_bool = answer;
2125 return ira->codegen->builtin_types.entry_bool;
2126 }
2127
2128 ir_build_bin_op_from(&ira->new_irb, &bin_op_instruction->base, op_id, casted_op1, casted_op2);
20582129
2059 return ira->codegen->builtin_types.entry_bool;2130 return ira->codegen->builtin_types.entry_bool;
2060}2131}
...@@ -2158,7 +2229,7 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp...@@ -2158,7 +2229,7 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
2158 IrInstruction *op1 = bin_op_instruction->op1->other;2229 IrInstruction *op1 = bin_op_instruction->op1->other;
2159 IrInstruction *op2 = bin_op_instruction->op2->other;2230 IrInstruction *op2 = bin_op_instruction->op2->other;
2160 IrInstruction *instructions[] = {op1, op2};2231 IrInstruction *instructions[] = {op1, op2};
2161 TypeTableEntry *resolved_type = ir_resolve_peer_types(ira, &bin_op_instruction->base, instructions, 2);2232 TypeTableEntry *resolved_type = ir_resolve_peer_types(ira, bin_op_instruction->base.source_node, instructions, 2);
2162 if (resolved_type->id == TypeTableEntryIdInvalid)2233 if (resolved_type->id == TypeTableEntryIdInvalid)
2163 return resolved_type;2234 return resolved_type;
2164 IrBinOp op_id = bin_op_instruction->op_id;2235 IrBinOp op_id = bin_op_instruction->op_id;
...@@ -2393,6 +2464,13 @@ static TypeTableEntry *ir_analyze_instruction_call(IrAnalyze *ira, IrInstruction...@@ -2393,6 +2464,13 @@ static TypeTableEntry *ir_analyze_instruction_call(IrAnalyze *ira, IrInstruction
23932464
2394 ir_link_new_instruction(cast_instruction, &call_instruction->base);2465 ir_link_new_instruction(cast_instruction, &call_instruction->base);
2395 return cast_instruction->type_entry;2466 return cast_instruction->type_entry;
2467 } else if (fn_ref->type_entry->id == TypeTableEntryIdFn) {
2468 // TODO fully port over the fn call analyze code to IR
2469 FnTableEntry *fn_table_entry = fn_ref->static_value.data.x_fn;
2470
2471 ir_build_call_from(&ira->new_irb, &call_instruction->base,
2472 call_instruction->fn, call_instruction->arg_count, call_instruction->args);
2473 return fn_table_entry->type_entry;
2396 } else {2474 } else {
2397 zig_panic("TODO analyze more fn call types");2475 zig_panic("TODO analyze more fn call types");
2398 }2476 }
...@@ -3777,9 +3855,15 @@ static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructio...@@ -3777,9 +3855,15 @@ static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructio
37773855
3778static TypeTableEntry *ir_analyze_instruction_br(IrAnalyze *ira, IrInstructionBr *br_instruction) {3856static TypeTableEntry *ir_analyze_instruction_br(IrAnalyze *ira, IrInstructionBr *br_instruction) {
3779 IrBasicBlock *old_dest_block = br_instruction->dest_block;3857 IrBasicBlock *old_dest_block = br_instruction->dest_block;
3780 IrBasicBlock *new_bb = ir_get_new_bb(ira, old_dest_block);3858
3781 ir_build_br_from(&ira->new_irb, &br_instruction->base, new_bb);3859 // TODO detect backward jumps
3860
3861 ir_inline_bb(ira, old_dest_block);
3782 return ira->codegen->builtin_types.entry_unreachable;3862 return ira->codegen->builtin_types.entry_unreachable;
3863
3864 //IrBasicBlock *new_bb = ir_get_new_bb(ira, old_dest_block);
3865 //ir_build_br_from(&ira->new_irb, &br_instruction->base, new_bb);
3866 //return ira->codegen->builtin_types.entry_unreachable;
3783}3867}
37843868
3785static TypeTableEntry *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructionCondBr *cond_br_instruction) {3869static TypeTableEntry *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstructionCondBr *cond_br_instruction) {
...@@ -3787,26 +3871,20 @@ static TypeTableEntry *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstruct...@@ -3787,26 +3871,20 @@ static TypeTableEntry *ir_analyze_instruction_cond_br(IrAnalyze *ira, IrInstruct
3787 IrInstruction *condition = ir_get_casted_value(ira, cond_br_instruction->condition->other, bool_type);3871 IrInstruction *condition = ir_get_casted_value(ira, cond_br_instruction->condition->other, bool_type);
3788 if (condition == ira->codegen->invalid_instruction)3872 if (condition == ira->codegen->invalid_instruction)
3789 return ira->codegen->builtin_types.entry_invalid;3873 return ira->codegen->builtin_types.entry_invalid;
3790 3874
3875 // TODO detect backward jumps
3791 if (condition->static_value.ok) {3876 if (condition->static_value.ok) {
3792 IrBasicBlock *old_dest_block;3877 IrBasicBlock *old_dest_block = condition->static_value.data.x_bool ?
3793 IrBasicBlock *old_ignored_block;3878 cond_br_instruction->then_block : cond_br_instruction->else_block;
3794 if (condition->static_value.data.x_bool) {3879
3795 old_dest_block = cond_br_instruction->then_block;3880 ir_inline_bb(ira, old_dest_block);
3796 old_ignored_block = cond_br_instruction->else_block;
3797 } else {
3798 old_dest_block = cond_br_instruction->else_block;
3799 old_ignored_block = cond_br_instruction->then_block;
3800 }
3801 ir_unref_bb(old_ignored_block);
3802 IrBasicBlock *new_bb = ir_get_new_bb(ira, old_dest_block);
3803 ir_build_br_from(&ira->new_irb, &cond_br_instruction->base, new_bb);
3804 return ira->codegen->builtin_types.entry_unreachable;3881 return ira->codegen->builtin_types.entry_unreachable;
3805 }3882 }
38063883
3807 IrBasicBlock *new_then_block = ir_get_new_bb(ira, cond_br_instruction->then_block);3884 IrBasicBlock *new_then_block = ir_get_new_bb(ira, cond_br_instruction->then_block);
3808 IrBasicBlock *new_else_block = ir_get_new_bb(ira, cond_br_instruction->else_block);3885 IrBasicBlock *new_else_block = ir_get_new_bb(ira, cond_br_instruction->else_block);
3809 ir_build_cond_br_from(&ira->new_irb, &cond_br_instruction->base, condition, new_then_block, new_else_block);3886 ir_build_cond_br_from(&ira->new_irb, &cond_br_instruction->base, condition, new_then_block, new_else_block);
3887 ir_finish_bb(ira);
3810 return ira->codegen->builtin_types.entry_unreachable;3888 return ira->codegen->builtin_types.entry_unreachable;
3811}3889}
38123890
...@@ -3862,7 +3940,9 @@ static TypeTableEntry *ir_analyze_instruction_builtin_call(IrAnalyze *ira,...@@ -3862,7 +3940,9 @@ static TypeTableEntry *ir_analyze_instruction_builtin_call(IrAnalyze *ira,
3862static TypeTableEntry *ir_analyze_instruction_unreachable(IrAnalyze *ira,3940static TypeTableEntry *ir_analyze_instruction_unreachable(IrAnalyze *ira,
3863 IrInstructionUnreachable *unreachable_instruction)3941 IrInstructionUnreachable *unreachable_instruction)
3864{3942{
3865 return ir_build_unreachable_from(&ira->new_irb, &unreachable_instruction->base)->type_entry;3943 IrInstruction *new_instruction = ir_build_unreachable_from(&ira->new_irb, &unreachable_instruction->base);
3944 ir_finish_bb(ira);
3945 return new_instruction->type_entry;
3866}3946}
38673947
3868static TypeTableEntry *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPhi *phi_instruction) {3948static TypeTableEntry *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPhi *phi_instruction) {
...@@ -3889,7 +3969,7 @@ static TypeTableEntry *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionP...@@ -3889,7 +3969,7 @@ static TypeTableEntry *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionP
3889 return first_value->type_entry;3969 return first_value->type_entry;
3890 }3970 }
38913971
3892 TypeTableEntry *resolved_type = ir_resolve_peer_types(ira, &phi_instruction->base,3972 TypeTableEntry *resolved_type = ir_resolve_peer_types(ira, phi_instruction->base.source_node,
3893 new_incoming_values.items, new_incoming_values.length);3973 new_incoming_values.items, new_incoming_values.length);
3894 if (resolved_type->id == TypeTableEntryIdInvalid)3974 if (resolved_type->id == TypeTableEntryIdInvalid)
3895 return resolved_type;3975 return resolved_type;
...@@ -4014,8 +4094,6 @@ static TypeTableEntry *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *ins...@@ -4014,8 +4094,6 @@ static TypeTableEntry *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *ins
4014{4094{
4015 TypeTableEntry *instruction_type = ir_analyze_instruction_nocast(ira, instruction);4095 TypeTableEntry *instruction_type = ir_analyze_instruction_nocast(ira, instruction);
4016 instruction->type_entry = instruction_type;4096 instruction->type_entry = instruction_type;
4017 if (instruction->other)
4018 instruction->other->type_entry = instruction_type;
40194097
4020 IrInstruction *casted_instruction = ir_get_casted_value(ira, instruction, expected_type);4098 IrInstruction *casted_instruction = ir_get_casted_value(ira, instruction, expected_type);
4021 return casted_instruction->type_entry;4099 return casted_instruction->type_entry;
...@@ -4024,11 +4102,12 @@ static TypeTableEntry *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *ins...@@ -4024,11 +4102,12 @@ static TypeTableEntry *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *ins
4024// This function attempts to evaluate IR code while doing type checking and other analysis.4102// This function attempts to evaluate IR code while doing type checking and other analysis.
4025// It emits a new IrExecutable which is partially evaluated IR code.4103// It emits a new IrExecutable which is partially evaluated IR code.
4026TypeTableEntry *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_exec,4104TypeTableEntry *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_exec,
4027 TypeTableEntry *expected_type)4105 TypeTableEntry *expected_type, AstNode *expected_type_source_node)
4028{4106{
4029 IrAnalyze ir_analyze_data = {};4107 IrAnalyze ir_analyze_data = {};
4030 IrAnalyze *ira = &ir_analyze_data;4108 IrAnalyze *ira = &ir_analyze_data;
4031 ira->codegen = codegen;4109 ira->codegen = codegen;
4110 ira->explicit_return_type = expected_type;
40324111
4033 ira->old_irb.codegen = codegen;4112 ira->old_irb.codegen = codegen;
4034 ira->old_irb.exec = old_exec;4113 ira->old_irb.exec = old_exec;
...@@ -4039,34 +4118,27 @@ TypeTableEntry *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutabl...@@ -4039,34 +4118,27 @@ TypeTableEntry *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutabl
4039 ira->exec_context.mem_slot_count = ira->old_irb.exec->mem_slot_count;4118 ira->exec_context.mem_slot_count = ira->old_irb.exec->mem_slot_count;
4040 ira->exec_context.mem_slot_list = allocate<ConstExprValue>(ira->exec_context.mem_slot_count);4119 ira->exec_context.mem_slot_list = allocate<ConstExprValue>(ira->exec_context.mem_slot_count);
40414120
4042 TypeTableEntry *return_type = ira->codegen->builtin_types.entry_void;4121 IrBasicBlock *old_entry_bb = ira->old_irb.exec->basic_block_list.at(0);
4043 for (size_t bb_i = 0; bb_i < ira->old_irb.exec->basic_block_list.length; bb_i += 1) {4122 IrBasicBlock *new_entry_bb = ir_get_new_bb(ira, old_entry_bb);
4044 ira->old_irb.current_basic_block = ira->old_irb.exec->basic_block_list.at(bb_i);4123 ir_ref_bb(new_entry_bb);
4045 if (ira->old_irb.current_basic_block->ref_count == 0)4124 ira->old_irb.current_basic_block = old_entry_bb;
4046 continue;4125 ira->new_irb.current_basic_block = new_entry_bb;
4126 ira->block_queue_index = 0;
4127 ira->instruction_index = 0;
40474128
4048 ira->new_irb.current_basic_block = ir_get_new_bb(ira, ira->old_irb.current_basic_block);4129 while (ira->block_queue_index < ira->block_queue.length) {
4130 IrInstruction *old_instruction = ira->old_irb.current_basic_block->instruction_list.at(ira->instruction_index);
4131 TypeTableEntry *return_type = ir_analyze_instruction(ira, old_instruction, nullptr);
40494132
4050 return_type = ira->codegen->builtin_types.entry_void;4133 // unreachable instructions do their own control flow.
4134 if (return_type->id == TypeTableEntryIdUnreachable)
4135 continue;
40514136
4052 for (size_t instr_i = 0; instr_i < ira->old_irb.current_basic_block->instruction_list.length; instr_i += 1) {4137 ira->instruction_index += 1;
4053 IrInstruction *instruction = ira->old_irb.current_basic_block->instruction_list.at(instr_i);
4054 if (return_type->id == TypeTableEntryIdUnreachable) {
4055 // TODO
4056 //add_node_error(ira->codegen, first_executing_node(instruction->source_node),
4057 // buf_sprintf("unreachable code"));
4058 break;
4059 }
4060 bool is_last = (instr_i == ira->old_irb.current_basic_block->instruction_list.length - 1);
4061 TypeTableEntry *passed_expected_type = is_last ? expected_type : nullptr;
4062 return_type = ir_analyze_instruction(ira, instruction, passed_expected_type);
4063 }
4064 }4138 }
40654139
4066 // Give entry block a ref4140 return ir_resolve_peer_types(ira, expected_type_source_node, ira->implicit_return_type_list.items,
4067 ir_ref_bb(ira->new_irb.exec->basic_block_list.at(0));4141 ira->implicit_return_type_list.length);
4068
4069 return return_type;
4070}4142}
40714143
4072static bool ir_builtin_call_has_side_effects(IrInstructionBuiltinCall *call_instruction) {4144static bool ir_builtin_call_has_side_effects(IrInstructionBuiltinCall *call_instruction) {
src/ir.hpp+1-1
...@@ -14,7 +14,7 @@ IrInstruction *ir_gen(CodeGen *g, AstNode *node, BlockContext *scope, IrExecutab...@@ -14,7 +14,7 @@ IrInstruction *ir_gen(CodeGen *g, AstNode *node, BlockContext *scope, IrExecutab
14IrInstruction *ir_gen_fn(CodeGen *g, FnTableEntry *fn_entry);14IrInstruction *ir_gen_fn(CodeGen *g, FnTableEntry *fn_entry);
1515
16TypeTableEntry *ir_analyze(CodeGen *g, IrExecutable *old_executable, IrExecutable *new_executable,16TypeTableEntry *ir_analyze(CodeGen *g, IrExecutable *old_executable, IrExecutable *new_executable,
17 TypeTableEntry *expected_type);17 TypeTableEntry *expected_type, AstNode *expected_type_source_node);
1818
19bool ir_has_side_effects(IrInstruction *instruction);19bool ir_has_side_effects(IrInstruction *instruction);
2020
src/ir_print.cpp+6-1
...@@ -62,6 +62,12 @@ static void ir_print_const_value(IrPrint *irp, TypeTableEntry *type_entry, Const...@@ -62,6 +62,12 @@ static void ir_print_const_value(IrPrint *irp, TypeTableEntry *type_entry, Const
62 fprintf(irp->f, "&");62 fprintf(irp->f, "&");
63 ir_print_const_value(irp, type_entry->data.pointer.child_type, const_val->data.x_ptr.ptr[0]);63 ir_print_const_value(irp, type_entry->data.pointer.child_type, const_val->data.x_ptr.ptr[0]);
64 break;64 break;
65 case TypeTableEntryIdFn:
66 {
67 FnTableEntry *fn_entry = const_val->data.x_fn;
68 fprintf(irp->f, "%s", buf_ptr(&fn_entry->symbol_name));
69 break;
70 }
65 case TypeTableEntryIdVar:71 case TypeTableEntryIdVar:
66 case TypeTableEntryIdFloat:72 case TypeTableEntryIdFloat:
67 case TypeTableEntryIdArray:73 case TypeTableEntryIdArray:
...@@ -73,7 +79,6 @@ static void ir_print_const_value(IrPrint *irp, TypeTableEntry *type_entry, Const...@@ -73,7 +79,6 @@ static void ir_print_const_value(IrPrint *irp, TypeTableEntry *type_entry, Const
73 case TypeTableEntryIdPureError:79 case TypeTableEntryIdPureError:
74 case TypeTableEntryIdEnum:80 case TypeTableEntryIdEnum:
75 case TypeTableEntryIdUnion:81 case TypeTableEntryIdUnion:
76 case TypeTableEntryIdFn:
77 case TypeTableEntryIdTypeDecl:82 case TypeTableEntryIdTypeDecl:
78 case TypeTableEntryIdNamespace:83 case TypeTableEntryIdNamespace:
79 case TypeTableEntryIdBlock:84 case TypeTableEntryIdBlock: