diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bf3c22744f165..5f9311635f6bf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -152,10 +152,6 @@ jobs: - name: dist-x86_64-linux os: ubuntu-latest-xl env: {} - - name: dist-x86_64-linux-alt - env: - IMAGE: dist-x86_64-linux - os: ubuntu-latest-xl timeout-minutes: 600 runs-on: "${{ matrix.os }}" steps: diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 58e4bef677efb..8f0a245a5658a 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -1206,7 +1206,7 @@ impl<'a> Builder<'a> { ); } - // If Control Flow Guard is enabled, pass the `control_flow_guard=checks` flag to rustc + // If Control Flow Guard is enabled, pass the `control-flow-guard` flag to rustc // when compiling the standard library, since this might be linked into the final outputs // produced by rustc. Since this mitigation is only available on Windows, only enable it // for the standard library in case the compiler is run on a non-Windows platform. @@ -1217,7 +1217,7 @@ impl<'a> Builder<'a> { && self.config.control_flow_guard && compiler.stage >= 1 { - rustflags.arg("-Zcontrol_flow_guard=checks"); + rustflags.arg("-Zcontrol-flow-guard"); } // For `cargo doc` invocations, make rustdoc print the Rust version into the docs diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index d1e53db573e4c..47673ce1e8703 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -141,6 +141,8 @@ def v(*args): "rootfs in qemu testing, you probably don't want to use this") v("qemu-aarch64-rootfs", "target.aarch64-unknown-linux-gnu.qemu-rootfs", "rootfs in qemu testing, you probably don't want to use this") +v("qemu-riscv64-rootfs", "target.riscv64gc-unknown-linux-gnu.qemu-rootfs", + "rootfs in qemu testing, you probably don't want to use this") v("experimental-targets", "llvm.experimental-targets", "experimental LLVM targets to build") v("release-channel", "rust.channel", "the name of the release channel to build") diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 252a6316e574b..0a14957384d28 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -689,48 +689,41 @@ fn supported_sanitizers( target: Interned, channel: &str, ) -> Vec { - let mut result = Vec::new(); + let darwin_libs = |os: &str, components: &[&str]| -> Vec { + components + .into_iter() + .map(move |c| SanitizerRuntime { + cmake_target: format!("clang_rt.{}_{}_dynamic", c, os), + path: out_dir + .join(&format!("build/lib/darwin/libclang_rt.{}_{}_dynamic.dylib", c, os)), + name: format!("librustc-{}_rt.{}.dylib", channel, c), + }) + .collect() + }; + + let common_libs = |os: &str, arch: &str, components: &[&str]| -> Vec { + components + .into_iter() + .map(move |c| SanitizerRuntime { + cmake_target: format!("clang_rt.{}-{}", c, arch), + path: out_dir.join(&format!("build/lib/{}/libclang_rt.{}-{}.a", os, c, arch)), + name: format!("librustc-{}_rt.{}.a", channel, c), + }) + .collect() + }; + match &*target { - "x86_64-apple-darwin" => { - for s in &["asan", "lsan", "tsan"] { - result.push(SanitizerRuntime { - cmake_target: format!("clang_rt.{}_osx_dynamic", s), - path: out_dir - .join(&format!("build/lib/darwin/libclang_rt.{}_osx_dynamic.dylib", s)), - name: format!("librustc-{}_rt.{}.dylib", channel, s), - }); - } + "aarch64-fuchsia" => common_libs("fuchsia", "aarch64", &["asan"]), + "aarch64-unknown-linux-gnu" => { + common_libs("linux", "aarch64", &["asan", "lsan", "msan", "tsan"]) } + "x86_64-apple-darwin" => darwin_libs("osx", &["asan", "lsan", "tsan"]), + "x86_64-fuchsia" => common_libs("fuchsia", "x86_64", &["asan"]), "x86_64-unknown-linux-gnu" => { - for s in &["asan", "lsan", "msan", "tsan"] { - result.push(SanitizerRuntime { - cmake_target: format!("clang_rt.{}-x86_64", s), - path: out_dir.join(&format!("build/lib/linux/libclang_rt.{}-x86_64.a", s)), - name: format!("librustc-{}_rt.{}.a", channel, s), - }); - } - } - "x86_64-fuchsia" => { - for s in &["asan"] { - result.push(SanitizerRuntime { - cmake_target: format!("clang_rt.{}-x86_64", s), - path: out_dir.join(&format!("build/lib/fuchsia/libclang_rt.{}-x86_64.a", s)), - name: format!("librustc-{}_rt.{}.a", channel, s), - }); - } - } - "aarch64-fuchsia" => { - for s in &["asan"] { - result.push(SanitizerRuntime { - cmake_target: format!("clang_rt.{}-aarch64", s), - path: out_dir.join(&format!("build/lib/fuchsia/libclang_rt.{}-aarch64.a", s)), - name: format!("librustc-{}_rt.{}.a", channel, s), - }); - } + common_libs("linux", "x86_64", &["asan", "lsan", "msan", "tsan"]) } - _ => {} + _ => Vec::new(), } - result } struct HashStamp { diff --git a/src/ci/azure-pipelines/try.yml b/src/ci/azure-pipelines/try.yml index 38a0685e0f75a..818306a009229 100644 --- a/src/ci/azure-pipelines/try.yml +++ b/src/ci/azure-pipelines/try.yml @@ -26,8 +26,6 @@ jobs: strategy: matrix: dist-x86_64-linux: {} - dist-x86_64-linux-alt: - IMAGE: dist-x86_64-linux # The macOS and Windows builds here are currently disabled due to them not being # overly necessary on `try` builds. We also don't actually have anything that diff --git a/src/ci/docker/disabled/riscv64gc-linux/0001-Remove-stime-function-calls.patch b/src/ci/docker/disabled/riscv64gc-linux/0001-Remove-stime-function-calls.patch new file mode 100644 index 0000000000000..08d0c5b2cac1e --- /dev/null +++ b/src/ci/docker/disabled/riscv64gc-linux/0001-Remove-stime-function-calls.patch @@ -0,0 +1,96 @@ +From c820da85c65c7f3aa9e9cb3ed71ada69bf9b783e Mon Sep 17 00:00:00 2001 +From: Alistair Francis +Date: Tue, 19 Nov 2019 13:06:40 +0100 +Subject: [PATCH] Remove stime() function calls + +stime() has been deprecated in glibc 2.31 and replaced with +clock_settime(). Let's replace the stime() function calls with +clock_settime() in preperation. + +function old new delta +rdate_main 197 224 +27 +clock_settime - 27 +27 +date_main 926 941 +15 +stime 37 - -37 +------------------------------------------------------------------------------ +(add/remove: 2/2 grow/shrink: 2/0 up/down: 69/-37) Total: 32 bytes + +Signed-off-by: Alistair Francis +Signed-off-by: Denys Vlasenko + +[Tom Eccles: adjust patch context to apply on top of 1.31.1-stable] +Signed-off-by: Tom Eccles +--- + coreutils/date.c | 6 +++++- + libbb/missing_syscalls.c | 8 -------- + util-linux/rdate.c | 8 ++++++-- + 3 files changed, 11 insertions(+), 11 deletions(-) + +diff --git a/coreutils/date.c b/coreutils/date.c +index 3414d38ae..4ade6abb4 100644 +--- a/coreutils/date.c ++++ b/coreutils/date.c +@@ -279,6 +279,9 @@ int date_main(int argc UNUSED_PARAM, char **argv) + time(&ts.tv_sec); + #endif + } ++#if !ENABLE_FEATURE_DATE_NANO ++ ts.tv_nsec = 0; ++#endif + localtime_r(&ts.tv_sec, &tm_time); + + /* If date string is given, update tm_time, and maybe set date */ +@@ -301,9 +304,10 @@ int date_main(int argc UNUSED_PARAM, char **argv) + if (date_str[0] != '@') + tm_time.tm_isdst = -1; + ts.tv_sec = validate_tm_time(date_str, &tm_time); ++ ts.tv_nsec = 0; + + /* if setting time, set it */ +- if ((opt & OPT_SET) && stime(&ts.tv_sec) < 0) { ++ if ((opt & OPT_SET) && clock_settime(CLOCK_REALTIME, &ts) < 0) { + bb_perror_msg("can't set date"); + } + } +diff --git a/libbb/missing_syscalls.c b/libbb/missing_syscalls.c +index 87cf59b3d..dc40d9155 100644 +--- a/libbb/missing_syscalls.c ++++ b/libbb/missing_syscalls.c +@@ -15,14 +15,6 @@ pid_t getsid(pid_t pid) + return syscall(__NR_getsid, pid); + } + +-int stime(const time_t *t) +-{ +- struct timeval tv; +- tv.tv_sec = *t; +- tv.tv_usec = 0; +- return settimeofday(&tv, NULL); +-} +- + int sethostname(const char *name, size_t len) + { + return syscall(__NR_sethostname, name, len); +diff --git a/util-linux/rdate.c b/util-linux/rdate.c +index 70f829e7f..878375d78 100644 +--- a/util-linux/rdate.c ++++ b/util-linux/rdate.c +@@ -95,9 +95,13 @@ int rdate_main(int argc UNUSED_PARAM, char **argv) + if (!(flags & 2)) { /* no -p (-s may be present) */ + if (time(NULL) == remote_time) + bb_error_msg("current time matches remote time"); +- else +- if (stime(&remote_time) < 0) ++ else { ++ struct timespec ts; ++ ts.tv_sec = remote_time; ++ ts.tv_nsec = 0; ++ if (clock_settime(CLOCK_REALTIME, &ts) < 0) + bb_perror_msg_and_die("can't set time of day"); ++ } + } + + if (flags != 1) /* not lone -s */ +-- +2.25.1 + diff --git a/src/ci/docker/disabled/riscv64gc-linux/Dockerfile b/src/ci/docker/disabled/riscv64gc-linux/Dockerfile new file mode 100644 index 0000000000000..f21dc2ba309b8 --- /dev/null +++ b/src/ci/docker/disabled/riscv64gc-linux/Dockerfile @@ -0,0 +1,102 @@ +# based on armhf-gnu/Dockerfile +FROM ubuntu:20.04 + +RUN echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections +RUN apt-get update -y && apt-get install -y --no-install-recommends \ + bc \ + bison \ + ca-certificates \ + cmake \ + cpio \ + curl \ + debian-ports-archive-keyring \ + debootstrap \ + flex \ + gcc \ + gcc-riscv64-linux-gnu \ + git \ + g++-riscv64-linux-gnu \ + g++ \ + libc6-dev \ + libc6-dev-riscv64-cross \ + make \ + patch \ + python3 \ + qemu-system-misc \ + xz-utils + +ENV ARCH=riscv +ENV CROSS_COMPILE=riscv64-linux-gnu- + +WORKDIR /build + +# From https://github.com/michaeljclark/busybear-linux/blob/master/conf/linux.config +COPY riscv64gc-linux/linux.config /build + +# Compile the kernel that we're going to be emulating with. This is +# basically just done to be compatible with the QEMU target that we're going +# to be using when running tests. +RUN curl https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.6.16.tar.xz | tar xJf - && \ + cp linux.config linux-5.6.16/.config && \ + cd /build/linux-5.6.16 && \ + make olddefconfig && \ + make -j$(nproc) vmlinux +RUN cp linux-5.6.16/vmlinux /tmp +RUN rm -rf linux-5.6.16 + +# Compile an instance of busybox as this provides a lightweight system and init +# binary which we will boot into. Only trick here is configuring busybox to +# build static binaries. +RUN curl https://busybox.net/downloads/busybox-1.31.1.tar.bz2 | tar xjf - +COPY riscv64gc-linux/0001-Remove-stime-function-calls.patch /build/busybox-1.31.1/ +RUN cd /build/busybox-1.31.1 && \ + patch -p1 -i 0001-Remove-stime-function-calls.patch && \ + make defconfig && \ + sed -i 's/.*CONFIG_STATIC.*/CONFIG_STATIC=y/' .config && \ + make -j$(nproc) && \ + make install && \ + mv _install /tmp/rootfs && \ + cd /build && \ + rm -rf busybox-1.31.1 + +# Download the ubuntu rootfs, which we'll use as a chroot for all our tests +# This is only needed to provide /lib/* and /usr/lib/* +WORKDIR /tmp +RUN debootstrap --variant=minbase --arch=riscv64 --foreign focal /tmp/rootfs/ubuntu +RUN cd rootfs && mkdir proc sys dev etc etc/init.d +# rootfs/ubuntu/proc is in a weird state (access fails with ELOOP) until +# rootfs/ubuntu/debootstrap/debootstrap --second-stage is run (under emulation), +# but this takes ages. Instead hack it into a good enough state. +# /proc is used by std::env::current_exe() (which is roughly +# `readlink /proc/self/exe`) +RUN cd rootfs/ubuntu && rm -rf proc && mkdir proc + +# Copy over our init script, which starts up our test server and also a few other +# misc tasks +COPY scripts/qemu-bare-bones-rcS rootfs/etc/init.d/rcS +RUN chmod +x rootfs/etc/init.d/rcS + +# Helper to quickly fill the entropy pool in the kernel +COPY scripts/qemu-bare-bones-addentropy.c /tmp/addentropy.c +RUN riscv64-linux-gnu-gcc addentropy.c -o rootfs/addentropy -static + +# download and build the riscv bootloader +RUN git clone https://github.com/riscv/riscv-pk +WORKDIR /tmp/riscv-pk +# nothing special about this revision: it is just master at the time of writing +# v1.0.0 doesn't build +RUN git checkout 5d9ed238e1cabfbca3c47f50d32894ce94bfc304 +RUN mkdir build && cd build && \ + ../configure --with-payload=/tmp/vmlinux --host=riscv64-linux-gnu && \ + make -j$(nproc) && \ + cp bbl /tmp +WORKDIR /tmp +RUN rm -rf /tmp/riscv-pk + +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh + +ENV RUST_CONFIGURE_ARGS --qemu-riscv64-rootfs=/tmp/rootfs +ENV SCRIPT python3 ../x.py test --target riscv64gc-unknown-linux-gnu + +ENV NO_CHANGE_USER=1 diff --git a/src/ci/docker/disabled/riscv64gc-linux/linux.config b/src/ci/docker/disabled/riscv64gc-linux/linux.config new file mode 100644 index 0000000000000..5142664742f20 --- /dev/null +++ b/src/ci/docker/disabled/riscv64gc-linux/linux.config @@ -0,0 +1,51 @@ +CONFIG_DEFAULT_HOSTNAME="busybear" +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_CGROUPS=y +CONFIG_CGROUP_SCHED=y +CONFIG_CFS_BANDWIDTH=y +CONFIG_CGROUP_BPF=y +CONFIG_NAMESPACES=y +CONFIG_USER_NS=y +CONFIG_CHECKPOINT_RESTORE=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_EXPERT=y +CONFIG_BPF_SYSCALL=y +CONFIG_SMP=y +CONFIG_MODULES=y +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_PACKET_DIAG=y +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_NETLINK_DIAG=y +# CONFIG_WIRELESS is not set +CONFIG_PCI=y +CONFIG_DEVTMPFS=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_VIRTIO_BLK=y +CONFIG_NETDEVICES=y +CONFIG_VIRTIO_NET=y +# CONFIG_ETHERNET is not set +# CONFIG_WLAN is not set +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_HVC_RISCV_SBI=y +# CONFIG_HW_RANDOM is not set +# CONFIG_USB_SUPPORT is not set +CONFIG_VIRTIO_MMIO=y +CONFIG_SIFIVE_PLIC=y +CONFIG_RAS=y +CONFIG_EXT2_FS=y +CONFIG_EXT3_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_AUTOFS4_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_TMPFS=y +# CONFIG_CRYPTO_ECHAINIV is not set +# CONFIG_CRYPTO_HW is not set +CONFIG_PRINTK_TIME=y diff --git a/src/ci/docker/dist-aarch64-linux/Dockerfile b/src/ci/docker/dist-aarch64-linux/Dockerfile index 74766dc970d9f..fd764965ef21b 100644 --- a/src/ci/docker/dist-aarch64-linux/Dockerfile +++ b/src/ci/docker/dist-aarch64-linux/Dockerfile @@ -35,5 +35,6 @@ ENV HOSTS=aarch64-unknown-linux-gnu ENV RUST_CONFIGURE_ARGS \ --enable-full-tools \ --enable-profiler \ + --enable-sanitizers \ --disable-docs ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $HOSTS diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml index a052d0879a3db..daa2d55c04399 100644 --- a/src/ci/github-actions/ci.yml +++ b/src/ci/github-actions/ci.yml @@ -281,11 +281,6 @@ jobs: - name: dist-x86_64-linux <<: *job-linux-xl - - name: dist-x86_64-linux-alt - env: - IMAGE: dist-x86_64-linux - <<: *job-linux-xl - auto: <<: *base-ci-job name: auto diff --git a/src/doc/unstable-book/src/compiler-flags/control-flow-guard.md b/src/doc/unstable-book/src/compiler-flags/control-flow-guard.md index 48dea213e8cee..4115825e92083 100644 --- a/src/doc/unstable-book/src/compiler-flags/control-flow-guard.md +++ b/src/doc/unstable-book/src/compiler-flags/control-flow-guard.md @@ -1,10 +1,10 @@ -# `control_flow_guard` +# `control-flow-guard` The tracking issue for this feature is: [#68793](https://github.com/rust-lang/rust/issues/68793). ------------------------ -The rustc flag `-Z control_flow_guard=checks` enables the Windows [Control Flow Guard](https://docs.microsoft.com/en-us/windows/win32/secbp/control-flow-guard) (CFG) platform security feature. +The rustc flag `-Z control-flow-guard` enables the Windows [Control Flow Guard](https://docs.microsoft.com/en-us/windows/win32/secbp/control-flow-guard) (CFG) platform security feature. CFG is an exploit mitigation designed to enforce control-flow integrity for software running on supported Windows platforms (Windows 8.1 onwards). Specifically, CFG uses runtime checks to validate the target address of every indirect call/jump before allowing the call to complete. @@ -29,7 +29,7 @@ The CFG checks and metadata can potentially increase binary size and runtime ove ## Testing Control Flow Guard -The rustc flag `-Z control_flow_guard=nochecks` instructs LLVM to emit the list of valid call targets without inserting runtime checks. This flag should only be used for testing purposes as it does not provide security enforcement. +The rustc flag `-Z control-flow-guard=nochecks` instructs LLVM to emit the list of valid call targets without inserting runtime checks. This flag should only be used for testing purposes as it does not provide security enforcement. ## Control Flow Guard in libraries @@ -44,14 +44,14 @@ For example: ```cmd rustup toolchain install --force nightly rustup component add rust-src -SET RUSTFLAGS=-Z control_flow_guard=checks +SET RUSTFLAGS=-Z control-flow-guard cargo +nightly build -Z build-std --target x86_64-pc-windows-msvc ``` ```PowerShell rustup toolchain install --force nightly rustup component add rust-src -$Env:RUSTFLAGS = "-Z control_flow_guard=checks" +$Env:RUSTFLAGS = "-Z control-flow-guard" cargo +nightly build -Z build-std --target x86_64-pc-windows-msvc ``` diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index 8a957a729fb68..0338aff509658 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -33,9 +33,9 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::interpret::truncate; use rustc_middle::mir::{self, Field, GeneratorLayout}; use rustc_middle::ty::layout::{self, IntegerExt, PrimitiveExt, TyAndLayout}; -use rustc_middle::ty::subst::{GenericArgKind, SubstsRef}; +use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::Instance; -use rustc_middle::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt}; +use rustc_middle::ty::{self, AdtKind, GeneratorSubsts, ParamEnv, Ty, TyCtxt}; use rustc_middle::{bug, span_bug}; use rustc_session::config::{self, DebugInfo}; use rustc_span::symbol::{Interner, Symbol}; @@ -392,6 +392,7 @@ fn vec_slice_metadata( align: pointer_align, flags: DIFlags::FlagZero, discriminant: None, + source_info: None, }, MemberDescription { name: "length".to_owned(), @@ -401,6 +402,7 @@ fn vec_slice_metadata( align: usize_align, flags: DIFlags::FlagZero, discriminant: None, + source_info: None, }, ]; @@ -508,6 +510,7 @@ fn trait_pointer_metadata( align: data_ptr_field.align.abi, flags: DIFlags::FlagArtificial, discriminant: None, + source_info: None, }, MemberDescription { name: "vtable".to_owned(), @@ -517,6 +520,7 @@ fn trait_pointer_metadata( align: vtable_field.align.abi, flags: DIFlags::FlagArtificial, discriminant: None, + source_info: None, }, ]; @@ -859,7 +863,7 @@ fn foreign_type_metadata( debug!("foreign_type_metadata: {:?}", t); let name = compute_debuginfo_type_name(cx.tcx, t, false); - create_struct_stub(cx, t, &name, unique_type_id, NO_SCOPE_METADATA) + create_struct_stub(cx, t, &name, unique_type_id, NO_SCOPE_METADATA, DIFlags::FlagZero) } fn pointer_type_metadata( @@ -1026,6 +1030,12 @@ impl MetadataCreationResult<'ll> { } } +#[derive(Debug)] +struct SourceInfo<'ll> { + file: &'ll DIFile, + line: u32, +} + /// Description of a type member, which can either be a regular field (as in /// structs or tuples) or an enum variant. #[derive(Debug)] @@ -1037,6 +1047,7 @@ struct MemberDescription<'ll> { align: Align, flags: DIFlags, discriminant: Option, + source_info: Option>, } impl<'ll> MemberDescription<'ll> { @@ -1045,14 +1056,18 @@ impl<'ll> MemberDescription<'ll> { cx: &CodegenCx<'ll, '_>, composite_type_metadata: &'ll DIScope, ) -> &'ll DIType { + let (file, line) = self + .source_info + .map(|info| (info.file, info.line)) + .unwrap_or_else(|| (unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER)); unsafe { llvm::LLVMRustDIBuilderCreateVariantMemberType( DIB(cx), composite_type_metadata, self.name.as_ptr().cast(), self.name.len(), - unknown_file_metadata(cx), - UNKNOWN_LINE_NUMBER, + file, + line, self.size.bits(), self.align.bits() as u32, self.offset.bits(), @@ -1124,6 +1139,7 @@ impl<'tcx> StructMemberDescriptionFactory<'tcx> { align: field.align.abi, flags: DIFlags::FlagZero, discriminant: None, + source_info: None, } }) .collect() @@ -1145,8 +1161,14 @@ fn prepare_struct_metadata( let containing_scope = get_namespace_for_item(cx, struct_def_id); - let struct_metadata_stub = - create_struct_stub(cx, struct_type, &struct_name, unique_type_id, Some(containing_scope)); + let struct_metadata_stub = create_struct_stub( + cx, + struct_type, + &struct_name, + unique_type_id, + Some(containing_scope), + DIFlags::FlagZero, + ); create_and_register_recursive_type_forward_declaration( cx, @@ -1185,6 +1207,7 @@ impl<'tcx> TupleMemberDescriptionFactory<'tcx> { align, flags: DIFlags::FlagZero, discriminant: None, + source_info: None, } }) .collect() @@ -1201,8 +1224,14 @@ fn prepare_tuple_metadata( ) -> RecursiveTypeDescription<'ll, 'tcx> { let tuple_name = compute_debuginfo_type_name(cx.tcx, tuple_type, false); - let struct_stub = - create_struct_stub(cx, tuple_type, &tuple_name[..], unique_type_id, containing_scope); + let struct_stub = create_struct_stub( + cx, + tuple_type, + &tuple_name[..], + unique_type_id, + containing_scope, + DIFlags::FlagZero, + ); create_and_register_recursive_type_forward_declaration( cx, @@ -1244,6 +1273,7 @@ impl<'tcx> UnionMemberDescriptionFactory<'tcx> { align: field.align.abi, flags: DIFlags::FlagZero, discriminant: None, + source_info: None, } }) .collect() @@ -1351,11 +1381,11 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { let variant_info_for = |index: VariantIdx| match self.enum_type.kind { ty::Adt(adt, _) => VariantInfo::Adt(&adt.variants[index]), - ty::Generator(_, substs, _) => { + ty::Generator(def_id, _, _) => { let (generator_layout, generator_saved_local_names) = generator_variant_info_data.as_ref().unwrap(); VariantInfo::Generator { - substs, + def_id, generator_layout: *generator_layout, generator_saved_local_names, variant_index: index, @@ -1371,6 +1401,10 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { } else { type_metadata(cx, self.enum_type, self.span) }; + let flags = match self.enum_type.kind { + ty::Generator(..) => DIFlags::FlagArtificial, + _ => DIFlags::FlagZero, + }; match self.layout.variants { Variants::Single { index } => { @@ -1404,8 +1438,9 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { offset: Size::ZERO, size: self.layout.size, align: self.layout.align.abi, - flags: DIFlags::FlagZero, + flags, discriminant: None, + source_info: variant_info.source_info(cx), }] } Variants::Multiple { @@ -1457,11 +1492,12 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { offset: Size::ZERO, size: self.layout.size, align: self.layout.align.abi, - flags: DIFlags::FlagZero, + flags, discriminant: Some( self.layout.ty.discriminant_for_variant(cx.tcx, i).unwrap().val as u64, ), + source_info: variant_info.source_info(cx), } }) .collect() @@ -1527,7 +1563,8 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { self.layout.fields.offset(tag_field), self.layout.field(cx, tag_field).size, ); - variant_info_for(*niche_variants.start()).map_struct_name(|variant_name| { + let variant_info = variant_info_for(*niche_variants.start()); + variant_info.map_struct_name(|variant_name| { name.push_str(variant_name); }); @@ -1538,8 +1575,9 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { offset: Size::ZERO, size: variant.size, align: variant.align.abi, - flags: DIFlags::FlagZero, + flags, discriminant: None, + source_info: variant_info.source_info(cx), }] } else { variants @@ -1587,8 +1625,9 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { offset: Size::ZERO, size: self.layout.size, align: self.layout.align.abi, - flags: DIFlags::FlagZero, + flags, discriminant: niche_value, + source_info: variant_info.source_info(cx), } }) .collect() @@ -1631,6 +1670,7 @@ impl VariantMemberDescriptionFactory<'ll, 'tcx> { align, flags: DIFlags::FlagZero, discriminant: None, + source_info: None, } }) .collect() @@ -1651,7 +1691,7 @@ enum EnumTagInfo<'ll> { enum VariantInfo<'a, 'tcx> { Adt(&'tcx ty::VariantDef), Generator { - substs: SubstsRef<'tcx>, + def_id: DefId, generator_layout: &'tcx GeneratorLayout<'tcx>, generator_saved_local_names: &'a IndexVec>, variant_index: VariantIdx, @@ -1662,8 +1702,8 @@ impl<'tcx> VariantInfo<'_, 'tcx> { fn map_struct_name(&self, f: impl FnOnce(&str) -> R) -> R { match self { VariantInfo::Adt(variant) => f(&variant.ident.as_str()), - VariantInfo::Generator { substs, variant_index, .. } => { - f(&substs.as_generator().variant_name(*variant_index)) + VariantInfo::Generator { variant_index, .. } => { + f(&GeneratorSubsts::variant_name(*variant_index)) } } } @@ -1699,6 +1739,32 @@ impl<'tcx> VariantInfo<'_, 'tcx> { }; field_name.map(|name| name.to_string()).unwrap_or_else(|| format!("__{}", i)) } + + fn source_info(&self, cx: &CodegenCx<'ll, 'tcx>) -> Option> { + match self { + VariantInfo::Generator { def_id, variant_index, .. } => { + let span = + cx.tcx.generator_layout(*def_id).variant_source_info[*variant_index].span; + if !span.is_dummy() { + let loc = cx.lookup_debug_loc(span.lo()); + return Some(SourceInfo { + file: file_metadata(cx, &loc.file, def_id.krate), + line: loc.line.unwrap_or(UNKNOWN_LINE_NUMBER), + }); + } + } + _ => {} + } + None + } + + #[allow(dead_code)] + fn is_artificial(&self) -> bool { + match self { + VariantInfo::Generator { .. } => true, + VariantInfo::Adt(..) => false, + } + } } /// Returns a tuple of (1) `type_metadata_stub` of the variant, (2) a @@ -1718,7 +1784,15 @@ fn describe_enum_variant( .type_map .borrow_mut() .get_unique_type_id_of_enum_variant(cx, layout.ty, &variant_name); - create_struct_stub(cx, layout.ty, &variant_name, unique_type_id, Some(containing_scope)) + create_struct_stub( + cx, + layout.ty, + &variant_name, + unique_type_id, + Some(containing_scope), + // FIXME(tmandry): This doesn't seem to have any effect. + if variant.is_artificial() { DIFlags::FlagArtificial } else { DIFlags::FlagZero }, + ) }); // Build an array of (field name, field type) pairs to be captured in the factory closure. @@ -1778,7 +1852,13 @@ fn prepare_enum_metadata( span: Span, outer_field_tys: Vec>, ) -> RecursiveTypeDescription<'ll, 'tcx> { - let enum_name = compute_debuginfo_type_name(cx.tcx, enum_type, false); + let tcx = cx.tcx; + let enum_name = compute_debuginfo_type_name(tcx, enum_type, false); + // FIXME(tmandry): This doesn't seem to have any effect. + let enum_flags = match enum_type.kind { + ty::Generator(..) => DIFlags::FlagArtificial, + _ => DIFlags::FlagZero, + }; let containing_scope = get_namespace_for_item(cx, enum_def_id); // FIXME: This should emit actual file metadata for the enum, but we @@ -1792,7 +1872,7 @@ fn prepare_enum_metadata( let discriminant_type_metadata = |discr: Primitive| { let enumerators_metadata: Vec<_> = match enum_type.kind { ty::Adt(def, _) => def - .discriminants(cx.tcx) + .discriminants(tcx) .zip(&def.variants) .map(|((_, discr), v)| { let name = v.ident.as_str(); @@ -1815,15 +1895,16 @@ fn prepare_enum_metadata( .collect(), ty::Generator(_, substs, _) => substs .as_generator() - .variant_range(enum_def_id, cx.tcx) + .variant_range(enum_def_id, tcx) .map(|variant_index| { - let name = substs.as_generator().variant_name(variant_index); + debug_assert_eq!(tcx.types.u32, substs.as_generator().discr_ty(tcx)); + let name = GeneratorSubsts::variant_name(variant_index); unsafe { Some(llvm::LLVMRustDIBuilderCreateEnumerator( DIB(cx), name.as_ptr().cast(), name.len(), - // Generators use u32 as discriminant type. + // Generators use u32 as discriminant type, verified above. variant_index.as_u32().into(), true, // IsUnsigned )) @@ -1841,12 +1922,12 @@ fn prepare_enum_metadata( None => { let (discriminant_size, discriminant_align) = (discr.size(cx), discr.align(cx)); let discriminant_base_type_metadata = - type_metadata(cx, discr.to_ty(cx.tcx), rustc_span::DUMMY_SP); + type_metadata(cx, discr.to_ty(tcx), rustc_span::DUMMY_SP); let item_name; let discriminant_name = match enum_type.kind { ty::Adt(..) => { - item_name = cx.tcx.item_name(enum_def_id).as_str(); + item_name = tcx.item_name(enum_def_id).as_str(); &*item_name } ty::Generator(..) => enum_name.as_str(), @@ -1912,7 +1993,7 @@ fn prepare_enum_metadata( UNKNOWN_LINE_NUMBER, layout.size.bits(), layout.align.abi.bits() as u32, - DIFlags::FlagZero, + enum_flags, None, 0, // RuntimeLang unique_type_id_str.as_ptr().cast(), @@ -2033,7 +2114,7 @@ fn prepare_enum_metadata( UNKNOWN_LINE_NUMBER, layout.size.bits(), layout.align.abi.bits() as u32, - DIFlags::FlagZero, + enum_flags, discriminator_metadata, empty_array, variant_part_unique_type_id_str.as_ptr().cast(), @@ -2059,7 +2140,7 @@ fn prepare_enum_metadata( UNKNOWN_LINE_NUMBER, layout.size.bits(), layout.align.abi.bits() as u32, - DIFlags::FlagZero, + enum_flags, None, type_array, 0, @@ -2110,6 +2191,7 @@ fn composite_type_metadata( composite_type_name, composite_type_unique_id, containing_scope, + DIFlags::FlagZero, ); // ... and immediately create and add the member descriptions. set_members_of_composite_type(cx, composite_type, composite_type_metadata, member_descriptions); @@ -2211,6 +2293,7 @@ fn create_struct_stub( struct_type_name: &str, unique_type_id: UniqueTypeId, containing_scope: Option<&'ll DIScope>, + flags: DIFlags, ) -> &'ll DICompositeType { let (struct_size, struct_align) = cx.size_and_align_of(struct_type); @@ -2232,7 +2315,7 @@ fn create_struct_stub( UNKNOWN_LINE_NUMBER, struct_size.bits(), struct_align.bits() as u32, - DIFlags::FlagZero, + flags, None, empty_array, 0, diff --git a/src/librustc_codegen_llvm/type_of.rs b/src/librustc_codegen_llvm/type_of.rs index 77009aca6d32e..5a0da6be5980e 100644 --- a/src/librustc_codegen_llvm/type_of.rs +++ b/src/librustc_codegen_llvm/type_of.rs @@ -70,10 +70,10 @@ fn uncached_llvm_type<'a, 'tcx>( write!(&mut name, "::{}", def.variants[index].ident).unwrap(); } } - if let (&ty::Generator(_, substs, _), &Variants::Single { index }) + if let (&ty::Generator(_, _, _), &Variants::Single { index }) = (&layout.ty.kind, &layout.variants) { - write!(&mut name, "::{}", substs.as_generator().variant_name(index)).unwrap(); + write!(&mut name, "::{}", ty::GeneratorSubsts::variant_name(index)).unwrap(); } Some(name) } diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index c7a58d9f2a2f6..6c995be913c9e 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -804,7 +804,10 @@ fn link_sanitizer_runtime(sess: &Session, linker: &mut dyn Linker, name: &str) { linker.args(&["-Wl,-rpath", "-Xlinker", rpath]); linker.link_dylib(Symbol::intern(&libname)); } - "x86_64-unknown-linux-gnu" | "x86_64-fuchsia" | "aarch64-fuchsia" => { + "aarch64-fuchsia" + | "aarch64-unknown-linux-gnu" + | "x86_64-fuchsia" + | "x86_64-unknown-linux-gnu" => { let filename = format!("librustc{}_rt.{}.a", channel, name); let path = default_tlib.join(&filename); linker.link_whole_rlib(&path); diff --git a/src/librustc_index/bit_set.rs b/src/librustc_index/bit_set.rs index 46c38840516e2..cb8b30830c5de 100644 --- a/src/librustc_index/bit_set.rs +++ b/src/librustc_index/bit_set.rs @@ -700,7 +700,7 @@ impl GrowableBitSet { /// /// All operations that involve a row and/or column index will panic if the /// index exceeds the relevant bound. -#[derive(Clone, Debug, Eq, PartialEq, RustcDecodable, RustcEncodable)] +#[derive(Clone, Eq, PartialEq, RustcDecodable, RustcEncodable)] pub struct BitMatrix { num_rows: usize, num_columns: usize, @@ -876,6 +876,22 @@ impl BitMatrix { } } +impl fmt::Debug for BitMatrix { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + /// Forces its contents to print in regular mode instead of alternate mode. + struct OneLinePrinter(T); + impl fmt::Debug for OneLinePrinter { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(fmt, "{:?}", self.0) + } + } + + write!(fmt, "BitMatrix({}x{}) ", self.num_rows, self.num_columns)?; + let items = self.rows().flat_map(|r| self.iter(r).map(move |c| (r, c))); + fmt.debug_set().entries(items.map(OneLinePrinter)).finish() + } +} + /// A fixed-column-size, variable-row-size 2D bit matrix with a moderately /// sparse representation. /// diff --git a/src/librustc_interface/tests.rs b/src/librustc_interface/tests.rs index a832c2decaaf6..d861b444c8816 100644 --- a/src/librustc_interface/tests.rs +++ b/src/librustc_interface/tests.rs @@ -465,7 +465,6 @@ fn test_debugging_options_tracking_hash() { untracked!(ast_json_noexpand, true); untracked!(borrowck, String::from("other")); untracked!(borrowck_stats, true); - untracked!(control_flow_guard, CFGuard::Checks); untracked!(deduplicate_diagnostics, true); untracked!(dep_tasks, true); untracked!(dont_buffer_diagnostics, true); @@ -539,6 +538,7 @@ fn test_debugging_options_tracking_hash() { tracked!(binary_dep_depinfo, true); tracked!(chalk, true); tracked!(codegen_backend, Some("abc".to_string())); + tracked!(control_flow_guard, CFGuard::Checks); tracked!(crate_attr, vec!["abc".to_string()]); tracked!(debug_macros, true); tracked!(dep_info_omit_d_target, true); diff --git a/src/librustc_metadata/rmeta/decoder.rs b/src/librustc_metadata/rmeta/decoder.rs index 0335aa8358c3c..800f794121ab3 100644 --- a/src/librustc_metadata/rmeta/decoder.rs +++ b/src/librustc_metadata/rmeta/decoder.rs @@ -565,6 +565,7 @@ impl MetadataBlob { impl EntryKind { fn def_kind(&self) -> DefKind { match *self { + EntryKind::AnonConst(..) => DefKind::AnonConst, EntryKind::Const(..) => DefKind::Const, EntryKind::AssocConst(..) => DefKind::AssocConst, EntryKind::ImmStatic @@ -1121,7 +1122,8 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { fn mir_const_qualif(&self, id: DefIndex) -> mir::ConstQualifs { match self.kind(id) { - EntryKind::Const(qualif, _) + EntryKind::AnonConst(qualif, _) + | EntryKind::Const(qualif, _) | EntryKind::AssocConst( AssocContainer::ImplDefault | AssocContainer::ImplFinal @@ -1340,7 +1342,9 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { fn get_rendered_const(&self, id: DefIndex) -> String { match self.kind(id) { - EntryKind::Const(_, data) | EntryKind::AssocConst(_, _, data) => data.decode(self).0, + EntryKind::AnonConst(_, data) + | EntryKind::Const(_, data) + | EntryKind::AssocConst(_, _, data) => data.decode(self).0, _ => bug!(), } } diff --git a/src/librustc_metadata/rmeta/encoder.rs b/src/librustc_metadata/rmeta/encoder.rs index d797e6d4a34af..31821ea459f1b 100644 --- a/src/librustc_metadata/rmeta/encoder.rs +++ b/src/librustc_metadata/rmeta/encoder.rs @@ -1358,7 +1358,7 @@ impl EncodeContext<'tcx> { let const_data = self.encode_rendered_const_for_body(body_id); let qualifs = self.tcx.mir_const_qualif(def_id); - record!(self.tables.kind[def_id.to_def_id()] <- EntryKind::Const(qualifs, const_data)); + record!(self.tables.kind[def_id.to_def_id()] <- EntryKind::AnonConst(qualifs, const_data)); record!(self.tables.visibility[def_id.to_def_id()] <- ty::Visibility::Public); record!(self.tables.span[def_id.to_def_id()] <- self.tcx.def_span(def_id)); self.encode_item_type(def_id.to_def_id()); diff --git a/src/librustc_metadata/rmeta/mod.rs b/src/librustc_metadata/rmeta/mod.rs index ec80a2b6171ed..381e7ee115e17 100644 --- a/src/librustc_metadata/rmeta/mod.rs +++ b/src/librustc_metadata/rmeta/mod.rs @@ -281,6 +281,7 @@ define_tables! { #[derive(Copy, Clone, RustcEncodable, RustcDecodable)] enum EntryKind { + AnonConst(mir::ConstQualifs, Lazy), Const(mir::ConstQualifs, Lazy), ImmStatic, MutStatic, diff --git a/src/librustc_middle/mir/query.rs b/src/librustc_middle/mir/query.rs index 1aae97cc2a894..9ad79230a4f6d 100644 --- a/src/librustc_middle/mir/query.rs +++ b/src/librustc_middle/mir/query.rs @@ -10,6 +10,8 @@ use rustc_index::vec::IndexVec; use rustc_span::{Span, Symbol}; use rustc_target::abi::VariantIdx; use smallvec::SmallVec; +use std::cell::Cell; +use std::fmt::{self, Debug}; use super::{Field, SourceInfo}; @@ -58,7 +60,7 @@ rustc_index::newtype_index! { } /// The layout of generator state. -#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)] +#[derive(Clone, RustcEncodable, RustcDecodable, HashStable, TypeFoldable)] pub struct GeneratorLayout<'tcx> { /// The type of every local stored inside the generator. pub field_tys: IndexVec>, @@ -67,12 +69,72 @@ pub struct GeneratorLayout<'tcx> { /// be stored in multiple variants. pub variant_fields: IndexVec>, + /// The source that led to each variant being created (usually, a yield or + /// await). + pub variant_source_info: IndexVec, + /// Which saved locals are storage-live at the same time. Locals that do not /// have conflicts with each other are allowed to overlap in the computed /// layout. pub storage_conflicts: BitMatrix, } +impl Debug for GeneratorLayout<'_> { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + /// Prints an iterator of (key, value) tuples as a map. + struct MapPrinter<'a, K, V>(Cell + 'a>>>); + impl<'a, K, V> MapPrinter<'a, K, V> { + fn new(iter: impl Iterator + 'a) -> Self { + Self(Cell::new(Some(Box::new(iter)))) + } + } + impl<'a, K: Debug, V: Debug> Debug for MapPrinter<'a, K, V> { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt.debug_map().entries(self.0.take().unwrap()).finish() + } + } + + /// Prints the generator variant name. + struct GenVariantPrinter(VariantIdx); + impl From for GenVariantPrinter { + fn from(idx: VariantIdx) -> Self { + GenVariantPrinter(idx) + } + } + impl Debug for GenVariantPrinter { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + let variant_name = ty::GeneratorSubsts::variant_name(self.0); + if fmt.alternate() { + write!(fmt, "{:9}({:?})", variant_name, self.0) + } else { + write!(fmt, "{}", variant_name) + } + } + } + + /// Forces its contents to print in regular mode instead of alternate mode. + struct OneLinePrinter(T); + impl Debug for OneLinePrinter { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(fmt, "{:?}", self.0) + } + } + + fmt.debug_struct("GeneratorLayout") + .field("field_tys", &MapPrinter::new(self.field_tys.iter_enumerated())) + .field( + "variant_fields", + &MapPrinter::new( + self.variant_fields + .iter_enumerated() + .map(|(k, v)| (GenVariantPrinter(k), OneLinePrinter(v))), + ), + ) + .field("storage_conflicts", &self.storage_conflicts) + .finish() + } +} + #[derive(Debug, RustcEncodable, RustcDecodable, HashStable)] pub struct BorrowCheckResult<'tcx> { /// All the opaque types that are restricted to concrete types diff --git a/src/librustc_middle/ty/sty.rs b/src/librustc_middle/ty/sty.rs index b0addcb2bb683..f64818ed12c18 100644 --- a/src/librustc_middle/ty/sty.rs +++ b/src/librustc_middle/ty/sty.rs @@ -522,8 +522,7 @@ impl<'tcx> GeneratorSubsts<'tcx> { /// Calls `f` with a reference to the name of the enumerator for the given /// variant `v`. - #[inline] - pub fn variant_name(self, v: VariantIdx) -> Cow<'static, str> { + pub fn variant_name(v: VariantIdx) -> Cow<'static, str> { match v.as_usize() { Self::UNRESUMED => Cow::from(Self::UNRESUMED_NAME), Self::RETURNED => Cow::from(Self::RETURNED_NAME), diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index c8702eeae1d5b..c7d8077d085b2 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -426,6 +426,9 @@ struct LivenessInfo { /// The set of saved locals live at each suspension point. live_locals_at_suspension_points: Vec>, + /// Parallel vec to the above with SourceInfo for each yield terminator. + source_info_at_suspension_points: Vec, + /// For every saved local, the set of other saved locals that are /// storage-live at the same time as this local. We cannot overlap locals in /// the layout which have conflicting storage. @@ -477,6 +480,7 @@ fn locals_live_across_suspend_points( let mut storage_liveness_map = IndexVec::from_elem(None, body.basic_blocks()); let mut live_locals_at_suspension_points = Vec::new(); + let mut source_info_at_suspension_points = Vec::new(); let mut live_locals_at_any_suspension_point = BitSet::new_empty(body.local_decls.len()); for (block, data) in body.basic_blocks().iter_enumerated() { @@ -522,6 +526,7 @@ fn locals_live_across_suspend_points( live_locals_at_any_suspension_point.union(&live_locals); live_locals_at_suspension_points.push(live_locals); + source_info_at_suspension_points.push(data.terminator().source_info); } } debug!("live_locals_anywhere = {:?}", live_locals_at_any_suspension_point); @@ -543,6 +548,7 @@ fn locals_live_across_suspend_points( LivenessInfo { live_locals: live_locals_at_any_suspension_point, live_locals_at_suspension_points, + source_info_at_suspension_points, storage_conflicts, storage_liveness: storage_liveness_map, } @@ -740,6 +746,7 @@ fn compute_layout<'tcx>( let LivenessInfo { live_locals, live_locals_at_suspension_points, + source_info_at_suspension_points, storage_conflicts, storage_liveness, } = locals_live_across_suspend_points(tcx, body, source, always_live_locals, movable); @@ -756,7 +763,18 @@ fn compute_layout<'tcx>( } // Leave empty variants for the UNRESUMED, RETURNED, and POISONED states. + // In debuginfo, these will correspond to the beginning (UNRESUMED) or end + // (RETURNED, POISONED) of the function. const RESERVED_VARIANTS: usize = 3; + let body_span = body.source_scopes[OUTERMOST_SOURCE_SCOPE].span; + let mut variant_source_info: IndexVec = [ + SourceInfo::outermost(body_span.shrink_to_lo()), + SourceInfo::outermost(body_span.shrink_to_hi()), + SourceInfo::outermost(body_span.shrink_to_hi()), + ] + .iter() + .copied() + .collect(); // Build the generator variant field list. // Create a map from local indices to generator struct indices. @@ -775,11 +793,13 @@ fn compute_layout<'tcx>( remap.entry(locals[saved_local]).or_insert((tys[saved_local], variant_index, idx)); } variant_fields.push(fields); + variant_source_info.push(source_info_at_suspension_points[suspension_point_idx]); } debug!("generator variant_fields = {:?}", variant_fields); debug!("generator storage_conflicts = {:#?}", storage_conflicts); - let layout = GeneratorLayout { field_tys: tys, variant_fields, storage_conflicts }; + let layout = + GeneratorLayout { field_tys: tys, variant_fields, variant_source_info, storage_conflicts }; (remap, layout, storage_liveness) } diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs index 02614044063fc..db45481e4fd25 100644 --- a/src/librustc_mir/util/pretty.rs +++ b/src/librustc_mir/util/pretty.rs @@ -131,7 +131,7 @@ fn dump_matched_mir_node<'tcx, F>( } writeln!(file, " {} {}", disambiguator, pass_name)?; if let Some(ref layout) = body.generator_layout { - writeln!(file, "// generator_layout = {:?}", layout)?; + writeln!(file, "/* generator_layout = {:#?} */", layout)?; } writeln!(file)?; extra_data(PassWhere::BeforeCFG, &mut file)?; diff --git a/src/librustc_session/config.rs b/src/librustc_session/config.rs index 53cec04083696..f77bf5ddefd3f 100644 --- a/src/librustc_session/config.rs +++ b/src/librustc_session/config.rs @@ -103,7 +103,7 @@ pub enum Strip { Symbols, } -/// The different settings that the `-Z control_flow_guard` flag can have. +/// The different settings that the `-Z control-flow-guard` flag can have. #[derive(Clone, Copy, PartialEq, Hash, Debug)] pub enum CFGuard { /// Do not emit Control Flow Guard metadata or checks. diff --git a/src/librustc_session/options.rs b/src/librustc_session/options.rs index 8032909bbcd7a..6c6f27502b614 100644 --- a/src/librustc_session/options.rs +++ b/src/librustc_session/options.rs @@ -250,7 +250,8 @@ macro_rules! options { pub const parse_relro_level: &str = "one of: `full`, `partial`, or `off`"; pub const parse_sanitizers: &str = "comma separated list of sanitizers: `address`, `leak`, `memory` or `thread`"; pub const parse_sanitizer_memory_track_origins: &str = "0, 1, or 2"; - pub const parse_cfguard: &str = "either `disabled`, `nochecks`, or `checks`"; + pub const parse_cfguard: &str = + "either a boolean (`yes`, `no`, `on`, `off`, etc), `checks`, or `nochecks`"; pub const parse_strip: &str = "either `none`, `debuginfo`, or `symbols`"; pub const parse_linker_flavor: &str = ::rustc_target::spec::LinkerFlavor::one_of(); pub const parse_optimization_fuel: &str = "crate=integer"; @@ -495,12 +496,24 @@ macro_rules! options { } fn parse_cfguard(slot: &mut CFGuard, v: Option<&str>) -> bool { - match v { - Some("disabled") => *slot = CFGuard::Disabled, - Some("nochecks") => *slot = CFGuard::NoChecks, - Some("checks") => *slot = CFGuard::Checks, - _ => return false, + if v.is_some() { + let mut bool_arg = None; + if parse_opt_bool(&mut bool_arg, v) { + *slot = if bool_arg.unwrap() { + CFGuard::Checks + } else { + CFGuard::Disabled + }; + return true + } } + + *slot = match v { + None => CFGuard::Checks, + Some("checks") => CFGuard::Checks, + Some("nochecks") => CFGuard::NoChecks, + Some(_) => return false, + }; true } @@ -796,8 +809,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "enable the experimental Chalk-based trait solving engine"), codegen_backend: Option = (None, parse_opt_string, [TRACKED], "the backend to use"), - control_flow_guard: CFGuard = (CFGuard::Disabled, parse_cfguard, [UNTRACKED], - "use Windows Control Flow Guard (`disabled`, `nochecks` or `checks`)"), + control_flow_guard: CFGuard = (CFGuard::Disabled, parse_cfguard, [TRACKED], + "use Windows Control Flow Guard (default: no)"), crate_attr: Vec = (Vec::new(), parse_string_push, [TRACKED], "inject the given attribute in the crate"), debug_macros: bool = (false, parse_bool, [TRACKED], diff --git a/src/librustc_session/session.rs b/src/librustc_session/session.rs index 90cd6ae5bf99f..2ea312c42dc64 100644 --- a/src/librustc_session/session.rs +++ b/src/librustc_session/session.rs @@ -1349,11 +1349,19 @@ fn validate_commandline_args_with_session_available(sess: &Session) { ); } - const ASAN_SUPPORTED_TARGETS: &[&str] = - &["aarch64-fuchsia", "x86_64-apple-darwin", "x86_64-fuchsia", "x86_64-unknown-linux-gnu"]; - const LSAN_SUPPORTED_TARGETS: &[&str] = &["x86_64-apple-darwin", "x86_64-unknown-linux-gnu"]; - const MSAN_SUPPORTED_TARGETS: &[&str] = &["x86_64-unknown-linux-gnu"]; - const TSAN_SUPPORTED_TARGETS: &[&str] = &["x86_64-apple-darwin", "x86_64-unknown-linux-gnu"]; + const ASAN_SUPPORTED_TARGETS: &[&str] = &[ + "aarch64-fuchsia", + "aarch64-unknown-linux-gnu", + "x86_64-apple-darwin", + "x86_64-fuchsia", + "x86_64-unknown-linux-gnu", + ]; + const LSAN_SUPPORTED_TARGETS: &[&str] = + &["aarch64-unknown-linux-gnu", "x86_64-apple-darwin", "x86_64-unknown-linux-gnu"]; + const MSAN_SUPPORTED_TARGETS: &[&str] = + &["aarch64-unknown-linux-gnu", "x86_64-unknown-linux-gnu"]; + const TSAN_SUPPORTED_TARGETS: &[&str] = + &["aarch64-unknown-linux-gnu", "x86_64-apple-darwin", "x86_64-unknown-linux-gnu"]; // Sanitizers can only be used on some tested platforms. for s in sess.opts.debugging_opts.sanitizer { diff --git a/src/libstd/sys/sgx/abi/entry.S b/src/libstd/sys/sgx/abi/entry.S index 2badfc973c972..fc6ce5770338e 100644 --- a/src/libstd/sys/sgx/abi/entry.S +++ b/src/libstd/sys/sgx/abi/entry.S @@ -26,18 +26,10 @@ IMAGE_BASE: .Lxsave_clear: .org .+24 .Lxsave_mxcsr: - .int 0 + .short 0x1f80 /* We can store a bunch of data in the gap between MXCSR and the XSAVE header */ -/* MXCSR initialization value for ABI */ -.Lmxcsr_init: - .int 0x1f80 - -/* x87 FPU control word initialization value for ABI */ -.Lfpucw_init: - .int 0x037f - /* The following symbols point at read-only data that will be filled in by the */ /* post-linker. */ @@ -177,13 +169,17 @@ sgx_entry: jz .Lskip_debug_init mov %r10,%gs:tcsls_debug_panic_buf_ptr .Lskip_debug_init: +/* reset cpu state */ + mov %rdx, %r10 + mov $-1, %rax + mov $-1, %rdx + xrstor .Lxsave_clear(%rip) + mov %r10, %rdx + /* check if returning from usercall */ mov %gs:tcsls_last_rsp,%r11 test %r11,%r11 jnz .Lusercall_ret -/* reset user state */ - ldmxcsr .Lmxcsr_init(%rip) - fldcw .Lfpucw_init(%rip) /* setup stack */ mov %gs:tcsls_tos,%rsp /* initially, RSP is not set to the correct value */ /* here. This is fixed below under "adjust stack". */ diff --git a/src/libstd/sys/unix/process/process_common.rs b/src/libstd/sys/unix/process/process_common.rs index 2d7267263dedf..6e33cdd3c4826 100644 --- a/src/libstd/sys/unix/process/process_common.rs +++ b/src/libstd/sys/unix/process/process_common.rs @@ -428,6 +428,7 @@ mod tests { // ignored there. #[cfg_attr(target_arch = "arm", ignore)] #[cfg_attr(target_arch = "aarch64", ignore)] + #[cfg_attr(target_arch = "riscv64", ignore)] fn test_process_mask() { unsafe { // Test to make sure that a signal mask does not get inherited. diff --git a/src/libstd/time.rs b/src/libstd/time.rs index 295ebcbb72939..84fa35e01bb09 100644 --- a/src/libstd/time.rs +++ b/src/libstd/time.rs @@ -811,11 +811,11 @@ mod tests { // Right now for CI this test is run in an emulator, and apparently the // aarch64 emulator's sense of time is that we're still living in the - // 70s. + // 70s. This is also true for riscv (also qemu) // // Otherwise let's assume that we're all running computers later than // 2000. - if !cfg!(target_arch = "aarch64") { + if !cfg!(target_arch = "aarch64") && !cfg!(target_arch = "riscv64") { assert!(a > thirty_years); } diff --git a/src/test/codegen/cfguard_checks.rs b/src/test/codegen/cfguard_checks.rs index 40a7353eac045..96f9158f9d394 100644 --- a/src/test/codegen/cfguard_checks.rs +++ b/src/test/codegen/cfguard_checks.rs @@ -1,4 +1,4 @@ -// compile-flags: -Z control_flow_guard=checks +// compile-flags: -Z control-flow-guard=checks #![crate_type = "lib"] diff --git a/src/test/codegen/cfguard_disabled.rs b/src/test/codegen/cfguard_disabled.rs index d1747931e15c8..1325ffc0f2595 100644 --- a/src/test/codegen/cfguard_disabled.rs +++ b/src/test/codegen/cfguard_disabled.rs @@ -1,4 +1,4 @@ -// compile-flags: -Z control_flow_guard=disabled +// compile-flags: -Z control-flow-guard=no #![crate_type = "lib"] diff --git a/src/test/codegen/cfguard_nochecks.rs b/src/test/codegen/cfguard_nochecks.rs index c5d7afbae257b..ae1de4c4d26d5 100644 --- a/src/test/codegen/cfguard_nochecks.rs +++ b/src/test/codegen/cfguard_nochecks.rs @@ -1,4 +1,4 @@ -// compile-flags: -Z control_flow_guard=nochecks +// compile-flags: -Z control-flow-guard=nochecks #![crate_type = "lib"] diff --git a/src/test/codegen/generator-debug.rs b/src/test/codegen/generator-debug.rs new file mode 100644 index 0000000000000..3007099393ffe --- /dev/null +++ b/src/test/codegen/generator-debug.rs @@ -0,0 +1,94 @@ +// Verify debuginfo for generators: +// - Each variant points to the file and line of its yield point +// - The generator types and variants are marked artificial +// - Captured vars from the source are not marked artificial +// +// ignore-tidy-linelength +// compile-flags: -C debuginfo=2 --edition=2018 + +#![feature(generators, generator_trait)] +use std::ops::Generator; + +fn generator_test() -> impl Generator { + || { + yield 0; + let s = String::from("foo"); + yield 1; + } +} + +async fn foo() {} +async fn async_fn_test() { + foo().await; + let s = String::from("foo"); + foo().await; +} + +// FIXME: We need "checksum" to prevent matching with the wrong (duplicate) file +// metadata, even when -C codegen-units=1. +// CHECK: [[FILE:!.*]] = !DIFile(filename: "{{.*}}/generator-debug.rs", {{.*}}, checksum: + +// CHECK: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "generator-0", scope: [[FN:![0-9]*]], +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: [[FN]] = !DINamespace(name: "generator_test" +// CHECK: [[VARIANT:!.*]] = !DICompositeType(tag: DW_TAG_variant_part, scope: [[FN]], +// CHECK-SAME: flags: DIFlagArtificial +// CHECK-SAME: discriminator: [[DISC:![0-9]*]] +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "0", scope: [[VARIANT]], +// CHECK-SAME: file: [[FILE]], line: 13, +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: {{!.*}} = !DICompositeType(tag: DW_TAG_structure_type, name: "Unresumed", scope: [[GEN]], +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "1", scope: [[VARIANT]], +// CHECK-SAME: file: [[FILE]], line: 17, +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "2", scope: [[VARIANT]], +// CHECK-SAME: file: [[FILE]], line: 17, +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "3", scope: [[VARIANT]], +// CHECK-SAME: file: [[FILE]], line: 14, +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "4", scope: [[VARIANT]], +// CHECK-SAME: file: [[FILE]], line: 16, +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: [[S1:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend1", scope: [[GEN]], +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "s", scope: [[S1]] +// CHECK-NOT: flags: DIFlagArtificial +// CHECK-SAME: ) +// CHECK: [[DISC]] = !DIDerivedType(tag: DW_TAG_member, name: "__state", scope: [[FN]], +// CHECK-SAME: flags: DIFlagArtificial + +// CHECK: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "generator-0", scope: [[FN:![0-9]*]], +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: [[FN]] = !DINamespace(name: "async_fn_test" +// CHECK: [[VARIANT:!.*]] = !DICompositeType(tag: DW_TAG_variant_part, scope: [[FN]], +// CHECK-SAME: flags: DIFlagArtificial +// CHECK-SAME: discriminator: [[DISC:![0-9]*]] +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "0", scope: [[VARIANT]], +// CHECK-SAME: file: [[FILE]], line: 21, +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "1", scope: [[VARIANT]], +// CHECK-SAME: file: [[FILE]], line: 25, +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "2", scope: [[VARIANT]], +// CHECK-SAME: file: [[FILE]], line: 25, +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "3", scope: [[VARIANT]], +// CHECK-SAME: file: [[FILE]], line: 22, +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "4", scope: [[VARIANT]], +// CHECK-SAME: file: [[FILE]], line: 24, +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: [[S1:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend1", scope: [[GEN]], +// CHECK-SAME: flags: DIFlagArtificial +// CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "s", scope: [[S1]] +// CHECK-NOT: flags: DIFlagArtificial +// CHECK-SAME: ) +// CHECK: [[DISC]] = !DIDerivedType(tag: DW_TAG_member, name: "__state", scope: [[FN]], +// CHECK-SAME: flags: DIFlagArtificial + +fn main() { + let _dummy = generator_test(); + let _dummy = async_fn_test(); +} diff --git a/src/test/mir-opt/generator-drop-cleanup/rustc.main-{{closure}}.generator_drop.0.mir b/src/test/mir-opt/generator-drop-cleanup/rustc.main-{{closure}}.generator_drop.0.mir index 3e7083ff62ecd..3c77995eea893 100644 --- a/src/test/mir-opt/generator-drop-cleanup/rustc.main-{{closure}}.generator_drop.0.mir +++ b/src/test/mir-opt/generator-drop-cleanup/rustc.main-{{closure}}.generator_drop.0.mir @@ -1,5 +1,18 @@ // MIR for `main::{{closure}}#0` 0 generator_drop -// generator_layout = GeneratorLayout { field_tys: [std::string::String], variant_fields: [[], [], [], [_0]], storage_conflicts: BitMatrix { num_rows: 1, num_columns: 1, words: [1], marker: PhantomData } } +/* generator_layout = GeneratorLayout { + field_tys: { + _0: std::string::String, + }, + variant_fields: { + Unresumed(0): [], + Returned (1): [], + Panicked (2): [], + Suspend0 (3): [_0], + }, + storage_conflicts: BitMatrix(1x1) { + (_0, _0), + }, +} */ fn main::{{closure}}#0(_1: *mut [generator@$DIR/generator-drop-cleanup.rs:10:15: 13:6 {std::string::String, ()}]) -> () { let mut _0: (); // return place in scope 0 at $DIR/generator-drop-cleanup.rs:10:15: 13:6 diff --git a/src/test/mir-opt/generator-tiny/rustc.main-{{closure}}.generator_resume.0.mir b/src/test/mir-opt/generator-tiny/rustc.main-{{closure}}.generator_resume.0.mir index c73dea5f8fde6..bd6db11a7e73e 100644 --- a/src/test/mir-opt/generator-tiny/rustc.main-{{closure}}.generator_resume.0.mir +++ b/src/test/mir-opt/generator-tiny/rustc.main-{{closure}}.generator_resume.0.mir @@ -1,5 +1,18 @@ // MIR for `main::{{closure}}#0` 0 generator_resume -// generator_layout = GeneratorLayout { field_tys: [HasDrop], variant_fields: [[], [], [], [_0]], storage_conflicts: BitMatrix { num_rows: 1, num_columns: 1, words: [1], marker: PhantomData } } +/* generator_layout = GeneratorLayout { + field_tys: { + _0: HasDrop, + }, + variant_fields: { + Unresumed(0): [], + Returned (1): [], + Panicked (2): [], + Suspend0 (3): [_0], + }, + storage_conflicts: BitMatrix(1x1) { + (_0, _0), + }, +} */ fn main::{{closure}}#0(_1: std::pin::Pin<&mut [generator@$DIR/generator-tiny.rs:19:16: 25:6 {u8, HasDrop, ()}]>, _2: u8) -> std::ops::GeneratorState<(), ()> { debug _x => _10; // in scope 0 at $DIR/generator-tiny.rs:19:17: 19:19 diff --git a/src/test/ui/const-generics/auxiliary/impl-const.rs b/src/test/ui/const-generics/auxiliary/impl-const.rs new file mode 100644 index 0000000000000..fc993d63927c3 --- /dev/null +++ b/src/test/ui/const-generics/auxiliary/impl-const.rs @@ -0,0 +1,9 @@ +#![feature(const_generics)] + +pub struct Num; + +// Braces around const expression causes crash +impl Num<{5}> { + pub fn five(&self) { + } +} diff --git a/src/test/ui/const-generics/issue-68104-print-stack-overflow.rs b/src/test/ui/const-generics/issue-68104-print-stack-overflow.rs new file mode 100644 index 0000000000000..bda9ce8767d08 --- /dev/null +++ b/src/test/ui/const-generics/issue-68104-print-stack-overflow.rs @@ -0,0 +1,14 @@ +// aux-build:impl-const.rs +// run-pass + +#![feature(const_generics)] +#![allow(incomplete_features)] + +extern crate impl_const; + +use impl_const::*; + +pub fn main() { + let n = Num::<5>; + n.five(); +} diff --git a/src/test/ui/sanitize/unsupported-target.stderr b/src/test/ui/sanitize/unsupported-target.stderr index f9434bc9512d0..f5961a11b1f1c 100644 --- a/src/test/ui/sanitize/unsupported-target.stderr +++ b/src/test/ui/sanitize/unsupported-target.stderr @@ -1,4 +1,4 @@ -error: `-Zsanitizer=leak` only works with targets: x86_64-apple-darwin, x86_64-unknown-linux-gnu +error: `-Zsanitizer=leak` only works with targets: aarch64-unknown-linux-gnu, x86_64-apple-darwin, x86_64-unknown-linux-gnu error: aborting due to previous error diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs index 0d56bf2d20fcb..0437ff8c9440a 100644 --- a/src/tools/compiletest/src/util.rs +++ b/src/tools/compiletest/src/util.rs @@ -82,16 +82,22 @@ const ARCH_TABLE: &'static [(&'static str, &'static str)] = &[ ("xcore", "xcore"), ]; -pub const ASAN_SUPPORTED_TARGETS: &'static [&'static str] = - &["aarch64-fuchsia", "x86_64-apple-darwin", "x86_64-fuchsia", "x86_64-unknown-linux-gnu"]; +pub const ASAN_SUPPORTED_TARGETS: &'static [&'static str] = &[ + "aarch64-fuchsia", + "aarch64-unknown-linux-gnu", + "x86_64-apple-darwin", + "x86_64-fuchsia", + "x86_64-unknown-linux-gnu", +]; pub const LSAN_SUPPORTED_TARGETS: &'static [&'static str] = - &["x86_64-apple-darwin", "x86_64-unknown-linux-gnu"]; + &["aarch64-unknown-linux-gnu", "x86_64-apple-darwin", "x86_64-unknown-linux-gnu"]; -pub const MSAN_SUPPORTED_TARGETS: &'static [&'static str] = &["x86_64-unknown-linux-gnu"]; +pub const MSAN_SUPPORTED_TARGETS: &'static [&'static str] = + &["aarch64-unknown-linux-gnu", "x86_64-unknown-linux-gnu"]; pub const TSAN_SUPPORTED_TARGETS: &'static [&'static str] = - &["x86_64-apple-darwin", "x86_64-unknown-linux-gnu"]; + &["aarch64-unknown-linux-gnu", "x86_64-apple-darwin", "x86_64-unknown-linux-gnu"]; pub fn matches_os(triple: &str, name: &str) -> bool { // For the wasm32 bare target we ignore anything also ignored on emscripten diff --git a/src/tools/remote-test-client/src/main.rs b/src/tools/remote-test-client/src/main.rs index efc29163455be..1fafe109d34e1 100644 --- a/src/tools/remote-test-client/src/main.rs +++ b/src/tools/remote-test-client/src/main.rs @@ -107,13 +107,23 @@ fn start_android_emulator(server: &Path) { Command::new("adb").arg("shell").arg("/data/tmp/testd").spawn().unwrap(); } -fn start_qemu_emulator(target: &str, rootfs: &Path, server: &Path, tmpdir: &Path) { +fn prepare_rootfs(target: &str, rootfs: &Path, server: &Path, rootfs_img: &Path) { + t!(fs::copy(server, rootfs.join("testd"))); + + match target { + "arm-unknown-linux-gnueabihf" | "aarch64-unknown-linux-gnu" => { + prepare_rootfs_cpio(rootfs, rootfs_img) + } + "riscv64gc-unknown-linux-gnu" => prepare_rootfs_ext4(rootfs, rootfs_img), + _ => panic!("{} is not supported", target), + } +} + +fn prepare_rootfs_cpio(rootfs: &Path, rootfs_img: &Path) { // Generate a new rootfs image now that we've updated the test server // executable. This is the equivalent of: // // find $rootfs -print 0 | cpio --null -o --format=newc > rootfs.img - t!(fs::copy(server, rootfs.join("testd"))); - let rootfs_img = tmpdir.join("rootfs.img"); let mut cmd = Command::new("cpio"); cmd.arg("--null") .arg("-o") @@ -128,6 +138,38 @@ fn start_qemu_emulator(target: &str, rootfs: &Path, server: &Path, tmpdir: &Path t!(io::copy(&mut child.stdout.take().unwrap(), &mut t!(File::create(&rootfs_img)))); assert!(t!(child.wait()).success()); + fn add_files(w: &mut dyn Write, root: &Path, cur: &Path) { + for entry in t!(cur.read_dir()) { + let entry = t!(entry); + let path = entry.path(); + let to_print = path.strip_prefix(root).unwrap(); + t!(write!(w, "{}\u{0}", to_print.to_str().unwrap())); + if t!(entry.file_type()).is_dir() { + add_files(w, root, &path); + } + } + } +} + +fn prepare_rootfs_ext4(rootfs: &Path, rootfs_img: &Path) { + let mut dd = Command::new("dd"); + dd.arg("if=/dev/zero") + .arg(&format!("of={}", rootfs_img.to_string_lossy())) + .arg("bs=1M") + .arg("count=1024"); + let mut dd_child = t!(dd.spawn()); + assert!(t!(dd_child.wait()).success()); + + let mut mkfs = Command::new("mkfs.ext4"); + mkfs.arg("-d").arg(rootfs).arg(rootfs_img); + let mut mkfs_child = t!(mkfs.spawn()); + assert!(t!(mkfs_child.wait()).success()); +} + +fn start_qemu_emulator(target: &str, rootfs: &Path, server: &Path, tmpdir: &Path) { + let rootfs_img = &tmpdir.join("rootfs.img"); + prepare_rootfs(target, rootfs, server, rootfs_img); + // Start up the emulator, in the background match target { "arm-unknown-linux-gnueabihf" => { @@ -170,19 +212,30 @@ fn start_qemu_emulator(target: &str, rootfs: &Path, server: &Path, tmpdir: &Path .arg("virtio-net-device,netdev=net0,mac=00:00:00:00:00:00"); t!(cmd.spawn()); } - _ => panic!("cannot start emulator for: {}" < target), - } - - fn add_files(w: &mut dyn Write, root: &Path, cur: &Path) { - for entry in t!(cur.read_dir()) { - let entry = t!(entry); - let path = entry.path(); - let to_print = path.strip_prefix(root).unwrap(); - t!(write!(w, "{}\u{0}", to_print.to_str().unwrap())); - if t!(entry.file_type()).is_dir() { - add_files(w, root, &path); - } + "riscv64gc-unknown-linux-gnu" => { + let mut cmd = Command::new("qemu-system-riscv64"); + cmd.arg("-nographic") + .arg("-machine") + .arg("virt") + .arg("-m") + .arg("1024") + .arg("-bios") + .arg("none") + .arg("-kernel") + .arg("/tmp/bbl") + .arg("-append") + .arg("quiet console=ttyS0 root=/dev/vda rw") + .arg("-netdev") + .arg("user,id=net0,hostfwd=tcp::12345-:12345") + .arg("-device") + .arg("virtio-net-device,netdev=net0,mac=00:00:00:00:00:00") + .arg("-device") + .arg("virtio-blk-device,drive=hd0") + .arg("-drive") + .arg(&format!("file={},format=raw,id=hd0", &rootfs_img.to_string_lossy())); + t!(cmd.spawn()); } + _ => panic!("cannot start emulator for: {}", target), } }