Format code using 'cargo fmt'
This commit is contained in:
parent
5b17cf2083
commit
f481a4b685
@ -2,8 +2,8 @@
|
||||
|
||||
use rustc::mir;
|
||||
|
||||
use crate::prelude::*;
|
||||
use crate::abi::pass_mode::*;
|
||||
use crate::prelude::*;
|
||||
|
||||
pub fn add_args_header_comment(fx: &mut FunctionCx<impl Backend>) {
|
||||
fx.add_global_comment(format!(
|
||||
|
146
src/abi/mod.rs
146
src/abi/mod.rs
@ -1,16 +1,20 @@
|
||||
#[cfg(debug_assertions)]
|
||||
mod comments;
|
||||
mod returning;
|
||||
mod pass_mode;
|
||||
mod returning;
|
||||
|
||||
use rustc_target::spec::abi::Abi;
|
||||
|
||||
use crate::prelude::*;
|
||||
use self::pass_mode::*;
|
||||
use crate::prelude::*;
|
||||
|
||||
pub use self::returning::codegen_return;
|
||||
|
||||
fn clif_sig_from_fn_sig<'tcx>(tcx: TyCtxt<'tcx>, sig: FnSig<'tcx>, is_vtable_fn: bool) -> Signature {
|
||||
fn clif_sig_from_fn_sig<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
sig: FnSig<'tcx>,
|
||||
is_vtable_fn: bool,
|
||||
) -> Signature {
|
||||
let abi = match sig.abi {
|
||||
Abi::System => {
|
||||
if tcx.sess.target.target.options.is_like_windows {
|
||||
@ -47,12 +51,18 @@ fn clif_sig_from_fn_sig<'tcx>(tcx: TyCtxt<'tcx>, sig: FnSig<'tcx>, is_vtable_fn:
|
||||
if i == 0 && is_vtable_fn {
|
||||
// Virtual calls turn their self param into a thin pointer.
|
||||
// See https://github.com/rust-lang/rust/blob/37b6a5e5e82497caf5353d9d856e4eb5d14cbe06/src/librustc/ty/layout.rs#L2519-L2572 for more info
|
||||
layout = tcx.layout_of(ParamEnv::reveal_all().and(tcx.mk_mut_ptr(tcx.mk_unit()))).unwrap();
|
||||
layout = tcx
|
||||
.layout_of(ParamEnv::reveal_all().and(tcx.mk_mut_ptr(tcx.mk_unit())))
|
||||
.unwrap();
|
||||
}
|
||||
get_pass_mode(tcx, layout).get_param_ty(tcx).into_iter()
|
||||
}).flatten();
|
||||
})
|
||||
.flatten();
|
||||
|
||||
let (params, returns) = match get_pass_mode(tcx, tcx.layout_of(ParamEnv::reveal_all().and(output)).unwrap()) {
|
||||
let (params, returns) = match get_pass_mode(
|
||||
tcx,
|
||||
tcx.layout_of(ParamEnv::reveal_all().and(output)).unwrap(),
|
||||
) {
|
||||
PassMode::NoPass => (inputs.map(AbiParam::new).collect(), vec![]),
|
||||
PassMode::ByVal(ret_ty) => (
|
||||
inputs.map(AbiParam::new).collect(),
|
||||
@ -87,7 +97,8 @@ pub fn get_function_name_and_sig<'tcx>(
|
||||
support_vararg: bool,
|
||||
) -> (String, Signature) {
|
||||
assert!(!inst.substs.needs_infer() && !inst.substs.has_param_types());
|
||||
let fn_sig = tcx.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), &inst.fn_sig(tcx));
|
||||
let fn_sig =
|
||||
tcx.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), &inst.fn_sig(tcx));
|
||||
if fn_sig.c_variadic && !support_vararg {
|
||||
unimpl!("Variadic function definitions are not yet supported");
|
||||
}
|
||||
@ -141,7 +152,8 @@ fn lib_call(
|
||||
.module
|
||||
.declare_func_in_func(func_id, &mut self.bcx.func);
|
||||
let call_inst = self.bcx.ins().call(func_ref, args);
|
||||
#[cfg(debug_assertions)] {
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
self.add_comment(call_inst, format!("easy_call {}", name));
|
||||
}
|
||||
let results = self.bcx.inst_results(call_inst);
|
||||
@ -185,7 +197,10 @@ pub fn easy_call(
|
||||
}
|
||||
|
||||
fn self_sig(&self) -> FnSig<'tcx> {
|
||||
self.tcx.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), &self.instance.fn_sig(self.tcx))
|
||||
self.tcx.normalize_erasing_late_bound_regions(
|
||||
ParamEnv::reveal_all(),
|
||||
&self.instance.fn_sig(self.tcx),
|
||||
)
|
||||
}
|
||||
|
||||
fn return_layout(&self) -> TyLayout<'tcx> {
|
||||
@ -213,10 +228,7 @@ fn local_place<'tcx>(
|
||||
fx.local_map[&local]
|
||||
}
|
||||
|
||||
pub fn codegen_fn_prelude(
|
||||
fx: &mut FunctionCx<'_, '_, impl Backend>,
|
||||
start_ebb: Ebb,
|
||||
) {
|
||||
pub fn codegen_fn_prelude(fx: &mut FunctionCx<'_, '_, impl Backend>, start_ebb: Ebb) {
|
||||
let ssa_analyzed = crate::analyze::analyze(fx);
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
@ -250,20 +262,13 @@ enum ArgKind<'tcx> {
|
||||
|
||||
let mut params = Vec::new();
|
||||
for (i, arg_ty) in tupled_arg_tys.types().enumerate() {
|
||||
let param = cvalue_for_param(
|
||||
fx,
|
||||
start_ebb,
|
||||
local,
|
||||
Some(i),
|
||||
arg_ty,
|
||||
);
|
||||
let param = cvalue_for_param(fx, start_ebb, local, Some(i), arg_ty);
|
||||
params.push(param);
|
||||
}
|
||||
|
||||
(local, ArgKind::Spread(params), arg_ty)
|
||||
} else {
|
||||
let param =
|
||||
cvalue_for_param(fx, start_ebb, local, None, arg_ty);
|
||||
let param = cvalue_for_param(fx, start_ebb, local, None, arg_ty);
|
||||
(local, ArgKind::Normal(param), arg_ty)
|
||||
}
|
||||
})
|
||||
@ -354,7 +359,9 @@ pub fn codegen_terminator_call<'tcx>(
|
||||
destination: &Option<(Place<'tcx>, BasicBlock)>,
|
||||
) {
|
||||
let fn_ty = fx.monomorphize(&func.ty(fx.mir, fx.tcx));
|
||||
let sig = fx.tcx.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), &fn_ty.fn_sig(fx.tcx));
|
||||
let sig = fx
|
||||
.tcx
|
||||
.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), &fn_ty.fn_sig(fx.tcx));
|
||||
|
||||
let destination = destination
|
||||
.as_ref()
|
||||
@ -365,7 +372,13 @@ pub fn codegen_terminator_call<'tcx>(
|
||||
ty::Instance::resolve(fx.tcx, ty::ParamEnv::reveal_all(), def_id, substs).unwrap();
|
||||
|
||||
if fx.tcx.symbol_name(instance).as_str().starts_with("llvm.") {
|
||||
crate::llvm_intrinsics::codegen_llvm_intrinsic_call(fx, &fx.tcx.symbol_name(instance).as_str(), substs, args, destination);
|
||||
crate::llvm_intrinsics::codegen_llvm_intrinsic_call(
|
||||
fx,
|
||||
&fx.tcx.symbol_name(instance).as_str(),
|
||||
substs,
|
||||
args,
|
||||
destination,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -430,7 +443,9 @@ fn codegen_call_inner<'tcx>(
|
||||
args: Vec<CValue<'tcx>>,
|
||||
ret_place: Option<CPlace<'tcx>>,
|
||||
) {
|
||||
let fn_sig = fx.tcx.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), &fn_ty.fn_sig(fx.tcx));
|
||||
let fn_sig = fx
|
||||
.tcx
|
||||
.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), &fn_ty.fn_sig(fx.tcx));
|
||||
|
||||
let instance = match fn_ty.sty {
|
||||
ty::FnDef(def_id, substs) => {
|
||||
@ -453,7 +468,10 @@ fn codegen_call_inner<'tcx>(
|
||||
let nop_inst = fx.bcx.ins().nop();
|
||||
fx.add_comment(
|
||||
nop_inst,
|
||||
format!("virtual call; self arg pass mode: {:?}", get_pass_mode(fx.tcx, args[0].layout())),
|
||||
format!(
|
||||
"virtual call; self arg pass mode: {:?}",
|
||||
get_pass_mode(fx.tcx, args[0].layout())
|
||||
),
|
||||
);
|
||||
}
|
||||
let (ptr, method) = crate::vtable::get_ptr_and_method_ref(fx, args[0], idx);
|
||||
@ -461,7 +479,13 @@ fn codegen_call_inner<'tcx>(
|
||||
}
|
||||
|
||||
// Normal call
|
||||
Some(_) => (None, args.get(0).map(|arg| adjust_arg_for_abi(fx, *arg)).unwrap_or(Empty), false),
|
||||
Some(_) => (
|
||||
None,
|
||||
args.get(0)
|
||||
.map(|arg| adjust_arg_for_abi(fx, *arg))
|
||||
.unwrap_or(Empty),
|
||||
false,
|
||||
),
|
||||
|
||||
// Indirect call
|
||||
None => {
|
||||
@ -474,36 +498,40 @@ fn codegen_call_inner<'tcx>(
|
||||
.load_scalar(fx);
|
||||
(
|
||||
Some(func),
|
||||
args.get(0).map(|arg| adjust_arg_for_abi(fx, *arg)).unwrap_or(Empty),
|
||||
args.get(0)
|
||||
.map(|arg| adjust_arg_for_abi(fx, *arg))
|
||||
.unwrap_or(Empty),
|
||||
false,
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
let (call_inst, call_args) = self::returning::codegen_with_call_return_arg(fx, fn_sig, ret_place, |fx, return_ptr| {
|
||||
let call_args: Vec<Value> = return_ptr
|
||||
.into_iter()
|
||||
.chain(first_arg.into_iter())
|
||||
.chain(
|
||||
args.into_iter()
|
||||
.skip(1)
|
||||
.map(|arg| adjust_arg_for_abi(fx, arg).into_iter())
|
||||
.flatten(),
|
||||
)
|
||||
.collect::<Vec<_>>();
|
||||
let (call_inst, call_args) =
|
||||
self::returning::codegen_with_call_return_arg(fx, fn_sig, ret_place, |fx, return_ptr| {
|
||||
let call_args: Vec<Value> = return_ptr
|
||||
.into_iter()
|
||||
.chain(first_arg.into_iter())
|
||||
.chain(
|
||||
args.into_iter()
|
||||
.skip(1)
|
||||
.map(|arg| adjust_arg_for_abi(fx, arg).into_iter())
|
||||
.flatten(),
|
||||
)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let call_inst = if let Some(func_ref) = func_ref {
|
||||
let sig = fx
|
||||
.bcx
|
||||
.import_signature(clif_sig_from_fn_sig(fx.tcx, fn_sig, is_virtual_call));
|
||||
fx.bcx.ins().call_indirect(sig, func_ref, &call_args)
|
||||
} else {
|
||||
let func_ref = fx.get_function_ref(instance.expect("non-indirect call on non-FnDef type"));
|
||||
fx.bcx.ins().call(func_ref, &call_args)
|
||||
};
|
||||
let call_inst = if let Some(func_ref) = func_ref {
|
||||
let sig =
|
||||
fx.bcx
|
||||
.import_signature(clif_sig_from_fn_sig(fx.tcx, fn_sig, is_virtual_call));
|
||||
fx.bcx.ins().call_indirect(sig, func_ref, &call_args)
|
||||
} else {
|
||||
let func_ref =
|
||||
fx.get_function_ref(instance.expect("non-indirect call on non-FnDef type"));
|
||||
fx.bcx.ins().call(func_ref, &call_args)
|
||||
};
|
||||
|
||||
(call_inst, call_args)
|
||||
});
|
||||
(call_inst, call_args)
|
||||
});
|
||||
|
||||
// FIXME find a cleaner way to support varargs
|
||||
if fn_sig.c_variadic {
|
||||
@ -526,10 +554,7 @@ fn codegen_call_inner<'tcx>(
|
||||
}
|
||||
}
|
||||
|
||||
pub fn codegen_drop<'tcx>(
|
||||
fx: &mut FunctionCx<'_, 'tcx, impl Backend>,
|
||||
drop_place: CPlace<'tcx>,
|
||||
) {
|
||||
pub fn codegen_drop<'tcx>(fx: &mut FunctionCx<'_, 'tcx, impl Backend>, drop_place: CPlace<'tcx>) {
|
||||
let ty = drop_place.layout().ty;
|
||||
let drop_fn = Instance::resolve_drop_in_place(fx.tcx, ty);
|
||||
|
||||
@ -542,7 +567,10 @@ pub fn codegen_drop<'tcx>(
|
||||
let (ptr, vtable) = drop_place.to_addr_maybe_unsized(fx);
|
||||
let drop_fn = crate::vtable::drop_fn_of_obj(fx, vtable.unwrap());
|
||||
|
||||
let fn_sig = fx.tcx.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), &drop_fn_ty.fn_sig(fx.tcx));
|
||||
let fn_sig = fx.tcx.normalize_erasing_late_bound_regions(
|
||||
ParamEnv::reveal_all(),
|
||||
&drop_fn_ty.fn_sig(fx.tcx),
|
||||
);
|
||||
|
||||
assert_eq!(fn_sig.output(), fx.tcx.mk_unit());
|
||||
|
||||
@ -564,13 +592,7 @@ pub fn codegen_drop<'tcx>(
|
||||
);
|
||||
drop_place.write_place_ref(fx, arg_place);
|
||||
let arg_value = arg_place.to_cvalue(fx);
|
||||
codegen_call_inner(
|
||||
fx,
|
||||
None,
|
||||
drop_fn_ty,
|
||||
vec![arg_value],
|
||||
None,
|
||||
);
|
||||
codegen_call_inner(fx, None, drop_fn_ty, vec![arg_value], None);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -50,14 +50,14 @@ impl<T: std::fmt::Debug> EmptySinglePair<T> {
|
||||
pub fn assert_single(self) -> T {
|
||||
match self {
|
||||
Single(v) => v,
|
||||
_ => panic!("Called assert_single on {:?}", self)
|
||||
_ => panic!("Called assert_single on {:?}", self),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn assert_pair(self) -> (T, T) {
|
||||
match self {
|
||||
Pair(a, b) => (a, b),
|
||||
_ => panic!("Called assert_pair on {:?}", self)
|
||||
_ => panic!("Called assert_pair on {:?}", self),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -75,10 +75,7 @@ pub fn get_param_ty(self, tcx: TyCtxt<'_>) -> EmptySinglePair<Type> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_pass_mode<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
layout: TyLayout<'tcx>,
|
||||
) -> PassMode {
|
||||
pub fn get_pass_mode<'tcx>(tcx: TyCtxt<'tcx>, layout: TyLayout<'tcx>) -> PassMode {
|
||||
assert!(!layout.is_unsized());
|
||||
|
||||
if layout.is_zst() {
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::prelude::*;
|
||||
use crate::abi::pass_mode::*;
|
||||
use crate::prelude::*;
|
||||
|
||||
pub fn codegen_return_param(
|
||||
fx: &mut FunctionCx<impl Backend>,
|
||||
@ -27,10 +27,8 @@ pub fn codegen_return_param(
|
||||
}
|
||||
PassMode::ByRef => {
|
||||
let ret_param = fx.bcx.append_ebb_param(start_ebb, fx.pointer_type);
|
||||
fx.local_map.insert(
|
||||
RETURN_PLACE,
|
||||
CPlace::for_addr(ret_param, ret_layout),
|
||||
);
|
||||
fx.local_map
|
||||
.insert(RETURN_PLACE, CPlace::for_addr(ret_param, ret_layout));
|
||||
|
||||
Single(ret_param)
|
||||
}
|
||||
|
@ -3,8 +3,8 @@
|
||||
|
||||
use crate::prelude::*;
|
||||
|
||||
use rustc_codegen_ssa::back::archive::{find_library, ArchiveBuilder};
|
||||
use rustc_codegen_ssa::{METADATA_FILENAME, RLIB_BYTECODE_EXTENSION};
|
||||
use rustc_codegen_ssa::back::archive::{ArchiveBuilder, find_library};
|
||||
|
||||
struct ArchiveConfig<'a> {
|
||||
sess: &'a Session,
|
||||
@ -16,7 +16,10 @@ struct ArchiveConfig<'a> {
|
||||
|
||||
#[derive(Debug)]
|
||||
enum ArchiveEntry {
|
||||
FromArchive { archive_index: usize, entry_index: usize },
|
||||
FromArchive {
|
||||
archive_index: usize,
|
||||
entry_index: usize,
|
||||
},
|
||||
File(PathBuf),
|
||||
}
|
||||
|
||||
@ -50,7 +53,10 @@ fn new(sess: &'a Session, output: &Path, input: Option<&Path>) -> Self {
|
||||
let entry = entry.unwrap();
|
||||
entries.push((
|
||||
String::from_utf8(entry.header().identifier().to_vec()).unwrap(),
|
||||
ArchiveEntry::FromArchive { archive_index: 0, entry_index: i },
|
||||
ArchiveEntry::FromArchive {
|
||||
archive_index: 0,
|
||||
entry_index: i,
|
||||
},
|
||||
));
|
||||
i += 1;
|
||||
}
|
||||
@ -73,7 +79,8 @@ fn src_files(&mut self) -> Vec<String> {
|
||||
}
|
||||
|
||||
fn remove_file(&mut self, name: &str) {
|
||||
let index = self.entries
|
||||
let index = self
|
||||
.entries
|
||||
.iter()
|
||||
.position(|(entry_name, _)| entry_name == name)
|
||||
.expect("Tried to remove file not existing in src archive");
|
||||
@ -89,12 +96,23 @@ fn add_file(&mut self, file: &Path) {
|
||||
|
||||
fn add_native_library(&mut self, name: &str) {
|
||||
let location = find_library(name, &self.config.lib_search_paths, self.config.sess);
|
||||
self.add_archive(location.clone(), |_| false).unwrap_or_else(|e| {
|
||||
panic!("failed to add native library {}: {}", location.to_string_lossy(), e);
|
||||
});
|
||||
self.add_archive(location.clone(), |_| false)
|
||||
.unwrap_or_else(|e| {
|
||||
panic!(
|
||||
"failed to add native library {}: {}",
|
||||
location.to_string_lossy(),
|
||||
e
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
fn add_rlib(&mut self, rlib: &Path, name: &str, lto: bool, skip_objects: bool) -> std::io::Result<()> {
|
||||
fn add_rlib(
|
||||
&mut self,
|
||||
rlib: &Path,
|
||||
name: &str,
|
||||
lto: bool,
|
||||
skip_objects: bool,
|
||||
) -> std::io::Result<()> {
|
||||
let obj_start = name.to_owned();
|
||||
|
||||
self.add_archive(rlib.to_owned(), move |fname: &str| {
|
||||
@ -147,7 +165,10 @@ enum BuilderKind<'a> {
|
||||
} else if self.config.use_gnu_style_archive {
|
||||
BuilderKind::Gnu(ar::GnuBuilder::new(
|
||||
File::create(&self.config.dst).unwrap(),
|
||||
self.entries.iter().map(|(name, _)| name.as_bytes().to_vec()).collect(),
|
||||
self.entries
|
||||
.iter()
|
||||
.map(|(name, _)| name.as_bytes().to_vec())
|
||||
.collect(),
|
||||
))
|
||||
} else {
|
||||
BuilderKind::Bsd(ar::Builder::new(File::create(&self.config.dst).unwrap()))
|
||||
@ -156,8 +177,12 @@ enum BuilderKind<'a> {
|
||||
// Add all files
|
||||
for (entry_name, entry) in self.entries.into_iter() {
|
||||
match entry {
|
||||
ArchiveEntry::FromArchive { archive_index, entry_index } => {
|
||||
let (ref src_archive_path, ref mut src_archive) = self.src_archives[archive_index];
|
||||
ArchiveEntry::FromArchive {
|
||||
archive_index,
|
||||
entry_index,
|
||||
} => {
|
||||
let (ref src_archive_path, ref mut src_archive) =
|
||||
self.src_archives[archive_index];
|
||||
let entry = src_archive.jump_to_entry(entry_index).unwrap();
|
||||
let orig_header = entry.header();
|
||||
|
||||
@ -170,22 +195,33 @@ enum BuilderKind<'a> {
|
||||
header.set_mode(orig_header.mode());
|
||||
|
||||
match builder {
|
||||
BuilderKind::Bsd(ref mut builder) => builder.append(&header, entry).unwrap(),
|
||||
BuilderKind::Gnu(ref mut builder) => builder.append(&header, entry).unwrap(),
|
||||
BuilderKind::Bsd(ref mut builder) => {
|
||||
builder.append(&header, entry).unwrap()
|
||||
}
|
||||
BuilderKind::Gnu(ref mut builder) => {
|
||||
builder.append(&header, entry).unwrap()
|
||||
}
|
||||
BuilderKind::NativeAr(archive_file) => {
|
||||
Command::new("ar").arg("x").arg(src_archive_path).arg(&entry_name).status().unwrap();
|
||||
Command::new("ar")
|
||||
.arg("x")
|
||||
.arg(src_archive_path)
|
||||
.arg(&entry_name)
|
||||
.status()
|
||||
.unwrap();
|
||||
add_file_using_ar(archive_file, Path::new(&entry_name));
|
||||
std::fs::remove_file(entry_name).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
ArchiveEntry::File(file) => {
|
||||
match builder {
|
||||
BuilderKind::Bsd(ref mut builder) => builder.append_file(entry_name.as_bytes(), &mut File::open(file).unwrap()).unwrap(),
|
||||
BuilderKind::Gnu(ref mut builder) => builder.append_file(entry_name.as_bytes(), &mut File::open(file).unwrap()).unwrap(),
|
||||
BuilderKind::NativeAr(archive_file) => add_file_using_ar(archive_file, &file),
|
||||
}
|
||||
}
|
||||
ArchiveEntry::File(file) => match builder {
|
||||
BuilderKind::Bsd(ref mut builder) => builder
|
||||
.append_file(entry_name.as_bytes(), &mut File::open(file).unwrap())
|
||||
.unwrap(),
|
||||
BuilderKind::Gnu(ref mut builder) => builder
|
||||
.append_file(entry_name.as_bytes(), &mut File::open(file).unwrap())
|
||||
.unwrap(),
|
||||
BuilderKind::NativeAr(archive_file) => add_file_using_ar(archive_file, &file),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@ -207,7 +243,8 @@ enum BuilderKind<'a> {
|
||||
|
||||
impl<'a> ArArchiveBuilder<'a> {
|
||||
fn add_archive<F>(&mut self, archive_path: PathBuf, mut skip: F) -> std::io::Result<()>
|
||||
where F: FnMut(&str) -> bool + 'static
|
||||
where
|
||||
F: FnMut(&str) -> bool + 'static,
|
||||
{
|
||||
let mut archive = ar::Archive::new(std::fs::File::open(&archive_path)?);
|
||||
let archive_index = self.src_archives.len();
|
||||
@ -219,7 +256,10 @@ fn add_archive<F>(&mut self, archive_path: PathBuf, mut skip: F) -> std::io::Res
|
||||
if !skip(&file_name) {
|
||||
self.entries.push((
|
||||
file_name,
|
||||
ArchiveEntry::FromArchive { archive_index, entry_index: i },
|
||||
ArchiveEntry::FromArchive {
|
||||
archive_index,
|
||||
entry_index: i,
|
||||
},
|
||||
));
|
||||
}
|
||||
i += 1;
|
||||
|
118
src/base.rs
118
src/base.rs
@ -72,15 +72,22 @@ pub fn trans_fn<'clif, 'tcx, B: Backend + 'static>(
|
||||
// Define function
|
||||
let context = &mut cx.caches.context;
|
||||
context.func = func;
|
||||
cx.module
|
||||
.define_function(func_id, context)
|
||||
.unwrap();
|
||||
cx.module.define_function(func_id, context).unwrap();
|
||||
|
||||
let value_ranges = context.build_value_labels_ranges(cx.module.isa()).expect("value location ranges");
|
||||
let value_ranges = context
|
||||
.build_value_labels_ranges(cx.module.isa())
|
||||
.expect("value location ranges");
|
||||
|
||||
// Write optimized function to file for debugging
|
||||
#[cfg(debug_assertions)]
|
||||
crate::pretty_clif::write_clif_file(cx.tcx, "opt", instance, &context.func, &clif_comments, Some(&value_ranges));
|
||||
crate::pretty_clif::write_clif_file(
|
||||
cx.tcx,
|
||||
"opt",
|
||||
instance,
|
||||
&context.func,
|
||||
&clif_comments,
|
||||
Some(&value_ranges),
|
||||
);
|
||||
|
||||
// Define debuginfo for function
|
||||
let isa = cx.module.isa();
|
||||
@ -164,7 +171,14 @@ fn codegen_fn_content(fx: &mut FunctionCx<'_, '_, impl Backend>) {
|
||||
} else {
|
||||
fx.bcx.ins().brz(cond, target, &[]);
|
||||
};
|
||||
trap_panic(fx, format!("[panic] Assert {:?} at {:?} failed.", msg, bb_data.terminator().source_info.span));
|
||||
trap_panic(
|
||||
fx,
|
||||
format!(
|
||||
"[panic] Assert {:?} at {:?} failed.",
|
||||
msg,
|
||||
bb_data.terminator().source_info.span
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
TerminatorKind::SwitchInt {
|
||||
@ -272,7 +286,8 @@ fn trans_stmt<'tcx>(
|
||||
let rhs = trans_operand(fx, rhs);
|
||||
|
||||
let res = if !fx.tcx.sess.overflow_checks() {
|
||||
let val = crate::num::trans_int_binop(fx, *bin_op, lhs, rhs).load_scalar(fx);
|
||||
let val =
|
||||
crate::num::trans_int_binop(fx, *bin_op, lhs, rhs).load_scalar(fx);
|
||||
let is_overflow = fx.bcx.ins().iconst(types::I8, 0);
|
||||
CValue::by_val_pair(val, is_overflow, lval.layout())
|
||||
} else {
|
||||
@ -293,9 +308,7 @@ fn trans_stmt<'tcx>(
|
||||
let res = fx.bcx.ins().icmp_imm(IntCC::Equal, val, 0);
|
||||
fx.bcx.ins().bint(types::I8, res)
|
||||
}
|
||||
ty::Uint(_) | ty::Int(_) => {
|
||||
fx.bcx.ins().bnot(val)
|
||||
}
|
||||
ty::Uint(_) | ty::Int(_) => fx.bcx.ins().bnot(val),
|
||||
_ => unimplemented!("un op Not for {:?}", layout.ty),
|
||||
}
|
||||
}
|
||||
@ -304,7 +317,12 @@ fn trans_stmt<'tcx>(
|
||||
let clif_ty = fx.clif_type(layout.ty).unwrap();
|
||||
if clif_ty == types::I128 {
|
||||
// FIXME implement it
|
||||
crate::trap::trap_unreachable_ret_value(fx, layout, "i128 neg is not yet supported").load_scalar(fx)
|
||||
crate::trap::trap_unreachable_ret_value(
|
||||
fx,
|
||||
layout,
|
||||
"i128 neg is not yet supported",
|
||||
)
|
||||
.load_scalar(fx)
|
||||
} else {
|
||||
let zero = fx.bcx.ins().iconst(clif_ty, 0);
|
||||
fx.bcx.ins().isub(zero, val)
|
||||
@ -343,10 +361,19 @@ fn trans_stmt<'tcx>(
|
||||
let operand = trans_operand(fx, operand);
|
||||
let from_ty = operand.layout().ty;
|
||||
|
||||
fn is_fat_ptr<'tcx>(fx: &FunctionCx<'_, 'tcx, impl Backend>, ty: Ty<'tcx>) -> bool {
|
||||
ty
|
||||
.builtin_deref(true)
|
||||
.map(|ty::TypeAndMut {ty: pointee_ty, mutbl: _ }| fx.layout_of(pointee_ty).is_unsized())
|
||||
fn is_fat_ptr<'tcx>(
|
||||
fx: &FunctionCx<'_, 'tcx, impl Backend>,
|
||||
ty: Ty<'tcx>,
|
||||
) -> bool {
|
||||
ty.builtin_deref(true)
|
||||
.map(
|
||||
|ty::TypeAndMut {
|
||||
ty: pointee_ty,
|
||||
mutbl: _,
|
||||
}| {
|
||||
fx.layout_of(pointee_ty).is_unsized()
|
||||
},
|
||||
)
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
@ -363,17 +390,27 @@ fn is_fat_ptr<'tcx>(fx: &FunctionCx<'_, 'tcx, impl Backend>, ty: Ty<'tcx>) -> bo
|
||||
// enum -> discriminant value
|
||||
assert!(adt_def.is_enum());
|
||||
match to_ty.sty {
|
||||
ty::Uint(_) | ty::Int(_) => {},
|
||||
ty::Uint(_) | ty::Int(_) => {}
|
||||
_ => unreachable!("cast adt {} -> {}", from_ty, to_ty),
|
||||
}
|
||||
|
||||
let discr = crate::discriminant::codegen_get_discriminant(fx, operand, fx.layout_of(to_ty));
|
||||
let discr = crate::discriminant::codegen_get_discriminant(
|
||||
fx,
|
||||
operand,
|
||||
fx.layout_of(to_ty),
|
||||
);
|
||||
lval.write_cvalue(fx, discr);
|
||||
} else {
|
||||
let to_clif_ty = fx.clif_type(to_ty).unwrap();
|
||||
let from = operand.load_scalar(fx);
|
||||
|
||||
let res = clif_int_or_float_cast(fx, from, type_sign(from_ty), to_clif_ty, type_sign(to_ty));
|
||||
let res = clif_int_or_float_cast(
|
||||
fx,
|
||||
from,
|
||||
type_sign(from_ty),
|
||||
to_clif_ty,
|
||||
type_sign(to_ty),
|
||||
);
|
||||
lval.write_cvalue(fx, CValue::by_val(res, dest_layout));
|
||||
}
|
||||
}
|
||||
@ -391,9 +428,7 @@ fn is_fat_ptr<'tcx>(fx: &FunctionCx<'_, 'tcx, impl Backend>, ty: Ty<'tcx>) -> bo
|
||||
let func_addr = fx.bcx.ins().func_addr(fx.pointer_type, func_ref);
|
||||
lval.write_cvalue(fx, CValue::by_val(func_addr, lval.layout()));
|
||||
}
|
||||
_ => {
|
||||
bug!("{} cannot be cast to a fn ptr", operand.layout().ty)
|
||||
}
|
||||
_ => bug!("{} cannot be cast to a fn ptr", operand.layout().ty),
|
||||
}
|
||||
}
|
||||
Rvalue::Cast(CastKind::Pointer(PointerCast::Unsize), operand, _ty) => {
|
||||
@ -403,7 +438,8 @@ fn is_fat_ptr<'tcx>(fx: &FunctionCx<'_, 'tcx, impl Backend>, ty: Ty<'tcx>) -> bo
|
||||
Rvalue::Discriminant(place) => {
|
||||
let place = trans_place(fx, place);
|
||||
let value = place.to_cvalue(fx);
|
||||
let discr = crate::discriminant::codegen_get_discriminant(fx, value, dest_layout);
|
||||
let discr =
|
||||
crate::discriminant::codegen_get_discriminant(fx, value, dest_layout);
|
||||
lval.write_cvalue(fx, discr);
|
||||
}
|
||||
Rvalue::Repeat(operand, times) => {
|
||||
@ -478,15 +514,19 @@ fn is_fat_ptr<'tcx>(fx: &FunctionCx<'_, 'tcx, impl Backend>, ty: Ty<'tcx>) -> bo
|
||||
|
||||
StatementKind::InlineAsm(asm) => {
|
||||
use syntax::ast::Name;
|
||||
let InlineAsm { asm, outputs: _, inputs: _ } = &**asm;
|
||||
let InlineAsm {
|
||||
asm,
|
||||
outputs: _,
|
||||
inputs: _,
|
||||
} = &**asm;
|
||||
let rustc::hir::InlineAsm {
|
||||
asm: asm_code, // Name
|
||||
outputs, // Vec<Name>
|
||||
inputs, // Vec<Name>
|
||||
clobbers, // Vec<Name>
|
||||
volatile, // bool
|
||||
alignstack, // bool
|
||||
dialect: _, // syntax::ast::AsmDialect
|
||||
outputs, // Vec<Name>
|
||||
inputs, // Vec<Name>
|
||||
clobbers, // Vec<Name>
|
||||
volatile, // bool
|
||||
alignstack, // bool
|
||||
dialect: _, // syntax::ast::AsmDialect
|
||||
asm_str_style: _,
|
||||
} = asm;
|
||||
match &*asm_code.as_str() {
|
||||
@ -494,7 +534,10 @@ fn is_fat_ptr<'tcx>(fx: &FunctionCx<'_, 'tcx, impl Backend>, ty: Ty<'tcx>) -> bo
|
||||
assert_eq!(inputs, &[Name::intern("{eax}"), Name::intern("{ecx}")]);
|
||||
|
||||
assert_eq!(outputs.len(), 4);
|
||||
for (i, c) in (&["={eax}", "={ebx}", "={ecx}", "={edx}"]).iter().enumerate() {
|
||||
for (i, c) in (&["={eax}", "={ebx}", "={ecx}", "={edx}"])
|
||||
.iter()
|
||||
.enumerate()
|
||||
{
|
||||
assert_eq!(&outputs[i].constraint.as_str(), c);
|
||||
assert!(!outputs[i].is_rw);
|
||||
assert!(!outputs[i].is_indirect);
|
||||
@ -505,7 +548,10 @@ fn is_fat_ptr<'tcx>(fx: &FunctionCx<'_, 'tcx, impl Backend>, ty: Ty<'tcx>) -> bo
|
||||
assert!(!volatile);
|
||||
assert!(!alignstack);
|
||||
|
||||
crate::trap::trap_unimplemented(fx, "__cpuid_count arch intrinsic is not supported");
|
||||
crate::trap::trap_unimplemented(
|
||||
fx,
|
||||
"__cpuid_count arch intrinsic is not supported",
|
||||
);
|
||||
}
|
||||
"xgetbv" => {
|
||||
assert_eq!(inputs, &[Name::intern("{ecx}")]);
|
||||
@ -565,7 +611,7 @@ pub fn trans_place<'tcx>(
|
||||
let instance = Instance::new(static_.def_id, fx.monomorphize(&substs));
|
||||
crate::constant::trans_promoted(fx, instance, promoted, static_.ty)
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
trans_place_projection(fx, base, &place.projection)
|
||||
@ -615,7 +661,9 @@ pub fn trans_place_projection<'tcx>(
|
||||
let len = crate::constant::force_eval_const(fx, len)
|
||||
.eval_usize(fx.tcx, ParamEnv::reveal_all());
|
||||
CPlace::for_addr(
|
||||
fx.bcx.ins().iadd_imm(ptr, elem_layout.size.bytes() as i64 * from as i64),
|
||||
fx.bcx
|
||||
.ins()
|
||||
.iadd_imm(ptr, elem_layout.size.bytes() as i64 * from as i64),
|
||||
fx.layout_of(fx.tcx.mk_array(elem_ty, len - from as u64 - to as u64)),
|
||||
)
|
||||
}
|
||||
@ -624,7 +672,9 @@ pub fn trans_place_projection<'tcx>(
|
||||
let (ptr, len) = base.to_addr_maybe_unsized(fx);
|
||||
let len = len.unwrap();
|
||||
CPlace::for_addr_with_extra(
|
||||
fx.bcx.ins().iadd_imm(ptr, elem_layout.size.bytes() as i64 * from as i64),
|
||||
fx.bcx
|
||||
.ins()
|
||||
.iadd_imm(ptr, elem_layout.size.bytes() as i64 * from as i64),
|
||||
fx.bcx.ins().iadd_imm(len, -(from as i64 + to as i64)),
|
||||
base.layout(),
|
||||
)
|
||||
|
76
src/cast.rs
76
src/cast.rs
@ -40,9 +40,7 @@ pub fn clif_intcast(
|
||||
fx.bcx.ins().ireduce(to, lsb)
|
||||
}
|
||||
}
|
||||
(_, _) => {
|
||||
fx.bcx.ins().ireduce(to, val)
|
||||
}
|
||||
(_, _) => fx.bcx.ins().ireduce(to, val),
|
||||
}
|
||||
}
|
||||
|
||||
@ -71,13 +69,10 @@ pub fn clif_int_or_float_cast(
|
||||
// __floatuntisf: u128 -> f32
|
||||
// __floatuntidf: u128 -> f64
|
||||
|
||||
let name = format!("__float{sign}ti{flt}f",
|
||||
sign=if from_signed {
|
||||
""
|
||||
} else {
|
||||
"un"
|
||||
},
|
||||
flt=match to_ty {
|
||||
let name = format!(
|
||||
"__float{sign}ti{flt}f",
|
||||
sign = if from_signed { "" } else { "un" },
|
||||
flt = match to_ty {
|
||||
types::F32 => "s",
|
||||
types::F64 => "d",
|
||||
_ => unreachable!("{:?}", to_ty),
|
||||
@ -96,11 +91,13 @@ pub fn clif_int_or_float_cast(
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
return fx.easy_call(
|
||||
&name,
|
||||
&[CValue::by_val(from, fx.layout_of(from_rust_ty))],
|
||||
to_rust_ty,
|
||||
).load_scalar(fx);
|
||||
return fx
|
||||
.easy_call(
|
||||
&name,
|
||||
&[CValue::by_val(from, fx.layout_of(from_rust_ty))],
|
||||
to_rust_ty,
|
||||
)
|
||||
.load_scalar(fx);
|
||||
}
|
||||
|
||||
// int-like -> float
|
||||
@ -117,13 +114,10 @@ pub fn clif_int_or_float_cast(
|
||||
// __fixunssfti: f32 -> u128
|
||||
// __fixunsdfti: f64 -> u128
|
||||
|
||||
let name = format!("__fix{sign}{flt}fti",
|
||||
sign=if to_signed {
|
||||
""
|
||||
} else {
|
||||
"uns"
|
||||
},
|
||||
flt=match from_ty {
|
||||
let name = format!(
|
||||
"__fix{sign}{flt}fti",
|
||||
sign = if to_signed { "" } else { "uns" },
|
||||
flt = match from_ty {
|
||||
types::F32 => "s",
|
||||
types::F64 => "d",
|
||||
_ => unreachable!("{:?}", to_ty),
|
||||
@ -142,11 +136,13 @@ pub fn clif_int_or_float_cast(
|
||||
fx.tcx.types.u128
|
||||
};
|
||||
|
||||
return fx.easy_call(
|
||||
&name,
|
||||
&[CValue::by_val(from, fx.layout_of(from_rust_ty))],
|
||||
to_rust_ty,
|
||||
).load_scalar(fx);
|
||||
return fx
|
||||
.easy_call(
|
||||
&name,
|
||||
&[CValue::by_val(from, fx.layout_of(from_rust_ty))],
|
||||
to_rust_ty,
|
||||
)
|
||||
.load_scalar(fx);
|
||||
}
|
||||
|
||||
// float -> int-like
|
||||
@ -162,24 +158,12 @@ pub fn clif_int_or_float_cast(
|
||||
let max_val = fx.bcx.ins().iconst(types::I32, max);
|
||||
|
||||
let val = if to_signed {
|
||||
let has_underflow = fx.bcx.ins().icmp_imm(
|
||||
IntCC::SignedLessThan,
|
||||
val,
|
||||
min,
|
||||
);
|
||||
let has_overflow = fx.bcx.ins().icmp_imm(
|
||||
IntCC::SignedGreaterThan,
|
||||
val,
|
||||
max,
|
||||
);
|
||||
let has_underflow = fx.bcx.ins().icmp_imm(IntCC::SignedLessThan, val, min);
|
||||
let has_overflow = fx.bcx.ins().icmp_imm(IntCC::SignedGreaterThan, val, max);
|
||||
let bottom_capped = fx.bcx.ins().select(has_underflow, min_val, val);
|
||||
fx.bcx.ins().select(has_overflow, max_val, bottom_capped)
|
||||
} else {
|
||||
let has_overflow = fx.bcx.ins().icmp_imm(
|
||||
IntCC::UnsignedGreaterThan,
|
||||
val,
|
||||
max,
|
||||
);
|
||||
let has_overflow = fx.bcx.ins().icmp_imm(IntCC::UnsignedGreaterThan, val, max);
|
||||
fx.bcx.ins().select(has_overflow, max_val, val)
|
||||
};
|
||||
fx.bcx.ins().ireduce(to_ty, val)
|
||||
@ -193,12 +177,8 @@ pub fn clif_int_or_float_cast(
|
||||
} else if from_ty.is_float() && to_ty.is_float() {
|
||||
// float -> float
|
||||
match (from_ty, to_ty) {
|
||||
(types::F32, types::F64) => {
|
||||
fx.bcx.ins().fpromote(types::F64, from)
|
||||
}
|
||||
(types::F64, types::F32) => {
|
||||
fx.bcx.ins().fdemote(types::F32, from)
|
||||
}
|
||||
(types::F32, types::F64) => fx.bcx.ins().fpromote(types::F64, from),
|
||||
(types::F64, types::F32) => fx.bcx.ins().fdemote(types::F32, from),
|
||||
_ => from,
|
||||
}
|
||||
} else {
|
||||
|
@ -30,7 +30,7 @@ pub fn maybe_codegen<'tcx>(
|
||||
fx.easy_call("__rust_i128_addo", &[lhs, rhs], out_ty)
|
||||
} else {
|
||||
fx.easy_call("__rust_u128_addo", &[lhs, rhs], out_ty)
|
||||
})
|
||||
});
|
||||
}
|
||||
BinOp::Sub => {
|
||||
let out_ty = fx.tcx.mk_tup([lhs.layout().ty, fx.tcx.types.bool].iter());
|
||||
@ -38,7 +38,7 @@ pub fn maybe_codegen<'tcx>(
|
||||
fx.easy_call("__rust_i128_subo", &[lhs, rhs], out_ty)
|
||||
} else {
|
||||
fx.easy_call("__rust_u128_subo", &[lhs, rhs], out_ty)
|
||||
})
|
||||
});
|
||||
}
|
||||
BinOp::Offset => unreachable!("offset should only be used on pointers, not 128bit ints"),
|
||||
BinOp::Mul => {
|
||||
@ -50,7 +50,11 @@ pub fn maybe_codegen<'tcx>(
|
||||
fx.easy_call("__rust_u128_mulo", &[lhs, rhs], out_ty)
|
||||
}
|
||||
} else {
|
||||
let val_ty = if is_signed { fx.tcx.types.i128 } else { fx.tcx.types.u128 };
|
||||
let val_ty = if is_signed {
|
||||
fx.tcx.types.i128
|
||||
} else {
|
||||
fx.tcx.types.u128
|
||||
};
|
||||
fx.easy_call("__multi3", &[lhs, rhs], val_ty)
|
||||
};
|
||||
return Some(res);
|
||||
@ -111,17 +115,21 @@ pub fn maybe_codegen<'tcx>(
|
||||
Some(CValue::by_val(val, fx.layout_of(fx.tcx.types.i128)))
|
||||
}
|
||||
(BinOp::Shl, _) => {
|
||||
let val_ty = if is_signed { fx.tcx.types.i128 } else { fx.tcx.types.u128 };
|
||||
let val_ty = if is_signed {
|
||||
fx.tcx.types.i128
|
||||
} else {
|
||||
fx.tcx.types.u128
|
||||
};
|
||||
let val = fx.bcx.ins().iconcat(all_zeros, lhs_lsb);
|
||||
Some(CValue::by_val(val, fx.layout_of(val_ty)))
|
||||
}
|
||||
_ => None
|
||||
_ => None,
|
||||
};
|
||||
if let Some(val) = val {
|
||||
if let Some(is_overflow) = is_overflow {
|
||||
let out_ty = fx.tcx.mk_tup([lhs.layout().ty, fx.tcx.types.bool].iter());
|
||||
let val = val.load_scalar(fx);
|
||||
return Some(CValue::by_val_pair(val, is_overflow, fx.layout_of(out_ty)))
|
||||
return Some(CValue::by_val_pair(val, is_overflow, fx.layout_of(out_ty)));
|
||||
} else {
|
||||
return Some(val);
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
use rustc::ty::layout::{FloatTy, Integer, Primitive};
|
||||
use rustc_target::spec::{HasTargetSpec, Target};
|
||||
|
||||
use cranelift::codegen::ir::{Opcode, InstructionData, ValueDef};
|
||||
use cranelift::codegen::ir::{InstructionData, Opcode, ValueDef};
|
||||
|
||||
use crate::prelude::*;
|
||||
|
||||
@ -35,10 +35,7 @@ pub fn scalar_to_clif_type(tcx: TyCtxt, scalar: Scalar) -> Type {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clif_type_from_ty<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
) -> Option<types::Type> {
|
||||
pub fn clif_type_from_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option<types::Type> {
|
||||
Some(match ty.sty {
|
||||
ty::Bool => types::I8,
|
||||
ty::Uint(size) => match size {
|
||||
@ -184,7 +181,8 @@ fn resolve_normal_value_imm(func: &Function, val: Value) -> Option<i64> {
|
||||
if let InstructionData::UnaryImm {
|
||||
opcode: Opcode::Iconst,
|
||||
imm,
|
||||
} = func.dfg[inst] {
|
||||
} = func.dfg[inst]
|
||||
{
|
||||
Some(imm.into())
|
||||
} else {
|
||||
None
|
||||
@ -199,7 +197,8 @@ fn resolve_128bit_value_imm(func: &Function, val: Value) -> Option<u128> {
|
||||
if let InstructionData::Binary {
|
||||
opcode: Opcode::Iconcat,
|
||||
args: [lsb, msb],
|
||||
} = func.dfg[inst] {
|
||||
} = func.dfg[inst]
|
||||
{
|
||||
(lsb, msb)
|
||||
} else {
|
||||
return None;
|
||||
@ -225,10 +224,9 @@ pub fn resolve_value_imm(func: &Function, val: Value) -> Option<u128> {
|
||||
pub fn type_min_max_value(ty: Type, signed: bool) -> (i64, i64) {
|
||||
assert!(ty.is_int());
|
||||
let min = match (ty, signed) {
|
||||
(types::I8 , false)
|
||||
| (types::I16, false)
|
||||
| (types::I32, false)
|
||||
| (types::I64, false) => 0i64,
|
||||
(types::I8, false) | (types::I16, false) | (types::I32, false) | (types::I64, false) => {
|
||||
0i64
|
||||
}
|
||||
(types::I8, true) => i8::min_value() as i64,
|
||||
(types::I16, true) => i16::min_value() as i64,
|
||||
(types::I32, true) => i32::min_value() as i64,
|
||||
@ -287,11 +285,14 @@ impl<'tcx, B: Backend> LayoutOf for FunctionCx<'_, 'tcx, B> {
|
||||
|
||||
fn layout_of(&self, ty: Ty<'tcx>) -> TyLayout<'tcx> {
|
||||
let ty = self.monomorphize(&ty);
|
||||
self.tcx.layout_of(ParamEnv::reveal_all().and(&ty))
|
||||
.unwrap_or_else(|e| if let layout::LayoutError::SizeOverflow(_) = e {
|
||||
self.tcx.sess.fatal(&e.to_string())
|
||||
} else {
|
||||
bug!("failed to get layout for `{}`: {}", ty, e)
|
||||
self.tcx
|
||||
.layout_of(ParamEnv::reveal_all().and(&ty))
|
||||
.unwrap_or_else(|e| {
|
||||
if let layout::LayoutError::SizeOverflow(_) = e {
|
||||
self.tcx.sess.fatal(&e.to_string())
|
||||
} else {
|
||||
bug!("failed to get layout for `{}`: {}", ty, e)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
129
src/constant.rs
129
src/constant.rs
@ -1,12 +1,11 @@
|
||||
use std::borrow::Cow;
|
||||
|
||||
use rustc::mir::interpret::{
|
||||
read_target_uint, AllocId, GlobalAlloc, Allocation, ConstValue, InterpResult, GlobalId, Scalar,
|
||||
read_target_uint, AllocId, Allocation, ConstValue, GlobalAlloc, GlobalId, InterpResult, Scalar,
|
||||
};
|
||||
use rustc::ty::{Const, layout::Align};
|
||||
use rustc::ty::{layout::Align, Const};
|
||||
use rustc_mir::interpret::{
|
||||
InterpCx, ImmTy, Machine, Memory, MemoryKind, OpTy, PlaceTy, Pointer,
|
||||
StackPopCleanup,
|
||||
ImmTy, InterpCx, Machine, Memory, MemoryKind, OpTy, PlaceTy, Pointer, StackPopCleanup,
|
||||
};
|
||||
|
||||
use cranelift_module::*;
|
||||
@ -26,11 +25,7 @@ enum TodoItem {
|
||||
}
|
||||
|
||||
impl ConstantCx {
|
||||
pub fn finalize(
|
||||
mut self,
|
||||
tcx: TyCtxt<'_>,
|
||||
module: &mut Module<impl Backend>,
|
||||
) {
|
||||
pub fn finalize(mut self, tcx: TyCtxt<'_>, module: &mut Module<impl Backend>) {
|
||||
//println!("todo {:?}", self.todo);
|
||||
define_all_allocs(tcx, module, &mut self);
|
||||
//println!("done {:?}", self.done);
|
||||
@ -58,25 +53,20 @@ pub fn trans_promoted<'tcx>(
|
||||
promoted: Promoted,
|
||||
dest_ty: Ty<'tcx>,
|
||||
) -> CPlace<'tcx> {
|
||||
match fx
|
||||
.tcx
|
||||
.const_eval(ParamEnv::reveal_all().and(GlobalId {
|
||||
instance,
|
||||
promoted: Some(promoted),
|
||||
}))
|
||||
{
|
||||
match fx.tcx.const_eval(ParamEnv::reveal_all().and(GlobalId {
|
||||
instance,
|
||||
promoted: Some(promoted),
|
||||
})) {
|
||||
Ok(const_) => {
|
||||
let cplace = trans_const_place(fx, const_);
|
||||
debug_assert_eq!(cplace.layout(), fx.layout_of(dest_ty));
|
||||
cplace
|
||||
}
|
||||
Err(_) => {
|
||||
crate::trap::trap_unreachable_ret_place(
|
||||
fx,
|
||||
fx.layout_of(dest_ty),
|
||||
"[panic] Tried to get value of promoted value with errored during const eval.",
|
||||
)
|
||||
}
|
||||
Err(_) => crate::trap::trap_unreachable_ret_place(
|
||||
fx,
|
||||
fx.layout_of(dest_ty),
|
||||
"[panic] Tried to get value of promoted value with errored during const eval.",
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
@ -120,13 +110,23 @@ pub fn trans_const_value<'tcx>(
|
||||
}
|
||||
ty::Int(_) => {
|
||||
let bits = const_.val.try_to_bits(layout.size).unwrap();
|
||||
CValue::const_val(fx, ty, rustc::mir::interpret::sign_extend(bits, layout.size))
|
||||
CValue::const_val(
|
||||
fx,
|
||||
ty,
|
||||
rustc::mir::interpret::sign_extend(bits, layout.size),
|
||||
)
|
||||
}
|
||||
ty::Float(fty) => {
|
||||
let bits = const_.val.try_to_bits(layout.size).unwrap();
|
||||
let val = match fty {
|
||||
FloatTy::F32 => fx.bcx.ins().f32const(Ieee32::with_bits(u32::try_from(bits).unwrap())),
|
||||
FloatTy::F64 => fx.bcx.ins().f64const(Ieee64::with_bits(u64::try_from(bits).unwrap())),
|
||||
FloatTy::F32 => fx
|
||||
.bcx
|
||||
.ins()
|
||||
.f32const(Ieee32::with_bits(u32::try_from(bits).unwrap())),
|
||||
FloatTy::F64 => fx
|
||||
.bcx
|
||||
.ins()
|
||||
.f64const(Ieee64::with_bits(u64::try_from(bits).unwrap())),
|
||||
};
|
||||
CValue::by_val(val, layout)
|
||||
}
|
||||
@ -170,7 +170,9 @@ fn trans_const_place<'tcx>(
|
||||
)?;
|
||||
let ptr = ecx.allocate(op.layout, MemoryKind::Stack);
|
||||
ecx.copy_op(op, ptr.into())?;
|
||||
let alloc = ecx.memory().get(ptr.to_ref().to_scalar()?.to_ptr()?.alloc_id)?;
|
||||
let alloc = ecx
|
||||
.memory()
|
||||
.get(ptr.to_ref().to_scalar()?.to_ptr()?.alloc_id)?;
|
||||
Ok(fx.tcx.intern_const_alloc(alloc.clone()))
|
||||
};
|
||||
let alloc = result().expect("unable to convert ConstValue to Allocation");
|
||||
@ -182,9 +184,18 @@ fn trans_const_place<'tcx>(
|
||||
cplace_for_dataid(fx, const_.ty, data_id)
|
||||
}
|
||||
|
||||
fn data_id_for_alloc_id<B: Backend>(module: &mut Module<B>, alloc_id: AllocId, align: Align) -> DataId {
|
||||
fn data_id_for_alloc_id<B: Backend>(
|
||||
module: &mut Module<B>,
|
||||
alloc_id: AllocId,
|
||||
align: Align,
|
||||
) -> DataId {
|
||||
module
|
||||
.declare_data(&format!("__alloc_{}", alloc_id.0), Linkage::Local, false, Some(align.bytes() as u8))
|
||||
.declare_data(
|
||||
&format!("__alloc_{}", alloc_id.0),
|
||||
Linkage::Local,
|
||||
false,
|
||||
Some(align.bytes() as u8),
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
@ -202,16 +213,29 @@ fn data_id_for_static(
|
||||
} else {
|
||||
!ty.is_freeze(tcx, ParamEnv::reveal_all(), DUMMY_SP)
|
||||
};
|
||||
let align = tcx.layout_of(ParamEnv::reveal_all().and(ty)).unwrap().align.pref.bytes();
|
||||
let align = tcx
|
||||
.layout_of(ParamEnv::reveal_all().and(ty))
|
||||
.unwrap()
|
||||
.align
|
||||
.pref
|
||||
.bytes();
|
||||
|
||||
let data_id = module
|
||||
.declare_data(&*symbol_name, linkage, is_mutable, Some(align.try_into().unwrap()))
|
||||
.declare_data(
|
||||
&*symbol_name,
|
||||
linkage,
|
||||
is_mutable,
|
||||
Some(align.try_into().unwrap()),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
if linkage == Linkage::Preemptible {
|
||||
if let ty::RawPtr(_) = ty.sty {
|
||||
} else {
|
||||
tcx.sess.span_fatal(tcx.def_span(def_id), "must have type `*const T` or `*mut T` due to `#[linkage]` attribute")
|
||||
tcx.sess.span_fatal(
|
||||
tcx.def_span(def_id),
|
||||
"must have type `*const T` or `*mut T` due to `#[linkage]` attribute",
|
||||
)
|
||||
}
|
||||
|
||||
let mut data_ctx = DataContext::new();
|
||||
@ -243,11 +267,7 @@ fn cplace_for_dataid<'tcx>(
|
||||
CPlace::for_addr(global_ptr, layout)
|
||||
}
|
||||
|
||||
fn define_all_allocs(
|
||||
tcx: TyCtxt<'_>,
|
||||
module: &mut Module<impl Backend>,
|
||||
cx: &mut ConstantCx,
|
||||
) {
|
||||
fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut Module<impl Backend>, cx: &mut ConstantCx) {
|
||||
let memory = Memory::<TransPlaceInterpreter>::new(tcx.at(DUMMY_SP), ());
|
||||
|
||||
while let Some(todo_item) = pop_set(&mut cx.todo) {
|
||||
@ -277,11 +297,16 @@ fn define_all_allocs(
|
||||
_ => bug!("static const eval returned {:#?}", const_),
|
||||
};
|
||||
|
||||
let data_id = data_id_for_static(tcx, module, def_id, if tcx.is_reachable_non_generic(def_id) {
|
||||
Linkage::Export
|
||||
} else {
|
||||
Linkage::Local
|
||||
});
|
||||
let data_id = data_id_for_static(
|
||||
tcx,
|
||||
module,
|
||||
def_id,
|
||||
if tcx.is_reachable_non_generic(def_id) {
|
||||
Linkage::Export
|
||||
} else {
|
||||
Linkage::Local
|
||||
},
|
||||
);
|
||||
(data_id, alloc)
|
||||
}
|
||||
};
|
||||
@ -395,10 +420,7 @@ fn call_intrinsic(
|
||||
panic!();
|
||||
}
|
||||
|
||||
fn find_foreign_static(
|
||||
_: TyCtxt<'tcx>,
|
||||
_: DefId,
|
||||
) -> InterpResult<'tcx, Cow<'tcx, Allocation>> {
|
||||
fn find_foreign_static(_: TyCtxt<'tcx>, _: DefId) -> InterpResult<'tcx, Cow<'tcx, Allocation>> {
|
||||
panic!();
|
||||
}
|
||||
|
||||
@ -411,10 +433,7 @@ fn binary_ptr_op(
|
||||
panic!();
|
||||
}
|
||||
|
||||
fn ptr_to_int(
|
||||
_: &Memory<'mir, 'tcx, Self>,
|
||||
_: Pointer<()>,
|
||||
) -> InterpResult<'tcx, u64> {
|
||||
fn ptr_to_int(_: &Memory<'mir, 'tcx, Self>, _: Pointer<()>) -> InterpResult<'tcx, u64> {
|
||||
panic!();
|
||||
}
|
||||
|
||||
@ -473,10 +492,12 @@ pub fn mir_operand_get_const_val<'tcx>(
|
||||
StaticKind::Static => unimplemented!(),
|
||||
StaticKind::Promoted(promoted, substs) => {
|
||||
let instance = Instance::new(static_.def_id, fx.monomorphize(substs));
|
||||
fx.tcx.const_eval(ParamEnv::reveal_all().and(GlobalId {
|
||||
instance,
|
||||
promoted: Some(*promoted),
|
||||
})).unwrap()
|
||||
fx.tcx
|
||||
.const_eval(ParamEnv::reveal_all().and(GlobalId {
|
||||
instance,
|
||||
promoted: Some(*promoted),
|
||||
}))
|
||||
.unwrap()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -30,11 +30,7 @@ fn line_program_add_file(
|
||||
FileName::Real(path) => {
|
||||
let dir_name = path.parent().unwrap().to_str().unwrap().as_bytes();
|
||||
let dir_id = if !dir_name.is_empty() {
|
||||
let dir_name = LineString::new(
|
||||
dir_name,
|
||||
line_program.encoding(),
|
||||
line_strings,
|
||||
);
|
||||
let dir_name = LineString::new(dir_name, line_program.encoding(), line_strings);
|
||||
line_program.add_directory(dir_name)
|
||||
} else {
|
||||
line_program.default_directory()
|
||||
@ -196,7 +192,11 @@ pub fn emit(&mut self, artifact: &mut Artifact) {
|
||||
let _: Result<()> = sections.for_each_mut(|id, section| {
|
||||
if !section.writer.slice().is_empty() {
|
||||
artifact
|
||||
.declare_with(id.name(), Decl::section(SectionKind::Debug), section.writer.take())
|
||||
.declare_with(
|
||||
id.name(),
|
||||
Decl::section(SectionKind::Debug),
|
||||
section.writer.take(),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
Ok(())
|
||||
|
@ -33,11 +33,12 @@ pub fn codegen_set_discriminant<'tcx>(
|
||||
layout::Variants::Multiple {
|
||||
discr: _,
|
||||
discr_index,
|
||||
discr_kind: layout::DiscriminantKind::Niche {
|
||||
dataful_variant,
|
||||
ref niche_variants,
|
||||
niche_start,
|
||||
},
|
||||
discr_kind:
|
||||
layout::DiscriminantKind::Niche {
|
||||
dataful_variant,
|
||||
ref niche_variants,
|
||||
niche_start,
|
||||
},
|
||||
variants: _,
|
||||
} => {
|
||||
if variant_index != dataful_variant {
|
||||
@ -59,7 +60,11 @@ pub fn codegen_get_discriminant<'tcx>(
|
||||
let layout = value.layout();
|
||||
|
||||
if layout.abi == layout::Abi::Uninhabited {
|
||||
return trap_unreachable_ret_value(fx, dest_layout, "[panic] Tried to get discriminant for uninhabited type.");
|
||||
return trap_unreachable_ret_value(
|
||||
fx,
|
||||
dest_layout,
|
||||
"[panic] Tried to get discriminant for uninhabited type.",
|
||||
);
|
||||
}
|
||||
|
||||
let (discr_scalar, discr_index, discr_kind) = match &layout.variants {
|
||||
@ -70,9 +75,12 @@ pub fn codegen_get_discriminant<'tcx>(
|
||||
.map_or(u128::from(index.as_u32()), |discr| discr.val);
|
||||
return CValue::const_val(fx, dest_layout.ty, discr_val);
|
||||
}
|
||||
layout::Variants::Multiple { discr, discr_index, discr_kind, variants: _ } => {
|
||||
(discr, *discr_index, discr_kind)
|
||||
}
|
||||
layout::Variants::Multiple {
|
||||
discr,
|
||||
discr_index,
|
||||
discr_kind,
|
||||
variants: _,
|
||||
} => (discr, *discr_index, discr_kind),
|
||||
};
|
||||
|
||||
let cast_to = fx.clif_type(dest_layout.ty).unwrap();
|
||||
@ -86,7 +94,7 @@ pub fn codegen_get_discriminant<'tcx>(
|
||||
layout::DiscriminantKind::Tag => {
|
||||
let signed = match discr_scalar.value {
|
||||
layout::Int(_, signed) => signed,
|
||||
_ => false
|
||||
_ => false,
|
||||
};
|
||||
let val = clif_intcast(fx, encoded_discr, cast_to, signed);
|
||||
return CValue::by_val(val, dest_layout);
|
||||
@ -112,11 +120,18 @@ pub fn codegen_get_discriminant<'tcx>(
|
||||
encoded_discr
|
||||
} else {
|
||||
// FIXME handle niche_start > i64::max_value()
|
||||
fx.bcx.ins().iadd_imm(encoded_discr, -i64::try_from(niche_start).unwrap())
|
||||
fx.bcx
|
||||
.ins()
|
||||
.iadd_imm(encoded_discr, -i64::try_from(niche_start).unwrap())
|
||||
};
|
||||
let relative_max = niche_variants.end().as_u32() - niche_variants.start().as_u32();
|
||||
let is_niche = {
|
||||
codegen_icmp_imm(fx, IntCC::UnsignedLessThanOrEqual, relative_discr, i128::from(relative_max))
|
||||
codegen_icmp_imm(
|
||||
fx,
|
||||
IntCC::UnsignedLessThanOrEqual,
|
||||
relative_discr,
|
||||
i128::from(relative_max),
|
||||
)
|
||||
};
|
||||
|
||||
// NOTE(eddyb) this addition needs to be performed on the final
|
||||
@ -135,18 +150,16 @@ pub fn codegen_get_discriminant<'tcx>(
|
||||
} else {
|
||||
clif_intcast(fx, relative_discr, cast_to, false)
|
||||
};
|
||||
fx.bcx.ins().iadd_imm(
|
||||
relative_discr,
|
||||
i64::from(niche_variants.start().as_u32()),
|
||||
)
|
||||
fx.bcx
|
||||
.ins()
|
||||
.iadd_imm(relative_discr, i64::from(niche_variants.start().as_u32()))
|
||||
};
|
||||
|
||||
let dataful_variant = fx.bcx.ins().iconst(cast_to, i64::from(dataful_variant.as_u32()));
|
||||
let discr = fx.bcx.ins().select(
|
||||
is_niche,
|
||||
niche_discr,
|
||||
dataful_variant,
|
||||
);
|
||||
let dataful_variant = fx
|
||||
.bcx
|
||||
.ins()
|
||||
.iconst(cast_to, i64::from(dataful_variant.as_u32()));
|
||||
let discr = fx.bcx.ins().select(is_niche, niche_discr, dataful_variant);
|
||||
CValue::by_val(discr, dest_layout)
|
||||
}
|
||||
}
|
||||
|
@ -109,7 +109,9 @@ fn load_imported_symbols_for_jit(tcx: TyCtxt<'_>) -> Vec<(String, *const u8)> {
|
||||
Linkage::NotLinked | Linkage::IncludedFromDylib => {}
|
||||
Linkage::Static => {
|
||||
let name = tcx.crate_name(cnum);
|
||||
let mut err = tcx.sess.struct_err(&format!("Can't load static lib {}", name.as_str()));
|
||||
let mut err = tcx
|
||||
.sess
|
||||
.struct_err(&format!("Can't load static lib {}", name.as_str()));
|
||||
err.note("rustc_codegen_cranelift can only load dylibs in JIT mode.");
|
||||
err.emit();
|
||||
}
|
||||
@ -222,8 +224,10 @@ fn run_aot(
|
||||
.as_str()
|
||||
.to_string();
|
||||
|
||||
let mut metadata_artifact =
|
||||
faerie::Artifact::new(crate::build_isa(tcx.sess, true).triple().clone(), metadata_cgu_name.clone());
|
||||
let mut metadata_artifact = faerie::Artifact::new(
|
||||
crate::build_isa(tcx.sess, true).triple().clone(),
|
||||
metadata_cgu_name.clone(),
|
||||
);
|
||||
crate::metadata::write_metadata(tcx, &mut metadata_artifact);
|
||||
|
||||
let tmp_file = tcx
|
||||
|
@ -138,7 +138,10 @@ pub fn lane_type_and_count<'tcx>(
|
||||
assert!(layout.ty.is_simd());
|
||||
let lane_count = match layout.fields {
|
||||
layout::FieldPlacement::Array { stride: _, count } => u32::try_from(count).unwrap(),
|
||||
_ => panic!("Non vector type {:?} passed to or returned from simd_* intrinsic {}", layout.ty, intrinsic),
|
||||
_ => panic!(
|
||||
"Non vector type {:?} passed to or returned from simd_* intrinsic {}",
|
||||
layout.ty, intrinsic
|
||||
),
|
||||
};
|
||||
let lane_layout = layout.field(fx, 0);
|
||||
(lane_layout, lane_count)
|
||||
@ -150,7 +153,13 @@ pub fn simd_for_each_lane<'tcx, B: Backend>(
|
||||
x: CValue<'tcx>,
|
||||
y: CValue<'tcx>,
|
||||
ret: CPlace<'tcx>,
|
||||
f: impl Fn(&mut FunctionCx<'_, 'tcx, B>, TyLayout<'tcx>, TyLayout<'tcx>, Value, Value) -> CValue<'tcx>,
|
||||
f: impl Fn(
|
||||
&mut FunctionCx<'_, 'tcx, B>,
|
||||
TyLayout<'tcx>,
|
||||
TyLayout<'tcx>,
|
||||
Value,
|
||||
Value,
|
||||
) -> CValue<'tcx>,
|
||||
) {
|
||||
assert_eq!(x.layout(), y.layout());
|
||||
let layout = x.layout();
|
||||
@ -184,7 +193,10 @@ pub fn bool_to_zero_or_max_uint<'tcx>(
|
||||
};
|
||||
|
||||
let zero = fx.bcx.ins().iconst(int_ty, 0);
|
||||
let max = fx.bcx.ins().iconst(int_ty, (u64::max_value() >> (64 - int_ty.bits())) as i64);
|
||||
let max = fx
|
||||
.bcx
|
||||
.ins()
|
||||
.iconst(int_ty, (u64::max_value() >> (64 - int_ty.bits())) as i64);
|
||||
let mut res = crate::common::codegen_select(&mut fx.bcx, val, max, zero);
|
||||
|
||||
if ty.is_float() {
|
||||
@ -196,83 +208,131 @@ pub fn bool_to_zero_or_max_uint<'tcx>(
|
||||
|
||||
macro_rules! simd_cmp {
|
||||
($fx:expr, $intrinsic:expr, $cc:ident($x:ident, $y:ident) -> $ret:ident) => {
|
||||
simd_for_each_lane($fx, $intrinsic, $x, $y, $ret, |fx, lane_layout, res_lane_layout, x_lane, y_lane| {
|
||||
let res_lane = match lane_layout.ty.sty {
|
||||
ty::Uint(_) | ty::Int(_) => codegen_icmp(fx, IntCC::$cc, x_lane, y_lane),
|
||||
_ => unreachable!("{:?}", lane_layout.ty),
|
||||
};
|
||||
bool_to_zero_or_max_uint(fx, res_lane_layout, res_lane)
|
||||
});
|
||||
simd_for_each_lane(
|
||||
$fx,
|
||||
$intrinsic,
|
||||
$x,
|
||||
$y,
|
||||
$ret,
|
||||
|fx, lane_layout, res_lane_layout, x_lane, y_lane| {
|
||||
let res_lane = match lane_layout.ty.sty {
|
||||
ty::Uint(_) | ty::Int(_) => codegen_icmp(fx, IntCC::$cc, x_lane, y_lane),
|
||||
_ => unreachable!("{:?}", lane_layout.ty),
|
||||
};
|
||||
bool_to_zero_or_max_uint(fx, res_lane_layout, res_lane)
|
||||
},
|
||||
);
|
||||
};
|
||||
($fx:expr, $intrinsic:expr, $cc_u:ident|$cc_s:ident($x:ident, $y:ident) -> $ret:ident) => {
|
||||
simd_for_each_lane($fx, $intrinsic, $x, $y, $ret, |fx, lane_layout, res_lane_layout, x_lane, y_lane| {
|
||||
let res_lane = match lane_layout.ty.sty {
|
||||
ty::Uint(_) => codegen_icmp(fx, IntCC::$cc_u, x_lane, y_lane),
|
||||
ty::Int(_) => codegen_icmp(fx, IntCC::$cc_s, x_lane, y_lane),
|
||||
_ => unreachable!("{:?}", lane_layout.ty),
|
||||
};
|
||||
bool_to_zero_or_max_uint(fx, res_lane_layout, res_lane)
|
||||
});
|
||||
simd_for_each_lane(
|
||||
$fx,
|
||||
$intrinsic,
|
||||
$x,
|
||||
$y,
|
||||
$ret,
|
||||
|fx, lane_layout, res_lane_layout, x_lane, y_lane| {
|
||||
let res_lane = match lane_layout.ty.sty {
|
||||
ty::Uint(_) => codegen_icmp(fx, IntCC::$cc_u, x_lane, y_lane),
|
||||
ty::Int(_) => codegen_icmp(fx, IntCC::$cc_s, x_lane, y_lane),
|
||||
_ => unreachable!("{:?}", lane_layout.ty),
|
||||
};
|
||||
bool_to_zero_or_max_uint(fx, res_lane_layout, res_lane)
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
macro_rules! simd_int_binop {
|
||||
($fx:expr, $intrinsic:expr, $op:ident($x:ident, $y:ident) -> $ret:ident) => {
|
||||
simd_for_each_lane($fx, $intrinsic, $x, $y, $ret, |fx, lane_layout, ret_lane_layout, x_lane, y_lane| {
|
||||
let res_lane = match lane_layout.ty.sty {
|
||||
ty::Uint(_) | ty::Int(_) => fx.bcx.ins().$op(x_lane, y_lane),
|
||||
_ => unreachable!("{:?}", lane_layout.ty),
|
||||
};
|
||||
CValue::by_val(res_lane, ret_lane_layout)
|
||||
});
|
||||
simd_for_each_lane(
|
||||
$fx,
|
||||
$intrinsic,
|
||||
$x,
|
||||
$y,
|
||||
$ret,
|
||||
|fx, lane_layout, ret_lane_layout, x_lane, y_lane| {
|
||||
let res_lane = match lane_layout.ty.sty {
|
||||
ty::Uint(_) | ty::Int(_) => fx.bcx.ins().$op(x_lane, y_lane),
|
||||
_ => unreachable!("{:?}", lane_layout.ty),
|
||||
};
|
||||
CValue::by_val(res_lane, ret_lane_layout)
|
||||
},
|
||||
);
|
||||
};
|
||||
($fx:expr, $intrinsic:expr, $op_u:ident|$op_s:ident($x:ident, $y:ident) -> $ret:ident) => {
|
||||
simd_for_each_lane($fx, $intrinsic, $x, $y, $ret, |fx, lane_layout, ret_lane_layout, x_lane, y_lane| {
|
||||
let res_lane = match lane_layout.ty.sty {
|
||||
ty::Uint(_) => fx.bcx.ins().$op_u(x_lane, y_lane),
|
||||
ty::Int(_) => fx.bcx.ins().$op_s(x_lane, y_lane),
|
||||
_ => unreachable!("{:?}", lane_layout.ty),
|
||||
};
|
||||
CValue::by_val(res_lane, ret_lane_layout)
|
||||
});
|
||||
simd_for_each_lane(
|
||||
$fx,
|
||||
$intrinsic,
|
||||
$x,
|
||||
$y,
|
||||
$ret,
|
||||
|fx, lane_layout, ret_lane_layout, x_lane, y_lane| {
|
||||
let res_lane = match lane_layout.ty.sty {
|
||||
ty::Uint(_) => fx.bcx.ins().$op_u(x_lane, y_lane),
|
||||
ty::Int(_) => fx.bcx.ins().$op_s(x_lane, y_lane),
|
||||
_ => unreachable!("{:?}", lane_layout.ty),
|
||||
};
|
||||
CValue::by_val(res_lane, ret_lane_layout)
|
||||
},
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! simd_int_flt_binop {
|
||||
($fx:expr, $intrinsic:expr, $op:ident|$op_f:ident($x:ident, $y:ident) -> $ret:ident) => {
|
||||
simd_for_each_lane($fx, $intrinsic, $x, $y, $ret, |fx, lane_layout, ret_lane_layout, x_lane, y_lane| {
|
||||
let res_lane = match lane_layout.ty.sty {
|
||||
ty::Uint(_) | ty::Int(_) => fx.bcx.ins().$op(x_lane, y_lane),
|
||||
ty::Float(_) => fx.bcx.ins().$op_f(x_lane, y_lane),
|
||||
_ => unreachable!("{:?}", lane_layout.ty),
|
||||
};
|
||||
CValue::by_val(res_lane, ret_lane_layout)
|
||||
});
|
||||
simd_for_each_lane(
|
||||
$fx,
|
||||
$intrinsic,
|
||||
$x,
|
||||
$y,
|
||||
$ret,
|
||||
|fx, lane_layout, ret_lane_layout, x_lane, y_lane| {
|
||||
let res_lane = match lane_layout.ty.sty {
|
||||
ty::Uint(_) | ty::Int(_) => fx.bcx.ins().$op(x_lane, y_lane),
|
||||
ty::Float(_) => fx.bcx.ins().$op_f(x_lane, y_lane),
|
||||
_ => unreachable!("{:?}", lane_layout.ty),
|
||||
};
|
||||
CValue::by_val(res_lane, ret_lane_layout)
|
||||
},
|
||||
);
|
||||
};
|
||||
($fx:expr, $intrinsic:expr, $op_u:ident|$op_s:ident|$op_f:ident($x:ident, $y:ident) -> $ret:ident) => {
|
||||
simd_for_each_lane($fx, $intrinsic, $x, $y, $ret, |fx, lane_layout, ret_lane_layout, x_lane, y_lane| {
|
||||
let res_lane = match lane_layout.ty.sty {
|
||||
ty::Uint(_) => fx.bcx.ins().$op_u(x_lane, y_lane),
|
||||
ty::Int(_) => fx.bcx.ins().$op_s(x_lane, y_lane),
|
||||
ty::Float(_) => fx.bcx.ins().$op_f(x_lane, y_lane),
|
||||
_ => unreachable!("{:?}", lane_layout.ty),
|
||||
};
|
||||
CValue::by_val(res_lane, ret_lane_layout)
|
||||
});
|
||||
simd_for_each_lane(
|
||||
$fx,
|
||||
$intrinsic,
|
||||
$x,
|
||||
$y,
|
||||
$ret,
|
||||
|fx, lane_layout, ret_lane_layout, x_lane, y_lane| {
|
||||
let res_lane = match lane_layout.ty.sty {
|
||||
ty::Uint(_) => fx.bcx.ins().$op_u(x_lane, y_lane),
|
||||
ty::Int(_) => fx.bcx.ins().$op_s(x_lane, y_lane),
|
||||
ty::Float(_) => fx.bcx.ins().$op_f(x_lane, y_lane),
|
||||
_ => unreachable!("{:?}", lane_layout.ty),
|
||||
};
|
||||
CValue::by_val(res_lane, ret_lane_layout)
|
||||
},
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! simd_flt_binop {
|
||||
($fx:expr, $intrinsic:expr, $op:ident($x:ident, $y:ident) -> $ret:ident) => {
|
||||
simd_for_each_lane($fx, $intrinsic, $x, $y, $ret, |fx, lane_layout, ret_lane_layout, x_lane, y_lane| {
|
||||
let res_lane = match lane_layout.ty.sty {
|
||||
ty::Float(_) => fx.bcx.ins().$op(x_lane, y_lane),
|
||||
_ => unreachable!("{:?}", lane_layout.ty),
|
||||
};
|
||||
CValue::by_val(res_lane, ret_lane_layout)
|
||||
});
|
||||
}
|
||||
simd_for_each_lane(
|
||||
$fx,
|
||||
$intrinsic,
|
||||
$x,
|
||||
$y,
|
||||
$ret,
|
||||
|fx, lane_layout, ret_lane_layout, x_lane, y_lane| {
|
||||
let res_lane = match lane_layout.ty.sty {
|
||||
ty::Float(_) => fx.bcx.ins().$op(x_lane, y_lane),
|
||||
_ => unreachable!("{:?}", lane_layout.ty),
|
||||
};
|
||||
CValue::by_val(res_lane, ret_lane_layout)
|
||||
},
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
pub fn codegen_intrinsic_call<'tcx>(
|
||||
@ -297,7 +357,10 @@ pub fn codegen_intrinsic_call<'tcx>(
|
||||
trap_unreachable(fx, "[corruption] Called intrinsic::unreachable.");
|
||||
}
|
||||
"transmute" => {
|
||||
trap_unreachable(fx, "[corruption] Called intrinsic::transmute with uninhabited argument.");
|
||||
trap_unreachable(
|
||||
fx,
|
||||
"[corruption] Called intrinsic::transmute with uninhabited argument.",
|
||||
);
|
||||
}
|
||||
_ => unimplemented!("unsupported instrinsic {}", intrinsic),
|
||||
}
|
||||
|
39
src/lib.rs
39
src/lib.rs
@ -71,8 +71,8 @@ mod prelude {
|
||||
};
|
||||
pub use rustc::ty::layout::{self, Abi, LayoutOf, Scalar, Size, TyLayout, VariantIdx};
|
||||
pub use rustc::ty::{
|
||||
self, FnSig, Instance, InstanceDef, ParamEnv, PolyFnSig, Ty, TyCtxt,
|
||||
TypeAndMut, TypeFoldable,
|
||||
self, FnSig, Instance, InstanceDef, ParamEnv, PolyFnSig, Ty, TyCtxt, TypeAndMut,
|
||||
TypeFoldable,
|
||||
};
|
||||
pub use rustc_data_structures::{
|
||||
fx::{FxHashMap, FxHashSet},
|
||||
@ -102,7 +102,7 @@ mod prelude {
|
||||
pub use crate::debuginfo::{DebugContext, FunctionDebugContext};
|
||||
pub use crate::trap::*;
|
||||
pub use crate::unimpl::{unimpl, with_unimpl_span};
|
||||
pub use crate::value_and_place::{CValue, CPlace, CPlaceInner};
|
||||
pub use crate::value_and_place::{CPlace, CPlaceInner, CValue};
|
||||
pub use crate::{Caches, CodegenCx};
|
||||
|
||||
pub struct PrintOnPanic<F: Fn() -> String>(pub F);
|
||||
@ -175,14 +175,18 @@ fn provide(&self, providers: &mut Providers) {
|
||||
if tcx.sess.opts.actually_rustdoc {
|
||||
// rustdoc needs to be able to document functions that use all the features, so
|
||||
// whitelist them all
|
||||
tcx.arena.alloc(target_features_whitelist::all_known_features()
|
||||
.map(|(a, b)| (a.to_string(), b))
|
||||
.collect())
|
||||
tcx.arena.alloc(
|
||||
target_features_whitelist::all_known_features()
|
||||
.map(|(a, b)| (a.to_string(), b))
|
||||
.collect(),
|
||||
)
|
||||
} else {
|
||||
tcx.arena.alloc(target_features_whitelist::target_feature_whitelist(tcx.sess)
|
||||
.iter()
|
||||
.map(|&(a, b)| (a.to_string(), b))
|
||||
.collect())
|
||||
tcx.arena.alloc(
|
||||
target_features_whitelist::target_feature_whitelist(tcx.sess)
|
||||
.iter()
|
||||
.map(|&(a, b)| (a.to_string(), b))
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -252,11 +256,16 @@ fn build_isa(sess: &Session, enable_pic: bool) -> Box<dyn isa::TargetIsa + 'stat
|
||||
flags_builder.set("is_pic", "false").unwrap();
|
||||
}
|
||||
flags_builder.set("probestack_enabled", "false").unwrap(); // __cranelift_probestack is not provided
|
||||
flags_builder.set("enable_verifier", if cfg!(debug_assertions) {
|
||||
"true"
|
||||
} else {
|
||||
"false"
|
||||
}).unwrap();
|
||||
flags_builder
|
||||
.set(
|
||||
"enable_verifier",
|
||||
if cfg!(debug_assertions) {
|
||||
"true"
|
||||
} else {
|
||||
"false"
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// FIXME(CraneStation/cranelift#732) fix LICM in presence of jump tables
|
||||
//flags_builder.set("opt_level", "best").unwrap();
|
||||
|
@ -1,4 +1,4 @@
|
||||
use rustc::mir::mono::{MonoItem, Linkage as RLinkage, Visibility};
|
||||
use rustc::mir::mono::{Linkage as RLinkage, MonoItem, Visibility};
|
||||
|
||||
use crate::prelude::*;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::prelude::*;
|
||||
use crate::intrinsics::*;
|
||||
use crate::prelude::*;
|
||||
|
||||
use rustc::ty::subst::SubstsRef;
|
||||
|
||||
|
@ -2,10 +2,7 @@
|
||||
|
||||
/// Create the `main` function which will initialize the rust runtime and call
|
||||
/// users main function.
|
||||
pub fn maybe_create_entry_wrapper(
|
||||
tcx: TyCtxt<'_>,
|
||||
module: &mut Module<impl Backend + 'static>,
|
||||
) {
|
||||
pub fn maybe_create_entry_wrapper(tcx: TyCtxt<'_>, module: &mut Module<impl Backend + 'static>) {
|
||||
use rustc::middle::lang_items::StartFnLangItem;
|
||||
use rustc::session::config::EntryFnType;
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
use std::fs::File;
|
||||
use std::path::Path;
|
||||
|
||||
use rustc::middle::cstore::{EncodedMetadata, MetadataLoader};
|
||||
use rustc::session::config;
|
||||
use rustc::ty::TyCtxt;
|
||||
use rustc::middle::cstore::{EncodedMetadata, MetadataLoader};
|
||||
use rustc_codegen_ssa::METADATA_FILENAME;
|
||||
use rustc_data_structures::owning_ref::{self, OwningRef};
|
||||
use rustc_data_structures::rustc_erase_owner;
|
||||
@ -41,40 +41,44 @@ fn get_dylib_metadata(
|
||||
use object::Object;
|
||||
let file = std::fs::read(path).map_err(|e| format!("read:{:?}", e))?;
|
||||
let file = object::File::parse(&file).map_err(|e| format!("parse: {:?}", e))?;
|
||||
let buf = file.section_data_by_name(".rustc").ok_or("no .rustc section")?.into_owned();
|
||||
let buf = file
|
||||
.section_data_by_name(".rustc")
|
||||
.ok_or("no .rustc section")?
|
||||
.into_owned();
|
||||
let buf: OwningRef<Vec<u8>, [u8]> = OwningRef::new(buf).into();
|
||||
Ok(rustc_erase_owner!(buf.map_owner_box()))
|
||||
}
|
||||
}
|
||||
|
||||
// Adapted from https://github.com/rust-lang/rust/blob/da573206f87b5510de4b0ee1a9c044127e409bd3/src/librustc_codegen_llvm/base.rs#L47-L112
|
||||
pub fn write_metadata(
|
||||
tcx: TyCtxt<'_>,
|
||||
artifact: &mut faerie::Artifact
|
||||
) -> EncodedMetadata {
|
||||
use std::io::Write;
|
||||
use flate2::Compression;
|
||||
pub fn write_metadata(tcx: TyCtxt<'_>, artifact: &mut faerie::Artifact) -> EncodedMetadata {
|
||||
use flate2::write::DeflateEncoder;
|
||||
use flate2::Compression;
|
||||
use std::io::Write;
|
||||
|
||||
#[derive(PartialEq, Eq, PartialOrd, Ord)]
|
||||
enum MetadataKind {
|
||||
None,
|
||||
Uncompressed,
|
||||
Compressed
|
||||
Compressed,
|
||||
}
|
||||
|
||||
let kind = tcx.sess.crate_types.borrow().iter().map(|ty| {
|
||||
match *ty {
|
||||
config::CrateType::Executable |
|
||||
config::CrateType::Staticlib |
|
||||
config::CrateType::Cdylib => MetadataKind::None,
|
||||
let kind = tcx
|
||||
.sess
|
||||
.crate_types
|
||||
.borrow()
|
||||
.iter()
|
||||
.map(|ty| match *ty {
|
||||
config::CrateType::Executable
|
||||
| config::CrateType::Staticlib
|
||||
| config::CrateType::Cdylib => MetadataKind::None,
|
||||
|
||||
config::CrateType::Rlib => MetadataKind::Uncompressed,
|
||||
|
||||
config::CrateType::Dylib |
|
||||
config::CrateType::ProcMacro => MetadataKind::Compressed,
|
||||
}
|
||||
}).max().unwrap_or(MetadataKind::None);
|
||||
config::CrateType::Dylib | config::CrateType::ProcMacro => MetadataKind::Compressed,
|
||||
})
|
||||
.max()
|
||||
.unwrap_or(MetadataKind::None);
|
||||
|
||||
if kind == MetadataKind::None {
|
||||
return EncodedMetadata::new();
|
||||
@ -88,19 +92,27 @@ enum MetadataKind {
|
||||
assert!(kind == MetadataKind::Compressed);
|
||||
let mut compressed = tcx.metadata_encoding_version();
|
||||
DeflateEncoder::new(&mut compressed, Compression::fast())
|
||||
.write_all(&metadata.raw_data).unwrap();
|
||||
.write_all(&metadata.raw_data)
|
||||
.unwrap();
|
||||
|
||||
artifact.declare(".rustc", faerie::Decl::section(faerie::SectionKind::Data)).unwrap();
|
||||
artifact.define_with_symbols(".rustc", compressed, {
|
||||
let mut map = std::collections::BTreeMap::new();
|
||||
// FIXME implement faerie elf backend section custom symbols
|
||||
// For MachO this is necessary to prevent the linker from throwing away the .rustc section,
|
||||
// but for ELF it isn't.
|
||||
if tcx.sess.target.target.options.is_like_osx {
|
||||
map.insert(rustc::middle::exported_symbols::metadata_symbol_name(tcx), 0);
|
||||
}
|
||||
map
|
||||
}).unwrap();
|
||||
artifact
|
||||
.declare(".rustc", faerie::Decl::section(faerie::SectionKind::Data))
|
||||
.unwrap();
|
||||
artifact
|
||||
.define_with_symbols(".rustc", compressed, {
|
||||
let mut map = std::collections::BTreeMap::new();
|
||||
// FIXME implement faerie elf backend section custom symbols
|
||||
// For MachO this is necessary to prevent the linker from throwing away the .rustc section,
|
||||
// but for ELF it isn't.
|
||||
if tcx.sess.target.target.options.is_like_osx {
|
||||
map.insert(
|
||||
rustc::middle::exported_symbols::metadata_symbol_name(tcx),
|
||||
0,
|
||||
);
|
||||
}
|
||||
map
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
metadata
|
||||
}
|
||||
|
98
src/num.rs
98
src/num.rs
@ -5,11 +5,35 @@ pub fn bin_op_to_intcc(bin_op: BinOp, signed: bool) -> Option<IntCC> {
|
||||
use IntCC::*;
|
||||
Some(match bin_op {
|
||||
Eq => Equal,
|
||||
Lt => if signed { SignedLessThan } else { UnsignedLessThan},
|
||||
Le => if signed { SignedLessThanOrEqual } else { UnsignedLessThanOrEqual},
|
||||
Lt => {
|
||||
if signed {
|
||||
SignedLessThan
|
||||
} else {
|
||||
UnsignedLessThan
|
||||
}
|
||||
}
|
||||
Le => {
|
||||
if signed {
|
||||
SignedLessThanOrEqual
|
||||
} else {
|
||||
UnsignedLessThanOrEqual
|
||||
}
|
||||
}
|
||||
Ne => NotEqual,
|
||||
Ge => if signed { SignedGreaterThanOrEqual } else { UnsignedGreaterThanOrEqual },
|
||||
Gt => if signed { SignedGreaterThan } else { UnsignedGreaterThan },
|
||||
Ge => {
|
||||
if signed {
|
||||
SignedGreaterThanOrEqual
|
||||
} else {
|
||||
UnsignedGreaterThanOrEqual
|
||||
}
|
||||
}
|
||||
Gt => {
|
||||
if signed {
|
||||
SignedGreaterThan
|
||||
} else {
|
||||
UnsignedGreaterThan
|
||||
}
|
||||
}
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
@ -41,9 +65,9 @@ pub fn codegen_binop<'tcx>(
|
||||
let lhs = in_lhs.load_scalar(fx);
|
||||
let rhs = in_rhs.load_scalar(fx);
|
||||
|
||||
let (lhs, rhs) = if
|
||||
(bin_op == BinOp::Eq || bin_op == BinOp::Ne)
|
||||
&& (in_lhs.layout().ty.sty == fx.tcx.types.i8.sty || in_lhs.layout().ty.sty == fx.tcx.types.i16.sty)
|
||||
let (lhs, rhs) = if (bin_op == BinOp::Eq || bin_op == BinOp::Ne)
|
||||
&& (in_lhs.layout().ty.sty == fx.tcx.types.i8.sty
|
||||
|| in_lhs.layout().ty.sty == fx.tcx.types.i16.sty)
|
||||
{
|
||||
// FIXME(CraneStation/cranelift#896) icmp_imm.i8/i16 with eq/ne for signed ints is implemented wrong.
|
||||
(
|
||||
@ -64,14 +88,15 @@ pub fn codegen_binop<'tcx>(
|
||||
|
||||
match in_lhs.layout().ty.sty {
|
||||
ty::Bool => crate::num::trans_bool_binop(fx, bin_op, in_lhs, in_rhs),
|
||||
ty::Uint(_) | ty::Int(_)=> {
|
||||
crate::num::trans_int_binop(fx, bin_op, in_lhs, in_rhs)
|
||||
}
|
||||
ty::Uint(_) | ty::Int(_) => crate::num::trans_int_binop(fx, bin_op, in_lhs, in_rhs),
|
||||
ty::Float(_) => crate::num::trans_float_binop(fx, bin_op, in_lhs, in_rhs),
|
||||
ty::RawPtr(..) | ty::FnPtr(..) => {
|
||||
crate::num::trans_ptr_binop(fx, bin_op, in_lhs, in_rhs)
|
||||
}
|
||||
_ => unimplemented!("{:?}({:?}, {:?})", bin_op, in_lhs.layout().ty, in_rhs.layout().ty),
|
||||
ty::RawPtr(..) | ty::FnPtr(..) => crate::num::trans_ptr_binop(fx, bin_op, in_lhs, in_rhs),
|
||||
_ => unimplemented!(
|
||||
"{:?}({:?}, {:?})",
|
||||
bin_op,
|
||||
in_lhs.layout().ty,
|
||||
in_rhs.layout().ty
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
@ -124,8 +149,20 @@ pub fn trans_int_binop<'tcx>(
|
||||
BinOp::Add => b.iadd(lhs, rhs),
|
||||
BinOp::Sub => b.isub(lhs, rhs),
|
||||
BinOp::Mul => b.imul(lhs, rhs),
|
||||
BinOp::Div => if signed { b.sdiv(lhs, rhs) } else { b.udiv(lhs, rhs) },
|
||||
BinOp::Rem => if signed { b.srem(lhs, rhs) } else { b.urem(lhs, rhs) },
|
||||
BinOp::Div => {
|
||||
if signed {
|
||||
b.sdiv(lhs, rhs)
|
||||
} else {
|
||||
b.udiv(lhs, rhs)
|
||||
}
|
||||
}
|
||||
BinOp::Rem => {
|
||||
if signed {
|
||||
b.srem(lhs, rhs)
|
||||
} else {
|
||||
b.urem(lhs, rhs)
|
||||
}
|
||||
}
|
||||
BinOp::BitXor => b.bxor(lhs, rhs),
|
||||
BinOp::BitAnd => b.band(lhs, rhs),
|
||||
BinOp::BitOr => b.bor(lhs, rhs),
|
||||
@ -144,7 +181,12 @@ pub fn trans_int_binop<'tcx>(
|
||||
}
|
||||
}
|
||||
// Compare binops handles by `codegen_binop`.
|
||||
_ => unreachable!("{:?}({:?}, {:?})", bin_op, in_lhs.layout().ty, in_rhs.layout().ty),
|
||||
_ => unreachable!(
|
||||
"{:?}({:?}, {:?})",
|
||||
bin_op,
|
||||
in_lhs.layout().ty,
|
||||
in_rhs.layout().ty
|
||||
),
|
||||
};
|
||||
|
||||
CValue::by_val(val, in_lhs.layout())
|
||||
@ -239,7 +281,11 @@ pub fn trans_checked_int_binop<'tcx>(
|
||||
};
|
||||
|
||||
let has_overflow = fx.bcx.ins().bint(types::I8, has_overflow);
|
||||
let out_place = CPlace::new_stack_slot(fx, fx.tcx.mk_tup([in_lhs.layout().ty, fx.tcx.types.bool].iter()));
|
||||
let out_place = CPlace::new_stack_slot(
|
||||
fx,
|
||||
fx.tcx
|
||||
.mk_tup([in_lhs.layout().ty, fx.tcx.types.bool].iter()),
|
||||
);
|
||||
let out_layout = out_place.layout();
|
||||
out_place.write_cvalue(fx, CValue::by_val_pair(res, has_overflow, out_layout));
|
||||
|
||||
@ -341,14 +387,24 @@ pub fn trans_ptr_binop<'tcx>(
|
||||
BinOp::Lt | BinOp::Le | BinOp::Ge | BinOp::Gt => {
|
||||
let ptr_eq = fx.bcx.ins().icmp(IntCC::Equal, lhs_ptr, rhs_ptr);
|
||||
|
||||
let ptr_cmp = fx.bcx.ins().icmp(bin_op_to_intcc(bin_op, false).unwrap(), lhs_ptr, rhs_ptr);
|
||||
let extra_cmp = fx.bcx.ins().icmp(bin_op_to_intcc(bin_op, false).unwrap(), lhs_extra, rhs_extra);
|
||||
let ptr_cmp =
|
||||
fx.bcx
|
||||
.ins()
|
||||
.icmp(bin_op_to_intcc(bin_op, false).unwrap(), lhs_ptr, rhs_ptr);
|
||||
let extra_cmp = fx.bcx.ins().icmp(
|
||||
bin_op_to_intcc(bin_op, false).unwrap(),
|
||||
lhs_extra,
|
||||
rhs_extra,
|
||||
);
|
||||
|
||||
fx.bcx.ins().select(ptr_eq, extra_cmp, ptr_cmp)
|
||||
}
|
||||
_ => panic!("bin_op {:?} on ptr", bin_op),
|
||||
};
|
||||
|
||||
CValue::by_val(fx.bcx.ins().bint(types::I8, res), fx.layout_of(fx.tcx.types.bool))
|
||||
CValue::by_val(
|
||||
fx.bcx.ins().bint(types::I8, res),
|
||||
fx.layout_of(fx.tcx.types.bool),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -4,11 +4,7 @@
|
||||
|
||||
use cranelift::codegen::{
|
||||
entity::SecondaryMap,
|
||||
ir::{
|
||||
self,
|
||||
entities::AnyEntity,
|
||||
function::DisplayFunctionAnnotations,
|
||||
},
|
||||
ir::{self, entities::AnyEntity, function::DisplayFunctionAnnotations},
|
||||
write::{FuncWriter, PlainWriter},
|
||||
ValueLabelsRanges,
|
||||
};
|
||||
@ -82,7 +78,13 @@ pub fn new<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Self {
|
||||
global_comments: vec![
|
||||
format!("symbol {}", tcx.symbol_name(instance).as_str()),
|
||||
format!("instance {:?}", instance),
|
||||
format!("sig {:?}", tcx.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), &instance.fn_sig(tcx))),
|
||||
format!(
|
||||
"sig {:?}",
|
||||
tcx.normalize_erasing_late_bound_regions(
|
||||
ParamEnv::reveal_all(),
|
||||
&instance.fn_sig(tcx)
|
||||
)
|
||||
),
|
||||
String::new(),
|
||||
],
|
||||
entity_comments: HashMap::new(),
|
||||
@ -218,7 +220,9 @@ pub fn write_clif_file<'tcx>(
|
||||
&mut clif,
|
||||
&func,
|
||||
&DisplayFunctionAnnotations {
|
||||
isa: Some(&*crate::build_isa(tcx.sess, true /* PIC doesn't matter here */)),
|
||||
isa: Some(&*crate::build_isa(
|
||||
tcx.sess, true, /* PIC doesn't matter here */
|
||||
)),
|
||||
value_ranges,
|
||||
},
|
||||
)
|
||||
|
@ -115,8 +115,10 @@
|
||||
///
|
||||
/// IMPORTANT: If you're adding another whitelist to the above lists, make sure to add it to this
|
||||
/// iterator!
|
||||
pub fn all_known_features() -> impl Iterator<Item=(&'static str, Option<Symbol>)> {
|
||||
ARM_WHITELIST.iter().cloned()
|
||||
pub fn all_known_features() -> impl Iterator<Item = (&'static str, Option<Symbol>)> {
|
||||
ARM_WHITELIST
|
||||
.iter()
|
||||
.cloned()
|
||||
.chain(AARCH64_WHITELIST.iter().cloned())
|
||||
.chain(X86_WHITELIST.iter().cloned())
|
||||
.chain(HEXAGON_WHITELIST.iter().cloned())
|
||||
@ -125,9 +127,7 @@ pub fn all_known_features() -> impl Iterator<Item=(&'static str, Option<Symbol>)
|
||||
.chain(WASM_WHITELIST.iter().cloned())
|
||||
}
|
||||
|
||||
pub fn target_feature_whitelist(sess: &Session)
|
||||
-> &'static [(&'static str, Option<Symbol>)]
|
||||
{
|
||||
pub fn target_feature_whitelist(sess: &Session) -> &'static [(&'static str, Option<Symbol>)] {
|
||||
match &*sess.target.target.arch {
|
||||
"arm" => ARM_WHITELIST,
|
||||
"aarch64" => AARCH64_WHITELIST,
|
||||
|
60
src/trap.rs
60
src/trap.rs
@ -1,13 +1,21 @@
|
||||
use crate::prelude::*;
|
||||
|
||||
fn codegen_print(fx: &mut FunctionCx<'_, '_, impl cranelift_module::Backend>, msg: &str) {
|
||||
let puts = fx.module.declare_function("puts", Linkage::Import, &Signature {
|
||||
call_conv: CallConv::SystemV,
|
||||
params: vec![AbiParam::new(pointer_ty(fx.tcx))],
|
||||
returns: vec![],
|
||||
}).unwrap();
|
||||
let puts = fx
|
||||
.module
|
||||
.declare_function(
|
||||
"puts",
|
||||
Linkage::Import,
|
||||
&Signature {
|
||||
call_conv: CallConv::SystemV,
|
||||
params: vec![AbiParam::new(pointer_ty(fx.tcx))],
|
||||
returns: vec![],
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
let puts = fx.module.declare_func_in_func(puts, &mut fx.bcx.func);
|
||||
#[cfg(debug_assertions)] {
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
fx.add_entity_comment(puts, "puts");
|
||||
}
|
||||
|
||||
@ -15,13 +23,22 @@ fn codegen_print(fx: &mut FunctionCx<'_, '_, impl cranelift_module::Backend>, ms
|
||||
let real_msg = format!("trap at {:?} ({}): {}\0", fx.instance, symbol_name, msg);
|
||||
let mut data_ctx = DataContext::new();
|
||||
data_ctx.define(real_msg.as_bytes().to_vec().into_boxed_slice());
|
||||
let msg_id = fx.module.declare_data(&(symbol_name.as_str().to_string() + msg), Linkage::Local, false, None).unwrap();
|
||||
let msg_id = fx
|
||||
.module
|
||||
.declare_data(
|
||||
&(symbol_name.as_str().to_string() + msg),
|
||||
Linkage::Local,
|
||||
false,
|
||||
None,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// Ignore DuplicateDefinition error, as the data will be the same
|
||||
let _ = fx.module.define_data(msg_id, &data_ctx);
|
||||
|
||||
let local_msg_id = fx.module.declare_data_in_func(msg_id, fx.bcx.func);
|
||||
#[cfg(debug_assertions)] {
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
fx.add_entity_comment(local_msg_id, msg);
|
||||
}
|
||||
let msg_ptr = fx.bcx.ins().global_value(pointer_ty(fx.tcx), local_msg_id);
|
||||
@ -31,7 +48,10 @@ fn codegen_print(fx: &mut FunctionCx<'_, '_, impl cranelift_module::Backend>, ms
|
||||
/// Use this when `rustc_codegen_llvm` would insert a call to the panic handler.
|
||||
///
|
||||
/// Trap code: user0
|
||||
pub fn trap_panic(fx: &mut FunctionCx<'_, '_, impl cranelift_module::Backend>, msg: impl AsRef<str>) {
|
||||
pub fn trap_panic(
|
||||
fx: &mut FunctionCx<'_, '_, impl cranelift_module::Backend>,
|
||||
msg: impl AsRef<str>,
|
||||
) {
|
||||
codegen_print(fx, msg.as_ref());
|
||||
fx.bcx.ins().trap(TrapCode::User(0));
|
||||
}
|
||||
@ -40,7 +60,10 @@ pub fn trap_panic(fx: &mut FunctionCx<'_, '_, impl cranelift_module::Backend>, m
|
||||
/// so you can **not** add instructions to it afterwards.
|
||||
///
|
||||
/// Trap code: user65535
|
||||
pub fn trap_unreachable(fx: &mut FunctionCx<'_, '_, impl cranelift_module::Backend>, msg: impl AsRef<str>) {
|
||||
pub fn trap_unreachable(
|
||||
fx: &mut FunctionCx<'_, '_, impl cranelift_module::Backend>,
|
||||
msg: impl AsRef<str>,
|
||||
) {
|
||||
codegen_print(fx, msg.as_ref());
|
||||
fx.bcx.ins().trap(TrapCode::User(!0));
|
||||
}
|
||||
@ -50,7 +73,10 @@ pub fn trap_unreachable(fx: &mut FunctionCx<'_, '_, impl cranelift_module::Backe
|
||||
/// to it afterwards.
|
||||
///
|
||||
/// Trap code: user65535
|
||||
pub fn trap_unimplemented(fx: &mut FunctionCx<'_, '_, impl cranelift_module::Backend>, msg: impl AsRef<str>) {
|
||||
pub fn trap_unimplemented(
|
||||
fx: &mut FunctionCx<'_, '_, impl cranelift_module::Backend>,
|
||||
msg: impl AsRef<str>,
|
||||
) {
|
||||
codegen_print(fx, msg.as_ref());
|
||||
let true_ = fx.bcx.ins().iconst(types::I32, 1);
|
||||
fx.bcx.ins().trapnz(true_, TrapCode::User(!0));
|
||||
@ -59,7 +85,11 @@ pub fn trap_unimplemented(fx: &mut FunctionCx<'_, '_, impl cranelift_module::Bac
|
||||
/// Like `trap_unreachable` but returns a fake value of the specified type.
|
||||
///
|
||||
/// Trap code: user65535
|
||||
pub fn trap_unreachable_ret_value<'tcx>(fx: &mut FunctionCx<'_, 'tcx, impl cranelift_module::Backend>, dest_layout: TyLayout<'tcx>, msg: impl AsRef<str>) -> CValue<'tcx> {
|
||||
pub fn trap_unreachable_ret_value<'tcx>(
|
||||
fx: &mut FunctionCx<'_, 'tcx, impl cranelift_module::Backend>,
|
||||
dest_layout: TyLayout<'tcx>,
|
||||
msg: impl AsRef<str>,
|
||||
) -> CValue<'tcx> {
|
||||
trap_unimplemented(fx, msg);
|
||||
let zero = fx.bcx.ins().iconst(fx.pointer_type, 0);
|
||||
CValue::by_ref(zero, dest_layout)
|
||||
@ -68,7 +98,11 @@ pub fn trap_unreachable_ret_value<'tcx>(fx: &mut FunctionCx<'_, 'tcx, impl crane
|
||||
/// Like `trap_unreachable` but returns a fake place for the specified type.
|
||||
///
|
||||
/// Trap code: user65535
|
||||
pub fn trap_unreachable_ret_place<'tcx>(fx: &mut FunctionCx<'_, 'tcx, impl cranelift_module::Backend>, dest_layout: TyLayout<'tcx>, msg: impl AsRef<str>) -> CPlace<'tcx> {
|
||||
pub fn trap_unreachable_ret_place<'tcx>(
|
||||
fx: &mut FunctionCx<'_, 'tcx, impl cranelift_module::Backend>,
|
||||
dest_layout: TyLayout<'tcx>,
|
||||
msg: impl AsRef<str>,
|
||||
) -> CPlace<'tcx> {
|
||||
trap_unimplemented(fx, msg);
|
||||
let zero = fx.bcx.ins().iconst(fx.pointer_type, 0);
|
||||
CPlace::for_addr(zero, dest_layout)
|
||||
|
@ -15,15 +15,13 @@ pub fn unsized_info<'tcx>(
|
||||
old_info: Option<Value>,
|
||||
) -> Value {
|
||||
let (source, target) =
|
||||
fx.tcx.struct_lockstep_tails_erasing_lifetimes(source, target, ParamEnv::reveal_all());
|
||||
fx.tcx
|
||||
.struct_lockstep_tails_erasing_lifetimes(source, target, ParamEnv::reveal_all());
|
||||
match (&source.sty, &target.sty) {
|
||||
(&ty::Array(_, len), &ty::Slice(_)) => fx
|
||||
.bcx
|
||||
.ins()
|
||||
.iconst(
|
||||
fx.pointer_type,
|
||||
len.eval_usize(fx.tcx, ParamEnv::reveal_all()) as i64,
|
||||
),
|
||||
(&ty::Array(_, len), &ty::Slice(_)) => fx.bcx.ins().iconst(
|
||||
fx.pointer_type,
|
||||
len.eval_usize(fx.tcx, ParamEnv::reveal_all()) as i64,
|
||||
),
|
||||
(&ty::Dynamic(..), &ty::Dynamic(..)) => {
|
||||
// For now, upcasts are limited to changes in marker
|
||||
// traits, and hence never actually require an actual
|
||||
|
@ -19,7 +19,10 @@ fn codegen_field<'tcx>(
|
||||
}
|
||||
|
||||
fn scalar_pair_calculate_b_offset(tcx: TyCtxt<'_>, a_scalar: &Scalar, b_scalar: &Scalar) -> i32 {
|
||||
let b_offset = a_scalar.value.size(&tcx).align_to(b_scalar.value.align(&tcx).abi);
|
||||
let b_offset = a_scalar
|
||||
.value
|
||||
.size(&tcx)
|
||||
.align_to(b_scalar.value.align(&tcx).abi);
|
||||
b_offset.bytes().try_into().unwrap()
|
||||
}
|
||||
|
||||
@ -88,7 +91,10 @@ pub fn load_scalar<'a>(self, fx: &mut FunctionCx<'_, 'tcx, impl Backend>) -> Val
|
||||
}
|
||||
|
||||
/// Load a value pair with layout.abi of scalar pair
|
||||
pub fn load_scalar_pair<'a>(self, fx: &mut FunctionCx<'_, 'tcx, impl Backend>) -> (Value, Value) {
|
||||
pub fn load_scalar_pair<'a>(
|
||||
self,
|
||||
fx: &mut FunctionCx<'_, 'tcx, impl Backend>,
|
||||
) -> (Value, Value) {
|
||||
let layout = self.1;
|
||||
match self.0 {
|
||||
CValueInner::ByRef(addr) => {
|
||||
@ -100,12 +106,7 @@ pub fn load_scalar_pair<'a>(self, fx: &mut FunctionCx<'_, 'tcx, impl Backend>) -
|
||||
let clif_ty1 = scalar_to_clif_type(fx.tcx, a_scalar.clone());
|
||||
let clif_ty2 = scalar_to_clif_type(fx.tcx, b_scalar.clone());
|
||||
let val1 = fx.bcx.ins().load(clif_ty1, MemFlags::new(), addr, 0);
|
||||
let val2 = fx.bcx.ins().load(
|
||||
clif_ty2,
|
||||
MemFlags::new(),
|
||||
addr,
|
||||
b_offset,
|
||||
);
|
||||
let val2 = fx.bcx.ins().load(clif_ty2, MemFlags::new(), addr, b_offset);
|
||||
(val1, val2)
|
||||
}
|
||||
CValueInner::ByVal(_) => bug!("Please use load_scalar for ByVal"),
|
||||
@ -144,20 +145,29 @@ pub fn const_val<'a>(
|
||||
let val = match ty.sty {
|
||||
ty::TyKind::Uint(UintTy::U128) | ty::TyKind::Int(IntTy::I128) => {
|
||||
let lsb = fx.bcx.ins().iconst(types::I64, const_val as u64 as i64);
|
||||
let msb = fx.bcx.ins().iconst(types::I64, (const_val >> 64) as u64 as i64);
|
||||
let msb = fx
|
||||
.bcx
|
||||
.ins()
|
||||
.iconst(types::I64, (const_val >> 64) as u64 as i64);
|
||||
fx.bcx.ins().iconcat(lsb, msb)
|
||||
}
|
||||
ty::TyKind::Bool => {
|
||||
assert!(const_val == 0 || const_val == 1, "Invalid bool 0x{:032X}", const_val);
|
||||
assert!(
|
||||
const_val == 0 || const_val == 1,
|
||||
"Invalid bool 0x{:032X}",
|
||||
const_val
|
||||
);
|
||||
fx.bcx.ins().iconst(types::I8, const_val as i64)
|
||||
}
|
||||
ty::TyKind::Uint(_) | ty::TyKind::Ref(..) | ty::TyKind::RawPtr(.. )=> {
|
||||
fx.bcx.ins().iconst(clif_ty, u64::try_from(const_val).expect("uint") as i64)
|
||||
}
|
||||
ty::TyKind::Int(_) => {
|
||||
fx.bcx.ins().iconst(clif_ty, const_val as i128 as i64)
|
||||
}
|
||||
_ => panic!("CValue::const_val for non bool/integer/pointer type {:?} is not allowed", ty),
|
||||
ty::TyKind::Uint(_) | ty::TyKind::Ref(..) | ty::TyKind::RawPtr(..) => fx
|
||||
.bcx
|
||||
.ins()
|
||||
.iconst(clif_ty, u64::try_from(const_val).expect("uint") as i64),
|
||||
ty::TyKind::Int(_) => fx.bcx.ins().iconst(clif_ty, const_val as i128 as i64),
|
||||
_ => panic!(
|
||||
"CValue::const_val for non bool/integer/pointer type {:?} is not allowed",
|
||||
ty
|
||||
),
|
||||
};
|
||||
|
||||
CValue::by_val(val, layout)
|
||||
@ -193,9 +203,9 @@ pub fn inner(&self) -> &CPlaceInner {
|
||||
}
|
||||
|
||||
pub fn no_place(layout: TyLayout<'tcx>) -> CPlace<'tcx> {
|
||||
CPlace{
|
||||
CPlace {
|
||||
inner: CPlaceInner::NoPlace,
|
||||
layout
|
||||
layout,
|
||||
}
|
||||
}
|
||||
|
||||
@ -299,7 +309,11 @@ pub fn write_cvalue(self, fx: &mut FunctionCx<'_, 'tcx, impl Backend>, from: CVa
|
||||
let from_ty = from.layout().ty;
|
||||
let to_ty = self.layout().ty;
|
||||
|
||||
fn assert_assignable<'tcx>(fx: &FunctionCx<'_, 'tcx, impl Backend>, from_ty: Ty<'tcx>, to_ty: Ty<'tcx>) {
|
||||
fn assert_assignable<'tcx>(
|
||||
fx: &FunctionCx<'_, 'tcx, impl Backend>,
|
||||
from_ty: Ty<'tcx>,
|
||||
to_ty: Ty<'tcx>,
|
||||
) {
|
||||
match (&from_ty.sty, &to_ty.sty) {
|
||||
(ty::Ref(_, t, MutImmutable), ty::Ref(_, u, MutImmutable))
|
||||
| (ty::Ref(_, t, MutMutable), ty::Ref(_, u, MutImmutable))
|
||||
@ -308,9 +322,10 @@ fn assert_assignable<'tcx>(fx: &FunctionCx<'_, 'tcx, impl Backend>, from_ty: Ty<
|
||||
// &mut T -> &T is allowed
|
||||
// &'a T -> &'b T is allowed
|
||||
}
|
||||
(ty::Ref(_, _, MutImmutable), ty::Ref(_, _, MutMutable)) => {
|
||||
panic!("Cant assign value of type {} to place of type {}", from_ty, to_ty)
|
||||
}
|
||||
(ty::Ref(_, _, MutImmutable), ty::Ref(_, _, MutMutable)) => panic!(
|
||||
"Cant assign value of type {} to place of type {}",
|
||||
from_ty, to_ty
|
||||
),
|
||||
(ty::FnPtr(_), ty::FnPtr(_)) => {
|
||||
let from_sig = fx.tcx.normalize_erasing_late_bound_regions(
|
||||
ParamEnv::reveal_all(),
|
||||
@ -328,14 +343,12 @@ fn assert_assignable<'tcx>(fx: &FunctionCx<'_, 'tcx, impl Backend>, from_ty: Ty<
|
||||
// fn(&T) -> for<'l> fn(&'l T) is allowed
|
||||
}
|
||||
(ty::Dynamic(from_traits, _), ty::Dynamic(to_traits, _)) => {
|
||||
let from_traits = fx.tcx.normalize_erasing_late_bound_regions(
|
||||
ParamEnv::reveal_all(),
|
||||
from_traits,
|
||||
);
|
||||
let to_traits = fx.tcx.normalize_erasing_late_bound_regions(
|
||||
ParamEnv::reveal_all(),
|
||||
to_traits,
|
||||
);
|
||||
let from_traits = fx
|
||||
.tcx
|
||||
.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), from_traits);
|
||||
let to_traits = fx
|
||||
.tcx
|
||||
.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), to_traits);
|
||||
assert_eq!(
|
||||
from_traits, to_traits,
|
||||
"Can't write trait object of incompatible traits {:?} to place with traits {:?}\n\n{:#?}",
|
||||
@ -382,24 +395,17 @@ fn assert_assignable<'tcx>(fx: &FunctionCx<'_, 'tcx, impl Backend>, from_ty: Ty<
|
||||
CValueInner::ByVal(val) => {
|
||||
fx.bcx.ins().store(MemFlags::new(), val, addr, 0);
|
||||
}
|
||||
CValueInner::ByValPair(value, extra) => {
|
||||
match dst_layout.abi {
|
||||
Abi::ScalarPair(ref a_scalar, ref b_scalar) => {
|
||||
let b_offset = scalar_pair_calculate_b_offset(fx.tcx, a_scalar, b_scalar);
|
||||
fx.bcx.ins().store(MemFlags::new(), value, addr, 0);
|
||||
fx.bcx.ins().store(
|
||||
MemFlags::new(),
|
||||
extra,
|
||||
addr,
|
||||
b_offset,
|
||||
);
|
||||
}
|
||||
_ => bug!(
|
||||
"Non ScalarPair abi {:?} for ByValPair CValue",
|
||||
dst_layout.abi
|
||||
),
|
||||
CValueInner::ByValPair(value, extra) => match dst_layout.abi {
|
||||
Abi::ScalarPair(ref a_scalar, ref b_scalar) => {
|
||||
let b_offset = scalar_pair_calculate_b_offset(fx.tcx, a_scalar, b_scalar);
|
||||
fx.bcx.ins().store(MemFlags::new(), value, addr, 0);
|
||||
fx.bcx.ins().store(MemFlags::new(), extra, addr, b_offset);
|
||||
}
|
||||
}
|
||||
_ => bug!(
|
||||
"Non ScalarPair abi {:?} for ByValPair CValue",
|
||||
dst_layout.abi
|
||||
),
|
||||
},
|
||||
CValueInner::ByRef(from_addr) => {
|
||||
let src_layout = from.1;
|
||||
let size = dst_layout.size.bytes();
|
||||
@ -468,7 +474,11 @@ pub fn write_place_ref(self, fx: &mut FunctionCx<'_, 'tcx, impl Backend>, dest:
|
||||
dest.write_cvalue(fx, ptr);
|
||||
} else {
|
||||
let (value, extra) = self.to_addr_maybe_unsized(fx);
|
||||
let ptr = CValue::by_val_pair(value, extra.expect("unsized type without metadata"), dest.layout());
|
||||
let ptr = CValue::by_val_pair(
|
||||
value,
|
||||
extra.expect("unsized type without metadata"),
|
||||
dest.layout(),
|
||||
);
|
||||
dest.write_cvalue(fx, ptr);
|
||||
}
|
||||
}
|
||||
|
@ -6,10 +6,7 @@
|
||||
const SIZE_INDEX: usize = 1;
|
||||
const ALIGN_INDEX: usize = 2;
|
||||
|
||||
pub fn drop_fn_of_obj(
|
||||
fx: &mut FunctionCx<'_, '_, impl Backend>,
|
||||
vtable: Value,
|
||||
) -> Value {
|
||||
pub fn drop_fn_of_obj(fx: &mut FunctionCx<'_, '_, impl Backend>, vtable: Value) -> Value {
|
||||
let usize_size = fx.layout_of(fx.tcx.types.usize).size.bytes() as usize;
|
||||
fx.bcx.ins().load(
|
||||
pointer_ty(fx.tcx),
|
||||
@ -19,10 +16,7 @@ pub fn drop_fn_of_obj(
|
||||
)
|
||||
}
|
||||
|
||||
pub fn size_of_obj(
|
||||
fx: &mut FunctionCx<'_, '_, impl Backend>,
|
||||
vtable: Value,
|
||||
) -> Value {
|
||||
pub fn size_of_obj(fx: &mut FunctionCx<'_, '_, impl Backend>, vtable: Value) -> Value {
|
||||
let usize_size = fx.layout_of(fx.tcx.types.usize).size.bytes() as usize;
|
||||
fx.bcx.ins().load(
|
||||
pointer_ty(fx.tcx),
|
||||
@ -32,10 +26,7 @@ pub fn size_of_obj(
|
||||
)
|
||||
}
|
||||
|
||||
pub fn min_align_of_obj(
|
||||
fx: &mut FunctionCx<'_, '_, impl Backend>,
|
||||
vtable: Value,
|
||||
) -> Value {
|
||||
pub fn min_align_of_obj(fx: &mut FunctionCx<'_, '_, impl Backend>, vtable: Value) -> Value {
|
||||
let usize_size = fx.layout_of(fx.tcx.types.usize).size.bytes() as usize;
|
||||
fx.bcx.ins().load(
|
||||
pointer_ty(fx.tcx),
|
||||
@ -86,11 +77,8 @@ fn build_vtable<'tcx>(
|
||||
let tcx = fx.tcx;
|
||||
let usize_size = fx.layout_of(fx.tcx.types.usize).size.bytes() as usize;
|
||||
|
||||
let drop_in_place_fn = import_function(
|
||||
tcx,
|
||||
fx.module,
|
||||
Instance::resolve_drop_in_place(tcx, ty),
|
||||
);
|
||||
let drop_in_place_fn =
|
||||
import_function(tcx, fx.module, Instance::resolve_drop_in_place(tcx, ty));
|
||||
|
||||
let mut components: Vec<_> = vec![Some(drop_in_place_fn), None, None];
|
||||
|
||||
@ -136,7 +124,15 @@ fn build_vtable<'tcx>(
|
||||
&format!("vtable.{:?}.for.{:?}", trait_ref, ty),
|
||||
Linkage::Local,
|
||||
false,
|
||||
Some(fx.tcx.data_layout.pointer_align.pref.bytes().try_into().unwrap())
|
||||
Some(
|
||||
fx.tcx
|
||||
.data_layout
|
||||
.pointer_align
|
||||
.pref
|
||||
.bytes()
|
||||
.try_into()
|
||||
.unwrap(),
|
||||
),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user