]> git.lizzy.rs Git - rust.git/blob - src/librustc_codegen_ssa/common.rs
Rollup merge of #71615 - RalfJung:share-machine-code, r=oli-obk
[rust.git] / src / librustc_codegen_ssa / common.rs
1 #![allow(non_camel_case_types, non_snake_case)]
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::ty::{Ty, TyCtxt};
8 use rustc_session::Session;
9 use rustc_span::Span;
10
11 use crate::base;
12 use crate::traits::BuilderMethods;
13 use crate::traits::*;
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 #[allow(dead_code)]
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     #[allow(dead_code)]
64     NotAtomic,
65     Unordered,
66     Monotonic,
67     // Consume,  // Not specified yet.
68     Acquire,
69     Release,
70     AcquireRelease,
71     SequentiallyConsistent,
72 }
73
74 pub enum SynchronizationScope {
75     // FIXME: figure out if this variant is needed at all.
76     #[allow(dead_code)]
77     Other,
78     SingleThread,
79     CrossThread,
80 }
81
82 #[derive(Copy, Clone, PartialEq, Debug)]
83 pub enum TypeKind {
84     Void,
85     Half,
86     Float,
87     Double,
88     X86_FP80,
89     FP128,
90     PPC_FP128,
91     Label,
92     Integer,
93     Function,
94     Struct,
95     Array,
96     Pointer,
97     Vector,
98     Metadata,
99     X86_MMX,
100     Token,
101 }
102
103 // FIXME(mw): Anything that is produced via DepGraph::with_task() must implement
104 //            the HashStable trait. Normally DepGraph::with_task() calls are
105 //            hidden behind queries, but CGU creation is a special case in two
106 //            ways: (1) it's not a query and (2) CGU are output nodes, so their
107 //            Fingerprints are not actually needed. It remains to be clarified
108 //            how exactly this case will be handled in the red/green system but
109 //            for now we content ourselves with providing a no-op HashStable
110 //            implementation for CGUs.
111 mod temp_stable_hash_impls {
112     use crate::ModuleCodegen;
113     use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
114
115     impl<HCX, M> HashStable<HCX> for ModuleCodegen<M> {
116         fn hash_stable(&self, _: &mut HCX, _: &mut StableHasher) {
117             // do nothing
118         }
119     }
120 }
121
122 pub fn langcall(tcx: TyCtxt<'_>, span: Option<Span>, msg: &str, li: LangItem) -> DefId {
123     tcx.lang_items().require(li).unwrap_or_else(|s| {
124         let msg = format!("{} {}", msg, s);
125         match span {
126             Some(span) => tcx.sess.span_fatal(span, &msg[..]),
127             None => tcx.sess.fatal(&msg[..]),
128         }
129     })
130 }
131
132 // To avoid UB from LLVM, these two functions mask RHS with an
133 // appropriate mask unconditionally (i.e., the fallback behavior for
134 // all shifts). For 32- and 64-bit types, this matches the semantics
135 // of Java. (See related discussion on #1877 and #10183.)
136
137 pub fn build_unchecked_lshift<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
138     bx: &mut Bx,
139     lhs: Bx::Value,
140     rhs: Bx::Value,
141 ) -> Bx::Value {
142     let rhs = base::cast_shift_expr_rhs(bx, hir::BinOpKind::Shl, lhs, rhs);
143     // #1877, #10183: Ensure that input is always valid
144     let rhs = shift_mask_rhs(bx, rhs);
145     bx.shl(lhs, rhs)
146 }
147
148 pub fn build_unchecked_rshift<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
149     bx: &mut Bx,
150     lhs_t: Ty<'tcx>,
151     lhs: Bx::Value,
152     rhs: Bx::Value,
153 ) -> Bx::Value {
154     let rhs = base::cast_shift_expr_rhs(bx, hir::BinOpKind::Shr, lhs, rhs);
155     // #1877, #10183: Ensure that input is always valid
156     let rhs = shift_mask_rhs(bx, rhs);
157     let is_signed = lhs_t.is_signed();
158     if is_signed { bx.ashr(lhs, rhs) } else { bx.lshr(lhs, rhs) }
159 }
160
161 fn shift_mask_rhs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
162     bx: &mut Bx,
163     rhs: Bx::Value,
164 ) -> Bx::Value {
165     let rhs_llty = bx.val_ty(rhs);
166     let shift_val = shift_mask_val(bx, rhs_llty, rhs_llty, false);
167     bx.and(rhs, shift_val)
168 }
169
170 pub fn shift_mask_val<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
171     bx: &mut Bx,
172     llty: Bx::Type,
173     mask_llty: Bx::Type,
174     invert: bool,
175 ) -> Bx::Value {
176     let kind = bx.type_kind(llty);
177     match kind {
178         TypeKind::Integer => {
179             // i8/u8 can shift by at most 7, i16/u16 by at most 15, etc.
180             let val = bx.int_width(llty) - 1;
181             if invert {
182                 bx.const_int(mask_llty, !val as i64)
183             } else {
184                 bx.const_uint(mask_llty, val)
185             }
186         }
187         TypeKind::Vector => {
188             let mask =
189                 shift_mask_val(bx, bx.element_type(llty), bx.element_type(mask_llty), invert);
190             bx.vector_splat(bx.vector_length(mask_llty), mask)
191         }
192         _ => bug!("shift_mask_val: expected Integer or Vector, found {:?}", kind),
193     }
194 }
195
196 pub fn span_invalid_monomorphization_error(a: &Session, b: Span, c: &str) {
197     struct_span_err!(a, b, E0511, "{}", c).emit();
198 }