]> git.lizzy.rs Git - rust.git/blob - src/librustc_codegen_ssa/common.rs
Auto merge of #58649 - pnkfelix:issue-57464-avoid-ice-when-region-sneaks-into-impl...
[rust.git] / src / librustc_codegen_ssa / common.rs
1 #![allow(non_camel_case_types, non_snake_case)]
2
3 use rustc::ty::{self, Ty, TyCtxt};
4 use syntax_pos::{DUMMY_SP, Span};
5
6 use rustc::hir::def_id::DefId;
7 use rustc::middle::lang_items::LangItem;
8 use crate::base;
9 use crate::traits::*;
10
11 use rustc::hir;
12 use crate::traits::BuilderMethods;
13
14 pub fn type_needs_drop<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> bool {
15     ty.needs_drop(tcx, ty::ParamEnv::reveal_all())
16 }
17
18 pub fn type_is_sized<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> bool {
19     ty.is_sized(tcx.at(DUMMY_SP), ty::ParamEnv::reveal_all())
20 }
21
22 pub fn type_is_freeze<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> bool {
23     ty.is_freeze(tcx, ty::ParamEnv::reveal_all(), DUMMY_SP)
24 }
25
26 pub enum IntPredicate {
27     IntEQ,
28     IntNE,
29     IntUGT,
30     IntUGE,
31     IntULT,
32     IntULE,
33     IntSGT,
34     IntSGE,
35     IntSLT,
36     IntSLE
37 }
38
39
40 #[allow(dead_code)]
41 pub enum RealPredicate {
42     RealPredicateFalse,
43     RealOEQ,
44     RealOGT,
45     RealOGE,
46     RealOLT,
47     RealOLE,
48     RealONE,
49     RealORD,
50     RealUNO,
51     RealUEQ,
52     RealUGT,
53     RealUGE,
54     RealULT,
55     RealULE,
56     RealUNE,
57     RealPredicateTrue
58 }
59
60 pub enum AtomicRmwBinOp {
61     AtomicXchg,
62     AtomicAdd,
63     AtomicSub,
64     AtomicAnd,
65     AtomicNand,
66     AtomicOr,
67     AtomicXor,
68     AtomicMax,
69     AtomicMin,
70     AtomicUMax,
71     AtomicUMin
72 }
73
74 pub enum AtomicOrdering {
75     #[allow(dead_code)]
76     NotAtomic,
77     Unordered,
78     Monotonic,
79     // Consume,  // Not specified yet.
80     Acquire,
81     Release,
82     AcquireRelease,
83     SequentiallyConsistent,
84 }
85
86 pub enum SynchronizationScope {
87     // FIXME: figure out if this variant is needed at all.
88     #[allow(dead_code)]
89     Other,
90     SingleThread,
91     CrossThread,
92 }
93
94 #[derive(Copy, Clone, PartialEq, Debug)]
95 pub enum TypeKind {
96     Void,
97     Half,
98     Float,
99     Double,
100     X86_FP80,
101     FP128,
102     PPC_FP128,
103     Label,
104     Integer,
105     Function,
106     Struct,
107     Array,
108     Pointer,
109     Vector,
110     Metadata,
111     X86_MMX,
112     Token,
113 }
114
115 // FIXME(mw): Anything that is produced via DepGraph::with_task() must implement
116 //            the HashStable trait. Normally DepGraph::with_task() calls are
117 //            hidden behind queries, but CGU creation is a special case in two
118 //            ways: (1) it's not a query and (2) CGU are output nodes, so their
119 //            Fingerprints are not actually needed. It remains to be clarified
120 //            how exactly this case will be handled in the red/green system but
121 //            for now we content ourselves with providing a no-op HashStable
122 //            implementation for CGUs.
123 mod temp_stable_hash_impls {
124     use rustc_data_structures::stable_hasher::{StableHasherResult, StableHasher,
125                                                HashStable};
126     use crate::ModuleCodegen;
127
128     impl<HCX, M> HashStable<HCX> for ModuleCodegen<M> {
129         fn hash_stable<W: StableHasherResult>(&self,
130                                               _: &mut HCX,
131                                               _: &mut StableHasher<W>) {
132             // do nothing
133         }
134     }
135 }
136
137 pub fn langcall(tcx: TyCtxt<'_, '_, '_>,
138                 span: Option<Span>,
139                 msg: &str,
140                 li: LangItem)
141                 -> DefId {
142     tcx.lang_items().require(li).unwrap_or_else(|s| {
143         let msg = format!("{} {}", msg, s);
144         match span {
145             Some(span) => tcx.sess.span_fatal(span, &msg[..]),
146             None => tcx.sess.fatal(&msg[..]),
147         }
148     })
149 }
150
151 // To avoid UB from LLVM, these two functions mask RHS with an
152 // appropriate mask unconditionally (i.e., the fallback behavior for
153 // all shifts). For 32- and 64-bit types, this matches the semantics
154 // of Java. (See related discussion on #1877 and #10183.)
155
156 pub fn build_unchecked_lshift<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
157     bx: &mut Bx,
158     lhs: Bx::Value,
159     rhs: Bx::Value
160 ) -> Bx::Value {
161     let rhs = base::cast_shift_expr_rhs(bx, hir::BinOpKind::Shl, lhs, rhs);
162     // #1877, #10183: Ensure that input is always valid
163     let rhs = shift_mask_rhs(bx, rhs);
164     bx.shl(lhs, rhs)
165 }
166
167 pub fn build_unchecked_rshift<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
168     bx: &mut Bx,
169     lhs_t: Ty<'tcx>,
170     lhs: Bx::Value,
171     rhs: Bx::Value
172 ) -> Bx::Value {
173     let rhs = base::cast_shift_expr_rhs(bx, hir::BinOpKind::Shr, lhs, rhs);
174     // #1877, #10183: Ensure that input is always valid
175     let rhs = shift_mask_rhs(bx, rhs);
176     let is_signed = lhs_t.is_signed();
177     if is_signed {
178         bx.ashr(lhs, rhs)
179     } else {
180         bx.lshr(lhs, rhs)
181     }
182 }
183
184 fn shift_mask_rhs<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
185     bx: &mut Bx,
186     rhs: Bx::Value
187 ) -> Bx::Value {
188     let rhs_llty = bx.val_ty(rhs);
189     let shift_val = shift_mask_val(bx, rhs_llty, rhs_llty, false);
190     bx.and(rhs, shift_val)
191 }
192
193 pub fn shift_mask_val<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
194     bx: &mut Bx,
195     llty: Bx::Type,
196     mask_llty: Bx::Type,
197     invert: bool
198 ) -> Bx::Value {
199     let kind = bx.type_kind(llty);
200     match kind {
201         TypeKind::Integer => {
202             // i8/u8 can shift by at most 7, i16/u16 by at most 15, etc.
203             let val = bx.int_width(llty) - 1;
204             if invert {
205                 bx.const_int(mask_llty, !val as i64)
206             } else {
207                 bx.const_uint(mask_llty, val)
208             }
209         },
210         TypeKind::Vector => {
211             let mask = shift_mask_val(
212                 bx,
213                 bx.element_type(llty),
214                 bx.element_type(mask_llty),
215                 invert
216             );
217             bx.vector_splat(bx.vector_length(mask_llty), mask)
218         },
219         _ => bug!("shift_mask_val: expected Integer or Vector, found {:?}", kind),
220     }
221 }