1 #![allow(non_camel_case_types)]
2
3 use rustc_hir::LangItem;
4 use rustc_middle::mir::interpret::ConstValue;
5 use rustc_middle::ty::{self, layout::TyAndLayout, Ty, TyCtxt};
6 use rustc_span::Span;
7
8 use crate::base;
9 use crate::traits::*;
10
11 #[derive(Copy, Clone)]
12 pub enum IntPredicate {
13 IntEQ,
14 IntNE,
15 IntUGT,
16 IntUGE,
17 IntULT,
18 IntULE,
19 IntSGT,
20 IntSGE,
21 IntSLT,
22 IntSLE,
23 }
24
25 #[derive(Copy, Clone)]
26 pub enum RealPredicate {
27 RealPredicateFalse,
28 RealOEQ,
29 RealOGT,
30 RealOGE,
31 RealOLT,
32 RealOLE,
33 RealONE,
34 RealORD,
35 RealUNO,
36 RealUEQ,
37 RealUGT,
38 RealUGE,
39 RealULT,
40 RealULE,
41 RealUNE,
42 RealPredicateTrue,
43 }
44
45 #[derive(Copy, Clone)]
46 pub enum AtomicRmwBinOp {
47 AtomicXchg,
48 AtomicAdd,
49 AtomicSub,
50 AtomicAnd,
51 AtomicNand,
52 AtomicOr,
53 AtomicXor,
54 AtomicMax,
55 AtomicMin,
56 AtomicUMax,
57 AtomicUMin,
58 }
59
60 #[derive(Copy, Clone)]
61 pub enum AtomicOrdering {
62 Unordered,
63 Relaxed,
64 Acquire,
65 Release,
66 AcquireRelease,
67 SequentiallyConsistent,
68 }
69
70 #[derive(Copy, Clone)]
71 pub enum SynchronizationScope {
72 SingleThread,
73 CrossThread,
74 }
75
76 #[derive(Copy, Clone, PartialEq, Debug)]
77 pub enum TypeKind {
78 Void,
79 Half,
80 Float,
81 Double,
82 X86_FP80,
83 FP128,
84 PPC_FP128,
85 Label,
86 Integer,
87 Function,
88 Struct,
89 Array,
90 Pointer,
91 Vector,
92 Metadata,
93 X86_MMX,
94 Token,
95 ScalableVector,
96 BFloat,
97 X86_AMX,
98 }
99
100 // FIXME(mw): Anything that is produced via DepGraph::with_task() must implement
101 // the HashStable trait. Normally DepGraph::with_task() calls are
102 // hidden behind queries, but CGU creation is a special case in two
103 // ways: (1) it's not a query and (2) CGU are output nodes, so their
104 // Fingerprints are not actually needed. It remains to be clarified
105 // how exactly this case will be handled in the red/green system but
106 // for now we content ourselves with providing a no-op HashStable
107 // implementation for CGUs.
108 mod temp_stable_hash_impls {
109 use crate::ModuleCodegen;
110 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
111
112 impl<HCX, M> HashStable<HCX> for ModuleCodegen<M> {
hash_stable(&self, _: &mut HCX, _: &mut StableHasher)113 fn hash_stable(&self, _: &mut HCX, _: &mut StableHasher) {
114 // do nothing
115 }
116 }
117 }
118
build_langcall<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( bx: &Bx, span: Option<Span>, li: LangItem, ) -> (Bx::FnAbiOfResult, Bx::Value)119 pub fn build_langcall<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
120 bx: &Bx,
121 span: Option<Span>,
122 li: LangItem,
123 ) -> (Bx::FnAbiOfResult, Bx::Value) {
124 let tcx = bx.tcx();
125 let def_id = tcx.require_lang_item(li, span);
126 let instance = ty::Instance::mono(tcx, def_id);
127 (bx.fn_abi_of_instance(instance, ty::List::empty()), bx.get_fn_addr(instance))
128 }
129
130 // To avoid UB from LLVM, these two functions mask RHS with an
131 // appropriate mask unconditionally (i.e., the fallback behavior for
132 // all shifts). For 32- and 64-bit types, this matches the semantics
133 // of Java. (See related discussion on #1877 and #10183.)
134
build_masked_lshift<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( bx: &mut Bx, lhs: Bx::Value, rhs: Bx::Value, ) -> Bx::Value135 pub fn build_masked_lshift<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
136 bx: &mut Bx,
137 lhs: Bx::Value,
138 rhs: Bx::Value,
139 ) -> Bx::Value {
140 let rhs = base::cast_shift_expr_rhs(bx, lhs, rhs);
141 // #1877, #10183: Ensure that input is always valid
142 let rhs = shift_mask_rhs(bx, rhs);
143 bx.shl(lhs, rhs)
144 }
145
build_masked_rshift<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( bx: &mut Bx, lhs_t: Ty<'tcx>, lhs: Bx::Value, rhs: Bx::Value, ) -> Bx::Value146 pub fn build_masked_rshift<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
147 bx: &mut Bx,
148 lhs_t: Ty<'tcx>,
149 lhs: Bx::Value,
150 rhs: Bx::Value,
151 ) -> Bx::Value {
152 let rhs = base::cast_shift_expr_rhs(bx, lhs, rhs);
153 // #1877, #10183: Ensure that input is always valid
154 let rhs = shift_mask_rhs(bx, rhs);
155 let is_signed = lhs_t.is_signed();
156 if is_signed { bx.ashr(lhs, rhs) } else { bx.lshr(lhs, rhs) }
157 }
158
shift_mask_rhs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( bx: &mut Bx, rhs: Bx::Value, ) -> Bx::Value159 fn shift_mask_rhs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
160 bx: &mut Bx,
161 rhs: Bx::Value,
162 ) -> Bx::Value {
163 let rhs_llty = bx.val_ty(rhs);
164 let shift_val = shift_mask_val(bx, rhs_llty, rhs_llty, false);
165 bx.and(rhs, shift_val)
166 }
167
shift_mask_val<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( bx: &mut Bx, llty: Bx::Type, mask_llty: Bx::Type, invert: bool, ) -> Bx::Value168 pub fn shift_mask_val<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
169 bx: &mut Bx,
170 llty: Bx::Type,
171 mask_llty: Bx::Type,
172 invert: bool,
173 ) -> Bx::Value {
174 let kind = bx.type_kind(llty);
175 match kind {
176 TypeKind::Integer => {
177 // i8/u8 can shift by at most 7, i16/u16 by at most 15, etc.
178 let val = bx.int_width(llty) - 1;
179 if invert {
180 bx.const_int(mask_llty, !val as i64)
181 } else {
182 bx.const_uint(mask_llty, val)
183 }
184 }
185 TypeKind::Vector => {
186 let mask =
187 shift_mask_val(bx, bx.element_type(llty), bx.element_type(mask_llty), invert);
188 bx.vector_splat(bx.vector_length(mask_llty), mask)
189 }
190 _ => bug!("shift_mask_val: expected Integer or Vector, found {:?}", kind),
191 }
192 }
193
asm_const_to_str<'tcx>( tcx: TyCtxt<'tcx>, sp: Span, const_value: ConstValue<'tcx>, ty_and_layout: TyAndLayout<'tcx>, ) -> String194 pub fn asm_const_to_str<'tcx>(
195 tcx: TyCtxt<'tcx>,
196 sp: Span,
197 const_value: ConstValue<'tcx>,
198 ty_and_layout: TyAndLayout<'tcx>,
199 ) -> String {
200 let ConstValue::Scalar(scalar) = const_value else {
201 span_bug!(sp, "expected Scalar for promoted asm const, but got {:#?}", const_value)
202 };
203 let value = scalar.assert_bits(ty_and_layout.size);
204 match ty_and_layout.ty.kind() {
205 ty::Uint(_) => value.to_string(),
206 ty::Int(int_ty) => match int_ty.normalize(tcx.sess.target.pointer_width) {
207 ty::IntTy::I8 => (value as i8).to_string(),
208 ty::IntTy::I16 => (value as i16).to_string(),
209 ty::IntTy::I32 => (value as i32).to_string(),
210 ty::IntTy::I64 => (value as i64).to_string(),
211 ty::IntTy::I128 => (value as i128).to_string(),
212 ty::IntTy::Isize => unreachable!(),
213 },
214 _ => span_bug!(sp, "asm const has bad type {}", ty_and_layout.ty),
215 }
216 }
217