| ... | ... | @@ -2119,7 +2119,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo |
| 2119 | 2119 | child_scope = elem_var->child_scope; |
| 2120 | 2120 | |
| 2121 | 2121 | IrInstruction *undefined_value = ir_build_const_undefined(irb, child_scope, elem_node); |
| 2122 | | ir_build_var_decl(irb, child_scope, elem_node, elem_var, elem_var_type, undefined_value); |
| 2122 | ir_build_var_decl(irb, child_scope, elem_node, elem_var, elem_var_type, undefined_value); |
| 2123 | 2123 | IrInstruction *elem_var_ptr = ir_build_var_ptr(irb, child_scope, node, elem_var); |
| 2124 | 2124 | |
| 2125 | 2125 | AstNode *index_var_source_node; |
| ... | ... | @@ -2137,7 +2137,7 @@ static IrInstruction *ir_gen_for_expr(IrBuilder *irb, Scope *parent_scope, AstNo |
| 2137 | 2137 | IrInstruction *usize = ir_build_const_type(irb, child_scope, node, irb->codegen->builtin_types.entry_usize); |
| 2138 | 2138 | IrInstruction *zero = ir_build_const_usize(irb, child_scope, node, 0); |
| 2139 | 2139 | IrInstruction *one = ir_build_const_usize(irb, child_scope, node, 1); |
| 2140 | | ir_build_var_decl(irb, child_scope, index_var_source_node, index_var, usize, zero); |
| 2140 | ir_build_var_decl(irb, child_scope, index_var_source_node, index_var, usize, zero); |
| 2141 | 2141 | IrInstruction *index_ptr = ir_build_var_ptr(irb, child_scope, node, index_var); |
| 2142 | 2142 | |
| 2143 | 2143 | |
| ... | ... | @@ -2347,7 +2347,7 @@ static IrInstruction *ir_gen_if_var_expr(IrBuilder *irb, Scope *scope, AstNode * |
| 2347 | 2347 | |
| 2348 | 2348 | IrInstruction *var_ptr_value = ir_build_unwrap_maybe(irb, scope, node, expr_value, false); |
| 2349 | 2349 | IrInstruction *var_value = var_is_ptr ? var_ptr_value : ir_build_load_ptr(irb, scope, node, var_ptr_value); |
| 2350 | | ir_build_var_decl(irb, scope, node, var, var_type, var_value); |
| 2350 | ir_build_var_decl(irb, scope, node, var, var_type, var_value); |
| 2351 | 2351 | IrInstruction *then_expr_result = ir_gen_node(irb, then_node, var->child_scope); |
| 2352 | 2352 | if (then_expr_result == irb->codegen->invalid_instruction) |
| 2353 | 2353 | return then_expr_result; |
| ... | ... | @@ -2405,7 +2405,7 @@ static bool ir_gen_switch_prong_expr(IrBuilder *irb, Scope *scope, AstNode *swit |
| 2405 | 2405 | var_value = var_is_ptr ? target_value_ptr : ir_build_load_ptr(irb, scope, var_symbol_node, target_value_ptr); |
| 2406 | 2406 | } |
| 2407 | 2407 | IrInstruction *var_type = nullptr; // infer the type |
| 2408 | | ir_build_var_decl(irb, scope, var_symbol_node, var, var_type, var_value); |
| 2408 | ir_build_var_decl(irb, scope, var_symbol_node, var, var_type, var_value); |
| 2409 | 2409 | } else { |
| 2410 | 2410 | child_scope = scope; |
| 2411 | 2411 | } |
| ... | ... | @@ -3287,44 +3287,6 @@ IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node |
| 3287 | 3287 | return result; |
| 3288 | 3288 | } |
| 3289 | 3289 | |
| 3290 | | static IrInstruction *ir_eval_fn(IrAnalyze *ira, IrInstruction *source_instruction, |
| 3291 | | FnTableEntry *fn_entry, IrInstruction **args) |
| 3292 | | { |
| 3293 | | if (!fn_entry) { |
| 3294 | | ir_add_error(ira, source_instruction, |
| 3295 | | buf_sprintf("unable to evaluate constant expression")); |
| 3296 | | return ira->codegen->invalid_instruction; |
| 3297 | | } |
| 3298 | | |
| 3299 | | if (!ir_emit_backward_branch(ira, source_instruction)) |
| 3300 | | return ira->codegen->invalid_instruction; |
| 3301 | | |
| 3302 | | TypeTableEntry *fn_type = fn_entry->type_entry; |
| 3303 | | FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id; |
| 3304 | | |
| 3305 | | // Fork a scope of the function with known values for the parameters. |
| 3306 | | |
| 3307 | | Scope *exec_scope = &fn_entry->fndef_scope->base; |
| 3308 | | for (size_t i = 0; i < fn_type_id->param_count; i += 1) { |
| 3309 | | AstNode *param_decl_node = fn_entry->proto_node->data.fn_proto.params.at(i); |
| 3310 | | Buf *param_name = param_decl_node->data.param_decl.name; |
| 3311 | | IrInstruction *arg = args[i]; |
| 3312 | | ConstExprValue *arg_val = ir_resolve_const(ira, arg); |
| 3313 | | if (!arg_val) |
| 3314 | | return ira->codegen->invalid_instruction; |
| 3315 | | |
| 3316 | | VariableTableEntry *var = add_variable(ira->codegen, param_decl_node, exec_scope, param_name, |
| 3317 | | arg->type_entry, true, arg_val); |
| 3318 | | exec_scope = var->child_scope; |
| 3319 | | } |
| 3320 | | |
| 3321 | | // Analyze the fn body block like any other constant expression. |
| 3322 | | |
| 3323 | | AstNode *body_node = fn_entry->fn_def_node->data.fn_def.body; |
| 3324 | | return ir_eval_const_value(ira->codegen, exec_scope, body_node, fn_type_id->return_type, |
| 3325 | | ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota); |
| 3326 | | } |
| 3327 | | |
| 3328 | 3290 | static TypeTableEntry *ir_resolve_type_lval(IrAnalyze *ira, IrInstruction *type_value, LValPurpose lval) { |
| 3329 | 3291 | if (lval != LValPurposeNone) |
| 3330 | 3292 | zig_panic("TODO"); |
| ... | ... | @@ -4257,6 +4219,33 @@ static TypeTableEntry *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruc |
| 4257 | 4219 | return ira->codegen->builtin_types.entry_void; |
| 4258 | 4220 | } |
| 4259 | 4221 | |
| 4222 | static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node, |
| 4223 | IrInstruction *arg, Scope **exec_scope, size_t *next_arg_index) |
| 4224 | { |
| 4225 | AstNode *param_decl_node = fn_proto_node->data.fn_proto.params.at(*next_arg_index); |
| 4226 | assert(param_decl_node->type == NodeTypeParamDecl); |
| 4227 | AstNode *param_type_node = param_decl_node->data.param_decl.type; |
| 4228 | TypeTableEntry *param_type = analyze_type_expr(ira->codegen, *exec_scope, param_type_node); |
| 4229 | if (param_type->id == TypeTableEntryIdInvalid) |
| 4230 | return false; |
| 4231 | |
| 4232 | IrInstruction *casted_arg = ir_get_casted_value(ira, arg, param_type); |
| 4233 | if (casted_arg->type_entry->id == TypeTableEntryIdInvalid) |
| 4234 | return false; |
| 4235 | |
| 4236 | ConstExprValue *first_arg_val = ir_resolve_const(ira, casted_arg); |
| 4237 | if (!first_arg_val) |
| 4238 | return false; |
| 4239 | |
| 4240 | Buf *param_name = param_decl_node->data.param_decl.name; |
| 4241 | VariableTableEntry *var = add_variable(ira->codegen, param_decl_node, |
| 4242 | *exec_scope, param_name, param_type, true, first_arg_val); |
| 4243 | *exec_scope = var->child_scope; |
| 4244 | *next_arg_index += 1; |
| 4245 | |
| 4246 | return true; |
| 4247 | } |
| 4248 | |
| 4260 | 4249 | static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call_instruction, |
| 4261 | 4250 | FnTableEntry *fn_entry, TypeTableEntry *fn_type, IrInstruction *fn_ref, |
| 4262 | 4251 | IrInstruction *first_arg_ptr, bool is_inline) |
| ... | ... | @@ -4289,8 +4278,58 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal |
| 4289 | 4278 | return ira->codegen->builtin_types.entry_invalid; |
| 4290 | 4279 | } |
| 4291 | 4280 | |
| 4281 | if (is_inline) { |
| 4282 | if (!fn_entry) { |
| 4283 | ir_add_error(ira, fn_ref, buf_sprintf("unable to evaluate constant expression")); |
| 4284 | return ira->codegen->builtin_types.entry_invalid; |
| 4285 | } |
| 4286 | |
| 4287 | if (!ir_emit_backward_branch(ira, &call_instruction->base)) |
| 4288 | return ira->codegen->builtin_types.entry_invalid; |
| 4289 | |
| 4290 | // Fork a scope of the function with known values for the parameters. |
| 4291 | Scope *exec_scope = &fn_entry->fndef_scope->base; |
| 4292 | |
| 4293 | size_t next_arg_index = 0; |
| 4294 | if (first_arg_ptr) { |
| 4295 | IrInstruction *first_arg = ir_get_deref(ira, first_arg_ptr, first_arg_ptr); |
| 4296 | if (first_arg->type_entry->id == TypeTableEntryIdInvalid) |
| 4297 | return ira->codegen->builtin_types.entry_invalid; |
| 4298 | |
| 4299 | if (!ir_analyze_fn_call_inline_arg(ira, fn_proto_node, first_arg, &exec_scope, &next_arg_index)) |
| 4300 | return ira->codegen->builtin_types.entry_invalid; |
| 4301 | } |
| 4302 | |
| 4303 | for (size_t call_i = 0; call_i < call_instruction->arg_count; call_i += 1) { |
| 4304 | IrInstruction *old_arg = call_instruction->args[call_i]->other; |
| 4305 | if (old_arg->type_entry->id == TypeTableEntryIdInvalid) |
| 4306 | return ira->codegen->builtin_types.entry_invalid; |
| 4307 | |
| 4308 | if (!ir_analyze_fn_call_inline_arg(ira, fn_proto_node, old_arg, &exec_scope, &next_arg_index)) |
| 4309 | return ira->codegen->builtin_types.entry_invalid; |
| 4310 | } |
| 4311 | |
| 4312 | AstNode *return_type_node = fn_proto_node->data.fn_proto.return_type; |
| 4313 | TypeTableEntry *return_type = analyze_type_expr(ira->codegen, exec_scope, return_type_node); |
| 4314 | if (return_type->id == TypeTableEntryIdInvalid) |
| 4315 | return ira->codegen->builtin_types.entry_invalid; |
| 4316 | |
| 4317 | // Analyze the fn body block like any other constant expression. |
| 4318 | AstNode *body_node = fn_entry->fn_def_node->data.fn_def.body; |
| 4319 | IrInstruction *result = ir_eval_const_value(ira->codegen, exec_scope, body_node, return_type, |
| 4320 | ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota); |
| 4321 | if (result->type_entry->id == TypeTableEntryIdInvalid) |
| 4322 | return ira->codegen->builtin_types.entry_invalid; |
| 4323 | |
| 4324 | ConstExprValue *out_val = ir_build_const_from(ira, &call_instruction->base, |
| 4325 | result->static_value.depends_on_compile_var); |
| 4326 | *out_val = result->static_value; |
| 4327 | return ir_finish_anal(ira, return_type); |
| 4328 | } |
| 4329 | |
| 4292 | 4330 | IrInstruction **casted_args = allocate<IrInstruction *>(call_param_count); |
| 4293 | 4331 | size_t next_arg_index = 0; |
| 4332 | |
| 4294 | 4333 | if (first_arg_ptr) { |
| 4295 | 4334 | IrInstruction *first_arg = ir_get_deref(ira, first_arg_ptr, first_arg_ptr); |
| 4296 | 4335 | if (first_arg->type_entry->id == TypeTableEntryIdInvalid) |
| ... | ... | @@ -4304,9 +4343,6 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal |
| 4304 | 4343 | if (casted_arg->type_entry->id == TypeTableEntryIdInvalid) |
| 4305 | 4344 | return ira->codegen->builtin_types.entry_invalid; |
| 4306 | 4345 | |
| 4307 | | if (is_inline && !ir_resolve_const(ira, casted_arg)) |
| 4308 | | return ira->codegen->builtin_types.entry_invalid; |
| 4309 | | |
| 4310 | 4346 | casted_args[next_arg_index] = casted_arg; |
| 4311 | 4347 | next_arg_index += 1; |
| 4312 | 4348 | } |
| ... | ... | @@ -4326,9 +4362,6 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal |
| 4326 | 4362 | casted_arg = old_arg; |
| 4327 | 4363 | } |
| 4328 | 4364 | |
| 4329 | | if (is_inline && !ir_resolve_const(ira, casted_arg)) |
| 4330 | | return ira->codegen->builtin_types.entry_invalid; |
| 4331 | | |
| 4332 | 4365 | casted_args[next_arg_index] = casted_arg; |
| 4333 | 4366 | next_arg_index += 1; |
| 4334 | 4367 | } |
| ... | ... | @@ -4339,25 +4372,13 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal |
| 4339 | 4372 | if (return_type->id == TypeTableEntryIdInvalid) |
| 4340 | 4373 | return ira->codegen->builtin_types.entry_invalid; |
| 4341 | 4374 | |
| 4342 | | if (is_inline) { |
| 4343 | | assert(call_param_count == fn_type_id->param_count); |
| 4344 | | IrInstruction *result = ir_eval_fn(ira, &call_instruction->base, fn_entry, casted_args); |
| 4345 | | if (result->type_entry->id == TypeTableEntryIdInvalid) |
| 4346 | | return ira->codegen->builtin_types.entry_invalid; |
| 4347 | | |
| 4348 | | ConstExprValue *out_val = ir_build_const_from(ira, &call_instruction->base, |
| 4349 | | result->static_value.depends_on_compile_var); |
| 4350 | | *out_val = result->static_value; |
| 4351 | | return ir_finish_anal(ira, return_type); |
| 4352 | | } |
| 4353 | | |
| 4354 | 4375 | IrInstruction *new_call_instruction = ir_build_call_from(&ira->new_irb, &call_instruction->base, |
| 4355 | 4376 | fn_entry, fn_ref, call_param_count, casted_args); |
| 4356 | 4377 | |
| 4357 | 4378 | if (type_has_bits(return_type) && handle_is_ptr(return_type)) { |
| 4358 | | FnTableEntry *owner_fn = exec_fn_entry(ira->new_irb.exec); |
| 4359 | | assert(owner_fn); |
| 4360 | | owner_fn->alloca_list.append(new_call_instruction); |
| 4379 | FnTableEntry *callsite_fn = exec_fn_entry(ira->new_irb.exec); |
| 4380 | assert(callsite_fn); |
| 4381 | callsite_fn->alloca_list.append(new_call_instruction); |
| 4361 | 4382 | } |
| 4362 | 4383 | |
| 4363 | 4384 | return ir_finish_anal(ira, return_type); |
| ... | ... | @@ -5349,7 +5370,7 @@ static TypeTableEntry *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructi |
| 5349 | 5370 | case TypeTableEntryIdTypeDecl: |
| 5350 | 5371 | { |
| 5351 | 5372 | ConstExprValue *out_val = ir_build_const_from(ira, &typeof_instruction->base, false); |
| 5352 | | // TODO depends_on_compile_var should be set based on whether the type of the expression |
| 5373 | // TODO depends_on_compile_var should be set based on whether the type of the expression |
| 5353 | 5374 | // depends_on_compile_var. but we currently don't have a thing to tell us if the type of |
| 5354 | 5375 | // something depends on a compile var |
| 5355 | 5376 | out_val->data.x_type = type_entry; |