]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_codegen_ssa/src/common.rs
Auto merge of #107843 - bjorn3:sync_cg_clif-2023-02-09, r=bjorn3
[rust.git] / compiler / rustc_codegen_ssa / src / common.rs
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> {
113         fn hash_stable(&self, _: &mut HCX, _: &mut StableHasher) {
114             // do nothing
115         }
116     }
117 }
118
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
135 pub fn build_unchecked_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
146 pub fn build_unchecked_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
159 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
168 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
194 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 }