2020-09-25 23:17:54 +00:00
|
|
|
#![allow(non_camel_case_types)]
|
2018-09-28 10:18:03 +00:00
|
|
|
|
2019-12-31 20:25:16 +00:00
|
|
|
use rustc_errors::struct_span_err;
|
2020-03-31 19:38:14 +00:00
|
|
|
use rustc_hir as hir;
|
|
|
|
use rustc_hir::LangItem;
|
2021-04-11 19:51:28 +00:00
|
|
|
use rustc_middle::mir::interpret::ConstValue;
|
|
|
|
use rustc_middle::ty::{self, layout::TyAndLayout, Ty, TyCtxt};
|
2020-03-11 11:49:08 +00:00
|
|
|
use rustc_session::Session;
|
2019-12-31 17:15:40 +00:00
|
|
|
use rustc_span::Span;
|
2018-11-13 10:53:29 +00:00
|
|
|
|
2019-02-09 14:31:47 +00:00
|
|
|
use crate::base;
|
2020-03-31 19:38:14 +00:00
|
|
|
use crate::traits::*;
|
2018-11-13 10:53:29 +00:00
|
|
|
|
2022-05-24 00:00:00 +00:00
|
|
|
#[derive(Copy, Clone)]
|
2018-09-28 09:40:59 +00:00
|
|
|
pub enum IntPredicate {
|
|
|
|
IntEQ,
|
|
|
|
IntNE,
|
|
|
|
IntUGT,
|
|
|
|
IntUGE,
|
|
|
|
IntULT,
|
|
|
|
IntULE,
|
|
|
|
IntSGT,
|
|
|
|
IntSGE,
|
|
|
|
IntSLT,
|
|
|
|
IntSLE,
|
|
|
|
}
|
2018-09-28 10:18:03 +00:00
|
|
|
|
2022-05-24 00:00:00 +00:00
|
|
|
#[derive(Copy, Clone)]
|
2018-09-28 10:18:03 +00:00
|
|
|
pub enum RealPredicate {
|
|
|
|
RealPredicateFalse,
|
|
|
|
RealOEQ,
|
|
|
|
RealOGT,
|
|
|
|
RealOGE,
|
|
|
|
RealOLT,
|
|
|
|
RealOLE,
|
|
|
|
RealONE,
|
|
|
|
RealORD,
|
|
|
|
RealUNO,
|
|
|
|
RealUEQ,
|
|
|
|
RealUGT,
|
|
|
|
RealUGE,
|
|
|
|
RealULT,
|
|
|
|
RealULE,
|
|
|
|
RealUNE,
|
|
|
|
RealPredicateTrue,
|
|
|
|
}
|
|
|
|
|
2022-05-24 00:00:00 +00:00
|
|
|
#[derive(Copy, Clone)]
|
2018-09-28 10:18:03 +00:00
|
|
|
pub enum AtomicRmwBinOp {
|
|
|
|
AtomicXchg,
|
|
|
|
AtomicAdd,
|
|
|
|
AtomicSub,
|
|
|
|
AtomicAnd,
|
|
|
|
AtomicNand,
|
|
|
|
AtomicOr,
|
|
|
|
AtomicXor,
|
|
|
|
AtomicMax,
|
|
|
|
AtomicMin,
|
|
|
|
AtomicUMax,
|
|
|
|
AtomicUMin,
|
|
|
|
}
|
|
|
|
|
2022-05-24 00:00:00 +00:00
|
|
|
#[derive(Copy, Clone)]
|
2018-09-28 10:18:03 +00:00
|
|
|
pub enum AtomicOrdering {
|
|
|
|
Unordered,
|
2022-05-24 00:00:00 +00:00
|
|
|
Relaxed,
|
2018-09-28 10:18:03 +00:00
|
|
|
Acquire,
|
|
|
|
Release,
|
|
|
|
AcquireRelease,
|
|
|
|
SequentiallyConsistent,
|
|
|
|
}
|
|
|
|
|
2022-05-24 00:00:00 +00:00
|
|
|
#[derive(Copy, Clone)]
|
2018-09-28 10:18:03 +00:00
|
|
|
pub enum SynchronizationScope {
|
|
|
|
SingleThread,
|
|
|
|
CrossThread,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Copy, Clone, PartialEq, Debug)]
|
|
|
|
pub enum TypeKind {
|
|
|
|
Void,
|
|
|
|
Half,
|
|
|
|
Float,
|
|
|
|
Double,
|
|
|
|
X86_FP80,
|
|
|
|
FP128,
|
|
|
|
PPC_FP128,
|
|
|
|
Label,
|
|
|
|
Integer,
|
|
|
|
Function,
|
|
|
|
Struct,
|
|
|
|
Array,
|
|
|
|
Pointer,
|
|
|
|
Vector,
|
|
|
|
Metadata,
|
|
|
|
X86_MMX,
|
|
|
|
Token,
|
2020-06-26 01:52:41 +00:00
|
|
|
ScalableVector,
|
|
|
|
BFloat,
|
2020-11-03 21:47:16 +00:00
|
|
|
X86_AMX,
|
2018-09-28 10:18:03 +00:00
|
|
|
}
|
2018-10-01 08:32:09 +00:00
|
|
|
|
|
|
|
// FIXME(mw): Anything that is produced via DepGraph::with_task() must implement
|
|
|
|
// the HashStable trait. Normally DepGraph::with_task() calls are
|
|
|
|
// hidden behind queries, but CGU creation is a special case in two
|
|
|
|
// ways: (1) it's not a query and (2) CGU are output nodes, so their
|
|
|
|
// Fingerprints are not actually needed. It remains to be clarified
|
|
|
|
// how exactly this case will be handled in the red/green system but
|
|
|
|
// for now we content ourselves with providing a no-op HashStable
|
|
|
|
// implementation for CGUs.
|
|
|
|
mod temp_stable_hash_impls {
|
2019-02-09 14:31:47 +00:00
|
|
|
use crate::ModuleCodegen;
|
2019-09-26 22:54:39 +00:00
|
|
|
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
2018-10-01 08:32:09 +00:00
|
|
|
|
|
|
|
impl<HCX, M> HashStable<HCX> for ModuleCodegen<M> {
|
2019-09-26 22:54:39 +00:00
|
|
|
fn hash_stable(&self, _: &mut HCX, _: &mut StableHasher) {
|
2018-10-01 08:32:09 +00:00
|
|
|
// do nothing
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-10-03 11:49:57 +00:00
|
|
|
|
2022-04-27 10:58:59 +00:00
|
|
|
pub fn build_langcall<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
|
|
|
bx: &Bx,
|
|
|
|
span: Option<Span>,
|
|
|
|
li: LangItem,
|
|
|
|
) -> (Bx::FnAbiOfResult, Bx::Value) {
|
|
|
|
let tcx = bx.tcx();
|
2022-04-28 12:18:01 +00:00
|
|
|
let def_id = tcx.require_lang_item(li, span);
|
2022-04-27 10:58:59 +00:00
|
|
|
let instance = ty::Instance::mono(tcx, def_id);
|
|
|
|
(bx.fn_abi_of_instance(instance, ty::List::empty()), bx.get_fn_addr(instance))
|
2018-10-03 11:49:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// To avoid UB from LLVM, these two functions mask RHS with an
|
2018-11-27 02:59:49 +00:00
|
|
|
// appropriate mask unconditionally (i.e., the fallback behavior for
|
2018-10-03 11:49:57 +00:00
|
|
|
// all shifts). For 32- and 64-bit types, this matches the semantics
|
|
|
|
// of Java. (See related discussion on #1877 and #10183.)
|
|
|
|
|
2019-06-14 16:39:39 +00:00
|
|
|
pub fn build_unchecked_lshift<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
2018-10-05 13:08:49 +00:00
|
|
|
bx: &mut Bx,
|
2018-10-03 11:49:57 +00:00
|
|
|
lhs: Bx::Value,
|
2019-06-16 09:41:24 +00:00
|
|
|
rhs: Bx::Value,
|
2018-10-03 11:49:57 +00:00
|
|
|
) -> Bx::Value {
|
|
|
|
let rhs = base::cast_shift_expr_rhs(bx, hir::BinOpKind::Shl, lhs, rhs);
|
|
|
|
// #1877, #10183: Ensure that input is always valid
|
|
|
|
let rhs = shift_mask_rhs(bx, rhs);
|
|
|
|
bx.shl(lhs, rhs)
|
|
|
|
}
|
|
|
|
|
2019-06-14 16:39:39 +00:00
|
|
|
pub fn build_unchecked_rshift<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
2018-10-05 13:08:49 +00:00
|
|
|
bx: &mut Bx,
|
2018-10-03 11:49:57 +00:00
|
|
|
lhs_t: Ty<'tcx>,
|
|
|
|
lhs: Bx::Value,
|
2019-06-16 09:41:24 +00:00
|
|
|
rhs: Bx::Value,
|
2018-10-03 11:49:57 +00:00
|
|
|
) -> Bx::Value {
|
|
|
|
let rhs = base::cast_shift_expr_rhs(bx, hir::BinOpKind::Shr, lhs, rhs);
|
|
|
|
// #1877, #10183: Ensure that input is always valid
|
|
|
|
let rhs = shift_mask_rhs(bx, rhs);
|
|
|
|
let is_signed = lhs_t.is_signed();
|
|
|
|
if is_signed { bx.ashr(lhs, rhs) } else { bx.lshr(lhs, rhs) }
|
|
|
|
}
|
|
|
|
|
2019-06-14 16:39:39 +00:00
|
|
|
fn shift_mask_rhs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
2018-10-05 13:08:49 +00:00
|
|
|
bx: &mut Bx,
|
2019-06-16 09:41:24 +00:00
|
|
|
rhs: Bx::Value,
|
2018-10-03 11:49:57 +00:00
|
|
|
) -> Bx::Value {
|
2018-11-27 18:00:25 +00:00
|
|
|
let rhs_llty = bx.val_ty(rhs);
|
2018-10-05 13:08:49 +00:00
|
|
|
let shift_val = shift_mask_val(bx, rhs_llty, rhs_llty, false);
|
|
|
|
bx.and(rhs, shift_val)
|
2018-10-03 11:49:57 +00:00
|
|
|
}
|
|
|
|
|
2019-06-14 16:39:39 +00:00
|
|
|
pub fn shift_mask_val<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
2018-10-05 13:08:49 +00:00
|
|
|
bx: &mut Bx,
|
2018-10-03 11:49:57 +00:00
|
|
|
llty: Bx::Type,
|
|
|
|
mask_llty: Bx::Type,
|
2019-06-16 09:41:24 +00:00
|
|
|
invert: bool,
|
2018-10-03 11:49:57 +00:00
|
|
|
) -> Bx::Value {
|
2018-11-27 18:00:25 +00:00
|
|
|
let kind = bx.type_kind(llty);
|
2018-10-03 11:49:57 +00:00
|
|
|
match kind {
|
|
|
|
TypeKind::Integer => {
|
|
|
|
// i8/u8 can shift by at most 7, i16/u16 by at most 15, etc.
|
2018-11-27 18:00:25 +00:00
|
|
|
let val = bx.int_width(llty) - 1;
|
2018-10-03 11:49:57 +00:00
|
|
|
if invert {
|
2018-11-27 18:00:25 +00:00
|
|
|
bx.const_int(mask_llty, !val as i64)
|
2018-10-03 11:49:57 +00:00
|
|
|
} else {
|
2018-11-27 18:00:25 +00:00
|
|
|
bx.const_uint(mask_llty, val)
|
2018-10-03 11:49:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
TypeKind::Vector => {
|
|
|
|
let mask =
|
2018-11-27 18:00:25 +00:00
|
|
|
shift_mask_val(bx, bx.element_type(llty), bx.element_type(mask_llty), invert);
|
|
|
|
bx.vector_splat(bx.vector_length(mask_llty), mask)
|
2018-10-03 11:49:57 +00:00
|
|
|
}
|
|
|
|
_ => bug!("shift_mask_val: expected Integer or Vector, found {:?}", kind),
|
|
|
|
}
|
|
|
|
}
|
2019-10-12 12:49:03 +00:00
|
|
|
|
|
|
|
pub fn span_invalid_monomorphization_error(a: &Session, b: Span, c: &str) {
|
2019-12-31 20:25:16 +00:00
|
|
|
struct_span_err!(a, b, E0511, "{}", c).emit();
|
2019-10-12 12:49:03 +00:00
|
|
|
}
|
2021-04-11 19:51:28 +00:00
|
|
|
|
|
|
|
pub fn asm_const_to_str<'tcx>(
|
|
|
|
tcx: TyCtxt<'tcx>,
|
|
|
|
sp: Span,
|
|
|
|
const_value: ConstValue<'tcx>,
|
|
|
|
ty_and_layout: TyAndLayout<'tcx>,
|
|
|
|
) -> String {
|
2022-02-18 23:48:49 +00:00
|
|
|
let ConstValue::Scalar(scalar) = const_value else {
|
|
|
|
span_bug!(sp, "expected Scalar for promoted asm const, but got {:#?}", const_value)
|
2021-04-11 19:51:28 +00:00
|
|
|
};
|
|
|
|
let value = scalar.assert_bits(ty_and_layout.size);
|
|
|
|
match ty_and_layout.ty.kind() {
|
|
|
|
ty::Uint(_) => value.to_string(),
|
|
|
|
ty::Int(int_ty) => match int_ty.normalize(tcx.sess.target.pointer_width) {
|
|
|
|
ty::IntTy::I8 => (value as i8).to_string(),
|
|
|
|
ty::IntTy::I16 => (value as i16).to_string(),
|
|
|
|
ty::IntTy::I32 => (value as i32).to_string(),
|
|
|
|
ty::IntTy::I64 => (value as i64).to_string(),
|
|
|
|
ty::IntTy::I128 => (value as i128).to_string(),
|
|
|
|
ty::IntTy::Isize => unreachable!(),
|
|
|
|
},
|
|
|
|
_ => span_bug!(sp, "asm const has bad type {}", ty_and_layout.ty),
|
|
|
|
}
|
|
|
|
}
|