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