]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_codegen_ssa/src/common.rs
Rollup merge of #85329 - RalfJung:version, r=Mark-Simulacrum
[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::def_id::DefId;
6 use rustc_hir::LangItem;
7 use rustc_middle::mir::interpret::ConstValue;
8 use rustc_middle::ty::{self, layout::TyAndLayout, Ty, TyCtxt};
9 use rustc_session::Session;
10 use rustc_span::Span;
11
12 use crate::base;
13 use crate::traits::BuilderMethods;
14 use crate::traits::*;
15
16 pub enum IntPredicate {
17     IntEQ,
18     IntNE,
19     IntUGT,
20     IntUGE,
21     IntULT,
22     IntULE,
23     IntSGT,
24     IntSGE,
25     IntSLT,
26     IntSLE,
27 }
28
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 pub enum AtomicRmwBinOp {
49     AtomicXchg,
50     AtomicAdd,
51     AtomicSub,
52     AtomicAnd,
53     AtomicNand,
54     AtomicOr,
55     AtomicXor,
56     AtomicMax,
57     AtomicMin,
58     AtomicUMax,
59     AtomicUMin,
60 }
61
62 pub enum AtomicOrdering {
63     NotAtomic,
64     Unordered,
65     Monotonic,
66     // Consume,  // Not specified yet.
67     Acquire,
68     Release,
69     AcquireRelease,
70     SequentiallyConsistent,
71 }
72
73 pub enum SynchronizationScope {
74     SingleThread,
75     CrossThread,
76 }
77
78 #[derive(Copy, Clone, PartialEq, Debug)]
79 pub enum TypeKind {
80     Void,
81     Half,
82     Float,
83     Double,
84     X86_FP80,
85     FP128,
86     PPC_FP128,
87     Label,
88     Integer,
89     Function,
90     Struct,
91     Array,
92     Pointer,
93     Vector,
94     Metadata,
95     X86_MMX,
96     Token,
97     ScalableVector,
98     BFloat,
99     X86_AMX,
100 }
101
102 // FIXME(mw): Anything that is produced via DepGraph::with_task() must implement
103 //            the HashStable trait. Normally DepGraph::with_task() calls are
104 //            hidden behind queries, but CGU creation is a special case in two
105 //            ways: (1) it's not a query and (2) CGU are output nodes, so their
106 //            Fingerprints are not actually needed. It remains to be clarified
107 //            how exactly this case will be handled in the red/green system but
108 //            for now we content ourselves with providing a no-op HashStable
109 //            implementation for CGUs.
110 mod temp_stable_hash_impls {
111     use crate::ModuleCodegen;
112     use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
113
114     impl<HCX, M> HashStable<HCX> for ModuleCodegen<M> {
115         fn hash_stable(&self, _: &mut HCX, _: &mut StableHasher) {
116             // do nothing
117         }
118     }
119 }
120
121 pub fn langcall(tcx: TyCtxt<'_>, span: Option<Span>, msg: &str, li: LangItem) -> DefId {
122     tcx.lang_items().require(li).unwrap_or_else(|s| {
123         let msg = format!("{} {}", msg, s);
124         match span {
125             Some(span) => tcx.sess.span_fatal(span, &msg[..]),
126             None => tcx.sess.fatal(&msg[..]),
127         }
128     })
129 }
130
131 // To avoid UB from LLVM, these two functions mask RHS with an
132 // appropriate mask unconditionally (i.e., the fallback behavior for
133 // all shifts). For 32- and 64-bit types, this matches the semantics
134 // of Java. (See related discussion on #1877 and #10183.)
135
136 pub fn build_unchecked_lshift<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
137     bx: &mut Bx,
138     lhs: Bx::Value,
139     rhs: Bx::Value,
140 ) -> Bx::Value {
141     let rhs = base::cast_shift_expr_rhs(bx, hir::BinOpKind::Shl, lhs, rhs);
142     // #1877, #10183: Ensure that input is always valid
143     let rhs = shift_mask_rhs(bx, rhs);
144     bx.shl(lhs, rhs)
145 }
146
147 pub fn build_unchecked_rshift<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
148     bx: &mut Bx,
149     lhs_t: Ty<'tcx>,
150     lhs: Bx::Value,
151     rhs: Bx::Value,
152 ) -> Bx::Value {
153     let rhs = base::cast_shift_expr_rhs(bx, hir::BinOpKind::Shr, lhs, rhs);
154     // #1877, #10183: Ensure that input is always valid
155     let rhs = shift_mask_rhs(bx, rhs);
156     let is_signed = lhs_t.is_signed();
157     if is_signed { bx.ashr(lhs, rhs) } else { bx.lshr(lhs, rhs) }
158 }
159
160 fn shift_mask_rhs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
161     bx: &mut Bx,
162     rhs: Bx::Value,
163 ) -> Bx::Value {
164     let rhs_llty = bx.val_ty(rhs);
165     let shift_val = shift_mask_val(bx, rhs_llty, rhs_llty, false);
166     bx.and(rhs, shift_val)
167 }
168
169 pub fn shift_mask_val<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
170     bx: &mut Bx,
171     llty: Bx::Type,
172     mask_llty: Bx::Type,
173     invert: bool,
174 ) -> Bx::Value {
175     let kind = bx.type_kind(llty);
176     match kind {
177         TypeKind::Integer => {
178             // i8/u8 can shift by at most 7, i16/u16 by at most 15, etc.
179             let val = bx.int_width(llty) - 1;
180             if invert {
181                 bx.const_int(mask_llty, !val as i64)
182             } else {
183                 bx.const_uint(mask_llty, val)
184             }
185         }
186         TypeKind::Vector => {
187             let mask =
188                 shift_mask_val(bx, bx.element_type(llty), bx.element_type(mask_llty), invert);
189             bx.vector_splat(bx.vector_length(mask_llty), mask)
190         }
191         _ => bug!("shift_mask_val: expected Integer or Vector, found {:?}", kind),
192     }
193 }
194
195 pub fn span_invalid_monomorphization_error(a: &Session, b: Span, c: &str) {
196     struct_span_err!(a, b, E0511, "{}", c).emit();
197 }
198
199 pub fn asm_const_to_str<'tcx>(
200     tcx: TyCtxt<'tcx>,
201     sp: Span,
202     const_value: ConstValue<'tcx>,
203     ty_and_layout: TyAndLayout<'tcx>,
204 ) -> String {
205     let scalar = match const_value {
206         ConstValue::Scalar(s) => s,
207         _ => {
208             span_bug!(sp, "expected Scalar for promoted asm const, but got {:#?}", const_value)
209         }
210     };
211     let value = scalar.assert_bits(ty_and_layout.size);
212     match ty_and_layout.ty.kind() {
213         ty::Uint(_) => value.to_string(),
214         ty::Int(int_ty) => match int_ty.normalize(tcx.sess.target.pointer_width) {
215             ty::IntTy::I8 => (value as i8).to_string(),
216             ty::IntTy::I16 => (value as i16).to_string(),
217             ty::IntTy::I32 => (value as i32).to_string(),
218             ty::IntTy::I64 => (value as i64).to_string(),
219             ty::IntTy::I128 => (value as i128).to_string(),
220             ty::IntTy::Isize => unreachable!(),
221         },
222         ty::Float(ty::FloatTy::F32) => f32::from_bits(value as u32).to_string(),
223         ty::Float(ty::FloatTy::F64) => f64::from_bits(value as u64).to_string(),
224         _ => span_bug!(sp, "asm const has bad type {}", ty_and_layout.ty),
225     }
226 }