| 3664 | } |
| 3665 | |
| 3666 | void ArgsCache::build_arg(uint8_t gi_index, GIDirection direction, |
| 3667 | const GI::ArgInfo& arg, |
| 3668 | const GI::CallableInfo& callable, |
| 3669 | bool* inc_counter_out) { |
| 3670 | g_assert(inc_counter_out && "forgot out parameter"); |
| 3671 | |
| 3672 | GI::StackTypeInfo type_info; |
| 3673 | arg.load_type(&type_info); |
| 3674 | |
| 3675 | GjsArgumentFlags flags = GjsArgumentFlags::NONE; |
| 3676 | if (arg.may_be_null()) |
| 3677 | flags |= GjsArgumentFlags::MAY_BE_NULL; |
| 3678 | if ((direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT) && |
| 3679 | arg.is_optional()) |
| 3680 | flags |= GjsArgumentFlags::MAY_BE_NULL; |
| 3681 | if (arg.caller_allocates()) |
| 3682 | flags |= GjsArgumentFlags::CALLER_ALLOCATES; |
| 3683 | |
| 3684 | if (direction == GI_DIRECTION_IN) |
| 3685 | flags |= GjsArgumentFlags::SKIP_OUT; |
| 3686 | else if (direction == GI_DIRECTION_OUT) |
| 3687 | flags |= GjsArgumentFlags::SKIP_IN; |
| 3688 | *inc_counter_out = true; |
| 3689 | |
| 3690 | Argument::Init common_args{arg.name(), gi_index, arg.ownership_transfer(), |
| 3691 | flags}; |
| 3692 | |
| 3693 | GITypeTag type_tag = type_info.tag(); |
| 3694 | if (direction == GI_DIRECTION_OUT && |
| 3695 | (flags & GjsArgumentFlags::CALLER_ALLOCATES)) { |
| 3696 | size_t size = 0; |
| 3697 | |
| 3698 | if (type_tag == GI_TYPE_TAG_ARRAY) { |
| 3699 | switch (type_info.array_type()) { |
| 3700 | case GI_ARRAY_TYPE_C: { |
| 3701 | Maybe<size_t> n_elements = type_info.array_fixed_size(); |
| 3702 | if (!n_elements || *n_elements == 0) |
| 3703 | break; |
| 3704 | |
| 3705 | GI::AutoTypeInfo element_type{type_info.element_type()}; |
| 3706 | size = gjs_type_get_element_size(element_type.tag(), |
| 3707 | element_type); |
| 3708 | size *= *n_elements; |
| 3709 | break; |
| 3710 | } |
| 3711 | default: |
| 3712 | break; |
| 3713 | } |
| 3714 | } else if (!type_tag_is_scalar(type_tag) && !type_info.is_pointer()) { |
| 3715 | // Scalar out parameters should not be annotated with |
| 3716 | // caller-allocates, which is for structured types that need to be |
| 3717 | // allocated in order for the function to fill them in. |
| 3718 | size = gjs_type_get_element_size(type_tag, type_info); |
| 3719 | } |
| 3720 | |
| 3721 | if (!size) { |
| 3722 | set_argument( |
| 3723 | new Arg::NotIntrospectable(OUT_CALLER_ALLOCATES_NON_STRUCT), |
no test coverage detected