| ... | ... | @@ -567,6 +567,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSetAlignStack *) |
| 567 | 567 | return IrInstructionIdSetAlignStack; |
| 568 | 568 | } |
| 569 | 569 | |
| 570 | static constexpr IrInstructionId ir_instruction_id(IrInstructionArgType *) { |
| 571 | return IrInstructionIdArgType; |
| 572 | } |
| 573 | |
| 570 | 574 | template<typename T> |
| 571 | 575 | static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) { |
| 572 | 576 | T *special_instruction = allocate<T>(1); |
| ... | ... | @@ -2263,6 +2267,19 @@ static IrInstruction *ir_build_set_align_stack(IrBuilder *irb, Scope *scope, Ast |
| 2263 | 2267 | return &instruction->base; |
| 2264 | 2268 | } |
| 2265 | 2269 | |
| 2270 | static IrInstruction *ir_build_arg_type(IrBuilder *irb, Scope *scope, AstNode *source_node, |
| 2271 | IrInstruction *fn_type, IrInstruction *arg_index) |
| 2272 | { |
| 2273 | IrInstructionArgType *instruction = ir_build_instruction<IrInstructionArgType>(irb, scope, source_node); |
| 2274 | instruction->fn_type = fn_type; |
| 2275 | instruction->arg_index = arg_index; |
| 2276 | |
| 2277 | ir_ref_instruction(fn_type, irb->current_basic_block); |
| 2278 | ir_ref_instruction(arg_index, irb->current_basic_block); |
| 2279 | |
| 2280 | return &instruction->base; |
| 2281 | } |
| 2282 | |
| 2266 | 2283 | static IrInstruction *ir_instruction_br_get_dep(IrInstructionBr *instruction, size_t index) { |
| 2267 | 2284 | return nullptr; |
| 2268 | 2285 | } |
| ... | ... | @@ -2992,6 +3009,14 @@ static IrInstruction *ir_instruction_setalignstack_get_dep(IrInstructionSetAlign |
| 2992 | 3009 | } |
| 2993 | 3010 | } |
| 2994 | 3011 | |
| 3012 | static IrInstruction *ir_instruction_argtype_get_dep(IrInstructionArgType *instruction, size_t index) { |
| 3013 | switch (index) { |
| 3014 | case 0: return instruction->fn_type; |
| 3015 | case 1: return instruction->arg_index; |
| 3016 | default: return nullptr; |
| 3017 | } |
| 3018 | } |
| 3019 | |
| 2995 | 3020 | static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t index) { |
| 2996 | 3021 | switch (instruction->id) { |
| 2997 | 3022 | case IrInstructionIdInvalid: |
| ... | ... | @@ -3194,6 +3219,8 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t |
| 3194 | 3219 | return ir_instruction_opaquetype_get_dep((IrInstructionOpaqueType *) instruction, index); |
| 3195 | 3220 | case IrInstructionIdSetAlignStack: |
| 3196 | 3221 | return ir_instruction_setalignstack_get_dep((IrInstructionSetAlignStack *) instruction, index); |
| 3222 | case IrInstructionIdArgType: |
| 3223 | return ir_instruction_argtype_get_dep((IrInstructionArgType *) instruction, index); |
| 3197 | 3224 | } |
| 3198 | 3225 | zig_unreachable(); |
| 3199 | 3226 | } |
| ... | ... | @@ -4629,6 +4656,20 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo |
| 4629 | 4656 | |
| 4630 | 4657 | return ir_build_set_align_stack(irb, scope, node, arg0_value); |
| 4631 | 4658 | } |
| 4659 | case BuiltinFnIdArgType: |
| 4660 | { |
| 4661 | AstNode *arg0_node = node->data.fn_call_expr.params.at(0); |
| 4662 | IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope); |
| 4663 | if (arg0_value == irb->codegen->invalid_instruction) |
| 4664 | return arg0_value; |
| 4665 | |
| 4666 | AstNode *arg1_node = node->data.fn_call_expr.params.at(1); |
| 4667 | IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope); |
| 4668 | if (arg1_value == irb->codegen->invalid_instruction) |
| 4669 | return arg1_value; |
| 4670 | |
| 4671 | return ir_build_arg_type(irb, scope, node, arg0_value, arg1_value); |
| 4672 | } |
| 4632 | 4673 | } |
| 4633 | 4674 | zig_unreachable(); |
| 4634 | 4675 | } |
| ... | ... | @@ -11686,6 +11727,13 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru |
| 11686 | 11727 | create_const_bool(ira->codegen, child_type->data.fn.fn_type_id.is_var_args), |
| 11687 | 11728 | ira->codegen->builtin_types.entry_bool, |
| 11688 | 11729 | ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile); |
| 11730 | } else if (buf_eql_str(field_name, "arg_count")) { |
| 11731 | bool ptr_is_const = true; |
| 11732 | bool ptr_is_volatile = false; |
| 11733 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, |
| 11734 | create_const_usize(ira->codegen, child_type->data.fn.fn_type_id.param_count), |
| 11735 | ira->codegen->builtin_types.entry_usize, |
| 11736 | ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile); |
| 11689 | 11737 | } else { |
| 11690 | 11738 | ir_add_error(ira, &field_ptr_instruction->base, |
| 11691 | 11739 | buf_sprintf("type '%s' has no member called '%s'", |
| ... | ... | @@ -15395,6 +15443,35 @@ static TypeTableEntry *ir_analyze_instruction_set_align_stack(IrAnalyze *ira, Ir |
| 15395 | 15443 | return ira->codegen->builtin_types.entry_void; |
| 15396 | 15444 | } |
| 15397 | 15445 | |
| 15446 | static TypeTableEntry *ir_analyze_instruction_arg_type(IrAnalyze *ira, IrInstructionArgType *instruction) { |
| 15447 | IrInstruction *fn_type_inst = instruction->fn_type->other; |
| 15448 | TypeTableEntry *fn_type = ir_resolve_type(ira, fn_type_inst); |
| 15449 | if (type_is_invalid(fn_type)) |
| 15450 | return ira->codegen->builtin_types.entry_invalid; |
| 15451 | |
| 15452 | IrInstruction *arg_index_inst = instruction->arg_index->other; |
| 15453 | uint64_t arg_index; |
| 15454 | if (!ir_resolve_usize(ira, arg_index_inst, &arg_index)) |
| 15455 | return ira->codegen->builtin_types.entry_invalid; |
| 15456 | |
| 15457 | if (fn_type->id != TypeTableEntryIdFn) { |
| 15458 | ir_add_error(ira, fn_type_inst, buf_sprintf("expected function, found '%s'", buf_ptr(&fn_type->name))); |
| 15459 | return ira->codegen->builtin_types.entry_invalid; |
| 15460 | } |
| 15461 | |
| 15462 | FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id; |
| 15463 | if (arg_index >= fn_type_id->param_count) { |
| 15464 | ir_add_error(ira, arg_index_inst, |
| 15465 | buf_sprintf("arg index %" ZIG_PRI_usize " out of bounds; '%s' has %" ZIG_PRI_usize " arguments", |
| 15466 | arg_index, buf_ptr(&fn_type->name), fn_type_id->param_count)); |
| 15467 | return ira->codegen->builtin_types.entry_invalid; |
| 15468 | } |
| 15469 | |
| 15470 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); |
| 15471 | out_val->data.x_type = fn_type_id->param_info[arg_index].type; |
| 15472 | return ira->codegen->builtin_types.entry_type; |
| 15473 | } |
| 15474 | |
| 15398 | 15475 | static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) { |
| 15399 | 15476 | switch (instruction->id) { |
| 15400 | 15477 | case IrInstructionIdInvalid: |
| ... | ... | @@ -15585,6 +15662,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 15585 | 15662 | return ir_analyze_instruction_opaque_type(ira, (IrInstructionOpaqueType *)instruction); |
| 15586 | 15663 | case IrInstructionIdSetAlignStack: |
| 15587 | 15664 | return ir_analyze_instruction_set_align_stack(ira, (IrInstructionSetAlignStack *)instruction); |
| 15665 | case IrInstructionIdArgType: |
| 15666 | return ir_analyze_instruction_arg_type(ira, (IrInstructionArgType *)instruction); |
| 15588 | 15667 | } |
| 15589 | 15668 | zig_unreachable(); |
| 15590 | 15669 | } |
| ... | ... | @@ -15765,6 +15844,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 15765 | 15844 | case IrInstructionIdTypeId: |
| 15766 | 15845 | case IrInstructionIdAlignCast: |
| 15767 | 15846 | case IrInstructionIdOpaqueType: |
| 15847 | case IrInstructionIdArgType: |
| 15768 | 15848 | return false; |
| 15769 | 15849 | case IrInstructionIdAsm: |
| 15770 | 15850 | { |