Merge commit '09fae60a86b848a2fc0ad219ecc4e438dc1eef86' into sync_cg_clif-2024-03-28

This commit is contained in:
bjorn3 2024-03-28 11:43:35 +00:00
commit 987ed345af
24 changed files with 840 additions and 291 deletions

View File

@ -46,18 +46,18 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "cranelift-bforest"
version = "0.105.2"
version = "0.106.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9515fcc42b6cb5137f76b84c1a6f819782d0cf12473d145d3bc5cd67eedc8bc2"
checksum = "6a535eb1cf5a6003197dc569320c40c1cb2d2f97ef5d5348eebf067f20957381"
dependencies = [
"cranelift-entity",
]
[[package]]
name = "cranelift-codegen"
version = "0.105.2"
version = "0.106.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ad827c6071bfe6d22de1bc331296a29f9ddc506ff926d8415b435ec6a6efce0"
checksum = "11b5066db32cec1492573827183af2142d2d88fe85a83cfc9e73f0f63d3788d4"
dependencies = [
"bumpalo",
"cranelift-bforest",
@ -76,39 +76,39 @@ dependencies = [
[[package]]
name = "cranelift-codegen-meta"
version = "0.105.2"
version = "0.106.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10e6b36237a9ca2ce2fb4cc7741d418a080afa1327402138412ef85d5367bef1"
checksum = "64942e5774308e835fbad4dd25f253105412c90324631910e1ec27963147bddb"
dependencies = [
"cranelift-codegen-shared",
]
[[package]]
name = "cranelift-codegen-shared"
version = "0.105.2"
version = "0.106.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c36bf4bfb86898a94ccfa773a1f86e8a5346b1983ff72059bdd2db4600325251"
checksum = "c39c33db9a86dd6d8d04166a10c53deb477aeea3500eaaefca682e4eda9bb986"
[[package]]
name = "cranelift-control"
version = "0.105.2"
version = "0.106.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7cbf36560e7a6bd1409ca91e7b43b2cc7ed8429f343d7605eadf9046e8fac0d0"
checksum = "4b7fc4937613aea3156a0538800a17bf56f345a5da2e79ae3df58488c93d867f"
dependencies = [
"arbitrary",
]
[[package]]
name = "cranelift-entity"
version = "0.105.2"
version = "0.106.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a71e11061a75b1184c09bea97c026a88f08b59ade96a7bb1f259d4ea0df2e942"
checksum = "f85575e79a153ce1ddbfb7fe1813519b4bfe1eb200cc9c8353b45ad123ae4d36"
[[package]]
name = "cranelift-frontend"
version = "0.105.2"
version = "0.106.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af5d4da63143ee3485c7bcedde0a818727d737d1083484a0ceedb8950c89e495"
checksum = "bbc31d6c0ab2249fe0c21e988256b42f5f401ab2673b4fc40076c82a698bdfb9"
dependencies = [
"cranelift-codegen",
"log",
@ -118,15 +118,15 @@ dependencies = [
[[package]]
name = "cranelift-isle"
version = "0.105.2"
version = "0.106.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "457a9832b089e26f5eea70dcf49bed8ec6edafed630ce7c83161f24d46ab8085"
checksum = "dc14f37e3314c0e4c53779c2f46753bf242efff76ee9473757a1fff3b495ad37"
[[package]]
name = "cranelift-jit"
version = "0.105.2"
version = "0.106.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0af95fe68d5a10919012c8db82b1d59820405b8001c8c6d05f94b08031334fa9"
checksum = "cfdd1942f3233176a68c285380dbc84ff0440246a1bce308611c0a385b56ab18"
dependencies = [
"anyhow",
"cranelift-codegen",
@ -144,9 +144,9 @@ dependencies = [
[[package]]
name = "cranelift-module"
version = "0.105.2"
version = "0.106.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "11b0b201fa10a4014062d4c56c307c8d18fdf9a84cb5279efe6080241f42c7a7"
checksum = "121b2b5a16912554a1b9aace75b9b21eca49f28e33cbfbad4786dd9bc5361a5c"
dependencies = [
"anyhow",
"cranelift-codegen",
@ -155,9 +155,9 @@ dependencies = [
[[package]]
name = "cranelift-native"
version = "0.105.2"
version = "0.106.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b490d579df1ce365e1ea359e24ed86d82289fa785153327c2f6a69a59a731e4"
checksum = "2ea5375f76ab31f9800a23fb2b440810286a6f669a3eb467cdd7ff255ea64268"
dependencies = [
"cranelift-codegen",
"libc",
@ -166,9 +166,9 @@ dependencies = [
[[package]]
name = "cranelift-object"
version = "0.105.2"
version = "0.106.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb7e821ac6db471bcdbd004e5a4fa0d374f1046bd3a2ce278c332e0b0c01ca63"
checksum = "f34e04419ab41661e973d90a73aa7b12771455394dae7a69b101a9b7e7589db7"
dependencies = [
"anyhow",
"cranelift-codegen",
@ -392,9 +392,9 @@ dependencies = [
[[package]]
name = "target-lexicon"
version = "0.12.12"
version = "0.12.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14c39fd04924ca3a864207c66fc2cd7d22d7c016007f9ce846cbb9326331930a"
checksum = "e1fc403891a21bcfb7c37834ba66a547a8f402146eba7265b5a6d88059c9ff2f"
[[package]]
name = "unicode-ident"
@ -410,9 +410,9 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "wasmtime-jit-icache-coherence"
version = "18.0.2"
version = "19.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33f4121cb29dda08139b2824a734dd095d83ce843f2d613a84eb580b9cfc17ac"
checksum = "2796e4b4989db62899d2117e1e0258b839d088c044591b14e3a0396e7b3ae53a"
dependencies = [
"cfg-if",
"libc",

View File

@ -8,12 +8,12 @@ crate-type = ["dylib"]
[dependencies]
# These have to be in sync with each other
cranelift-codegen = { version = "0.105.2", default-features = false, features = ["std", "unwind", "all-arch"] }
cranelift-frontend = { version = "0.105.2" }
cranelift-module = { version = "0.105.2" }
cranelift-native = { version = "0.105.2" }
cranelift-jit = { version = "0.105.2", optional = true }
cranelift-object = { version = "0.105.2" }
cranelift-codegen = { version = "0.106.0", default-features = false, features = ["std", "unwind", "all-arch"] }
cranelift-frontend = { version = "0.106.0" }
cranelift-module = { version = "0.106.0" }
cranelift-native = { version = "0.106.0" }
cranelift-jit = { version = "0.106.0", optional = true }
cranelift-object = { version = "0.106.0" }
target-lexicon = "0.12.0"
gimli = { version = "0.28", default-features = false, features = ["write"]}
object = { version = "0.32", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] }

View File

@ -39,6 +39,6 @@ index 42a26ae..5ac1042 100644
+#![cfg(test)]
#![feature(alloc_layout_extra)]
#![feature(array_chunks)]
#![feature(array_windows)]
#![feature(array_ptr_get)]
--
2.21.0 (Apple Git-122)

View File

@ -1,3 +1,3 @@
[toolchain]
channel = "nightly-2024-03-16"
channel = "nightly-2024-03-28"
components = ["rust-src", "rustc-dev", "llvm-tools"]

View File

@ -26,9 +26,10 @@ fn main() {
codegen_backend_arg.push(cg_clif_dylib_path);
args.push(codegen_backend_arg);
}
if !passed_args.iter().any(|arg| {
arg == "--sysroot" || arg.to_str().is_some_and(|s| s.starts_with("--sysroot="))
}) {
if !passed_args
.iter()
.any(|arg| arg == "--sysroot" || arg.to_str().is_some_and(|s| s.starts_with("--sysroot=")))
{
args.push(OsString::from("--sysroot"));
args.push(OsString::from(sysroot.to_str().unwrap()));
}

View File

@ -26,12 +26,18 @@ fn main() {
codegen_backend_arg.push(cg_clif_dylib_path);
args.push(codegen_backend_arg);
}
if !passed_args.iter().any(|arg| {
arg == "--sysroot" || arg.to_str().is_some_and(|s| s.starts_with("--sysroot="))
}) {
if !passed_args
.iter()
.any(|arg| arg == "--sysroot" || arg.to_str().is_some_and(|s| s.starts_with("--sysroot=")))
{
args.push(OsString::from("--sysroot"));
args.push(OsString::from(sysroot.to_str().unwrap()));
}
if passed_args.is_empty() {
// Don't pass any arguments when the user didn't pass any arguments
// either to ensure the help message is shown.
args.clear();
}
args.extend(passed_args);
let rustdoc = if let Some(rustdoc) = option_env!("RUSTDOC") {

View File

@ -10,14 +10,6 @@ pushd rust
command -v rg >/dev/null 2>&1 || cargo install ripgrep
# FIXME(rust-lang/rust#122196) fix stage0 rmake.rs run-make tests and remove
# this workaround
for test in $(ls tests/run-make); do
if [[ -e "tests/run-make/$test/rmake.rs" ]]; then
rm -r "tests/run-make/$test"
fi
done
# FIXME remove this workaround once ICE tests no longer emit an outdated nightly message
for test in $(rg -i --files-with-matches "//@(\[.*\])? failure-status: 101" tests/ui); do
echo "rm $test"
@ -42,7 +34,6 @@ rm tests/ui/parser/unclosed-delimiter-in-dep.rs # submodule contains //~ERROR
# ================
# vendor intrinsics
rm tests/ui/simd/array-type.rs # "Index argument for `simd_insert` is not a constant"
rm tests/ui/asm/x86_64/evex512-implicit-feature.rs # unimplemented AVX512 x86 vendor intrinsic
# exotic linkages
@ -59,12 +50,9 @@ rm -r tests/run-make/c-link-to-rust-va-list-fn # requires callee side vararg sup
rm -r tests/run-pass-valgrind/unsized-locals
# misc unimplemented things
rm tests/ui/intrinsics/intrinsic-nearby.rs # unimplemented nearbyintf32 and nearbyintf64 intrinsics
rm tests/ui/target-feature/missing-plusminus.rs # error not implemented
rm -r tests/run-make/emit-named-files # requires full --emit support
rm -r tests/run-make/repr128-dwarf # debuginfo test
rm -r tests/run-make/split-debuginfo # same
rm -r tests/run-make/symbols-include-type-name # --emit=asm not supported
rm -r tests/run-make/target-specs # i686 not supported by Cranelift
rm -r tests/run-make/mismatching-target-triples # same
rm tests/ui/asm/x86_64/issue-96797.rs # const and sym inline asm operands don't work entirely correctly
@ -102,6 +90,17 @@ rm tests/ui/abi/stack-protector.rs # requires stack protector support
rm -r tests/run-make/emit-stack-sizes # requires support for -Z emit-stack-sizes
rm -r tests/run-make/optimization-remarks-dir # remarks are LLVM specific
# requires asm, llvm-ir and/or llvm-bc emit support
# =============================================
rm -r tests/run-make/emit-named-files
rm -r tests/run-make/issue-30063
rm -r tests/run-make/multiple-emits
rm -r tests/run-make/output-type-permutations
rm -r tests/run-make/emit-to-stdout
rm -r tests/run-make/compressed-debuginfo
rm -r tests/run-make/symbols-include-type-name
# giving different but possibly correct results
# =============================================
rm tests/ui/mir/mir_misc_casts.rs # depends on deduplication of constants
@ -109,35 +108,21 @@ rm tests/ui/mir/mir_raw_fat_ptr.rs # same
rm tests/ui/consts/issue-33537.rs # same
rm tests/ui/consts/const-mut-refs-crate.rs # same
# rustdoc-clif passes extra args, suppressing the help message when no args are passed
rm -r tests/run-make/issue-88756-default-output
# doesn't work due to the way the rustc test suite is invoked.
# should work when using ./x.py test the way it is intended
# ============================================================
rm -r tests/run-make/remap-path-prefix-dwarf # requires llvm-dwarfdump
rm -r tests/run-make/compiler-builtins # Expects lib/rustlib/src/rust to contains the standard library source
# genuine bugs
# ============
rm tests/incremental/spike-neg1.rs # errors out for some reason
rm tests/incremental/spike-neg2.rs # same
rm -r tests/run-make/issue-51671 # wrong filename given in case of --emit=obj
rm -r tests/run-make/issue-30063 # same
rm -r tests/run-make/multiple-emits # same
rm -r tests/run-make/output-type-permutations # same
rm -r tests/run-make/used # same
rm -r tests/run-make/no-alloc-shim
rm -r tests/run-make/emit-to-stdout
rm -r tests/run-make/compressed-debuginfo
rm -r tests/run-make/extern-fn-explicit-align # argument alignment not yet supported
rm tests/ui/codegen/subtyping-enforces-type-equality.rs # assert_assignable bug with Coroutine's
rm -r tests/run-make/panic-abort-eh_frame # .eh_frame emitted with panic=abort
# bugs in the test suite
# ======================
rm tests/ui/backtrace.rs # TODO warning
rm tests/ui/process/nofile-limit.rs # TODO some AArch64 linking issue
rm tests/ui/stdio-is-blocking.rs # really slow with unoptimized libstd
@ -160,6 +145,19 @@ index ea06b620c4c..b969d0009c6 100644
ifdef RUSTC_LINKER
RUSTC := \$(RUSTC) -Clinker='\$(RUSTC_LINKER)'
RUSTDOC := \$(RUSTDOC) -Clinker='\$(RUSTC_LINKER)'
diff --git a/src/tools/run-make-support/src/rustdoc.rs b/src/tools/run-make-support/src/rustdoc.rs
index 9607ff02f96..b7d97caf9a2 100644
--- a/src/tools/run-make-support/src/rustdoc.rs
+++ b/src/tools/run-make-support/src/rustdoc.rs
@@ -34,8 +34,6 @@ pub fn bare() -> Self {
/// Construct a \`rustdoc\` invocation with \`-L \$(TARGET_RPATH_DIR)\` set.
pub fn new() -> Self {
let mut cmd = setup_common();
- let target_rpath_dir = env::var_os("TARGET_RPATH_DIR").unwrap();
- cmd.arg(format!("-L{}", target_rpath_dir.to_string_lossy()));
Self { cmd }
}
EOF
echo "[TEST] rustc test suite"

View File

@ -222,17 +222,15 @@ pub(crate) fn codegen_fn_prelude<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, start_
Spread(Vec<Option<CValue<'tcx>>>),
}
let fn_abi = fx.fn_abi.take().unwrap();
// FIXME implement variadics in cranelift
if fn_abi.c_variadic {
if fx.fn_abi.c_variadic {
fx.tcx.dcx().span_fatal(
fx.mir.span,
"Defining variadic functions is not yet supported by Cranelift",
);
}
let mut arg_abis_iter = fn_abi.args.iter();
let mut arg_abis_iter = fx.fn_abi.args.iter();
let func_params = fx
.mir
@ -279,7 +277,6 @@ pub(crate) fn codegen_fn_prelude<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, start_
}
assert!(arg_abis_iter.next().is_none(), "ArgAbi left behind");
fx.fn_abi = Some(fn_abi);
assert!(block_params_iter.next().is_none(), "arg_value left behind");
self::comments::add_locals_header_comment(fx);

View File

@ -12,27 +12,15 @@ pub(super) fn codegen_return_param<'tcx>(
ssa_analyzed: &rustc_index::IndexSlice<Local, crate::analyze::SsaKind>,
block_params_iter: &mut impl Iterator<Item = Value>,
) -> CPlace<'tcx> {
let (ret_place, ret_param): (_, SmallVec<[_; 2]>) = match fx.fn_abi.as_ref().unwrap().ret.mode {
let (ret_place, ret_param): (_, SmallVec<[_; 2]>) = match fx.fn_abi.ret.mode {
PassMode::Ignore | PassMode::Direct(_) | PassMode::Pair(_, _) | PassMode::Cast { .. } => {
let is_ssa =
ssa_analyzed[RETURN_PLACE].is_ssa(fx, fx.fn_abi.as_ref().unwrap().ret.layout.ty);
(
super::make_local_place(
fx,
RETURN_PLACE,
fx.fn_abi.as_ref().unwrap().ret.layout,
is_ssa,
),
smallvec![],
)
let is_ssa = ssa_analyzed[RETURN_PLACE].is_ssa(fx, fx.fn_abi.ret.layout.ty);
(super::make_local_place(fx, RETURN_PLACE, fx.fn_abi.ret.layout, is_ssa), smallvec![])
}
PassMode::Indirect { attrs: _, meta_attrs: None, on_stack: _ } => {
let ret_param = block_params_iter.next().unwrap();
assert_eq!(fx.bcx.func.dfg.value_type(ret_param), fx.pointer_type);
(
CPlace::for_ptr(Pointer::new(ret_param), fx.fn_abi.as_ref().unwrap().ret.layout),
smallvec![ret_param],
)
(CPlace::for_ptr(Pointer::new(ret_param), fx.fn_abi.ret.layout), smallvec![ret_param])
}
PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack: _ } => {
unreachable!("unsized return value")
@ -45,8 +33,8 @@ pub(super) fn codegen_return_param<'tcx>(
Some(RETURN_PLACE),
None,
&ret_param,
&fx.fn_abi.as_ref().unwrap().ret.mode,
fx.fn_abi.as_ref().unwrap().ret.layout,
&fx.fn_abi.ret.mode,
fx.fn_abi.ret.layout,
);
ret_place
@ -115,7 +103,7 @@ pub(super) fn codegen_with_call_return_arg<'tcx>(
/// Codegen a return instruction with the right return value(s) if any.
pub(crate) fn codegen_return(fx: &mut FunctionCx<'_, '_, '_>) {
match fx.fn_abi.as_ref().unwrap().ret.mode {
match fx.fn_abi.ret.mode {
PassMode::Ignore | PassMode::Indirect { attrs: _, meta_attrs: None, on_stack: _ } => {
fx.bcx.ins().return_(&[]);
}

View File

@ -11,7 +11,7 @@ use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_monomorphize::is_call_from_compiler_builtins_to_upstream_monomorphization;
use crate::constant::ConstantCx;
use crate::debuginfo::FunctionDebugContext;
use crate::debuginfo::{FunctionDebugContext, TypeDebugContext};
use crate::prelude::*;
use crate::pretty_clif::CommentWriter;
@ -26,6 +26,7 @@ pub(crate) struct CodegenedFunction {
pub(crate) fn codegen_fn<'tcx>(
tcx: TyCtxt<'tcx>,
cx: &mut crate::CodegenCx,
type_dbg: &mut TypeDebugContext<'tcx>,
cached_func: Function,
module: &mut dyn Module,
instance: Instance<'tcx>,
@ -69,8 +70,10 @@ pub(crate) fn codegen_fn<'tcx>(
let pointer_type = target_config.pointer_type();
let clif_comments = crate::pretty_clif::CommentWriter::new(tcx, instance);
let fn_abi = RevealAllLayoutCx(tcx).fn_abi_of_instance(instance, ty::List::empty());
let func_debug_cx = if let Some(debug_context) = &mut cx.debug_context {
Some(debug_context.define_function(tcx, &symbol_name, mir.span))
Some(debug_context.define_function(tcx, type_dbg, instance, fn_abi, &symbol_name, mir.span))
} else {
None
};
@ -87,7 +90,7 @@ pub(crate) fn codegen_fn<'tcx>(
instance,
symbol_name,
mir,
fn_abi: Some(RevealAllLayoutCx(tcx).fn_abi_of_instance(instance, ty::List::empty())),
fn_abi,
bcx,
block_map,
@ -95,7 +98,6 @@ pub(crate) fn codegen_fn<'tcx>(
caller_location: None, // set by `codegen_fn_prelude`
clif_comments,
last_source_file: None,
next_ssa_var: 0,
};

View File

@ -1,12 +1,9 @@
use cranelift_codegen::isa::TargetFrontendConfig;
use gimli::write::FileId;
use rustc_data_structures::sync::Lrc;
use rustc_index::IndexVec;
use rustc_middle::ty::layout::{
FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOfHelpers,
};
use rustc_span::source_map::Spanned;
use rustc_span::SourceFile;
use rustc_target::abi::call::FnAbi;
use rustc_target::abi::{Integer, Primitive};
use rustc_target::spec::{HasTargetSpec, Target};
@ -294,7 +291,7 @@ pub(crate) struct FunctionCx<'m, 'clif, 'tcx: 'm> {
pub(crate) instance: Instance<'tcx>,
pub(crate) symbol_name: String,
pub(crate) mir: &'tcx Body<'tcx>,
pub(crate) fn_abi: Option<&'tcx FnAbi<'tcx, Ty<'tcx>>>,
pub(crate) fn_abi: &'tcx FnAbi<'tcx, Ty<'tcx>>,
pub(crate) bcx: FunctionBuilder<'clif>,
pub(crate) block_map: IndexVec<BasicBlock, Block>,
@ -305,11 +302,6 @@ pub(crate) struct FunctionCx<'m, 'clif, 'tcx: 'm> {
pub(crate) clif_comments: crate::pretty_clif::CommentWriter,
/// Last accessed source file and it's debuginfo file id.
///
/// For optimization purposes only
pub(crate) last_source_file: Option<(Lrc<SourceFile>, FileId)>,
/// This should only be accessed by `CPlace::new_var`.
pub(crate) next_ssa_var: u32,
}
@ -419,25 +411,8 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
pub(crate) fn set_debug_loc(&mut self, source_info: mir::SourceInfo) {
if let Some(debug_context) = &mut self.cx.debug_context {
let (file, line, column) =
DebugContext::get_span_loc(self.tcx, self.mir.span, source_info.span);
// add_source_file is very slow.
// Optimize for the common case of the current file not being changed.
let mut cached_file_id = None;
if let Some((ref last_source_file, last_file_id)) = self.last_source_file {
// If the allocations are not equal, the files may still be equal, but that
// doesn't matter, as this is just an optimization.
if rustc_data_structures::sync::Lrc::ptr_eq(last_source_file, &file) {
cached_file_id = Some(last_file_id);
}
}
let file_id = if let Some(file_id) = cached_file_id {
file_id
} else {
debug_context.add_source_file(&file)
};
let (file_id, line, column) =
debug_context.get_span_loc(self.tcx, self.mir.span, source_info.span);
let source_loc =
self.func_debug_cx.as_mut().unwrap().add_dbg_loc(file_id, line, column);

View File

@ -6,17 +6,16 @@ use cranelift_module::*;
use rustc_data_structures::fx::FxHashSet;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::mir::interpret::{read_target_uint, AllocId, GlobalAlloc, Scalar};
use rustc_middle::ty::ScalarInt;
use rustc_middle::ty::{Binder, ExistentialTraitRef, ScalarInt};
use crate::prelude::*;
pub(crate) struct ConstantCx {
todo: Vec<TodoItem>,
done: FxHashSet<DataId>,
anon_allocs: FxHashMap<AllocId, DataId>,
}
#[derive(Copy, Clone, Debug)]
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
enum TodoItem {
Alloc(AllocId),
Static(DefId),
@ -24,19 +23,24 @@ enum TodoItem {
impl ConstantCx {
pub(crate) fn new() -> Self {
ConstantCx { todo: vec![], done: FxHashSet::default(), anon_allocs: FxHashMap::default() }
ConstantCx { todo: vec![], anon_allocs: FxHashMap::default() }
}
pub(crate) fn finalize(mut self, tcx: TyCtxt<'_>, module: &mut dyn Module) {
define_all_allocs(tcx, module, &mut self);
self.done.clear();
}
}
pub(crate) fn codegen_static(tcx: TyCtxt<'_>, module: &mut dyn Module, def_id: DefId) {
pub(crate) fn codegen_static(tcx: TyCtxt<'_>, module: &mut dyn Module, def_id: DefId) -> DataId {
let mut constants_cx = ConstantCx::new();
constants_cx.todo.push(TodoItem::Static(def_id));
constants_cx.finalize(tcx, module);
data_id_for_static(
tcx, module, def_id, false,
// For a declaration the stated mutability doesn't matter.
false,
)
}
pub(crate) fn codegen_tls_ref<'tcx>(
@ -153,14 +157,12 @@ pub(crate) fn codegen_const_value<'tcx>(
fx.bcx.ins().func_addr(fx.pointer_type, local_func_id)
}
GlobalAlloc::VTable(ty, trait_ref) => {
let alloc_id = fx.tcx.vtable_allocation((ty, trait_ref));
let alloc = fx.tcx.global_alloc(alloc_id).unwrap_memory();
// FIXME: factor this common code with the `Memory` arm into a function?
let data_id = data_id_for_alloc_id(
let data_id = data_id_for_vtable(
fx.tcx,
&mut fx.constants_cx,
fx.module,
alloc_id,
alloc.inner().mutability,
ty,
trait_ref,
);
let local_data_id =
fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
@ -208,12 +210,8 @@ fn pointer_for_allocation<'tcx>(
alloc_id: AllocId,
) -> crate::pointer::Pointer {
let alloc = fx.tcx.global_alloc(alloc_id).unwrap_memory();
let data_id = data_id_for_alloc_id(
&mut fx.constants_cx,
&mut *fx.module,
alloc_id,
alloc.inner().mutability,
);
let data_id =
data_id_for_alloc_id(&mut fx.constants_cx, fx.module, alloc_id, alloc.inner().mutability);
let local_data_id = fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
if fx.clif_comments.enabled() {
@ -235,6 +233,17 @@ pub(crate) fn data_id_for_alloc_id(
.or_insert_with(|| module.declare_anonymous_data(mutability.is_mut(), false).unwrap())
}
pub(crate) fn data_id_for_vtable<'tcx>(
tcx: TyCtxt<'tcx>,
cx: &mut ConstantCx,
module: &mut dyn Module,
ty: Ty<'tcx>,
trait_ref: Option<Binder<'tcx, ExistentialTraitRef<'tcx>>>,
) -> DataId {
let alloc_id = tcx.vtable_allocation((ty, trait_ref));
data_id_for_alloc_id(cx, module, alloc_id, Mutability::Not)
}
fn data_id_for_static(
tcx: TyCtxt<'_>,
module: &mut dyn Module,
@ -327,7 +336,12 @@ fn data_id_for_static(
}
fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut ConstantCx) {
let mut done = FxHashSet::default();
while let Some(todo_item) = cx.todo.pop() {
if !done.insert(todo_item) {
continue;
}
let (data_id, alloc, section_name) = match todo_item {
TodoItem::Alloc(alloc_id) => {
let alloc = match tcx.global_alloc(alloc_id) {
@ -358,10 +372,6 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
}
};
if cx.done.contains(&data_id) {
continue;
}
let mut data = DataDescription::new();
let alloc = alloc.inner();
data.set_align(alloc.align.bytes());
@ -384,13 +394,7 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
}
let bytes = alloc.inspect_with_uninit_and_ptr_outside_interpreter(0..alloc.len()).to_vec();
if bytes.is_empty() {
// FIXME(bytecodealliance/wasmtime#7918) cranelift-jit has a bug where it causes UB on
// empty data objects
data.define(Box::new([0]));
} else {
data.define(bytes.into_boxed_slice());
}
data.define(bytes.into_boxed_slice());
for &(offset, prov) in alloc.provenance().ptrs().iter() {
let alloc_id = prov.alloc_id();
@ -418,8 +422,7 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
data_id_for_alloc_id(cx, module, alloc_id, target_alloc.inner().mutability)
}
GlobalAlloc::VTable(ty, trait_ref) => {
let alloc_id = tcx.vtable_allocation((ty, trait_ref));
data_id_for_alloc_id(cx, module, alloc_id, Mutability::Not)
data_id_for_vtable(tcx, cx, module, ty, trait_ref)
}
GlobalAlloc::Static(def_id) => {
if tcx.codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::THREAD_LOCAL)
@ -446,7 +449,6 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
}
module.define_data(data_id, &data).unwrap();
cx.done.insert(data_id);
}
assert!(cx.todo.is_empty(), "{:?}", cx.todo);

View File

@ -1,5 +1,6 @@
//! Write the debuginfo into an object file.
use cranelift_module::{DataId, FuncId};
use cranelift_object::ObjectProduct;
use gimli::write::{Address, AttributeValue, EndianVec, Result, Sections, Writer};
use gimli::{RunTimeEndian, SectionId};
@ -8,6 +9,18 @@ use rustc_data_structures::fx::FxHashMap;
use super::object::WriteDebugInfo;
use super::DebugContext;
pub(super) fn address_for_func(func_id: FuncId) -> Address {
let symbol = func_id.as_u32();
assert!(symbol & 1 << 31 == 0);
Address::Symbol { symbol: symbol as usize, addend: 0 }
}
pub(super) fn address_for_data(data_id: DataId) -> Address {
let symbol = data_id.as_u32();
assert!(symbol & 1 << 31 == 0);
Address::Symbol { symbol: (symbol | 1 << 31) as usize, addend: 0 }
}
impl DebugContext {
pub(crate) fn emit(&mut self, product: &mut ObjectProduct) {
let unit_range_list_id = self.dwarf.unit.ranges.add(self.unit_range_list.clone());
@ -171,6 +184,7 @@ impl Writer for WriterRelocate {
gimli::DW_EH_PE_pcrel => {
let size = match eh_pe.format() {
gimli::DW_EH_PE_sdata4 => 4,
gimli::DW_EH_PE_sdata8 => 8,
_ => return Err(gimli::write::Error::UnsupportedPointerEncoding(eh_pe)),
};
self.relocs.push(DebugReloc {

View File

@ -5,14 +5,12 @@ use std::path::{Component, Path};
use cranelift_codegen::binemit::CodeOffset;
use cranelift_codegen::MachSrcLoc;
use gimli::write::{
Address, AttributeValue, FileId, FileInfo, LineProgram, LineString, LineStringTable,
};
use rustc_data_structures::sync::Lrc;
use gimli::write::{AttributeValue, FileId, FileInfo, LineProgram, LineString, LineStringTable};
use rustc_span::{
FileName, Pos, SourceFile, SourceFileAndLine, SourceFileHash, SourceFileHashAlgorithm,
};
use crate::debuginfo::emit::address_for_func;
use crate::debuginfo::FunctionDebugContext;
use crate::prelude::*;
@ -60,10 +58,11 @@ fn make_file_info(hash: SourceFileHash) -> Option<FileInfo> {
impl DebugContext {
pub(crate) fn get_span_loc(
&mut self,
tcx: TyCtxt<'_>,
function_span: Span,
span: Span,
) -> (Lrc<SourceFile>, u64, u64) {
) -> (FileId, u64, u64) {
// Based on https://github.com/rust-lang/rust/blob/e369d87b015a84653343032833d65d0545fd3f26/src/librustc_codegen_ssa/mir/mod.rs#L116-L131
// In order to have a good line stepping behavior in debugger, we overwrite debug
// locations of macro expansions with that of the outermost expansion site (when the macro is
@ -71,61 +70,66 @@ impl DebugContext {
let span = tcx.collapsed_debuginfo(span, function_span);
match tcx.sess.source_map().lookup_line(span.lo()) {
Ok(SourceFileAndLine { sf: file, line }) => {
let file_id = self.add_source_file(&file);
let line_pos = file.lines()[line];
let col = file.relative_position(span.lo()) - line_pos;
(file, u64::try_from(line).unwrap() + 1, u64::from(col.to_u32()) + 1)
(file_id, u64::try_from(line).unwrap() + 1, u64::from(col.to_u32()) + 1)
}
Err(file) => (file, 0, 0),
Err(file) => (self.add_source_file(&file), 0, 0),
}
}
pub(crate) fn add_source_file(&mut self, source_file: &SourceFile) -> FileId {
let line_program: &mut LineProgram = &mut self.dwarf.unit.line_program;
let line_strings: &mut LineStringTable = &mut self.dwarf.line_strings;
let cache_key = (source_file.stable_id, source_file.src_hash);
*self.created_files.entry(cache_key).or_insert_with(|| {
let line_program: &mut LineProgram = &mut self.dwarf.unit.line_program;
let line_strings: &mut LineStringTable = &mut self.dwarf.line_strings;
match &source_file.name {
FileName::Real(path) => {
let (dir_path, file_name) =
split_path_dir_and_file(if self.should_remap_filepaths {
path.remapped_path_if_available()
} else {
path.local_path_if_available()
});
let dir_name = osstr_as_utf8_bytes(dir_path.as_os_str());
let file_name = osstr_as_utf8_bytes(file_name);
let dir_id = if !dir_name.is_empty() {
let dir_name = LineString::new(dir_name, line_program.encoding(), line_strings);
line_program.add_directory(dir_name)
} else {
line_program.default_directory()
};
let file_name = LineString::new(file_name, line_program.encoding(), line_strings);
let info = make_file_info(source_file.src_hash);
line_program.file_has_md5 &= info.is_some();
line_program.add_file(file_name, dir_id, info)
}
// FIXME give more appropriate file names
filename => {
let dir_id = line_program.default_directory();
let dummy_file_name = LineString::new(
filename
.display(if self.should_remap_filepaths {
FileNameDisplayPreference::Remapped
match &source_file.name {
FileName::Real(path) => {
let (dir_path, file_name) =
split_path_dir_and_file(if self.should_remap_filepaths {
path.remapped_path_if_available()
} else {
FileNameDisplayPreference::Local
})
.to_string()
.into_bytes(),
line_program.encoding(),
line_strings,
);
line_program.add_file(dummy_file_name, dir_id, None)
path.local_path_if_available()
});
let dir_name = osstr_as_utf8_bytes(dir_path.as_os_str());
let file_name = osstr_as_utf8_bytes(file_name);
let dir_id = if !dir_name.is_empty() {
let dir_name =
LineString::new(dir_name, line_program.encoding(), line_strings);
line_program.add_directory(dir_name)
} else {
line_program.default_directory()
};
let file_name =
LineString::new(file_name, line_program.encoding(), line_strings);
let info = make_file_info(source_file.src_hash);
line_program.file_has_md5 &= info.is_some();
line_program.add_file(file_name, dir_id, info)
}
filename => {
let dir_id = line_program.default_directory();
let dummy_file_name = LineString::new(
filename
.display(if self.should_remap_filepaths {
FileNameDisplayPreference::Remapped
} else {
FileNameDisplayPreference::Local
})
.to_string()
.into_bytes(),
line_program.encoding(),
line_strings,
);
line_program.add_file(dummy_file_name, dir_id, None)
}
}
}
})
}
}
@ -138,7 +142,7 @@ impl FunctionDebugContext {
pub(super) fn create_debug_lines(
&mut self,
debug_context: &mut DebugContext,
symbol: usize,
func_id: FuncId,
context: &Context,
) -> CodeOffset {
let create_row_for_span =
@ -151,11 +155,7 @@ impl FunctionDebugContext {
debug_context.dwarf.unit.line_program.generate_row();
};
debug_context
.dwarf
.unit
.line_program
.begin_sequence(Some(Address::Symbol { symbol, addend: 0 }));
debug_context.dwarf.unit.line_program.begin_sequence(Some(address_for_func(func_id)));
let mut func_end = 0;
@ -178,10 +178,7 @@ impl FunctionDebugContext {
assert_ne!(func_end, 0);
let entry = debug_context.dwarf.unit.get_mut(self.entry_id);
entry.set(
gimli::DW_AT_low_pc,
AttributeValue::Address(Address::Symbol { symbol, addend: 0 }),
);
entry.set(gimli::DW_AT_low_pc, AttributeValue::Address(address_for_func(func_id)));
entry.set(gimli::DW_AT_high_pc, AttributeValue::Udata(u64::from(func_end)));
func_end

View File

@ -3,20 +3,29 @@
mod emit;
mod line_info;
mod object;
mod types;
mod unwind;
use cranelift_codegen::ir::Endianness;
use cranelift_codegen::isa::TargetIsa;
use cranelift_module::DataId;
use gimli::write::{
Address, AttributeValue, DwarfUnit, FileId, LineProgram, LineString, Range, RangeList,
UnitEntryId,
Address, AttributeValue, DwarfUnit, Expression, FileId, LineProgram, LineString, Range,
RangeList, UnitEntryId,
};
use gimli::{Encoding, Format, LineEncoding, RunTimeEndian};
use gimli::{AArch64, Encoding, Format, LineEncoding, Register, RiscV, RunTimeEndian, X86_64};
use indexmap::IndexSet;
use rustc_codegen_ssa::debuginfo::type_names;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefIdMap;
use rustc_session::Session;
use rustc_span::{SourceFileHash, StableSourceFileId};
use rustc_target::abi::call::FnAbi;
pub(crate) use self::emit::{DebugReloc, DebugRelocName};
pub(crate) use self::types::TypeDebugContext;
pub(crate) use self::unwind::UnwindContext;
use crate::debuginfo::emit::{address_for_data, address_for_func};
use crate::prelude::*;
pub(crate) fn producer(sess: &Session) -> String {
@ -28,6 +37,10 @@ pub(crate) struct DebugContext {
dwarf: DwarfUnit,
unit_range_list: RangeList,
created_files: FxHashMap<(StableSourceFileId, SourceFileHash), FileId>,
stack_pointer_register: Register,
namespace_map: DefIdMap<UnitEntryId>,
array_size_type: UnitEntryId,
should_remap_filepaths: bool,
}
@ -39,7 +52,7 @@ pub(crate) struct FunctionDebugContext {
}
impl DebugContext {
pub(crate) fn new(tcx: TyCtxt<'_>, isa: &dyn TargetIsa) -> Self {
pub(crate) fn new(tcx: TyCtxt<'_>, isa: &dyn TargetIsa, cgu_name: &str) -> Self {
let encoding = Encoding {
format: Format::Dwarf32,
// FIXME this should be configurable
@ -60,6 +73,15 @@ impl DebugContext {
Endianness::Big => RunTimeEndian::Big,
};
let stack_pointer_register = match isa.triple().architecture {
target_lexicon::Architecture::Aarch64(_) => AArch64::SP,
target_lexicon::Architecture::Riscv64(_) => RiscV::SP,
target_lexicon::Architecture::X86_64 | target_lexicon::Architecture::X86_64h => {
X86_64::RSP
}
_ => Register(u16::MAX),
};
let mut dwarf = DwarfUnit::new(encoding);
let should_remap_filepaths = tcx.sess.should_prefer_remapped_for_codegen();
@ -95,7 +117,7 @@ impl DebugContext {
dwarf.unit.line_program = line_program;
{
let name = dwarf.strings.add(name);
let name = dwarf.strings.add(format!("{name}/@/{cgu_name}"));
let comp_dir = dwarf.strings.add(comp_dir);
let root = dwarf.unit.root();
@ -103,41 +125,134 @@ impl DebugContext {
root.set(gimli::DW_AT_producer, AttributeValue::StringRef(dwarf.strings.add(producer)));
root.set(gimli::DW_AT_language, AttributeValue::Language(gimli::DW_LANG_Rust));
root.set(gimli::DW_AT_name, AttributeValue::StringRef(name));
// This will be replaced when emitting the debuginfo. It is only
// defined here to ensure that the order of the attributes matches
// rustc.
root.set(gimli::DW_AT_stmt_list, AttributeValue::Udata(0));
root.set(gimli::DW_AT_comp_dir, AttributeValue::StringRef(comp_dir));
root.set(gimli::DW_AT_low_pc, AttributeValue::Address(Address::Constant(0)));
}
let array_size_type = dwarf.unit.add(dwarf.unit.root(), gimli::DW_TAG_base_type);
let array_size_type_entry = dwarf.unit.get_mut(array_size_type);
array_size_type_entry.set(
gimli::DW_AT_name,
AttributeValue::StringRef(dwarf.strings.add("__ARRAY_SIZE_TYPE__")),
);
array_size_type_entry
.set(gimli::DW_AT_encoding, AttributeValue::Encoding(gimli::DW_ATE_unsigned));
array_size_type_entry.set(
gimli::DW_AT_byte_size,
AttributeValue::Udata(isa.frontend_config().pointer_bytes().into()),
);
DebugContext {
endian,
dwarf,
unit_range_list: RangeList(Vec::new()),
created_files: FxHashMap::default(),
stack_pointer_register,
namespace_map: DefIdMap::default(),
array_size_type,
should_remap_filepaths,
}
}
pub(crate) fn define_function(
fn item_namespace(&mut self, tcx: TyCtxt<'_>, def_id: DefId) -> UnitEntryId {
if let Some(&scope) = self.namespace_map.get(&def_id) {
return scope;
}
let def_key = tcx.def_key(def_id);
let parent_scope = def_key
.parent
.map(|parent| self.item_namespace(tcx, DefId { krate: def_id.krate, index: parent }))
.unwrap_or(self.dwarf.unit.root());
let namespace_name = {
let mut output = String::new();
type_names::push_item_name(tcx, def_id, false, &mut output);
output
};
let namespace_name_id = self.dwarf.strings.add(namespace_name);
let scope = self.dwarf.unit.add(parent_scope, gimli::DW_TAG_namespace);
let scope_entry = self.dwarf.unit.get_mut(scope);
scope_entry.set(gimli::DW_AT_name, AttributeValue::StringRef(namespace_name_id));
self.namespace_map.insert(def_id, scope);
scope
}
pub(crate) fn define_function<'tcx>(
&mut self,
tcx: TyCtxt<'_>,
name: &str,
tcx: TyCtxt<'tcx>,
type_dbg: &mut TypeDebugContext<'tcx>,
instance: Instance<'tcx>,
fn_abi: &'tcx FnAbi<'tcx, Ty<'tcx>>,
linkage_name: &str,
function_span: Span,
) -> FunctionDebugContext {
let (file, line, column) = DebugContext::get_span_loc(tcx, function_span, function_span);
let (file_id, line, column) = self.get_span_loc(tcx, function_span, function_span);
let file_id = self.add_source_file(&file);
let scope = self.item_namespace(tcx, tcx.parent(instance.def_id()));
// FIXME: add to appropriate scope instead of root
let scope = self.dwarf.unit.root();
let mut name = String::new();
type_names::push_item_name(tcx, instance.def_id(), false, &mut name);
// Find the enclosing function, in case this is a closure.
let enclosing_fn_def_id = tcx.typeck_root_def_id(instance.def_id());
// We look up the generics of the enclosing function and truncate the args
// to their length in order to cut off extra stuff that might be in there for
// closures or coroutines.
let generics = tcx.generics_of(enclosing_fn_def_id);
let args = instance.args.truncate_to(tcx, generics);
type_names::push_generic_params(
tcx,
tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), args),
enclosing_fn_def_id,
&mut name,
);
let entry_id = self.dwarf.unit.add(scope, gimli::DW_TAG_subprogram);
let entry = self.dwarf.unit.get_mut(entry_id);
let linkage_name_id =
if name != linkage_name { Some(self.dwarf.strings.add(linkage_name)) } else { None };
let name_id = self.dwarf.strings.add(name);
// These will be replaced in FunctionDebugContext::finalize. They are
// only defined here to ensure that the order of the attributes matches
// rustc.
entry.set(gimli::DW_AT_low_pc, AttributeValue::Udata(0));
entry.set(gimli::DW_AT_high_pc, AttributeValue::Udata(0));
let mut frame_base_expr = Expression::new();
frame_base_expr.op_reg(self.stack_pointer_register);
entry.set(gimli::DW_AT_frame_base, AttributeValue::Exprloc(frame_base_expr));
if let Some(linkage_name_id) = linkage_name_id {
entry.set(gimli::DW_AT_linkage_name, AttributeValue::StringRef(linkage_name_id));
}
// Gdb requires DW_AT_name. Otherwise the DW_TAG_subprogram is skipped.
entry.set(gimli::DW_AT_name, AttributeValue::StringRef(name_id));
entry.set(gimli::DW_AT_linkage_name, AttributeValue::StringRef(name_id));
entry.set(gimli::DW_AT_decl_file, AttributeValue::FileIndex(Some(file_id)));
entry.set(gimli::DW_AT_decl_line, AttributeValue::Udata(line));
entry.set(gimli::DW_AT_decl_column, AttributeValue::Udata(column));
if !fn_abi.ret.is_ignore() {
let return_dw_ty = self.debug_type(tcx, type_dbg, fn_abi.ret.layout.ty);
let entry = self.dwarf.unit.get_mut(entry_id);
entry.set(gimli::DW_AT_type, AttributeValue::UnitRef(return_dw_ty));
}
if tcx.is_reachable_non_generic(instance.def_id()) {
let entry = self.dwarf.unit.get_mut(entry_id);
entry.set(gimli::DW_AT_external, AttributeValue::FlagPresent);
}
FunctionDebugContext {
entry_id,
@ -145,6 +260,62 @@ impl DebugContext {
source_loc_set: IndexSet::new(),
}
}
// Adapted from https://github.com/rust-lang/rust/blob/10a7aa14fed9b528b74b0f098c4899c37c09a9c7/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs#L1288-L1346
pub(crate) fn define_static<'tcx>(
&mut self,
tcx: TyCtxt<'tcx>,
type_dbg: &mut TypeDebugContext<'tcx>,
def_id: DefId,
data_id: DataId,
) {
let DefKind::Static { nested, .. } = tcx.def_kind(def_id) else { bug!() };
if nested {
return;
}
let scope = self.item_namespace(tcx, tcx.parent(def_id));
let span = tcx.def_span(def_id);
let (file_id, line, _column) = self.get_span_loc(tcx, span, span);
let static_type = Instance::mono(tcx, def_id).ty(tcx, ty::ParamEnv::reveal_all());
let static_layout = tcx.layout_of(ty::ParamEnv::reveal_all().and(static_type)).unwrap();
// FIXME use the actual type layout
let type_id = self.debug_type(tcx, type_dbg, static_type);
let name = tcx.item_name(def_id);
let linkage_name = tcx.symbol_name(Instance::mono(tcx, def_id)).name;
let entry_id = self.dwarf.unit.add(scope, gimli::DW_TAG_variable);
let entry = self.dwarf.unit.get_mut(entry_id);
let linkage_name_id = if name.as_str() != linkage_name {
Some(self.dwarf.strings.add(linkage_name))
} else {
None
};
let name_id = self.dwarf.strings.add(name.as_str());
entry.set(gimli::DW_AT_name, AttributeValue::StringRef(name_id));
entry.set(gimli::DW_AT_type, AttributeValue::UnitRef(type_id));
if tcx.is_reachable_non_generic(def_id) {
entry.set(gimli::DW_AT_external, AttributeValue::FlagPresent);
}
entry.set(gimli::DW_AT_decl_file, AttributeValue::FileIndex(Some(file_id)));
entry.set(gimli::DW_AT_decl_line, AttributeValue::Udata(line));
entry.set(gimli::DW_AT_alignment, AttributeValue::Udata(static_layout.align.pref.bytes()));
let mut expr = Expression::new();
expr.op_addr(address_for_data(data_id));
entry.set(gimli::DW_AT_location, AttributeValue::Exprloc(expr));
if let Some(linkage_name_id) = linkage_name_id {
entry.set(gimli::DW_AT_linkage_name, AttributeValue::StringRef(linkage_name_id));
}
}
}
impl FunctionDebugContext {
@ -154,21 +325,16 @@ impl FunctionDebugContext {
func_id: FuncId,
context: &Context,
) {
let symbol = func_id.as_u32() as usize;
let end = self.create_debug_lines(debug_context, func_id, context);
let end = self.create_debug_lines(debug_context, symbol, context);
debug_context.unit_range_list.0.push(Range::StartLength {
begin: Address::Symbol { symbol, addend: 0 },
length: u64::from(end),
});
debug_context
.unit_range_list
.0
.push(Range::StartLength { begin: address_for_func(func_id), length: u64::from(end) });
let func_entry = debug_context.dwarf.unit.get_mut(self.entry_id);
// Gdb requires both DW_AT_low_pc and DW_AT_high_pc. Otherwise the DW_TAG_subprogram is skipped.
func_entry.set(
gimli::DW_AT_low_pc,
AttributeValue::Address(Address::Symbol { symbol, addend: 0 }),
);
func_entry.set(gimli::DW_AT_low_pc, AttributeValue::Address(address_for_func(func_id)));
// Using Udata for DW_AT_high_pc requires at least DWARF4
func_entry.set(gimli::DW_AT_high_pc, AttributeValue::Udata(u64::from(end)));
}

View File

@ -1,4 +1,4 @@
use cranelift_module::FuncId;
use cranelift_module::{DataId, FuncId};
use cranelift_object::ObjectProduct;
use gimli::SectionId;
use object::write::{Relocation, StandardSegment};
@ -57,10 +57,13 @@ impl WriteDebugInfo for ObjectProduct {
let (symbol, symbol_offset) = match reloc.name {
DebugRelocName::Section(id) => (section_map.get(&id).unwrap().1, 0),
DebugRelocName::Symbol(id) => {
let symbol_id = self.function_symbol(FuncId::from_u32(id.try_into().unwrap()));
self.object
.symbol_section_and_offset(symbol_id)
.expect("Debug reloc for undef sym???")
let id = id.try_into().unwrap();
let symbol_id = if id & 1 << 31 == 0 {
self.function_symbol(FuncId::from_u32(id))
} else {
self.data_symbol(DataId::from_u32(id & !(1 << 31)))
};
self.object.symbol_section_and_offset(symbol_id).unwrap_or((symbol_id, 0))
}
};
self.object

View File

@ -0,0 +1,204 @@
// Adapted from https://github.com/rust-lang/rust/blob/10a7aa14fed9b528b74b0f098c4899c37c09a9c7/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
use gimli::write::{AttributeValue, UnitEntryId};
use rustc_codegen_ssa::debuginfo::type_names;
use rustc_data_structures::fx::FxHashMap;
use rustc_middle::ty::layout::LayoutOf;
use rustc_middle::ty::{self, Ty, TyCtxt};
use crate::{has_ptr_meta, DebugContext, RevealAllLayoutCx};
#[derive(Default)]
pub(crate) struct TypeDebugContext<'tcx> {
type_map: FxHashMap<Ty<'tcx>, UnitEntryId>,
}
/// Returns from the enclosing function if the type debuginfo node with the given
/// unique ID can be found in the type map.
macro_rules! return_if_type_created_in_meantime {
($type_dbg:expr, $ty:expr) => {
if let Some(&type_id) = $type_dbg.type_map.get(&$ty) {
return type_id;
}
};
}
impl DebugContext {
pub(crate) fn debug_type<'tcx>(
&mut self,
tcx: TyCtxt<'tcx>,
type_dbg: &mut TypeDebugContext<'tcx>,
ty: Ty<'tcx>,
) -> UnitEntryId {
if let Some(&type_id) = type_dbg.type_map.get(&ty) {
return type_id;
}
let type_id = match ty.kind() {
ty::Never | ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) => {
self.basic_type(tcx, ty)
}
ty::Tuple(elems) if elems.is_empty() => self.basic_type(tcx, ty),
ty::Array(elem_ty, len) => self.array_type(
tcx,
type_dbg,
ty,
*elem_ty,
len.eval_target_usize(tcx, ty::ParamEnv::reveal_all()),
),
// ty::Slice(_) | ty::Str
// ty::Dynamic
// ty::Foreign
ty::RawPtr(pointee_type, _) | ty::Ref(_, pointee_type, _) => {
self.pointer_type(tcx, type_dbg, ty, *pointee_type)
}
// ty::Adt(def, args) if def.is_box() && args.get(1).map_or(true, |arg| cx.layout_of(arg.expect_ty()).is_1zst())
// ty::FnDef(..) | ty::FnPtr(..)
// ty::Closure(..)
// ty::Adt(def, ..)
ty::Tuple(components) => self.tuple_type(tcx, type_dbg, ty, *components),
// ty::Param(_)
// FIXME implement remaining types and add unreachable!() to the fallback branch
_ => self.placeholder_for_type(tcx, type_dbg, ty),
};
type_dbg.type_map.insert(ty, type_id);
type_id
}
fn basic_type<'tcx>(&mut self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> UnitEntryId {
let (name, encoding) = match ty.kind() {
ty::Never => ("!", gimli::DW_ATE_unsigned),
ty::Tuple(elems) if elems.is_empty() => ("()", gimli::DW_ATE_unsigned),
ty::Bool => ("bool", gimli::DW_ATE_boolean),
ty::Char => ("char", gimli::DW_ATE_UTF),
ty::Int(int_ty) => (int_ty.name_str(), gimli::DW_ATE_signed),
ty::Uint(uint_ty) => (uint_ty.name_str(), gimli::DW_ATE_unsigned),
ty::Float(float_ty) => (float_ty.name_str(), gimli::DW_ATE_float),
_ => unreachable!(),
};
let type_id = self.dwarf.unit.add(self.dwarf.unit.root(), gimli::DW_TAG_base_type);
let type_entry = self.dwarf.unit.get_mut(type_id);
type_entry.set(gimli::DW_AT_name, AttributeValue::StringRef(self.dwarf.strings.add(name)));
type_entry.set(gimli::DW_AT_encoding, AttributeValue::Encoding(encoding));
type_entry.set(
gimli::DW_AT_byte_size,
AttributeValue::Udata(RevealAllLayoutCx(tcx).layout_of(ty).size.bytes()),
);
type_id
}
fn array_type<'tcx>(
&mut self,
tcx: TyCtxt<'tcx>,
type_dbg: &mut TypeDebugContext<'tcx>,
array_ty: Ty<'tcx>,
elem_ty: Ty<'tcx>,
len: u64,
) -> UnitEntryId {
let elem_dw_ty = self.debug_type(tcx, type_dbg, elem_ty);
return_if_type_created_in_meantime!(type_dbg, array_ty);
let array_type_id = self.dwarf.unit.add(self.dwarf.unit.root(), gimli::DW_TAG_array_type);
let array_type_entry = self.dwarf.unit.get_mut(array_type_id);
array_type_entry.set(gimli::DW_AT_type, AttributeValue::UnitRef(elem_dw_ty));
let subrange_id = self.dwarf.unit.add(array_type_id, gimli::DW_TAG_subrange_type);
let subrange_entry = self.dwarf.unit.get_mut(subrange_id);
subrange_entry.set(gimli::DW_AT_type, AttributeValue::UnitRef(self.array_size_type));
subrange_entry.set(gimli::DW_AT_lower_bound, AttributeValue::Udata(0));
subrange_entry.set(gimli::DW_AT_count, AttributeValue::Udata(len));
array_type_id
}
fn pointer_type<'tcx>(
&mut self,
tcx: TyCtxt<'tcx>,
type_dbg: &mut TypeDebugContext<'tcx>,
ptr_type: Ty<'tcx>,
pointee_type: Ty<'tcx>,
) -> UnitEntryId {
let pointee_dw_ty = self.debug_type(tcx, type_dbg, pointee_type);
return_if_type_created_in_meantime!(type_dbg, ptr_type);
let name = type_names::compute_debuginfo_type_name(tcx, ptr_type, true);
if !has_ptr_meta(tcx, ptr_type) {
let pointer_type_id =
self.dwarf.unit.add(self.dwarf.unit.root(), gimli::DW_TAG_pointer_type);
let pointer_entry = self.dwarf.unit.get_mut(pointer_type_id);
pointer_entry.set(gimli::DW_AT_type, AttributeValue::UnitRef(pointee_dw_ty));
pointer_entry
.set(gimli::DW_AT_name, AttributeValue::StringRef(self.dwarf.strings.add(name)));
pointer_type_id
} else {
// FIXME implement debuginfo for fat pointers
self.placeholder_for_type(tcx, type_dbg, ptr_type)
}
}
fn tuple_type<'tcx>(
&mut self,
tcx: TyCtxt<'tcx>,
type_dbg: &mut TypeDebugContext<'tcx>,
tuple_type: Ty<'tcx>,
components: &'tcx [Ty<'tcx>],
) -> UnitEntryId {
let components = components
.into_iter()
.map(|&ty| (ty, self.debug_type(tcx, type_dbg, ty)))
.collect::<Vec<_>>();
return_if_type_created_in_meantime!(type_dbg, tuple_type);
let name = type_names::compute_debuginfo_type_name(tcx, tuple_type, false);
let layout = RevealAllLayoutCx(tcx).layout_of(tuple_type);
let tuple_type_id =
self.dwarf.unit.add(self.dwarf.unit.root(), gimli::DW_TAG_structure_type);
let tuple_entry = self.dwarf.unit.get_mut(tuple_type_id);
tuple_entry.set(gimli::DW_AT_name, AttributeValue::StringRef(self.dwarf.strings.add(name)));
tuple_entry.set(gimli::DW_AT_byte_size, AttributeValue::Udata(layout.size.bytes()));
tuple_entry.set(gimli::DW_AT_alignment, AttributeValue::Udata(layout.align.pref.bytes()));
for (i, (ty, dw_ty)) in components.into_iter().enumerate() {
let member_id = self.dwarf.unit.add(tuple_type_id, gimli::DW_TAG_member);
let member_entry = self.dwarf.unit.get_mut(member_id);
member_entry.set(
gimli::DW_AT_name,
AttributeValue::StringRef(self.dwarf.strings.add(format!("__{i}"))),
);
member_entry.set(gimli::DW_AT_type, AttributeValue::UnitRef(dw_ty));
member_entry.set(
gimli::DW_AT_alignment,
AttributeValue::Udata(RevealAllLayoutCx(tcx).layout_of(ty).align.pref.bytes()),
);
member_entry.set(
gimli::DW_AT_data_member_location,
AttributeValue::Udata(layout.fields.offset(i).bytes()),
);
}
tuple_type_id
}
fn placeholder_for_type<'tcx>(
&mut self,
tcx: TyCtxt<'tcx>,
type_dbg: &mut TypeDebugContext<'tcx>,
ty: Ty<'tcx>,
) -> UnitEntryId {
self.debug_type(
tcx,
type_dbg,
Ty::new_array(tcx, tcx.types.u8, RevealAllLayoutCx(tcx).layout_of(ty).size.bytes()),
)
}
}

View File

@ -3,9 +3,10 @@
use cranelift_codegen::ir::Endianness;
use cranelift_codegen::isa::{unwind::UnwindInfo, TargetIsa};
use cranelift_object::ObjectProduct;
use gimli::write::{Address, CieId, EhFrame, FrameTable, Section};
use gimli::write::{CieId, EhFrame, FrameTable, Section};
use gimli::RunTimeEndian;
use super::emit::address_for_func;
use super::object::WriteDebugInfo;
use crate::prelude::*;
@ -47,11 +48,8 @@ impl UnwindContext {
match unwind_info {
UnwindInfo::SystemV(unwind_info) => {
self.frame_table.add_fde(
self.cie_id.unwrap(),
unwind_info
.to_fde(Address::Symbol { symbol: func_id.as_u32() as usize, addend: 0 }),
);
self.frame_table
.add_fde(self.cie_id.unwrap(), unwind_info.to_fde(address_for_func(func_id)));
}
UnwindInfo::WindowsX64(_) => {
// FIXME implement this

View File

@ -1,25 +1,29 @@
//! The AOT driver uses [`cranelift_object`] to write object files suitable for linking into a
//! standalone executable.
use std::fs::File;
use std::path::PathBuf;
use std::fs::{self, File};
use std::path::{Path, PathBuf};
use std::sync::Arc;
use std::thread::JoinHandle;
use cranelift_object::{ObjectBuilder, ObjectModule};
use rustc_codegen_ssa::assert_module_sources::CguReuse;
use rustc_codegen_ssa::back::link::ensure_removed;
use rustc_codegen_ssa::back::metadata::create_compressed_metadata_file;
use rustc_codegen_ssa::base::determine_cgu_reuse;
use rustc_codegen_ssa::errors as ssa_errors;
use rustc_codegen_ssa::{CodegenResults, CompiledModule, CrateInfo, ModuleKind};
use rustc_data_structures::profiling::SelfProfilerRef;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_metadata::fs::copy_to_stdout;
use rustc_metadata::EncodedMetadata;
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
use rustc_middle::mir::mono::{CodegenUnit, MonoItem};
use rustc_session::config::{DebugInfo, OutputFilenames, OutputType};
use rustc_session::config::{DebugInfo, OutFileName, OutputFilenames, OutputType};
use rustc_session::Session;
use crate::concurrency_limiter::{ConcurrencyLimiter, ConcurrencyLimiterToken};
use crate::debuginfo::TypeDebugContext;
use crate::global_asm::GlobalAsmConfig;
use crate::{prelude::*, BackendConfig};
@ -53,6 +57,7 @@ impl OngoingCodegen {
pub(crate) fn join(
self,
sess: &Session,
outputs: &OutputFilenames,
backend_config: &BackendConfig,
) -> (CodegenResults, FxIndexMap<WorkProductId, WorkProduct>) {
let mut work_products = FxIndexMap::default();
@ -110,19 +115,185 @@ impl OngoingCodegen {
sess.dcx().abort_if_errors();
(
CodegenResults {
modules,
allocator_module: self.allocator_module,
metadata_module: self.metadata_module,
metadata: self.metadata,
crate_info: self.crate_info,
},
work_products,
)
let codegen_results = CodegenResults {
modules,
allocator_module: self.allocator_module,
metadata_module: self.metadata_module,
metadata: self.metadata,
crate_info: self.crate_info,
};
produce_final_output_artifacts(sess, &codegen_results, outputs);
(codegen_results, work_products)
}
}
// Adapted from https://github.com/rust-lang/rust/blob/73476d49904751f8d90ce904e16dfbc278083d2c/compiler/rustc_codegen_ssa/src/back/write.rs#L547C1-L706C2
fn produce_final_output_artifacts(
sess: &Session,
codegen_results: &CodegenResults,
crate_output: &OutputFilenames,
) {
let user_wants_bitcode = false;
let mut user_wants_objects = false;
// Produce final compile outputs.
let copy_gracefully = |from: &Path, to: &OutFileName| match to {
OutFileName::Stdout => {
if let Err(e) = copy_to_stdout(from) {
sess.dcx().emit_err(ssa_errors::CopyPath::new(from, to.as_path(), e));
}
}
OutFileName::Real(path) => {
if let Err(e) = fs::copy(from, path) {
sess.dcx().emit_err(ssa_errors::CopyPath::new(from, path, e));
}
}
};
let copy_if_one_unit = |output_type: OutputType, keep_numbered: bool| {
if codegen_results.modules.len() == 1 {
// 1) Only one codegen unit. In this case it's no difficulty
// to copy `foo.0.x` to `foo.x`.
let module_name = Some(&codegen_results.modules[0].name[..]);
let path = crate_output.temp_path(output_type, module_name);
let output = crate_output.path(output_type);
if !output_type.is_text_output() && output.is_tty() {
sess.dcx()
.emit_err(ssa_errors::BinaryOutputToTty { shorthand: output_type.shorthand() });
} else {
copy_gracefully(&path, &output);
}
if !sess.opts.cg.save_temps && !keep_numbered {
// The user just wants `foo.x`, not `foo.#module-name#.x`.
ensure_removed(sess.dcx(), &path);
}
} else {
let extension = crate_output
.temp_path(output_type, None)
.extension()
.unwrap()
.to_str()
.unwrap()
.to_owned();
if crate_output.outputs.contains_explicit_name(&output_type) {
// 2) Multiple codegen units, with `--emit foo=some_name`. We have
// no good solution for this case, so warn the user.
sess.dcx().emit_warn(ssa_errors::IgnoringEmitPath { extension });
} else if crate_output.single_output_file.is_some() {
// 3) Multiple codegen units, with `-o some_name`. We have
// no good solution for this case, so warn the user.
sess.dcx().emit_warn(ssa_errors::IgnoringOutput { extension });
} else {
// 4) Multiple codegen units, but no explicit name. We
// just leave the `foo.0.x` files in place.
// (We don't have to do any work in this case.)
}
}
};
// Flag to indicate whether the user explicitly requested bitcode.
// Otherwise, we produced it only as a temporary output, and will need
// to get rid of it.
for output_type in crate_output.outputs.keys() {
match *output_type {
OutputType::Bitcode => {
// Cranelift doesn't have bitcode
// user_wants_bitcode = true;
// // Copy to .bc, but always keep the .0.bc. There is a later
// // check to figure out if we should delete .0.bc files, or keep
// // them for making an rlib.
// copy_if_one_unit(OutputType::Bitcode, true);
}
OutputType::LlvmAssembly => {
// Cranelift IR text already emitted during codegen
// copy_if_one_unit(OutputType::LlvmAssembly, false);
}
OutputType::Assembly => {
// Currently no support for emitting raw assembly files
// copy_if_one_unit(OutputType::Assembly, false);
}
OutputType::Object => {
user_wants_objects = true;
copy_if_one_unit(OutputType::Object, true);
}
OutputType::Mir | OutputType::Metadata | OutputType::Exe | OutputType::DepInfo => {}
}
}
// Clean up unwanted temporary files.
// We create the following files by default:
// - #crate#.#module-name#.bc
// - #crate#.#module-name#.o
// - #crate#.crate.metadata.bc
// - #crate#.crate.metadata.o
// - #crate#.o (linked from crate.##.o)
// - #crate#.bc (copied from crate.##.bc)
// We may create additional files if requested by the user (through
// `-C save-temps` or `--emit=` flags).
if !sess.opts.cg.save_temps {
// Remove the temporary .#module-name#.o objects. If the user didn't
// explicitly request bitcode (with --emit=bc), and the bitcode is not
// needed for building an rlib, then we must remove .#module-name#.bc as
// well.
// Specific rules for keeping .#module-name#.bc:
// - If the user requested bitcode (`user_wants_bitcode`), and
// codegen_units > 1, then keep it.
// - If the user requested bitcode but codegen_units == 1, then we
// can toss .#module-name#.bc because we copied it to .bc earlier.
// - If we're not building an rlib and the user didn't request
// bitcode, then delete .#module-name#.bc.
// If you change how this works, also update back::link::link_rlib,
// where .#module-name#.bc files are (maybe) deleted after making an
// rlib.
let needs_crate_object = crate_output.outputs.contains_key(&OutputType::Exe);
let keep_numbered_bitcode = user_wants_bitcode && sess.codegen_units().as_usize() > 1;
let keep_numbered_objects =
needs_crate_object || (user_wants_objects && sess.codegen_units().as_usize() > 1);
for module in codegen_results.modules.iter() {
if let Some(ref path) = module.object {
if !keep_numbered_objects {
ensure_removed(sess.dcx(), path);
}
}
if let Some(ref path) = module.dwarf_object {
if !keep_numbered_objects {
ensure_removed(sess.dcx(), path);
}
}
if let Some(ref path) = module.bytecode {
if !keep_numbered_bitcode {
ensure_removed(sess.dcx(), path);
}
}
}
if !user_wants_bitcode {
if let Some(ref allocator_module) = codegen_results.allocator_module {
if let Some(ref path) = allocator_module.bytecode {
ensure_removed(sess.dcx(), path);
}
}
}
}
// We leave the following files around by default:
// - #crate#.o
// - #crate#.crate.metadata.o
// - #crate#.bc
// These are used in linking steps and will be cleaned up afterward.
}
fn make_module(sess: &Session, backend_config: &BackendConfig, name: String) -> ObjectModule {
let isa = crate::build_isa(sess, backend_config);
@ -290,6 +461,7 @@ fn module_codegen(
tcx.sess.opts.debuginfo != DebugInfo::None,
cgu_name,
);
let mut type_dbg = TypeDebugContext::default();
super::predefine_mono_items(tcx, &mut module, &mono_items);
let mut codegened_functions = vec![];
for (mono_item, _) in mono_items {
@ -298,6 +470,7 @@ fn module_codegen(
let codegened_function = crate::base::codegen_fn(
tcx,
&mut cx,
&mut type_dbg,
Function::new(),
&mut module,
inst,
@ -305,7 +478,10 @@ fn module_codegen(
codegened_functions.push(codegened_function);
}
MonoItem::Static(def_id) => {
crate::constant::codegen_static(tcx, &mut module, def_id)
let data_id = crate::constant::codegen_static(tcx, &mut module, def_id);
if let Some(debug_context) = &mut cx.debug_context {
debug_context.define_static(tcx, &mut type_dbg, def_id, data_id);
}
}
MonoItem::GlobalAsm(item_id) => {
crate::global_asm::codegen_global_asm_item(

View File

@ -12,6 +12,7 @@ use rustc_middle::mir::mono::MonoItem;
use rustc_session::Session;
use rustc_span::Symbol;
use crate::debuginfo::TypeDebugContext;
use crate::{prelude::*, BackendConfig};
use crate::{CodegenCx, CodegenMode};
@ -229,7 +230,14 @@ pub(crate) fn codegen_and_compile_fn<'tcx>(
crate::PrintOnPanic(|| format!("{:?} {}", instance, tcx.symbol_name(instance).name));
let cached_func = std::mem::replace(&mut cached_context.func, Function::new());
let codegened_func = crate::base::codegen_fn(tcx, cx, cached_func, module, instance);
let codegened_func = crate::base::codegen_fn(
tcx,
cx,
&mut TypeDebugContext::default(),
cached_func,
module,
instance,
);
crate::base::compile_fn(cx, cached_context, module, codegened_func);
});

View File

@ -8,6 +8,7 @@ use std::sync::Arc;
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
use rustc_hir::{InlineAsmOperand, ItemId};
use rustc_middle::mir::interpret::ErrorHandled;
use rustc_session::config::{OutputFilenames, OutputType};
use rustc_target::asm::InlineAsmArch;
@ -32,18 +33,27 @@ pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String,
InlineAsmTemplatePiece::Placeholder { operand_idx, modifier: _, span: op_sp } => {
match asm.operands[operand_idx].0 {
InlineAsmOperand::Const { ref anon_const } => {
let const_value =
tcx.const_eval_poly(anon_const.def_id.to_def_id()).unwrap_or_else(
|_| span_bug!(op_sp, "asm const cannot be resolved"),
);
let ty = tcx.typeck_body(anon_const.body).node_type(anon_const.hir_id);
let string = rustc_codegen_ssa::common::asm_const_to_str(
tcx,
op_sp,
const_value,
RevealAllLayoutCx(tcx).layout_of(ty),
);
global_asm.push_str(&string);
match tcx.const_eval_poly(anon_const.def_id.to_def_id()) {
Ok(const_value) => {
let ty = tcx
.typeck_body(anon_const.body)
.node_type(anon_const.hir_id);
let string = rustc_codegen_ssa::common::asm_const_to_str(
tcx,
op_sp,
const_value,
RevealAllLayoutCx(tcx).layout_of(ty),
);
global_asm.push_str(&string);
}
Err(ErrorHandled::Reported { .. }) => {
// An error has already been reported and compilation is
// guaranteed to fail if execution hits this path.
}
Err(ErrorHandled::TooGeneric(_)) => {
span_bug!(op_sp, "asm const cannot be resolved; too generic");
}
}
}
InlineAsmOperand::SymFn { anon_const } => {
if cfg!(not(feature = "inline_asm_sym")) {

View File

@ -341,6 +341,8 @@ fn codegen_float_intrinsic_call<'tcx>(
sym::roundf64 => ("round", 1, fx.tcx.types.f64, types::F64),
sym::roundevenf32 => ("roundevenf", 1, fx.tcx.types.f32, types::F32),
sym::roundevenf64 => ("roundeven", 1, fx.tcx.types.f64, types::F64),
sym::nearbyintf32 => ("nearbyintf", 1, fx.tcx.types.f32, types::F32),
sym::nearbyintf64 => ("nearbyint", 1, fx.tcx.types.f64, types::F64),
sym::sinf32 => ("sinf", 1, fx.tcx.types.f32, types::F32),
sym::sinf64 => ("sin", 1, fx.tcx.types.f64, types::F64),
sym::cosf32 => ("cosf", 1, fx.tcx.types.f32, types::F32),
@ -392,6 +394,8 @@ fn codegen_float_intrinsic_call<'tcx>(
| sym::ceilf64
| sym::truncf32
| sym::truncf64
| sym::nearbyintf32
| sym::nearbyintf64
| sym::sqrtf32
| sym::sqrtf64 => {
let val = match intrinsic {
@ -399,6 +403,7 @@ fn codegen_float_intrinsic_call<'tcx>(
sym::floorf32 | sym::floorf64 => fx.bcx.ins().floor(args[0]),
sym::ceilf32 | sym::ceilf64 => fx.bcx.ins().ceil(args[0]),
sym::truncf32 | sym::truncf64 => fx.bcx.ins().trunc(args[0]),
sym::nearbyintf32 | sym::nearbyintf64 => fx.bcx.ins().nearest(args[0]),
sym::sqrtf32 | sym::sqrtf64 => fx.bcx.ins().sqrt(args[0]),
_ => unreachable!(),
};

View File

@ -148,7 +148,7 @@ impl CodegenCx {
let unwind_context =
UnwindContext::new(isa, matches!(backend_config.codegen_mode, CodegenMode::Aot));
let debug_context = if debug_info && !tcx.sess.target.options.is_like_windows {
Some(DebugContext::new(tcx, isa))
Some(DebugContext::new(tcx, isa, cgu_name.as_str()))
} else {
None
};
@ -233,12 +233,13 @@ impl CodegenBackend for CraneliftCodegenBackend {
&self,
ongoing_codegen: Box<dyn Any>,
sess: &Session,
_outputs: &OutputFilenames,
outputs: &OutputFilenames,
) -> (CodegenResults, FxIndexMap<WorkProductId, WorkProduct>) {
ongoing_codegen
.downcast::<driver::aot::OngoingCodegen>()
.unwrap()
.join(sess, self.config.borrow().as_ref().unwrap())
ongoing_codegen.downcast::<driver::aot::OngoingCodegen>().unwrap().join(
sess,
outputs,
self.config.borrow().as_ref().unwrap(),
)
}
fn link(

View File

@ -2,7 +2,7 @@
//!
//! See `rustc_codegen_ssa/src/meth.rs` for reference.
use crate::constant::data_id_for_alloc_id;
use crate::constant::data_id_for_vtable;
use crate::prelude::*;
pub(crate) fn vtable_memflags() -> MemFlags {
@ -92,12 +92,10 @@ pub(crate) fn get_vtable<'tcx>(
ty: Ty<'tcx>,
trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
) -> Value {
let alloc_id = fx.tcx.vtable_allocation((ty, trait_ref));
let data_id =
data_id_for_alloc_id(&mut fx.constants_cx, &mut *fx.module, alloc_id, Mutability::Not);
let data_id = data_id_for_vtable(fx.tcx, &mut fx.constants_cx, fx.module, ty, trait_ref);
let local_data_id = fx.module.declare_data_in_func(data_id, fx.bcx.func);
if fx.clif_comments.enabled() {
fx.add_comment(local_data_id, format!("vtable: {:?}", alloc_id));
fx.add_comment(local_data_id, "vtable");
}
fx.bcx.ins().global_value(fx.pointer_type, local_data_id)
}