| ... | ... | @@ -2,57 +2,35 @@ |
| 2 | 2 | #include "ir.hpp" |
| 3 | 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 | 16 | CodeGen *codegen; |
| 7 | | AstNode *node; |
| 8 | | IrBasicBlock *current_basic_block; |
| 9 | 17 | IrExecutable *exec; |
| 18 | IrBasicBlock *current_basic_block; |
| 10 | 19 | }; |
| 11 | 20 | |
| 12 | 21 | struct IrAnalyze { |
| 13 | 22 | CodeGen *codegen; |
| 14 | | IrExecutable *exec; |
| 15 | | IrBasicBlock *current_basic_block; |
| 23 | IrBuilder old_irb; |
| 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 | 30 | static void ir_instruction_append(IrBasicBlock *basic_block, IrInstruction *instruction) { |
| 21 | | if (!basic_block->last) { |
| 22 | | basic_block->first = instruction; |
| 23 | | basic_block->last = 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 | | } |
| 31 | assert(basic_block); |
| 32 | assert(instruction); |
| 33 | basic_block->instruction_list.append(instruction); |
| 56 | 34 | } |
| 57 | 35 | |
| 58 | 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 | 93 | } |
| 116 | 94 | |
| 117 | 95 | template<typename T> |
| 118 | | static T *ir_build_instruction(IrGen *irg, AstNode *source_node) { |
| 119 | | T *special_instruction = ir_create_instruction<T>(irg->exec, source_node); |
| 120 | | ir_instruction_append(irg->current_basic_block, &special_instruction->base); |
| 96 | static T *ir_build_instruction(IrBuilder *irb, AstNode *source_node) { |
| 97 | T *special_instruction = ir_create_instruction<T>(irb->exec, source_node); |
| 98 | ir_instruction_append(irb->current_basic_block, &special_instruction->base); |
| 121 | 99 | return special_instruction; |
| 122 | 100 | } |
| 123 | 101 | |
| 124 | | static IrInstruction *ir_insert_const_type(IrAnalyze *ira, IrInstruction *before_instruction, |
| 125 | | IrInstruction *after_instruction, TypeTableEntry *type_entry) |
| 102 | static IrInstruction *ir_build_cast(IrBuilder *irb, AstNode *source_node, IrInstruction *dest_type, |
| 103 | IrInstruction *value, bool is_implicit) |
| 126 | 104 | { |
| 127 | | IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(ira->exec, |
| 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); |
| 105 | IrInstructionCast *cast_instruction = ir_build_instruction<IrInstructionCast>(irb, source_node); |
| 142 | 106 | cast_instruction->dest_type = dest_type; |
| 143 | 107 | cast_instruction->value = value; |
| 144 | 108 | cast_instruction->is_implicit = is_implicit; |
| 145 | | ir_instruction_insert(ira->current_basic_block, before_instruction, after_instruction, &cast_instruction->base); |
| 146 | 109 | return &cast_instruction->base; |
| 147 | 110 | } |
| 148 | 111 | |
| 149 | | static IrInstruction *ir_build_return(IrGen *irg, AstNode *source_node, IrInstruction *return_value) { |
| 150 | | IrInstructionReturn *return_instruction = ir_build_instruction<IrInstructionReturn>(irg, source_node); |
| 151 | | return_instruction->base.type_entry = irg->codegen->builtin_types.entry_unreachable; |
| 112 | static IrInstruction *ir_build_return(IrBuilder *irb, AstNode *source_node, IrInstruction *return_value) { |
| 113 | IrInstructionReturn *return_instruction = ir_build_instruction<IrInstructionReturn>(irb, source_node); |
| 114 | return_instruction->base.type_entry = irb->codegen->builtin_types.entry_unreachable; |
| 152 | 115 | return_instruction->base.static_value.ok = true; |
| 153 | 116 | return_instruction->value = return_value; |
| 154 | 117 | return &return_instruction->base; |
| 155 | 118 | } |
| 156 | 119 | |
| 157 | | static IrInstruction *ir_build_const_void(IrGen *irg, AstNode *source_node) { |
| 158 | | IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irg, source_node); |
| 159 | | const_instruction->base.type_entry = irg->codegen->builtin_types.entry_void; |
| 120 | static IrInstruction *ir_build_const_void(IrBuilder *irb, AstNode *source_node) { |
| 121 | IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node); |
| 122 | const_instruction->base.type_entry = irb->codegen->builtin_types.entry_void; |
| 160 | 123 | const_instruction->base.static_value.ok = true; |
| 161 | 124 | return &const_instruction->base; |
| 162 | 125 | } |
| 163 | 126 | |
| 164 | | static IrInstruction *ir_build_const_bignum(IrGen *irg, AstNode *source_node, BigNum *bignum) { |
| 165 | | IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irg, source_node); |
| 127 | static IrInstruction *ir_build_const_bignum(IrBuilder *irb, AstNode *source_node, BigNum *bignum) { |
| 128 | IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node); |
| 166 | 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 | 131 | const_instruction->base.static_value.ok = true; |
| 169 | 132 | const_instruction->base.static_value.data.x_bignum = *bignum; |
| 170 | 133 | return &const_instruction->base; |
| 171 | 134 | } |
| 172 | 135 | |
| 173 | | static IrInstruction *ir_build_const_type(IrGen *irg, AstNode *source_node, TypeTableEntry *type_entry) { |
| 174 | | IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irg, source_node); |
| 175 | | const_instruction->base.type_entry = irg->codegen->builtin_types.entry_type; |
| 136 | static IrInstruction *ir_build_const_type(IrBuilder *irb, AstNode *source_node, TypeTableEntry *type_entry) { |
| 137 | IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node); |
| 138 | const_instruction->base.type_entry = irb->codegen->builtin_types.entry_type; |
| 176 | 139 | const_instruction->base.static_value.ok = true; |
| 177 | 140 | const_instruction->base.static_value.data.x_type = type_entry; |
| 178 | 141 | return &const_instruction->base; |
| 179 | 142 | } |
| 180 | 143 | |
| 181 | | static IrInstruction *ir_build_const_fn(IrGen *irg, AstNode *source_node, FnTableEntry *fn_entry) { |
| 182 | | IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irg, source_node); |
| 144 | static IrInstruction *ir_build_const_fn(IrBuilder *irb, AstNode *source_node, FnTableEntry *fn_entry) { |
| 145 | IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node); |
| 183 | 146 | const_instruction->base.type_entry = fn_entry->type_entry; |
| 184 | 147 | const_instruction->base.static_value.ok = true; |
| 185 | 148 | const_instruction->base.static_value.data.x_fn = fn_entry; |
| 186 | 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) { |
| 190 | | IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irg, source_node); |
| 152 | static IrInstruction *ir_build_const_generic_fn(IrBuilder *irb, AstNode *source_node, TypeTableEntry *fn_type) { |
| 153 | IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node); |
| 191 | 154 | const_instruction->base.type_entry = fn_type; |
| 192 | 155 | const_instruction->base.static_value.ok = true; |
| 193 | 156 | const_instruction->base.static_value.data.x_type = fn_type; |
| 194 | 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 | 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 | 164 | bin_op_instruction->op_id = op_id; |
| 202 | 165 | bin_op_instruction->op1 = op1; |
| 203 | 166 | bin_op_instruction->op2 = op2; |
| 204 | 167 | return &bin_op_instruction->base; |
| 205 | 168 | } |
| 206 | 169 | |
| 207 | | static IrInstruction *ir_build_load_var(IrGen *irg, AstNode *source_node, VariableTableEntry *var) { |
| 208 | | IrInstructionLoadVar *load_var_instruction = ir_build_instruction<IrInstructionLoadVar>(irg, source_node); |
| 170 | static IrInstruction *ir_build_load_var(IrBuilder *irb, AstNode *source_node, VariableTableEntry *var) { |
| 171 | IrInstructionLoadVar *load_var_instruction = ir_build_instruction<IrInstructionLoadVar>(irb, source_node); |
| 209 | 172 | load_var_instruction->base.type_entry = var->type; |
| 210 | 173 | load_var_instruction->var = var; |
| 211 | 174 | return &load_var_instruction->base; |
| ... | ... | @@ -226,7 +189,7 @@ static IrInstruction *ir_build_load_var(IrGen *irg, AstNode *source_node, Variab |
| 226 | 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 | 193 | bool gen_error_defers, bool gen_maybe_defers) |
| 231 | 194 | { |
| 232 | 195 | while (inner_block != outer_block) { |
| ... | ... | @@ -236,15 +199,15 @@ static void ir_gen_defers_for_block(IrGen *irg, BlockContext *inner_block, Block |
| 236 | 199 | (gen_maybe_defers && inner_block->node->data.defer.kind == ReturnKindMaybe))) |
| 237 | 200 | { |
| 238 | 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 | 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 | 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 | 211 | // if (rk == ReturnKnowledgeUnknown) { |
| 249 | 212 | // if (get_conditional_defer_count(defer_inner_block, defer_outer_block) > 0) { |
| 250 | 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 | 215 | // zig_panic("TODO"); |
| 253 | 216 | // } |
| 254 | 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 | 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 | 226 | assert(block_node->type == NodeTypeBlock); |
| 264 | 227 | |
| 265 | 228 | BlockContext *parent_context = block_node->block_context; |
| ... | ... | @@ -269,8 +232,8 @@ static IrInstruction *ir_gen_block(IrGen *irg, AstNode *block_node) { |
| 269 | 232 | IrInstruction *return_value = nullptr; |
| 270 | 233 | for (size_t i = 0; i < block_node->data.block.statements.length; i += 1) { |
| 271 | 234 | AstNode *statement_node = block_node->data.block.statements.at(i); |
| 272 | | return_value = ir_gen_node(irg, statement_node, child_context); |
| 273 | | if (statement_node->type == NodeTypeDefer && return_value != irg->codegen->invalid_instruction) { |
| 235 | return_value = ir_gen_node(irb, statement_node, child_context); |
| 236 | if (statement_node->type == NodeTypeDefer && return_value != irb->codegen->invalid_instruction) { |
| 274 | 237 | // defer starts a new block context |
| 275 | 238 | child_context = statement_node->data.defer.child_block; |
| 276 | 239 | assert(child_context); |
| ... | ... | @@ -278,20 +241,20 @@ static IrInstruction *ir_gen_block(IrGen *irg, AstNode *block_node) { |
| 278 | 241 | } |
| 279 | 242 | |
| 280 | 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 | 248 | return return_value; |
| 286 | 249 | } |
| 287 | 250 | |
| 288 | | static IrInstruction *ir_gen_bin_op_id(IrGen *irg, AstNode *node, IrBinOp op_id) { |
| 289 | | IrInstruction *op1 = ir_gen_node(irg, 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); |
| 291 | | return ir_build_bin_op(irg, node, op_id, op1, op2); |
| 251 | static IrInstruction *ir_gen_bin_op_id(IrBuilder *irb, AstNode *node, IrBinOp op_id) { |
| 252 | IrInstruction *op1 = ir_gen_node(irb, node->data.bin_op_expr.op1, node->block_context); |
| 253 | IrInstruction *op2 = ir_gen_node(irb, node->data.bin_op_expr.op2, node->block_context); |
| 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 | 258 | assert(node->type == NodeTypeBinOpExpr); |
| 296 | 259 | |
| 297 | 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 | 285 | // because of the control flow |
| 323 | 286 | zig_panic("TODO gen IR for bool or/and"); |
| 324 | 287 | case BinOpTypeCmpEq: |
| 325 | | return ir_gen_bin_op_id(irg, node, IrBinOpCmpEq); |
| 288 | return ir_gen_bin_op_id(irb, node, IrBinOpCmpEq); |
| 326 | 289 | case BinOpTypeCmpNotEq: |
| 327 | | return ir_gen_bin_op_id(irg, node, IrBinOpCmpNotEq); |
| 290 | return ir_gen_bin_op_id(irb, node, IrBinOpCmpNotEq); |
| 328 | 291 | case BinOpTypeCmpLessThan: |
| 329 | | return ir_gen_bin_op_id(irg, node, IrBinOpCmpLessThan); |
| 292 | return ir_gen_bin_op_id(irb, node, IrBinOpCmpLessThan); |
| 330 | 293 | case BinOpTypeCmpGreaterThan: |
| 331 | | return ir_gen_bin_op_id(irg, node, IrBinOpCmpGreaterThan); |
| 294 | return ir_gen_bin_op_id(irb, node, IrBinOpCmpGreaterThan); |
| 332 | 295 | case BinOpTypeCmpLessOrEq: |
| 333 | | return ir_gen_bin_op_id(irg, node, IrBinOpCmpLessOrEq); |
| 296 | return ir_gen_bin_op_id(irb, node, IrBinOpCmpLessOrEq); |
| 334 | 297 | case BinOpTypeCmpGreaterOrEq: |
| 335 | | return ir_gen_bin_op_id(irg, node, IrBinOpCmpGreaterOrEq); |
| 298 | return ir_gen_bin_op_id(irb, node, IrBinOpCmpGreaterOrEq); |
| 336 | 299 | case BinOpTypeBinOr: |
| 337 | | return ir_gen_bin_op_id(irg, node, IrBinOpBinOr); |
| 300 | return ir_gen_bin_op_id(irb, node, IrBinOpBinOr); |
| 338 | 301 | case BinOpTypeBinXor: |
| 339 | | return ir_gen_bin_op_id(irg, node, IrBinOpBinXor); |
| 302 | return ir_gen_bin_op_id(irb, node, IrBinOpBinXor); |
| 340 | 303 | case BinOpTypeBinAnd: |
| 341 | | return ir_gen_bin_op_id(irg, node, IrBinOpBinAnd); |
| 304 | return ir_gen_bin_op_id(irb, node, IrBinOpBinAnd); |
| 342 | 305 | case BinOpTypeBitShiftLeft: |
| 343 | | return ir_gen_bin_op_id(irg, node, IrBinOpBitShiftLeft); |
| 306 | return ir_gen_bin_op_id(irb, node, IrBinOpBitShiftLeft); |
| 344 | 307 | case BinOpTypeBitShiftLeftWrap: |
| 345 | | return ir_gen_bin_op_id(irg, node, IrBinOpBitShiftLeftWrap); |
| 308 | return ir_gen_bin_op_id(irb, node, IrBinOpBitShiftLeftWrap); |
| 346 | 309 | case BinOpTypeBitShiftRight: |
| 347 | | return ir_gen_bin_op_id(irg, node, IrBinOpBitShiftRight); |
| 310 | return ir_gen_bin_op_id(irb, node, IrBinOpBitShiftRight); |
| 348 | 311 | case BinOpTypeAdd: |
| 349 | | return ir_gen_bin_op_id(irg, node, IrBinOpAdd); |
| 312 | return ir_gen_bin_op_id(irb, node, IrBinOpAdd); |
| 350 | 313 | case BinOpTypeAddWrap: |
| 351 | | return ir_gen_bin_op_id(irg, node, IrBinOpAddWrap); |
| 314 | return ir_gen_bin_op_id(irb, node, IrBinOpAddWrap); |
| 352 | 315 | case BinOpTypeSub: |
| 353 | | return ir_gen_bin_op_id(irg, node, IrBinOpSub); |
| 316 | return ir_gen_bin_op_id(irb, node, IrBinOpSub); |
| 354 | 317 | case BinOpTypeSubWrap: |
| 355 | | return ir_gen_bin_op_id(irg, node, IrBinOpSubWrap); |
| 318 | return ir_gen_bin_op_id(irb, node, IrBinOpSubWrap); |
| 356 | 319 | case BinOpTypeMult: |
| 357 | | return ir_gen_bin_op_id(irg, node, IrBinOpMult); |
| 320 | return ir_gen_bin_op_id(irb, node, IrBinOpMult); |
| 358 | 321 | case BinOpTypeMultWrap: |
| 359 | | return ir_gen_bin_op_id(irg, node, IrBinOpMultWrap); |
| 322 | return ir_gen_bin_op_id(irb, node, IrBinOpMultWrap); |
| 360 | 323 | case BinOpTypeDiv: |
| 361 | | return ir_gen_bin_op_id(irg, node, IrBinOpDiv); |
| 324 | return ir_gen_bin_op_id(irb, node, IrBinOpDiv); |
| 362 | 325 | case BinOpTypeMod: |
| 363 | | return ir_gen_bin_op_id(irg, node, IrBinOpMod); |
| 326 | return ir_gen_bin_op_id(irb, node, IrBinOpMod); |
| 364 | 327 | case BinOpTypeArrayCat: |
| 365 | | return ir_gen_bin_op_id(irg, node, IrBinOpArrayCat); |
| 328 | return ir_gen_bin_op_id(irb, node, IrBinOpArrayCat); |
| 366 | 329 | case BinOpTypeArrayMult: |
| 367 | | return ir_gen_bin_op_id(irg, node, IrBinOpArrayMult); |
| 330 | return ir_gen_bin_op_id(irb, node, IrBinOpArrayMult); |
| 368 | 331 | case BinOpTypeUnwrapMaybe: |
| 369 | 332 | zig_panic("TODO gen IR for unwrap maybe"); |
| 370 | 333 | } |
| 371 | 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 | 338 | assert(node->type == NodeTypeNumberLiteral); |
| 376 | 339 | |
| 377 | 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")); |
| 379 | | return irg->codegen->invalid_instruction; |
| 341 | add_node_error(irb->codegen, node, buf_sprintf("number literal too large to be represented in any type")); |
| 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 | 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 | 352 | TopLevelDecl *tld = get_as_top_level_decl(decl_node); |
| 390 | 353 | if (tld->resolution == TldResolutionInvalid) |
| 391 | | return irg->codegen->invalid_instruction; |
| 354 | return irb->codegen->invalid_instruction; |
| 392 | 355 | |
| 393 | 356 | if (decl_node->type == NodeTypeVariableDeclaration) { |
| 394 | 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 | 359 | } else if (decl_node->type == NodeTypeFnProto) { |
| 397 | 360 | FnTableEntry *fn_entry = decl_node->data.fn_proto.fn_table_entry; |
| 398 | 361 | assert(fn_entry->type_entry); |
| 399 | 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 | 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 | 367 | } else if (decl_node->type == NodeTypeContainerDecl) { |
| 405 | 368 | if (decl_node->data.struct_decl.generic_params.length > 0) { |
| 406 | 369 | TypeTableEntry *type_entry = decl_node->data.struct_decl.generic_fn_type; |
| 407 | 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 | 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 | 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 | 377 | } else { |
| 415 | 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 | 383 | assert(node->type == NodeTypeSymbol); |
| 421 | 384 | |
| 422 | 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 | 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 | 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 | 395 | if (var) |
| 433 | | return ir_build_load_var(irg, node, var); |
| 396 | return ir_build_load_var(irb, node, var); |
| 434 | 397 | |
| 435 | 398 | AstNode *decl_node = find_decl(node->block_context, variable_name); |
| 436 | 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 | 402 | if (node->owner->any_imports_failed) { |
| 440 | 403 | // skip the error message since we had a failing import in this file |
| 441 | 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))); |
| 446 | | return irg->codegen->invalid_instruction; |
| 408 | add_node_error(irb->codegen, node, buf_sprintf("use of undeclared identifier '%s'", buf_ptr(variable_name))); |
| 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 | 413 | bool pointer_only) |
| 451 | 414 | { |
| 452 | 415 | node->block_context = block_context; |
| 453 | 416 | |
| 454 | 417 | switch (node->type) { |
| 455 | 418 | case NodeTypeBlock: |
| 456 | | return ir_gen_block(irg, node); |
| 419 | return ir_gen_block(irb, node); |
| 457 | 420 | case NodeTypeBinOpExpr: |
| 458 | | return ir_gen_bin_op(irg, node); |
| 421 | return ir_gen_bin_op(irb, node); |
| 459 | 422 | case NodeTypeNumberLiteral: |
| 460 | | return ir_gen_num_lit(irg, node); |
| 423 | return ir_gen_num_lit(irb, node); |
| 461 | 424 | case NodeTypeSymbol: |
| 462 | | return ir_gen_symbol(irg, node, pointer_only); |
| 425 | return ir_gen_symbol(irb, node, pointer_only); |
| 463 | 426 | case NodeTypeUnwrapErrorExpr: |
| 464 | 427 | case NodeTypeReturnExpr: |
| 465 | 428 | case NodeTypeDefer: |
| ... | ... | @@ -509,9 +472,9 @@ static IrInstruction *ir_gen_node_extra(IrGen *irg, AstNode *node, BlockContext |
| 509 | 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 | 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 | 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 | 482 | { |
| 520 | 483 | assert(node->owner); |
| 521 | 484 | |
| 522 | | IrGen ir_gen = {0}; |
| 523 | | IrGen *irg = &ir_gen; |
| 485 | IrBuilder ir_gen = {0}; |
| 486 | IrBuilder *irb = &ir_gen; |
| 524 | 487 | |
| 525 | | irg->codegen = g; |
| 526 | | irg->node = node; |
| 527 | | irg->exec = ir_executable; |
| 488 | irb->codegen = g; |
| 489 | irb->exec = ir_executable; |
| 528 | 490 | |
| 529 | | irg->exec->basic_block_list = allocate<IrBasicBlock*>(1); |
| 530 | | irg->exec->basic_block_count = 1; |
| 491 | irb->current_basic_block = allocate<IrBasicBlock>(1); |
| 492 | irb->exec->basic_block_list.append(irb->current_basic_block); |
| 531 | 493 | |
| 532 | | IrBasicBlock *entry_basic_block = allocate<IrBasicBlock>(1); |
| 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); |
| 494 | IrInstruction *result = ir_gen_node_extra(irb, node, scope, pointer_only); |
| 537 | 495 | assert(result); |
| 538 | 496 | |
| 539 | 497 | if (result == g->invalid_instruction) |
| 540 | 498 | return result; |
| 541 | 499 | |
| 542 | 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 | 503 | return result; |
| 546 | 504 | } |
| ... | ... | @@ -566,6 +524,11 @@ IrInstruction *ir_gen_fn(CodeGen *codegn, FnTableEntry *fn_entry) { |
| 566 | 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 | 533 | static void analyze_goto_pass2(CodeGen *g, ImportTableEntry *import, AstNode *node) { |
| 571 | 534 | assert(node->type == NodeTypeGoto); |
| ... | ... | @@ -640,7 +603,7 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstruction *instruc |
| 640 | 603 | |
| 641 | 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 | 607 | buf_sprintf("%s value %s cannot be implicitly casted to type '%s'", |
| 645 | 608 | num_lit_str, |
| 646 | 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 | 617 | assert(instruction_count >= 1); |
| 655 | 618 | IrInstruction *prev_inst = instructions[0]; |
| 656 | 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 | 622 | for (size_t i = 1; i < instruction_count; i += 1) { |
| 660 | 623 | IrInstruction *cur_inst = instructions[i]; |
| ... | ... | @@ -701,7 +664,7 @@ static TypeTableEntry *ir_determine_peer_types(IrAnalyze *ira, IrInstruction *pa |
| 701 | 664 | prev_inst = cur_inst; |
| 702 | 665 | continue; |
| 703 | 666 | } else { |
| 704 | | return ira->codegen->builtin_types.entry_invalid; |
| 667 | return ira->old_irb.codegen->builtin_types.entry_invalid; |
| 705 | 668 | } |
| 706 | 669 | } else if (cur_type->id == TypeTableEntryIdNumLitInt || |
| 707 | 670 | cur_type->id == TypeTableEntryIdNumLitFloat) |
| ... | ... | @@ -709,14 +672,14 @@ static TypeTableEntry *ir_determine_peer_types(IrAnalyze *ira, IrInstruction *pa |
| 709 | 672 | if (ir_num_lit_fits_in_other_type(ira, cur_inst, prev_type)) { |
| 710 | 673 | continue; |
| 711 | 674 | } else { |
| 712 | | return ira->codegen->builtin_types.entry_invalid; |
| 675 | return ira->old_irb.codegen->builtin_types.entry_invalid; |
| 713 | 676 | } |
| 714 | 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 | 679 | buf_sprintf("incompatible types: '%s' and '%s'", |
| 717 | 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 | 685 | return prev_inst->type_entry; |
| ... | ... | @@ -819,14 +782,9 @@ static TypeTableEntry *ir_resolve_peer_types(IrAnalyze *ira, IrInstruction *pare |
| 819 | 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, |
| 823 | | TypeTableEntry *expected_type, |
| 824 | | IrInstruction *before_instruction, IrInstruction *after_instruction) |
| 825 | | { |
| 785 | static IrInstruction *ir_get_casted_value(IrAnalyze *ira, IrInstruction *value, TypeTableEntry *expected_type) { |
| 826 | 786 | assert(value); |
| 827 | | assert(before_instruction || after_instruction); |
| 828 | | assert(!before_instruction || !after_instruction); |
| 829 | | assert(value != ira->codegen->invalid_instruction); |
| 787 | assert(value != ira->old_irb.codegen->invalid_instruction); |
| 830 | 788 | assert(!expected_type || expected_type->id != TypeTableEntryIdInvalid); |
| 831 | 789 | assert(value->type_entry); |
| 832 | 790 | assert(value->type_entry->id != TypeTableEntryIdInvalid); |
| ... | ... | @@ -840,23 +798,22 @@ static IrInstruction *ir_get_casted_value(IrAnalyze *ira, IrInstruction *value, |
| 840 | 798 | ImplicitCastMatchResult result = ir_types_match_with_implicit_cast(ira, expected_type, value->type_entry, value); |
| 841 | 799 | switch (result) { |
| 842 | 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 | 802 | buf_sprintf("expected type '%s', got '%s'", |
| 845 | 803 | buf_ptr(&expected_type->name), |
| 846 | 804 | buf_ptr(&value->type_entry->name))); |
| 847 | | return ira->codegen->invalid_instruction; |
| 805 | return ira->old_irb.codegen->invalid_instruction; |
| 848 | 806 | |
| 849 | 807 | case ImplicitCastMatchResultYes: |
| 850 | 808 | { |
| 851 | | IrInstruction *dest_type = ir_insert_const_type(ira, before_instruction, |
| 852 | | after_instruction, expected_type); |
| 809 | IrInstruction *dest_type = ir_build_const_type(&ira->new_irb, value->source_node, expected_type); |
| 853 | 810 | bool is_implicit = true; |
| 854 | | IrInstruction *cast_instruction = ir_insert_cast(ira, nullptr, dest_type, |
| 855 | | dest_type, value, is_implicit); |
| 811 | IrInstruction *cast_instruction = ir_build_cast(&ira->new_irb, value->source_node, dest_type, |
| 812 | value, is_implicit); |
| 856 | 813 | return cast_instruction; |
| 857 | 814 | } |
| 858 | 815 | case ImplicitCastMatchResultReportedError: |
| 859 | | return ira->codegen->invalid_instruction; |
| 816 | return ira->old_irb.codegen->invalid_instruction; |
| 860 | 817 | } |
| 861 | 818 | |
| 862 | 819 | zig_unreachable(); |
| ... | ... | @@ -871,19 +828,20 @@ static TypeTableEntry *ir_analyze_instruction_return(IrAnalyze *ira, IrInstructi |
| 871 | 828 | } |
| 872 | 829 | |
| 873 | 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, |
| 879 | | return_instruction->value, expected_return_type, &return_instruction->base, nullptr); |
| 880 | | if (return_instruction->value == ira->codegen->invalid_instruction) { |
| 832 | IrInstruction *value = ir_get_casted_value(ira, return_instruction->value->other, expected_return_type); |
| 833 | if (value == ira->codegen->invalid_instruction) { |
| 881 | 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 | 840 | return ira->codegen->builtin_types.entry_unreachable; |
| 884 | 841 | } |
| 885 | 842 | |
| 886 | 843 | static TypeTableEntry *ir_analyze_instruction_const(IrAnalyze *ira, IrInstructionConst *const_instruction) { |
| 844 | const_instruction->base.other = &const_instruction->base; |
| 887 | 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 | 849 | IrInstruction *op1 = bin_op_instruction->op1; |
| 892 | 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, |
| 895 | | &bin_op_instruction->base, nullptr); |
| 896 | | if (casted_op1 == ira->codegen->invalid_instruction) |
| 897 | | return ira->codegen->builtin_types.entry_invalid; |
| 852 | IrInstruction *casted_op1 = ir_get_casted_value(ira, op1->other, ira->old_irb.codegen->builtin_types.entry_bool); |
| 853 | if (casted_op1 == ira->old_irb.codegen->invalid_instruction) |
| 854 | return ira->old_irb.codegen->builtin_types.entry_invalid; |
| 898 | 855 | |
| 899 | | IrInstruction *casted_op2 = ir_get_casted_value(ira, op2, ira->codegen->builtin_types.entry_bool, |
| 900 | | &bin_op_instruction->base, nullptr); |
| 901 | | if (casted_op2 == ira->codegen->invalid_instruction) |
| 902 | | return ira->codegen->builtin_types.entry_invalid; |
| 856 | IrInstruction *casted_op2 = ir_get_casted_value(ira, op2->other, ira->old_irb.codegen->builtin_types.entry_bool); |
| 857 | if (casted_op2 == ira->old_irb.codegen->invalid_instruction) |
| 858 | return ira->old_irb.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 | 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 | 876 | AstNode *source_node = bin_op_instruction->base.source_node; |
| 918 | 877 | switch (resolved_type->id) { |
| 919 | 878 | case TypeTableEntryIdInvalid: |
| 920 | | return ira->codegen->builtin_types.entry_invalid; |
| 879 | return ira->old_irb.codegen->builtin_types.entry_invalid; |
| 921 | 880 | |
| 922 | 881 | case TypeTableEntryIdNumLitFloat: |
| 923 | 882 | case TypeTableEntryIdNumLitInt: |
| ... | ... | @@ -936,17 +895,17 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp |
| 936 | 895 | case TypeTableEntryIdBlock: |
| 937 | 896 | case TypeTableEntryIdGenericFn: |
| 938 | 897 | if (!is_equality_cmp) { |
| 939 | | add_node_error(ira->codegen, source_node, |
| 898 | add_node_error(ira->old_irb.codegen, source_node, |
| 940 | 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 | 902 | break; |
| 944 | 903 | |
| 945 | 904 | case TypeTableEntryIdEnum: |
| 946 | 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 | 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 | 910 | break; |
| 952 | 911 | |
| ... | ... | @@ -958,15 +917,18 @@ static TypeTableEntry *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp |
| 958 | 917 | case TypeTableEntryIdMaybe: |
| 959 | 918 | case TypeTableEntryIdErrorUnion: |
| 960 | 919 | case TypeTableEntryIdUnion: |
| 961 | | add_node_error(ira->codegen, source_node, |
| 920 | add_node_error(ira->old_irb.codegen, source_node, |
| 962 | 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 | 924 | case TypeTableEntryIdVar: |
| 966 | 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 | 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 | 955 | // float |
| 994 | 956 | } else { |
| 995 | 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 | 959 | buf_ptr(&op1->type_entry->name), |
| 998 | 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 | 967 | return resolved_type; |
| 1003 | 968 | } |
| 1004 | 969 | |
| ... | ... | @@ -1041,6 +1006,8 @@ static TypeTableEntry *ir_analyze_instruction_bin_op(IrAnalyze *ira, IrInstructi |
| 1041 | 1006 | } |
| 1042 | 1007 | |
| 1043 | 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 | 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 | 1040 | { |
| 1074 | 1041 | TypeTableEntry *instruction_type = ir_analyze_instruction_nocast(ira, instruction); |
| 1075 | 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, |
| 1078 | | nullptr, instruction); |
| 1046 | IrInstruction *casted_instruction = ir_get_casted_value(ira, instruction, expected_type); |
| 1079 | 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 | 1055 | IrAnalyze ir_analyze_data = {}; |
| 1084 | 1056 | IrAnalyze *ira = &ir_analyze_data; |
| 1085 | 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 | 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) { |
| 1091 | | ira->current_basic_block = executable->basic_block_list[i]; |
| 1070 | ira->new_irb.current_basic_block = allocate<IrBasicBlock>(1); |
| 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; |
| 1094 | | instruction = instruction->next) |
| 1095 | | { |
| 1096 | | if (return_type->id == TypeTableEntryIdUnreachable) { |
| 1097 | | add_node_error(ira->codegen, first_executing_node(instruction->source_node), |
| 1098 | | buf_sprintf("unreachable code")); |
| 1099 | | break; |
| 1100 | | } |
| 1101 | | bool is_last = (instruction == ira->current_basic_block->last); |
| 1102 | | TypeTableEntry *passed_expected_type = is_last ? expected_type : nullptr; |
| 1103 | | return_type = ir_analyze_instruction(ira, instruction, passed_expected_type); |
| 1073 | ira->old_irb.current_basic_block = ira->old_irb.exec->basic_block_list.at(0); |
| 1074 | |
| 1075 | ira->new_irb.current_basic_block->other = ira->old_irb.current_basic_block; |
| 1076 | ira->old_irb.current_basic_block->other = ira->new_irb.current_basic_block; |
| 1077 | |
| 1078 | |
| 1079 | for (size_t i = 0; i < ira->old_irb.current_basic_block->instruction_list.length; i += 1) { |
| 1080 | IrInstruction *instruction = ira->old_irb.current_basic_block->instruction_list.at(i); |
| 1081 | if (return_type->id == TypeTableEntryIdUnreachable) { |
| 1082 | add_node_error(ira->codegen, first_executing_node(instruction->source_node), |
| 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 | 1091 | return return_type; |