|
1 | 1 | //! Interpret intrinsics, lang items and `extern "C"` wellknown functions which their implementation
|
2 | 2 | //! is not available.
|
3 | 3 | //!
|
4 |
| -use std::cmp; |
| 4 | +use std::cmp::{self, Ordering}; |
5 | 5 |
|
6 | 6 | use chalk_ir::TyKind;
|
7 | 7 | use hir_def::{
|
8 | 8 | builtin_type::{BuiltinInt, BuiltinUint},
|
| 9 | + lang_item::LangItemTarget, |
9 | 10 | resolver::HasResolver,
|
10 | 11 | };
|
11 | 12 | use hir_expand::name::Name;
|
@@ -1317,6 +1318,82 @@ impl Evaluator<'_> {
|
1317 | 1318 | self.write_memory_using_ref(dst, size)?.fill(val);
|
1318 | 1319 | Ok(())
|
1319 | 1320 | }
|
| 1321 | + "ptr_metadata" => { |
| 1322 | + let [ptr] = args else { |
| 1323 | + return Err(MirEvalError::InternalError( |
| 1324 | + "ptr_metadata args are not provided".into(), |
| 1325 | + )); |
| 1326 | + }; |
| 1327 | + let arg = ptr.interval.get(self)?.to_owned(); |
| 1328 | + let metadata = &arg[self.ptr_size()..]; |
| 1329 | + destination.write_from_bytes(self, metadata)?; |
| 1330 | + Ok(()) |
| 1331 | + } |
| 1332 | + "three_way_compare" => { |
| 1333 | + let [lhs, rhs] = args else { |
| 1334 | + return Err(MirEvalError::InternalError( |
| 1335 | + "three_way_compare args are not provided".into(), |
| 1336 | + )); |
| 1337 | + }; |
| 1338 | + let Some(ty) = |
| 1339 | + generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner)) |
| 1340 | + else { |
| 1341 | + return Err(MirEvalError::InternalError( |
| 1342 | + "three_way_compare generic arg is not provided".into(), |
| 1343 | + )); |
| 1344 | + }; |
| 1345 | + let signed = match ty.as_builtin().unwrap() { |
| 1346 | + BuiltinType::Int(_) => true, |
| 1347 | + BuiltinType::Uint(_) => false, |
| 1348 | + _ => { |
| 1349 | + return Err(MirEvalError::InternalError( |
| 1350 | + "three_way_compare expects an integral type".into(), |
| 1351 | + )) |
| 1352 | + } |
| 1353 | + }; |
| 1354 | + let rhs = rhs.get(self)?; |
| 1355 | + let lhs = lhs.get(self)?; |
| 1356 | + let mut result = Ordering::Equal; |
| 1357 | + for (l, r) in lhs.iter().zip(rhs).rev() { |
| 1358 | + let it = l.cmp(r); |
| 1359 | + if it != Ordering::Equal { |
| 1360 | + result = it; |
| 1361 | + break; |
| 1362 | + } |
| 1363 | + } |
| 1364 | + if signed { |
| 1365 | + if let Some((&l, &r)) = lhs.iter().zip(rhs).next_back() { |
| 1366 | + if l != r { |
| 1367 | + result = (l as i8).cmp(&(r as i8)); |
| 1368 | + } |
| 1369 | + } |
| 1370 | + } |
| 1371 | + if let Some(LangItemTarget::EnumId(e)) = |
| 1372 | + self.db.lang_item(self.crate_id, LangItem::Ordering) |
| 1373 | + { |
| 1374 | + let ty = self.db.ty(e.into()); |
| 1375 | + let r = self |
| 1376 | + .compute_discriminant(ty.skip_binders().clone(), &[result as i8 as u8])?; |
| 1377 | + destination.write_from_bytes(self, &r.to_le_bytes()[0..destination.size])?; |
| 1378 | + Ok(()) |
| 1379 | + } else { |
| 1380 | + Err(MirEvalError::InternalError("Ordering enum not found".into())) |
| 1381 | + } |
| 1382 | + } |
| 1383 | + "aggregate_raw_ptr" => { |
| 1384 | + let [data, meta] = args else { |
| 1385 | + return Err(MirEvalError::InternalError( |
| 1386 | + "aggregate_raw_ptr args are not provided".into(), |
| 1387 | + )); |
| 1388 | + }; |
| 1389 | + destination.write_from_interval(self, data.interval)?; |
| 1390 | + Interval { |
| 1391 | + addr: destination.addr.offset(data.interval.size), |
| 1392 | + size: destination.size - data.interval.size, |
| 1393 | + } |
| 1394 | + .write_from_interval(self, meta.interval)?; |
| 1395 | + Ok(()) |
| 1396 | + } |
1320 | 1397 | _ if needs_override => not_supported!("intrinsic {name} is not implemented"),
|
1321 | 1398 | _ => return Ok(false),
|
1322 | 1399 | }
|
|
0 commit comments