Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,7 @@
path = src/gcc
url = https://github.com/rust-lang/gcc.git
shallow = true
[submodule "src/tpde"]
path = src/tpde
url = https://github.com/rust-lang/tpde.git
shallow = true
7 changes: 5 additions & 2 deletions bootstrap.example.toml
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,12 @@
# Whether to build Enzyme as AutoDiff backend.
#llvm.enzyme = false

# Whether to build LLVM with support for it's gpu offload runtime.
# Whether to build LLVM with support for its gpu offload runtime.
#llvm.offload = false

# Whether to build TPDE as an experimental alternative LLVM backend.
#llvm.tpde = false

# Absolute path to the directory containing ClangConfig.cmake
#llvm.offload-clang-dir = ""

Expand Down Expand Up @@ -842,7 +845,7 @@
# sysroot.
#rust.llvm-tools = true

# Indicates whether the `self-contained` llvm-bitcode-linker, will be made available
# Indicates whether the `self-contained` llvm-bitcode-linker will be made available
# in the sysroot. It is required for running nvptx tests.
#rust.llvm-bitcode-linker = false

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -610,7 +610,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
// loop iteration. In this case, try using the loop terminator location in
// `find_sub_region_live_at`.
if let Some(loop_terminator_location) =
regioncx.find_loop_terminator_location(borrow.region, body)
regioncx.find_loop_terminator_location(borrow.region, body, location)
{
region_sub = self
.regioncx
Expand Down
11 changes: 7 additions & 4 deletions compiler/rustc_borrowck/src/region_infer/region_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -816,16 +816,19 @@ impl<'tcx> RegionInferenceContextInner<'tcx> {
&self,
r: RegionVid,
body: &Body<'_>,
from_location: Location,
) -> Option<Location> {
let scc = self.constraint_sccs.scc(r);
let locations = self.scc_values.locations_outlived_by(scc);
for location in locations {
let bb = &body[location.block];
if let Some(terminator) = &bb.terminator
if from_location.is_predecessor_of(location, body) {
let bb = &body[location.block];
if let Some(terminator) = &bb.terminator
// terminator of a loop should be TerminatorKind::FalseUnwind
&& let TerminatorKind::FalseUnwind { .. } = terminator.kind
{
return Some(location);
{
return Some(location);
}
}
}
None
Expand Down
33 changes: 22 additions & 11 deletions compiler/rustc_expand/src/mbe/macro_rules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use rustc_ast_pretty::pprust;
use rustc_attr_ir::diagnostic::Directive;
use rustc_attr_ir::{self as attrs, find_attr};
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan};
use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan, StringPart};
use rustc_feature::Features;
use rustc_hir::def::MacroKinds;
use rustc_lint_defs::builtin::{
Expand Down Expand Up @@ -1643,21 +1643,32 @@ fn check_matcher_core<'tt>(
);
}

let msg = "allowed there are: ";
match possible {
&[] => {}
&[t] => {
err.note(format!(
"only {t} is allowed after `{kind}` fragments",
));
err.highlighted_note(vec![
StringPart::normal("only "),
StringPart::highlighted(t),
StringPart::normal(format!(
" is allowed after `{kind}` fragments"
)),
]);
}
ts => {
err.note(format!(
"{}{} or {}",
msg,
ts[..ts.len() - 1].to_vec().join(", "),
ts[ts.len() - 1],
));
let mut msg_parts =
vec![StringPart::normal("allowed there are: ")];

for (i, &t) in ts.iter().enumerate() {
if i == ts.len() - 1 {
msg_parts.push(StringPart::normal(" or "));
} else if i > 0 {
msg_parts.push(StringPart::normal(", "));
}

msg_parts.push(StringPart::highlighted(t));
}

err.highlighted_note(msg_parts);
}
}
errored = Err(err.emit_err());
Expand Down
19 changes: 19 additions & 0 deletions library/std/src/sys/fs/unsupported.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,25 @@ pub struct FileType(!);
#[derive(Debug)]
pub struct DirBuilder {}

// Dummy Drops so that `needs_drop::<std::fs::File>()` etc. is true independent of platform,
// avoiding a portability hazard.
// The types not listed here are pure data and don’t implement Drop even when real.
impl Drop for File {
fn drop(&mut self) {
self.0
}
}
impl Drop for ReadDir {
fn drop(&mut self) {
self.0
}
}
impl Drop for DirEntry {
fn drop(&mut self) {
self.0
}
}

