Call function using C/native calling convention (not a Python callable).
(
self,
desc: CFunctionDescription,
args: list[Value],
line: int,
result_type: RType | None = None,
)
| 2223 | self.add_bool_branch(remaining, true, false) |
| 2224 | |
| 2225 | def call_c( |
| 2226 | self, |
| 2227 | desc: CFunctionDescription, |
| 2228 | args: list[Value], |
| 2229 | line: int, |
| 2230 | result_type: RType | None = None, |
| 2231 | ) -> Value: |
| 2232 | """Call function using C/native calling convention (not a Python callable).""" |
| 2233 | # Handle void function via singleton RVoid instance |
| 2234 | coerced = [] |
| 2235 | # Coerce fixed number arguments |
| 2236 | for i in range(min(len(args), len(desc.arg_types))): |
| 2237 | formal_type = desc.arg_types[i] |
| 2238 | arg = args[i] |
| 2239 | arg = self.coerce(arg, formal_type, line) |
| 2240 | coerced.append(arg) |
| 2241 | # Reorder args if necessary |
| 2242 | if desc.ordering is not None: |
| 2243 | assert desc.var_arg_type is None |
| 2244 | coerced = [coerced[i] for i in desc.ordering] |
| 2245 | # Coerce any var_arg |
| 2246 | var_arg_idx = -1 |
| 2247 | if desc.var_arg_type is not None: |
| 2248 | var_arg_idx = len(desc.arg_types) |
| 2249 | for i in range(len(desc.arg_types), len(args)): |
| 2250 | arg = args[i] |
| 2251 | arg = self.coerce(arg, desc.var_arg_type, line) |
| 2252 | coerced.append(arg) |
| 2253 | # Add extra integer constant if any |
| 2254 | for item in desc.extra_int_constants: |
| 2255 | val, typ = item |
| 2256 | extra_int_constant = Integer(val, typ, line) |
| 2257 | coerced.append(extra_int_constant) |
| 2258 | error_kind = desc.error_kind |
| 2259 | if error_kind == ERR_NEG_INT: |
| 2260 | # Handled with an explicit comparison |
| 2261 | error_kind = ERR_NEVER |
| 2262 | target = self.add( |
| 2263 | CallC( |
| 2264 | desc.c_function_name, |
| 2265 | coerced, |
| 2266 | desc.return_type, |
| 2267 | desc.steals, |
| 2268 | desc.is_borrowed, |
| 2269 | error_kind, |
| 2270 | line, |
| 2271 | var_arg_idx, |
| 2272 | is_pure=desc.is_pure, |
| 2273 | returns_null=desc.returns_null, |
| 2274 | dependencies=desc.dependencies, |
| 2275 | ) |
| 2276 | ) |
| 2277 | if desc.is_borrowed: |
| 2278 | # If the result is borrowed, force the arguments to be |
| 2279 | # kept alive afterwards, as otherwise the result might be |
| 2280 | # immediately freed, at the risk of a dangling pointer. |
| 2281 | for arg in coerced: |
| 2282 | if not isinstance(arg, (Integer, LoadLiteral)): |
no test coverage detected