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

Generated by: LCOV version 2.5.0-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.