impl FileAttr {
pub fn size(&self) -> u64 {
self.0
Expand Down
7 changes: 7 additions & 0 deletions library/std/src/sys/fs/vexos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,13 @@ impl Drop for File {
}
}

impl Drop for ReadDir {
fn drop(&mut self) {
// Dummy Drop so that `needs_drop::<ReadDir>()` is true independent of platform.
self.0
}
}

pub fn readdir(_p: &Path) -> io::Result<ReadDir> {
// While there *is* a userspace function for reading file directories,
// the necessary implementation cannot currently be done cleanly, as
Expand Down
20 changes: 20 additions & 0 deletions src/bootstrap/src/core/build_steps/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2551,6 +2551,26 @@ impl CommandLineStep for Assemble {

maybe_install_llvm_bitcode_linker();

if builder.config.llvm_tpde {
debug!("`llvm_tpde` requested");
// The rustc TPDE integration is Linux-only for now
if !host.contains("linux") {
builder.info(&format!("host target `{host}` not supported by tpde. skipping"));
} else {
// Put TPDE next to librustc_driver.so
let tpde_output = builder.ensure(llvm::Tpde { target: host });
let target_libdir =
builder.sysroot_target_libdir(target_compiler, target_compiler.host);
let target_dst_lib =
target_libdir.join(tpde_output.plugin_path().file_name().unwrap());
builder.copy_link(
tpde_output.plugin_path(),
&target_dst_lib,
FileType::NativeLibrary,
);
}
}

// Ensure that `libLLVM.so` ends up in the newly build compiler directory,
// so that it can be found when the newly built `rustc` is run.
debug!(
Expand Down
179 changes: 177 additions & 2 deletions src/bootstrap/src/core/build_steps/llvm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -854,7 +854,7 @@ fn try_link_with_in_tree_lld(
cfg: &mut cmake::Config,
ldflags: &mut LdFlags,
) {
// Apple has it's own ld64 linker, so don't use LLD on Darwin.
// Apple has its own ld64 linker, so don't use LLD on Darwin.
if target.contains("apple") {
return;
}
Expand All @@ -869,7 +869,8 @@ fn try_link_with_in_tree_lld(
}

let lld_bin = builder.ensure(Lld { target }).join("bin");
ldflags.push_all(format!("-B{} -fuse-ld=lld", lld_bin.display()));
// Quote the path to LLD to prevent it from splitting if it contains a space
ldflags.push_all(format!("'-B{}' -fuse-ld=lld", lld_bin.display()));

if llvm_output.link_shared() {
// LLD in this case needs the LLVM lib, so tell where to look for it.
Expand Down Expand Up @@ -2291,3 +2292,177 @@ impl Step for FileCheck {
llvm_output.root_dir().join("bin").join(exe("FileCheck", self.target))
}
}

/// Result of building TPDE artifacts.
///
/// Currently only tpde-plugin.so is consumed elsewhere.
#[derive(Clone)]
pub struct TpdeOutput {
tpde_root_dir: PathBuf,
tpde_plugin_path: PathBuf,
}

impl TpdeOutput {
/// Path to tpde-plugin.so
pub fn plugin_path(&self) -> &Path {
&self.tpde_plugin_path
}
}

pub struct TpdeBuildInfo {
stamp: BuildStamp,
output: TpdeOutput,
}

pub enum TpdeBuildStatus {
AlreadyBuilt(TpdeOutput),
ShouldBuild(TpdeBuildInfo),
}

/// Return build status of TPDE, considering only the locally built TPDE.
///
/// Calling this function should never attempt to checkout the TPDE submodule.
fn get_locally_built_tpde_build_status(
builder: &Builder<'_>,
target: TargetSelection,
) -> TpdeBuildStatus {
let out_dir = tpde_output_dir(builder, target);

let res = TpdeOutput {
tpde_plugin_path: out_dir.join("build").join("tpde-llvm").join("tpde-plugin.so"),
tpde_root_dir: out_dir,
};

static STAMP_HASH_MEMO: OnceLock<String> = OnceLock::new();
let smart_stamp_hash = STAMP_HASH_MEMO.get_or_init(|| {
generate_smart_stamp_hash(
builder,
&builder.config.src.join("src/tpde"),
builder.in_tree_tpde_info.sha().unwrap_or_default(),
)
});

// Rebuild if build options change
let stamp = BuildStamp::new(&res.tpde_root_dir)
.with_prefix("tpde")
.add_stamp(smart_stamp_hash)
.add_stamp(builder.config.llvm_assertions)
.add_stamp(builder.config.llvm_optimize)
.add_stamp(builder.config.llvm_release_debuginfo);

if stamp.is_up_to_date() {
if smart_stamp_hash.is_empty() {
builder.info(
"Could not determine the TPDE submodule commit hash. \
Assuming that a TPDE rebuild is not necessary.",
);
builder.info(&format!(
"To force TPDE to rebuild, remove the file `{}`",
stamp.path().display()
));
}
return TpdeBuildStatus::AlreadyBuilt(res);
}

TpdeBuildStatus::ShouldBuild(TpdeBuildInfo { stamp, output: res })
}

/// Output directory of *locally built* TPDE for the given `target`.
/// Should only be used within this module, when building TPDE.
/// Otherwise, you should ensure the `Tpde` step and read its root directory.
fn tpde_output_dir(builder: &Builder<'_>, target: TargetSelection) -> PathBuf {
builder.config.out.join(target).join("tpde")
}

#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct Tpde {
pub target: TargetSelection,
}

impl CommandLineStep for Tpde {
type Output = TpdeOutput;

const IS_HOST: bool = true;

fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
run.path("src/tpde").alias("tpde")
}

fn make_run(run: RunConfig<'_>) {
run.builder.ensure(Tpde { target: run.target });
}

/// Compile TPDE for `target`.
fn run(self, builder: &Builder<'_>) -> TpdeOutput {
let target = self.target;
if !target.contains("linux") {
builder.info(&format!("WARNING: host target {target} not supported by TPDE"));
}
let llvm = builder.ensure(Llvm { target });
if llvm.kind() != LlvmKind::BuiltLocally || !llvm.link_shared() {
// Due to current limitations with the way LLVM configures CMake exports, it is not possible to use CI LLVM.
// FIXME: experiment with LLVM_OMIT_EXPORTS_FROM_CONFIG=OFF and changing library search paths as described in https://github.com/rust-lang/rust/pull/163731#discussion_r4286684608,
// or (preferred) wait until upstream LLVM patches have landed to decouple static exports from dynamic exports in the CMake config
panic!(
"TPDE currently requires building with a locally built LLVM and `llvm.link-shared = true` in bootstrap"
);
}
builder.config.update_submodule("src/tpde");
// If TPDE has already been built, we avoid building it again.
let TpdeBuildInfo { stamp, output } =
match get_locally_built_tpde_build_status(builder, target) {
TpdeBuildStatus::AlreadyBuilt(p) => return p,
TpdeBuildStatus::ShouldBuild(m) => m,
};

let _guard = builder.msg_unstaged(Kind::Build, "TPDE", target);
t!(stamp.remove());
let _time = helpers::timeit(builder);
t!(fs::create_dir_all(&output.tpde_root_dir));

let mut cfg = cmake::Config::new(builder.src.join("src/tpde"));

let profile = get_llvm_profile(&builder.config);
let assertions = if builder.config.llvm_assertions { "ON" } else { "OFF" };

cfg.out_dir(&output.tpde_root_dir)
.profile(profile)
.define("TPDE_ENABLE_ASSERTIONS", assertions)
.define("TPDE_ENABLE_LLVM", "ON")
.define("TPDE_ENABLE_ENCODEGEN", "ON")
.define("TPDE_INCLUDE_TESTS", "OFF")
.define("TPDE_ENABLE_ASAN", "OFF")
.define("TPDE_LOGGING", "OFF")
.define("TPDE_ENABLE_COVERAGE", "OFF")
.define("TPDE_BUILD_DOCS", "OFF")
.define("TPDE_ENABLE_EH", "OFF")
.define("LLVM_DIR", llvm.cmake_dir());

let mut ldflags = LdFlags::default();
try_link_with_in_tree_lld(builder, target, &llvm, &mut cfg, &mut ldflags);
configure_cmake(builder, target, &mut cfg, true, ldflags, CcFlags::default(), &[]);

if builder.config.dry_run() {
return output;
}

cfg.build_target("tpde-plugin.so");

// When building TPDE as a shared library on linux, it can contain unexpected debuginfo:
// some can come from the C++ standard library. Unless we're explicitly requesting TPDE to
// be built with debuginfo, strip it away after the fact, to make dist artifacts smaller.
if builder.config.llvm_optimize && !builder.config.llvm_release_debuginfo {
// If the shared library exists in TPDE's `/build/tpde-llvm` folder, strip its
// debuginfo.
crate::core::build_steps::compile::strip_debug(builder, target, output.plugin_path());
}

t!(stamp.write());

output
}

fn metadata(&self) -> Option<StepMetadata> {
Some(StepMetadata::build("tpde", self.target))
}
}
Loading
Loading