1use std::assert_matches;
2use std::ops::Deref;
3
4use rustc_abi::{Align, Scalar, Size, WrappingRange};
5use rustc_ast::expand::typetree::{FncTree, TypeTree};
6use rustc_hir::attrs::AttributeKind;
7use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
8use rustc_middle::mir;
9use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, TyAndLayout};
10use rustc_middle::ty::typetree::typetree_from_ty;
11use rustc_middle::ty::{AtomicOrdering, Instance, Ty};
12use rustc_session::config::OptLevel;
13use rustc_span::Span;
14use rustc_target::callconv::FnAbi;
15
16use super::abi::AbiBuilderMethods;
17use super::asm::AsmBuilderMethods;
18use super::consts::ConstCodegenMethods;
19use super::coverageinfo::CoverageInfoBuilderMethods;
20use super::debuginfo::DebugInfoBuilderMethods;
21use super::intrinsic::IntrinsicCallBuilderMethods;
22use super::misc::MiscCodegenMethods;
23use super::type_::{ArgAbiBuilderMethods, BaseTypeCodegenMethods, LayoutTypeCodegenMethods};
24use super::{CodegenMethods, StaticBuilderMethods};
25use crate::MemFlags;
26use crate::common::{AtomicRmwBinOp, IntPredicate, RealPredicate, SynchronizationScope, TypeKind};
27use crate::mir::operand::{OperandRef, OperandValue};
28use crate::mir::place::{PlaceRef, PlaceValue};
29
30#[derive(#[automatically_derived]
impl ::core::marker::Copy for OverflowOp { }Copy, #[automatically_derived]
impl ::core::clone::Clone for OverflowOp {
#[inline]
fn clone(&self) -> OverflowOp { *self }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for OverflowOp {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f,
match self {
OverflowOp::Add => "Add",
OverflowOp::Sub => "Sub",
OverflowOp::Mul => "Mul",
})
}
}Debug, #[automatically_derived]
impl ::core::cmp::PartialEq for OverflowOp {
#[inline]
fn eq(&self, other: &OverflowOp) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for OverflowOp {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {}
}Eq)]
31pub enum OverflowOp {
32 Add,
33 Sub,
34 Mul,
35}
36
37pub trait BuilderMethods<'a, 'tcx>:
38 Sized
39 + LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>>
40 + FnAbiOf<'tcx, FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>>
41 + Deref<Target = Self::CodegenCx>
42 + CoverageInfoBuilderMethods<'tcx>
43 + DebugInfoBuilderMethods<'tcx>
44 + ArgAbiBuilderMethods<'tcx>
45 + AbiBuilderMethods
46 + IntrinsicCallBuilderMethods<'tcx>
47 + AsmBuilderMethods<'tcx>
48 + StaticBuilderMethods
49{
50 type CodegenCx: CodegenMethods<
54 'tcx,
55 Value = Self::Value,
56 Function = Self::Function,
57 BasicBlock = Self::BasicBlock,
58 Type = Self::Type,
59 FunctionSignature = Self::FunctionSignature,
60 Funclet = Self::Funclet,
61 DIScope = Self::DIScope,
62 DILocation = Self::DILocation,
63 DIVariable = Self::DIVariable,
64 >;
65
66 fn build(cx: &'a Self::CodegenCx, llbb: Self::BasicBlock) -> Self;
67
68 fn cx(&self) -> &Self::CodegenCx;
69 fn llbb(&self) -> Self::BasicBlock;
70
71 fn set_span(&mut self, span: Span);
72
73 fn append_block(cx: &'a Self::CodegenCx, llfn: Self::Function, name: &str) -> Self::BasicBlock;
75
76 fn append_sibling_block(&mut self, name: &str) -> Self::BasicBlock;
77
78 fn switch_to_block(&mut self, llbb: Self::BasicBlock);
79
80 fn ret_void(&mut self);
81 fn ret(&mut self, v: Self::Value);
82 fn br(&mut self, dest: Self::BasicBlock);
83 fn br_with_attrs(&mut self, dest: Self::BasicBlock, _attributes: &[AttributeKind]) {
84 self.br(dest)
85 }
86 fn cond_br(
87 &mut self,
88 cond: Self::Value,
89 then_llbb: Self::BasicBlock,
90 else_llbb: Self::BasicBlock,
91 );
92
93 fn cond_br_with_expect(
100 &mut self,
101 mut cond: Self::Value,
102 then_llbb: Self::BasicBlock,
103 else_llbb: Self::BasicBlock,
104 expect: Option<bool>,
105 ) {
106 if let Some(expect) = expect {
107 cond = self.expect(cond, expect);
108 }
109 self.cond_br(cond, then_llbb, else_llbb)
110 }
111
112 fn switch(
113 &mut self,
114 v: Self::Value,
115 else_llbb: Self::BasicBlock,
116 cases: impl ExactSizeIterator<Item = (u128, Self::BasicBlock)>,
117 );
118
119 fn switch_with_weights(
123 &mut self,
124 v: Self::Value,
125 else_llbb: Self::BasicBlock,
126 _else_is_cold: bool,
127 cases: impl ExactSizeIterator<Item = (u128, Self::BasicBlock, bool)>,
128 ) {
129 self.switch(v, else_llbb, cases.map(|(val, bb, _)| (val, bb)))
130 }
131
132 fn invoke(
133 &mut self,
134 llty: Self::FunctionSignature,
135 fn_attrs: Option<&CodegenFnAttrs>,
136 fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>,
137 llfn: Self::Value,
138 args: &[Self::Value],
139 then: Self::BasicBlock,
140 catch: Self::BasicBlock,
141 funclet: Option<&Self::Funclet>,
142 instance: Option<Instance<'tcx>>,
143 ) -> Self::Value;
144 fn unreachable(&mut self);
145
146 fn unreachable_nonterminator(&mut self) {
148 let const_true = self.cx().const_bool(true);
152 let poison_ptr = self.const_poison(self.cx().type_ptr());
153 self.store(const_true, poison_ptr, Align::ONE);
154 }
155
156 fn add(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
157 fn fadd(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
158 fn fadd_fast(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
159 fn fadd_algebraic(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
160 fn sub(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
161 fn fsub(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
162 fn fsub_fast(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
163 fn fsub_algebraic(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
164 fn mul(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
165 fn fmul(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
166 fn fmul_fast(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
167 fn fmul_algebraic(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
168 fn udiv(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
169 fn exactudiv(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
170 fn sdiv(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
171 fn exactsdiv(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
172 fn fdiv(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
173 fn fdiv_fast(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
174 fn fdiv_algebraic(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
175 fn urem(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
176 fn srem(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
177 fn frem(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
178 fn frem_fast(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
179 fn frem_algebraic(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
180 fn shl(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
183 fn lshr(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
187 fn ashr(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
191 fn unchecked_sadd(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value {
192 self.add(lhs, rhs)
193 }
194 fn unchecked_uadd(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value {
195 self.add(lhs, rhs)
196 }
197 fn unchecked_suadd(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value {
198 self.unchecked_sadd(lhs, rhs)
199 }
200 fn unchecked_ssub(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value {
201 self.sub(lhs, rhs)
202 }
203 fn unchecked_usub(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value {
204 self.sub(lhs, rhs)
205 }
206 fn unchecked_susub(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value {
207 self.unchecked_ssub(lhs, rhs)
208 }
209 fn unchecked_smul(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value {
210 self.mul(lhs, rhs)
211 }
212 fn unchecked_umul(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value {
213 self.mul(lhs, rhs)
214 }
215 fn unchecked_sumul(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value {
216 self.unchecked_smul(lhs, rhs)
219 }
220 fn and(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
221 fn or(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
222 fn or_disjoint(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value {
225 self.or(lhs, rhs)
226 }
227 fn xor(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
228 fn neg(&mut self, v: Self::Value) -> Self::Value;
229 fn fneg(&mut self, v: Self::Value) -> Self::Value;
230 fn not(&mut self, v: Self::Value) -> Self::Value;
231
232 fn checked_binop(
233 &mut self,
234 oop: OverflowOp,
235 ty: Ty<'tcx>,
236 lhs: Self::Value,
237 rhs: Self::Value,
238 ) -> (Self::Value, Self::Value);
239
240 fn from_immediate(&mut self, val: Self::Value) -> Self::Value;
241 fn to_immediate_scalar(&mut self, val: Self::Value, scalar: Scalar) -> Self::Value;
242
243 fn alloca(&mut self, size: Size, align: Align) -> Self::Value;
244 fn alloca_with_ty(&mut self, layout: TyAndLayout<'tcx>) -> Self::Value;
245
246 fn load(&mut self, ty: Self::Type, ptr: Self::Value, align: Align) -> Self::Value;
247 fn volatile_load(&mut self, ty: Self::Type, ptr: Self::Value, align: Align) -> Self::Value;
248 fn atomic_load(
249 &mut self,
250 ty: Self::Type,
251 ptr: Self::Value,
252 order: AtomicOrdering,
253 volatile: bool,
254 size: Size,
255 ) -> Self::Value;
256 fn load_from_place(&mut self, ty: Self::Type, place: PlaceValue<Self::Value>) -> Self::Value {
257 {
match (&place.llextra, &None) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};assert_eq!(place.llextra, None);
258 self.load(ty, place.llval, place.align)
259 }
260 fn load_operand(&mut self, place: PlaceRef<'tcx, Self::Value>)
261 -> OperandRef<'tcx, Self::Value>;
262
263 fn write_operand_repeatedly(
265 &mut self,
266 elem: OperandRef<'tcx, Self::Value>,
267 count: u64,
268 dest: PlaceRef<'tcx, Self::Value>,
269 );
270
271 fn assume_integer_range(&mut self, imm: Self::Value, ty: Self::Type, range: WrappingRange) {
276 let WrappingRange { start, end } = range;
277
278 let shifted = if start == 0 {
282 imm
283 } else {
284 let low = self.const_uint_big(ty, start);
285 self.sub(imm, low)
286 };
287 let width = self.const_uint_big(ty, u128::wrapping_sub(end, start));
288 let cmp = self.icmp(IntPredicate::IntULE, shifted, width);
289 self.assume(cmp);
290 }
291
292 fn assume_nonnull(&mut self, val: Self::Value) {
296 let null = self.const_null(self.type_ptr());
301 let is_null = self.icmp(IntPredicate::IntNE, val, null);
302 self.assume(is_null);
303 }
304
305 fn range_metadata(&mut self, load: Self::Value, range: WrappingRange);
306 fn nonnull_metadata(&mut self, load: Self::Value);
307
308 fn store(&mut self, val: Self::Value, ptr: Self::Value, align: Align) -> Self::Value;
309 fn store_to_place(&mut self, val: Self::Value, place: PlaceValue<Self::Value>) -> Self::Value {
310 {
match (&place.llextra, &None) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};assert_eq!(place.llextra, None);
311 self.store(val, place.llval, place.align)
312 }
313 fn store_with_flags(
314 &mut self,
315 val: Self::Value,
316 ptr: Self::Value,
317 align: Align,
318 flags: MemFlags,
319 ) -> Self::Value;
320 fn store_to_place_with_flags(
321 &mut self,
322 val: Self::Value,
323 place: PlaceValue<Self::Value>,
324 flags: MemFlags,
325 ) -> Self::Value {
326 {
match (&place.llextra, &None) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};assert_eq!(place.llextra, None);
327 self.store_with_flags(val, place.llval, place.align, flags)
328 }
329 fn atomic_store(
330 &mut self,
331 val: Self::Value,
332 ptr: Self::Value,
333 order: AtomicOrdering,
334 volatile: bool,
335 size: Size,
336 );
337
338 fn gep(&mut self, ty: Self::Type, ptr: Self::Value, indices: &[Self::Value]) -> Self::Value;
339 fn inbounds_gep(
340 &mut self,
341 ty: Self::Type,
342 ptr: Self::Value,
343 indices: &[Self::Value],
344 ) -> Self::Value;
345 fn inbounds_nuw_gep(
346 &mut self,
347 ty: Self::Type,
348 ptr: Self::Value,
349 indices: &[Self::Value],
350 ) -> Self::Value {
351 self.inbounds_gep(ty, ptr, indices)
352 }
353 fn ptradd(&mut self, ptr: Self::Value, offset: Self::Value) -> Self::Value {
354 self.gep(self.cx().type_i8(), ptr, &[offset])
355 }
356 fn inbounds_ptradd(&mut self, ptr: Self::Value, offset: Self::Value) -> Self::Value {
357 self.inbounds_gep(self.cx().type_i8(), ptr, &[offset])
358 }
359
360 fn trunc(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value;
361 fn unchecked_utrunc(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value {
364 self.trunc(val, dest_ty)
365 }
366 fn unchecked_strunc(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value {
369 self.trunc(val, dest_ty)
370 }
371
372 fn sext(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value;
373 fn fptoui_sat(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value;
374 fn fptosi_sat(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value;
375 fn fptoui(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value;
376 fn fptosi(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value;
377 fn uitofp(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value;
378 fn sitofp(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value;
379 fn fptrunc(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value;
380 fn fpext(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value;
381 fn ptrtoint(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value;
382 fn inttoptr(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value;
383 fn bitcast(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value;
384 fn intcast(&mut self, val: Self::Value, dest_ty: Self::Type, is_signed: bool) -> Self::Value;
385 fn pointercast(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value;
386
387 fn cast_float_to_int(
388 &mut self,
389 signed: bool,
390 x: Self::Value,
391 dest_ty: Self::Type,
392 ) -> Self::Value {
393 let in_ty = self.cx().val_ty(x);
394 let (float_ty, int_ty) = if self.cx().type_kind(dest_ty) == TypeKind::Vector
395 && self.cx().type_kind(in_ty) == TypeKind::Vector
396 {
397 (self.cx().element_type(in_ty), self.cx().element_type(dest_ty))
398 } else {
399 (in_ty, dest_ty)
400 };
401 {
match self.cx().type_kind(float_ty) {
TypeKind::Half | TypeKind::Float | TypeKind::Double | TypeKind::FP128
=> {}
ref left_val => {
::core::panicking::assert_matches_failed(left_val,
"TypeKind::Half | TypeKind::Float | TypeKind::Double | TypeKind::FP128",
::core::option::Option::None);
}
}
};assert_matches!(
402 self.cx().type_kind(float_ty),
403 TypeKind::Half | TypeKind::Float | TypeKind::Double | TypeKind::FP128
404 );
405 {
match (&self.cx().type_kind(int_ty), &TypeKind::Integer) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};assert_eq!(self.cx().type_kind(int_ty), TypeKind::Integer);
406
407 if let Some(false) = self.cx().sess().opts.unstable_opts.saturating_float_casts {
408 return if signed { self.fptosi(x, dest_ty) } else { self.fptoui(x, dest_ty) };
409 }
410
411 if signed { self.fptosi_sat(x, dest_ty) } else { self.fptoui_sat(x, dest_ty) }
412 }
413
414 fn icmp(&mut self, op: IntPredicate, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
415 fn fcmp(&mut self, op: RealPredicate, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
416
417 fn three_way_compare(
419 &mut self,
420 ty: Ty<'tcx>,
421 lhs: Self::Value,
422 rhs: Self::Value,
423 ) -> Self::Value {
424 use std::cmp::Ordering;
429 let pred = |op| crate::base::bin_op_to_icmp_predicate(op, ty.is_signed());
430 if self.cx().sess().opts.optimize == OptLevel::No {
431 let is_gt = self.icmp(pred(mir::BinOp::Gt), lhs, rhs);
437 let gtext = self.zext(is_gt, self.type_i8());
438 let is_lt = self.icmp(pred(mir::BinOp::Lt), lhs, rhs);
439 let ltext = self.zext(is_lt, self.type_i8());
440 self.unchecked_ssub(gtext, ltext)
441 } else {
442 let is_lt = self.icmp(pred(mir::BinOp::Lt), lhs, rhs);
445 let is_ne = self.icmp(pred(mir::BinOp::Ne), lhs, rhs);
446 let ge = self.select(
447 is_ne,
448 self.cx().const_i8(Ordering::Greater as i8),
449 self.cx().const_i8(Ordering::Equal as i8),
450 );
451 self.select(is_lt, self.cx().const_i8(Ordering::Less as i8), ge)
452 }
453 }
454
455 fn memcpy(
456 &mut self,
457 dst: Self::Value,
458 dst_align: Align,
459 src: Self::Value,
460 src_align: Align,
461 size: Self::Value,
462 flags: MemFlags,
463 tt: Option<FncTree>,
464 );
465 fn memmove(
466 &mut self,
467 dst: Self::Value,
468 dst_align: Align,
469 src: Self::Value,
470 src_align: Align,
471 size: Self::Value,
472 flags: MemFlags,
473 );
474 fn memset(
475 &mut self,
476 ptr: Self::Value,
477 fill_byte: Self::Value,
478 size: Self::Value,
479 align: Align,
480 flags: MemFlags,
481 );
482
483 fn vscale(&mut self, ty: Self::Type) -> Self::Value;
487
488 fn typed_place_copy(
495 &mut self,
496 dst: PlaceValue<Self::Value>,
497 src: PlaceValue<Self::Value>,
498 layout: TyAndLayout<'tcx>,
499 ) {
500 self.typed_place_copy_with_flags(dst, src, layout, MemFlags::empty());
501 }
502
503 fn typed_place_copy_with_flags(
504 &mut self,
505 dst: PlaceValue<Self::Value>,
506 src: PlaceValue<Self::Value>,
507 layout: TyAndLayout<'tcx>,
508 flags: MemFlags,
509 ) {
510 if !layout.is_sized() {
{
::core::panicking::panic_fmt(format_args!("cannot typed-copy an unsigned type"));
}
};assert!(layout.is_sized(), "cannot typed-copy an unsigned type");
511 if !src.llextra.is_none() {
{
::core::panicking::panic_fmt(format_args!("cannot directly copy from unsized values"));
}
};assert!(src.llextra.is_none(), "cannot directly copy from unsized values");
512 if !dst.llextra.is_none() {
{
::core::panicking::panic_fmt(format_args!("cannot directly copy into unsized values"));
}
};assert!(dst.llextra.is_none(), "cannot directly copy into unsized values");
513 if flags.contains(MemFlags::NONTEMPORAL) {
514 let ty = self.backend_type(layout);
516 let val = self.load_from_place(ty, src);
517 self.store_to_place_with_flags(val, dst, flags);
518 } else if self.sess().opts.optimize == OptLevel::No
519 && layout.backend_repr.is_scalar_or_simd()
520 {
521 let temp = self.load_operand(src.with_type(layout));
524 temp.val.store_with_flags(self, dst.with_type(layout), flags);
525 } else if !layout.is_zst() {
526 let tt = typetree_from_ty(self.tcx(), layout.ty);
527 let tt = tt.add_indirection();
529 let fnc_tree = FncTree { args: ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[tt.clone(), tt]))vec![tt.clone(), tt], ret: TypeTree::new() };
530 let bytes = self.const_usize(layout.size.bytes());
531 let bytes = if layout.peel_transparent_wrappers(self).ty.is_scalable_vector() {
532 let vscale = self.vscale(self.type_i64());
533 self.mul(vscale, bytes)
534 } else {
535 bytes
536 };
537 self.memcpy(dst.llval, dst.align, src.llval, src.align, bytes, flags, Some(fnc_tree));
538 }
539 }
540
541 fn typed_place_swap(
549 &mut self,
550 left: PlaceValue<Self::Value>,
551 right: PlaceValue<Self::Value>,
552 layout: TyAndLayout<'tcx>,
553 ) {
554 let mut temp = self.load_operand(left.with_type(layout));
555 if let OperandValue::Ref(..) = temp.val {
556 let alloca = PlaceRef::alloca(self, layout);
558 self.typed_place_copy(alloca.val, left, layout);
559 temp = self.load_operand(alloca);
560 }
561 self.typed_place_copy(left, right, layout);
562 temp.val.store(self, right.with_type(layout));
563 }
564
565 fn select(
566 &mut self,
567 cond: Self::Value,
568 then_val: Self::Value,
569 else_val: Self::Value,
570 ) -> Self::Value;
571
572 fn va_arg(&mut self, list: Self::Value, ty: Self::Type) -> Self::Value;
573 fn extract_element(&mut self, vec: Self::Value, idx: Self::Value) -> Self::Value;
574 fn vector_splat(&mut self, num_elts: usize, elt: Self::Value) -> Self::Value;
575 fn extract_value(&mut self, agg_val: Self::Value, idx: u64) -> Self::Value;
576 fn insert_value(&mut self, agg_val: Self::Value, elt: Self::Value, idx: u64) -> Self::Value;
577
578 fn set_personality_fn(&mut self, personality: Self::Function);
579
580 fn cleanup_landing_pad(&mut self, pers_fn: Self::Function) -> (Self::Value, Self::Value);
582 fn filter_landing_pad(&mut self, pers_fn: Self::Function);
583 fn resume(&mut self, exn0: Self::Value, exn1: Self::Value);
584
585 fn cleanup_pad(&mut self, parent: Option<Self::Value>, args: &[Self::Value]) -> Self::Funclet;
587 fn cleanup_ret(&mut self, funclet: &Self::Funclet, unwind: Option<Self::BasicBlock>);
588 fn catch_pad(&mut self, parent: Self::Value, args: &[Self::Value]) -> Self::Funclet;
589 fn catch_switch(
590 &mut self,
591 parent: Option<Self::Value>,
592 unwind: Option<Self::BasicBlock>,
593 handlers: &[Self::BasicBlock],
594 ) -> Self::Value;
595 fn get_funclet_cleanuppad(&self, funclet: &Self::Funclet) -> Self::Value;
596
597 fn atomic_cmpxchg(
598 &mut self,
599 dst: Self::Value,
600 cmp: Self::Value,
601 src: Self::Value,
602 order: AtomicOrdering,
603 failure_order: AtomicOrdering,
604 weak: bool,
605 ) -> (Self::Value, Self::Value);
606 fn atomic_rmw(
609 &mut self,
610 op: AtomicRmwBinOp,
611 dst: Self::Value,
612 src: Self::Value,
613 order: AtomicOrdering,
614 ret_ptr: bool,
615 ) -> Self::Value;
616 fn atomic_fence(&mut self, order: AtomicOrdering, scope: SynchronizationScope);
617 fn set_invariant_load(&mut self, load: Self::Value);
618
619 fn lifetime_start(&mut self, ptr: Self::Value, size: Size);
621
622 fn lifetime_end(&mut self, ptr: Self::Value, size: Size);
624
625 fn call(
650 &mut self,
651 llty: Self::FunctionSignature,
652 caller_attrs: Option<&CodegenFnAttrs>,
653 fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>,
654 fn_val: Self::Value,
655 args: &[Self::Value],
656 funclet: Option<&Self::Funclet>,
657 callee_instance: Option<Instance<'tcx>>,
658 ) -> Self::Value;
659
660 fn tail_call(
661 &mut self,
662 llty: Self::FunctionSignature,
663 caller_attrs: Option<&CodegenFnAttrs>,
664 fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
665 llfn: Self::Value,
666 args: &[Self::Value],
667 funclet: Option<&Self::Funclet>,
668 callee_instance: Option<Instance<'tcx>>,
669 );
670
671 fn zext(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value;
672
673 fn apply_attrs_to_cleanup_callsite(&mut self, llret: Self::Value);
674}