authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-09-30 20:12:00-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-09-30 20:12:00-04:00
log633781e31dedaa27d9692d56f6cf073931ca311a
tree64f05abeb6225a8c45164a073afe02bb2af47ec0
parent4e2fa2d15be248c29051a58995e38caa0b1de0a5

empty function compiles successfully with IR


10 files changed, 610 insertions(+), 248 deletions(-)

CMakeLists.txt+1
...@@ -48,6 +48,7 @@ set(ZIG_SOURCES...@@ -48,6 +48,7 @@ set(ZIG_SOURCES
48 "${CMAKE_SOURCE_DIR}/src/error.cpp"48 "${CMAKE_SOURCE_DIR}/src/error.cpp"
49 "${CMAKE_SOURCE_DIR}/src/eval.cpp"49 "${CMAKE_SOURCE_DIR}/src/eval.cpp"
50 "${CMAKE_SOURCE_DIR}/src/ir.cpp"50 "${CMAKE_SOURCE_DIR}/src/ir.cpp"
51 "${CMAKE_SOURCE_DIR}/src/ir_print.cpp"
51 "${CMAKE_SOURCE_DIR}/src/link.cpp"52 "${CMAKE_SOURCE_DIR}/src/link.cpp"
52 "${CMAKE_SOURCE_DIR}/src/main.cpp"53 "${CMAKE_SOURCE_DIR}/src/main.cpp"
53 "${CMAKE_SOURCE_DIR}/src/os.cpp"54 "${CMAKE_SOURCE_DIR}/src/os.cpp"
src/all_types.hpp+151
...@@ -28,6 +28,14 @@ struct BuiltinFnEntry;...@@ -28,6 +28,14 @@ struct BuiltinFnEntry;
28struct TypeStructField;28struct TypeStructField;
29struct CodeGen;29struct CodeGen;
30struct ConstExprValue;30struct ConstExprValue;
31struct IrInstruction;
32struct IrBasicBlock;
33
34struct IrExecutable {
35 IrBasicBlock **basic_block_list;
36 size_t basic_block_count;
37 size_t next_debug_id;
38};
3139
32enum OutType {40enum OutType {
33 OutTypeUnknown,41 OutTypeUnknown,
...@@ -1105,6 +1113,7 @@ struct FnTableEntry {...@@ -1105,6 +1113,7 @@ struct FnTableEntry {
1105 AstNode *want_pure_return_type;1113 AstNode *want_pure_return_type;
1106 FnInline fn_inline;1114 FnInline fn_inline;
1107 FnAnalState anal_state;1115 FnAnalState anal_state;
1116 IrExecutable ir_executable;
11081117
1109 AstNode *fn_no_inline_set_node;1118 AstNode *fn_no_inline_set_node;
1110 AstNode *fn_export_set_node;1119 AstNode *fn_export_set_node;
...@@ -1317,6 +1326,8 @@ struct CodeGen {...@@ -1317,6 +1326,8 @@ struct CodeGen {
1317 ZigList<AstNode *> error_decls;1326 ZigList<AstNode *> error_decls;
1318 bool generate_error_name_table;1327 bool generate_error_name_table;
1319 LLVMValueRef err_name_table;1328 LLVMValueRef err_name_table;
1329
1330 IrInstruction *invalid_instruction;
1320};1331};
13211332
1322struct VariableTableEntry {1333struct VariableTableEntry {
...@@ -1388,5 +1399,145 @@ enum AtomicOrder {...@@ -1388,5 +1399,145 @@ enum AtomicOrder {
1388 AtomicOrderSeqCst,1399 AtomicOrderSeqCst,
1389};1400};
13901401
1402// A basic block contains no branching. Branches send control flow
1403// to another basic block.
1404// Phi instructions must be first in a basic block.
1405// The last instruction in a basic block must be an expression of type unreachable.
1406struct IrBasicBlock {
1407 IrInstruction *first;
1408 IrInstruction *last;
1409};
1410
1411enum IrInstructionId {
1412 IrInstructionIdInvalid,
1413 IrInstructionIdCondBr,
1414 IrInstructionIdSwitchBr,
1415 IrInstructionIdPhi,
1416 IrInstructionIdBinOp,
1417 IrInstructionIdLoadVar,
1418 IrInstructionIdStoreVar,
1419 IrInstructionIdCall,
1420 IrInstructionIdBuiltinCall,
1421 IrInstructionIdConst,
1422 IrInstructionIdReturn,
1423};
1424
1425struct IrInstruction {
1426 IrInstruction *prev;
1427 IrInstruction *next;
1428
1429 IrInstructionId id;
1430 AstNode *source_node;
1431 ConstExprValue static_value;
1432 TypeTableEntry *type_entry;
1433 size_t debug_id;
1434 LLVMValueRef llvm_value;
1435};
1436
1437struct IrInstructionCondBr {
1438 IrInstruction base;
1439
1440 // If the condition is null, then this is an unconditional branch.
1441 IrInstruction *cond;
1442 IrBasicBlock *dest;
1443};
1444
1445struct IrInstructionSwitchBrCase {
1446 IrInstruction *value;
1447 IrBasicBlock *block;
1448};
1449
1450struct IrInstructionSwitchBr {
1451 IrInstruction base;
1452
1453 IrInstruction *target_value;
1454 IrBasicBlock *else_block;
1455 size_t case_count;
1456 IrInstructionSwitchBrCase *cases;
1457};
1458
1459struct IrInstructionPhi {
1460 IrInstruction base;
1461
1462 size_t incoming_block_count;
1463 IrBasicBlock **incoming_blocks;
1464 IrInstruction **incoming_values;
1465};
1466
1467enum IrBinOp {
1468 IrBinOpInvalid,
1469 IrBinOpBoolOr,
1470 IrBinOpBoolAnd,
1471 IrBinOpCmpEq,
1472 IrBinOpCmpNotEq,
1473 IrBinOpCmpLessThan,
1474 IrBinOpCmpGreaterThan,
1475 IrBinOpCmpLessOrEq,
1476 IrBinOpCmpGreaterOrEq,
1477 IrBinOpBinOr,
1478 IrBinOpBinXor,
1479 IrBinOpBinAnd,
1480 IrBinOpBitShiftLeft,
1481 IrBinOpBitShiftLeftWrap,
1482 IrBinOpBitShiftRight,
1483 IrBinOpAdd,
1484 IrBinOpAddWrap,
1485 IrBinOpSub,
1486 IrBinOpSubWrap,
1487 IrBinOpMult,
1488 IrBinOpMultWrap,
1489 IrBinOpDiv,
1490 IrBinOpMod,
1491 IrBinOpArrayCat,
1492 IrBinOpArrayMult,
1493};
1494
1495struct IrInstructionBinOp {
1496 IrInstruction base;
1497
1498 IrInstruction *op1;
1499 IrBinOp op_id;
1500 IrInstruction *op2;
1501};
1502
1503struct IrInstructionLoadVar {
1504 IrInstruction base;
1505
1506 VariableTableEntry *var;
1507};
1508
1509struct IrInstructionStoreVar {
1510 IrInstruction base;
1511
1512 IrInstruction *value;
1513 VariableTableEntry *var;
1514};
1515
1516struct IrInstructionCall {
1517 IrInstruction base;
1518
1519 IrInstruction *fn;
1520 size_t arg_count;
1521 IrInstruction **args;
1522};
1523
1524struct IrInstructionBuiltinCall {
1525 IrInstruction base;
1526
1527 BuiltinFnId fn_id;
1528 size_t arg_count;
1529 IrInstruction **args;
1530};
1531
1532struct IrInstructionConst {
1533 IrInstruction base;
1534};
1535
1536struct IrInstructionReturn {
1537 IrInstruction base;
1538
1539 IrInstruction *value;
1540};
1541
13911542
1392#endif1543#endif
src/analyze.cpp+10-16
...@@ -11,6 +11,7 @@...@@ -11,6 +11,7 @@
11#include "error.hpp"11#include "error.hpp"
12#include "eval.hpp"12#include "eval.hpp"
13#include "ir.hpp"13#include "ir.hpp"
14#include "ir_print.hpp"
14#include "os.hpp"15#include "os.hpp"
15#include "parseh.hpp"16#include "parseh.hpp"
16#include "parser.hpp"17#include "parser.hpp"
...@@ -54,7 +55,7 @@ static void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry);...@@ -54,7 +55,7 @@ static void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry);
54static void resolve_use_decl(CodeGen *g, AstNode *node);55static void resolve_use_decl(CodeGen *g, AstNode *node);
55static void preview_use_decl(CodeGen *g, AstNode *node);56static void preview_use_decl(CodeGen *g, AstNode *node);
5657
57static AstNode *first_executing_node(AstNode *node) {58AstNode *first_executing_node(AstNode *node) {
58 switch (node->type) {59 switch (node->type) {
59 case NodeTypeFnCallExpr:60 case NodeTypeFnCallExpr:
60 return first_executing_node(node->data.fn_call_expr.fn_ref_expr);61 return first_executing_node(node->data.fn_call_expr.fn_ref_expr);
...@@ -2381,18 +2382,6 @@ static VariableTableEntry *find_variable(CodeGen *g, BlockContext *orig_context,...@@ -2381,18 +2382,6 @@ static VariableTableEntry *find_variable(CodeGen *g, BlockContext *orig_context,
2381 return nullptr;2382 return nullptr;
2382}2383}
23832384
2384static LabelTableEntry *find_label(CodeGen *g, BlockContext *orig_context, Buf *name) {
2385 BlockContext *context = orig_context;
2386 while (context && context->fn_entry) {
2387 auto entry = context->label_table.maybe_get(name);
2388 if (entry) {
2389 return entry->value;
2390 }
2391 context = context->parent;
2392 }
2393 return nullptr;
2394}
2395
2396static TypeEnumField *find_enum_type_field(TypeTableEntry *enum_type, Buf *name) {2385static TypeEnumField *find_enum_type_field(TypeTableEntry *enum_type, Buf *name) {
2397 for (uint32_t i = 0; i < enum_type->data.enumeration.src_field_count; i += 1) {2386 for (uint32_t i = 0; i < enum_type->data.enumeration.src_field_count; i += 1) {
2398 TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[i];2387 TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[i];
...@@ -7098,14 +7087,19 @@ static void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry) {...@@ -7098,14 +7087,19 @@ static void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry) {
7098 buf_sprintf("byvalue types not yet supported on extern function return values"));7087 buf_sprintf("byvalue types not yet supported on extern function return values"));
7099 }7088 }
71007089
7101 IrBasicBlock *entry_basic_block = ir_gen(g, node, expected_type);7090 IrInstruction *result = ir_gen_fn(g, fn_table_entry);
7102 if (!entry_basic_block) {7091 if (result == g->invalid_instruction) {
7103 fn_proto_node->data.fn_proto.skip = true;7092 fn_proto_node->data.fn_proto.skip = true;
7104 fn_table_entry->anal_state = FnAnalStateSkipped;7093 fn_table_entry->anal_state = FnAnalStateSkipped;
7105 return;7094 return;
7106 }7095 }
7107 TypeTableEntry *block_return_type = ir_analyze(g, node, entry_basic_block, expected_type);7096 if (g->verbose) {
7097 fprintf(stderr, "fn %s {\n", buf_ptr(&fn_table_entry->symbol_name));
7098 ir_print(stderr, &fn_table_entry->ir_executable, 4);
7099 fprintf(stderr, "}\n");
7100 }
71087101
7102 TypeTableEntry *block_return_type = ir_analyze(g, &fn_table_entry->ir_executable, expected_type);
7109 node->data.fn_def.implicit_return_type = block_return_type;7103 node->data.fn_def.implicit_return_type = block_return_type;
71107104
7111 fn_table_entry->anal_state = FnAnalStateComplete;7105 fn_table_entry->anal_state = FnAnalStateComplete;
src/analyze.hpp+2
...@@ -43,4 +43,6 @@ uint64_t get_memcpy_align(CodeGen *g, TypeTableEntry *type_entry);...@@ -43,4 +43,6 @@ uint64_t get_memcpy_align(CodeGen *g, TypeTableEntry *type_entry);
43ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package,43ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package,
44 Buf *abs_full_path, Buf *src_dirname, Buf *src_basename, Buf *source_code);44 Buf *abs_full_path, Buf *src_dirname, Buf *src_basename, Buf *source_code);
4545
46AstNode *first_executing_node(AstNode *node);
47
46#endif48#endif
src/codegen.cpp+59-13
...@@ -5,18 +5,18 @@...@@ -5,18 +5,18 @@
5 * See http://opensource.org/licenses/MIT5 * See http://opensource.org/licenses/MIT
6 */6 */
77
8#include "analyze.hpp"
9#include "ast_render.hpp"
8#include "codegen.hpp"10#include "codegen.hpp"
9#include "hash_map.hpp"
10#include "zig_llvm.hpp"
11#include "os.hpp"
12#include "config.h"11#include "config.h"
13#include "error.hpp"
14#include "analyze.hpp"
15#include "errmsg.hpp"12#include "errmsg.hpp"
13#include "error.hpp"
14#include "hash_map.hpp"
15#include "link.hpp"
16#include "os.hpp"
16#include "parseh.hpp"17#include "parseh.hpp"
17#include "ast_render.hpp"
18#include "target.hpp"18#include "target.hpp"
19#include "link.hpp"19#include "zig_llvm.hpp"
2020
21#include <stdio.h>21#include <stdio.h>
22#include <errno.h>22#include <errno.h>
...@@ -65,6 +65,8 @@ CodeGen *codegen_create(Buf *root_source_dir, const ZigTarget *target) {...@@ -65,6 +65,8 @@ CodeGen *codegen_create(Buf *root_source_dir, const ZigTarget *target) {
65 g->is_test_build = false;65 g->is_test_build = false;
66 g->want_h_file = true;66 g->want_h_file = true;
6767
68 g->invalid_instruction = allocate<IrInstruction>(1);
69
68 // the error.Ok value70 // the error.Ok value
69 g->error_decls.append(nullptr);71 g->error_decls.append(nullptr);
7072
...@@ -235,6 +237,7 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, AstNode *source_node, BinOpType b...@@ -235,6 +237,7 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, AstNode *source_node, BinOpType b
235static LLVMValueRef gen_unwrap_maybe(CodeGen *g, AstNode *node, LLVMValueRef maybe_struct_ref);237static LLVMValueRef gen_unwrap_maybe(CodeGen *g, AstNode *node, LLVMValueRef maybe_struct_ref);
236static LLVMValueRef gen_div(CodeGen *g, AstNode *source_node, LLVMValueRef val1, LLVMValueRef val2,238static LLVMValueRef gen_div(CodeGen *g, AstNode *source_node, LLVMValueRef val1, LLVMValueRef val2,
237 TypeTableEntry *type_entry, bool exact);239 TypeTableEntry *type_entry, bool exact);
240static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val);
238241
239static TypeTableEntry *get_type_for_type_node(AstNode *node) {242static TypeTableEntry *get_type_for_type_node(AstNode *node) {
240 Expr *expr = get_resolved_expr(node);243 Expr *expr = get_resolved_expr(node);
...@@ -249,6 +252,10 @@ static void set_debug_source_node(CodeGen *g, AstNode *node) {...@@ -249,6 +252,10 @@ static void set_debug_source_node(CodeGen *g, AstNode *node) {
249 ZigLLVMSetCurrentDebugLocation(g->builder, node->line + 1, node->column + 1, node->block_context->di_scope);252 ZigLLVMSetCurrentDebugLocation(g->builder, node->line + 1, node->column + 1, node->block_context->di_scope);
250}253}
251254
255static void ir_set_debug(CodeGen *g, IrInstruction *instruction) {
256 set_debug_source_node(g, instruction->source_node);
257}
258
252static void clear_debug_source_node(CodeGen *g) {259static void clear_debug_source_node(CodeGen *g) {
253 ZigLLVMClearCurrentDebugLocation(g->builder);260 ZigLLVMClearCurrentDebugLocation(g->builder);
254}261}
...@@ -2792,6 +2799,47 @@ static LLVMValueRef gen_if_var_expr(CodeGen *g, AstNode *node) {...@@ -2792,6 +2799,47 @@ static LLVMValueRef gen_if_var_expr(CodeGen *g, AstNode *node) {
2792 return nullptr;2799 return nullptr;
2793}2800}
27942801
2802static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrInstructionReturn *return_instruction) {
2803 ir_set_debug(g, &return_instruction->base);
2804 LLVMBuildRet(g->builder, return_instruction->value->llvm_value);
2805 return nullptr;
2806}
2807
2808static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, IrInstruction *instruction) {
2809 switch (instruction->id) {
2810 case IrInstructionIdInvalid:
2811 zig_unreachable();
2812 case IrInstructionIdConst:
2813 return gen_const_val(g, instruction->type_entry, &instruction->static_value);
2814 case IrInstructionIdReturn:
2815 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);
2816 case IrInstructionIdCondBr:
2817 case IrInstructionIdSwitchBr:
2818 case IrInstructionIdPhi:
2819 case IrInstructionIdBinOp:
2820 case IrInstructionIdLoadVar:
2821 case IrInstructionIdStoreVar:
2822 case IrInstructionIdCall:
2823 case IrInstructionIdBuiltinCall:
2824 zig_panic("TODO render more IR instructions to LLVM");
2825 }
2826 zig_unreachable();
2827}
2828
2829static void ir_render(CodeGen *g, FnTableEntry *fn_entry) {
2830 assert(fn_entry);
2831 IrExecutable *executable = &fn_entry->ir_executable;
2832 assert(executable->basic_block_count > 0);
2833 for (size_t i = 0; i < executable->basic_block_count; i += 1) {
2834 IrBasicBlock *current_block = executable->basic_block_list[i];
2835 for (IrInstruction *instruction = current_block->first; instruction != nullptr;
2836 instruction = instruction->next)
2837 {
2838 instruction->llvm_value = ir_render_instruction(g, executable, instruction);
2839 }
2840 }
2841}
2842
2795static LLVMValueRef gen_block(CodeGen *g, AstNode *block_node, TypeTableEntry *implicit_return_type) {2843static LLVMValueRef gen_block(CodeGen *g, AstNode *block_node, TypeTableEntry *implicit_return_type) {
2796 assert(block_node->type == NodeTypeBlock);2844 assert(block_node->type == NodeTypeBlock);
27972845
...@@ -3836,6 +3884,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE...@@ -3836,6 +3884,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE
3836 return LLVMConstStruct(fields, 2, false);3884 return LLVMConstStruct(fields, 2, false);
3837 }3885 }
3838 }3886 }
3887 case TypeTableEntryIdVoid:
3888 return nullptr;
3839 case TypeTableEntryIdInvalid:3889 case TypeTableEntryIdInvalid:
3840 case TypeTableEntryIdMetaType:3890 case TypeTableEntryIdMetaType:
3841 case TypeTableEntryIdUnreachable:3891 case TypeTableEntryIdUnreachable:
...@@ -3843,7 +3893,6 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE...@@ -3843,7 +3893,6 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE
3843 case TypeTableEntryIdNumLitInt:3893 case TypeTableEntryIdNumLitInt:
3844 case TypeTableEntryIdUndefLit:3894 case TypeTableEntryIdUndefLit:
3845 case TypeTableEntryIdNullLit:3895 case TypeTableEntryIdNullLit:
3846 case TypeTableEntryIdVoid:
3847 case TypeTableEntryIdNamespace:3896 case TypeTableEntryIdNamespace:
3848 case TypeTableEntryIdBlock:3897 case TypeTableEntryIdBlock:
3849 case TypeTableEntryIdGenericFn:3898 case TypeTableEntryIdGenericFn:
...@@ -4199,7 +4248,6 @@ static void do_code_gen(CodeGen *g) {...@@ -4199,7 +4248,6 @@ static void do_code_gen(CodeGen *g) {
4199 }4248 }
42004249
4201 ImportTableEntry *import = fn_table_entry->import_entry;4250 ImportTableEntry *import = fn_table_entry->import_entry;
4202 AstNode *fn_def_node = fn_table_entry->fn_def_node;
4203 LLVMValueRef fn = fn_table_entry->fn_value;4251 LLVMValueRef fn = fn_table_entry->fn_value;
4204 g->cur_fn = fn_table_entry;4252 g->cur_fn = fn_table_entry;
4205 if (handle_is_ptr(fn_table_entry->type_entry->data.fn.fn_type_id.return_type)) {4253 if (handle_is_ptr(fn_table_entry->type_entry->data.fn.fn_type_id.return_type)) {
...@@ -4307,9 +4355,7 @@ static void do_code_gen(CodeGen *g) {...@@ -4307,9 +4355,7 @@ static void do_code_gen(CodeGen *g) {
4307 gen_var_debug_decl(g, variable);4355 gen_var_debug_decl(g, variable);
4308 }4356 }
43094357
43104358 ir_render(g, fn_table_entry);
4311 TypeTableEntry *implicit_return_type = fn_def_node->data.fn_def.implicit_return_type;
4312 gen_block(g, fn_def_node->data.fn_def.body, implicit_return_type);
43134359
4314 }4360 }
4315 assert(!g->errors.length);4361 assert(!g->errors.length);
...@@ -4967,7 +5013,6 @@ static void init(CodeGen *g, Buf *source_path) {...@@ -4967,7 +5013,6 @@ static void init(CodeGen *g, Buf *source_path) {
49675013
4968 define_builtin_types(g);5014 define_builtin_types(g);
4969 define_builtin_fns(g);5015 define_builtin_fns(g);
4970
4971}5016}
49725017
4973void codegen_parseh(CodeGen *g, Buf *src_dirname, Buf *src_basename, Buf *source_code) {5018void codegen_parseh(CodeGen *g, Buf *src_dirname, Buf *src_basename, Buf *source_code) {
...@@ -5078,6 +5123,7 @@ void codegen_add_root_code(CodeGen *g, Buf *src_dir, Buf *src_basename, Buf *sou...@@ -5078,6 +5123,7 @@ void codegen_add_root_code(CodeGen *g, Buf *src_dir, Buf *src_basename, Buf *sou
5078 if (g->verbose) {5123 if (g->verbose) {
5079 fprintf(stderr, "\nCode Generation:\n");5124 fprintf(stderr, "\nCode Generation:\n");
5080 fprintf(stderr, "------------------\n");5125 fprintf(stderr, "------------------\n");
5126
5081 }5127 }
50825128
5083 do_code_gen(g);5129 do_code_gen(g);
src/ir.cpp+262-69
...@@ -1,44 +1,117 @@...@@ -1,44 +1,117 @@
1#include "analyze.hpp"1#include "analyze.hpp"
2#include "ir.hpp"2#include "ir.hpp"
33#include "error.hpp"
4static IrInstruction *ir_gen_node(IrGen *ir, AstNode *node, BlockContext *block_context);
5
6static const IrInstruction invalid_instruction_data;
7static const IrInstruction *invalid_instruction = &invalid_instruction_data;
8
9static const IrInstruction void_instruction_data;
10static const IrInstruction *void_instruction = &void_instruction_data;
114
12struct IrGen {5struct IrGen {
13 CodeGen *codegen;6 CodeGen *codegen;
14 AstNode *fn_def_node;7 AstNode *node;
15 IrBasicBlock *current_basic_block;8 IrBasicBlock *current_basic_block;
9 IrExecutable *exec;
16};10};
1711
18static IrInstruction *ir_build_return(Ir *ir, AstNode *source_node, IrInstruction *return_value) {12static IrInstruction *ir_gen_node(IrGen *ir, AstNode *node, BlockContext *block_context);
19 IrInstruction *instructon = allocate<IrInstructionReturn>(1);
20 instruction->base.id = IrInstructionIdReturn;
21 instruction->base.source_node = source_node;
22 instruction->base.type_entry = ir->codegen->builtin_types.entry_unreachable;
23 ir->current_basic_block->instructions->append(instruction);
24 return instructon;
25}
2613
27static size_t get_conditional_defer_count(BlockContext *inner_block, BlockContext *outer_block) {14static void ir_instruction_append(IrBasicBlock *basic_block, IrInstruction *instruction) {
28 size_t result = 0;15 if (!basic_block->last) {
29 while (inner_block != outer_block) {16 basic_block->first = instruction;
30 if (inner_block->node->type == NodeTypeDefer &&17 basic_block->last = instruction;
31 (inner_block->node->data.defer.kind == ReturnKindError ||18 instruction->prev = nullptr;
32 inner_block->node->data.defer.kind == ReturnKindMaybe))19 instruction->next = nullptr;
33 {20 } else {
34 result += 1;21 basic_block->last->next = instruction;
35 }22 instruction->prev = basic_block->last;
36 inner_block = inner_block->parent;23 instruction->next = nullptr;
24 basic_block->last = instruction;
37 }25 }
26}
27
28static size_t exec_next_debug_id(IrGen *ir) {
29 size_t result = ir->exec->next_debug_id;
30 ir->exec->next_debug_id += 1;
38 return result;31 return result;
39}32}
4033
41static void ir_gen_defers_for_block(Ir *ir, BlockContext *inner_block, BlockContext *outer_block,34static constexpr IrInstructionId ir_instruction_id(IrInstructionCondBr *) {
35 return IrInstructionIdCondBr;
36}
37
38static constexpr IrInstructionId ir_instruction_id(IrInstructionSwitchBr *) {
39 return IrInstructionIdSwitchBr;
40}
41
42static constexpr IrInstructionId ir_instruction_id(IrInstructionPhi *) {
43 return IrInstructionIdPhi;
44}
45
46static constexpr IrInstructionId ir_instruction_id(IrInstructionBinOp *) {
47 return IrInstructionIdBinOp;
48}
49
50static constexpr IrInstructionId ir_instruction_id(IrInstructionLoadVar *) {
51 return IrInstructionIdLoadVar;
52}
53
54static constexpr IrInstructionId ir_instruction_id(IrInstructionStoreVar *) {
55 return IrInstructionIdStoreVar;
56}
57
58static constexpr IrInstructionId ir_instruction_id(IrInstructionCall *) {
59 return IrInstructionIdCall;
60}
61
62static constexpr IrInstructionId ir_instruction_id(IrInstructionBuiltinCall *) {
63 return IrInstructionIdBuiltinCall;
64}
65
66static constexpr IrInstructionId ir_instruction_id(IrInstructionConst *) {
67 return IrInstructionIdConst;
68}
69
70static constexpr IrInstructionId ir_instruction_id(IrInstructionReturn *) {
71 return IrInstructionIdReturn;
72}
73
74template<typename T>
75static T *ir_build_instruction(IrGen *ir, AstNode *source_node) {
76 T *special_instruction = allocate<T>(1);
77 special_instruction->base.id = ir_instruction_id(special_instruction);
78 special_instruction->base.source_node = source_node;
79 special_instruction->base.type_entry = ir->codegen->builtin_types.entry_unreachable;
80 special_instruction->base.debug_id = exec_next_debug_id(ir);
81 ir_instruction_append(ir->current_basic_block, &special_instruction->base);
82 return special_instruction;
83}
84
85static IrInstruction *ir_build_return(IrGen *ir, AstNode *source_node, IrInstruction *return_value) {
86 IrInstructionReturn *return_instruction = ir_build_instruction<IrInstructionReturn>(ir, source_node);
87 return_instruction->base.type_entry = ir->codegen->builtin_types.entry_unreachable;
88 return_instruction->base.static_value.ok = true;
89 return_instruction->value = return_value;
90 return &return_instruction->base;
91}
92
93static IrInstruction *ir_build_void(IrGen *ir, AstNode *source_node) {
94 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(ir, source_node);
95 const_instruction->base.type_entry = ir->codegen->builtin_types.entry_void;
96 const_instruction->base.static_value.ok = true;
97 return &const_instruction->base;
98}
99
100//static size_t get_conditional_defer_count(BlockContext *inner_block, BlockContext *outer_block) {
101// size_t result = 0;
102// while (inner_block != outer_block) {
103// if (inner_block->node->type == NodeTypeDefer &&
104// (inner_block->node->data.defer.kind == ReturnKindError ||
105// inner_block->node->data.defer.kind == ReturnKindMaybe))
106// {
107// result += 1;
108// }
109// inner_block = inner_block->parent;
110// }
111// return result;
112//}
113
114static void ir_gen_defers_for_block(IrGen *ir, BlockContext *inner_block, BlockContext *outer_block,
42 bool gen_error_defers, bool gen_maybe_defers)115 bool gen_error_defers, bool gen_maybe_defers)
43{116{
44 while (inner_block != outer_block) {117 while (inner_block != outer_block) {
...@@ -54,42 +127,44 @@ static void ir_gen_defers_for_block(Ir *ir, BlockContext *inner_block, BlockCont...@@ -54,42 +127,44 @@ static void ir_gen_defers_for_block(Ir *ir, BlockContext *inner_block, BlockCont
54 }127 }
55}128}
56129
57static IrInstruction *ir_gen_return(Ir *ir, AstNode *source_node, IrInstruction *value, ReturnKnowledge rk) {130//static IrInstruction *ir_gen_return(IrGen *ir, AstNode *source_node, IrInstruction *value, ReturnKnowledge rk) {
58 BlockContext *defer_inner_block = source_node->block_context;131// BlockContext *defer_inner_block = source_node->block_context;
59 BlockContext *defer_outer_block = ir->fn_def_node->block_context;132// BlockContext *defer_outer_block = ir->node->block_context;
60 if (rk == ReturnKnowledgeUnknown) {133// if (rk == ReturnKnowledgeUnknown) {
61 if (get_conditional_defer_count(defer_inner_block, defer_outer_block) > 0) {134// if (get_conditional_defer_count(defer_inner_block, defer_outer_block) > 0) {
62 // generate branching code that checks the return value and generates defers135// // generate branching code that checks the return value and generates defers
63 // if the return value is error136// // if the return value is error
64 zig_panic("TODO");137// zig_panic("TODO");
65 }138// }
66 } else if (rk != ReturnKnowledgeSkipDefers) {139// } else if (rk != ReturnKnowledgeSkipDefers) {
67 ir_gen_defers_for_block(g, defer_inner_block, defer_outer_block,140// ir_gen_defers_for_block(ir, defer_inner_block, defer_outer_block,
68 rk == ReturnKnowledgeKnownError, rk == ReturnKnowledgeKnownNull);141// rk == ReturnKnowledgeKnownError, rk == ReturnKnowledgeKnownNull);
69 }142// }
70143//
71 ir_build_return(ir, source_node, value);144// return ir_build_return(ir, source_node, value);
72 return void_instruction;145//}
73}
74146
75static IrInstruction *ir_gen_block(IrGen *ir, AstNode *block_node, TypeTableEntry *implicit_return_type) {147static IrInstruction *ir_gen_block(IrGen *ir, AstNode *block_node) {
76 assert(block_node->type == NodeTypeBlock);148 assert(block_node->type == NodeTypeBlock);
77149
78 BlockContext *parent_context = block_node->context;150 BlockContext *parent_context = block_node->block_context;
79 BlockContext *outer_block_context = new_block_context(block_node, parent_context);151 BlockContext *outer_block_context = new_block_context(block_node, parent_context);
80 BlockContext *child_context = outer_block_context;152 BlockContext *child_context = outer_block_context;
81153
82 IrInstruction *return_value = nullptr;154 IrInstruction *return_value = nullptr;
83 for (size_t i = 0; i < block_node->data.block.statements.length; i += 1) {155 for (size_t i = 0; i < block_node->data.block.statements.length; i += 1) {
84 AstNode *statement_node = block_node->data.block.statements.at(i);156 AstNode *statement_node = block_node->data.block.statements.at(i);
85 return_value = ir_gen_node(g, statement_node, child_context);157 return_value = ir_gen_node(ir, statement_node, child_context);
86 if (statement_node->type == NodeTypeDefer && return_value != invalid_instruction) {158 if (statement_node->type == NodeTypeDefer && return_value != ir->codegen->invalid_instruction) {
87 // defer starts a new block context159 // defer starts a new block context
88 child_context = statement_node->data.defer.child_block;160 child_context = statement_node->data.defer.child_block;
89 assert(child_context);161 assert(child_context);
90 }162 }
91 }163 }
92164
165 if (!return_value)
166 return_value = ir_build_void(ir, block_node);
167
93 ir_gen_defers_for_block(ir, child_context, outer_block_context, false, false);168 ir_gen_defers_for_block(ir, child_context, outer_block_context, false, false);
94169
95 return return_value;170 return return_value;
...@@ -100,7 +175,7 @@ static IrInstruction *ir_gen_node(IrGen *ir, AstNode *node, BlockContext *block_...@@ -100,7 +175,7 @@ static IrInstruction *ir_gen_node(IrGen *ir, AstNode *node, BlockContext *block_
100175
101 switch (node->type) {176 switch (node->type) {
102 case NodeTypeBlock:177 case NodeTypeBlock:
103 return ir_gen_block(ir, node, nullptr);178 return ir_gen_block(ir, node);
104 case NodeTypeBinOpExpr:179 case NodeTypeBinOpExpr:
105 case NodeTypeUnwrapErrorExpr:180 case NodeTypeUnwrapErrorExpr:
106 case NodeTypeReturnExpr:181 case NodeTypeReturnExpr:
...@@ -153,23 +228,53 @@ static IrInstruction *ir_gen_node(IrGen *ir, AstNode *node, BlockContext *block_...@@ -153,23 +228,53 @@ static IrInstruction *ir_gen_node(IrGen *ir, AstNode *node, BlockContext *block_
153 zig_unreachable();228 zig_unreachable();
154}229}
155230
156IrBasicBlock *ir_gen(CodeGen *g, AstNode *fn_def_node, TypeTableEntry *return_type) {231static IrInstruction *ir_gen_add_return(CodeGen *g, AstNode *node, BlockContext *scope,
157 assert(fn_def_node->type == NodeTypeFnDef);232 IrExecutable *ir_executable, bool add_return)
158 assert(fn_def_node->data.fn_def.block_context);233{
159 assert(fn_def_node->owner);234 assert(node->owner);
160 assert(return_type);
161 assert(return_type->id != TypeTableEntryIdInvalid);
162235
163 IrGen ir_gen = {0};236 IrGen ir_gen = {0};
164 IrGen *ir = &ir_gen;237 IrGen *ir = &ir_gen;
165238
239 ir->codegen = g;
240 ir->node = node;
241 ir->exec = ir_executable;
242
243 ir->exec->basic_block_list = allocate<IrBasicBlock*>(1);
244 ir->exec->basic_block_count = 1;
245
166 IrBasicBlock *entry_basic_block = allocate<IrBasicBlock>(1);246 IrBasicBlock *entry_basic_block = allocate<IrBasicBlock>(1);
167 ir->current_basic_block = entry_basic_block;247 ir->current_basic_block = entry_basic_block;
248 ir->exec->basic_block_list[0] = entry_basic_block;
249
250 IrInstruction *result = ir_gen_node(ir, node, scope);
251 assert(result);
252
253 if (result == g->invalid_instruction)
254 return result;
255
256 if (add_return)
257 return ir_build_return(ir, result->source_node, result);
258
259 return result;
260}
261
262IrInstruction *ir_gen(CodeGen *g, AstNode *node, BlockContext *scope, IrExecutable *ir_executable) {
263 return ir_gen_add_return(g, node, scope, ir_executable, false);
264}
265
266IrInstruction *ir_gen_fn(CodeGen *g, FnTableEntry *fn_entry) {
267 assert(fn_entry);
268
269 IrExecutable *ir_executable = &fn_entry->ir_executable;
270 AstNode *fn_def_node = fn_entry->fn_def_node;
271 assert(fn_def_node->type == NodeTypeFnDef);
168272
169 AstNode *body_node = fn_def_node->data.fn_def.body;273 AstNode *body_node = fn_def_node->data.fn_def.body;
170 body_node->block_context = fn_def_node->data.fn_def.block_context;274 BlockContext *scope = fn_def_node->data.fn_def.block_context;
171 IrInstruction *instruction = ir_gen_block(ir, body_node, return_type);275
172 return (instructon == invalid_instruction) ? nullptr : entry_basic_block;276 bool add_return_yes = true;
277 return ir_gen_add_return(g, body_node, scope, ir_executable, add_return_yes);
173}278}
174279
175/*280/*
...@@ -205,22 +310,110 @@ static void analyze_goto_pass2(CodeGen *g, ImportTableEntry *import, AstNode *no...@@ -205,22 +310,110 @@ static void analyze_goto_pass2(CodeGen *g, ImportTableEntry *import, AstNode *no
205 }310 }
206*/311*/
207312
313//static LabelTableEntry *find_label(CodeGen *g, BlockContext *orig_context, Buf *name) {
314// BlockContext *context = orig_context;
315// while (context && context->fn_entry) {
316// auto entry = context->label_table.maybe_get(name);
317// if (entry) {
318// return entry->value;
319// }
320// context = context->parent;
321// }
322// return nullptr;
323//}
324
325static IrInstruction *ir_get_casted_instruction(CodeGen *g, IrInstruction *instruction,
326 TypeTableEntry *expected_type)
327{
328 assert(instruction);
329 assert(instruction != g->invalid_instruction);
330 assert(!expected_type || expected_type->id != TypeTableEntryIdInvalid);
331 assert(instruction->type_entry);
332 assert(instruction->type_entry->id != TypeTableEntryIdInvalid);
333 if (expected_type == nullptr)
334 return instruction; // anything will do
335 if (expected_type == instruction->type_entry)
336 return instruction; // match
337 if (instruction->type_entry->id == TypeTableEntryIdUnreachable)
338 return instruction;
339
340 zig_panic("TODO implicit cast instruction");
341}
342
343static TypeTableEntry *ir_analyze_instruction_return(CodeGen *g, IrInstructionReturn *return_instruction) {
344 AstNode *source_node = return_instruction->base.source_node;
345 BlockContext *scope = source_node->block_context;
346 if (!scope->fn_entry) {
347 add_node_error(g, source_node, buf_sprintf("return expression outside function definition"));
348 return g->builtin_types.entry_invalid;
349 }
208350
209TypeTableEntry *ir_analyze(CodeGen *g, AstNode *fn_def_node, IrBasicBlock *entry_basic_block,351 TypeTableEntry *expected_return_type = scope->fn_entry->type_entry->data.fn.fn_type_id.return_type;
352 if (expected_return_type->id == TypeTableEntryIdVoid && !return_instruction->value) {
353 return g->builtin_types.entry_unreachable;
354 }
355
356 return_instruction->value = ir_get_casted_instruction(g, return_instruction->value, expected_return_type);
357 if (return_instruction->value == g->invalid_instruction) {
358 return g->builtin_types.entry_invalid;
359 }
360 return g->builtin_types.entry_unreachable;
361}
362
363static TypeTableEntry *ir_analyze_instruction_const(CodeGen *g, IrInstructionConst *const_instruction) {
364 return const_instruction->base.type_entry;
365}
366
367static TypeTableEntry *ir_analyze_instruction_nocast(CodeGen *g, IrInstruction *instruction) {
368 switch (instruction->id) {
369 case IrInstructionIdInvalid:
370 zig_unreachable();
371 case IrInstructionIdReturn:
372 return ir_analyze_instruction_return(g, (IrInstructionReturn *)instruction);
373 case IrInstructionIdConst:
374 return ir_analyze_instruction_const(g, (IrInstructionConst *)instruction);
375 case IrInstructionIdCondBr:
376 case IrInstructionIdSwitchBr:
377 case IrInstructionIdPhi:
378 case IrInstructionIdBinOp:
379 case IrInstructionIdLoadVar:
380 case IrInstructionIdStoreVar:
381 case IrInstructionIdCall:
382 case IrInstructionIdBuiltinCall:
383 zig_panic("TODO analyze more instructions");
384 }
385 zig_unreachable();
386}
387
388static TypeTableEntry *ir_analyze_instruction(CodeGen *g, IrInstruction *instruction,
210 TypeTableEntry *expected_type)389 TypeTableEntry *expected_type)
211{390{
391 TypeTableEntry *instruction_type = ir_analyze_instruction_nocast(g, instruction);
392 instruction->type_entry = instruction_type;
393
394 IrInstruction *casted_instruction = ir_get_casted_instruction(g, instruction, expected_type);
395 return casted_instruction->type_entry;
396}
397
398TypeTableEntry *ir_analyze(CodeGen *g, IrExecutable *executable, TypeTableEntry *expected_type) {
212 TypeTableEntry *return_type = g->builtin_types.entry_void;399 TypeTableEntry *return_type = g->builtin_types.entry_void;
213400
214 for (size_t i = 0; i < entry_basic_block->instructions.length; i += 1) {401 for (size_t i = 0; i < executable->basic_block_count; i += 1) {
215 IrInstruction *instruction = entry_basic_block->instructions.at(i);402 IrBasicBlock *current_block = executable->basic_block_list[i];
216403
217 if (return_type->id == TypeTableEntryIdUnreachable) {404 for (IrInstruction *instruction = current_block->first; instruction != nullptr;
218 add_node_error(g, first_executing_node(instruction->source_node),405 instruction = instruction->next)
219 buf_sprintf("unreachable code"));406 {
220 break;407 if (return_type->id == TypeTableEntryIdUnreachable) {
408 add_node_error(g, first_executing_node(instruction->source_node),
409 buf_sprintf("unreachable code"));
410 break;
411 }
412 bool is_last = (instruction == current_block->last);
413 TypeTableEntry *passed_expected_type = is_last ? expected_type : nullptr;
414 return_type = ir_analyze_instruction(g, instruction, passed_expected_type);
221 }415 }
222 bool is_last = (i == entry_basic_block->instructions.length - 1);
223 TypeTableEntry *passed_expected_type = is_last ? expected_type : nullptr;
224 return_type = ir_analyze_instruction(g, instruction, passed_expected_type, child);
225 }416 }
417
418 return return_type;
226}419}
src/ir.hpp+3-138
...@@ -10,144 +10,9 @@...@@ -10,144 +10,9 @@
1010
11#include "all_types.hpp"11#include "all_types.hpp"
1212
13struct IrInstruction;13IrInstruction *ir_gen(CodeGen *g, AstNode *node, BlockContext *scope, IrExecutable *ir_executable);
14IrInstruction *ir_gen_fn(CodeGen *g, FnTableEntry *fn_entry);
1415
15// A basic block contains no branching. Branches send control flow16TypeTableEntry *ir_analyze(CodeGen *g, IrExecutable *executable, TypeTableEntry *expected_type);
16// to another basic block.
17// Phi instructions must be first in a basic block.
18// The last instruction in a basic block must be an expression of type unreachable.
19struct IrBasicBlock {
20 ZigList<IrInstruction *> instructions;
21};
22
23enum IrInstructionId {
24 IrInstructionIdCondBr,
25 IrInstructionIdSwitchBr,
26 IrInstructionIdPhi,
27 IrInstructionIdAdd,
28 IrInstructionIdBinOp,
29 IrInstructionIdLoadVar,
30 IrInstructionIdStoreVar,
31 IrInstructionIdCall,
32 IrInstructionIdBuiltinCall,
33 IrInstructionIdConst,
34 IrInstructionIdReturn,
35};
36
37struct IrInstruction {
38 IrInstructionId id;
39 AstNode *source_node;
40 ConstExprValue static_value;
41 TypeTableEntry *type_entry;
42};
43
44struct IrInstructionCondBr {
45 IrInstruction base;
46
47 // If the condition is null, then this is an unconditional branch.
48 IrInstruction *cond;
49 IrBasicBlock *dest;
50};
51
52struct IrInstructionSwitchBrCase {
53 IrInstruction *value;
54 IrBasicBlock *block;
55};
56
57struct IrInstructionSwitchBr {
58 IrInstruction base;
59
60 IrInstruction *target_value;
61 IrBasicBlock *else_block;
62 size_t case_count;
63 IrInstructionSwitchBrCase *cases;
64};
65
66struct IrInstructionPhi {
67 IrInstruction base;
68
69 size_t incoming_block_count;
70 IrBasicBlock **incoming_blocks;
71 IrInstruction **incoming_values;
72};
73
74enum IrBinOp {
75 IrBinOpInvalid,
76 IrBinOpBoolOr,
77 IrBinOpBoolAnd,
78 IrBinOpCmpEq,
79 IrBinOpCmpNotEq,
80 IrBinOpCmpLessThan,
81 IrBinOpCmpGreaterThan,
82 IrBinOpCmpLessOrEq,
83 IrBinOpCmpGreaterOrEq,
84 IrBinOpBinOr,
85 IrBinOpBinXor,
86 IrBinOpBinAnd,
87 IrBinOpBitShiftLeft,
88 IrBinOpBitShiftLeftWrap,
89 IrBinOpBitShiftRight,
90 IrBinOpAdd,
91 IrBinOpAddWrap,
92 IrBinOpSub,
93 IrBinOpSubWrap,
94 IrBinOpMult,
95 IrBinOpMultWrap,
96 IrBinOpDiv,
97 IrBinOpMod,
98 IrBinOpArrayCat,
99 IrBinOpArrayMult,
100};
101
102struct IrInstructionBinOp {
103 IrInstruction base;
104
105 IrInstruction *op1;
106 IrBinOp op_id;
107 IrInstruction *op2;
108};
109
110struct IrInstructionLoadVar {
111 IrInstruction base;
112
113 VariableTableEntry *var;
114};
115
116struct IrInstructionStoreVar {
117 IrInstruction base;
118
119 IrInstruction *value;
120 VariableTableEntry *var;
121};
122
123struct IrInstructionCall {
124 IrInstruction base;
125
126 IrInstruction *fn;
127 size_t arg_count;
128 IrInstruction **args;
129};
130
131struct IrInstructionBuiltinCall {
132 IrInstruction base;
133
134 BuiltinFnId fn_id;
135 size_t arg_count;
136 IrInstruction **args;
137};
138
139struct IrInstructionConst {
140 IrInstruction base;
141};
142
143struct IrInstructionReturn {
144 IrInstruction base;
145
146 IrInstruction *value;
147};
148
149IrBasicBlock *ir_gen(CodeGen *g, AstNode *fn_def_node, TypeTableEntry *return_type);
150TypeTableEntry *ir_analyze(CodeGen *g, AstNode *fn_def_node, IrBasicBlock *entry_basic_block,
151 TypeTableEntry *expected_type);
15217
153#endif18#endif
src/ir_print.cpp created+94
...@@ -0,0 +1,94 @@
1#include "ir_print.hpp"
2
3struct IrPrint {
4 FILE *f;
5 int indent;
6 int indent_size;
7};
8
9static void ir_print_indent(IrPrint *irp) {
10 for (int i = 0; i < irp->indent; i += 1) {
11 fprintf(irp->f, " ");
12 }
13}
14
15static void ir_print_prefix(IrPrint *irp, IrInstruction *instruction) {
16 ir_print_indent(irp);
17 fprintf(irp->f, "#%-3zu| ", instruction->debug_id);
18}
19
20static void ir_print_return(IrPrint *irp, IrInstructionReturn *return_instruction) {
21 ir_print_prefix(irp, &return_instruction->base);
22 assert(return_instruction->value);
23 fprintf(irp->f, "return #%zu;\n", return_instruction->value->debug_id);
24}
25
26static void ir_print_const(IrPrint *irp, IrInstructionConst *const_instruction) {
27 ir_print_prefix(irp, &const_instruction->base);
28 switch (const_instruction->base.type_entry->id) {
29 case TypeTableEntryIdInvalid:
30 zig_unreachable();
31 case TypeTableEntryIdVoid:
32 fprintf(irp->f, "void\n");
33 break;
34 case TypeTableEntryIdVar:
35 case TypeTableEntryIdMetaType:
36 case TypeTableEntryIdBool:
37 case TypeTableEntryIdUnreachable:
38 case TypeTableEntryIdInt:
39 case TypeTableEntryIdFloat:
40 case TypeTableEntryIdPointer:
41 case TypeTableEntryIdArray:
42 case TypeTableEntryIdStruct:
43 case TypeTableEntryIdNumLitFloat:
44 case TypeTableEntryIdNumLitInt:
45 case TypeTableEntryIdUndefLit:
46 case TypeTableEntryIdNullLit:
47 case TypeTableEntryIdMaybe:
48 case TypeTableEntryIdErrorUnion:
49 case TypeTableEntryIdPureError:
50 case TypeTableEntryIdEnum:
51 case TypeTableEntryIdUnion:
52 case TypeTableEntryIdFn:
53 case TypeTableEntryIdTypeDecl:
54 case TypeTableEntryIdNamespace:
55 case TypeTableEntryIdBlock:
56 case TypeTableEntryIdGenericFn:
57 zig_panic("TODO render more constant types in IR printer");
58 }
59}
60
61void ir_print(FILE *f, IrExecutable *executable, int indent_size) {
62 IrPrint ir_print = {};
63 IrPrint *irp = &ir_print;
64 irp->f = f;
65 irp->indent = indent_size;
66 irp->indent_size = indent_size;
67
68 for (size_t i = 0; i < executable->basic_block_count; i += 1) {
69 IrBasicBlock *current_block = executable->basic_block_list[i];
70 for (IrInstruction *instruction = current_block->first; instruction != nullptr;
71 instruction = instruction->next)
72 {
73 switch (instruction->id) {
74 case IrInstructionIdInvalid:
75 zig_unreachable();
76 case IrInstructionIdReturn:
77 ir_print_return(irp, (IrInstructionReturn *)instruction);
78 break;
79 case IrInstructionIdConst:
80 ir_print_const(irp, (IrInstructionConst *)instruction);
81 break;
82 case IrInstructionIdCondBr:
83 case IrInstructionIdSwitchBr:
84 case IrInstructionIdPhi:
85 case IrInstructionIdBinOp:
86 case IrInstructionIdLoadVar:
87 case IrInstructionIdStoreVar:
88 case IrInstructionIdCall:
89 case IrInstructionIdBuiltinCall:
90 zig_panic("TODO print more IR instructions");
91 }
92 }
93 }
94}
src/ir_print.hpp created+17
...@@ -0,0 +1,17 @@
1/*
2 * Copyright (c) 2016 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#ifndef ZIG_IR_PRINT_HPP
9#define ZIG_IR_PRINT_HPP
10
11#include "all_types.hpp"
12
13#include <stdio.h>
14
15void ir_print(FILE *f, IrExecutable *executable, int indent_size);
16
17#endif
src/parser.cpp+11-12
...@@ -1912,14 +1912,14 @@ static AstNode *ast_parse_label(ParseContext *pc, size_t *token_index, bool mand...@@ -1912,14 +1912,14 @@ static AstNode *ast_parse_label(ParseContext *pc, size_t *token_index, bool mand
1912 return node;1912 return node;
1913}1913}
19141914
1915static AstNode *ast_create_void_expr(ParseContext *pc, Token *token) {1915//static AstNode *ast_create_void_expr(ParseContext *pc, Token *token) {
1916 AstNode *node = ast_create_node(pc, NodeTypeContainerInitExpr, token);1916// AstNode *node = ast_create_node(pc, NodeTypeContainerInitExpr, token);
1917 node->data.container_init_expr.type = ast_create_node(pc, NodeTypeSymbol, token);1917// node->data.container_init_expr.type = ast_create_node(pc, NodeTypeSymbol, token);
1918 node->data.container_init_expr.kind = ContainerInitKindArray;1918// node->data.container_init_expr.kind = ContainerInitKindArray;
1919 node->data.container_init_expr.type->data.symbol_expr.symbol = pc->void_buf;1919// node->data.container_init_expr.type->data.symbol_expr.symbol = pc->void_buf;
1920 normalize_parent_ptrs(node);1920// normalize_parent_ptrs(node);
1921 return node;1921// return node;
1922}1922//}
19231923
1924/*1924/*
1925Block : token(LBrace) list(option(Statement), token(Semicolon)) token(RBrace)1925Block : token(LBrace) list(option(Statement), token(Semicolon)) token(RBrace)
...@@ -1961,13 +1961,12 @@ static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mand...@@ -1961,13 +1961,12 @@ static AstNode *ast_parse_block(ParseContext *pc, size_t *token_index, bool mand
1961 semicolon_expected = !statement_node;1961 semicolon_expected = !statement_node;
1962 if (!statement_node) {1962 if (!statement_node) {
1963 statement_node = ast_parse_non_block_expr(pc, token_index, false);1963 statement_node = ast_parse_non_block_expr(pc, token_index, false);
1964 if (!statement_node) {
1965 statement_node = ast_create_void_expr(pc, last_token);
1966 }
1967 }1964 }
1968 }1965 }
1969 }1966 }
1970 node->data.block.statements.append(statement_node);1967 if (statement_node) {
1968 node->data.block.statements.append(statement_node);
1969 }
19711970
1972 last_token = &pc->tokens->at(*token_index);1971 last_token = &pc->tokens->at(*token_index);
1973 if (last_token->id == TokenIdRBrace) {1972 if (last_token->id == TokenIdRBrace) {