]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_codegen_ssa/src/common.rs
Rollup merge of #99480 - miam-miam100:arg-format, r=oli-obk
[rust.git] / compiler / rustc_codegen_ssa / src / common.rs
1 #![allow(non_camel_case_types)]
2
3 use rustc_errors::struct_span_err;
4 use rustc_hir as hir;
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;
9 use rustc_span::Span;
10
11 use crate::base;
12 use crate::traits::*;
13
14 #[derive(Copy, Clone)]
15 pub enum IntPredicate {
16     IntEQ,
17     IntNE,
18     IntUGT,
19     IntUGE,
20     IntULT,
21     IntULE,
22     IntSGT,
23     IntSGE,
24     IntSLT,
25     IntSLE,
26 }
27
28 #[derive(Copy, Clone)]
29 pub enum RealPredicate {
30     RealPredicateFalse,
31     RealOEQ,
32     RealOGT,
33     RealOGE,
34     RealOLT,
35     RealOLE,
36     RealONE,
37     RealORD,
38     RealUNO,
39     RealUEQ,
40     RealUGT,
41     RealUGE,
42     RealULT,
43     RealULE,
44     RealUNE,
45     RealPredicateTrue,
46 }
47
48 #[derive(Copy, Clone)]
49 pub enum AtomicRmwBinOp {
50     AtomicXchg,
51     AtomicAdd,
52     AtomicSub,
53     AtomicAnd,
54     AtomicNand,
55     AtomicOr,
56     AtomicXor,
57     AtomicMax,
58     AtomicMin,
59     AtomicUMax,
60     AtomicUMin,
61 }
62
63 #[derive(Copy, Clone)]
64 pub enum AtomicOrdering {
65     Unordered,
66     Relaxed,
67     Acquire,
68     Release,
69     AcquireRelease,
70     SequentiallyConsistent,
71 }
72
73 #[derive(Copy, Clone)]
74 pub enum SynchronizationScope {
75     SingleThread,
76     CrossThread,
77 }
78
79 #[derive(Copy, Clone, PartialEq, Debug)]
80 pub enum TypeKind {
81     Void,
82     Half,
83     Float,
84     Double,
85     X86_FP80,
86     FP128,
87     PPC_FP128,
88     Label,
89     Integer,
90     Function,
91     Struct,
92     Array,
93     Pointer,
94     Vector,
95     Metadata,
96     X86_MMX,
97     Token,
98     ScalableVector,
99     BFloat,
100     X86_AMX,
101 }
102
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};
114
115     impl<HCX, M> HashStable<HCX> for ModuleCodegen<M> {
116         fn hash_stable(&self, _: &mut HCX, _: &mut StableHasher) {
117             // do nothing
118         }
119     }
120 }
121
122 pub fn build_langcall<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
123     bx: &Bx,
124     span: Option<Span>,
125     li: LangItem,
126 ) -> (Bx::FnAbiOfResult, Bx::Value) {
127     let tcx = bx.tcx();
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))
131 }
132
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.)
137
138 pub fn build_unchecked_lshift<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
139     bx: &mut Bx,
140     lhs: Bx::Value,
141     rhs: Bx::Value,
142 ) -> Bx::Value {
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);
146     bx.shl(lhs, rhs)
147 }
148
149 pub fn build_unchecked_rshift<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
150     bx: &mut Bx,
151     lhs_t: Ty<'tcx>,
152     lhs: Bx::Value,
153     rhs: Bx::Value,
154 ) -> Bx::Value {
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) }
160 }
161
162 fn shift_mask_rhs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
163     bx: &mut Bx,
164     rhs: Bx::Value,
165 ) -> Bx::Value {
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)
169 }
170
171 pub fn shift_mask_val<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
172     bx: &mut Bx,
173     llty: Bx::Type,
174     mask_llty: Bx::Type,
175     invert: bool,
176 ) -> Bx::Value {
177     let kind = bx.type_kind(llty);
178     match kind {
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;
182             if invert {
183                 bx.const_int(mask_llty, !val as i64)
184             } else {
185                 bx.const_uint(mask_llty, val)
186             }
187         }
188         TypeKind::Vector => {
189             let mask =
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)
192         }
193         _ => bug!("shift_mask_val: expected Integer or Vector, found {:?}", kind),
194     }
195 }
196
197 pub fn span_invalid_monomorphization_error(a: &Session, b: Span, c: &str) {
198     struct_span_err!(a, b, E0511, "{}", c).emit();
199 }
200
201 pub fn asm_const_to_str<'tcx>(
202     tcx: TyCtxt<'tcx>,
203     sp: Span,
204     const_value: ConstValue<'tcx>,
205     ty_and_layout: TyAndLayout<'tcx>,
206 ) -> String {
207     let ConstValue::Scalar(scalar) = const_value else {
208         span_bug!(sp, "expected Scalar for promoted asm const, but got {:#?}", const_value)
209     };
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!(),
220         },
221         _ => span_bug!(sp, "asm const has bad type {}", ty_and_layout.ty),
222     }
223 }