1 #![allow(non_camel_case_types)]
3 use rustc_errors::struct_span_err;
5 use rustc_hir::LangItem;
6 use rustc_middle::mir::interpret::ConstValue;
7 use rustc_middle::ty::{self, layout::TyAndLayout, Ty, TyCtxt};
8 use rustc_session::Session;
14 #[derive(Copy, Clone)]
15 pub enum IntPredicate {
28 #[derive(Copy, Clone)]
29 pub enum RealPredicate {
48 #[derive(Copy, Clone)]
49 pub enum AtomicRmwBinOp {
63 #[derive(Copy, Clone)]
64 pub enum AtomicOrdering {
70 SequentiallyConsistent,
73 #[derive(Copy, Clone)]
74 pub enum SynchronizationScope {
79 #[derive(Copy, Clone, PartialEq, Debug)]
103 // FIXME(mw): Anything that is produced via DepGraph::with_task() must implement
104 // the HashStable trait. Normally DepGraph::with_task() calls are
105 // hidden behind queries, but CGU creation is a special case in two
106 // ways: (1) it's not a query and (2) CGU are output nodes, so their
107 // Fingerprints are not actually needed. It remains to be clarified
108 // how exactly this case will be handled in the red/green system but
109 // for now we content ourselves with providing a no-op HashStable
110 // implementation for CGUs.
111 mod temp_stable_hash_impls {
112 use crate::ModuleCodegen;
113 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
115 impl<HCX, M> HashStable<HCX> for ModuleCodegen<M> {
116 fn hash_stable(&self, _: &mut HCX, _: &mut StableHasher) {
122 pub fn build_langcall<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
126 ) -> (Bx::FnAbiOfResult, Bx::Value) {
128 let def_id = tcx.require_lang_item(li, span);
129 let instance = ty::Instance::mono(tcx, def_id);
130 (bx.fn_abi_of_instance(instance, ty::List::empty()), bx.get_fn_addr(instance))
133 // To avoid UB from LLVM, these two functions mask RHS with an
134 // appropriate mask unconditionally (i.e., the fallback behavior for
135 // all shifts). For 32- and 64-bit types, this matches the semantics
136 // of Java. (See related discussion on #1877 and #10183.)
138 pub fn build_unchecked_lshift<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
143 let rhs = base::cast_shift_expr_rhs(bx, hir::BinOpKind::Shl, lhs, rhs);
144 // #1877, #10183: Ensure that input is always valid
145 let rhs = shift_mask_rhs(bx, rhs);
149 pub fn build_unchecked_rshift<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
155 let rhs = base::cast_shift_expr_rhs(bx, hir::BinOpKind::Shr, lhs, rhs);
156 // #1877, #10183: Ensure that input is always valid
157 let rhs = shift_mask_rhs(bx, rhs);
158 let is_signed = lhs_t.is_signed();
159 if is_signed { bx.ashr(lhs, rhs) } else { bx.lshr(lhs, rhs) }
162 fn shift_mask_rhs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
166 let rhs_llty = bx.val_ty(rhs);
167 let shift_val = shift_mask_val(bx, rhs_llty, rhs_llty, false);
168 bx.and(rhs, shift_val)
171 pub fn shift_mask_val<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
177 let kind = bx.type_kind(llty);
179 TypeKind::Integer => {
180 // i8/u8 can shift by at most 7, i16/u16 by at most 15, etc.
181 let val = bx.int_width(llty) - 1;
183 bx.const_int(mask_llty, !val as i64)
185 bx.const_uint(mask_llty, val)
188 TypeKind::Vector => {
190 shift_mask_val(bx, bx.element_type(llty), bx.element_type(mask_llty), invert);
191 bx.vector_splat(bx.vector_length(mask_llty), mask)
193 _ => bug!("shift_mask_val: expected Integer or Vector, found {:?}", kind),
197 pub fn span_invalid_monomorphization_error(a: &Session, b: Span, c: &str) {
198 struct_span_err!(a, b, E0511, "{}", c).emit();
201 pub fn asm_const_to_str<'tcx>(
204 const_value: ConstValue<'tcx>,
205 ty_and_layout: TyAndLayout<'tcx>,
207 let ConstValue::Scalar(scalar) = const_value else {
208 span_bug!(sp, "expected Scalar for promoted asm const, but got {:#?}", const_value)
210 let value = scalar.assert_bits(ty_and_layout.size);
211 match ty_and_layout.ty.kind() {
212 ty::Uint(_) => value.to_string(),
213 ty::Int(int_ty) => match int_ty.normalize(tcx.sess.target.pointer_width) {
214 ty::IntTy::I8 => (value as i8).to_string(),
215 ty::IntTy::I16 => (value as i16).to_string(),
216 ty::IntTy::I32 => (value as i32).to_string(),
217 ty::IntTy::I64 => (value as i64).to_string(),
218 ty::IntTy::I128 => (value as i128).to_string(),
219 ty::IntTy::Isize => unreachable!(),
221 _ => span_bug!(sp, "asm const has bad type {}", ty_and_layout.ty),