Merge commit '40dd3e2b70
' into sync_cg_clif-2021-05-27
This commit is contained in:
commit
fa702d0d2b
25 changed files with 218 additions and 296 deletions
|
@ -160,7 +160,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
|
|||
};
|
||||
|
||||
if !self.no_builtin_ranlib {
|
||||
match object::File::parse(&data) {
|
||||
match object::File::parse(&*data) {
|
||||
Ok(object) => {
|
||||
symbol_table.insert(
|
||||
entry_name.as_bytes().to_vec(),
|
||||
|
|
|
@ -110,11 +110,6 @@ pub(crate) fn codegen_fn<'tcx>(
|
|||
// Verify function
|
||||
verify_func(tcx, &clif_comments, &context.func);
|
||||
|
||||
// Perform rust specific optimizations
|
||||
tcx.sess.time("optimize clif ir", || {
|
||||
crate::optimize::optimize_function(tcx, instance, context, &mut clif_comments);
|
||||
});
|
||||
|
||||
// If the return block is not reachable, then the SSA builder may have inserted an `iconst.i128`
|
||||
// instruction, which doesn't have an encoding.
|
||||
context.compute_cfg();
|
||||
|
@ -125,10 +120,14 @@ pub(crate) fn codegen_fn<'tcx>(
|
|||
// invalidate it when it would change.
|
||||
context.domtree.clear();
|
||||
|
||||
context.want_disasm = crate::pretty_clif::should_write_ir(tcx);
|
||||
// Perform rust specific optimizations
|
||||
tcx.sess.time("optimize clif ir", || {
|
||||
crate::optimize::optimize_function(tcx, instance, context, &mut clif_comments);
|
||||
});
|
||||
|
||||
// Define function
|
||||
tcx.sess.time("define function", || {
|
||||
context.want_disasm = crate::pretty_clif::should_write_ir(tcx);
|
||||
module
|
||||
.define_function(func_id, context, &mut NullTrapSink {}, &mut NullStackMapSink {})
|
||||
.unwrap()
|
||||
|
@ -870,7 +869,7 @@ pub(crate) fn codegen_operand<'tcx>(
|
|||
pub(crate) fn codegen_panic<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, msg_str: &str, span: Span) {
|
||||
let location = fx.get_caller_location(span).load_scalar(fx);
|
||||
|
||||
let msg_ptr = fx.anonymous_str("assert", msg_str);
|
||||
let msg_ptr = fx.anonymous_str(msg_str);
|
||||
let msg_len = fx.bcx.ins().iconst(fx.pointer_type, i64::try_from(msg_str.len()).unwrap());
|
||||
let args = [msg_ptr, msg_len, location];
|
||||
|
||||
|
|
|
@ -347,19 +347,10 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
|
|||
self.module.isa().triple()
|
||||
}
|
||||
|
||||
pub(crate) fn anonymous_str(&mut self, prefix: &str, msg: &str) -> Value {
|
||||
use std::collections::hash_map::DefaultHasher;
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
||||
let mut hasher = DefaultHasher::new();
|
||||
msg.hash(&mut hasher);
|
||||
let msg_hash = hasher.finish();
|
||||
pub(crate) fn anonymous_str(&mut self, msg: &str) -> Value {
|
||||
let mut data_ctx = DataContext::new();
|
||||
data_ctx.define(msg.as_bytes().to_vec().into_boxed_slice());
|
||||
let msg_id = self
|
||||
.module
|
||||
.declare_data(&format!("__{}_{:08x}", prefix, msg_hash), Linkage::Local, false, false)
|
||||
.unwrap();
|
||||
let msg_id = self.module.declare_anonymous_data(false, false).unwrap();
|
||||
|
||||
// Ignore DuplicateDefinition error, as the data will be the same
|
||||
let _ = self.module.define_data(msg_id, &data_ctx);
|
||||
|
|
|
@ -48,6 +48,12 @@ pub struct BackendConfig {
|
|||
/// Can be set using `-Cllvm-args=display_cg_time=...`.
|
||||
pub display_cg_time: bool,
|
||||
|
||||
/// The register allocator to use.
|
||||
///
|
||||
/// Defaults to the value of `CG_CLIF_REGALLOC` or `backtracking` otherwise. Can be set using
|
||||
/// `-Cllvm-args=regalloc=...`.
|
||||
pub regalloc: String,
|
||||
|
||||
/// Enable the Cranelift ir verifier for all compilation passes. If not set it will only run
|
||||
/// once before passing the clif ir to Cranelift for compilation.
|
||||
///
|
||||
|
@ -74,6 +80,8 @@ impl Default for BackendConfig {
|
|||
args.split(' ').map(|arg| arg.to_string()).collect()
|
||||
},
|
||||
display_cg_time: bool_env_var("CG_CLIF_DISPLAY_CG_TIME"),
|
||||
regalloc: std::env::var("CG_CLIF_REGALLOC")
|
||||
.unwrap_or_else(|_| "backtracking".to_string()),
|
||||
enable_verifier: cfg!(debug_assertions) || bool_env_var("CG_CLIF_ENABLE_VERIFIER"),
|
||||
disable_incr_cache: bool_env_var("CG_CLIF_DISABLE_INCR_CACHE"),
|
||||
}
|
||||
|
@ -93,6 +101,7 @@ impl BackendConfig {
|
|||
match name {
|
||||
"mode" => config.codegen_mode = value.parse()?,
|
||||
"display_cg_time" => config.display_cg_time = parse_bool(name, value)?,
|
||||
"regalloc" => config.regalloc = value.to_string(),
|
||||
"enable_verifier" => config.enable_verifier = parse_bool(name, value)?,
|
||||
"disable_incr_cache" => config.disable_incr_cache = parse_bool(name, value)?,
|
||||
_ => return Err(format!("Unknown option `{}`", name)),
|
||||
|
|
|
@ -7,7 +7,8 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
|||
use rustc_errors::ErrorReported;
|
||||
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
||||
use rustc_middle::mir::interpret::{
|
||||
alloc_range, read_target_uint, AllocId, Allocation, ConstValue, ErrorHandled, GlobalAlloc, Scalar,
|
||||
alloc_range, read_target_uint, AllocId, Allocation, ConstValue, ErrorHandled, GlobalAlloc,
|
||||
Scalar,
|
||||
};
|
||||
use rustc_middle::ty::ConstKind;
|
||||
|
||||
|
@ -375,8 +376,19 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
|
|||
data_ctx.set_align(alloc.align.bytes());
|
||||
|
||||
if let Some(section_name) = section_name {
|
||||
// FIXME set correct segment for Mach-O files
|
||||
data_ctx.set_segment_section("", &*section_name);
|
||||
let (segment_name, section_name) = if tcx.sess.target.is_like_osx {
|
||||
if let Some(names) = section_name.split_once(',') {
|
||||
names
|
||||
} else {
|
||||
tcx.sess.fatal(&format!(
|
||||
"#[link_section = \"{}\"] is not valid for macos target: must be segment and section separated by comma",
|
||||
section_name
|
||||
));
|
||||
}
|
||||
} else {
|
||||
("", &*section_name)
|
||||
};
|
||||
data_ctx.set_segment_section(segment_name, section_name);
|
||||
}
|
||||
|
||||
let bytes = alloc.inspect_with_uninit_and_ptr_outside_interpreter(0..alloc.len()).to_vec();
|
||||
|
@ -438,12 +450,89 @@ pub(crate) fn mir_operand_get_const_val<'tcx>(
|
|||
operand: &Operand<'tcx>,
|
||||
) -> Option<ConstValue<'tcx>> {
|
||||
match operand {
|
||||
Operand::Copy(_) | Operand::Move(_) => None,
|
||||
Operand::Constant(const_) => match const_.literal {
|
||||
ConstantKind::Ty(const_) => {
|
||||
fx.monomorphize(const_).eval(fx.tcx, ParamEnv::reveal_all()).val.try_to_value()
|
||||
}
|
||||
ConstantKind::Val(val, _) => Some(val),
|
||||
},
|
||||
// FIXME(rust-lang/rust#85105): Casts like `IMM8 as u32` result in the const being stored
|
||||
// inside a temporary before being passed to the intrinsic requiring the const argument.
|
||||
// This code tries to find a single constant defining definition of the referenced local.
|
||||
Operand::Copy(place) | Operand::Move(place) => {
|
||||
if !place.projection.is_empty() {
|
||||
return None;
|
||||
}
|
||||
let mut computed_const_val = None;
|
||||
for bb_data in fx.mir.basic_blocks() {
|
||||
for stmt in &bb_data.statements {
|
||||
match &stmt.kind {
|
||||
StatementKind::Assign(local_and_rvalue) if &local_and_rvalue.0 == place => {
|
||||
match &local_and_rvalue.1 {
|
||||
Rvalue::Cast(CastKind::Misc, operand, ty) => {
|
||||
if computed_const_val.is_some() {
|
||||
return None; // local assigned twice
|
||||
}
|
||||
if !matches!(ty.kind(), ty::Uint(_) | ty::Int(_)) {
|
||||
return None;
|
||||
}
|
||||
let const_val = mir_operand_get_const_val(fx, operand)?;
|
||||
if fx.layout_of(ty).size
|
||||
!= const_val.try_to_scalar_int()?.size()
|
||||
{
|
||||
return None;
|
||||
}
|
||||
computed_const_val = Some(const_val);
|
||||
}
|
||||
Rvalue::Use(operand) => {
|
||||
computed_const_val = mir_operand_get_const_val(fx, operand)
|
||||
}
|
||||
_ => return None,
|
||||
}
|
||||
}
|
||||
StatementKind::SetDiscriminant { place: stmt_place, variant_index: _ }
|
||||
if &**stmt_place == place =>
|
||||
{
|
||||
return None;
|
||||
}
|
||||
StatementKind::LlvmInlineAsm(_) | StatementKind::CopyNonOverlapping(_) => {
|
||||
return None;
|
||||
} // conservative handling
|
||||
StatementKind::Assign(_)
|
||||
| StatementKind::FakeRead(_)
|
||||
| StatementKind::SetDiscriminant { .. }
|
||||
| StatementKind::StorageLive(_)
|
||||
| StatementKind::StorageDead(_)
|
||||
| StatementKind::Retag(_, _)
|
||||
| StatementKind::AscribeUserType(_, _)
|
||||
| StatementKind::Coverage(_)
|
||||
| StatementKind::Nop => {}
|
||||
}
|
||||
}
|
||||
match &bb_data.terminator().kind {
|
||||
TerminatorKind::Goto { .. }
|
||||
| TerminatorKind::SwitchInt { .. }
|
||||
| TerminatorKind::Resume
|
||||
| TerminatorKind::Abort
|
||||
| TerminatorKind::Return
|
||||
| TerminatorKind::Unreachable
|
||||
| TerminatorKind::Drop { .. }
|
||||
| TerminatorKind::Assert { .. } => {}
|
||||
TerminatorKind::DropAndReplace { .. }
|
||||
| TerminatorKind::Yield { .. }
|
||||
| TerminatorKind::GeneratorDrop
|
||||
| TerminatorKind::FalseEdge { .. }
|
||||
| TerminatorKind::FalseUnwind { .. } => unreachable!(),
|
||||
TerminatorKind::InlineAsm { .. } => return None,
|
||||
TerminatorKind::Call { destination: Some((call_place, _)), .. }
|
||||
if call_place == place =>
|
||||
{
|
||||
return None;
|
||||
}
|
||||
TerminatorKind::Call { .. } => {}
|
||||
}
|
||||
}
|
||||
computed_const_val
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -73,9 +73,8 @@ fn reuse_workproduct_for_cgu(
|
|||
let mut object = None;
|
||||
let work_product = cgu.work_product(tcx);
|
||||
if let Some(saved_file) = &work_product.saved_file {
|
||||
let obj_out = tcx
|
||||
.output_filenames(())
|
||||
.temp_path(OutputType::Object, Some(&cgu.name().as_str()));
|
||||
let obj_out =
|
||||
tcx.output_filenames(()).temp_path(OutputType::Object, Some(&cgu.name().as_str()));
|
||||
object = Some(obj_out.clone());
|
||||
let source_file = rustc_incremental::in_incr_comp_dir(&incr_comp_session_dir, &saved_file);
|
||||
if let Err(err) = rustc_fs_util::link_or_copy(&source_file, &obj_out) {
|
||||
|
@ -145,7 +144,13 @@ fn module_codegen(
|
|||
}
|
||||
}
|
||||
}
|
||||
crate::main_shim::maybe_create_entry_wrapper(tcx, &mut module, &mut cx.unwind_context, false);
|
||||
crate::main_shim::maybe_create_entry_wrapper(
|
||||
tcx,
|
||||
&mut module,
|
||||
&mut cx.unwind_context,
|
||||
false,
|
||||
cgu.is_primary(),
|
||||
);
|
||||
|
||||
let debug_context = cx.debug_context;
|
||||
let unwind_context = cx.unwind_context;
|
||||
|
@ -275,9 +280,8 @@ pub(crate) fn run_aot(
|
|||
.as_str()
|
||||
.to_string();
|
||||
|
||||
let tmp_file = tcx
|
||||
.output_filenames(())
|
||||
.temp_path(OutputType::Metadata, Some(&metadata_cgu_name));
|
||||
let tmp_file =
|
||||
tcx.output_filenames(()).temp_path(OutputType::Metadata, Some(&metadata_cgu_name));
|
||||
|
||||
let obj = crate::backend::with_object(tcx.sess, &metadata_cgu_name, |object| {
|
||||
crate::metadata::write_metadata(tcx, object);
|
||||
|
@ -352,8 +356,7 @@ fn codegen_global_asm(tcx: TyCtxt<'_>, cgu_name: &str, global_asm: &str) {
|
|||
.collect::<Vec<_>>()
|
||||
.join("\n");
|
||||
|
||||
let output_object_file =
|
||||
tcx.output_filenames(()).temp_path(OutputType::Object, Some(cgu_name));
|
||||
let output_object_file = tcx.output_filenames(()).temp_path(OutputType::Object, Some(cgu_name));
|
||||
|
||||
// Assemble `global_asm`
|
||||
let global_asm_object_file = add_file_stem_postfix(output_object_file.clone(), ".asm");
|
||||
|
|
|
@ -45,6 +45,7 @@ fn create_jit_module<'tcx>(
|
|||
&mut jit_module,
|
||||
&mut cx.unwind_context,
|
||||
true,
|
||||
true,
|
||||
);
|
||||
|
||||
(jit_module, cx)
|
||||
|
@ -206,7 +207,7 @@ fn load_imported_symbols_for_jit(tcx: TyCtxt<'_>) -> Vec<(String, *const u8)> {
|
|||
use object::{Object, ObjectSymbol};
|
||||
let lib = libloading::Library::new(&path).unwrap();
|
||||
let obj = std::fs::read(path).unwrap();
|
||||
let obj = object::File::parse(&obj).unwrap();
|
||||
let obj = object::File::parse(&*obj).unwrap();
|
||||
imported_symbols.extend(obj.dynamic_symbols().filter_map(|symbol| {
|
||||
let name = symbol.name().unwrap().to_string();
|
||||
if name.is_empty() || !symbol.is_global() || symbol.is_undefined() {
|
||||
|
|
|
@ -24,14 +24,22 @@ pub(crate) fn codegen_inline_asm<'tcx>(
|
|||
let true_ = fx.bcx.ins().iconst(types::I32, 1);
|
||||
fx.bcx.ins().trapnz(true_, TrapCode::User(1));
|
||||
return;
|
||||
} else if template[0] == InlineAsmTemplatePiece::String("mov rsi, rbx".to_string())
|
||||
&& template[1] == InlineAsmTemplatePiece::String("\n".to_string())
|
||||
&& template[2] == InlineAsmTemplatePiece::String("cpuid".to_string())
|
||||
&& template[3] == InlineAsmTemplatePiece::String("\n".to_string())
|
||||
&& template[4] == InlineAsmTemplatePiece::String("xchg rsi, rbx".to_string())
|
||||
} else if template[0] == InlineAsmTemplatePiece::String("movq %rbx, ".to_string())
|
||||
&& matches!(
|
||||
template[1],
|
||||
InlineAsmTemplatePiece::Placeholder { operand_idx: 0, modifier: Some('r'), span: _ }
|
||||
)
|
||||
&& template[2] == InlineAsmTemplatePiece::String("\n".to_string())
|
||||
&& template[3] == InlineAsmTemplatePiece::String("cpuid".to_string())
|
||||
&& template[4] == InlineAsmTemplatePiece::String("\n".to_string())
|
||||
&& template[5] == InlineAsmTemplatePiece::String("xchgq %rbx, ".to_string())
|
||||
&& matches!(
|
||||
template[6],
|
||||
InlineAsmTemplatePiece::Placeholder { operand_idx: 0, modifier: Some('r'), span: _ }
|
||||
)
|
||||
{
|
||||
assert_eq!(operands.len(), 4);
|
||||
let (leaf, eax_place) = match operands[0] {
|
||||
let (leaf, eax_place) = match operands[1] {
|
||||
InlineAsmOperand::InOut { reg, late: true, ref in_value, out_place } => {
|
||||
let reg = expect_reg(reg);
|
||||
assert_eq!(reg, InlineAsmReg::X86(X86InlineAsmReg::ax));
|
||||
|
@ -42,10 +50,14 @@ pub(crate) fn codegen_inline_asm<'tcx>(
|
|||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let ebx_place = match operands[1] {
|
||||
let ebx_place = match operands[0] {
|
||||
InlineAsmOperand::Out { reg, late: true, place } => {
|
||||
let reg = expect_reg(reg);
|
||||
assert_eq!(reg, InlineAsmReg::X86(X86InlineAsmReg::si));
|
||||
assert_eq!(
|
||||
reg,
|
||||
InlineAsmRegOrRegClass::RegClass(InlineAsmRegClass::X86(
|
||||
X86InlineAsmRegClass::reg
|
||||
))
|
||||
);
|
||||
crate::base::codegen_place(fx, place.unwrap())
|
||||
}
|
||||
_ => unreachable!(),
|
||||
|
|
|
@ -12,6 +12,7 @@ pub(crate) fn codegen_cpuid_call<'tcx>(
|
|||
) -> (Value, Value, Value, Value) {
|
||||
let leaf_0 = fx.bcx.create_block();
|
||||
let leaf_1 = fx.bcx.create_block();
|
||||
let leaf_7 = fx.bcx.create_block();
|
||||
let leaf_8000_0000 = fx.bcx.create_block();
|
||||
let leaf_8000_0001 = fx.bcx.create_block();
|
||||
let unsupported_leaf = fx.bcx.create_block();
|
||||
|
@ -25,6 +26,7 @@ pub(crate) fn codegen_cpuid_call<'tcx>(
|
|||
let mut switch = cranelift_frontend::Switch::new();
|
||||
switch.set_entry(0, leaf_0);
|
||||
switch.set_entry(1, leaf_1);
|
||||
switch.set_entry(7, leaf_7);
|
||||
switch.set_entry(0x8000_0000, leaf_8000_0000);
|
||||
switch.set_entry(0x8000_0001, leaf_8000_0001);
|
||||
switch.emit(&mut fx.bcx, leaf, unsupported_leaf);
|
||||
|
@ -43,6 +45,11 @@ pub(crate) fn codegen_cpuid_call<'tcx>(
|
|||
let edx_features = fx.bcx.ins().iconst(types::I32, 1 << 25 /* sse */ | 1 << 26 /* sse2 */);
|
||||
fx.bcx.ins().jump(dest, &[cpu_signature, additional_information, ecx_features, edx_features]);
|
||||
|
||||
fx.bcx.switch_to_block(leaf_7);
|
||||
// This leaf technically has subleaves, but we just return zero for all subleaves.
|
||||
let zero = fx.bcx.ins().iconst(types::I32, 0);
|
||||
fx.bcx.ins().jump(dest, &[zero, zero, zero, zero]);
|
||||
|
||||
fx.bcx.switch_to_block(leaf_8000_0000);
|
||||
let extended_max_basic_leaf = fx.bcx.ins().iconst(types::I32, 0);
|
||||
let zero = fx.bcx.ins().iconst(types::I32, 0);
|
||||
|
|
|
@ -8,8 +8,8 @@ mod simd;
|
|||
pub(crate) use cpuid::codegen_cpuid_call;
|
||||
pub(crate) use llvm::codegen_llvm_intrinsic_call;
|
||||
|
||||
use rustc_span::symbol::{sym, kw};
|
||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||
use rustc_span::symbol::{kw, sym};
|
||||
|
||||
use crate::prelude::*;
|
||||
use cranelift_codegen::ir::AtomicRmwOp;
|
||||
|
|
|
@ -256,6 +256,8 @@ fn build_isa(sess: &Session, backend_config: &BackendConfig) -> Box<dyn isa::Tar
|
|||
|
||||
flags_builder.set("enable_llvm_abi_extensions", "true").unwrap();
|
||||
|
||||
flags_builder.set("regalloc", &backend_config.regalloc).unwrap();
|
||||
|
||||
use rustc_session::config::OptLevel;
|
||||
match sess.opts.optimize {
|
||||
OptLevel::No => {
|
||||
|
@ -277,21 +279,23 @@ fn build_isa(sess: &Session, backend_config: &BackendConfig) -> Box<dyn isa::Tar
|
|||
builder
|
||||
}
|
||||
Some(value) => {
|
||||
let mut builder = cranelift_codegen::isa::lookup_variant(target_triple, variant).unwrap();
|
||||
let mut builder =
|
||||
cranelift_codegen::isa::lookup_variant(target_triple, variant).unwrap();
|
||||
if let Err(_) = builder.enable(value) {
|
||||
sess.fatal("The specified target cpu isn't currently supported by Cranelift.");
|
||||
}
|
||||
builder
|
||||
}
|
||||
None => {
|
||||
let mut builder = cranelift_codegen::isa::lookup_variant(target_triple, variant).unwrap();
|
||||
let mut builder =
|
||||
cranelift_codegen::isa::lookup_variant(target_triple, variant).unwrap();
|
||||
// Don't use "haswell" as the default, as it implies `has_lzcnt`.
|
||||
// macOS CI is still at Ivy Bridge EP, so `lzcnt` is interpreted as `bsr`.
|
||||
builder.enable("nehalem").unwrap();
|
||||
builder
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
isa_builder.finish(flags)
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ pub(crate) fn maybe_create_entry_wrapper(
|
|||
module: &mut impl Module,
|
||||
unwind_context: &mut UnwindContext,
|
||||
is_jit: bool,
|
||||
is_primary_cgu: bool,
|
||||
) {
|
||||
let (main_def_id, is_main_fn) = match tcx.entry_fn(()) {
|
||||
Some((def_id, entry_ty)) => (
|
||||
|
@ -26,8 +27,12 @@ pub(crate) fn maybe_create_entry_wrapper(
|
|||
None => return,
|
||||
};
|
||||
|
||||
let instance = Instance::mono(tcx, main_def_id).polymorphize(tcx);
|
||||
if !is_jit && module.get_name(&*tcx.symbol_name(instance).name).is_none() {
|
||||
if main_def_id.is_local() {
|
||||
let instance = Instance::mono(tcx, main_def_id).polymorphize(tcx);
|
||||
if !is_jit && module.get_name(&*tcx.symbol_name(instance).name).is_none() {
|
||||
return;
|
||||
}
|
||||
} else if !is_primary_cgu {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ fn codegen_print(fx: &mut FunctionCx<'_, '_, '_>, msg: &str) {
|
|||
}
|
||||
|
||||
let real_msg = format!("trap at {:?} ({}): {}\0", fx.instance, fx.symbol_name, msg);
|
||||
let msg_ptr = fx.anonymous_str("trap", &real_msg);
|
||||
let msg_ptr = fx.anonymous_str(&real_msg);
|
||||
fx.bcx.ins().call(puts, &[msg_ptr]);
|
||||
}
|
||||
|
||||
|
|
|
@ -561,6 +561,7 @@ impl<'tcx> CPlace<'tcx> {
|
|||
dst_align,
|
||||
src_align,
|
||||
true,
|
||||
MemFlags::trusted(),
|
||||
);
|
||||
}
|
||||
CValueInner::ByRef(_, Some(_)) => todo!(),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue