| ... | @@ -2,57 +2,35 @@ | ... | @@ -2,57 +2,35 @@ |
| 2 | #include "ir.hpp" | 2 | #include "ir.hpp" |
| 3 | #include "error.hpp" | 3 | #include "error.hpp" |
| 4 | | 4 | |
| 5 | struct IrGen { | 5 | struct IrVarSlot { |
| | 6 | ConstExprValue value; |
| | 7 | bool runtime; |
| | 8 | }; |
| | 9 | |
| | 10 | struct IrExecContext { |
| | 11 | IrVarSlot *var_slot_list; |
| | 12 | size_t var_slot_count; |
| | 13 | }; |
| | 14 | |
| | 15 | struct IrBuilder { |
| 6 | CodeGen *codegen; | 16 | CodeGen *codegen; |
| 7 | AstNode *node; | | |
| 8 | IrBasicBlock *current_basic_block; | | |
| 9 | IrExecutable *exec; | 17 | IrExecutable *exec; |
| | 18 | IrBasicBlock *current_basic_block; |
| 10 | }; | 19 | }; |
| 11 | | 20 | |
| 12 | struct IrAnalyze { | 21 | struct IrAnalyze { |
| 13 | CodeGen *codegen; | 22 | CodeGen *codegen; |
| 14 | IrExecutable *exec; | 23 | IrBuilder old_irb; |
| 15 | IrBasicBlock *current_basic_block; | 24 | IrBuilder new_irb; |
| | 25 | IrExecContext exec_context; |
| 16 | }; | 26 | }; |
| 17 | | 27 | |
| 18 | static IrInstruction *ir_gen_node(IrGen *irg, AstNode *node, BlockContext *scope); | 28 | static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, BlockContext *scope); |
| 19 | | 29 | |
| 20 | static void ir_instruction_append(IrBasicBlock *basic_block, IrInstruction *instruction) { | 30 | static void ir_instruction_append(IrBasicBlock *basic_block, IrInstruction *instruction) { |
| 21 | if (!basic_block->last) { | 31 | assert(basic_block); |
| 22 | basic_block->first = instruction; | 32 | assert(instruction); |
| 23 | basic_block->last = instruction; | 33 | basic_block->instruction_list.append(instruction); |
| 24 | instruction->prev = nullptr; | | |
| 25 | instruction->next = nullptr; | | |
| 26 | } else { | | |
| 27 | basic_block->last->next = instruction; | | |
| 28 | instruction->prev = basic_block->last; | | |
| 29 | instruction->next = nullptr; | | |
| 30 | basic_block->last = instruction; | | |
| 31 | } | | |
| 32 | } | | |
| 33 | | | |
| 34 | static void ir_instruction_insert(IrBasicBlock *basic_block, | | |
| 35 | IrInstruction *before_instruction, IrInstruction *after_instruction, | | |
| 36 | IrInstruction *new_instruction) | | |
| 37 | { | | |
| 38 | assert(before_instruction || after_instruction); | | |
| 39 | assert(!before_instruction || !after_instruction); | | |
| 40 | | | |
| 41 | if (before_instruction) { | | |
| 42 | IrInstruction *displaced_instruction = before_instruction->prev; | | |
| 43 | before_instruction->prev = new_instruction; | | |
| 44 | new_instruction->prev = displaced_instruction; | | |
| 45 | new_instruction->next = before_instruction; | | |
| 46 | if (basic_block->first == before_instruction) | | |
| 47 | basic_block->first = new_instruction; | | |
| 48 | } else { | | |
| 49 | IrInstruction *displaced_instruction = after_instruction->next; | | |
| 50 | after_instruction->next = new_instruction; | | |
| 51 | new_instruction->prev = after_instruction; | | |
| 52 | new_instruction->next = displaced_instruction; | | |
| 53 | if (basic_block->last == after_instruction) | | |
| 54 | basic_block->last = new_instruction; | | |
| 55 | } | | |
| 56 | } | 34 | } |
| 57 | | 35 | |
| 58 | static size_t exec_next_debug_id(IrExecutable *exec) { | 36 | static size_t exec_next_debug_id(IrExecutable *exec) { |
| ... | @@ -115,97 +93,82 @@ static T *ir_create_instruction(IrExecutable *exec, AstNode *source_node) { | ... | @@ -115,97 +93,82 @@ static T *ir_create_instruction(IrExecutable *exec, AstNode *source_node) { |
| 115 | } | 93 | } |
| 116 | | 94 | |
| 117 | template<typename T> | 95 | template<typename T> |
| 118 | static T *ir_build_instruction(IrGen *irg, AstNode *source_node) { | 96 | static T *ir_build_instruction(IrBuilder *irb, AstNode *source_node) { |
| 119 | T *special_instruction = ir_create_instruction<T>(irg->exec, source_node); | 97 | T *special_instruction = ir_create_instruction<T>(irb->exec, source_node); |
| 120 | ir_instruction_append(irg->current_basic_block, &special_instruction->base); | 98 | ir_instruction_append(irb->current_basic_block, &special_instruction->base); |
| 121 | return special_instruction; | 99 | return special_instruction; |
| 122 | } | 100 | } |
| 123 | | 101 | |
| 124 | static IrInstruction *ir_insert_const_type(IrAnalyze *ira, IrInstruction *before_instruction, | 102 | static IrInstruction *ir_build_cast(IrBuilder *irb, AstNode *source_node, IrInstruction *dest_type, |
| 125 | IrInstruction *after_instruction, TypeTableEntry *type_entry) | 103 | IrInstruction *value, bool is_implicit) |
| 126 | { | 104 | { |
| 127 | IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(ira->exec, | 105 | IrInstructionCast *cast_instruction = ir_build_instruction<IrInstructionCast>(irb, source_node); |
| 128 | before_instruction->source_node); | | |
| 129 | const_instruction->base.type_entry = ira->codegen->builtin_types.entry_type; | | |
| 130 | const_instruction->base.static_value.ok = true; | | |
| 131 | const_instruction->base.static_value.data.x_type = type_entry; | | |
| 132 | ir_instruction_insert(ira->current_basic_block, before_instruction, after_instruction, &const_instruction->base); | | |
| 133 | return &const_instruction->base; | | |
| 134 | } | | |
| 135 | | | |
| 136 | static IrInstruction *ir_insert_cast(IrAnalyze *ira, | | |
| 137 | IrInstruction *before_instruction, IrInstruction *after_instruction, | | |
| 138 | IrInstruction *dest_type, IrInstruction *value, bool is_implicit) | | |
| 139 | { | | |
| 140 | IrInstructionCast *cast_instruction = ir_create_instruction<IrInstructionCast>(ira->exec, | | |
| 141 | before_instruction->source_node); | | |
| 142 | cast_instruction->dest_type = dest_type; | 106 | cast_instruction->dest_type = dest_type; |
| 143 | cast_instruction->value = value; | 107 | cast_instruction->value = value; |
| 144 | cast_instruction->is_implicit = is_implicit; | 108 | cast_instruction->is_implicit = is_implicit; |
| 145 | ir_instruction_insert(ira->current_basic_block, before_instruction, after_instruction, &cast_instruction->base); | | |
| 146 | return &cast_instruction->base; | 109 | return &cast_instruction->base; |
| 147 | } | 110 | } |
| 148 | | 111 | |
| 149 | static IrInstruction *ir_build_return(IrGen *irg, AstNode *source_node, IrInstruction *return_value) { | 112 | static IrInstruction *ir_build_return(IrBuilder *irb, AstNode *source_node, IrInstruction *return_value) { |
| 150 | IrInstructionReturn *return_instruction = ir_build_instruction<IrInstructionReturn>(irg, source_node); | 113 | IrInstructionReturn *return_instruction = ir_build_instruction<IrInstructionReturn>(irb, source_node); |
| 151 | return_instruction->base.type_entry = irg->codegen->builtin_types.entry_unreachable; | 114 | return_instruction->base.type_entry = irb->codegen->builtin_types.entry_unreachable; |
| 152 | return_instruction->base.static_value.ok = true; | 115 | return_instruction->base.static_value.ok = true; |
| 153 | return_instruction->value = return_value; | 116 | return_instruction->value = return_value; |
| 154 | return &return_instruction->base; | 117 | return &return_instruction->base; |
| 155 | } | 118 | } |
| 156 | | 119 | |
| 157 | static IrInstruction *ir_build_const_void(IrGen *irg, AstNode *source_node) { | 120 | static IrInstruction *ir_build_const_void(IrBuilder *irb, AstNode *source_node) { |
| 158 | IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irg, source_node); | 121 | IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node); |
| 159 | const_instruction->base.type_entry = irg->codegen->builtin_types.entry_void; | 122 | const_instruction->base.type_entry = irb->codegen->builtin_types.entry_void; |
| 160 | const_instruction->base.static_value.ok = true; | 123 | const_instruction->base.static_value.ok = true; |
| 161 | return &const_instruction->base; | 124 | return &const_instruction->base; |
| 162 | } | 125 | } |
| 163 | | 126 | |
| 164 | static IrInstruction *ir_build_const_bignum(IrGen *irg, AstNode *source_node, BigNum *bignum) { | 127 | static IrInstruction *ir_build_const_bignum(IrBuilder *irb, AstNode *source_node, BigNum *bignum) { |
| 165 | IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irg, source_node); | 128 | IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node); |
| 166 | const_instruction->base.type_entry = (bignum->kind == BigNumKindInt) ? | 129 | const_instruction->base.type_entry = (bignum->kind == BigNumKindInt) ? |
| 167 | irg->codegen->builtin_types.entry_num_lit_int : irg->codegen->builtin_types.entry_num_lit_float; | 130 | irb->codegen->builtin_types.entry_num_lit_int : irb->codegen->builtin_types.entry_num_lit_float; |
| 168 | const_instruction->base.static_value.ok = true; | 131 | const_instruction->base.static_value.ok = true; |
| 169 | const_instruction->base.static_value.data.x_bignum = *bignum; | 132 | const_instruction->base.static_value.data.x_bignum = *bignum; |
| 170 | return &const_instruction->base; | 133 | return &const_instruction->base; |
| 171 | } | 134 | } |
| 172 | | 135 | |
| 173 | static IrInstruction *ir_build_const_type(IrGen *irg, AstNode *source_node, TypeTableEntry *type_entry) { | 136 | static IrInstruction *ir_build_const_type(IrBuilder *irb, AstNode *source_node, TypeTableEntry *type_entry) { |
| 174 | IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irg, source_node); | 137 | IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node); |
| 175 | const_instruction->base.type_entry = irg->codegen->builtin_types.entry_type; | 138 | const_instruction->base.type_entry = irb->codegen->builtin_types.entry_type; |
| 176 | const_instruction->base.static_value.ok = true; | 139 | const_instruction->base.static_value.ok = true; |
| 177 | const_instruction->base.static_value.data.x_type = type_entry; | 140 | const_instruction->base.static_value.data.x_type = type_entry; |
| 178 | return &const_instruction->base; | 141 | return &const_instruction->base; |
| 179 | } | 142 | } |
| 180 | | 143 | |
| 181 | static IrInstruction *ir_build_const_fn(IrGen *irg, AstNode *source_node, FnTableEntry *fn_entry) { | 144 | static IrInstruction *ir_build_const_fn(IrBuilder *irb, AstNode *source_node, FnTableEntry *fn_entry) { |
| 182 | IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irg, source_node); | 145 | IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node); |
| 183 | const_instruction->base.type_entry = fn_entry->type_entry; | 146 | const_instruction->base.type_entry = fn_entry->type_entry; |
| 184 | const_instruction->base.static_value.ok = true; | 147 | const_instruction->base.static_value.ok = true; |
| 185 | const_instruction->base.static_value.data.x_fn = fn_entry; | 148 | const_instruction->base.static_value.data.x_fn = fn_entry; |
| 186 | return &const_instruction->base; | 149 | return &const_instruction->base; |
| 187 | } | 150 | } |
| 188 | | 151 | |
| 189 | static IrInstruction *ir_build_const_generic_fn(IrGen *irg, AstNode *source_node, TypeTableEntry *fn_type) { | 152 | static IrInstruction *ir_build_const_generic_fn(IrBuilder *irb, AstNode *source_node, TypeTableEntry *fn_type) { |
| 190 | IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irg, source_node); | 153 | IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node); |
| 191 | const_instruction->base.type_entry = fn_type; | 154 | const_instruction->base.type_entry = fn_type; |
| 192 | const_instruction->base.static_value.ok = true; | 155 | const_instruction->base.static_value.ok = true; |
| 193 | const_instruction->base.static_value.data.x_type = fn_type; | 156 | const_instruction->base.static_value.data.x_type = fn_type; |
| 194 | return &const_instruction->base; | 157 | return &const_instruction->base; |
| 195 | } | 158 | } |
| 196 | | 159 | |
| 197 | static IrInstruction *ir_build_bin_op(IrGen *irg, AstNode *source_node, IrBinOp op_id, | 160 | static IrInstruction *ir_build_bin_op(IrBuilder *irb, AstNode *source_node, IrBinOp op_id, |
| 198 | IrInstruction *op1, IrInstruction *op2) | 161 | IrInstruction *op1, IrInstruction *op2) |
| 199 | { | 162 | { |
| 200 | IrInstructionBinOp *bin_op_instruction = ir_build_instruction<IrInstructionBinOp>(irg, source_node); | 163 | IrInstructionBinOp *bin_op_instruction = ir_build_instruction<IrInstructionBinOp>(irb, source_node); |
| 201 | bin_op_instruction->op_id = op_id; | 164 | bin_op_instruction->op_id = op_id; |
| 202 | bin_op_instruction->op1 = op1; | 165 | bin_op_instruction->op1 = op1; |
| 203 | bin_op_instruction->op2 = op2; | 166 | bin_op_instruction->op2 = op2; |
| 204 | return &bin_op_instruction->base; | 167 | return &bin_op_instruction->base; |
| 205 | } | 168 | } |
| 206 | | 169 | |
| 207 | static IrInstruction *ir_build_load_var(IrGen *irg, AstNode *source_node, VariableTableEntry *var) { | 170 | static IrInstruction *ir_build_load_var(IrBuilder *irb, AstNode *source_node, VariableTableEntry *var) { |
| 208 | IrInstructionLoadVar *load_var_instruction = ir_build_instruction<IrInstructionLoadVar>(irg, source_node); | 171 | IrInstructionLoadVar *load_var_instruction = ir_build_instruction<IrInstructionLoadVar>(irb, source_node); |
| 209 | load_var_instruction->base.type_entry = var->type; | 172 | load_var_instruction->base.type_entry = var->type; |
| 210 | load_var_instruction->var = var; | 173 | load_var_instruction->var = var; |
| 211 | return &load_var_instruction->base; | 174 | return &load_var_instruction->base; |
| ... | @@ -226,7 +189,7 @@ static IrInstruction *ir_build_load_var(IrGen *irg, AstNode *source_node, Variab | ... | @@ -226,7 +189,7 @@ static IrInstruction *ir_build_load_var(IrGen *irg, AstNode *source_node, Variab |
| 226 | // return result; | 189 | // return result; |
| 227 | //} | 190 | //} |
| 228 | | 191 | |
| 229 | static void ir_gen_defers_for_block(IrGen *irg, BlockContext *inner_block, BlockContext *outer_block, | 192 | static void ir_gen_defers_for_block(IrBuilder *irb, BlockContext *inner_block, BlockContext *outer_block, |
| 230 | bool gen_error_defers, bool gen_maybe_defers) | 193 | bool gen_error_defers, bool gen_maybe_defers) |
| 231 | { | 194 | { |
| 232 | while (inner_block != outer_block) { | 195 | while (inner_block != outer_block) { |
| ... | @@ -236,15 +199,15 @@ static void ir_gen_defers_for_block(IrGen *irg, BlockContext *inner_block, Block | ... | @@ -236,15 +199,15 @@ static void ir_gen_defers_for_block(IrGen *irg, BlockContext *inner_block, Block |
| 236 | (gen_maybe_defers && inner_block->node->data.defer.kind == ReturnKindMaybe))) | 199 | (gen_maybe_defers && inner_block->node->data.defer.kind == ReturnKindMaybe))) |
| 237 | { | 200 | { |
| 238 | AstNode *defer_expr_node = inner_block->node->data.defer.expr; | 201 | AstNode *defer_expr_node = inner_block->node->data.defer.expr; |
| 239 | ir_gen_node(irg, defer_expr_node, defer_expr_node->block_context); | 202 | ir_gen_node(irb, defer_expr_node, defer_expr_node->block_context); |
| 240 | } | 203 | } |
| 241 | inner_block = inner_block->parent; | 204 | inner_block = inner_block->parent; |
| 242 | } | 205 | } |
| 243 | } | 206 | } |
| 244 | | 207 | |
| 245 | //static IrInstruction *ir_gen_return(IrGen *irg, AstNode *source_node, IrInstruction *value, ReturnKnowledge rk) { | 208 | //static IrInstruction *ir_gen_return(IrBuilder *irb, AstNode *source_node, IrInstruction *value, ReturnKnowledge rk) { |
| 246 | // BlockContext *defer_inner_block = source_node->block_context; | 209 | // BlockContext *defer_inner_block = source_node->block_context; |
| 247 | // BlockContext *defer_outer_block = irg->node->block_context; | 210 | // BlockContext *defer_outer_block = irb->node->block_context; |
| 248 | // if (rk == ReturnKnowledgeUnknown) { | 211 | // if (rk == ReturnKnowledgeUnknown) { |
| 249 | // if (get_conditional_defer_count(defer_inner_block, defer_outer_block) > 0) { | 212 | // if (get_conditional_defer_count(defer_inner_block, defer_outer_block) > 0) { |
| 250 | // // generate branching code that checks the return value and generates defers | 213 | // // generate branching code that checks the return value and generates defers |
| ... | @@ -252,14 +215,14 @@ static void ir_gen_defers_for_block(IrGen *irg, BlockContext *inner_block, Block | ... | @@ -252,14 +215,14 @@ static void ir_gen_defers_for_block(IrGen *irg, BlockContext *inner_block, Block |
| 252 | // zig_panic("TODO"); | 215 | // zig_panic("TODO"); |
| 253 | // } | 216 | // } |
| 254 | // } else if (rk != ReturnKnowledgeSkipDefers) { | 217 | // } else if (rk != ReturnKnowledgeSkipDefers) { |
| 255 | // ir_gen_defers_for_block(irg, defer_inner_block, defer_outer_block, | 218 | // ir_gen_defers_for_block(irb, defer_inner_block, defer_outer_block, |
| 256 | // rk == ReturnKnowledgeKnownError, rk == ReturnKnowledgeKnownNull); | 219 | // rk == ReturnKnowledgeKnownError, rk == ReturnKnowledgeKnownNull); |
| 257 | // } | 220 | // } |
| 258 | // | 221 | // |
| 259 | // return ir_build_return(irg, source_node, value); | 222 | // return ir_build_return(irb, source_node, value); |
| 260 | //} | 223 | //} |
| 261 | | 224 | |
| 262 | static IrInstruction *ir_gen_block(IrGen *irg, AstNode *block_node) { | 225 | static IrInstruction *ir_gen_block(IrBuilder *irb, AstNode *block_node) { |
| 263 | assert(block_node->type == NodeTypeBlock); | 226 | assert(block_node->type == NodeTypeBlock); |
| 264 | | 227 | |
| 265 | BlockContext *parent_context = block_node->block_context; | 228 | BlockContext *parent_context = block_node->block_context; |
| ... | @@ -269,8 +232,8 @@ static IrInstruction *ir_gen_block(IrGen *irg, AstNode *block_node) { | ... | @@ -269,8 +232,8 @@ static IrInstruction *ir_gen_block(IrGen *irg, AstNode *block_node) { |
| 269 | IrInstruction *return_value = nullptr; | 232 | IrInstruction *return_value = nullptr; |
| 270 | for (size_t i = 0; i < block_node->data.block.statements.length; i += 1) { | 233 | for (size_t i = 0; i < block_node->data.block.statements.length; i += 1) { |
| 271 | AstNode *statement_node = block_node->data.block.statements.at(i); | 234 | AstNode *statement_node = block_node->data.block.statements.at(i); |
| 272 | return_value = ir_gen_node(irg, statement_node, child_context); | 235 | return_value = ir_gen_node(irb, statement_node, child_context); |
| 273 | if (statement_node->type == NodeTypeDefer && return_value != irg->codegen->invalid_instruction) { | 236 | if (statement_node->type == NodeTypeDefer && return_value != irb->codegen->invalid_instruction) { |
| 274 | // defer starts a new block context | 237 | // defer starts a new block context |
| 275 | child_context = statement_node->data.defer.child_block; | 238 | child_context = statement_node->data.defer.child_block; |
| 276 | assert(child_context); | 239 | assert(child_context); |
| ... | @@ -278,20 +241,20 @@ static IrInstruction *ir_gen_block(IrGen *irg, AstNode *block_node) { | ... | @@ -278,20 +241,20 @@ static IrInstruction *ir_gen_block(IrGen *irg, AstNode *block_node) { |
| 278 | } | 241 | } |
| 279 | | 242 | |
| 280 | if (!return_value) | 243 | if (!return_value) |
| 281 | return_value = ir_build_const_void(irg, block_node); | 244 | return_value = ir_build_const_void(irb, block_node); |
| 282 | | 245 | |
| 283 | ir_gen_defers_for_block(irg, child_context, outer_block_context, false, false); | 246 | ir_gen_defers_for_block(irb, child_context, outer_block_context, false, false); |
| 284 | | 247 | |
| 285 | return return_value; | 248 | return return_value; |
| 286 | } | 249 | } |
| 287 | | 250 | |
| 288 | static IrInstruction *ir_gen_bin_op_id(IrGen *irg, AstNode *node, IrBinOp op_id) { | 251 | static IrInstruction *ir_gen_bin_op_id(IrBuilder *irb, AstNode *node, IrBinOp op_id) { |
| 289 | IrInstruction *op1 = ir_gen_node(irg, node->data.bin_op_expr.op1, node->block_context); | 252 | IrInstruction *op1 = ir_gen_node(irb, node->data.bin_op_expr.op1, node->block_context); |
| 290 | IrInstruction *op2 = ir_gen_node(irg, node->data.bin_op_expr.op2, node->block_context); | 253 | IrInstruction *op2 = ir_gen_node(irb, node->data.bin_op_expr.op2, node->block_context); |
| 291 | return ir_build_bin_op(irg, node, op_id, op1, op2); | 254 | return ir_build_bin_op(irb, node, op_id, op1, op2); |
| 292 | } | 255 | } |
| 293 | | 256 | |
| 294 | static IrInstruction *ir_gen_bin_op(IrGen *irg, AstNode *node) { | 257 | static IrInstruction *ir_gen_bin_op(IrBuilder *irb, AstNode *node) { |
| 295 | assert(node->type == NodeTypeBinOpExpr); | 258 | assert(node->type == NodeTypeBinOpExpr); |
| 296 | | 259 | |
| 297 | BinOpType bin_op_type = node->data.bin_op_expr.bin_op; | 260 | BinOpType bin_op_type = node->data.bin_op_expr.bin_op; |
| ... | @@ -322,144 +285,144 @@ static IrInstruction *ir_gen_bin_op(IrGen *irg, AstNode *node) { | ... | @@ -322,144 +285,144 @@ static IrInstruction *ir_gen_bin_op(IrGen *irg, AstNode *node) { |
| 322 | // because of the control flow | 285 | // because of the control flow |
| 323 | zig_panic("TODO gen IR for bool or/and"); | 286 | zig_panic("TODO gen IR for bool or/and"); |
| 324 | case BinOpTypeCmpEq: | 287 | case BinOpTypeCmpEq: |
| 325 | return ir_gen_bin_op_id(irg, node, IrBinOpCmpEq); | 288 | return ir_gen_bin_op_id(irb, node, IrBinOpCmpEq); |
| 326 | case BinOpTypeCmpNotEq: | 289 | case BinOpTypeCmpNotEq: |
| 327 | return ir_gen_bin_op_id(irg, node, IrBinOpCmpNotEq); | 290 | return ir_gen_bin_op_id(irb, node, IrBinOpCmpNotEq); |
| 328 | case BinOpTypeCmpLessThan: | 291 | case BinOpTypeCmpLessThan: |
| 329 | return ir_gen_bin_op_id(irg, node, IrBinOpCmpLessThan); | 292 | return ir_gen_bin_op_id(irb, node, IrBinOpCmpLessThan); |
| 330 | case BinOpTypeCmpGreaterThan: | 293 | case BinOpTypeCmpGreaterThan: |
| 331 | return ir_gen_bin_op_id(irg, node, IrBinOpCmpGreaterThan); | 294 | return ir_gen_bin_op_id(irb, node, IrBinOpCmpGreaterThan); |
| 332 | case BinOpTypeCmpLessOrEq: | 295 | case BinOpTypeCmpLessOrEq: |
| 333 | return ir_gen_bin_op_id(irg, node, IrBinOpCmpLessOrEq); | 296 | return ir_gen_bin_op_id(irb, node, IrBinOpCmpLessOrEq); |
| 334 | case BinOpTypeCmpGreaterOrEq: | 297 | case BinOpTypeCmpGreaterOrEq: |
| 335 | return ir_gen_bin_op_id(irg, node, IrBinOpCmpGreaterOrEq); | 298 | return ir_gen_bin_op_id(irb, node, IrBinOpCmpGreaterOrEq); |
| 336 | case BinOpTypeBinOr: | 299 | case BinOpTypeBinOr: |
| 337 | return ir_gen_bin_op_id(irg, node, IrBinOpBinOr); | 300 | return ir_gen_bin_op_id(irb, node, IrBinOpBinOr); |
| 338 | case BinOpTypeBinXor: | 301 | case BinOpTypeBinXor: |
| 339 | return ir_gen_bin_op_id(irg, node, IrBinOpBinXor); | 302 | return ir_gen_bin_op_id(irb, node, IrBinOpBinXor); |
| 340 | case BinOpTypeBinAnd: | 303 | case BinOpTypeBinAnd: |
| 341 | return ir_gen_bin_op_id(irg, node, IrBinOpBinAnd); | 304 | return ir_gen_bin_op_id(irb, node, IrBinOpBinAnd); |
| 342 | case BinOpTypeBitShiftLeft: | 305 | case BinOpTypeBitShiftLeft: |
| 343 | return ir_gen_bin_op_id(irg, node, IrBinOpBitShiftLeft); | 306 | return ir_gen_bin_op_id(irb, node, IrBinOpBitShiftLeft); |
| 344 | case BinOpTypeBitShiftLeftWrap: | 307 | case BinOpTypeBitShiftLeftWrap: |
| 345 | return ir_gen_bin_op_id(irg, node, IrBinOpBitShiftLeftWrap); | 308 | return ir_gen_bin_op_id(irb, node, IrBinOpBitShiftLeftWrap); |
| 346 | case BinOpTypeBitShiftRight: | 309 | case BinOpTypeBitShiftRight: |
| 347 | return ir_gen_bin_op_id(irg, node, IrBinOpBitShiftRight); | 310 | return ir_gen_bin_op_id(irb, node, IrBinOpBitShiftRight); |
| 348 | case BinOpTypeAdd: | 311 | case BinOpTypeAdd: |
| 349 | return ir_gen_bin_op_id(irg, node, IrBinOpAdd); | 312 | return ir_gen_bin_op_id(irb, node, IrBinOpAdd); |
| 350 | case BinOpTypeAddWrap: | 313 | case BinOpTypeAddWrap: |
| 351 | return ir_gen_bin_op_id(irg, node, IrBinOpAddWrap); | 314 | return ir_gen_bin_op_id(irb, node, IrBinOpAddWrap); |
| 352 | case BinOpTypeSub: | 315 | case BinOpTypeSub: |
| 353 | return ir_gen_bin_op_id(irg, node, IrBinOpSub); | 316 | return ir_gen_bin_op_id(irb, node, IrBinOpSub); |
| 354 | case BinOpTypeSubWrap: | 317 | case BinOpTypeSubWrap: |
| 355 | return ir_gen_bin_op_id(irg, node, IrBinOpSubWrap); | 318 | return ir_gen_bin_op_id(irb, node, IrBinOpSubWrap); |
| 356 | case BinOpTypeMult: | 319 | case BinOpTypeMult: |
| 357 | return ir_gen_bin_op_id(irg, node, IrBinOpMult); | 320 | return ir_gen_bin_op_id(irb, node, IrBinOpMult); |
| 358 | case BinOpTypeMultWrap: | 321 | case BinOpTypeMultWrap: |
| 359 | return ir_gen_bin_op_id(irg, node, IrBinOpMultWrap); | 322 | return ir_gen_bin_op_id(irb, node, IrBinOpMultWrap); |
| 360 | case BinOpTypeDiv: | 323 | case BinOpTypeDiv: |
| 361 | return ir_gen_bin_op_id(irg, node, IrBinOpDiv); | 324 | return ir_gen_bin_op_id(irb, node, IrBinOpDiv); |
| 362 | case BinOpTypeMod: | 325 | case BinOpTypeMod: |
| 363 | return ir_gen_bin_op_id(irg, node, IrBinOpMod); | 326 | return ir_gen_bin_op_id(irb, node, IrBinOpMod); |
| 364 | case BinOpTypeArrayCat: | 327 | case BinOpTypeArrayCat: |
| 365 | return ir_gen_bin_op_id(irg, node, IrBinOpArrayCat); | 328 | return ir_gen_bin_op_id(irb, node, IrBinOpArrayCat); |
| 366 | case BinOpTypeArrayMult: | 329 | case BinOpTypeArrayMult: |
| 367 | return ir_gen_bin_op_id(irg, node, IrBinOpArrayMult); | 330 | return ir_gen_bin_op_id(irb, node, IrBinOpArrayMult); |
| 368 | case BinOpTypeUnwrapMaybe: | 331 | case BinOpTypeUnwrapMaybe: |
| 369 | zig_panic("TODO gen IR for unwrap maybe"); | 332 | zig_panic("TODO gen IR for unwrap maybe"); |
| 370 | } | 333 | } |
| 371 | zig_unreachable(); | 334 | zig_unreachable(); |
| 372 | } | 335 | } |
| 373 | | 336 | |
| 374 | static IrInstruction *ir_gen_num_lit(IrGen *irg, AstNode *node) { | 337 | static IrInstruction *ir_gen_num_lit(IrBuilder *irb, AstNode *node) { |
| 375 | assert(node->type == NodeTypeNumberLiteral); | 338 | assert(node->type == NodeTypeNumberLiteral); |
| 376 | | 339 | |
| 377 | if (node->data.number_literal.overflow) { | 340 | if (node->data.number_literal.overflow) { |
| 378 | add_node_error(irg->codegen, node, buf_sprintf("number literal too large to be represented in any type")); | 341 | add_node_error(irb->codegen, node, buf_sprintf("number literal too large to be represented in any type")); |
| 379 | return irg->codegen->invalid_instruction; | 342 | return irb->codegen->invalid_instruction; |
| 380 | } | 343 | } |
| 381 | | 344 | |
| 382 | return ir_build_const_bignum(irg, node, node->data.number_literal.bignum); | 345 | return ir_build_const_bignum(irb, node, node->data.number_literal.bignum); |
| 383 | } | 346 | } |
| 384 | | 347 | |
| 385 | static IrInstruction *ir_gen_decl_ref(IrGen *irg, AstNode *source_node, AstNode *decl_node, | 348 | static IrInstruction *ir_gen_decl_ref(IrBuilder *irb, AstNode *source_node, AstNode *decl_node, |
| 386 | bool pointer_only, BlockContext *scope) | 349 | bool pointer_only, BlockContext *scope) |
| 387 | { | 350 | { |
| 388 | resolve_top_level_decl(irg->codegen, decl_node, pointer_only); | 351 | resolve_top_level_decl(irb->codegen, decl_node, pointer_only); |
| 389 | TopLevelDecl *tld = get_as_top_level_decl(decl_node); | 352 | TopLevelDecl *tld = get_as_top_level_decl(decl_node); |
| 390 | if (tld->resolution == TldResolutionInvalid) | 353 | if (tld->resolution == TldResolutionInvalid) |
| 391 | return irg->codegen->invalid_instruction; | 354 | return irb->codegen->invalid_instruction; |
| 392 | | 355 | |
| 393 | if (decl_node->type == NodeTypeVariableDeclaration) { | 356 | if (decl_node->type == NodeTypeVariableDeclaration) { |
| 394 | VariableTableEntry *var = decl_node->data.variable_declaration.variable; | 357 | VariableTableEntry *var = decl_node->data.variable_declaration.variable; |
| 395 | return ir_build_load_var(irg, source_node, var); | 358 | return ir_build_load_var(irb, source_node, var); |
| 396 | } else if (decl_node->type == NodeTypeFnProto) { | 359 | } else if (decl_node->type == NodeTypeFnProto) { |
| 397 | FnTableEntry *fn_entry = decl_node->data.fn_proto.fn_table_entry; | 360 | FnTableEntry *fn_entry = decl_node->data.fn_proto.fn_table_entry; |
| 398 | assert(fn_entry->type_entry); | 361 | assert(fn_entry->type_entry); |
| 399 | if (fn_entry->type_entry->id == TypeTableEntryIdGenericFn) { | 362 | if (fn_entry->type_entry->id == TypeTableEntryIdGenericFn) { |
| 400 | return ir_build_const_generic_fn(irg, source_node, fn_entry->type_entry); | 363 | return ir_build_const_generic_fn(irb, source_node, fn_entry->type_entry); |
| 401 | } else { | 364 | } else { |
| 402 | return ir_build_const_fn(irg, source_node, fn_entry); | 365 | return ir_build_const_fn(irb, source_node, fn_entry); |
| 403 | } | 366 | } |
| 404 | } else if (decl_node->type == NodeTypeContainerDecl) { | 367 | } else if (decl_node->type == NodeTypeContainerDecl) { |
| 405 | if (decl_node->data.struct_decl.generic_params.length > 0) { | 368 | if (decl_node->data.struct_decl.generic_params.length > 0) { |
| 406 | TypeTableEntry *type_entry = decl_node->data.struct_decl.generic_fn_type; | 369 | TypeTableEntry *type_entry = decl_node->data.struct_decl.generic_fn_type; |
| 407 | assert(type_entry); | 370 | assert(type_entry); |
| 408 | return ir_build_const_generic_fn(irg, source_node, type_entry); | 371 | return ir_build_const_generic_fn(irb, source_node, type_entry); |
| 409 | } else { | 372 | } else { |
| 410 | return ir_build_const_type(irg, source_node, decl_node->data.struct_decl.type_entry); | 373 | return ir_build_const_type(irb, source_node, decl_node->data.struct_decl.type_entry); |
| 411 | } | 374 | } |
| 412 | } else if (decl_node->type == NodeTypeTypeDecl) { | 375 | } else if (decl_node->type == NodeTypeTypeDecl) { |
| 413 | return ir_build_const_type(irg, source_node, decl_node->data.type_decl.child_type_entry); | 376 | return ir_build_const_type(irb, source_node, decl_node->data.type_decl.child_type_entry); |
| 414 | } else { | 377 | } else { |
| 415 | zig_unreachable(); | 378 | zig_unreachable(); |
| 416 | } | 379 | } |
| 417 | } | 380 | } |
| 418 | | 381 | |
| 419 | static IrInstruction *ir_gen_symbol(IrGen *irg, AstNode *node, bool pointer_only) { | 382 | static IrInstruction *ir_gen_symbol(IrBuilder *irb, AstNode *node, bool pointer_only) { |
| 420 | assert(node->type == NodeTypeSymbol); | 383 | assert(node->type == NodeTypeSymbol); |
| 421 | | 384 | |
| 422 | if (node->data.symbol_expr.override_type_entry) | 385 | if (node->data.symbol_expr.override_type_entry) |
| 423 | return ir_build_const_type(irg, node, node->data.symbol_expr.override_type_entry); | 386 | return ir_build_const_type(irb, node, node->data.symbol_expr.override_type_entry); |
| 424 | | 387 | |
| 425 | Buf *variable_name = node->data.symbol_expr.symbol; | 388 | Buf *variable_name = node->data.symbol_expr.symbol; |
| 426 | | 389 | |
| 427 | auto primitive_table_entry = irg->codegen->primitive_type_table.maybe_get(variable_name); | 390 | auto primitive_table_entry = irb->codegen->primitive_type_table.maybe_get(variable_name); |
| 428 | if (primitive_table_entry) | 391 | if (primitive_table_entry) |
| 429 | return ir_build_const_type(irg, node, primitive_table_entry->value); | 392 | return ir_build_const_type(irb, node, primitive_table_entry->value); |
| 430 | | 393 | |
| 431 | VariableTableEntry *var = find_variable(irg->codegen, node->block_context, variable_name); | 394 | VariableTableEntry *var = find_variable(irb->codegen, node->block_context, variable_name); |
| 432 | if (var) | 395 | if (var) |
| 433 | return ir_build_load_var(irg, node, var); | 396 | return ir_build_load_var(irb, node, var); |
| 434 | | 397 | |
| 435 | AstNode *decl_node = find_decl(node->block_context, variable_name); | 398 | AstNode *decl_node = find_decl(node->block_context, variable_name); |
| 436 | if (decl_node) | 399 | if (decl_node) |
| 437 | return ir_gen_decl_ref(irg, node, decl_node, pointer_only, node->block_context); | 400 | return ir_gen_decl_ref(irb, node, decl_node, pointer_only, node->block_context); |
| 438 | | 401 | |
| 439 | if (node->owner->any_imports_failed) { | 402 | if (node->owner->any_imports_failed) { |
| 440 | // skip the error message since we had a failing import in this file | 403 | // skip the error message since we had a failing import in this file |
| 441 | // if an import breaks we don't need redundant undeclared identifier errors | 404 | // if an import breaks we don't need redundant undeclared identifier errors |
| 442 | return irg->codegen->invalid_instruction; | 405 | return irb->codegen->invalid_instruction; |
| 443 | } | 406 | } |
| 444 | | 407 | |
| 445 | add_node_error(irg->codegen, node, buf_sprintf("use of undeclared identifier '%s'", buf_ptr(variable_name))); | 408 | add_node_error(irb->codegen, node, buf_sprintf("use of undeclared identifier '%s'", buf_ptr(variable_name))); |
| 446 | return irg->codegen->invalid_instruction; | 409 | return irb->codegen->invalid_instruction; |
| 447 | } | 410 | } |
| 448 | | 411 | |
| 449 | static IrInstruction *ir_gen_node_extra(IrGen *irg, AstNode *node, BlockContext *block_context, | 412 | static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockContext *block_context, |
| 450 | bool pointer_only) | 413 | bool pointer_only) |
| 451 | { | 414 | { |
| 452 | node->block_context = block_context; | 415 | node->block_context = block_context; |
| 453 | | 416 | |
| 454 | switch (node->type) { | 417 | switch (node->type) { |
| 455 | case NodeTypeBlock: | 418 | case NodeTypeBlock: |
| 456 | return ir_gen_block(irg, node); | 419 | return ir_gen_block(irb, node); |
| 457 | case NodeTypeBinOpExpr: | 420 | case NodeTypeBinOpExpr: |
| 458 | return ir_gen_bin_op(irg, node); | 421 | return ir_gen_bin_op(irb, node); |
| 459 | case NodeTypeNumberLiteral: | 422 | case NodeTypeNumberLiteral: |
| 460 | return ir_gen_num_lit(irg, node); | 423 | return ir_gen_num_lit(irb, node); |
| 461 | case NodeTypeSymbol: | 424 | case NodeTypeSymbol: |
| 462 | return ir_gen_symbol(irg, node, pointer_only); | 425 | return ir_gen_symbol(irb, node, pointer_only); |
| 463 | case NodeTypeUnwrapErrorExpr: | 426 | case NodeTypeUnwrapErrorExpr: |
| 464 | case NodeTypeReturnExpr: | 427 | case NodeTypeReturnExpr: |
| 465 | case NodeTypeDefer: | 428 | case NodeTypeDefer: |
| ... | @@ -509,9 +472,9 @@ static IrInstruction *ir_gen_node_extra(IrGen *irg, AstNode *node, BlockContext | ... | @@ -509,9 +472,9 @@ static IrInstruction *ir_gen_node_extra(IrGen *irg, AstNode *node, BlockContext |
| 509 | zig_unreachable(); | 472 | zig_unreachable(); |
| 510 | } | 473 | } |
| 511 | | 474 | |
| 512 | static IrInstruction *ir_gen_node(IrGen *irg, AstNode *node, BlockContext *scope) { | 475 | static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, BlockContext *scope) { |
| 513 | bool pointer_only_no = false; | 476 | bool pointer_only_no = false; |
| 514 | return ir_gen_node_extra(irg, node, scope, pointer_only_no); | 477 | return ir_gen_node_extra(irb, node, scope, pointer_only_no); |
| 515 | } | 478 | } |
| 516 | | 479 | |
| 517 | static IrInstruction *ir_gen_add_return(CodeGen *g, AstNode *node, BlockContext *scope, | 480 | static IrInstruction *ir_gen_add_return(CodeGen *g, AstNode *node, BlockContext *scope, |
| ... | @@ -519,28 +482,23 @@ static IrInstruction *ir_gen_add_return(CodeGen *g, AstNode *node, BlockContext | ... | @@ -519,28 +482,23 @@ static IrInstruction *ir_gen_add_return(CodeGen *g, AstNode *node, BlockContext |
| 519 | { | 482 | { |
| 520 | assert(node->owner); | 483 | assert(node->owner); |
| 521 | | 484 | |
| 522 | IrGen ir_gen = {0}; | 485 | IrBuilder ir_gen = {0}; |
| 523 | IrGen *irg = &ir_gen; | 486 | IrBuilder *irb = &ir_gen; |
| 524 | | 487 | |
| 525 | irg->codegen = g; | 488 | irb->codegen = g; |
| 526 | irg->node = node; | 489 | irb->exec = ir_executable; |
| 527 | irg->exec = ir_executable; | | |
| 528 | | 490 | |
| 529 | irg->exec->basic_block_list = allocate<IrBasicBlock*>(1); | 491 | irb->current_basic_block = allocate<IrBasicBlock>(1); |
| 530 | irg->exec->basic_block_count = 1; | 492 | irb->exec->basic_block_list.append(irb->current_basic_block); |
| 531 | | 493 | |
| 532 | IrBasicBlock *entry_basic_block = allocate<IrBasicBlock>(1); | 494 | IrInstruction *result = ir_gen_node_extra(irb, node, scope, pointer_only); |
| 533 | irg->current_basic_block = entry_basic_block; | | |
| 534 | irg->exec->basic_block_list[0] = entry_basic_block; | | |
| 535 | | | |
| 536 | IrInstruction *result = ir_gen_node_extra(irg, node, scope, pointer_only); | | |
| 537 | assert(result); | 495 | assert(result); |
| 538 | | 496 | |
| 539 | if (result == g->invalid_instruction) | 497 | if (result == g->invalid_instruction) |
| 540 | return result; | 498 | return result; |
| 541 | | 499 | |
| 542 | if (add_return) | 500 | if (add_return) |
| 543 | return ir_build_return(irg, result->source_node, result); | 501 | return ir_build_return(irb, result->source_node, result); |
| 544 | | 502 | |
| 545 | return result; | 503 | return result; |
| 546 | } | 504 | } |
| ... | @@ -566,6 +524,11 @@ IrInstruction *ir_gen_fn(CodeGen *codegn, FnTableEntry *fn_entry) { | ... | @@ -566,6 +524,11 @@ IrInstruction *ir_gen_fn(CodeGen *codegn, FnTableEntry *fn_entry) { |
| 566 | return ir_gen_add_return(codegn, body_node, scope, ir_executable, add_return_yes, pointer_only_no); | 524 | return ir_gen_add_return(codegn, body_node, scope, ir_executable, add_return_yes, pointer_only_no); |
| 567 | } | 525 | } |
| 568 | | 526 | |
| | 527 | static void ir_link_new(IrInstruction *new_instruction, IrInstruction *old_instruction) { |
| | 528 | new_instruction->other = old_instruction; |
| | 529 | old_instruction->other = new_instruction; |
| | 530 | } |
| | 531 | |
| 569 | /* | 532 | /* |
| 570 | static void analyze_goto_pass2(CodeGen *g, ImportTableEntry *import, AstNode *node) { | 533 | static void analyze_goto_pass2(CodeGen *g, ImportTableEntry *import, AstNode *node) { |
| 571 | assert(node->type == NodeTypeGoto); | 534 | assert(node->type == NodeTypeGoto); |
| ... | @@ -640,7 +603,7 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc | ... | @@ -640,7 +603,7 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc |
| 640 | | 603 | |
| 641 | const char *num_lit_str = (const_val->data.x_bignum.kind == BigNumKindFloat) ? "float" : "integer"; | 604 | const char *num_lit_str = (const_val->data.x_bignum.kind == BigNumKindFloat) ? "float" : "integer"; |
| 642 | | 605 | |
| 643 | add_node_error(ira->codegen, instruction->source_node, | 606 | add_node_error(ira->old_irb.codegen, instruction->source_node, |
| 644 | buf_sprintf("%s value %s cannot be implicitly casted to type '%s'", | 607 | buf_sprintf("%s value %s cannot be implicitly casted to type '%s'", |
| 645 | num_lit_str, | 608 | num_lit_str, |
| 646 | buf_ptr(bignum_to_buf(&const_val->data.x_bignum)), | 609 | buf_ptr(bignum_to_buf(&const_val->data.x_bignum)), |
| ... | @@ -654,7 +617,7 @@ static TypeTableEntry *ir_determine_peer_types(IrAnalyze *ira, IrInstruction *pa | ... | @@ -654,7 +617,7 @@ static TypeTableEntry *ir_determine_peer_types(IrAnalyze *ira, IrInstruction *pa |
| 654 | assert(instruction_count >= 1); | 617 | assert(instruction_count >= 1); |
| 655 | IrInstruction *prev_inst = instructions[0]; | 618 | IrInstruction *prev_inst = instructions[0]; |
| 656 | if (prev_inst->type_entry->id == TypeTableEntryIdInvalid) { | 619 | if (prev_inst->type_entry->id == TypeTableEntryIdInvalid) { |
| 657 | return ira->codegen->builtin_types.entry_invalid; | 620 | return ira->old_irb.codegen->builtin_types.entry_invalid; |
| 658 | } | 621 | } |
| 659 | for (size_t i = 1; i < instruction_count; i += 1) { | 622 | for (size_t i = 1; i < instruction_count; i += 1) { |
| 660 | IrInstruction *cur_inst = instructions[i]; | 623 | IrInstruction *cur_inst = instructions[i]; |
| ... | @@ -701,7 +664,7 @@ static TypeTableEntry *ir_determine_peer_types(IrAnalyze *ira, IrInstruction *pa | ... | @@ -701,7 +664,7 @@ static TypeTableEntry *ir_determine_peer_types(IrAnalyze *ira, IrInstruction *pa |
| 701 | prev_inst = cur_inst; | 664 | prev_inst = cur_inst; |
| 702 | continue; | 665 | continue; |
| 703 | } else { | 666 | } else { |
| 704 | return ira->codegen->builtin_types.entry_invalid; | 667 | return ira->old_irb.codegen->builtin_types.entry_invalid; |
| 705 | } | 668 | } |
| 706 | } else if (cur_type->id == TypeTableEntryIdNumLitInt || | 669 | } else if (cur_type->id == TypeTableEntryIdNumLitInt || |
| 707 | cur_type->id == TypeTableEntryIdNumLitFloat) | 670 | cur_type->id == TypeTableEntryIdNumLitFloat) |
| ... | @@ -709,14 +672,14 @@ static TypeTableEntry *ir_determine_peer_types(IrAnalyze *ira, IrInstruction *pa | ... | @@ -709,14 +672,14 @@ static TypeTableEntry *ir_determine_peer_types(IrAnalyze *ira, IrInstruction *pa |
| 709 | if (ir_num_lit_fits_in_other_type(ira, cur_inst, prev_type)) { | 672 | if (ir_num_lit_fits_in_other_type(ira, cur_inst, prev_type)) { |
| 710 | continue; | 673 | continue; |
| 711 | } else { | 674 | } else { |
| 712 | return ira->codegen->builtin_types.entry_invalid; | 675 | return ira->old_irb.codegen->builtin_types.entry_invalid; |
| 713 | } | 676 | } |
| 714 | } else { | 677 | } else { |
| 715 | add_node_error(ira->codegen, parent_instruction->source_node, | 678 | add_node_error(ira->old_irb.codegen, parent_instruction->source_node, |
| 716 | buf_sprintf("incompatible types: '%s' and '%s'", | 679 | buf_sprintf("incompatible types: '%s' and '%s'", |
| 717 | buf_ptr(&prev_type->name), buf_ptr(&cur_type->name))); | 680 | buf_ptr(&prev_type->name), buf_ptr(&cur_type->name))); |
| 718 | | 681 | |
| 719 | return ira->codegen->builtin_types.entry_invalid; | 682 | return ira->old_irb.codegen->builtin_types.entry_invalid; |
| 720 | } | 683 | } |
| 721 | } | 684 | } |
| 722 | return prev_inst->type_entry; | 685 | return prev_inst->type_entry; |
| ... | @@ -819,14 +782,9 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, IrInstruction *pare | ... | @@ -819,14 +782,9 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, IrInstruction *pare |
| 819 | return ir_determine_peer_types(ira, parent_instruction, instructions, instruction_count); | 782 | return ir_determine_peer_types(ira, parent_instruction, instructions, instruction_count); |
| 820 | } | 783 | } |
| 821 | | 784 | |
| 822 | static IrInstruction *ir_get_casted_value(IrAnalyze *ira, IrInstruction *value, | 785 | static IrInstruction *ir_get_casted_value(IrAnalyze *ira, IrInstruction *value, TypeTableEntry *expected_type) { |
| 823 | TypeTableEntry *expected_type, | | |
| 824 | IrInstruction *before_instruction, IrInstruction *after_instruction) | | |
| 825 | { | | |
| 826 | assert(value); | 786 | assert(value); |
| 827 | assert(before_instruction || after_instruction); | 787 | assert(value != ira->old_irb.codegen->invalid_instruction); |
| 828 | assert(!before_instruction || !after_instruction); | | |
| 829 | assert(value != ira->codegen->invalid_instruction); | | |
| 830 | assert(!expected_type || expected_type->id != TypeTableEntryIdInvalid); | 788 | assert(!expected_type || expected_type->id != TypeTableEntryIdInvalid); |
| 831 | assert(value->type_entry); | 789 | assert(value->type_entry); |
| 832 | assert(value->type_entry->id != TypeTableEntryIdInvalid); | 790 | assert(value->type_entry->id != TypeTableEntryIdInvalid); |
| ... | @@ -840,23 +798,22 @@ static IrInstruction *ir_get_casted_value(IrAnalyze *ira, IrInstruction *value, | ... | @@ -840,23 +798,22 @@ static IrInstruction *ir_get_casted_value(IrAnalyze *ira, IrInstruction *value, |
| 840 | ImplicitCastMatchResult result = ir_types_match_with_implicit_cast(ira, expected_type, value->type_entry, value); | 798 | ImplicitCastMatchResult result = ir_types_match_with_implicit_cast(ira, expected_type, value->type_entry, value); |
| 841 | switch (result) { | 799 | switch (result) { |
| 842 | case ImplicitCastMatchResultNo: | 800 | case ImplicitCastMatchResultNo: |
| 843 | add_node_error(ira->codegen, first_executing_node(value->source_node), | 801 | add_node_error(ira->old_irb.codegen, first_executing_node(value->source_node), |
| 844 | buf_sprintf("expected type '%s', got '%s'", | 802 | buf_sprintf("expected type '%s', got '%s'", |
| 845 | buf_ptr(&expected_type->name), | 803 | buf_ptr(&expected_type->name), |
| 846 | buf_ptr(&value->type_entry->name))); | 804 | buf_ptr(&value->type_entry->name))); |
| 847 | return ira->codegen->invalid_instruction; | 805 | return ira->old_irb.codegen->invalid_instruction; |
| 848 | | 806 | |
| 849 | case ImplicitCastMatchResultYes: | 807 | case ImplicitCastMatchResultYes: |
| 850 | { | 808 | { |
| 851 | IrInstruction *dest_type = ir_insert_const_type(ira, before_instruction, | 809 | IrInstruction *dest_type = ir_build_const_type(&ira->new_irb, value->source_node, expected_type); |
| 852 | after_instruction, expected_type); | | |
| 853 | bool is_implicit = true; | 810 | bool is_implicit = true; |
| 854 | IrInstruction *cast_instruction = ir_insert_cast(ira, nullptr, dest_type, | 811 | IrInstruction *cast_instruction = ir_build_cast(&ira->new_irb, value->source_node, dest_type, |
| 855 | dest_type, value, is_implicit); | 812 | value, is_implicit); |
| 856 | return cast_instruction; | 813 | return cast_instruction; |
| 857 | } | 814 | } |
| 858 | case ImplicitCastMatchResultReportedError: | 815 | case ImplicitCastMatchResultReportedError: |
| 859 | return ira->codegen->invalid_instruction; | 816 | return ira->old_irb.codegen->invalid_instruction; |
| 860 | } | 817 | } |
| 861 | | 818 | |
| 862 | zig_unreachable(); | 819 | zig_unreachable(); |
| ... | @@ -871,19 +828,20 @@ static TypeTableEntry *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructi | ... | @@ -871,19 +828,20 @@ static TypeTableEntry *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructi |
| 871 | } | 828 | } |
| 872 | | 829 | |
| 873 | TypeTableEntry *expected_return_type = scope->fn_entry->type_entry->data.fn.fn_type_id.return_type; | 830 | TypeTableEntry *expected_return_type = scope->fn_entry->type_entry->data.fn.fn_type_id.return_type; |
| 874 | if (expected_return_type->id == TypeTableEntryIdVoid && !return_instruction->value) { | | |
| 875 | return ira->codegen->builtin_types.entry_unreachable; | | |
| 876 | } | | |
| 877 | | 831 | |
| 878 | return_instruction->value = ir_get_casted_value(ira, | 832 | IrInstruction *value = ir_get_casted_value(ira, return_instruction->value->other, expected_return_type); |
| 879 | return_instruction->value, expected_return_type, &return_instruction->base, nullptr); | 833 | if (value == ira->codegen->invalid_instruction) { |
| 880 | if (return_instruction->value == ira->codegen->invalid_instruction) { | | |
| 881 | return ira->codegen->builtin_types.entry_invalid; | 834 | return ira->codegen->builtin_types.entry_invalid; |
| 882 | } | 835 | } |
| | 836 | |
| | 837 | ir_link_new(ir_build_return(&ira->new_irb, return_instruction->base.source_node, value), |
| | 838 | &return_instruction->base); |
| | 839 | |
| 883 | return ira->codegen->builtin_types.entry_unreachable; | 840 | return ira->codegen->builtin_types.entry_unreachable; |
| 884 | } | 841 | } |
| 885 | | 842 | |
| 886 | static TypeTableEntry *ir_analyze_instruction_const(IrAnalyze *ira, IrInstructionConst *const_instruction) { | 843 | static TypeTableEntry *ir_analyze_instruction_const(IrAnalyze *ira, IrInstructionConst *const_instruction) { |
| | 844 | const_instruction->base.other = &const_instruction->base; |
| 887 | return const_instruction->base.type_entry; | 845 | return const_instruction->base.type_entry; |
| 888 | } | 846 | } |
| 889 | | 847 | |
| ... | @@ -891,17 +849,18 @@ static TypeTableEntry *ir_analyze_bin_op_bool(IrAnalyze *ira, IrInstructionBinOp | ... | @@ -891,17 +849,18 @@ static TypeTableEntry *ir_analyze_bin_op_bool(IrAnalyze *ira, IrInstructionBinOp |
| 891 | IrInstruction *op1 = bin_op_instruction->op1; | 849 | IrInstruction *op1 = bin_op_instruction->op1; |
| 892 | IrInstruction *op2 = bin_op_instruction->op2; | 850 | IrInstruction *op2 = bin_op_instruction->op2; |
| 893 | | 851 | |
| 894 | IrInstruction *casted_op1 = ir_get_casted_value(ira, op1, ira->codegen->builtin_types.entry_bool, | 852 | IrInstruction *casted_op1 = ir_get_casted_value(ira, op1->other, ira->old_irb.codegen->builtin_types.entry_bool); |
| 895 | &bin_op_instruction->base, nullptr); | 853 | if (casted_op1 == ira->old_irb.codegen->invalid_instruction) |
| 896 | if (casted_op1 == ira->codegen->invalid_instruction) | 854 | return ira->old_irb.codegen->builtin_types.entry_invalid; |
| 897 | return ira->codegen->builtin_types.entry_invalid; | | |
| 898 | | 855 | |
| 899 | IrInstruction *casted_op2 = ir_get_casted_value(ira, op2, ira->codegen->builtin_types.entry_bool, | 856 | IrInstruction *casted_op2 = ir_get_casted_value(ira, op2->other, ira->old_irb.codegen->builtin_types.entry_bool); |
| 900 | &bin_op_instruction->base, nullptr); | 857 | if (casted_op2 == ira->old_irb.codegen->invalid_instruction) |
| 901 | if (casted_op2 == ira->codegen->invalid_instruction) | 858 | return ira->old_irb.codegen->builtin_types.entry_invalid; |
| 902 | return ira->codegen->builtin_types.entry_invalid; | 859 | |
| | 860 | ir_link_new(ir_build_bin_op(&ira->new_irb, bin_op_instruction->base.source_node, |
| | 861 | bin_op_instruction->op_id, op1->other, op2->other), &bin_op_instruction->base); |
| 903 | | 862 | |
| 904 | return ira->codegen->builtin_types.entry_bool; | 863 | return ira->old_irb.codegen->builtin_types.entry_bool; |
| 905 | } | 864 | } |
| 906 | | 865 | |
| 907 | static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) { | 866 | static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) { |
| ... | @@ -917,7 +876,7 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp | ... | @@ -917,7 +876,7 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp |
| 917 | AstNode *source_node = bin_op_instruction->base.source_node; | 876 | AstNode *source_node = bin_op_instruction->base.source_node; |
| 918 | switch (resolved_type->id) { | 877 | switch (resolved_type->id) { |
| 919 | case TypeTableEntryIdInvalid: | 878 | case TypeTableEntryIdInvalid: |
| 920 | return ira->codegen->builtin_types.entry_invalid; | 879 | return ira->old_irb.codegen->builtin_types.entry_invalid; |
| 921 | | 880 | |
| 922 | case TypeTableEntryIdNumLitFloat: | 881 | case TypeTableEntryIdNumLitFloat: |
| 923 | case TypeTableEntryIdNumLitInt: | 882 | case TypeTableEntryIdNumLitInt: |
| ... | @@ -936,17 +895,17 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp | ... | @@ -936,17 +895,17 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp |
| 936 | case TypeTableEntryIdBlock: | 895 | case TypeTableEntryIdBlock: |
| 937 | case TypeTableEntryIdGenericFn: | 896 | case TypeTableEntryIdGenericFn: |
| 938 | if (!is_equality_cmp) { | 897 | if (!is_equality_cmp) { |
| 939 | add_node_error(ira->codegen, source_node, | 898 | add_node_error(ira->old_irb.codegen, source_node, |
| 940 | buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name))); | 899 | buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name))); |
| 941 | return ira->codegen->builtin_types.entry_invalid; | 900 | return ira->old_irb.codegen->builtin_types.entry_invalid; |
| 942 | } | 901 | } |
| 943 | break; | 902 | break; |
| 944 | | 903 | |
| 945 | case TypeTableEntryIdEnum: | 904 | case TypeTableEntryIdEnum: |
| 946 | if (!is_equality_cmp || resolved_type->data.enumeration.gen_field_count != 0) { | 905 | if (!is_equality_cmp || resolved_type->data.enumeration.gen_field_count != 0) { |
| 947 | add_node_error(ira->codegen, source_node, | 906 | add_node_error(ira->old_irb.codegen, source_node, |
| 948 | buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name))); | 907 | buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name))); |
| 949 | return ira->codegen->builtin_types.entry_invalid; | 908 | return ira->old_irb.codegen->builtin_types.entry_invalid; |
| 950 | } | 909 | } |
| 951 | break; | 910 | break; |
| 952 | | 911 | |
| ... | @@ -958,15 +917,18 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp | ... | @@ -958,15 +917,18 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp |
| 958 | case TypeTableEntryIdMaybe: | 917 | case TypeTableEntryIdMaybe: |
| 959 | case TypeTableEntryIdErrorUnion: | 918 | case TypeTableEntryIdErrorUnion: |
| 960 | case TypeTableEntryIdUnion: | 919 | case TypeTableEntryIdUnion: |
| 961 | add_node_error(ira->codegen, source_node, | 920 | add_node_error(ira->old_irb.codegen, source_node, |
| 962 | buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name))); | 921 | buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name))); |
| 963 | return ira->codegen->builtin_types.entry_invalid; | 922 | return ira->old_irb.codegen->builtin_types.entry_invalid; |
| 964 | | 923 | |
| 965 | case TypeTableEntryIdVar: | 924 | case TypeTableEntryIdVar: |
| 966 | zig_unreachable(); | 925 | zig_unreachable(); |
| 967 | } | 926 | } |
| 968 | | 927 | |
| 969 | return ira->codegen->builtin_types.entry_bool; | 928 | ir_link_new(ir_build_bin_op(&ira->new_irb, bin_op_instruction->base.source_node, |
| | 929 | op_id, op1->other, op2->other), &bin_op_instruction->base); |
| | 930 | |
| | 931 | return ira->old_irb.codegen->builtin_types.entry_bool; |
| 970 | } | 932 | } |
| 971 | | 933 | |
| 972 | static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) { | 934 | static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) { |
| ... | @@ -993,12 +955,15 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp | ... | @@ -993,12 +955,15 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp |
| 993 | // float | 955 | // float |
| 994 | } else { | 956 | } else { |
| 995 | AstNode *source_node = bin_op_instruction->base.source_node; | 957 | AstNode *source_node = bin_op_instruction->base.source_node; |
| 996 | add_node_error(ira->codegen, source_node, buf_sprintf("invalid operands to binary expression: '%s' and '%s'", | 958 | add_node_error(ira->old_irb.codegen, source_node, buf_sprintf("invalid operands to binary expression: '%s' and '%s'", |
| 997 | buf_ptr(&op1->type_entry->name), | 959 | buf_ptr(&op1->type_entry->name), |
| 998 | buf_ptr(&op2->type_entry->name))); | 960 | buf_ptr(&op2->type_entry->name))); |
| 999 | return ira->codegen->builtin_types.entry_invalid; | 961 | return ira->old_irb.codegen->builtin_types.entry_invalid; |
| 1000 | } | 962 | } |
| 1001 | | 963 | |
| | 964 | ir_link_new(ir_build_bin_op(&ira->new_irb, bin_op_instruction->base.source_node, |
| | 965 | op_id, op1->other, op2->other), &bin_op_instruction->base); |
| | 966 | |
| 1002 | return resolved_type; | 967 | return resolved_type; |
| 1003 | } | 968 | } |
| 1004 | | 969 | |
| ... | @@ -1041,6 +1006,8 @@ static TypeTableEntry *ir_analyze_instruction_bin_op(IrAnalyze *ira, IrInstructi | ... | @@ -1041,6 +1006,8 @@ static TypeTableEntry *ir_analyze_instruction_bin_op(IrAnalyze *ira, IrInstructi |
| 1041 | } | 1006 | } |
| 1042 | | 1007 | |
| 1043 | static TypeTableEntry *ir_analyze_instruction_load_var(IrAnalyze *ira, IrInstructionLoadVar *load_var_instruction) { | 1008 | static TypeTableEntry *ir_analyze_instruction_load_var(IrAnalyze *ira, IrInstructionLoadVar *load_var_instruction) { |
| | 1009 | ir_link_new(ir_build_load_var(&ira->new_irb, load_var_instruction->base.source_node, |
| | 1010 | load_var_instruction->var), &load_var_instruction->base); |
| 1044 | return load_var_instruction->var->type; | 1011 | return load_var_instruction->var->type; |
| 1045 | } | 1012 | } |
| 1046 | | 1013 | |
| ... | @@ -1073,35 +1040,52 @@ static TypeTableEntry *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *ins | ... | @@ -1073,35 +1040,52 @@ static TypeTableEntry *ir_analyze_instruction(IrAnalyze *ira, IrInstruction *ins |
| 1073 | { | 1040 | { |
| 1074 | TypeTableEntry *instruction_type = ir_analyze_instruction_nocast(ira, instruction); | 1041 | TypeTableEntry *instruction_type = ir_analyze_instruction_nocast(ira, instruction); |
| 1075 | instruction->type_entry = instruction_type; | 1042 | instruction->type_entry = instruction_type; |
| | 1043 | if (instruction->other) |
| | 1044 | instruction->other->type_entry = instruction_type; |
| 1076 | | 1045 | |
| 1077 | IrInstruction *casted_instruction = ir_get_casted_value(ira, instruction, expected_type, | 1046 | IrInstruction *casted_instruction = ir_get_casted_value(ira, instruction, expected_type); |
| 1078 | nullptr, instruction); | | |
| 1079 | return casted_instruction->type_entry; | 1047 | return casted_instruction->type_entry; |
| 1080 | } | 1048 | } |
| 1081 | | 1049 | |
| 1082 | TypeTableEntry *ir_analyze(CodeGen *codegen, IrExecutable *executable, TypeTableEntry *expected_type) { | 1050 | // This function attempts to evaluate IR code while doing type checking and other analysis. |
| | 1051 | // It emits a new IrExecutable which is partially evaluated IR code. |
| | 1052 | TypeTableEntry *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_exec, |
| | 1053 | TypeTableEntry *expected_type) |
| | 1054 | { |
| 1083 | IrAnalyze ir_analyze_data = {}; | 1055 | IrAnalyze ir_analyze_data = {}; |
| 1084 | IrAnalyze *ira = &ir_analyze_data; | 1056 | IrAnalyze *ira = &ir_analyze_data; |
| 1085 | ira->codegen = codegen; | 1057 | ira->codegen = codegen; |
| 1086 | ira->exec = executable; | 1058 | |
| | 1059 | ira->old_irb.codegen = codegen; |
| | 1060 | ira->old_irb.exec = old_exec; |
| | 1061 | |
| | 1062 | ira->new_irb.codegen = codegen; |
| | 1063 | ira->new_irb.exec = new_exec; |
| | 1064 | |
| | 1065 | ira->exec_context.var_slot_count = ira->old_irb.exec->var_slot_count; |
| | 1066 | ira->exec_context.var_slot_list = allocate<IrVarSlot>(ira->exec_context.var_slot_count); |
| 1087 | | 1067 | |
| 1088 | TypeTableEntry *return_type = ira->codegen->builtin_types.entry_void; | 1068 | TypeTableEntry *return_type = ira->codegen->builtin_types.entry_void; |
| 1089 | | 1069 | |
| 1090 | for (size_t i = 0; i < executable->basic_block_count; i += 1) { | 1070 | ira->new_irb.current_basic_block = allocate<IrBasicBlock>(1); |
| 1091 | ira->current_basic_block = executable->basic_block_list[i]; | 1071 | ira->new_irb.exec->basic_block_list.append(ira->new_irb.current_basic_block); |
| 1092 | | 1072 | |
| 1093 | for (IrInstruction *instruction = ira->current_basic_block->first; instruction != nullptr; | 1073 | ira->old_irb.current_basic_block = ira->old_irb.exec->basic_block_list.at(0); |
| 1094 | instruction = instruction->next) | 1074 | |
| 1095 | { | 1075 | ira->new_irb.current_basic_block->other = ira->old_irb.current_basic_block; |
| 1096 | if (return_type->id == TypeTableEntryIdUnreachable) { | 1076 | ira->old_irb.current_basic_block->other = ira->new_irb.current_basic_block; |
| 1097 | add_node_error(ira->codegen, first_executing_node(instruction->source_node), | 1077 | |
| 1098 | buf_sprintf("unreachable code")); | 1078 | |
| 1099 | break; | 1079 | for (size_t i = 0; i < ira->old_irb.current_basic_block->instruction_list.length; i += 1) { |
| 1100 | } | 1080 | IrInstruction *instruction = ira->old_irb.current_basic_block->instruction_list.at(i); |
| 1101 | bool is_last = (instruction == ira->current_basic_block->last); | 1081 | if (return_type->id == TypeTableEntryIdUnreachable) { |
| 1102 | TypeTableEntry *passed_expected_type = is_last ? expected_type : nullptr; | 1082 | add_node_error(ira->codegen, first_executing_node(instruction->source_node), |
| 1103 | return_type = ir_analyze_instruction(ira, instruction, passed_expected_type); | 1083 | buf_sprintf("unreachable code")); |
| | 1084 | break; |
| 1104 | } | 1085 | } |
| | 1086 | bool is_last = (i == ira->old_irb.current_basic_block->instruction_list.length - 1); |
| | 1087 | TypeTableEntry *passed_expected_type = is_last ? expected_type : nullptr; |
| | 1088 | return_type = ir_analyze_instruction(ira, instruction, passed_expected_type); |
| 1105 | } | 1089 | } |
| 1106 | | 1090 | |
| 1107 | return return_type; | 1091 | return return_type; |