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 size: Size,
254 ) -> Self::Value;
255 fn load_from_place(&mut self, ty: Self::Type, place: PlaceValue<Self::Value>) -> Self::Value {
256 {
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);
257 self.load(ty, place.llval, place.align)
258 }
259 fn load_operand(&mut self, place: PlaceRef<'tcx, Self::Value>)
260 -> OperandRef<'tcx, Self::Value>;
261
262 fn write_operand_repeatedly(
264 &mut self,
265 elem: OperandRef<'tcx, Self::Value>,
266 count: u64,
267 dest: PlaceRef<'tcx, Self::Value>,
268 );
269
270 fn assume_integer_range(&mut self, imm: Self::Value, ty: Self::Type, range: WrappingRange) {
275 let WrappingRange { start, end } = range;
276
277 let shifted = if start == 0 {
281 imm
282 } else {
283 let low = self.const_uint_big(ty, start);
284 self.sub(imm, low)
285 };
286 let width = self.const_uint_big(ty, u128::wrapping_sub(end, start));
287 let cmp = self.icmp(IntPredicate::IntULE, shifted, width);
288 self.assume(cmp);
289 }
290
291 fn assume_nonnull(&mut self, val: Self::Value) {
295 let null = self.const_null(self.type_ptr());
300 let is_null = self.icmp(IntPredicate::IntNE, val, null);
301 self.assume(is_null);
302 }
303
304 fn range_metadata(&mut self, load: Self::Value, range: WrappingRange);
305 fn nonnull_metadata(&mut self, load: Self::Value);
306
307 fn store(&mut self, val: Self::Value, ptr: Self::Value, align: Align) -> Self::Value;
308 fn store_to_place(&mut self, val: Self::Value, place: PlaceValue<Self::Value>) -> Self::Value {
309 {
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);
310 self.store(val, place.llval, place.align)
311 }
312 fn store_with_flags(
313 &mut self,
314 val: Self::Value,
315 ptr: Self::Value,
316 align: Align,
317 flags: MemFlags,
318 ) -> Self::Value;
319 fn store_to_place_with_flags(
320 &mut self,
321 val: Self::Value,
322 place: PlaceValue<Self::Value>,
323 flags: MemFlags,
324 ) -> Self::Value {
325 {
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);
326 self.store_with_flags(val, place.llval, place.align, flags)
327 }
328 fn atomic_store(
329 &mut self,
330 val: Self::Value,
331 ptr: Self::Value,
332 order: AtomicOrdering,
333 size: Size,
334 );
335
336 fn gep(&mut self, ty: Self::Type, ptr: Self::Value, indices: &[Self::Value]) -> Self::Value;
337 fn inbounds_gep(
338 &mut self,
339 ty: Self::Type,
340 ptr: Self::Value,
341 indices: &[Self::Value],
342 ) -> Self::Value;
343 fn inbounds_nuw_gep(
344 &mut self,
345 ty: Self::Type,
346 ptr: Self::Value,
347 indices: &[Self::Value],
348 ) -> Self::Value {
349 self.inbounds_gep(ty, ptr, indices)
350 }
351 fn ptradd(&mut self, ptr: Self::Value, offset: Self::Value) -> Self::Value {
352 self.gep(self.cx().type_i8(), ptr, &[offset])
353 }
354 fn inbounds_ptradd(&mut self, ptr: Self::Value, offset: Self::Value) -> Self::Value {
355 self.inbounds_gep(self.cx().type_i8(), ptr, &[offset])
356 }
357
358 fn trunc(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value;
359 fn unchecked_utrunc(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value {
362 self.trunc(val, dest_ty)
363 }
364 fn unchecked_strunc(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value {
367 self.trunc(val, dest_ty)
368 }
369
370 fn sext(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value;
371 fn fptoui_sat(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value;
372 fn fptosi_sat(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value;
373 fn fptoui(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value;
374 fn fptosi(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value;
375 fn uitofp(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value;
376 fn sitofp(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value;
377 fn fptrunc(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value;
378 fn fpext(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value;
379 fn ptrtoint(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value;
380 fn inttoptr(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value;
381 fn bitcast(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value;
382 fn intcast(&mut self, val: Self::Value, dest_ty: Self::Type, is_signed: bool) -> Self::Value;
383 fn pointercast(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value;
384
385 fn cast_float_to_int(
386 &mut self,
387 signed: bool,
388 x: Self::Value,
389 dest_ty: Self::Type,
390 ) -> Self::Value {
391 let in_ty = self.cx().val_ty(x);
392 let (float_ty, int_ty) = if self.cx().type_kind(dest_ty) == TypeKind::Vector
393 && self.cx().type_kind(in_ty) == TypeKind::Vector
394 {
395 (self.cx().element_type(in_ty), self.cx().element_type(dest_ty))
396 } else {
397 (in_ty, dest_ty)
398 };
399 {
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!(
400 self.cx().type_kind(float_ty),
401 TypeKind::Half | TypeKind::Float | TypeKind::Double | TypeKind::FP128
402 );
403 {
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);
404
405 if let Some(false) = self.cx().sess().opts.unstable_opts.saturating_float_casts {
406 return if signed { self.fptosi(x, dest_ty) } else { self.fptoui(x, dest_ty) };
407 }
408
409 if signed { self.fptosi_sat(x, dest_ty) } else { self.fptoui_sat(x, dest_ty) }
410 }
411
412 fn icmp(&mut self, op: IntPredicate, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
413 fn fcmp(&mut self, op: RealPredicate, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
414
415 fn three_way_compare(
417 &mut self,
418 ty: Ty<'tcx>,
419 lhs: Self::Value,
420 rhs: Self::Value,
421 ) -> Self::Value {
422 use std::cmp::Ordering;
427 let pred = |op| crate::base::bin_op_to_icmp_predicate(op, ty.is_signed());
428 if self.cx().sess().opts.optimize == OptLevel::No {
429 let is_gt = self.icmp(pred(mir::BinOp::Gt), lhs, rhs);
435 let gtext = self.zext(is_gt, self.type_i8());
436 let is_lt = self.icmp(pred(mir::BinOp::Lt), lhs, rhs);
437 let ltext = self.zext(is_lt, self.type_i8());
438 self.unchecked_ssub(gtext, ltext)
439 } else {
440 let is_lt = self.icmp(pred(mir::BinOp::Lt), lhs, rhs);
443 let is_ne = self.icmp(pred(mir::BinOp::Ne), lhs, rhs);
444 let ge = self.select(
445 is_ne,
446 self.cx().const_i8(Ordering::Greater as i8),
447 self.cx().const_i8(Ordering::Equal as i8),
448 );
449 self.select(is_lt, self.cx().const_i8(Ordering::Less as i8), ge)
450 }
451 }
452
453 fn memcpy(
454 &mut self,
455 dst: Self::Value,
456 dst_align: Align,
457 src: Self::Value,
458 src_align: Align,
459 size: Self::Value,
460 flags: MemFlags,
461 tt: Option<FncTree>,
462 );
463 fn memmove(
464 &mut self,
465 dst: Self::Value,
466 dst_align: Align,
467 src: Self::Value,
468 src_align: Align,
469 size: Self::Value,
470 flags: MemFlags,
471 );
472 fn memset(
473 &mut self,
474 ptr: Self::Value,
475 fill_byte: Self::Value,
476 size: Self::Value,
477 align: Align,
478 flags: MemFlags,
479 );
480
481 fn vscale(&mut self, ty: Self::Type) -> Self::Value;
485
486 fn typed_place_copy(
493 &mut self,
494 dst: PlaceValue<Self::Value>,
495 src: PlaceValue<Self::Value>,
496 layout: TyAndLayout<'tcx>,
497 ) {
498 self.typed_place_copy_with_flags(dst, src, layout, MemFlags::empty());
499 }
500
501 fn typed_place_copy_with_flags(
502 &mut self,
503 dst: PlaceValue<Self::Value>,
504 src: PlaceValue<Self::Value>,
505 layout: TyAndLayout<'tcx>,
506 flags: MemFlags,
507 ) {
508 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");
509 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");
510 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");
511 if flags.contains(MemFlags::NONTEMPORAL) {
512 let ty = self.backend_type(layout);
514 let val = self.load_from_place(ty, src);
515 self.store_to_place_with_flags(val, dst, flags);
516 } else if self.sess().opts.optimize == OptLevel::No
517 && layout.backend_repr.is_scalar_or_simd()
518 {
519 let temp = self.load_operand(src.with_type(layout));
522 temp.val.store_with_flags(self, dst.with_type(layout), flags);
523 } else if !layout.is_zst() {
524 let tt = typetree_from_ty(self.tcx(), layout.ty);
525 let tt = tt.add_indirection();
527 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() };
528 let bytes = self.const_usize(layout.size.bytes());
529 let bytes = if layout.peel_transparent_wrappers(self).ty.is_scalable_vector() {
530 let vscale = self.vscale(self.type_i64());
531 self.mul(vscale, bytes)
532 } else {
533 bytes
534 };
535 self.memcpy(dst.llval, dst.align, src.llval, src.align, bytes, flags, Some(fnc_tree));
536 }
537 }
538
539 fn typed_place_swap(
547 &mut self,
548 left: PlaceValue<Self::Value>,
549 right: PlaceValue<Self::Value>,
550 layout: TyAndLayout<'tcx>,
551 ) {
552 let mut temp = self.load_operand(left.with_type(layout));
553 if let OperandValue::Ref(..) = temp.val {
554 let alloca = PlaceRef::alloca(self, layout);
556 self.typed_place_copy(alloca.val, left, layout);
557 temp = self.load_operand(alloca);
558 }
559 self.typed_place_copy(left, right, layout);
560 temp.val.store(self, right.with_type(layout));
561 }
562
563 fn select(
564 &mut self,
565 cond: Self::Value,
566 then_val: Self::Value,
567 else_val: Self::Value,
568 ) -> Self::Value;
569
570 fn va_arg(&mut self, list: Self::Value, ty: Self::Type) -> Self::Value;
571 fn extract_element(&mut self, vec: Self::Value, idx: Self::Value) -> Self::Value;
572 fn vector_splat(&mut self, num_elts: usize, elt: Self::Value) -> Self::Value;
573 fn extract_value(&mut self, agg_val: Self::Value, idx: u64) -> Self::Value;
574 fn insert_value(&mut self, agg_val: Self::Value, elt: Self::Value, idx: u64) -> Self::Value;
575
576 fn set_personality_fn(&mut self, personality: Self::Function);
577
578 fn cleanup_landing_pad(&mut self, pers_fn: Self::Function) -> (Self::Value, Self::Value);
580 fn filter_landing_pad(&mut self, pers_fn: Self::Function);
581 fn resume(&mut self, exn0: Self::Value, exn1: Self::Value);
582
583 fn cleanup_pad(&mut self, parent: Option<Self::Value>, args: &[Self::Value]) -> Self::Funclet;
585 fn cleanup_ret(&mut self, funclet: &Self::Funclet, unwind: Option<Self::BasicBlock>);
586 fn catch_pad(&mut self, parent: Self::Value, args: &[Self::Value]) -> Self::Funclet;
587 fn catch_switch(
588 &mut self,
589 parent: Option<Self::Value>,
590 unwind: Option<Self::BasicBlock>,
591 handlers: &[Self::BasicBlock],
592 ) -> Self::Value;
593 fn get_funclet_cleanuppad(&self, funclet: &Self::Funclet) -> Self::Value;
594
595 fn atomic_cmpxchg(
596 &mut self,
597 dst: Self::Value,
598 cmp: Self::Value,
599 src: Self::Value,
600 order: AtomicOrdering,
601 failure_order: AtomicOrdering,
602 weak: bool,
603 ) -> (Self::Value, Self::Value);
604 fn atomic_rmw(
607 &mut self,
608 op: AtomicRmwBinOp,
609 dst: Self::Value,
610 src: Self::Value,
611 order: AtomicOrdering,
612 ret_ptr: bool,
613 ) -> Self::Value;
614 fn atomic_fence(&mut self, order: AtomicOrdering, scope: SynchronizationScope);
615 fn set_invariant_load(&mut self, load: Self::Value);
616
617 fn lifetime_start(&mut self, ptr: Self::Value, size: Size);
619
620 fn lifetime_end(&mut self, ptr: Self::Value, size: Size);
622
623 fn call(
648 &mut self,
649 llty: Self::FunctionSignature,
650 caller_attrs: Option<&CodegenFnAttrs>,
651 fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>,
652 fn_val: Self::Value,
653 args: &[Self::Value],
654 funclet: Option<&Self::Funclet>,
655 callee_instance: Option<Instance<'tcx>>,
656 ) -> Self::Value;
657
658 fn tail_call(
659 &mut self,
660 llty: Self::FunctionSignature,
661 caller_attrs: Option<&CodegenFnAttrs>,
662 fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
663 llfn: Self::Value,
664 args: &[Self::Value],
665 funclet: Option<&Self::Funclet>,
666 callee_instance: Option<Instance<'tcx>>,
667 );
668
669 fn zext(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value;
670
671 fn apply_attrs_to_cleanup_callsite(&mut self, llret: Self::Value);
672}