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-07-11 15:47:05 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              : 
     315              : };
     316              : 
     317              : IntrinsicCheckResult
     318         1439 : IntrinsicChecker::check (const TyTy::FnType *fntype)
     319              : {
     320         2878 :   auto it = intrinsic_rules.find (fntype->get_identifier ());
     321         1439 :   if (it == intrinsic_rules.end ())
     322              :     {
     323           16 :       rust_error_at (fntype->get_locus (), ErrorCode::E0093,
     324              :                      "unrecognized intrinsic function: %qs",
     325            8 :                      fntype->get_identifier ().c_str ());
     326            8 :       return IntrinsicCheckResult::Invalid;
     327              :     }
     328         1431 :   auto rule = &it->second;
     329              : 
     330         1431 :   if (fntype->get_substs ().size () != rule->generic_count)
     331              :     {
     332            3 :       rust_error_at (fntype->get_locus (), ErrorCode::E0094,
     333              :                      "intrinsic has wrong number of type parameters: found "
     334              :                      "%lu, expected %lu",
     335            1 :                      (unsigned long) fntype->get_substs ().size (),
     336              :                      (unsigned long) rule->generic_count);
     337            1 :       return IntrinsicCheckResult::Invalid;
     338              :     }
     339              : 
     340         1430 :   IntrinsicCheckResult result = IntrinsicCheckResult::Valid;
     341              : 
     342         1430 :   if (fntype->get_num_params () != rule->param_types.size ())
     343              :     {
     344            3 :       rust_error_at (fntype->get_locus (), ErrorCode::E0308,
     345              :                      "intrinsic has wrong number of function parameters: found "
     346              :                      "%lu, expected %lu",
     347            1 :                      (unsigned long) fntype->get_params ().size (),
     348            1 :                      (unsigned long) rule->param_types.size ());
     349            1 :       result = IntrinsicCheckResult::Invalid;
     350              :     }
     351              :   else
     352              :     {
     353         3236 :       for (size_t i = 0; i < rule->param_types.size (); i++)
     354              :         {
     355         1807 :           const TyTy::BaseType *actual_param
     356         1807 :             = fntype->get_params ().at (i).get_type ();
     357         1807 :           IntrinsicRuleType expected_type = rule->param_types.at (i);
     358              : 
     359         1807 :           if (!check_type (actual_param, expected_type, fntype))
     360              :             {
     361            3 :               rust_error_at (fntype->get_locus (), ErrorCode::E0308,
     362              :                              "intrinsic has wrong type");
     363            3 :               result = IntrinsicCheckResult::Invalid;
     364              :             }
     365              :         }
     366              :     }
     367              : 
     368         1430 :   if (!check_type (fntype->get_return_type (), rule->return_type, fntype))
     369              :     {
     370            2 :       rust_error_at (fntype->get_locus (), ErrorCode::E0308,
     371              :                      "intrinsic has wrong type");
     372            2 :       result = IntrinsicCheckResult::Invalid;
     373              :     }
     374              : 
     375         1430 :   if (result == IntrinsicCheckResult::Invalid)
     376              :     {
     377            5 :       rust_inform (fntype->get_locus (), "expected fn pointer %qs",
     378            5 :                    expected_intrinsic_as_string (fntype).c_str ());
     379            5 :       rust_inform (fntype->get_locus (), "   found fn pointer %qs",
     380           10 :                    found_intrinsic_as_string (fntype).c_str ());
     381              :     }
     382              :   return result;
     383              : }
     384              : 
     385              : bool
     386         3290 : IntrinsicChecker::check_type (const TyTy::BaseType *actual,
     387              :                               IntrinsicRuleType expected,
     388              :                               const TyTy::FnType *fntype)
     389              : {
     390         3802 :   switch (expected)
     391              :     {
     392            1 :     case IRT::Bool:
     393            1 :       return actual->get_kind () == TyTy::TypeKind::BOOL;
     394          336 :     case IRT::F32:
     395          336 :       return actual->get_kind () == TyTy::TypeKind::FLOAT
     396          336 :              && static_cast<const TyTy::FloatType *> (actual)->get_float_kind ()
     397              :                   == TyTy::FloatType::FloatKind::F32;
     398          336 :     case IRT::F64:
     399          336 :       return actual->get_kind () == TyTy::TypeKind::FLOAT
     400          336 :              && static_cast<const TyTy::FloatType *> (actual)->get_float_kind ()
     401              :                   == TyTy::FloatType::FloatKind::F64;
     402           29 :     case IRT::I32:
     403           29 :       return actual->get_kind () == TyTy::TypeKind::INT
     404           29 :              && static_cast<const TyTy::IntType *> (actual)->get_int_kind ()
     405              :                   == TyTy::IntType::IntKind::I32;
     406          106 :     case IRT::Isize:
     407          106 :       return actual->get_kind () == TyTy::TypeKind::ISIZE;
     408           12 :     case IRT::U8:
     409           12 :       return actual->get_kind () == TyTy::TypeKind::UINT
     410           12 :              && static_cast<const TyTy::UintType *> (actual)->get_uint_kind ()
     411              :                   == TyTy::UintType::UintKind::U8;
     412            0 :     case IRT::U64:
     413            0 :       return actual->get_kind () == TyTy::TypeKind::UINT
     414            0 :              && static_cast<const TyTy::UintType *> (actual)->get_uint_kind ()
     415              :                   == TyTy::UintType::UintKind::U64;
     416          138 :     case IRT::Usize:
     417          138 :       return actual->get_kind () == TyTy::TypeKind::USIZE;
     418          148 :     case IRT::Unit:
     419          148 :       return actual->is_unit ();
     420          156 :     case IRT::Never:
     421          156 :       return actual->get_kind () == TyTy::TypeKind::NEVER;
     422              : 
     423         1904 :     case IRT::FirstGeneric:
     424         1904 :     case IRT::SecondGeneric:
     425         1904 :       {
     426         1904 :         if (actual->get_kind () != TyTy::TypeKind::PARAM)
     427              :           return false;
     428              : 
     429         1902 :         auto param = static_cast<const TyTy::ParamType *> (actual);
     430         1902 :         size_t expected_index = (expected == IRT::FirstGeneric) ? 0 : 1;
     431         1902 :         if (fntype->get_substs ().size () <= expected_index)
     432              :           return false;
     433         1902 :         auto expected_param
     434         1902 :           = fntype->get_substs ().at (expected_index).get_param_ty ();
     435         1902 :         return param->get_ty_ref () == expected_param->get_ty_ref ();
     436              :       }
     437          297 :     case IRT::ConstPtrFirstGeneric:
     438          297 :       {
     439          297 :         if (actual->get_kind () != TyTy::TypeKind::POINTER)
     440              :           return false;
     441          296 :         auto ptr = static_cast<const TyTy::PointerType *> (actual);
     442          296 :         if (!ptr->is_const ())
     443              :           return false;
     444          296 :         return check_type (ptr->get_base (), IntrinsicRuleType::FirstGeneric,
     445          296 :                            fntype);
     446              :       }
     447          131 :     case IRT::MutPtrFirstGeneric:
     448          131 :       {
     449          131 :         if (actual->get_kind () != TyTy::TypeKind::POINTER)
     450              :           return false;
     451          131 :         auto ptr = static_cast<const TyTy::PointerType *> (actual);
     452          131 :         if (!ptr->is_mutable ())
     453              :           return false;
     454          131 :         return check_type (ptr->get_base (), IntrinsicRuleType::FirstGeneric,
     455          131 :                            fntype);
     456              :       }
     457           72 :     case IRT::RefFirstGeneric:
     458           72 :       {
     459           72 :         if (actual->get_kind () != TyTy::TypeKind::REF)
     460              :           return false;
     461           72 :         auto ref = static_cast<const TyTy::ReferenceType *> (actual);
     462           72 :         if (ref->is_mutable ())
     463              :           return false;
     464           72 :         return check_type (ref->get_base (), IntrinsicRuleType::FirstGeneric,
     465           72 :                            fntype);
     466              :       }
     467            0 :     case IRT::RefAdt:
     468            0 :       {
     469            0 :         if (actual->get_kind () != TyTy::TypeKind::REF)
     470              :           return false;
     471            0 :         auto ref = static_cast<const TyTy::ReferenceType *> (actual);
     472            0 :         if (ref->is_mutable ())
     473              :           return false;
     474            0 :         return ref->get_base ()->get_kind () == TyTy::TypeKind::ADT;
     475              :       }
     476           11 :     case IRT::MutPtrU8:
     477           11 :       {
     478           11 :         if (actual->get_kind () != TyTy::TypeKind::POINTER)
     479              :           return false;
     480           11 :         auto ptr = static_cast<const TyTy::PointerType *> (actual);
     481           11 :         if (!ptr->is_mutable ())
     482              :           return false;
     483           11 :         return check_type (ptr->get_base (), IRT::U8, fntype);
     484              :       }
     485            0 :     case IRT::RefStaticStr:
     486            0 :       {
     487            0 :         if (actual->get_kind () != TyTy::TypeKind::REF)
     488              :           return false;
     489            0 :         auto ref = static_cast<const TyTy::ReferenceType *> (actual);
     490            0 :         if (ref->is_mutable ())
     491              :           return false;
     492            0 :         return ref->get_base ()->get_kind () == TyTy::TypeKind::STR;
     493              :       }
     494              :     case IRT::AssocTypePlaceholder:
     495              :       return true;
     496              : 
     497           47 :     case IRT::TupleFirstGenericAndBool:
     498           47 :       {
     499           47 :         if (actual->get_kind () != TyTy::TypeKind::TUPLE)
     500              :           return false;
     501           47 :         auto tuple = static_cast<const TyTy::TupleType *> (actual);
     502           47 :         if (tuple->num_fields () != 2)
     503              :           return false;
     504           47 :         return tuple->get_field (1)->get_kind () == TyTy::TypeKind::BOOL
     505           47 :                && check_type (tuple->get_field (0),
     506              :                               IntrinsicRuleType::FirstGeneric, fntype);
     507              :       }
     508              : 
     509            3 :     case IRT::Fn_MutPtrU8:
     510            3 :       {
     511            3 :         if (actual->get_kind () != TyTy::TypeKind::FNPTR)
     512              :           return false;
     513            2 :         auto fn = static_cast<const TyTy::FnPtr *> (actual);
     514            2 :         if (!fn->get_return_type ()->is_unit ())
     515              :           return false;
     516            2 :         if (fn->get_num_params () != 1)
     517              :           return false;
     518            2 :         return check_type (fn->get_param_type_at (0), IRT::MutPtrU8, fntype);
     519              :       }
     520            3 :     case IRT::Fn_MutPtrU8MutPtrU8:
     521            3 :       {
     522            3 :         if (actual->get_kind () != TyTy::TypeKind::FNPTR)
     523              :           return false;
     524            3 :         auto fn = static_cast<const TyTy::FnPtr *> (actual);
     525            3 :         if (!fn->get_return_type ()->is_unit ())
     526              :           return false;
     527            3 :         if (fn->get_num_params () != 2)
     528              :           return false;
     529            3 :         return check_type (fn->get_param_type_at (0), IRT::MutPtrU8, fntype)
     530            3 :                && check_type (fn->get_param_type_at (1), IRT::MutPtrU8, fntype);
     531              :       }
     532              : 
     533            0 :     default:
     534            0 :       rust_unreachable ();
     535              :     };
     536              :   return true;
     537              : }
     538              : 
     539              : static std::string
     540           22 : to_string (const TyTy::BaseType *type, const TyTy::FnType *fntype)
     541              : {
     542           22 :   switch (type->get_kind ())
     543              :     {
     544            1 :     case TyTy::TypeKind::BOOL:
     545            1 :       return "bool";
     546            3 :     case TyTy::TypeKind::USIZE:
     547            3 :       return "usize";
     548            1 :     case TyTy::TypeKind::ISIZE:
     549            1 :       return "isize";
     550            1 :     case TyTy::TypeKind::NEVER:
     551            1 :       return "!";
     552            0 :     case TyTy::TypeKind::STR:
     553            0 :       return "str";
     554              : 
     555            3 :     case TyTy::TypeKind::INT:
     556            3 :       {
     557            3 :         auto int_ty = static_cast<const TyTy::IntType *> (type);
     558            3 :         switch (int_ty->get_int_kind ())
     559              :           {
     560            0 :           case TyTy::IntType::IntKind::I8:
     561            0 :             return "i8";
     562            0 :           case TyTy::IntType::IntKind::I16:
     563            0 :             return "i16";
     564            3 :           case TyTy::IntType::IntKind::I32:
     565            3 :             return "i32";
     566            0 :           case TyTy::IntType::IntKind::I64:
     567            0 :             return "i64";
     568            0 :           case TyTy::IntType::IntKind::I128:
     569            0 :             return "i128";
     570              :           }
     571            0 :         rust_unreachable ();
     572              :       }
     573              : 
     574            3 :     case TyTy::TypeKind::UINT:
     575            3 :       {
     576            3 :         auto uint_ty = static_cast<const TyTy::UintType *> (type);
     577            3 :         switch (uint_ty->get_uint_kind ())
     578              :           {
     579            3 :           case TyTy::UintType::UintKind::U8:
     580            3 :             return "u8";
     581            0 :           case TyTy::UintType::UintKind::U16:
     582            0 :             return "u16";
     583            0 :           case TyTy::UintType::UintKind::U32:
     584            0 :             return "u32";
     585            0 :           case TyTy::UintType::UintKind::U64:
     586            0 :             return "u64";
     587            0 :           case TyTy::UintType::UintKind::U128:
     588            0 :             return "u128";
     589              :           }
     590            0 :         rust_unreachable ();
     591              :       }
     592              : 
     593            0 :     case TyTy::TypeKind::FLOAT:
     594            0 :       {
     595            0 :         auto float_ty = static_cast<const TyTy::FloatType *> (type);
     596            0 :         switch (float_ty->get_float_kind ())
     597              :           {
     598            0 :           case TyTy::FloatType::FloatKind::F32:
     599            0 :             return "f32";
     600            0 :           case TyTy::FloatType::FloatKind::F64:
     601            0 :             return "f64";
     602              :           }
     603            0 :         rust_unreachable ();
     604              :       }
     605              : 
     606            4 :     case TyTy::TypeKind::PARAM:
     607            4 :       {
     608            4 :         auto param = static_cast<const TyTy::ParamType *> (type);
     609            4 :         if (fntype != nullptr)
     610              :           {
     611            4 :             auto substs = fntype->get_substs ();
     612            4 :             for (size_t i = 0; i < substs.size (); i++)
     613              :               {
     614            8 :                 if (substs[i].get_param_ty ()->get_ty_ref ()
     615            4 :                     == param->get_ty_ref ())
     616            4 :                   return "P" + std::to_string (i);
     617              :               }
     618            4 :           }
     619            0 :         return param->get_symbol ();
     620              :       }
     621              : 
     622            4 :     case TyTy::TypeKind::POINTER:
     623            4 :       {
     624            4 :         auto ptr = static_cast<const TyTy::PointerType *> (type);
     625            4 :         std::string prefix = ptr->is_mutable () ? "*mut "
     626            1 :                              : ptr->is_const () ? "*const "
     627            5 :                                                 : "*";
     628            4 :         return prefix + to_string (ptr->get_base (), fntype);
     629            4 :       }
     630              : 
     631            0 :     case TyTy::TypeKind::REF:
     632            0 :       {
     633            0 :         auto ref = static_cast<const TyTy::ReferenceType *> (type);
     634            0 :         std::string prefix = ref->is_mutable () ? "&mut " : "&";
     635            0 :         return prefix + to_string (ref->get_base (), fntype);
     636            0 :       }
     637              : 
     638            1 :     case TyTy::TypeKind::TUPLE:
     639            1 :       {
     640            1 :         auto tuple = static_cast<const TyTy::TupleType *> (type);
     641            1 :         if (tuple->num_fields () == 0)
     642            0 :           return "()";
     643              : 
     644            1 :         std::string res = "(";
     645            3 :         for (size_t i = 0; i < tuple->num_fields (); i++)
     646              :           {
     647            2 :             if (i > 0)
     648            1 :               res += ", ";
     649            4 :             res += to_string (tuple->get_field (i), fntype);
     650              :           }
     651            1 :         res += ")";
     652            1 :         return res;
     653            1 :       }
     654              : 
     655            1 :     case TyTy::TypeKind::FNPTR:
     656            1 :       {
     657            1 :         auto fnptr = static_cast<const TyTy::FnPtr *> (type);
     658            1 :         std::string res = "fn(";
     659            3 :         for (size_t i = 0; i < fnptr->get_num_params (); i++)
     660              :           {
     661            2 :             if (i > 0)
     662            1 :               res += ", ";
     663            4 :             res += to_string (fnptr->get_param_type_at (i), fntype);
     664              :           }
     665            1 :         res += ")";
     666            1 :         if (!fnptr->get_return_type ()->is_unit ()
     667            1 :             || fnptr->get_return_type ()->get_kind () == TyTy::TypeKind::NEVER)
     668              :           {
     669            0 :             res += " -> ";
     670            0 :             res += to_string (fnptr->get_return_type (), fntype);
     671              :           }
     672            1 :         return res;
     673            1 :       }
     674              : 
     675            0 :     case TyTy::TypeKind::ADT:
     676            0 :       {
     677            0 :         auto adt = static_cast<const TyTy::ADTType *> (type);
     678            0 :         return adt->get_name ();
     679              :       }
     680              : 
     681            0 :     case TyTy::TypeKind::PLACEHOLDER:
     682            0 :       {
     683            0 :         auto ph = static_cast<const TyTy::PlaceholderType *> (type);
     684            0 :         return "<" + ph->get_symbol () + ">";
     685              :       }
     686              : 
     687            0 :     default:
     688            0 :       return type->as_string ();
     689              :     }
     690              : }
     691              : 
     692              : static std::string
     693           12 : to_string (IntrinsicRuleType ty)
     694              : {
     695           12 :   switch (ty)
     696              :     {
     697            0 :     case IRT::Bool:
     698            0 :       return "bool";
     699            0 :     case IRT::F32:
     700            0 :       return "f32";
     701            0 :     case IRT::F64:
     702            0 :       return "f64";
     703            0 :     case IRT::I32:
     704            0 :       return "i32";
     705            1 :     case IRT::Isize:
     706            1 :       return "isize";
     707            0 :     case IRT::U8:
     708            0 :       return "u8";
     709            0 :     case IRT::U64:
     710            0 :       return "u64";
     711            0 :     case IRT::Usize:
     712            0 :       return "usize";
     713            0 :     case IRT::Unit:
     714            0 :       return "()";
     715            1 :     case IRT::Never:
     716            1 :       return "!";
     717              : 
     718            3 :     case IRT::FirstGeneric:
     719            3 :       return "P0";
     720            1 :     case IRT::SecondGeneric:
     721            1 :       return "P1";
     722              : 
     723            2 :     case IRT::ConstPtrFirstGeneric:
     724            2 :       return "*const P0";
     725            0 :     case IRT::MutPtrFirstGeneric:
     726            0 :       return "*mut P0";
     727            0 :     case IRT::RefFirstGeneric:
     728            0 :       return "&P0";
     729              : 
     730            0 :     case IRT::RefAdt:
     731            0 :       return "&<ADT>";
     732            1 :     case IRT::MutPtrU8:
     733            1 :       return "*mut u8";
     734            0 :     case IRT::RefStaticStr:
     735            0 :       return "&'static str";
     736            0 :     case IRT::AssocTypePlaceholder:
     737            0 :       return "<AssocType>";
     738              : 
     739            1 :     case IRT::TupleFirstGenericAndBool:
     740            1 :       return "(P0, bool)";
     741              : 
     742            1 :     case IRT::Fn_MutPtrU8:
     743            1 :       return "fn(*mut u8)";
     744            1 :     case IRT::Fn_MutPtrU8MutPtrU8:
     745            1 :       return "fn(*mut u8, *mut u8)";
     746            0 :     };
     747            0 :   rust_unreachable ();
     748              : }
     749              : 
     750              : std::string
     751            5 : IntrinsicChecker::expected_intrinsic_as_string (const TyTy::FnType *fntype)
     752              : {
     753           10 :   auto it = intrinsic_rules.find (fntype->get_identifier ());
     754            5 :   rust_assert (it != intrinsic_rules.end ());
     755            5 :   auto rule = &it->second;
     756            5 :   std::stringstream result;
     757            5 :   result << "extern \"rust-intrinsic\" fn(";
     758            5 :   if (rule->param_types.size () > 0)
     759              :     {
     760           12 :       for (size_t i = 0; i < rule->param_types.size (); i++)
     761              :         {
     762            8 :           if (i != 0)
     763            4 :             result << ", ";
     764           16 :           result << to_string (rule->param_types.at (i));
     765              :         }
     766              :     }
     767            5 :   result << ")";
     768            5 :   if (rule->return_type != IntrinsicRuleType::Unit)
     769              :     {
     770            8 :       result << " -> " << to_string (rule->return_type);
     771              :     }
     772            5 :   return result.str ();
     773            5 : }
     774              : 
     775              : std::string
     776            5 : IntrinsicChecker::found_intrinsic_as_string (const TyTy::FnType *fntype)
     777              : {
     778            5 :   std::stringstream result;
     779            5 :   result << "extern \"rust-intrinsic\" fn(";
     780            5 :   if (fntype->get_num_params () > 0)
     781              :     {
     782            5 :       const auto &params = fntype->get_params ();
     783           14 :       for (size_t i = 0; i < params.size (); i++)
     784              :         {
     785            9 :           if (i != 0)
     786            4 :             result << ", ";
     787           18 :           result << to_string (params.at (i).get_type (), fntype);
     788              :         }
     789              :     }
     790            5 :   result << ")";
     791            5 :   if (!fntype->get_return_type ()->is_unit ()
     792            5 :       || fntype->get_return_type ()->get_kind () == TyTy::TypeKind::NEVER)
     793              :     {
     794           10 :       result << " -> " << to_string (fntype->get_return_type (), fntype);
     795              :     }
     796            5 :   return result.str ();
     797            5 : }
     798              : 
     799              : } // namespace Resolver
     800              : } // 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.