1#![allow(non_camel_case_types)]
2
3use rustc_hir::LangItem;
4use rustc_middle::ty::layout::TyAndLayout;
5use rustc_middle::ty::{self, Instance, TyCtxt};
6use rustc_middle::{bug, mir, span_bug};
7use rustc_session::cstore::{DllCallingConvention, DllImport, PeImportNameType};
8use rustc_span::Span;
9use rustc_target::spec::Target;
10
11use crate::traits::*;
12
13#[derive(Copy, Clone, Debug)]
14pub enum IntPredicate {
15 IntEQ,
16 IntNE,
17 IntUGT,
18 IntUGE,
19 IntULT,
20 IntULE,
21 IntSGT,
22 IntSGE,
23 IntSLT,
24 IntSLE,
25}
26
27#[derive(Copy, Clone, Debug)]
28pub enum RealPredicate {
29 RealPredicateFalse,
30 RealOEQ,
31 RealOGT,
32 RealOGE,
33 RealOLT,
34 RealOLE,
35 RealONE,
36 RealORD,
37 RealUNO,
38 RealUEQ,
39 RealUGT,
40 RealUGE,
41 RealULT,
42 RealULE,
43 RealUNE,
44 RealPredicateTrue,
45}
46
47#[derive(Copy, Clone, PartialEq, Debug)]
48pub 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#[derive(Copy, Clone, Debug)]
63pub enum AtomicOrdering {
64 Unordered,
65 Relaxed,
66 Acquire,
67 Release,
68 AcquireRelease,
69 SequentiallyConsistent,
70}
71
72#[derive(Copy, Clone, Debug)]
73pub enum SynchronizationScope {
74 SingleThread,
75 CrossThread,
76}
77
78#[derive(Copy, Clone, PartialEq, Debug)]
79pub 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 Token,
96 ScalableVector,
97 BFloat,
98 X86_AMX,
99}
100
101mod temp_stable_hash_impls {
110 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
111
112 use crate::ModuleCodegen;
113
114 impl<HCX, M> HashStable<HCX> for ModuleCodegen<M> {
115 fn hash_stable(&self, _: &mut HCX, _: &mut StableHasher) {
116 }
118 }
119}
120
121pub(crate) fn build_langcall<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
122 bx: &Bx,
123 span: Option<Span>,
124 li: LangItem,
125) -> (Bx::FnAbiOfResult, Bx::Value, Instance<'tcx>) {
126 let tcx = bx.tcx();
127 let def_id = tcx.require_lang_item(li, span);
128 let instance = ty::Instance::mono(tcx, def_id);
129 (bx.fn_abi_of_instance(instance, ty::List::empty()), bx.get_fn_addr(instance), instance)
130}
131
132pub(crate) fn shift_mask_val<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
133 bx: &mut Bx,
134 llty: Bx::Type,
135 mask_llty: Bx::Type,
136 invert: bool,
137) -> Bx::Value {
138 let kind = bx.type_kind(llty);
139 match kind {
140 TypeKind::Integer => {
141 let val = bx.int_width(llty) - 1;
143 if invert {
144 bx.const_int(mask_llty, !val as i64)
145 } else {
146 bx.const_uint(mask_llty, val)
147 }
148 }
149 TypeKind::Vector => {
150 let mask =
151 shift_mask_val(bx, bx.element_type(llty), bx.element_type(mask_llty), invert);
152 bx.vector_splat(bx.vector_length(mask_llty), mask)
153 }
154 _ => bug!("shift_mask_val: expected Integer or Vector, found {:?}", kind),
155 }
156}
157
158pub fn asm_const_to_str<'tcx>(
159 tcx: TyCtxt<'tcx>,
160 sp: Span,
161 const_value: mir::ConstValue<'tcx>,
162 ty_and_layout: TyAndLayout<'tcx>,
163) -> String {
164 let mir::ConstValue::Scalar(scalar) = const_value else {
165 span_bug!(sp, "expected Scalar for promoted asm const, but got {:#?}", const_value)
166 };
167 let value = scalar.assert_scalar_int().to_bits(ty_and_layout.size);
168 match ty_and_layout.ty.kind() {
169 ty::Uint(_) => value.to_string(),
170 ty::Int(int_ty) => match int_ty.normalize(tcx.sess.target.pointer_width) {
171 ty::IntTy::I8 => (value as i8).to_string(),
172 ty::IntTy::I16 => (value as i16).to_string(),
173 ty::IntTy::I32 => (value as i32).to_string(),
174 ty::IntTy::I64 => (value as i64).to_string(),
175 ty::IntTy::I128 => (value as i128).to_string(),
176 ty::IntTy::Isize => unreachable!(),
177 },
178 _ => span_bug!(sp, "asm const has bad type {}", ty_and_layout.ty),
179 }
180}
181
182pub fn is_mingw_gnu_toolchain(target: &Target) -> bool {
183 target.vendor == "pc" && target.os == "windows" && target.env == "gnu" && target.abi.is_empty()
184}
185
186pub fn i686_decorated_name(
187 dll_import: &DllImport,
188 mingw: bool,
189 disable_name_mangling: bool,
190 force_fully_decorated: bool,
191) -> String {
192 let name = dll_import.name.as_str();
193
194 let (add_prefix, add_suffix) = match (force_fully_decorated, dll_import.import_name_type) {
195 (_, Some(PeImportNameType::NoPrefix)) => (false, true),
198 (false, Some(PeImportNameType::Undecorated)) => (false, false),
199 _ => (true, true),
200 };
201
202 let mut decorated_name = String::with_capacity(name.len() + 6);
204
205 if disable_name_mangling {
206 decorated_name.push('\x01');
209 }
210
211 let prefix = if add_prefix && dll_import.is_fn {
212 match dll_import.calling_convention {
213 DllCallingConvention::C | DllCallingConvention::Vectorcall(_) => None,
214 DllCallingConvention::Stdcall(_) => (!mingw
215 || dll_import.import_name_type == Some(PeImportNameType::Decorated))
216 .then_some('_'),
217 DllCallingConvention::Fastcall(_) => Some('@'),
218 }
219 } else if !dll_import.is_fn && !mingw {
220 Some('_')
222 } else {
223 None
224 };
225 if let Some(prefix) = prefix {
226 decorated_name.push(prefix);
227 }
228
229 decorated_name.push_str(name);
230
231 if add_suffix && dll_import.is_fn {
232 use std::fmt::Write;
233
234 match dll_import.calling_convention {
235 DllCallingConvention::C => {}
236 DllCallingConvention::Stdcall(arg_list_size)
237 | DllCallingConvention::Fastcall(arg_list_size) => {
238 write!(&mut decorated_name, "@{arg_list_size}").unwrap();
239 }
240 DllCallingConvention::Vectorcall(arg_list_size) => {
241 write!(&mut decorated_name, "@@{arg_list_size}").unwrap();
242 }
243 }
244 }
245
246 decorated_name
247}