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 SynchronizationScope {
64 SingleThread,
65 CrossThread,
66}
67
68#[derive(Copy, Clone, PartialEq, Debug)]
69pub enum TypeKind {
70 Void,
71 Half,
72 Float,
73 Double,
74 X86_FP80,
75 FP128,
76 PPC_FP128,
77 Label,
78 Integer,
79 Function,
80 Struct,
81 Array,
82 Pointer,
83 Vector,
84 Metadata,
85 Token,
86 ScalableVector,
87 BFloat,
88 X86_AMX,
89}
90
91mod temp_stable_hash_impls {
100 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
101
102 use crate::ModuleCodegen;
103
104 impl<HCX, M> HashStable<HCX> for ModuleCodegen<M> {
105 fn hash_stable(&self, _: &mut HCX, _: &mut StableHasher) {
106 }
108 }
109}
110
111pub(crate) fn build_langcall<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
112 bx: &Bx,
113 span: Span,
114 li: LangItem,
115) -> (Bx::FnAbiOfResult, Bx::Value, Instance<'tcx>) {
116 let tcx = bx.tcx();
117 let def_id = tcx.require_lang_item(li, span);
118 let instance = ty::Instance::mono(tcx, def_id);
119 (bx.fn_abi_of_instance(instance, ty::List::empty()), bx.get_fn_addr(instance), instance)
120}
121
122pub(crate) fn shift_mask_val<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
123 bx: &mut Bx,
124 llty: Bx::Type,
125 mask_llty: Bx::Type,
126 invert: bool,
127) -> Bx::Value {
128 let kind = bx.type_kind(llty);
129 match kind {
130 TypeKind::Integer => {
131 let val = bx.int_width(llty) - 1;
133 if invert {
134 bx.const_int(mask_llty, !val as i64)
135 } else {
136 bx.const_uint(mask_llty, val)
137 }
138 }
139 TypeKind::Vector => {
140 let mask =
141 shift_mask_val(bx, bx.element_type(llty), bx.element_type(mask_llty), invert);
142 bx.vector_splat(bx.vector_length(mask_llty), mask)
143 }
144 _ => bug!("shift_mask_val: expected Integer or Vector, found {:?}", kind),
145 }
146}
147
148pub fn asm_const_to_str<'tcx>(
149 tcx: TyCtxt<'tcx>,
150 sp: Span,
151 const_value: mir::ConstValue<'tcx>,
152 ty_and_layout: TyAndLayout<'tcx>,
153) -> String {
154 let mir::ConstValue::Scalar(scalar) = const_value else {
155 span_bug!(sp, "expected Scalar for promoted asm const, but got {:#?}", const_value)
156 };
157 let value = scalar.assert_scalar_int().to_bits(ty_and_layout.size);
158 match ty_and_layout.ty.kind() {
159 ty::Uint(_) => value.to_string(),
160 ty::Int(int_ty) => match int_ty.normalize(tcx.sess.target.pointer_width) {
161 ty::IntTy::I8 => (value as i8).to_string(),
162 ty::IntTy::I16 => (value as i16).to_string(),
163 ty::IntTy::I32 => (value as i32).to_string(),
164 ty::IntTy::I64 => (value as i64).to_string(),
165 ty::IntTy::I128 => (value as i128).to_string(),
166 ty::IntTy::Isize => unreachable!(),
167 },
168 _ => span_bug!(sp, "asm const has bad type {}", ty_and_layout.ty),
169 }
170}
171
172pub fn is_mingw_gnu_toolchain(target: &Target) -> bool {
173 target.vendor == "pc" && target.os == "windows" && target.env == "gnu" && target.abi.is_empty()
174}
175
176pub fn i686_decorated_name(
177 dll_import: &DllImport,
178 mingw: bool,
179 disable_name_mangling: bool,
180 force_fully_decorated: bool,
181) -> String {
182 let name = dll_import.name.as_str();
183
184 let (add_prefix, add_suffix) = match (force_fully_decorated, dll_import.import_name_type) {
185 (_, Some(PeImportNameType::NoPrefix)) => (false, true),
188 (false, Some(PeImportNameType::Undecorated)) => (false, false),
189 _ => (true, true),
190 };
191
192 let mut decorated_name = String::with_capacity(name.len() + 6);
194
195 if disable_name_mangling {
196 decorated_name.push('\x01');
199 }
200
201 let prefix = if add_prefix && dll_import.is_fn {
202 match dll_import.calling_convention {
203 DllCallingConvention::C | DllCallingConvention::Vectorcall(_) => None,
204 DllCallingConvention::Stdcall(_) => (!mingw
205 || dll_import.import_name_type == Some(PeImportNameType::Decorated))
206 .then_some('_'),
207 DllCallingConvention::Fastcall(_) => Some('@'),
208 }
209 } else if !dll_import.is_fn && !mingw {
210 Some('_')
212 } else {
213 None
214 };
215 if let Some(prefix) = prefix {
216 decorated_name.push(prefix);
217 }
218
219 decorated_name.push_str(name);
220
221 if add_suffix && dll_import.is_fn {
222 use std::fmt::Write;
223
224 match dll_import.calling_convention {
225 DllCallingConvention::C => {}
226 DllCallingConvention::Stdcall(arg_list_size)
227 | DllCallingConvention::Fastcall(arg_list_size) => {
228 write!(&mut decorated_name, "@{arg_list_size}").unwrap();
229 }
230 DllCallingConvention::Vectorcall(arg_list_size) => {
231 write!(&mut decorated_name, "@@{arg_list_size}").unwrap();
232 }
233 }
234 }
235
236 decorated_name
237}