| 1144 | } |
| 1145 | |
| 1146 | void GDScriptByteCodeGenerator::write_call_utility(const Address &p_target, const StringName &p_function, const Vector<Address> &p_arguments) { |
| 1147 | bool is_validated = true; |
| 1148 | if (Variant::is_utility_function_vararg(p_function)) { |
| 1149 | is_validated = false; // Vararg needs runtime checks, can't use validated call. |
| 1150 | } else if (p_arguments.size() == Variant::get_utility_function_argument_count(p_function)) { |
| 1151 | bool all_types_exact = true; |
| 1152 | for (int i = 0; i < p_arguments.size(); i++) { |
| 1153 | if (!IS_BUILTIN_TYPE(p_arguments[i], Variant::get_utility_function_argument_type(p_function, i))) { |
| 1154 | all_types_exact = false; |
| 1155 | break; |
| 1156 | } |
| 1157 | } |
| 1158 | |
| 1159 | is_validated = all_types_exact; |
| 1160 | } |
| 1161 | |
| 1162 | if (is_validated) { |
| 1163 | Variant::Type result_type = Variant::has_utility_function_return_value(p_function) ? Variant::get_utility_function_return_type(p_function) : Variant::NIL; |
| 1164 | CallTarget ct = get_call_target(p_target, result_type); |
| 1165 | Variant::Type temp_type = temporaries[ct.target.address].type; |
| 1166 | if (result_type != temp_type) { |
| 1167 | write_type_adjust(ct.target, result_type); |
| 1168 | } |
| 1169 | append_opcode_and_argcount(GDScriptFunction::OPCODE_CALL_UTILITY_VALIDATED, 1 + p_arguments.size()); |
| 1170 | for (int i = 0; i < p_arguments.size(); i++) { |
| 1171 | append(p_arguments[i]); |
| 1172 | } |
| 1173 | append(ct.target); |
| 1174 | append(p_arguments.size()); |
| 1175 | append(Variant::get_validated_utility_function(p_function)); |
| 1176 | ct.cleanup(); |
| 1177 | #ifdef DEBUG_ENABLED |
| 1178 | add_debug_name(utilities_names, get_utility_pos(Variant::get_validated_utility_function(p_function)), p_function); |
| 1179 | #endif |
| 1180 | } else { |
| 1181 | append_opcode_and_argcount(GDScriptFunction::OPCODE_CALL_UTILITY, 1 + p_arguments.size()); |
| 1182 | for (int i = 0; i < p_arguments.size(); i++) { |
| 1183 | append(p_arguments[i]); |
| 1184 | } |
| 1185 | CallTarget ct = get_call_target(p_target); |
| 1186 | append(ct.target); |
| 1187 | append(p_arguments.size()); |
| 1188 | append(p_function); |
| 1189 | ct.cleanup(); |
| 1190 | } |
| 1191 | } |
| 1192 | |
| 1193 | void GDScriptByteCodeGenerator::write_call_builtin_type(const Address &p_target, const Address &p_base, Variant::Type p_type, const StringName &p_method, bool p_is_static, const Vector<Address> &p_arguments) { |
| 1194 | bool is_validated = false; |
no test coverage detected