LCOV - code coverage report
Current view: top level - gcc/rust/typecheck - rust-hir-type-check-intrinsic.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 71.1 % 325 231
Test Date: 2026-08-22 16:33:35 Functions: 100.0 % 6 6
Legend: Lines:     hit not hit

            Line data    Source code
       1              : // Copyright (C) 2026 Free Software Foundation, Inc.
       2              : 
       3              : // This file is part of GCC.
       4              : 
       5              : // GCC is free software; you can redistribute it and/or modify it under
       6              : // the terms of the GNU General Public License as published by the Free
       7              : // Software Foundation; either version 3, or (at your option) any later
       8              : // version.
       9              : 
      10              : // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      11              : // WARRANTY; without even the implied warranty of MERCHANTABILITY or
      12              : // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      13              : // for more details.
      14              : 
      15              : // You should have received a copy of the GNU General Public License
      16              : // along with GCC; see the file COPYING3.  If not see
      17              : // <http://www.gnu.org/licenses/>.
      18              : 
      19              : #include "rust-hir-type-check-intrinsic.h"
      20              : #include "rust-diagnostics.h"
      21              : #include "rust-intrinsic-values.h"
      22              : #include "rust-system.h"
      23              : #include "rust-tyty.h"
      24              : 
      25              : namespace Rust {
      26              : namespace Resolver {
      27              : 
      28              : using IValue = Values::Intrinsics;
      29              : using IRT = IntrinsicRuleType;
      30              : 
      31              : const std::unordered_map<std::string, IntrinsicRules>
      32              :   IntrinsicChecker::intrinsic_rules = {
      33              :     // fn unreachable() -> !;
      34              :     {IValue::UNREACHABLE, {0, {}, IRT::Never}},
      35              : 
      36              :     // pub fn sqrtf32(x: f32) -> f32;
      37              :     {IValue::SQRTF32, {0, {IRT::F32}, IRT::F32}},
      38              :     // pub fn sqrtf64(x: f64) -> f64;
      39              :     {IValue::SQRTF64, {0, {IRT::F64}, IRT::F64}},
      40              :     // pub fn sinf32(x: f32) -> f32;
      41              :     {IValue::SINF32, {0, {IRT::F32}, IRT::F32}},
      42              :     // pub fn sinf64(x: f64) -> f64;
      43              :     {IValue::SINF64, {0, {IRT::F64}, IRT::F64}},
      44              :     // pub fn cosf32(x: f32) -> f32;
      45              :     {IValue::COSF32, {0, {IRT::F32}, IRT::F32}},
      46              :     // pub fn cosf64(x: f64) -> f64;
      47              :     {IValue::COSF64, {0, {IRT::F64}, IRT::F64}},
      48              :     // pub fn expf32(x: f32) -> f32;
      49              :     {IValue::EXPF32, {0, {IRT::F32}, IRT::F32}},
      50              :     // pub fn expf64(x: f64) -> f64;
      51              :     {IValue::EXPF64, {0, {IRT::F64}, IRT::F64}},
      52              :     // pub fn exp2f32(x: f32) -> f32;
      53              :     {IValue::EXP2F32, {0, {IRT::F32}, IRT::F32}},
      54              :     // pub fn exp2f64(x: f64) -> f64;
      55              :     {IValue::EXP2F64, {0, {IRT::F64}, IRT::F64}},
      56              :     // pub fn logf32(x: f32) -> f32;
      57              :     {IValue::LOGF32, {0, {IRT::F32}, IRT::F32}},
      58              :     // pub fn logf64(x: f64) -> f64;
      59              :     {IValue::LOGF64, {0, {IRT::F64}, IRT::F64}},
      60              :     // pub fn log10f32(x: f32) -> f32;
      61              :     {IValue::LOG10F32, {0, {IRT::F32}, IRT::F32}},
      62              :     // pub fn log10f64(x: f64) -> f64;
      63              :     {IValue::LOG10F64, {0, {IRT::F64}, IRT::F64}},
      64              :     // pub fn log2f32(x: f32) -> f32;
      65              :     {IValue::LOG2F32, {0, {IRT::F32}, IRT::F32}},
      66              :     // pub fn log2f64(x: f64) -> f64;
      67              :     {IValue::LOG2F64, {0, {IRT::F64}, IRT::F64}},
      68              :     // pub fn fabsf32(x: f32) -> f32;
      69              :     {IValue::FABSF32, {0, {IRT::F32}, IRT::F32}},
      70              :     // pub fn fabsf64(x: f64) -> f64;
      71              :     {IValue::FABSF64, {0, {IRT::F64}, IRT::F64}},
      72              :     // pub fn floorf32(x: f32) -> f32;
      73              :     {IValue::FLOORF32, {0, {IRT::F32}, IRT::F32}},
      74              :     // pub fn floorf64(x: f64) -> f64;
      75              :     {IValue::FLOORF64, {0, {IRT::F64}, IRT::F64}},
      76              :     // pub fn ceilf32(x: f32) -> f32;
      77              :     {IValue::CEILF32, {0, {IRT::F32}, IRT::F32}},
      78              :     // pub fn ceilf64(x: f64) -> f64;
      79              :     {IValue::CEILF64, {0, {IRT::F64}, IRT::F64}},
      80              :     // pub fn truncf32(x: f32) -> f32;
      81              :     {IValue::TRUNCF32, {0, {IRT::F32}, IRT::F32}},
      82              :     // pub fn truncf64(x: f64) -> f64;
      83              :     {IValue::TRUNCF64, {0, {IRT::F64}, IRT::F64}},
      84              :     // pub fn rintf32(x: f32) -> f32;
      85              :     {IValue::RINTF32, {0, {IRT::F32}, IRT::F32}},
      86              :     // pub fn rintf64(x: f64) -> f64;
      87              :     {IValue::RINTF64, {0, {IRT::F64}, IRT::F64}},
      88              :     // pub fn nearbyintf32(x: f32) -> f32;
      89              :     {IValue::NEARBYINTF32, {0, {IRT::F32}, IRT::F32}},
      90              :     // pub fn nearbyintf64(x: f64) -> f64;
      91              :     {IValue::NEARBYINTF64, {0, {IRT::F64}, IRT::F64}},
      92              :     // pub fn roundf32(x: f32) -> f32;
      93              :     {IValue::ROUNDF32, {0, {IRT::F32}, IRT::F32}},
      94              :     // pub fn roundf64(x: f64) -> f64;
      95              :     {IValue::ROUNDF64, {0, {IRT::F64}, IRT::F64}},
      96              :     // pub fn minnumf32(x: f32, y: f32) -> f32;
      97              :     {IValue::MINNUMF32, {0, {IRT::F32, IRT::F32}, IRT::F32}},
      98              :     // pub fn minnumf64(x: f64, y: f64) -> f64;
      99              :     {IValue::MINNUMF64, {0, {IRT::F64, IRT::F64}, IRT::F64}},
     100              :     // pub fn maxnumf32(x: f32, y: f32) -> f32;
     101              :     {IValue::MAXNUMF32, {0, {IRT::F32, IRT::F32}, IRT::F32}},
     102              :     // pub fn maxnumf64(x: f64, y: f64) -> f64;
     103              :     {IValue::MAXNUMF64, {0, {IRT::F64, IRT::F64}, IRT::F64}},
     104              : 
     105              :     // pub fn powf32(a: f32, x: f32) -> f32;
     106              :     {IValue::POWF32, {0, {IRT::F32, IRT::F32}, IRT::F32}},
     107              :     // pub fn powf64(a: f64, x: f64) -> f64;
     108              :     {IValue::POWF64, {0, {IRT::F64, IRT::F64}, IRT::F64}},
     109              :     // pub fn copysignf32(x: f32, y: f32) -> f32;
     110              :     {IValue::COPYSIGNF32, {0, {IRT::F32, IRT::F32}, IRT::F32}},
     111              :     // pub fn copysignf64(x: f64, y: f64) -> f64;
     112              :     {IValue::COPYSIGNF64, {0, {IRT::F64, IRT::F64}, IRT::F64}},
     113              : 
     114              :     // pub fn fmaf32(a: f32, b: f32, c: f32) -> f32;
     115              :     {IValue::FMAF32, {0, {IRT::F32, IRT::F32, IRT::F32}, IRT::F32}},
     116              :     // pub fn fmaf64(a: f64, b: f64, c: f64) -> f64;
     117              :     {IValue::FMAF64, {0, {IRT::F64, IRT::F64, IRT::F64}, IRT::F64}},
     118              : 
     119              :     // pub fn powif32(a: f32, x: i32) -> f32;
     120              :     {IValue::POWIF32, {0, {IRT::F32, IRT::I32}, IRT::F32}},
     121              :     // pub fn powif64(a: f64, x: i32) -> f64;
     122              :     {IValue::POWIF64, {0, {IRT::F64, IRT::I32}, IRT::F64}},
     123              : 
     124              :     // pub fn abort() -> !;
     125              :     {IValue::ABORT, {0, {}, IRT::Never}},
     126              :     // pub fn offset<T>(dst: *const T, offset: isize) -> *const T;
     127              :     {IValue::OFFSET,
     128              :      {1, {IRT::ConstPtrFirstGeneric, IRT::Isize}, IRT::ConstPtrFirstGeneric}},
     129              :     // pub fn size_of<T>() -> usize;
     130              :     {IValue::SIZE_OF, {1, {}, IRT::Usize}},
     131              :     // pub fn size_of_val<T: ?Sized>(_: *const T) -> usize;
     132              :     {IValue::SIZE_OF_VAL, {1, {IRT::ConstPtrFirstGeneric}, IRT::Usize}},
     133              :     // pub fn transmute<T, U>(e: T) -> U;
     134              :     {IValue::TRANSMUTE, {2, {IRT::FirstGeneric}, IRT::SecondGeneric}},
     135              :     // pub fn add_with_overflow<T: Copy>(x: T, y: T) -> (T, bool);
     136              :     {IValue::ADD_WITH_OVERFLOW,
     137              :      {1,
     138              :       {IRT::FirstGeneric, IRT::FirstGeneric},
     139              :       IRT::TupleFirstGenericAndBool}},
     140              :     // pub fn sub_with_overflow<T: Copy>(x: T, y: T) -> (T, bool);
     141              :     {IValue::SUB_WITH_OVERFLOW,
     142              :      {1,
     143              :       {IRT::FirstGeneric, IRT::FirstGeneric},
     144              :       IRT::TupleFirstGenericAndBool}},
     145              :     // pub fn mul_with_overflow<T: Copy>(x: T, y: T) -> (T, bool);
     146              :     {IValue::MUL_WITH_OVERFLOW,
     147              :      {1,
     148              :       {IRT::FirstGeneric, IRT::FirstGeneric},
     149              :       IRT::TupleFirstGenericAndBool}},
     150              :     // fn copy<T>(src: *const T, dst: *mut T, count: usize);
     151              :     {IValue::COPY,
     152              :      {1,
     153              :       {IRT::ConstPtrFirstGeneric, IRT::MutPtrFirstGeneric, IRT::Usize},
     154              :       IRT::Unit}},
     155              :     // fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
     156              :     {IValue::COPY_NONOVERLAPPING,
     157              :      {1,
     158              :       {IRT::ConstPtrFirstGeneric, IRT::MutPtrFirstGeneric, IRT::Usize},
     159              :       IRT::Unit}},
     160              :     // pub fn prefetch_read_data<T>(data: *const T, locality: i32);
     161              :     {IValue::PREFETCH_READ_DATA,
     162              :      {1, {IRT::ConstPtrFirstGeneric, IRT::I32}, IRT::Unit}},
     163              :     // pub fn prefetch_write_data<T>(data: *const T, locality: i32);
     164              :     {IValue::PREFETCH_WRITE_DATA,
     165              :      {1, {IRT::ConstPtrFirstGeneric, IRT::I32}, IRT::Unit}},
     166              :     // pub unsafe fn atomic_store_seqcst<T: Copy>(_dst: *mut T, _val: T);
     167              :     {IValue::ATOMIC_STORE_SEQCST,
     168              :      {1, {IRT::MutPtrFirstGeneric, IRT::FirstGeneric}, IRT::Unit}},
     169              :     // pub unsafe fn atomic_store_release<T: Copy>(_dst: *mut T, _val: T);
     170              :     {IValue::ATOMIC_STORE_RELEASE,
     171              :      {1, {IRT::MutPtrFirstGeneric, IRT::FirstGeneric}, IRT::Unit}},
     172              :     // pub unsafe fn atomic_store_relaxed<T: Copy>(_dst: *mut T, _val: T);
     173              :     {IValue::ATOMIC_STORE_RELAXED,
     174              :      {1, {IRT::MutPtrFirstGeneric, IRT::FirstGeneric}, IRT::Unit}},
     175              :     // pub unsafe fn atomic_store_unordered<T: Copy>(_dst: *mut T, _val: T);
     176              :     {IValue::ATOMIC_STORE_UNORDERED,
     177              :      {1, {IRT::MutPtrFirstGeneric, IRT::FirstGeneric}, IRT::Unit}},
     178              :     // pub unsafe fn atomic_load_seqcst<T: Copy>(_src: *const T) -> T;
     179              :     {IValue::ATOMIC_LOAD_SEQCST,
     180              :      {1, {IRT::ConstPtrFirstGeneric}, IRT::FirstGeneric}},
     181              :     // pub unsafe fn atomic_load_acquire<T: Copy>(_src: *const T) -> T;
     182              :     {IValue::ATOMIC_LOAD_ACQUIRE,
     183              :      {1, {IRT::ConstPtrFirstGeneric}, IRT::FirstGeneric}},
     184              :     // pub unsafe fn atomic_load_relaxed<T: Copy>(_src: *const T) -> T;
     185              :     {IValue::ATOMIC_LOAD_RELAXED,
     186              :      {1, {IRT::ConstPtrFirstGeneric}, IRT::FirstGeneric}},
     187              :     // pub unsafe fn atomic_load_unordered<T: Copy>(_src: *const T) -> T;
     188              :     {IValue::ATOMIC_LOAD_UNORDERED,
     189              :      {1, {IRT::ConstPtrFirstGeneric}, IRT::FirstGeneric}},
     190              :     // pub fn unchecked_add<T: Copy>(x: T, y: T) -> T;
     191              :     {IValue::UNCHECKED_ADD,
     192              :      {1, {IRT::FirstGeneric, IRT::FirstGeneric}, IRT::FirstGeneric}},
     193              :     // pub fn unchecked_sub<T: Copy>(x: T, y: T) -> T;
     194              :     {IValue::UNCHECKED_SUB,
     195              :      {1, {IRT::FirstGeneric, IRT::FirstGeneric}, IRT::FirstGeneric}},
     196              :     // pub fn unchecked_mul<T: Copy>(x: T, y: T) -> T;
     197              :     {IValue::UNCHECKED_MUL,
     198              :      {1, {IRT::FirstGeneric, IRT::FirstGeneric}, IRT::FirstGeneric}},
     199              :     // pub fn unchecked_div<T: Copy>(x: T, y: T) -> T;
     200              :     {IValue::UNCHECKED_DIV,
     201              :      {1, {IRT::FirstGeneric, IRT::FirstGeneric}, IRT::FirstGeneric}},
     202              :     // pub fn unchecked_rem<T: Copy>(x: T, y: T) -> T;
     203              :     {IValue::UNCHECKED_REM,
     204              :      {1, {IRT::FirstGeneric, IRT::FirstGeneric}, IRT::FirstGeneric}},
     205              :     // pub fn unchecked_shl<T: Copy>(x: T, y: T) -> T;
     206              :     {IValue::UNCHECKED_SHL,
     207              :      {1, {IRT::FirstGeneric, IRT::FirstGeneric}, IRT::FirstGeneric}},
     208              :     // pub fn unchecked_shr<T: Copy>(x: T, y: T) -> T;
     209              :     {IValue::UNCHECKED_SHR,
     210              :      {1, {IRT::FirstGeneric, IRT::FirstGeneric}, IRT::FirstGeneric}},
     211              :     // pub unsafe fn uninit<T>() -> T
     212              :     {IValue::UNINIT, {1, {}, IRT::FirstGeneric}},
     213              :     // pub fn move_val_init<T>(dst: *mut T, src: T);
     214              :     {IValue::MOVE_VAL_INIT,
     215              :      {1, {IRT::MutPtrFirstGeneric, IRT::FirstGeneric}, IRT::Unit}},
     216              :     // pub fn rotate_left<T: Copy>(x: T, y: T) -> T;
     217              :     {IValue::ROTATE_LEFT,
     218              :      {1, {IRT::FirstGeneric, IRT::FirstGeneric}, IRT::FirstGeneric}},
     219              :     // pub fn rotate_right<T: Copy>(x: T, y: T) -> T;
     220              :     {IValue::ROTATE_RIGHT,
     221              :      {1, {IRT::FirstGeneric, IRT::FirstGeneric}, IRT::FirstGeneric}},
     222              :     // pub fn wrapping_add<T: Copy>(a: T, b: T) -> T;
     223              :     {IValue::WRAPPING_ADD,
     224              :      {1, {IRT::FirstGeneric, IRT::FirstGeneric}, IRT::FirstGeneric}},
     225              :     // pub fn wrapping_sub<T: Copy>(a: T, b: T) -> T;
     226              :     {IValue::WRAPPING_SUB,
     227              :      {1, {IRT::FirstGeneric, IRT::FirstGeneric}, IRT::FirstGeneric}},
     228              :     // pub fn wrapping_mul<T: Copy>(a: T, b: T) -> T;
     229              :     {IValue::WRAPPING_MUL,
     230              :      {1, {IRT::FirstGeneric, IRT::FirstGeneric}, IRT::FirstGeneric}},
     231              :     // pub fn saturating_add<T: Copy>(a: T, b: T) -> T;
     232              :     {IValue::SATURATING_ADD,
     233              :      {1, {IRT::FirstGeneric, IRT::FirstGeneric}, IRT::FirstGeneric}},
     234              :     // pub fn saturating_sub<T: Copy>(a: T, b: T) -> T;
     235              :     {IValue::SATURATING_SUB,
     236              :      {1, {IRT::FirstGeneric, IRT::FirstGeneric}, IRT::FirstGeneric}},
     237              :     // pub fn likely(b: bool) -> bool;
     238              :     {IValue::LIKELY, {0, {IRT::Bool}, IRT::Bool}},
     239              :     // pub fn unlikely(b: bool) -> bool;
     240              :     {IValue::UNLIKELY, {0, {IRT::Bool}, IRT::Bool}},
     241              :     // fn discriminant_value<T>(v: &T) -> <T as DiscriminantKind>::Discriminant;
     242              :     {IValue::DISCRIMINANT_VALUE,
     243              :      {1, {IRT::RefFirstGeneric}, IRT::AssocTypePlaceholder}},
     244              :     // pub fn variant_count<T>() -> usize;
     245              :     {IValue::VARIANT_COUNT, {1, {}, IRT::Usize}},
     246              :     // NOTE: The return value was temporarily set to () instead of i32.
     247              :     // pub unsafe fn catch_unwind(
     248              :     //    _try_fn: fn(_: *mut u8),
     249              :     //    _data: *mut u8,
     250              :     //    _catch_fn: fn(_: *mut u8, _: *mut u8),
     251              :     // ) -> i32
     252              :     {IValue::CATCH_UNWIND,
     253              :      {0,
     254              :       {IRT::Fn_MutPtrU8, IRT::MutPtrU8, IRT::Fn_MutPtrU8MutPtrU8},
     255              :       IRT::Unit}},
     256              :     // pub fn r#try(
     257              :     //          try_fn: fn(*mut u8),
     258              :     //          data: *mut u8,
     259              :     //          catch_fn: fn(*mut u8,
     260              :     //          *mut u8)
     261              :     // ) -> i32;
     262              :     {IValue::TRY,
     263              :      {0,
     264              :       {IRT::Fn_MutPtrU8, IRT::MutPtrU8, IRT::Fn_MutPtrU8MutPtrU8},
     265              :       IRT::I32}},
     266              :     // pub fn assume(b: bool);
     267              :     {IValue::ASSUME, {0, {IRT::Bool}, IRT::Unit}},
     268              :     // pub fn min_align_of<T>() -> usize;
     269              :     {IValue::MIN_ALIGN_OF, {1, {}, IRT::Usize}},
     270              :     // pub fn min_align_of_val<T: ?Sized>(_: *const T) -> usize;
     271              :     {IValue::MIN_ALIGN_OF_VAL, {1, {IRT::ConstPtrFirstGeneric}, IRT::Usize}},
     272              :     // pub fn needs_drop<T>() -> bool;
     273              :     {IValue::NEEDS_DROP, {1, {}, IRT::Bool}},
     274              :     // pub fn caller_location() -> &'static crate::panic::Location<'static>;
     275              :     {IValue::CALLER_LOCATION, {0, {}, IRT::RefAdt}},
     276              :     // pub fn ctpop<T: Copy>(x: T) -> T;
     277              :     {IValue::CTPOP, {1, {IRT::FirstGeneric}, IRT::FirstGeneric}},
     278              : 
     279              :     // pub fn ctlz<T: Copy>(x: T) -> T;
     280              :     {IValue::CTLZ, {1, {IRT::FirstGeneric}, IRT::FirstGeneric}},
     281              :     // pub fn ctlz_nonzero<T: Copy>(x: T) -> T;
     282              :     {IValue::CTLZ_NONZERO, {1, {IRT::FirstGeneric}, IRT::FirstGeneric}},
     283              :     // pub fn cttz<T: Copy>(x: T) -> T;
     284              :     {IValue::CTTZ, {1, {IRT::FirstGeneric}, IRT::FirstGeneric}},
     285              :     // pub fn cttz_nonzero<T: Copy>(x: T) -> T;
     286              :     {IValue::CTTZ_NONZERO, {1, {IRT::FirstGeneric}, IRT::FirstGeneric}},
     287              :     // pub fn bswap<T: Copy>(x: T) -> T;
     288              :     {IValue::BSWAP, {1, {IRT::FirstGeneric}, IRT::FirstGeneric}},
     289              :     // pub fn bitreverse<T: Copy>(x: T) -> T;
     290              :     {IValue::BITREVERSE, {1, {IRT::FirstGeneric}, IRT::FirstGeneric}},
     291              :     // pub fn type_id<T: ?Sized + 'static>() -> u64;
     292              :     {IValue::TYPE_ID, {1, {}, IRT::U64}},
     293              :     // pub fn ptr_guaranteed_eq<T>(ptr: *const T, other: *const T) -> bool;
     294              :     {IValue::PTR_GUARANTEED_EQ,
     295              :      {1, {IRT::ConstPtrFirstGeneric, IRT::ConstPtrFirstGeneric}, IRT::Bool}},
     296              :     // pub fn ptr_guaranteed_ne<T>(ptr: *const T, other: *const T) -> bool;
     297              :     {IValue::PTR_GUARANTEED_NE,
     298              :      {1, {IRT::ConstPtrFirstGeneric, IRT::ConstPtrFirstGeneric}, IRT::Bool}},
     299              :     // pub fn rustc_peek<T>(_: T) -> T;
     300              :     {IValue::RUSTC_PEEK, {1, {IRT::FirstGeneric}, IRT::FirstGeneric}},
     301              :     // pub fn type_name<T: ?Sized>() -> &'static str;
     302              :     {IValue::TYPE_NAME, {1, {}, IRT::RefStaticStr}},
     303              :     // pub fn forget<T: ?Sized>(_: T);
     304              :     {IValue::FORGET, {1, {IRT::FirstGeneric}, IRT::Unit}},
     305              :     // pub fn black_box<T>(mut dummy: T) -> T
     306              :     {IValue::BLACK_BOX, {1, {IRT::FirstGeneric}, IRT::FirstGeneric}},
     307              : 
     308              :     // pub fn arith_offset<T>(dst: *const T, offset: isize) -> *const T;
     309              :     {IValue::ARITH_OFFSET,
     310              :      {1, {IRT::ConstPtrFirstGeneric, IRT::Isize}, IRT::ConstPtrFirstGeneric}},
     311              :     // fn write_bytes<T>(dst: *mut T, val: u8, count: usize)
     312              :     {IValue::WRITE_BYTES,
     313              :      {1, {IRT::MutPtrFirstGeneric, IRT::U8, IRT::Usize}, IRT::Unit}},
     314              :     // pub fn assert_zero_valid<T>();
     315              :     {IValue::ASSERT_ZERO_VALID, {1, {}, IRT::Unit}},
     316              : };
     317              : 
     318              : IntrinsicCheckResult
     319         1441 : IntrinsicChecker::check (const TyTy::FnType *fntype)
     320              : {
     321         2882 :   auto it = intrinsic_rules.find (fntype->get_identifier ());
     322         1441 :   if (it == intrinsic_rules.end ())
     323              :     {
     324           16 :       rust_error_at (fntype->get_locus (), ErrorCode::E0093,
     325              :                      "unrecognized intrinsic function: %qs",
     326            8 :                      fntype->get_identifier ().c_str ());
     327            8 :       return IntrinsicCheckResult::Invalid;
     328              :     }
     329         1433 :   auto rule = &it->second;
     330              : 
     331         1433 :   if (fntype->get_substs ().size () != rule->generic_count)
     332              :     {
     333            3 :       rust_error_at (fntype->get_locus (), ErrorCode::E0094,
     334              :                      "intrinsic has wrong number of type parameters: found "
     335              :                      "%lu, expected %lu",
     336            1 :                      (unsigned long) fntype->get_substs ().size (),
     337              :                      (unsigned long) rule->generic_count);
     338            1 :       return IntrinsicCheckResult::Invalid;
     339              :     }
     340              : 
     341         1432 :   IntrinsicCheckResult result = IntrinsicCheckResult::Valid;
     342              : 
     343         1432 :   if (fntype->get_num_params () != rule->param_types.size ())
     344              :     {
     345            3 :       rust_error_at (fntype->get_locus (), ErrorCode::E0308,
     346              :                      "intrinsic has wrong number of function parameters: found "
     347              :                      "%lu, expected %lu",
     348            1 :                      (unsigned long) fntype->get_params ().size (),
     349            1 :                      (unsigned long) rule->param_types.size ());
     350            1 :       result = IntrinsicCheckResult::Invalid;
     351              :     }
     352              :   else
     353              :     {
     354         3240 :       for (size_t i = 0; i < rule->param_types.size (); i++)
     355              :         {
     356         1809 :           const TyTy::BaseType *actual_param
     357         1809 :             = fntype->get_params ().at (i).get_type ();
     358         1809 :           IntrinsicRuleType expected_type = rule->param_types.at (i);
     359              : 
     360         1809 :           if (!check_type (actual_param, expected_type, fntype))
     361              :             {
     362            3 :               rust_error_at (fntype->get_locus (), ErrorCode::E0308,
     363              :                              "intrinsic has wrong type");
     364            3 :               result = IntrinsicCheckResult::Invalid;
     365              :             }
     366              :         }
     367              :     }
     368              : 
     369         1432 :   if (!check_type (fntype->get_return_type (), rule->return_type, fntype))
     370              :     {
     371            2 :       rust_error_at (fntype->get_locus (), ErrorCode::E0308,
     372              :                      "intrinsic has wrong type");
     373            2 :       result = IntrinsicCheckResult::Invalid;
     374              :     }
     375              : 
     376         1432 :   if (result == IntrinsicCheckResult::Invalid)
     377              :     {
     378            5 :       rust_inform (fntype->get_locus (), "expected fn pointer %qs",
     379            5 :                    expected_intrinsic_as_string (fntype).c_str ());
     380            5 :       rust_inform (fntype->get_locus (), "   found fn pointer %qs",
     381           10 :                    found_intrinsic_as_string (fntype).c_str ());
     382              :     }
     383              :   return result;
     384              : }
     385              : 
     386              : bool
     387         3294 : IntrinsicChecker::check_type (const TyTy::BaseType *actual,
     388              :                               IntrinsicRuleType expected,
     389              :                               const TyTy::FnType *fntype)
     390              : {
     391         3808 :   switch (expected)
     392              :     {
     393            1 :     case IRT::Bool:
     394            1 :       return actual->get_kind () == TyTy::TypeKind::BOOL;
     395          336 :     case IRT::F32:
     396          336 :       return actual->get_kind () == TyTy::TypeKind::FLOAT
     397          336 :              && static_cast<const TyTy::FloatType *> (actual)->get_float_kind ()
     398              :                   == TyTy::FloatType::FloatKind::F32;
     399          336 :     case IRT::F64:
     400          336 :       return actual->get_kind () == TyTy::TypeKind::FLOAT
     401          336 :              && static_cast<const TyTy::FloatType *> (actual)->get_float_kind ()
     402              :                   == TyTy::FloatType::FloatKind::F64;
     403           29 :     case IRT::I32:
     404           29 :       return actual->get_kind () == TyTy::TypeKind::INT
     405           29 :              && static_cast<const TyTy::IntType *> (actual)->get_int_kind ()
     406              :                   == TyTy::IntType::IntKind::I32;
     407          107 :     case IRT::Isize:
     408          107 :       return actual->get_kind () == TyTy::TypeKind::ISIZE;
     409           12 :     case IRT::U8:
     410           12 :       return actual->get_kind () == TyTy::TypeKind::UINT
     411           12 :              && static_cast<const TyTy::UintType *> (actual)->get_uint_kind ()
     412              :                   == TyTy::UintType::UintKind::U8;
     413            0 :     case IRT::U64:
     414            0 :       return actual->get_kind () == TyTy::TypeKind::UINT
     415            0 :              && static_cast<const TyTy::UintType *> (actual)->get_uint_kind ()
     416              :                   == TyTy::UintType::UintKind::U64;
     417          138 :     case IRT::Usize:
     418          138 :       return actual->get_kind () == TyTy::TypeKind::USIZE;
     419          149 :     case IRT::Unit:
     420          149 :       return actual->is_unit ();
     421          156 :     case IRT::Never:
     422          156 :       return actual->get_kind () == TyTy::TypeKind::NEVER;
     423              : 
     424         1906 :     case IRT::FirstGeneric:
     425         1906 :     case IRT::SecondGeneric:
     426         1906 :       {
     427         1906 :         if (actual->get_kind () != TyTy::TypeKind::PARAM)
     428              :           return false;
     429              : 
     430         1904 :         auto param = static_cast<const TyTy::ParamType *> (actual);
     431         1904 :         size_t expected_index = (expected == IRT::FirstGeneric) ? 0 : 1;
     432         1904 :         if (fntype->get_substs ().size () <= expected_index)
     433              :           return false;
     434         1904 :         auto expected_param
     435         1904 :           = fntype->get_substs ().at (expected_index).get_param_ty ();
     436         1904 :         return param->get_ty_ref () == expected_param->get_ty_ref ();
     437              :       }
     438          299 :     case IRT::ConstPtrFirstGeneric:
     439          299 :       {
     440          299 :         if (actual->get_kind () != TyTy::TypeKind::POINTER)
     441              :           return false;
     442          298 :         auto ptr = static_cast<const TyTy::PointerType *> (actual);
     443          298 :         if (!ptr->is_const ())
     444              :           return false;
     445          298 :         return check_type (ptr->get_base (), IntrinsicRuleType::FirstGeneric,
     446          298 :                            fntype);
     447              :       }
     448          131 :     case IRT::MutPtrFirstGeneric:
     449          131 :       {
     450          131 :         if (actual->get_kind () != TyTy::TypeKind::POINTER)
     451              :           return false;
     452          131 :         auto ptr = static_cast<const TyTy::PointerType *> (actual);
     453          131 :         if (!ptr->is_mutable ())
     454              :           return false;
     455          131 :         return check_type (ptr->get_base (), IntrinsicRuleType::FirstGeneric,
     456          131 :                            fntype);
     457              :       }
     458           72 :     case IRT::RefFirstGeneric:
     459           72 :       {
     460           72 :         if (actual->get_kind () != TyTy::TypeKind::REF)
     461              :           return false;
     462           72 :         auto ref = static_cast<const TyTy::ReferenceType *> (actual);
     463           72 :         if (ref->is_mutable ())
     464              :           return false;
     465           72 :         return check_type (ref->get_base (), IntrinsicRuleType::FirstGeneric,
     466           72 :                            fntype);
     467              :       }
     468            0 :     case IRT::RefAdt:
     469            0 :       {
     470            0 :         if (actual->get_kind () != TyTy::TypeKind::REF)
     471              :           return false;
     472            0 :         auto ref = static_cast<const TyTy::ReferenceType *> (actual);
     473            0 :         if (ref->is_mutable ())
     474              :           return false;
     475            0 :         return ref->get_base ()->get_kind () == TyTy::TypeKind::ADT;
     476              :       }
     477           11 :     case IRT::MutPtrU8:
     478           11 :       {
     479           11 :         if (actual->get_kind () != TyTy::TypeKind::POINTER)
     480              :           return false;
     481           11 :         auto ptr = static_cast<const TyTy::PointerType *> (actual);
     482           11 :         if (!ptr->is_mutable ())
     483              :           return false;
     484           11 :         return check_type (ptr->get_base (), IRT::U8, fntype);
     485              :       }
     486            0 :     case IRT::RefStaticStr:
     487            0 :       {
     488            0 :         if (actual->get_kind () != TyTy::TypeKind::REF)
     489              :           return false;
     490            0 :         auto ref = static_cast<const TyTy::ReferenceType *> (actual);
     491            0 :         if (ref->is_mutable ())
     492              :           return false;
     493            0 :         return ref->get_base ()->get_kind () == TyTy::TypeKind::STR;
     494              :       }
     495              :     case IRT::AssocTypePlaceholder:
     496              :       return true;
     497              : 
     498           47 :     case IRT::TupleFirstGenericAndBool:
     499           47 :       {
     500           47 :         if (actual->get_kind () != TyTy::TypeKind::TUPLE)
     501              :           return false;
     502           47 :         auto tuple = static_cast<const TyTy::TupleType *> (actual);
     503           47 :         if (tuple->num_fields () != 2)
     504              :           return false;
     505           47 :         return tuple->get_field (1)->get_kind () == TyTy::TypeKind::BOOL
     506           47 :                && check_type (tuple->get_field (0),
     507              :                               IntrinsicRuleType::FirstGeneric, fntype);
     508              :       }
     509              : 
     510            3 :     case IRT::Fn_MutPtrU8:
     511            3 :       {
     512            3 :         if (actual->get_kind () != TyTy::TypeKind::FNPTR)
     513              :           return false;
     514            2 :         auto fn = static_cast<const TyTy::FnPtr *> (actual);
     515            2 :         if (!fn->get_return_type ()->is_unit ())
     516              :           return false;
     517            2 :         if (fn->get_num_params () != 1)
     518              :           return false;
     519            2 :         return check_type (fn->get_param_type_at (0), IRT::MutPtrU8, fntype);
     520              :       }
     521            3 :     case IRT::Fn_MutPtrU8MutPtrU8:
     522            3 :       {
     523            3 :         if (actual->get_kind () != TyTy::TypeKind::FNPTR)
     524              :           return false;
     525            3 :         auto fn = static_cast<const TyTy::FnPtr *> (actual);
     526            3 :         if (!fn->get_return_type ()->is_unit ())
     527              :           return false;
     528            3 :         if (fn->get_num_params () != 2)
     529              :           return false;
     530            3 :         return check_type (fn->get_param_type_at (0), IRT::MutPtrU8, fntype)
     531            3 :                && check_type (fn->get_param_type_at (1), IRT::MutPtrU8, fntype);
     532              :       }
     533              : 
     534            0 :     default:
     535            0 :       rust_unreachable ();
     536              :     };
     537              :   return true;
     538              : }
     539              : 
     540              : static std::string
     541           22 : to_string (const TyTy::BaseType *type, const TyTy::FnType *fntype)
     542              : {
     543           22 :   switch (type->get_kind ())
     544              :     {
     545            1 :     case TyTy::TypeKind::BOOL:
     546            1 :       return "bool";
     547            3 :     case TyTy::TypeKind::USIZE:
     548            3 :       return "usize";
     549            1 :     case TyTy::TypeKind::ISIZE:
     550            1 :       return "isize";
     551            1 :     case TyTy::TypeKind::NEVER:
     552            1 :       return "!";
     553            0 :     case TyTy::TypeKind::STR:
     554            0 :       return "str";
     555              : 
     556            3 :     case TyTy::TypeKind::INT:
     557            3 :       {
     558            3 :         auto int_ty = static_cast<const TyTy::IntType *> (type);
     559            3 :         switch (int_ty->get_int_kind ())
     560              :           {
     561            0 :           case TyTy::IntType::IntKind::I8:
     562            0 :             return "i8";
     563            0 :           case TyTy::IntType::IntKind::I16:
     564            0 :             return "i16";
     565            3 :           case TyTy::IntType::IntKind::I32:
     566            3 :             return "i32";
     567            0 :           case TyTy::IntType::IntKind::I64:
     568            0 :             return "i64";
     569            0 :           case TyTy::IntType::IntKind::I128:
     570            0 :             return "i128";
     571              :           }
     572            0 :         rust_unreachable ();
     573              :       }
     574              : 
     575            3 :     case TyTy::TypeKind::UINT:
     576            3 :       {
     577            3 :         auto uint_ty = static_cast<const TyTy::UintType *> (type);
     578            3 :         switch (uint_ty->get_uint_kind ())
     579              :           {
     580            3 :           case TyTy::UintType::UintKind::U8:
     581            3 :             return "u8";
     582            0 :           case TyTy::UintType::UintKind::U16:
     583            0 :             return "u16";
     584            0 :           case TyTy::UintType::UintKind::U32:
     585            0 :             return "u32";
     586            0 :           case TyTy::UintType::UintKind::U64:
     587            0 :             return "u64";
     588            0 :           case TyTy::UintType::UintKind::U128:
     589            0 :             return "u128";
     590              :           }
     591            0 :         rust_unreachable ();
     592              :       }
     593              : 
     594            0 :     case TyTy::TypeKind::FLOAT:
     595            0 :       {
     596            0 :         auto float_ty = static_cast<const TyTy::FloatType *> (type);
     597            0 :         switch (float_ty->get_float_kind ())
     598              :           {
     599            0 :           case TyTy::FloatType::FloatKind::F32:
     600            0 :             return "f32";
     601            0 :           case TyTy::FloatType::FloatKind::F64:
     602            0 :             return "f64";
     603              :           }
     604            0 :         rust_unreachable ();
     605              :       }
     606              : 
     607            4 :     case TyTy::TypeKind::PARAM:
     608            4 :       {
     609            4 :         auto param = static_cast<const TyTy::ParamType *> (type);
     610            4 :         if (fntype != nullptr)
     611              :           {
     612            4 :             auto substs = fntype->get_substs ();
     613            8 :             for (size_t i = 0; i < substs.size (); i++)
     614              :               {
     615            8 :                 if (substs[i].get_param_ty ()->get_ty_ref ()
     616            4 :                     == param->get_ty_ref ())
     617            4 :                   return "P" + std::to_string (i);
     618              :               }
     619            4 :           }
     620            0 :         return param->get_symbol ();
     621              :       }
     622              : 
     623            4 :     case TyTy::TypeKind::POINTER:
     624            4 :       {
     625            4 :         auto ptr = static_cast<const TyTy::PointerType *> (type);
     626            4 :         std::string prefix = ptr->is_mutable () ? "*mut "
     627            1 :                              : ptr->is_const () ? "*const "
     628            5 :                                                 : "*";
     629            4 :         return prefix + to_string (ptr->get_base (), fntype);
     630            4 :       }
     631              : 
     632            0 :     case TyTy::TypeKind::REF:
     633            0 :       {
     634            0 :         auto ref = static_cast<const TyTy::ReferenceType *> (type);
     635            0 :         std::string prefix = ref->is_mutable () ? "&mut " : "&";
     636            0 :         return prefix + to_string (ref->get_base (), fntype);
     637            0 :       }
     638              : 
     639            1 :     case TyTy::TypeKind::TUPLE:
     640            1 :       {
     641            1 :         auto tuple = static_cast<const TyTy::TupleType *> (type);
     642            1 :         if (tuple->num_fields () == 0)
     643            0 :           return "()";
     644              : 
     645            1 :         std::string res = "(";
     646            3 :         for (size_t i = 0; i < tuple->num_fields (); i++)
     647              :           {
     648            2 :             if (i > 0)
     649            1 :               res += ", ";
     650            4 :             res += to_string (tuple->get_field (i), fntype);
     651              :           }
     652            1 :         res += ")";
     653            1 :         return res;
     654            1 :       }
     655              : 
     656            1 :     case TyTy::TypeKind::FNPTR:
     657            1 :       {
     658            1 :         auto fnptr = static_cast<const TyTy::FnPtr *> (type);
     659            1 :         std::string res = "fn(";
     660            3 :         for (size_t i = 0; i < fnptr->get_num_params (); i++)
     661              :           {
     662            2 :             if (i > 0)
     663            1 :               res += ", ";
     664            4 :             res += to_string (fnptr->get_param_type_at (i), fntype);
     665              :           }
     666            1 :         res += ")";
     667            1 :         if (!fnptr->get_return_type ()->is_unit ()
     668            1 :             || fnptr->get_return_type ()->get_kind () == TyTy::TypeKind::NEVER)
     669              :           {
     670            0 :             res += " -> ";
     671            0 :             res += to_string (fnptr->get_return_type (), fntype);
     672              :           }
     673            1 :         return res;
     674            1 :       }
     675              : 
     676            0 :     case TyTy::TypeKind::ADT:
     677            0 :       {
     678            0 :         auto adt = static_cast<const TyTy::ADTType *> (type);
     679            0 :         return adt->get_name ();
     680              :       }
     681              : 
     682            0 :     case TyTy::TypeKind::PLACEHOLDER:
     683            0 :       {
     684            0 :         auto ph = static_cast<const TyTy::PlaceholderType *> (type);
     685            0 :         return "<" + ph->get_symbol () + ">";
     686              :       }
     687              : 
     688            0 :     default:
     689            0 :       return type->as_string ();
     690              :     }
     691              : }
     692              : 
     693              : static std::string
     694           12 : to_string (IntrinsicRuleType ty)
     695              : {
     696           12 :   switch (ty)
     697              :     {
     698            0 :     case IRT::Bool:
     699            0 :       return "bool";
     700            0 :     case IRT::F32:
     701            0 :       return "f32";
     702            0 :     case IRT::F64:
     703            0 :       return "f64";
     704            0 :     case IRT::I32:
     705            0 :       return "i32";
     706            1 :     case IRT::Isize:
     707            1 :       return "isize";
     708            0 :     case IRT::U8:
     709            0 :       return "u8";
     710            0 :     case IRT::U64:
     711            0 :       return "u64";
     712            0 :     case IRT::Usize:
     713            0 :       return "usize";
     714            0 :     case IRT::Unit:
     715            0 :       return "()";
     716            1 :     case IRT::Never:
     717            1 :       return "!";
     718              : 
     719            3 :     case IRT::FirstGeneric:
     720            3 :       return "P0";
     721            1 :     case IRT::SecondGeneric:
     722            1 :       return "P1";
     723              : 
     724            2 :     case IRT::ConstPtrFirstGeneric:
     725            2 :       return "*const P0";
     726            0 :     case IRT::MutPtrFirstGeneric:
     727            0 :       return "*mut P0";
     728            0 :     case IRT::RefFirstGeneric:
     729            0 :       return "&P0";
     730              : 
     731            0 :     case IRT::RefAdt:
     732            0 :       return "&<ADT>";
     733            1 :     case IRT::MutPtrU8:
     734            1 :       return "*mut u8";
     735            0 :     case IRT::RefStaticStr:
     736            0 :       return "&'static str";
     737            0 :     case IRT::AssocTypePlaceholder:
     738            0 :       return "<AssocType>";
     739              : 
     740            1 :     case IRT::TupleFirstGenericAndBool:
     741            1 :       return "(P0, bool)";
     742              : 
     743            1 :     case IRT::Fn_MutPtrU8:
     744            1 :       return "fn(*mut u8)";
     745            1 :     case IRT::Fn_MutPtrU8MutPtrU8:
     746            1 :       return "fn(*mut u8, *mut u8)";
     747            0 :     };
     748            0 :   rust_unreachable ();
     749              : }
     750              : 
     751              : std::string
     752            5 : IntrinsicChecker::expected_intrinsic_as_string (const TyTy::FnType *fntype)
     753              : {
     754           10 :   auto it = intrinsic_rules.find (fntype->get_identifier ());
     755            5 :   rust_assert (it != intrinsic_rules.end ());
     756            5 :   auto rule = &it->second;
     757            5 :   std::stringstream result;
     758            5 :   result << "extern \"rust-intrinsic\" fn(";
     759            5 :   if (rule->param_types.size () > 0)
     760              :     {
     761           12 :       for (size_t i = 0; i < rule->param_types.size (); i++)
     762              :         {
     763            8 :           if (i != 0)
     764            4 :             result << ", ";
     765           16 :           result << to_string (rule->param_types.at (i));
     766              :         }
     767              :     }
     768            5 :   result << ")";
     769            5 :   if (rule->return_type != IntrinsicRuleType::Unit)
     770              :     {
     771            8 :       result << " -> " << to_string (rule->return_type);
     772              :     }
     773            5 :   return result.str ();
     774            5 : }
     775              : 
     776              : std::string
     777            5 : IntrinsicChecker::found_intrinsic_as_string (const TyTy::FnType *fntype)
     778              : {
     779            5 :   std::stringstream result;
     780            5 :   result << "extern \"rust-intrinsic\" fn(";
     781            5 :   if (fntype->get_num_params () > 0)
     782              :     {
     783            5 :       const auto &params = fntype->get_params ();
     784           14 :       for (size_t i = 0; i < params.size (); i++)
     785              :         {
     786            9 :           if (i != 0)
     787            4 :             result << ", ";
     788           18 :           result << to_string (params.at (i).get_type (), fntype);
     789              :         }
     790              :     }
     791            5 :   result << ")";
     792            5 :   if (!fntype->get_return_type ()->is_unit ()
     793            5 :       || fntype->get_return_type ()->get_kind () == TyTy::TypeKind::NEVER)
     794              :     {
     795           10 :       result << " -> " << to_string (fntype->get_return_type (), fntype);
     796              :     }
     797            5 :   return result.str ();
     798            5 : }
     799              : 
     800              : } // namespace Resolver
     801              : } // namespace Rust
        

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.