]> git.lizzy.rs Git - rust.git/blob - src/librustc_codegen_ssa/common.rs
Rollup merge of #66263 - guanqun:make-error-explicit, r=alexcrichton
[rust.git] / src / librustc_codegen_ssa / common.rs
1 #![allow(non_camel_case_types, non_snake_case)]
2
3 use rustc::ty::{Ty, TyCtxt};
4 use rustc::session::Session;
5 use syntax_pos::Span;
6
7 use rustc::hir::def_id::DefId;
8 use rustc::middle::lang_items::LangItem;
9 use crate::base;
10 use crate::traits::*;
11
12 use rustc::hir;
13 use crate::traits::BuilderMethods;
14
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
29 #[allow(dead_code)]
30 pub enum RealPredicate {
31     RealPredicateFalse,
32     RealOEQ,
33     RealOGT,
34     RealOGE,
35     RealOLT,
36     RealOLE,
37     RealONE,
38     RealORD,
39     RealUNO,
40     RealUEQ,
41     RealUGT,
42     RealUGE,
43     RealULT,
44     RealULE,
45     RealUNE,
46     RealPredicateTrue
47 }
48
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 pub enum AtomicOrdering {
64     #[allow(dead_code)]
65     NotAtomic,
66     Unordered,
67     Monotonic,
68     // Consume,  // Not specified yet.
69     Acquire,
70     Release,
71     AcquireRelease,
72     SequentiallyConsistent,
73 }
74
75 pub enum SynchronizationScope {
76     // FIXME: figure out if this variant is needed at all.
77     #[allow(dead_code)]
78     Other,
79     SingleThread,
80     CrossThread,
81 }
82
83 #[derive(Copy, Clone, PartialEq, Debug)]
84 pub enum TypeKind {
85     Void,
86     Half,
87     Float,
88     Double,
89     X86_FP80,
90     FP128,
91     PPC_FP128,
92     Label,
93     Integer,
94     Function,
95     Struct,
96     Array,
97     Pointer,
98     Vector,
99     Metadata,
100     X86_MMX,
101     Token,
102 }
103
104 // FIXME(mw): Anything that is produced via DepGraph::with_task() must implement
105 //            the HashStable trait. Normally DepGraph::with_task() calls are
106 //            hidden behind queries, but CGU creation is a special case in two
107 //            ways: (1) it's not a query and (2) CGU are output nodes, so their
108 //            Fingerprints are not actually needed. It remains to be clarified
109 //            how exactly this case will be handled in the red/green system but
110 //            for now we content ourselves with providing a no-op HashStable
111 //            implementation for CGUs.
112 mod temp_stable_hash_impls {
113     use rustc_data_structures::stable_hasher::{StableHasher, HashStable};
114     use crate::ModuleCodegen;
115
116     impl<HCX, M> HashStable<HCX> for ModuleCodegen<M> {
117         fn hash_stable(&self, _: &mut HCX, _: &mut StableHasher) {
118             // do nothing
119         }
120     }
121 }
122
123 pub fn langcall(tcx: TyCtxt<'_>, span: Option<Span>, msg: &str, li: LangItem) -> DefId {
124     tcx.lang_items().require(li).unwrap_or_else(|s| {
125         let msg = format!("{} {}", msg, s);
126         match span {
127             Some(span) => tcx.sess.span_fatal(span, &msg[..]),
128             None => tcx.sess.fatal(&msg[..]),
129         }
130     })
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 {
160         bx.ashr(lhs, rhs)
161     } else {
162         bx.lshr(lhs, rhs)
163     }
164 }
165
166 fn shift_mask_rhs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
167     bx: &mut Bx,
168     rhs: Bx::Value,
169 ) -> Bx::Value {
170     let rhs_llty = bx.val_ty(rhs);
171     let shift_val = shift_mask_val(bx, rhs_llty, rhs_llty, false);
172     bx.and(rhs, shift_val)
173 }
174
175 pub fn shift_mask_val<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
176     bx: &mut Bx,
177     llty: Bx::Type,
178     mask_llty: Bx::Type,
179     invert: bool,
180 ) -> Bx::Value {
181     let kind = bx.type_kind(llty);
182     match kind {
183         TypeKind::Integer => {
184             // i8/u8 can shift by at most 7, i16/u16 by at most 15, etc.
185             let val = bx.int_width(llty) - 1;
186             if invert {
187                 bx.const_int(mask_llty, !val as i64)
188             } else {
189                 bx.const_uint(mask_llty, val)
190             }
191         },
192         TypeKind::Vector => {
193             let mask = shift_mask_val(
194                 bx,
195                 bx.element_type(llty),
196                 bx.element_type(mask_llty),
197                 invert
198             );
199             bx.vector_splat(bx.vector_length(mask_llty), mask)
200         },
201         _ => bug!("shift_mask_val: expected Integer or Vector, found {:?}", kind),
202     }
203 }
204
205 pub fn span_invalid_monomorphization_error(a: &Session, b: Span, c: &str) {
206     span_err!(a, b, E0511, "{}", c);
207 }