authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-12-04 23:52:43-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-12-04 23:52:43-05:00
log25a89e7a362ab4876139fad7427a2193665cb042
treef84e4d5374c20dd9aa649192384bb9d06f35970d
parent9f23475b172dbe09861c5680ebec2eb96f307cb0

IR: compile time function evaluation


6 files changed, 156 insertions(+), 82 deletions(-)

src/all_types.hpp+3-1
...@@ -46,7 +46,7 @@ struct IrExecutable {...@@ -46,7 +46,7 @@ struct IrExecutable {
46 ZigList<IrBasicBlock *> basic_block_list;46 ZigList<IrBasicBlock *> basic_block_list;
47 size_t mem_slot_count;47 size_t mem_slot_count;
48 size_t next_debug_id;48 size_t next_debug_id;
49 size_t backward_branch_count;49 size_t *backward_branch_count;
50 size_t backward_branch_quota;50 size_t backward_branch_quota;
51 bool invalid;51 bool invalid;
52 ZigList<LabelTableEntry *> all_labels;52 ZigList<LabelTableEntry *> all_labels;
...@@ -968,6 +968,7 @@ struct FnTableEntry {...@@ -968,6 +968,7 @@ struct FnTableEntry {
968 FnAnalState anal_state;968 FnAnalState anal_state;
969 IrExecutable ir_executable;969 IrExecutable ir_executable;
970 IrExecutable analyzed_executable;970 IrExecutable analyzed_executable;
971 size_t prealloc_bbc;
971972
972 AstNode *fn_no_inline_set_node;973 AstNode *fn_no_inline_set_node;
973 AstNode *fn_export_set_node;974 AstNode *fn_export_set_node;
...@@ -1311,6 +1312,7 @@ struct IrBasicBlock {...@@ -1311,6 +1312,7 @@ struct IrBasicBlock {
1311 size_t debug_id;1312 size_t debug_id;
1312 size_t ref_count;1313 size_t ref_count;
1313 LLVMBasicBlockRef llvm_block;1314 LLVMBasicBlockRef llvm_block;
1315 LLVMBasicBlockRef llvm_exit_block;
1314};1316};
13151317
1316enum IrInstructionId {1318enum IrInstructionId {
src/analyze.cpp+5-38
...@@ -873,43 +873,9 @@ TypeTableEntry *get_underlying_type(TypeTableEntry *type_entry) {...@@ -873,43 +873,9 @@ TypeTableEntry *get_underlying_type(TypeTableEntry *type_entry) {
873 }873 }
874}874}
875875
876static IrInstruction *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node,876static IrInstruction *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, TypeTableEntry *type_entry) {
877 TypeTableEntry *expected_type)877 size_t backward_branch_count = 0;
878{878 return ir_eval_const_value(g, scope, node, type_entry, &backward_branch_count, default_backward_branch_quota);
879 IrExecutable ir_executable = {0};
880 ir_executable.is_inline = true;
881 ir_gen(g, node, scope, &ir_executable);
882
883 if (ir_executable.invalid)
884 return g->invalid_instruction;
885
886 if (g->verbose) {
887 fprintf(stderr, "\nSource: ");
888 ast_render(stderr, node, 4);
889 fprintf(stderr, "\n{ // (IR)\n");
890 ir_print(stderr, &ir_executable, 4);
891 fprintf(stderr, "}\n");
892 }
893 IrExecutable analyzed_executable = {0};
894 analyzed_executable.is_inline = true;
895 analyzed_executable.backward_branch_quota = default_backward_branch_quota;
896 TypeTableEntry *result_type = ir_analyze(g, &ir_executable, &analyzed_executable, expected_type, node);
897 if (result_type->id == TypeTableEntryIdInvalid)
898 return g->invalid_instruction;
899
900 if (g->verbose) {
901 fprintf(stderr, "{ // (analyzed)\n");
902 ir_print(stderr, &analyzed_executable, 4);
903 fprintf(stderr, "}\n");
904 }
905
906 IrInstruction *result = ir_exec_const_result(&analyzed_executable);
907 if (!result) {
908 add_node_error(g, node, buf_sprintf("unable to evaluate constant expression"));
909 return g->invalid_instruction;
910 }
911
912 return result;
913}879}
914880
915static TypeTableEntry *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node) {881static TypeTableEntry *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node) {
...@@ -1403,9 +1369,10 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {...@@ -1403,9 +1369,10 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {
1403 }1369 }
14041370
1405 FnTableEntry *fn_table_entry = allocate<FnTableEntry>(1);1371 FnTableEntry *fn_table_entry = allocate<FnTableEntry>(1);
1372 fn_table_entry->analyzed_executable.backward_branch_count = &fn_table_entry->prealloc_bbc;
1406 fn_table_entry->analyzed_executable.backward_branch_quota = default_backward_branch_quota;1373 fn_table_entry->analyzed_executable.backward_branch_quota = default_backward_branch_quota;
1407 fn_table_entry->ir_executable.fn_entry = fn_table_entry;
1408 fn_table_entry->analyzed_executable.fn_entry = fn_table_entry;1374 fn_table_entry->analyzed_executable.fn_entry = fn_table_entry;
1375 fn_table_entry->ir_executable.fn_entry = fn_table_entry;
1409 fn_table_entry->import_entry = import;1376 fn_table_entry->import_entry = import;
1410 fn_table_entry->proto_node = proto_node;1377 fn_table_entry->proto_node = proto_node;
1411 fn_table_entry->fn_def_node = fn_def_node;1378 fn_table_entry->fn_def_node = fn_def_node;
src/codegen.cpp+2-1
...@@ -1758,7 +1758,7 @@ static LLVMValueRef ir_render_phi(CodeGen *g, IrExecutable *executable, IrInstru...@@ -1758,7 +1758,7 @@ static LLVMValueRef ir_render_phi(CodeGen *g, IrExecutable *executable, IrInstru
1758 LLVMBasicBlockRef *incoming_blocks = allocate<LLVMBasicBlockRef>(instruction->incoming_count);1758 LLVMBasicBlockRef *incoming_blocks = allocate<LLVMBasicBlockRef>(instruction->incoming_count);
1759 for (size_t i = 0; i < instruction->incoming_count; i += 1) {1759 for (size_t i = 0; i < instruction->incoming_count; i += 1) {
1760 incoming_values[i] = ir_llvm_value(g, instruction->incoming_values[i]);1760 incoming_values[i] = ir_llvm_value(g, instruction->incoming_values[i]);
1761 incoming_blocks[i] = instruction->incoming_blocks[i]->llvm_block;1761 incoming_blocks[i] = instruction->incoming_blocks[i]->llvm_exit_block;
1762 }1762 }
1763 LLVMAddIncoming(phi, incoming_values, incoming_blocks, instruction->incoming_count);1763 LLVMAddIncoming(phi, incoming_values, incoming_blocks, instruction->incoming_count);
1764 return phi;1764 return phi;
...@@ -1877,6 +1877,7 @@ static void ir_render(CodeGen *g, FnTableEntry *fn_entry) {...@@ -1877,6 +1877,7 @@ static void ir_render(CodeGen *g, FnTableEntry *fn_entry) {
1877 continue;1877 continue;
1878 instruction->llvm_value = ir_render_instruction(g, executable, instruction);1878 instruction->llvm_value = ir_render_instruction(g, executable, instruction);
1879 }1879 }
1880 current_block->llvm_exit_block = LLVMGetInsertBlock(g->builder);
1880 }1881 }
1881}1882}
18821883
src/ir.cpp+125-40
...@@ -6,6 +6,7 @@...@@ -6,6 +6,7 @@
6 */6 */
77
8#include "analyze.hpp"8#include "analyze.hpp"
9#include "ast_render.hpp"
9#include "error.hpp"10#include "error.hpp"
10#include "eval.hpp"11#include "eval.hpp"
11#include "ir.hpp"12#include "ir.hpp"
...@@ -2814,7 +2815,7 @@ IrInstruction *ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutabl...@@ -2814,7 +2815,7 @@ IrInstruction *ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutabl
2814 return return_instruction;2815 return return_instruction;
2815}2816}
28162817
2817IrInstruction *ir_gen_fn(CodeGen *codegn, FnTableEntry *fn_entry) {2818IrInstruction *ir_gen_fn(CodeGen *codegen, FnTableEntry *fn_entry) {
2818 assert(fn_entry);2819 assert(fn_entry);
28192820
2820 IrExecutable *ir_executable = &fn_entry->ir_executable;2821 IrExecutable *ir_executable = &fn_entry->ir_executable;
...@@ -2826,18 +2827,30 @@ IrInstruction *ir_gen_fn(CodeGen *codegn, FnTableEntry *fn_entry) {...@@ -2826,18 +2827,30 @@ IrInstruction *ir_gen_fn(CodeGen *codegn, FnTableEntry *fn_entry) {
2826 assert(fn_entry->child_scope);2827 assert(fn_entry->child_scope);
2827 Scope *child_scope = fn_entry->child_scope;2828 Scope *child_scope = fn_entry->child_scope;
28282829
2829 return ir_gen(codegn, body_node, child_scope, ir_executable);2830 return ir_gen(codegen, body_node, child_scope, ir_executable);
2830}2831}
28312832
2832static ErrorMsg *ir_add_error(IrAnalyze *ira, IrInstruction *source_instruction, Buf *msg) {2833static ErrorMsg *ir_add_error(IrAnalyze *ira, IrInstruction *source_instruction, Buf *msg) {
2834 ira->new_irb.exec->invalid = true;
2833 return add_node_error(ira->codegen, source_instruction->source_node, msg);2835 return add_node_error(ira->codegen, source_instruction->source_node, msg);
2834}2836}
28352837
2836static IrInstruction *ir_eval_fn(IrAnalyze *ira, IrInstruction *source_instruction,2838static IrInstruction *ir_exec_const_result(IrExecutable *exec) {
2837 size_t arg_count, IrInstruction **args)2839 if (exec->basic_block_list.length != 1)
2838{2840 return nullptr;
2839 // TODO count this as part of the backward branch quota2841
2840 zig_panic("TODO ir_eval_fn");2842 IrBasicBlock *bb = exec->basic_block_list.at(0);
2843 if (bb->instruction_list.length != 1)
2844 return nullptr;
2845
2846 IrInstruction *only_inst = bb->instruction_list.at(0);
2847 if (only_inst->id != IrInstructionIdReturn)
2848 return nullptr;
2849
2850 IrInstructionReturn *ret_inst = (IrInstructionReturn *)only_inst;
2851 IrInstruction *value = ret_inst->value;
2852 assert(value->static_value.special != ConstValSpecialRuntime);
2853 return value;
2841}2854}
28422855
2843static bool ir_emit_global_runtime_side_effect(IrAnalyze *ira, IrInstruction *source_instruction) {2856static bool ir_emit_global_runtime_side_effect(IrAnalyze *ira, IrInstruction *source_instruction) {
...@@ -3140,14 +3153,26 @@ static TypeTableEntry *ir_unreach_error(IrAnalyze *ira) {...@@ -3140,14 +3153,26 @@ static TypeTableEntry *ir_unreach_error(IrAnalyze *ira) {
3140 return ira->codegen->builtin_types.entry_unreachable;3153 return ira->codegen->builtin_types.entry_unreachable;
3141}3154}
31423155
3156static bool ir_emit_backward_branch(IrAnalyze *ira, IrInstruction *source_instruction) {
3157 size_t *bbc = ira->new_irb.exec->backward_branch_count;
3158 size_t quota = ira->new_irb.exec->backward_branch_quota;
3159
3160 // If we're already over quota, we've already given an error message for this.
3161 if (*bbc > quota)
3162 return false;
3163
3164 *bbc += 1;
3165 if (*bbc > quota) {
3166 ir_add_error(ira, source_instruction, buf_sprintf("evaluation exceeded %zu backwards branches", quota));
3167 return false;
3168 }
3169 return true;
3170}
3171
3143static TypeTableEntry *ir_inline_bb(IrAnalyze *ira, IrInstruction *source_instruction, IrBasicBlock *old_bb) {3172static TypeTableEntry *ir_inline_bb(IrAnalyze *ira, IrInstruction *source_instruction, IrBasicBlock *old_bb) {
3144 if (old_bb->debug_id <= ira->old_irb.current_basic_block->debug_id) {3173 if (old_bb->debug_id <= ira->old_irb.current_basic_block->debug_id) {
3145 ira->new_irb.exec->backward_branch_count += 1;3174 if (!ir_emit_backward_branch(ira, source_instruction))
3146 if (ira->new_irb.exec->backward_branch_count > ira->new_irb.exec->backward_branch_quota) {
3147 add_node_error(ira->codegen, source_instruction->source_node,
3148 buf_sprintf("evaluation exceeded %zu backwards branches", ira->new_irb.exec->backward_branch_quota));
3149 return ir_unreach_error(ira);3175 return ir_unreach_error(ira);
3150 }
3151 }3176 }
31523177
3153 ir_start_bb(ira, old_bb, ira->old_irb.current_basic_block);3178 ir_start_bb(ira, old_bb, ira->old_irb.current_basic_block);
...@@ -3216,13 +3241,90 @@ static TypeTableEntry *ir_analyze_const_usize(IrAnalyze *ira, IrInstruction *ins...@@ -3216,13 +3241,90 @@ static TypeTableEntry *ir_analyze_const_usize(IrAnalyze *ira, IrInstruction *ins
32163241
3217static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value) {3242static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value) {
3218 if (value->static_value.special != ConstValSpecialStatic) {3243 if (value->static_value.special != ConstValSpecialStatic) {
3219 add_node_error(ira->codegen, value->source_node,3244 ir_add_error(ira, value, buf_sprintf("unable to evaluate constant expression"));
3220 buf_sprintf("unable to evaluate constant expression"));
3221 return nullptr;3245 return nullptr;
3222 }3246 }
3223 return &value->static_value;3247 return &value->static_value;
3224}3248}
32253249
3250IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
3251 TypeTableEntry *expected_type, size_t *backward_branch_count, size_t backward_branch_quota)
3252{
3253 IrExecutable ir_executable = {0};
3254 ir_executable.is_inline = true;
3255 ir_gen(codegen, node, scope, &ir_executable);
3256
3257 if (ir_executable.invalid)
3258 return codegen->invalid_instruction;
3259
3260 if (codegen->verbose) {
3261 fprintf(stderr, "\nSource: ");
3262 ast_render(stderr, node, 4);
3263 fprintf(stderr, "\n{ // (IR)\n");
3264 ir_print(stderr, &ir_executable, 4);
3265 fprintf(stderr, "}\n");
3266 }
3267 IrExecutable analyzed_executable = {0};
3268 analyzed_executable.is_inline = true;
3269 analyzed_executable.backward_branch_count = backward_branch_count;
3270 analyzed_executable.backward_branch_quota = backward_branch_quota;
3271 TypeTableEntry *result_type = ir_analyze(codegen, &ir_executable, &analyzed_executable, expected_type, node);
3272 if (result_type->id == TypeTableEntryIdInvalid)
3273 return codegen->invalid_instruction;
3274
3275 if (codegen->verbose) {
3276 fprintf(stderr, "{ // (analyzed)\n");
3277 ir_print(stderr, &analyzed_executable, 4);
3278 fprintf(stderr, "}\n");
3279 }
3280
3281 IrInstruction *result = ir_exec_const_result(&analyzed_executable);
3282 if (!result) {
3283 add_node_error(codegen, node, buf_sprintf("unable to evaluate constant expression"));
3284 return codegen->invalid_instruction;
3285 }
3286
3287 return result;
3288}
3289
3290static IrInstruction *ir_eval_fn(IrAnalyze *ira, IrInstruction *source_instruction,
3291 FnTableEntry *fn_entry, IrInstruction **args)
3292{
3293 if (!fn_entry) {
3294 ir_add_error(ira, source_instruction,
3295 buf_sprintf("unable to evaluate constant expression"));
3296 return ira->codegen->invalid_instruction;
3297 }
3298
3299 if (!ir_emit_backward_branch(ira, source_instruction))
3300 return ira->codegen->invalid_instruction;
3301
3302 TypeTableEntry *fn_type = fn_entry->type_entry;
3303 FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id;
3304
3305 // Fork a scope of the function with known values for the parameters.
3306
3307 Scope *exec_scope = &fn_entry->fndef_scope->base;
3308 for (size_t i = 0; i < fn_type_id->param_count; i += 1) {
3309 AstNode *param_decl_node = fn_entry->proto_node->data.fn_proto.params.at(i);
3310 Buf *param_name = param_decl_node->data.param_decl.name;
3311 IrInstruction *arg = args[i];
3312 ConstExprValue *arg_val = ir_resolve_const(ira, arg);
3313 if (!arg_val)
3314 return ira->codegen->invalid_instruction;
3315
3316 VariableTableEntry *var = add_variable(ira->codegen, param_decl_node, exec_scope, param_name,
3317 arg->type_entry, true, arg_val);
3318 exec_scope = var->child_scope;
3319 }
3320
3321 // Analyze the fn body block like any other constant expression.
3322
3323 AstNode *body_node = fn_entry->fn_def_node->data.fn_def.body;
3324 return ir_eval_const_value(ira->codegen, exec_scope, body_node, fn_type_id->return_type,
3325 ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota);
3326}
3327
3226static TypeTableEntry *ir_resolve_type_lval(IrAnalyze *ira, IrInstruction *type_value, LValPurpose lval) {3328static TypeTableEntry *ir_resolve_type_lval(IrAnalyze *ira, IrInstruction *type_value, LValPurpose lval) {
3227 if (lval != LValPurposeNone)3329 if (lval != LValPurposeNone)
3228 zig_panic("TODO");3330 zig_panic("TODO");
...@@ -4238,7 +4340,8 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal...@@ -4238,7 +4340,8 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal
4238 return ira->codegen->builtin_types.entry_invalid;4340 return ira->codegen->builtin_types.entry_invalid;
42394341
4240 if (is_inline) {4342 if (is_inline) {
4241 IrInstruction *result = ir_eval_fn(ira, &call_instruction->base, call_param_count, casted_args);4343 assert(call_param_count == fn_type_id->param_count);
4344 IrInstruction *result = ir_eval_fn(ira, &call_instruction->base, fn_entry, casted_args);
4242 if (result->type_entry->id == TypeTableEntryIdInvalid)4345 if (result->type_entry->id == TypeTableEntryIdInvalid)
4243 return ira->codegen->builtin_types.entry_invalid;4346 return ira->codegen->builtin_types.entry_invalid;
42444347
...@@ -4252,9 +4355,9 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal...@@ -4252,9 +4355,9 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal
4252 fn_entry, fn_ref, call_param_count, casted_args);4355 fn_entry, fn_ref, call_param_count, casted_args);
42534356
4254 if (type_has_bits(return_type) && handle_is_ptr(return_type)) {4357 if (type_has_bits(return_type) && handle_is_ptr(return_type)) {
4255 FnTableEntry *fn_entry = exec_fn_entry(ira->new_irb.exec);4358 FnTableEntry *owner_fn = exec_fn_entry(ira->new_irb.exec);
4256 assert(fn_entry);4359 assert(owner_fn);
4257 fn_entry->alloca_list.append(new_call_instruction);4360 owner_fn->alloca_list.append(new_call_instruction);
4258 }4361 }
42594362
4260 return ir_finish_anal(ira, return_type);4363 return ir_finish_anal(ira, return_type);
...@@ -4782,13 +4885,13 @@ static TypeTableEntry *ir_analyze_var_ptr(IrAnalyze *ira, IrInstruction *instruc...@@ -4782,13 +4885,13 @@ static TypeTableEntry *ir_analyze_var_ptr(IrAnalyze *ira, IrInstruction *instruc
47824885
4783 ConstExprValue *mem_slot = nullptr;4886 ConstExprValue *mem_slot = nullptr;
4784 FnTableEntry *fn_entry = scope_fn_entry(var->parent_scope);4887 FnTableEntry *fn_entry = scope_fn_entry(var->parent_scope);
4785 if (fn_entry) {4888 if (var->src_is_const && var->value) {
4889 mem_slot = var->value;
4890 assert(mem_slot->special != ConstValSpecialRuntime);
4891 } else if (fn_entry) {
4786 // TODO once the analyze code is fully ported over to IR we won't need this SIZE_MAX thing.4892 // TODO once the analyze code is fully ported over to IR we won't need this SIZE_MAX thing.
4787 if (var->mem_slot_index != SIZE_MAX)4893 if (var->mem_slot_index != SIZE_MAX)
4788 mem_slot = &ira->exec_context.mem_slot_list[var->mem_slot_index];4894 mem_slot = &ira->exec_context.mem_slot_list[var->mem_slot_index];
4789 } else if (var->src_is_const) {
4790 mem_slot = var->value;
4791 assert(mem_slot->special != ConstValSpecialRuntime);
4792 }4895 }
47934896
4794 if (mem_slot && mem_slot->special != ConstValSpecialRuntime) {4897 if (mem_slot && mem_slot->special != ConstValSpecialRuntime) {
...@@ -6481,24 +6584,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -6481,24 +6584,6 @@ bool ir_has_side_effects(IrInstruction *instruction) {
6481 zig_unreachable();6584 zig_unreachable();
6482}6585}
64836586
6484IrInstruction *ir_exec_const_result(IrExecutable *exec) {
6485 if (exec->basic_block_list.length != 1)
6486 return nullptr;
6487
6488 IrBasicBlock *bb = exec->basic_block_list.at(0);
6489 if (bb->instruction_list.length != 1)
6490 return nullptr;
6491
6492 IrInstruction *only_inst = bb->instruction_list.at(0);
6493 if (only_inst->id != IrInstructionIdReturn)
6494 return nullptr;
6495
6496 IrInstructionReturn *ret_inst = (IrInstructionReturn *)only_inst;
6497 IrInstruction *value = ret_inst->value;
6498 assert(value->static_value.special != ConstValSpecialRuntime);
6499 return value;
6500}
6501
6502// TODO port over all this commented out code into new IR way of doing things6587// TODO port over all this commented out code into new IR way of doing things
65036588
6504//static TypeTableEntry *analyze_min_max_value(CodeGen *g, ImportTableEntry *import, BlockContext *context,6589//static TypeTableEntry *analyze_min_max_value(CodeGen *g, ImportTableEntry *import, BlockContext *context,
src/ir.hpp+3-2
...@@ -13,11 +13,12 @@...@@ -13,11 +13,12 @@
13IrInstruction *ir_gen(CodeGen *g, AstNode *node, Scope *scope, IrExecutable *ir_executable);13IrInstruction *ir_gen(CodeGen *g, AstNode *node, Scope *scope, IrExecutable *ir_executable);
14IrInstruction *ir_gen_fn(CodeGen *g, FnTableEntry *fn_entry);14IrInstruction *ir_gen_fn(CodeGen *g, FnTableEntry *fn_entry);
1515
16IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
17 TypeTableEntry *expected_type, size_t *backward_branch_count, size_t backward_branch_quota);
18
16TypeTableEntry *ir_analyze(CodeGen *g, IrExecutable *old_executable, IrExecutable *new_executable,19TypeTableEntry *ir_analyze(CodeGen *g, IrExecutable *old_executable, IrExecutable *new_executable,
17 TypeTableEntry *expected_type, AstNode *expected_type_source_node);20 TypeTableEntry *expected_type, AstNode *expected_type_source_node);
1821
19IrInstruction *ir_exec_const_result(IrExecutable *exec);
20
21bool ir_has_side_effects(IrInstruction *instruction);22bool ir_has_side_effects(IrInstruction *instruction);
22ConstExprValue *const_ptr_pointee(ConstExprValue *const_val);23ConstExprValue *const_ptr_pointee(ConstExprValue *const_val);
2324
test/self_hosted2.zig+18
...@@ -96,6 +96,22 @@ fn testStructStatic() {...@@ -96,6 +96,22 @@ fn testStructStatic() {
96 assert(result == 7);96 assert(result == 7);
97}97}
9898
99const should_be_11 = FooA.add(5, 6);
100fn testStaticFnEval() {
101 assert(should_be_11 == 11);
102}
103
104fn fib(x: i32) -> i32 {
105 if (x < 2) x else fib(x - 1) + fib(x - 2)
106}
107
108const fib_7 = fib(7);
109
110fn testCompileTimeFib() {
111 assert(fib_7 == 13);
112}
113
114
99fn assert(ok: bool) {115fn assert(ok: bool) {
100 if (!ok)116 if (!ok)
101 @unreachable();117 @unreachable();
...@@ -111,6 +127,8 @@ fn runAllTests() {...@@ -111,6 +127,8 @@ fn runAllTests() {
111 testNamespaceFnCall();127 testNamespaceFnCall();
112 gotoAndLabels();128 gotoAndLabels();
113 testStructStatic();129 testStructStatic();
130 testStaticFnEval();
131 testCompileTimeFib();
114}132}
115133
116export nakedcc fn _start() -> unreachable {134export nakedcc fn _start() -> unreachable {