rustc_codegen_ssa/
common.rs

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
91// FIXME(mw): Anything that is produced via DepGraph::with_task() must implement
92//            the HashStable trait. Normally DepGraph::with_task() calls are
93//            hidden behind queries, but CGU creation is a special case in two
94//            ways: (1) it's not a query and (2) CGU are output nodes, so their
95//            Fingerprints are not actually needed. It remains to be clarified
96//            how exactly this case will be handled in the red/green system but
97//            for now we content ourselves with providing a no-op HashStable
98//            implementation for CGUs.
99mod 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            // do nothing
107        }
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            // i8/u8 can shift by at most 7, i16/u16 by at most 15, etc.
132            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        // No prefix is a bit weird, in that LLVM/ar_archive_writer won't emit it, so we will
186        // ignore `force_fully_decorated` and always partially decorate it.
187        (_, Some(PeImportNameType::NoPrefix)) => (false, true),
188        (false, Some(PeImportNameType::Undecorated)) => (false, false),
189        _ => (true, true),
190    };
191
192    // Worst case: +1 for disable name mangling, +1 for prefix, +4 for suffix (@@__).
193    let mut decorated_name = String::with_capacity(name.len() + 6);
194
195    if disable_name_mangling {
196        // LLVM uses a binary 1 ('\x01') prefix to a name to indicate that mangling needs to be
197        // disabled.
198        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        // For static variables, prefix with '_' on MSVC.
211        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}
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy