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