mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-21 22:34:05 +00:00
Auto merge of #104215 - Manishearth:rollup-5r957ad, r=Manishearth
Rollup of 9 pull requests Successful merges: - #101005 (Migrate rustc_codegen_llvm to SessionDiagnostics) - #103307 (Add context to compiler error message) - #103464 (Add support for custom mir) - #103929 (Cleanup Apple-related code in rustc_target) - #104015 (Remove linuxkernel targets) - #104020 (Limit efiapi calling convention to supported arches) - #104156 (Cleanups in autoderef impl) - #104171 (Update books) - #104184 (Fix `rustdoc --version` when used with download-rustc) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
34115d040b
@ -1557,7 +1557,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||
}
|
||||
|
||||
let mut err = self.temporary_value_borrowed_for_too_long(proper_span);
|
||||
err.span_label(proper_span, "creates a temporary which is freed while still in use");
|
||||
err.span_label(proper_span, "creates a temporary value which is freed while still in use");
|
||||
err.span_label(drop_span, "temporary value is freed at the end of this statement");
|
||||
|
||||
match explanation {
|
||||
|
@ -18,6 +18,7 @@ extern crate tracing;
|
||||
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::graph::dominators::Dominators;
|
||||
use rustc_data_structures::vec_map::VecMap;
|
||||
use rustc_errors::{Diagnostic, DiagnosticBuilder, ErrorGuaranteed};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
@ -129,6 +130,19 @@ fn mir_borrowck<'tcx>(
|
||||
) -> &'tcx BorrowCheckResult<'tcx> {
|
||||
let (input_body, promoted) = tcx.mir_promoted(def);
|
||||
debug!("run query mir_borrowck: {}", tcx.def_path_str(def.did.to_def_id()));
|
||||
|
||||
if input_body.borrow().should_skip() {
|
||||
debug!("Skipping borrowck because of injected body");
|
||||
// Let's make up a borrowck result! Fun times!
|
||||
let result = BorrowCheckResult {
|
||||
concrete_opaque_types: VecMap::new(),
|
||||
closure_requirements: None,
|
||||
used_mut_upvars: SmallVec::new(),
|
||||
tainted_by_errors: None,
|
||||
};
|
||||
return tcx.arena.alloc(result);
|
||||
}
|
||||
|
||||
let hir_owner = tcx.hir().local_def_id_to_hir_id(def.did).owner;
|
||||
|
||||
let infcx =
|
||||
|
@ -59,7 +59,7 @@ impl DebugContext {
|
||||
|
||||
let producer = format!(
|
||||
"cg_clif (rustc {}, cranelift {})",
|
||||
rustc_interface::util::version_str().unwrap_or("unknown version"),
|
||||
rustc_interface::util::rustc_version_str().unwrap_or("unknown version"),
|
||||
cranelift_codegen::VERSION,
|
||||
);
|
||||
let comp_dir = tcx
|
||||
|
@ -12,6 +12,7 @@ use rustc_target::spec::{FramePointer, SanitizerSet, StackProbeType, StackProtec
|
||||
use smallvec::SmallVec;
|
||||
|
||||
use crate::attributes;
|
||||
use crate::errors::{MissingFeatures, SanitizerMemtagRequiresMte, TargetFeatureDisableOrEnable};
|
||||
use crate::llvm::AttributePlace::Function;
|
||||
use crate::llvm::{self, AllocKindFlags, Attribute, AttributeKind, AttributePlace, MemoryEffects};
|
||||
use crate::llvm_util;
|
||||
@ -82,7 +83,7 @@ pub fn sanitize_attrs<'ll>(
|
||||
let mte_feature =
|
||||
features.iter().map(|s| &s[..]).rfind(|n| ["+mte", "-mte"].contains(&&n[..]));
|
||||
if let None | Some("-mte") = mte_feature {
|
||||
cx.tcx.sess.err("`-Zsanitizer=memtag` requires `-Ctarget-feature=+mte`");
|
||||
cx.tcx.sess.emit_err(SanitizerMemtagRequiresMte);
|
||||
}
|
||||
|
||||
attrs.push(llvm::AttributeKind::SanitizeMemTag.create_attr(cx.llcx));
|
||||
@ -393,13 +394,14 @@ pub fn from_fn_attrs<'ll, 'tcx>(
|
||||
.get_attrs(instance.def_id(), sym::target_feature)
|
||||
.next()
|
||||
.map_or_else(|| cx.tcx.def_span(instance.def_id()), |a| a.span);
|
||||
let msg = format!(
|
||||
"the target features {} must all be either enabled or disabled together",
|
||||
f.join(", ")
|
||||
);
|
||||
let mut err = cx.tcx.sess.struct_span_err(span, &msg);
|
||||
err.help("add the missing features in a `target_feature` attribute");
|
||||
err.emit();
|
||||
cx.tcx
|
||||
.sess
|
||||
.create_err(TargetFeatureDisableOrEnable {
|
||||
features: f,
|
||||
span: Some(span),
|
||||
missing_features: Some(MissingFeatures),
|
||||
})
|
||||
.emit();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,10 @@ use std::str;
|
||||
use object::read::macho::FatArch;
|
||||
|
||||
use crate::common;
|
||||
use crate::errors::{
|
||||
ArchiveBuildFailure, DlltoolFailImportLibrary, ErrorCallingDllTool, ErrorCreatingImportLibrary,
|
||||
ErrorWritingDEFFile, UnknownArchiveKind,
|
||||
};
|
||||
use crate::llvm::archive_ro::{ArchiveRO, Child};
|
||||
use crate::llvm::{self, ArchiveKind, LLVMMachineType, LLVMRustCOFFShortExport};
|
||||
use rustc_codegen_ssa::back::archive::{ArchiveBuilder, ArchiveBuilderBuilder};
|
||||
@ -147,7 +151,7 @@ impl<'a> ArchiveBuilder<'a> for LlvmArchiveBuilder<'a> {
|
||||
fn build(mut self: Box<Self>, output: &Path) -> bool {
|
||||
match self.build_with_llvm(output) {
|
||||
Ok(any_members) => any_members,
|
||||
Err(e) => self.sess.fatal(&format!("failed to build archive: {}", e)),
|
||||
Err(e) => self.sess.emit_fatal(ArchiveBuildFailure { error: e }),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -217,7 +221,7 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
|
||||
match std::fs::write(&def_file_path, def_file_content) {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
sess.fatal(&format!("Error writing .DEF file: {}", e));
|
||||
sess.emit_fatal(ErrorWritingDEFFile { error: e });
|
||||
}
|
||||
};
|
||||
|
||||
@ -239,13 +243,14 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
|
||||
|
||||
match result {
|
||||
Err(e) => {
|
||||
sess.fatal(&format!("Error calling dlltool: {}", e));
|
||||
sess.emit_fatal(ErrorCallingDllTool { error: e });
|
||||
}
|
||||
Ok(output) if !output.status.success() => {
|
||||
sess.emit_fatal(DlltoolFailImportLibrary {
|
||||
stdout: String::from_utf8_lossy(&output.stdout),
|
||||
stderr: String::from_utf8_lossy(&output.stderr),
|
||||
})
|
||||
}
|
||||
Ok(output) if !output.status.success() => sess.fatal(&format!(
|
||||
"Dlltool could not create import library: {}\n{}",
|
||||
String::from_utf8_lossy(&output.stdout),
|
||||
String::from_utf8_lossy(&output.stderr)
|
||||
)),
|
||||
_ => {}
|
||||
}
|
||||
} else {
|
||||
@ -293,11 +298,10 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
|
||||
};
|
||||
|
||||
if result == crate::llvm::LLVMRustResult::Failure {
|
||||
sess.fatal(&format!(
|
||||
"Error creating import library for {}: {}",
|
||||
sess.emit_fatal(ErrorCreatingImportLibrary {
|
||||
lib_name,
|
||||
llvm::last_error().unwrap_or("unknown LLVM error".to_string())
|
||||
));
|
||||
error: llvm::last_error().unwrap_or("unknown LLVM error".to_string()),
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@ -308,9 +312,10 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder {
|
||||
impl<'a> LlvmArchiveBuilder<'a> {
|
||||
fn build_with_llvm(&mut self, output: &Path) -> io::Result<bool> {
|
||||
let kind = &*self.sess.target.archive_format;
|
||||
let kind = kind.parse::<ArchiveKind>().map_err(|_| kind).unwrap_or_else(|kind| {
|
||||
self.sess.fatal(&format!("Don't know how to build archive of type: {}", kind))
|
||||
});
|
||||
let kind = kind
|
||||
.parse::<ArchiveKind>()
|
||||
.map_err(|_| kind)
|
||||
.unwrap_or_else(|kind| self.sess.emit_fatal(UnknownArchiveKind { kind }));
|
||||
|
||||
let mut additions = mem::take(&mut self.additions);
|
||||
let mut strings = Vec::new();
|
||||
|
@ -1,4 +1,5 @@
|
||||
use crate::back::write::{self, save_temp_bitcode, DiagnosticHandlers};
|
||||
use crate::errors::DynamicLinkingWithLTO;
|
||||
use crate::llvm::{self, build_string};
|
||||
use crate::{LlvmCodegenBackend, ModuleLlvm};
|
||||
use object::read::archive::ArchiveFile;
|
||||
@ -90,13 +91,7 @@ fn prepare_lto(
|
||||
}
|
||||
|
||||
if cgcx.opts.cg.prefer_dynamic && !cgcx.opts.unstable_opts.dylib_lto {
|
||||
diag_handler
|
||||
.struct_err("cannot prefer dynamic linking when performing LTO")
|
||||
.note(
|
||||
"only 'staticlib', 'bin', and 'cdylib' outputs are \
|
||||
supported with LTO",
|
||||
)
|
||||
.emit();
|
||||
diag_handler.emit_err(DynamicLinkingWithLTO);
|
||||
return Err(FatalError);
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
use crate::base;
|
||||
use crate::common::{self, CodegenCx};
|
||||
use crate::debuginfo;
|
||||
use crate::errors::{InvalidMinimumAlignment, LinkageConstOrMutType, SymbolAlreadyDefined};
|
||||
use crate::llvm::{self, True};
|
||||
use crate::llvm_util;
|
||||
use crate::type_::Type;
|
||||
@ -146,7 +147,7 @@ fn set_global_alignment<'ll>(cx: &CodegenCx<'ll, '_>, gv: &'ll Value, mut align:
|
||||
match Align::from_bits(min) {
|
||||
Ok(min) => align = align.max(min),
|
||||
Err(err) => {
|
||||
cx.sess().err(&format!("invalid minimum global alignment: {}", err));
|
||||
cx.sess().emit_err(InvalidMinimumAlignment { err });
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -174,10 +175,7 @@ fn check_and_apply_linkage<'ll, 'tcx>(
|
||||
let llty2 = if let ty::RawPtr(ref mt) = ty.kind() {
|
||||
cx.layout_of(mt.ty).llvm_type(cx)
|
||||
} else {
|
||||
cx.sess().span_fatal(
|
||||
cx.tcx.def_span(def_id),
|
||||
"must have type `*const T` or `*mut T` due to `#[linkage]` attribute",
|
||||
)
|
||||
cx.sess().emit_fatal(LinkageConstOrMutType { span: cx.tcx.def_span(def_id) })
|
||||
};
|
||||
unsafe {
|
||||
// Declare a symbol `foo` with the desired linkage.
|
||||
@ -193,10 +191,10 @@ fn check_and_apply_linkage<'ll, 'tcx>(
|
||||
let mut real_name = "_rust_extern_with_linkage_".to_string();
|
||||
real_name.push_str(sym);
|
||||
let g2 = cx.define_global(&real_name, llty).unwrap_or_else(|| {
|
||||
cx.sess().span_fatal(
|
||||
cx.tcx.def_span(def_id),
|
||||
&format!("symbol `{}` is already defined", &sym),
|
||||
)
|
||||
cx.sess().emit_fatal(SymbolAlreadyDefined {
|
||||
span: cx.tcx.def_span(def_id),
|
||||
symbol_name: sym,
|
||||
})
|
||||
});
|
||||
llvm::LLVMRustSetLinkage(g2, llvm::Linkage::InternalLinkage);
|
||||
llvm::LLVMSetInitializer(g2, g1);
|
||||
|
@ -3,6 +3,7 @@ use crate::back::write::to_llvm_code_model;
|
||||
use crate::callee::get_fn;
|
||||
use crate::coverageinfo;
|
||||
use crate::debuginfo;
|
||||
use crate::errors::BranchProtectionRequiresAArch64;
|
||||
use crate::llvm;
|
||||
use crate::llvm_util;
|
||||
use crate::type_::Type;
|
||||
@ -26,6 +27,7 @@ use rustc_session::config::{BranchProtection, CFGuard, CFProtection};
|
||||
use rustc_session::config::{CrateType, DebugInfo, PAuthKey, PacRet};
|
||||
use rustc_session::Session;
|
||||
use rustc_span::source_map::Span;
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_target::abi::{
|
||||
call::FnAbi, HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx,
|
||||
};
|
||||
@ -275,7 +277,7 @@ pub unsafe fn create_module<'ll>(
|
||||
|
||||
if let Some(BranchProtection { bti, pac_ret }) = sess.opts.unstable_opts.branch_protection {
|
||||
if sess.target.arch != "aarch64" {
|
||||
sess.err("-Zbranch-protection is only supported on aarch64");
|
||||
sess.emit_err(BranchProtectionRequiresAArch64);
|
||||
} else {
|
||||
llvm::LLVMRustAddModuleFlag(
|
||||
llmod,
|
||||
@ -951,7 +953,7 @@ impl<'tcx> LayoutOfHelpers<'tcx> for CodegenCx<'_, 'tcx> {
|
||||
#[inline]
|
||||
fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! {
|
||||
if let LayoutError::SizeOverflow(_) = err {
|
||||
self.sess().span_fatal(span, &err.to_string())
|
||||
self.sess().emit_fatal(Spanned { span, node: err })
|
||||
} else {
|
||||
span_bug!(span, "failed to get layout for `{}`: {}", ty, err)
|
||||
}
|
||||
@ -969,7 +971,7 @@ impl<'tcx> FnAbiOfHelpers<'tcx> for CodegenCx<'_, 'tcx> {
|
||||
fn_abi_request: FnAbiRequest<'tcx>,
|
||||
) -> ! {
|
||||
if let FnAbiError::Layout(LayoutError::SizeOverflow(_)) = err {
|
||||
self.sess().span_fatal(span, &err.to_string())
|
||||
self.sess().emit_fatal(Spanned { span, node: err })
|
||||
} else {
|
||||
match fn_abi_request {
|
||||
FnAbiRequest::OfFnPtr { sig, extra_args } => {
|
||||
|
@ -1,5 +1,6 @@
|
||||
use crate::common::CodegenCx;
|
||||
use crate::coverageinfo;
|
||||
use crate::errors::InstrumentCoverageRequiresLLVM12;
|
||||
use crate::llvm;
|
||||
|
||||
use llvm::coverageinfo::CounterMappingRegion;
|
||||
@ -37,7 +38,7 @@ pub fn finalize<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) {
|
||||
// LLVM 12.
|
||||
let version = coverageinfo::mapping_version();
|
||||
if version < 4 {
|
||||
tcx.sess.fatal("rustc option `-C instrument-coverage` requires LLVM 12 or higher.");
|
||||
tcx.sess.emit_fatal(InstrumentCoverageRequiresLLVM12);
|
||||
}
|
||||
|
||||
debug!("Generating coverage map for CodegenUnit: `{}`", cx.codegen_unit.name());
|
||||
|
139
compiler/rustc_codegen_llvm/src/errors.rs
Normal file
139
compiler/rustc_codegen_llvm/src/errors.rs
Normal file
@ -0,0 +1,139 @@
|
||||
use std::borrow::Cow;
|
||||
|
||||
use rustc_errors::fluent;
|
||||
use rustc_errors::DiagnosticBuilder;
|
||||
use rustc_errors::ErrorGuaranteed;
|
||||
use rustc_errors::Handler;
|
||||
use rustc_errors::IntoDiagnostic;
|
||||
use rustc_macros::{Diagnostic, Subdiagnostic};
|
||||
use rustc_span::Span;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_unknown_ctarget_feature_prefix)]
|
||||
#[note]
|
||||
pub(crate) struct UnknownCTargetFeaturePrefix<'a> {
|
||||
pub feature: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_unknown_ctarget_feature)]
|
||||
#[note]
|
||||
pub(crate) struct UnknownCTargetFeature<'a> {
|
||||
pub feature: &'a str,
|
||||
#[subdiagnostic]
|
||||
pub rust_feature: PossibleFeature<'a>,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub(crate) enum PossibleFeature<'a> {
|
||||
#[help(possible_feature)]
|
||||
Some { rust_feature: &'a str },
|
||||
#[help(consider_filing_feature_request)]
|
||||
None,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_error_creating_import_library)]
|
||||
pub(crate) struct ErrorCreatingImportLibrary<'a> {
|
||||
pub lib_name: &'a str,
|
||||
pub error: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_instrument_coverage_requires_llvm_12)]
|
||||
pub(crate) struct InstrumentCoverageRequiresLLVM12;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_symbol_already_defined)]
|
||||
pub(crate) struct SymbolAlreadyDefined<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub symbol_name: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_branch_protection_requires_aarch64)]
|
||||
pub(crate) struct BranchProtectionRequiresAArch64;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_invalid_minimum_alignment)]
|
||||
pub(crate) struct InvalidMinimumAlignment {
|
||||
pub err: String,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_linkage_const_or_mut_type)]
|
||||
pub(crate) struct LinkageConstOrMutType {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_sanitizer_memtag_requires_mte)]
|
||||
pub(crate) struct SanitizerMemtagRequiresMte;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_archive_build_failure)]
|
||||
pub(crate) struct ArchiveBuildFailure {
|
||||
pub error: std::io::Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_error_writing_def_file)]
|
||||
pub(crate) struct ErrorWritingDEFFile {
|
||||
pub error: std::io::Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_error_calling_dlltool)]
|
||||
pub(crate) struct ErrorCallingDllTool {
|
||||
pub error: std::io::Error,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_dlltool_fail_import_library)]
|
||||
pub(crate) struct DlltoolFailImportLibrary<'a> {
|
||||
pub stdout: Cow<'a, str>,
|
||||
pub stderr: Cow<'a, str>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_unknown_archive_kind)]
|
||||
pub(crate) struct UnknownArchiveKind<'a> {
|
||||
pub kind: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_dynamic_linking_with_lto)]
|
||||
#[note]
|
||||
pub(crate) struct DynamicLinkingWithLTO;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_fail_parsing_target_machine_config_to_target_machine)]
|
||||
pub(crate) struct FailParsingTargetMachineConfigToTargetMachine {
|
||||
pub error: String,
|
||||
}
|
||||
|
||||
pub(crate) struct TargetFeatureDisableOrEnable<'a> {
|
||||
pub features: &'a [&'a str],
|
||||
pub span: Option<Span>,
|
||||
pub missing_features: Option<MissingFeatures>,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[help(codegen_llvm_missing_features)]
|
||||
pub(crate) struct MissingFeatures;
|
||||
|
||||
impl IntoDiagnostic<'_, ErrorGuaranteed> for TargetFeatureDisableOrEnable<'_> {
|
||||
fn into_diagnostic(self, sess: &'_ Handler) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
|
||||
let mut diag = sess.struct_err(fluent::codegen_llvm_target_feature_disable_or_enable);
|
||||
if let Some(span) = self.span {
|
||||
diag.set_span(span);
|
||||
};
|
||||
if let Some(missing_features) = self.missing_features {
|
||||
diag.subdiagnostic(missing_features);
|
||||
}
|
||||
diag.set_arg("features", self.features.join(", "));
|
||||
diag
|
||||
}
|
||||
}
|
@ -12,6 +12,8 @@
|
||||
#![feature(iter_intersperse)]
|
||||
#![recursion_limit = "256"]
|
||||
#![allow(rustc::potential_query_instability)]
|
||||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate rustc_macros;
|
||||
@ -20,6 +22,7 @@ extern crate tracing;
|
||||
|
||||
use back::write::{create_informational_target_machine, create_target_machine};
|
||||
|
||||
use errors::FailParsingTargetMachineConfigToTargetMachine;
|
||||
pub use llvm_util::target_features;
|
||||
use rustc_ast::expand::allocator::AllocatorKind;
|
||||
use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule};
|
||||
@ -62,6 +65,7 @@ mod context;
|
||||
mod coverageinfo;
|
||||
mod debuginfo;
|
||||
mod declare;
|
||||
mod errors;
|
||||
mod intrinsic;
|
||||
|
||||
// The following is a work around that replaces `pub mod llvm;` and that fixes issue 53912.
|
||||
@ -412,7 +416,7 @@ impl ModuleLlvm {
|
||||
let tm = match (cgcx.tm_factory)(tm_factory_config) {
|
||||
Ok(m) => m,
|
||||
Err(e) => {
|
||||
handler.struct_err(&e).emit();
|
||||
handler.emit_err(FailParsingTargetMachineConfigToTargetMachine { error: e });
|
||||
return Err(FatalError);
|
||||
}
|
||||
};
|
||||
|
@ -1,4 +1,8 @@
|
||||
use crate::back::write::create_informational_target_machine;
|
||||
use crate::errors::{
|
||||
PossibleFeature, TargetFeatureDisableOrEnable, UnknownCTargetFeature,
|
||||
UnknownCTargetFeaturePrefix,
|
||||
};
|
||||
use crate::llvm;
|
||||
use libc::c_int;
|
||||
use rustc_codegen_ssa::target_features::{
|
||||
@ -434,12 +438,7 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec<Str
|
||||
Some(c @ '+' | c @ '-') => c,
|
||||
Some(_) => {
|
||||
if diagnostics {
|
||||
let mut diag = sess.struct_warn(&format!(
|
||||
"unknown feature specified for `-Ctarget-feature`: `{}`",
|
||||
s
|
||||
));
|
||||
diag.note("features must begin with a `+` to enable or `-` to disable it");
|
||||
diag.emit();
|
||||
sess.emit_warning(UnknownCTargetFeaturePrefix { feature: s });
|
||||
}
|
||||
return None;
|
||||
}
|
||||
@ -456,17 +455,15 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec<Str
|
||||
None
|
||||
}
|
||||
});
|
||||
let mut diag = sess.struct_warn(&format!(
|
||||
"unknown feature specified for `-Ctarget-feature`: `{}`",
|
||||
feature
|
||||
));
|
||||
diag.note("it is still passed through to the codegen backend");
|
||||
if let Some(rust_feature) = rust_feature {
|
||||
diag.help(&format!("you might have meant: `{}`", rust_feature));
|
||||
let unknown_feature = if let Some(rust_feature) = rust_feature {
|
||||
UnknownCTargetFeature {
|
||||
feature,
|
||||
rust_feature: PossibleFeature::Some { rust_feature },
|
||||
}
|
||||
} else {
|
||||
diag.note("consider filing a feature request");
|
||||
}
|
||||
diag.emit();
|
||||
UnknownCTargetFeature { feature, rust_feature: PossibleFeature::None }
|
||||
};
|
||||
sess.emit_warning(unknown_feature);
|
||||
}
|
||||
|
||||
if diagnostics {
|
||||
@ -492,10 +489,11 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec<Str
|
||||
features.extend(feats);
|
||||
|
||||
if diagnostics && let Some(f) = check_tied_features(sess, &featsmap) {
|
||||
sess.err(&format!(
|
||||
"target features {} must all be enabled or disabled together",
|
||||
f.join(", ")
|
||||
));
|
||||
sess.emit_err(TargetFeatureDisableOrEnable {
|
||||
features: f,
|
||||
span: None,
|
||||
missing_features: None,
|
||||
});
|
||||
}
|
||||
|
||||
features
|
||||
|
@ -1,6 +1,7 @@
|
||||
use crate::attributes;
|
||||
use crate::base;
|
||||
use crate::context::CodegenCx;
|
||||
use crate::errors::SymbolAlreadyDefined;
|
||||
use crate::llvm;
|
||||
use crate::type_of::LayoutLlvmExt;
|
||||
use rustc_codegen_ssa::traits::*;
|
||||
@ -25,10 +26,8 @@ impl<'tcx> PreDefineMethods<'tcx> for CodegenCx<'_, 'tcx> {
|
||||
let llty = self.layout_of(ty).llvm_type(self);
|
||||
|
||||
let g = self.define_global(symbol_name, llty).unwrap_or_else(|| {
|
||||
self.sess().span_fatal(
|
||||
self.tcx.def_span(def_id),
|
||||
&format!("symbol `{}` is already defined", symbol_name),
|
||||
)
|
||||
self.sess()
|
||||
.emit_fatal(SymbolAlreadyDefined { span: self.tcx.def_span(def_id), symbol_name })
|
||||
});
|
||||
|
||||
unsafe {
|
||||
|
@ -15,10 +15,8 @@ use rustc_data_structures::profiling::TimingGuard;
|
||||
use rustc_data_structures::profiling::VerboseTimingGuard;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_errors::emitter::Emitter;
|
||||
use rustc_errors::{
|
||||
translation::{to_fluent_args, Translate},
|
||||
DiagnosticId, FatalError, Handler, Level,
|
||||
};
|
||||
use rustc_errors::{translation::Translate, DiagnosticId, FatalError, Handler, Level};
|
||||
use rustc_errors::{DiagnosticMessage, Style};
|
||||
use rustc_fs_util::link_or_copy;
|
||||
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
|
||||
use rustc_incremental::{
|
||||
@ -38,6 +36,7 @@ use rustc_span::{BytePos, FileName, InnerSpan, Pos, Span};
|
||||
use rustc_target::spec::{MergeFunctions, SanitizerSet};
|
||||
|
||||
use std::any::Any;
|
||||
use std::borrow::Cow;
|
||||
use std::fs;
|
||||
use std::io;
|
||||
use std::marker::PhantomData;
|
||||
@ -969,8 +968,11 @@ pub enum Message<B: WriteBackendMethods> {
|
||||
CodegenAborted,
|
||||
}
|
||||
|
||||
type DiagnosticArgName<'source> = Cow<'source, str>;
|
||||
|
||||
struct Diagnostic {
|
||||
msg: String,
|
||||
msg: Vec<(DiagnosticMessage, Style)>,
|
||||
args: FxHashMap<DiagnosticArgName<'static>, rustc_errors::DiagnosticArgValue<'static>>,
|
||||
code: Option<DiagnosticId>,
|
||||
lvl: Level,
|
||||
}
|
||||
@ -1743,15 +1745,18 @@ impl Translate for SharedEmitter {
|
||||
|
||||
impl Emitter for SharedEmitter {
|
||||
fn emit_diagnostic(&mut self, diag: &rustc_errors::Diagnostic) {
|
||||
let fluent_args = to_fluent_args(diag.args());
|
||||
let args: FxHashMap<Cow<'_, str>, rustc_errors::DiagnosticArgValue<'_>> =
|
||||
diag.args().map(|(name, arg)| (name.clone(), arg.clone())).collect();
|
||||
drop(self.sender.send(SharedEmitterMessage::Diagnostic(Diagnostic {
|
||||
msg: self.translate_messages(&diag.message, &fluent_args).to_string(),
|
||||
msg: diag.message.clone(),
|
||||
args: args.clone(),
|
||||
code: diag.code.clone(),
|
||||
lvl: diag.level(),
|
||||
})));
|
||||
for child in &diag.children {
|
||||
drop(self.sender.send(SharedEmitterMessage::Diagnostic(Diagnostic {
|
||||
msg: self.translate_messages(&child.message, &fluent_args).to_string(),
|
||||
msg: child.message.clone(),
|
||||
args: args.clone(),
|
||||
code: None,
|
||||
lvl: child.level,
|
||||
})));
|
||||
@ -1782,10 +1787,11 @@ impl SharedEmitterMain {
|
||||
match message {
|
||||
Ok(SharedEmitterMessage::Diagnostic(diag)) => {
|
||||
let handler = sess.diagnostic();
|
||||
let mut d = rustc_errors::Diagnostic::new(diag.lvl, &diag.msg);
|
||||
let mut d = rustc_errors::Diagnostic::new_with_messages(diag.lvl, diag.msg);
|
||||
if let Some(code) = diag.code {
|
||||
d.code(code);
|
||||
}
|
||||
d.replace_args(diag.args);
|
||||
handler.emit_diagnostic(&mut d);
|
||||
}
|
||||
Ok(SharedEmitterMessage::InlineAsmError(cookie, msg, level, source)) => {
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||
#![feature(once_cell)]
|
||||
#![feature(decl_macro)]
|
||||
#![recursion_limit = "256"]
|
||||
#![allow(rustc::potential_query_instability)]
|
||||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
@ -753,20 +754,41 @@ fn print_crate_info(
|
||||
}
|
||||
|
||||
/// Prints version information
|
||||
pub fn version(binary: &str, matches: &getopts::Matches) {
|
||||
///
|
||||
/// NOTE: this is a macro to support drivers built at a different time than the main `rustc_driver` crate.
|
||||
pub macro version($binary: literal, $matches: expr) {
|
||||
fn unw(x: Option<&str>) -> &str {
|
||||
x.unwrap_or("unknown")
|
||||
}
|
||||
$crate::version_at_macro_invocation(
|
||||
$binary,
|
||||
$matches,
|
||||
unw(option_env!("CFG_VERSION")),
|
||||
unw(option_env!("CFG_VER_HASH")),
|
||||
unw(option_env!("CFG_VER_DATE")),
|
||||
unw(option_env!("CFG_RELEASE")),
|
||||
)
|
||||
}
|
||||
|
||||
#[doc(hidden)] // use the macro instead
|
||||
pub fn version_at_macro_invocation(
|
||||
binary: &str,
|
||||
matches: &getopts::Matches,
|
||||
version: &str,
|
||||
commit_hash: &str,
|
||||
commit_date: &str,
|
||||
release: &str,
|
||||
) {
|
||||
let verbose = matches.opt_present("verbose");
|
||||
|
||||
println!("{} {}", binary, util::version_str().unwrap_or("unknown version"));
|
||||
println!("{} {}", binary, version);
|
||||
|
||||
if verbose {
|
||||
fn unw(x: Option<&str>) -> &str {
|
||||
x.unwrap_or("unknown")
|
||||
}
|
||||
println!("binary: {}", binary);
|
||||
println!("commit-hash: {}", unw(util::commit_hash_str()));
|
||||
println!("commit-date: {}", unw(util::commit_date_str()));
|
||||
println!("commit-hash: {}", commit_hash);
|
||||
println!("commit-date: {}", commit_date);
|
||||
println!("host: {}", config::host_triple());
|
||||
println!("release: {}", unw(util::release_str()));
|
||||
println!("release: {}", release);
|
||||
|
||||
let debug_flags = matches.opt_strs("Z");
|
||||
let backend_name = debug_flags.iter().find_map(|x| x.strip_prefix("codegen-backend="));
|
||||
@ -1082,7 +1104,7 @@ pub fn handle_options(args: &[String]) -> Option<getopts::Matches> {
|
||||
}
|
||||
|
||||
if matches.opt_present("version") {
|
||||
version("rustc", &matches);
|
||||
version!("rustc", &matches);
|
||||
return None;
|
||||
}
|
||||
|
||||
@ -1227,7 +1249,7 @@ pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) {
|
||||
format!("we would appreciate a bug report: {}", bug_report_url).into(),
|
||||
format!(
|
||||
"rustc {} running on {}",
|
||||
util::version_str().unwrap_or("unknown_version"),
|
||||
util::version_str!().unwrap_or("unknown_version"),
|
||||
config::host_triple()
|
||||
)
|
||||
.into(),
|
||||
|
58
compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl
Normal file
58
compiler/rustc_error_messages/locales/en-US/codegen_llvm.ftl
Normal file
@ -0,0 +1,58 @@
|
||||
codegen_llvm_unknown_ctarget_feature =
|
||||
unknown feature specified for `-Ctarget-feature`: `{$feature}`
|
||||
.note = it is still passed through to the codegen backend
|
||||
.possible_feature = you might have meant: `{$rust_feature}`
|
||||
.consider_filing_feature_request = consider filing a feature request
|
||||
|
||||
codegen_llvm_unknown_ctarget_feature_prefix =
|
||||
unknown feature specified for `-Ctarget-feature`: `{$feature}`
|
||||
.note = features must begin with a `+` to enable or `-` to disable it
|
||||
|
||||
codegen_llvm_error_creating_import_library =
|
||||
Error creating import library for {$lib_name}: {$error}
|
||||
|
||||
codegen_llvm_instrument_coverage_requires_llvm_12 =
|
||||
rustc option `-C instrument-coverage` requires LLVM 12 or higher.
|
||||
|
||||
codegen_llvm_symbol_already_defined =
|
||||
symbol `{$symbol_name}` is already defined
|
||||
|
||||
codegen_llvm_branch_protection_requires_aarch64 =
|
||||
-Zbranch-protection is only supported on aarch64
|
||||
|
||||
codegen_llvm_invalid_minimum_alignment =
|
||||
invalid minimum global alignment: {$err}
|
||||
|
||||
codegen_llvm_linkage_const_or_mut_type =
|
||||
must have type `*const T` or `*mut T` due to `#[linkage]` attribute
|
||||
|
||||
codegen_llvm_sanitizer_memtag_requires_mte =
|
||||
`-Zsanitizer=memtag` requires `-Ctarget-feature=+mte`
|
||||
|
||||
codegen_llvm_archive_build_failure =
|
||||
failed to build archive: {$error}
|
||||
|
||||
codegen_llvm_error_writing_def_file =
|
||||
Error writing .DEF file: {$error}
|
||||
|
||||
codegen_llvm_error_calling_dlltool =
|
||||
Error calling dlltool: {$error}
|
||||
|
||||
codegen_llvm_dlltool_fail_import_library =
|
||||
Dlltool could not create import library: {$stdout}\n{$stderr}
|
||||
|
||||
codegen_llvm_unknown_archive_kind =
|
||||
Don't know how to build archive of type: {$kind}
|
||||
|
||||
codegen_llvm_target_feature_disable_or_enable =
|
||||
the target features {$features} must all be either enabled or disabled together
|
||||
|
||||
codegen_llvm_missing_features =
|
||||
add the missing features in a `target_feature` attribute
|
||||
|
||||
codegen_llvm_dynamic_linking_with_lto =
|
||||
cannot prefer dynamic linking when performing LTO
|
||||
.note = only 'staticlib', 'bin', and 'cdylib' outputs are supported with LTO
|
||||
|
||||
codegen_llvm_fail_parsing_target_machine_config_to_target_machine =
|
||||
failed to parse target machine config to target machine: {$error}
|
@ -42,6 +42,7 @@ fluent_messages! {
|
||||
borrowck => "../locales/en-US/borrowck.ftl",
|
||||
builtin_macros => "../locales/en-US/builtin_macros.ftl",
|
||||
codegen_gcc => "../locales/en-US/codegen_gcc.ftl",
|
||||
codegen_llvm => "../locales/en-US/codegen_llvm.ftl",
|
||||
codegen_ssa => "../locales/en-US/codegen_ssa.ftl",
|
||||
compiletest => "../locales/en-US/compiletest.ftl",
|
||||
const_eval => "../locales/en-US/const_eval.ftl",
|
||||
|
@ -44,6 +44,15 @@ pub trait IntoDiagnosticArg {
|
||||
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static>;
|
||||
}
|
||||
|
||||
impl<'source> IntoDiagnosticArg for DiagnosticArgValue<'source> {
|
||||
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
|
||||
match self {
|
||||
DiagnosticArgValue::Str(s) => DiagnosticArgValue::Str(Cow::Owned(s.into_owned())),
|
||||
DiagnosticArgValue::Number(n) => DiagnosticArgValue::Number(n),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'source> Into<FluentValue<'source>> for DiagnosticArgValue<'source> {
|
||||
fn into(self) -> FluentValue<'source> {
|
||||
match self {
|
||||
@ -204,6 +213,22 @@ impl Diagnostic {
|
||||
Diagnostic::new_with_code(level, None, message)
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub fn new_with_messages(level: Level, messages: Vec<(DiagnosticMessage, Style)>) -> Self {
|
||||
Diagnostic {
|
||||
level,
|
||||
message: messages,
|
||||
code: None,
|
||||
span: MultiSpan::new(),
|
||||
children: vec![],
|
||||
suggestions: Ok(vec![]),
|
||||
args: Default::default(),
|
||||
sort_span: DUMMY_SP,
|
||||
is_lint: false,
|
||||
emitted_at: DiagnosticLocation::caller(),
|
||||
}
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub fn new_with_code<M: Into<DiagnosticMessage>>(
|
||||
level: Level,
|
||||
@ -931,6 +956,13 @@ impl Diagnostic {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn replace_args(
|
||||
&mut self,
|
||||
args: FxHashMap<DiagnosticArgName<'static>, DiagnosticArgValue<'static>>,
|
||||
) {
|
||||
self.args = args;
|
||||
}
|
||||
|
||||
pub fn styled_message(&self) -> &[(DiagnosticMessage, Style)] {
|
||||
&self.message
|
||||
}
|
||||
|
@ -107,6 +107,12 @@ impl IntoDiagnosticArg for String {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoDiagnosticArg for Cow<'a, str> {
|
||||
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
|
||||
DiagnosticArgValue::Str(Cow::Owned(self.into_owned()))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoDiagnosticArg for &'a Path {
|
||||
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
|
||||
DiagnosticArgValue::Str(Cow::Owned(self.display().to_string()))
|
||||
|
@ -152,6 +152,8 @@ declare_features! (
|
||||
(active, anonymous_lifetime_in_impl_trait, "1.63.0", None, None),
|
||||
/// Allows identifying the `compiler_builtins` crate.
|
||||
(active, compiler_builtins, "1.13.0", None, None),
|
||||
/// Allows writing custom MIR
|
||||
(active, custom_mir, "1.65.0", None, None),
|
||||
/// Outputs useful `assert!` messages
|
||||
(active, generic_assert, "1.63.0", None, None),
|
||||
/// Allows using the `rust-intrinsic`'s "ABI".
|
||||
|
@ -810,6 +810,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
||||
rustc_attr!(TEST, rustc_polymorphize_error, Normal, template!(Word), WarnFollowing),
|
||||
rustc_attr!(TEST, rustc_def_path, Normal, template!(Word), WarnFollowing),
|
||||
rustc_attr!(TEST, rustc_mir, Normal, template!(List: "arg1, arg2, ..."), DuplicatesOk),
|
||||
gated!(
|
||||
custom_mir, Normal, template!(List: r#"dialect = "...", phase = "...""#),
|
||||
ErrorFollowing, "the `#[custom_mir]` attribute is just used for the Rust test suite",
|
||||
),
|
||||
rustc_attr!(TEST, rustc_dump_program_clauses, Normal, template!(Word), WarnFollowing),
|
||||
rustc_attr!(TEST, rustc_dump_env_program_clauses, Normal, template!(Word), WarnFollowing),
|
||||
rustc_attr!(TEST, rustc_object_lifetime_default, Normal, template!(Word), WarnFollowing),
|
||||
|
@ -1708,8 +1708,7 @@ fn receiver_is_valid<'tcx>(
|
||||
return true;
|
||||
}
|
||||
|
||||
let mut autoderef =
|
||||
Autoderef::new(infcx, wfcx.param_env, wfcx.body_id, span, receiver_ty, span);
|
||||
let mut autoderef = Autoderef::new(infcx, wfcx.param_env, wfcx.body_id, span, receiver_ty);
|
||||
|
||||
// The `arbitrary_self_types` feature allows raw pointer receivers like `self: *const Self`.
|
||||
if arbitrary_self_types_enabled {
|
||||
|
@ -12,18 +12,7 @@ use std::iter;
|
||||
|
||||
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
pub fn autoderef(&'a self, span: Span, base_ty: Ty<'tcx>) -> Autoderef<'a, 'tcx> {
|
||||
Autoderef::new(self, self.param_env, self.body_id, span, base_ty, span)
|
||||
}
|
||||
|
||||
/// Like `autoderef`, but provides a custom `Span` to use for calls to
|
||||
/// an overloaded `Deref` operator
|
||||
pub fn autoderef_overloaded_span(
|
||||
&'a self,
|
||||
span: Span,
|
||||
base_ty: Ty<'tcx>,
|
||||
overloaded_span: Span,
|
||||
) -> Autoderef<'a, 'tcx> {
|
||||
Autoderef::new(self, self.param_env, self.body_id, span, base_ty, overloaded_span)
|
||||
Autoderef::new(self, self.param_env, self.body_id, span, base_ty)
|
||||
}
|
||||
|
||||
pub fn try_overloaded_deref(
|
||||
@ -55,11 +44,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
|InferOk { value: method, obligations: o }| {
|
||||
obligations.extend(o);
|
||||
if let ty::Ref(region, _, mutbl) = *method.sig.output().kind() {
|
||||
Some(OverloadedDeref {
|
||||
region,
|
||||
mutbl,
|
||||
span: autoderef.overloaded_span(),
|
||||
})
|
||||
Some(OverloadedDeref { region, mutbl, span: autoderef.span() })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -151,8 +151,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
||||
) -> Ty<'tcx> {
|
||||
// Commit the autoderefs by calling `autoderef` again, but this
|
||||
// time writing the results into the various typeck results.
|
||||
let mut autoderef =
|
||||
self.autoderef_overloaded_span(self.span, unadjusted_self_ty, self.call_expr.span);
|
||||
let mut autoderef = self.autoderef(self.call_expr.span, unadjusted_self_ty);
|
||||
let Some((ty, n)) = autoderef.nth(pick.autoderefs) else {
|
||||
return self.tcx.ty_error_with_message(
|
||||
rustc_span::DUMMY_SP,
|
||||
|
@ -475,10 +475,9 @@ fn method_autoderef_steps<'tcx>(
|
||||
let (ref infcx, goal, inference_vars) = tcx.infer_ctxt().build_with_canonical(DUMMY_SP, &goal);
|
||||
let ParamEnvAnd { param_env, value: self_ty } = goal;
|
||||
|
||||
let mut autoderef =
|
||||
Autoderef::new(infcx, param_env, hir::CRATE_HIR_ID, DUMMY_SP, self_ty, DUMMY_SP)
|
||||
.include_raw_pointers()
|
||||
.silence_errors();
|
||||
let mut autoderef = Autoderef::new(infcx, param_env, hir::CRATE_HIR_ID, DUMMY_SP, self_ty)
|
||||
.include_raw_pointers()
|
||||
.silence_errors();
|
||||
let mut reached_raw_pointer = false;
|
||||
let mut steps: Vec<_> = autoderef
|
||||
.by_ref()
|
||||
|
@ -19,7 +19,6 @@ use rustc_span::lev_distance::find_best_match_for_name;
|
||||
use rustc_span::source_map::{Span, Spanned};
|
||||
use rustc_span::symbol::{kw, sym, Ident};
|
||||
use rustc_span::{BytePos, DUMMY_SP};
|
||||
use rustc_trait_selection::autoderef::Autoderef;
|
||||
use rustc_trait_selection::traits::{ObligationCause, Pattern};
|
||||
use ty::VariantDef;
|
||||
|
||||
@ -2132,7 +2131,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
&& let ty::Array(..) | ty::Slice(..) = ty.kind()
|
||||
{
|
||||
err.help("the semantics of slice patterns changed recently; see issue #62254");
|
||||
} else if Autoderef::new(&self.infcx, self.param_env, self.body_id, span, expected_ty, span)
|
||||
} else if self.autoderef(span, expected_ty)
|
||||
.any(|(ty, _)| matches!(ty.kind(), ty::Slice(..) | ty::Array(..)))
|
||||
&& let (Some(span), true) = (ti.span, ti.origin_expr)
|
||||
&& let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
|
||||
|
@ -1,4 +1,5 @@
|
||||
#![feature(box_patterns)]
|
||||
#![feature(decl_macro)]
|
||||
#![feature(internal_output_capture)]
|
||||
#![feature(thread_spawn_unchecked)]
|
||||
#![feature(once_cell)]
|
||||
|
@ -327,7 +327,7 @@ fn get_codegen_sysroot(maybe_sysroot: &Option<PathBuf>, backend_name: &str) -> M
|
||||
let mut file: Option<PathBuf> = None;
|
||||
|
||||
let expected_names = &[
|
||||
format!("rustc_codegen_{}-{}", backend_name, release_str().expect("CFG_RELEASE")),
|
||||
format!("rustc_codegen_{}-{}", backend_name, env!("CFG_RELEASE")),
|
||||
format!("rustc_codegen_{}", backend_name),
|
||||
];
|
||||
for entry in d.filter_map(|e| e.ok()) {
|
||||
@ -554,22 +554,12 @@ pub fn build_output_filenames(
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a version string such as "1.46.0 (04488afe3 2020-08-24)"
|
||||
pub fn version_str() -> Option<&'static str> {
|
||||
/// Returns a version string such as "1.46.0 (04488afe3 2020-08-24)" when invoked by an in-tree tool.
|
||||
pub macro version_str() {
|
||||
option_env!("CFG_VERSION")
|
||||
}
|
||||
|
||||
/// Returns a version string such as "0.12.0-dev".
|
||||
pub fn release_str() -> Option<&'static str> {
|
||||
option_env!("CFG_RELEASE")
|
||||
}
|
||||
|
||||
/// Returns the full SHA1 hash of HEAD of the Git repo from which rustc was built.
|
||||
pub fn commit_hash_str() -> Option<&'static str> {
|
||||
option_env!("CFG_VER_HASH")
|
||||
}
|
||||
|
||||
/// Returns the "commit date" of HEAD of the Git repo from which rustc was built as a static string.
|
||||
pub fn commit_date_str() -> Option<&'static str> {
|
||||
option_env!("CFG_VER_DATE")
|
||||
/// Returns the version string for `rustc` itself (which may be different from a tool version).
|
||||
pub fn rustc_version_str() -> Option<&'static str> {
|
||||
version_str!()
|
||||
}
|
||||
|
@ -138,6 +138,48 @@ impl MirPhase {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Parses an `MirPhase` from a pair of strings. Panics if this isn't possible for any reason.
|
||||
pub fn parse(dialect: String, phase: Option<String>) -> Self {
|
||||
match &*dialect.to_ascii_lowercase() {
|
||||
"built" => {
|
||||
assert!(phase.is_none(), "Cannot specify a phase for `Built` MIR");
|
||||
MirPhase::Built
|
||||
}
|
||||
"analysis" => Self::Analysis(AnalysisPhase::parse(phase)),
|
||||
"runtime" => Self::Runtime(RuntimePhase::parse(phase)),
|
||||
_ => panic!("Unknown MIR dialect {}", dialect),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AnalysisPhase {
|
||||
pub fn parse(phase: Option<String>) -> Self {
|
||||
let Some(phase) = phase else {
|
||||
return Self::Initial;
|
||||
};
|
||||
|
||||
match &*phase.to_ascii_lowercase() {
|
||||
"initial" => Self::Initial,
|
||||
"post_cleanup" | "post-cleanup" | "postcleanup" => Self::PostCleanup,
|
||||
_ => panic!("Unknown analysis phase {}", phase),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl RuntimePhase {
|
||||
pub fn parse(phase: Option<String>) -> Self {
|
||||
let Some(phase) = phase else {
|
||||
return Self::Initial;
|
||||
};
|
||||
|
||||
match &*phase.to_ascii_lowercase() {
|
||||
"initial" => Self::Initial,
|
||||
"post_cleanup" | "post-cleanup" | "postcleanup" => Self::PostCleanup,
|
||||
"optimized" => Self::Optimized,
|
||||
_ => panic!("Unknown runtime phase {}", phase),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for MirPhase {
|
||||
@ -293,6 +335,13 @@ pub struct Body<'tcx> {
|
||||
/// potentially allow things like `[u8; std::mem::size_of::<T>() * 0]` due to this.
|
||||
pub is_polymorphic: bool,
|
||||
|
||||
/// The phase at which this MIR should be "injected" into the compilation process.
|
||||
///
|
||||
/// Everything that comes before this `MirPhase` should be skipped.
|
||||
///
|
||||
/// This is only `Some` if the function that this body comes from was annotated with `rustc_custom_mir`.
|
||||
pub injection_phase: Option<MirPhase>,
|
||||
|
||||
pub tainted_by_errors: Option<ErrorGuaranteed>,
|
||||
}
|
||||
|
||||
@ -339,6 +388,7 @@ impl<'tcx> Body<'tcx> {
|
||||
span,
|
||||
required_consts: Vec::new(),
|
||||
is_polymorphic: false,
|
||||
injection_phase: None,
|
||||
tainted_by_errors,
|
||||
};
|
||||
body.is_polymorphic = body.has_non_region_param();
|
||||
@ -366,6 +416,7 @@ impl<'tcx> Body<'tcx> {
|
||||
required_consts: Vec::new(),
|
||||
var_debug_info: Vec::new(),
|
||||
is_polymorphic: false,
|
||||
injection_phase: None,
|
||||
tainted_by_errors: None,
|
||||
};
|
||||
body.is_polymorphic = body.has_non_region_param();
|
||||
@ -508,6 +559,14 @@ impl<'tcx> Body<'tcx> {
|
||||
pub fn generator_kind(&self) -> Option<GeneratorKind> {
|
||||
self.generator.as_ref().map(|generator| generator.generator_kind)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn should_skip(&self) -> bool {
|
||||
let Some(injection_phase) = self.injection_phase else {
|
||||
return false;
|
||||
};
|
||||
injection_phase > self.phase
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug, TyEncodable, TyDecodable, HashStable)]
|
||||
|
@ -189,8 +189,8 @@ pub enum LayoutError<'tcx> {
|
||||
NormalizationFailure(Ty<'tcx>, NormalizationError<'tcx>),
|
||||
}
|
||||
|
||||
impl<'a> IntoDiagnostic<'a, !> for LayoutError<'a> {
|
||||
fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, !> {
|
||||
impl IntoDiagnostic<'_, !> for LayoutError<'_> {
|
||||
fn into_diagnostic(self, handler: &Handler) -> DiagnosticBuilder<'_, !> {
|
||||
let mut diag = handler.struct_fatal("");
|
||||
|
||||
match self {
|
||||
@ -1126,8 +1126,8 @@ impl<'tcx> fmt::Display for FnAbiError<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> IntoDiagnostic<'tcx, !> for FnAbiError<'tcx> {
|
||||
fn into_diagnostic(self, handler: &'tcx Handler) -> DiagnosticBuilder<'tcx, !> {
|
||||
impl IntoDiagnostic<'_, !> for FnAbiError<'_> {
|
||||
fn into_diagnostic(self, handler: &Handler) -> DiagnosticBuilder<'_, !> {
|
||||
handler.struct_fatal(self.to_string())
|
||||
}
|
||||
}
|
||||
|
155
compiler/rustc_mir_build/src/build/custom/mod.rs
Normal file
155
compiler/rustc_mir_build/src/build/custom/mod.rs
Normal file
@ -0,0 +1,155 @@
|
||||
//! Provides the implementation of the `custom_mir` attribute.
|
||||
//!
|
||||
//! Up until MIR building, this attribute has absolutely no effect. The `mir!` macro is a normal
|
||||
//! decl macro that expands like any other, and the code goes through parsing, name resolution and
|
||||
//! type checking like all other code. In MIR building we finally detect whether this attribute is
|
||||
//! present, and if so we branch off into this module, which implements the attribute by
|
||||
//! implementing a custom lowering from THIR to MIR.
|
||||
//!
|
||||
//! The result of this lowering is returned "normally" from the `mir_built` query, with the only
|
||||
//! notable difference being that the `injected` field in the body is set. Various components of the
|
||||
//! MIR pipeline, like borrowck and the pass manager will then consult this field (via
|
||||
//! `body.should_skip()`) to skip the parts of the MIR pipeline that precede the MIR phase the user
|
||||
//! specified.
|
||||
//!
|
||||
//! This file defines the general framework for the custom parsing. The parsing for all the
|
||||
//! "top-level" constructs can be found in the `parse` submodule, while the parsing for statements,
|
||||
//! terminators, and everything below can be found in the `parse::instruction` submodule.
|
||||
//!
|
||||
|
||||
use rustc_ast::Attribute;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_index::vec::IndexVec;
|
||||
use rustc_middle::{
|
||||
mir::*,
|
||||
thir::*,
|
||||
ty::{Ty, TyCtxt},
|
||||
};
|
||||
use rustc_span::Span;
|
||||
|
||||
mod parse;
|
||||
|
||||
pub(super) fn build_custom_mir<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
did: DefId,
|
||||
thir: &Thir<'tcx>,
|
||||
expr: ExprId,
|
||||
params: &IndexVec<ParamId, Param<'tcx>>,
|
||||
return_ty: Ty<'tcx>,
|
||||
return_ty_span: Span,
|
||||
span: Span,
|
||||
attr: &Attribute,
|
||||
) -> Body<'tcx> {
|
||||
let mut body = Body {
|
||||
basic_blocks: BasicBlocks::new(IndexVec::new()),
|
||||
source: MirSource::item(did),
|
||||
phase: MirPhase::Built,
|
||||
source_scopes: IndexVec::new(),
|
||||
generator: None,
|
||||
local_decls: LocalDecls::new(),
|
||||
user_type_annotations: IndexVec::new(),
|
||||
arg_count: params.len(),
|
||||
spread_arg: None,
|
||||
var_debug_info: Vec::new(),
|
||||
span,
|
||||
required_consts: Vec::new(),
|
||||
is_polymorphic: false,
|
||||
tainted_by_errors: None,
|
||||
injection_phase: None,
|
||||
pass_count: 1,
|
||||
};
|
||||
|
||||
body.local_decls.push(LocalDecl::new(return_ty, return_ty_span));
|
||||
body.basic_blocks_mut().push(BasicBlockData::new(None));
|
||||
body.source_scopes.push(SourceScopeData {
|
||||
span,
|
||||
parent_scope: None,
|
||||
inlined: None,
|
||||
inlined_parent_scope: None,
|
||||
local_data: ClearCrossCrate::Clear,
|
||||
});
|
||||
body.injection_phase = Some(parse_attribute(attr));
|
||||
|
||||
let mut pctxt = ParseCtxt {
|
||||
tcx,
|
||||
thir,
|
||||
source_info: SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE },
|
||||
body: &mut body,
|
||||
local_map: FxHashMap::default(),
|
||||
block_map: FxHashMap::default(),
|
||||
};
|
||||
|
||||
let res = (|| {
|
||||
pctxt.parse_args(¶ms)?;
|
||||
pctxt.parse_body(expr)
|
||||
})();
|
||||
if let Err(err) = res {
|
||||
tcx.sess.diagnostic().span_fatal(
|
||||
err.span,
|
||||
format!("Could not parse {}, found: {:?}", err.expected, err.item_description),
|
||||
)
|
||||
}
|
||||
|
||||
body
|
||||
}
|
||||
|
||||
fn parse_attribute(attr: &Attribute) -> MirPhase {
|
||||
let meta_items = attr.meta_item_list().unwrap();
|
||||
let mut dialect: Option<String> = None;
|
||||
let mut phase: Option<String> = None;
|
||||
|
||||
for nested in meta_items {
|
||||
let name = nested.name_or_empty();
|
||||
let value = nested.value_str().unwrap().as_str().to_string();
|
||||
match name.as_str() {
|
||||
"dialect" => {
|
||||
assert!(dialect.is_none());
|
||||
dialect = Some(value);
|
||||
}
|
||||
"phase" => {
|
||||
assert!(phase.is_none());
|
||||
phase = Some(value);
|
||||
}
|
||||
other => {
|
||||
panic!("Unexpected key {}", other);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let Some(dialect) = dialect else {
|
||||
assert!(phase.is_none());
|
||||
return MirPhase::Built;
|
||||
};
|
||||
|
||||
MirPhase::parse(dialect, phase)
|
||||
}
|
||||
|
||||
struct ParseCtxt<'tcx, 'body> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
thir: &'body Thir<'tcx>,
|
||||
source_info: SourceInfo,
|
||||
|
||||
body: &'body mut Body<'tcx>,
|
||||
local_map: FxHashMap<LocalVarId, Local>,
|
||||
block_map: FxHashMap<LocalVarId, BasicBlock>,
|
||||
}
|
||||
|
||||
struct ParseError {
|
||||
span: Span,
|
||||
item_description: String,
|
||||
expected: String,
|
||||
}
|
||||
|
||||
impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
|
||||
fn expr_error(&self, expr: ExprId, expected: &'static str) -> ParseError {
|
||||
let expr = &self.thir[expr];
|
||||
ParseError {
|
||||
span: expr.span,
|
||||
item_description: format!("{:?}", expr.kind),
|
||||
expected: expected.to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type PResult<T> = Result<T, ParseError>;
|
245
compiler/rustc_mir_build/src/build/custom/parse.rs
Normal file
245
compiler/rustc_mir_build/src/build/custom/parse.rs
Normal file
@ -0,0 +1,245 @@
|
||||
use rustc_index::vec::IndexVec;
|
||||
use rustc_middle::{mir::*, thir::*, ty::Ty};
|
||||
use rustc_span::Span;
|
||||
|
||||
use super::{PResult, ParseCtxt, ParseError};
|
||||
|
||||
mod instruction;
|
||||
|
||||
/// Helper macro for parsing custom MIR.
|
||||
///
|
||||
/// Example usage looks something like:
|
||||
/// ```rust,ignore (incomplete example)
|
||||
/// parse_by_kind!(
|
||||
/// self, // : &ParseCtxt
|
||||
/// expr_id, // what you're matching against
|
||||
/// "assignment", // the thing you're trying to parse
|
||||
/// @call("mir_assign", args) => { args[0] }, // match invocations of the `mir_assign` special function
|
||||
/// ExprKind::Assign { lhs, .. } => { lhs }, // match thir assignment expressions
|
||||
/// // no need for fallthrough case - reasonable error is automatically generated
|
||||
/// )
|
||||
/// ```
|
||||
macro_rules! parse_by_kind {
|
||||
(
|
||||
$self:ident,
|
||||
$expr_id:expr,
|
||||
$expected:literal,
|
||||
$(
|
||||
@call($name:literal, $args:ident) => $call_expr:expr,
|
||||
)*
|
||||
$(
|
||||
$pat:pat => $expr:expr,
|
||||
)*
|
||||
) => {{
|
||||
let expr_id = $self.preparse($expr_id);
|
||||
let expr = &$self.thir[expr_id];
|
||||
match &expr.kind {
|
||||
$(
|
||||
ExprKind::Call { ty, fun: _, args: $args, .. } if {
|
||||
match ty.kind() {
|
||||
ty::FnDef(did, _) => {
|
||||
$self.tcx.is_diagnostic_item(rustc_span::Symbol::intern($name), *did)
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
} => $call_expr,
|
||||
)*
|
||||
$(
|
||||
$pat => $expr,
|
||||
)*
|
||||
#[allow(unreachable_patterns)]
|
||||
_ => return Err($self.expr_error(expr_id, $expected))
|
||||
}
|
||||
}};
|
||||
}
|
||||
pub(crate) use parse_by_kind;
|
||||
|
||||
impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
|
||||
/// Expressions should only ever be matched on after preparsing them. This removes extra scopes
|
||||
/// we don't care about.
|
||||
fn preparse(&self, expr_id: ExprId) -> ExprId {
|
||||
let expr = &self.thir[expr_id];
|
||||
match expr.kind {
|
||||
ExprKind::Scope { value, .. } => self.preparse(value),
|
||||
_ => expr_id,
|
||||
}
|
||||
}
|
||||
|
||||
fn statement_as_expr(&self, stmt_id: StmtId) -> PResult<ExprId> {
|
||||
match &self.thir[stmt_id].kind {
|
||||
StmtKind::Expr { expr, .. } => Ok(*expr),
|
||||
kind @ StmtKind::Let { pattern, .. } => {
|
||||
return Err(ParseError {
|
||||
span: pattern.span,
|
||||
item_description: format!("{:?}", kind),
|
||||
expected: "expression".to_string(),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_args(&mut self, params: &IndexVec<ParamId, Param<'tcx>>) -> PResult<()> {
|
||||
for param in params.iter() {
|
||||
let (var, span) = {
|
||||
let pat = param.pat.as_ref().unwrap();
|
||||
match &pat.kind {
|
||||
PatKind::Binding { var, .. } => (*var, pat.span),
|
||||
_ => {
|
||||
return Err(ParseError {
|
||||
span: pat.span,
|
||||
item_description: format!("{:?}", pat.kind),
|
||||
expected: "local".to_string(),
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
let decl = LocalDecl::new(param.ty, span);
|
||||
let local = self.body.local_decls.push(decl);
|
||||
self.local_map.insert(var, local);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Bodies are of the form:
|
||||
///
|
||||
/// ```text
|
||||
/// {
|
||||
/// let bb1: BasicBlock;
|
||||
/// let bb2: BasicBlock;
|
||||
/// {
|
||||
/// let RET: _;
|
||||
/// let local1;
|
||||
/// let local2;
|
||||
///
|
||||
/// {
|
||||
/// { // entry block
|
||||
/// statement1;
|
||||
/// terminator1
|
||||
/// };
|
||||
///
|
||||
/// bb1 = {
|
||||
/// statement2;
|
||||
/// terminator2
|
||||
/// };
|
||||
///
|
||||
/// bb2 = {
|
||||
/// statement3;
|
||||
/// terminator3
|
||||
/// }
|
||||
///
|
||||
/// RET
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// This allows us to easily parse the basic blocks declarations, local declarations, and
|
||||
/// basic block definitions in order.
|
||||
pub fn parse_body(&mut self, expr_id: ExprId) -> PResult<()> {
|
||||
let body = parse_by_kind!(self, expr_id, "whole body",
|
||||
ExprKind::Block { block } => self.thir[*block].expr.unwrap(),
|
||||
);
|
||||
let (block_decls, rest) = parse_by_kind!(self, body, "body with block decls",
|
||||
ExprKind::Block { block } => {
|
||||
let block = &self.thir[*block];
|
||||
(&block.stmts, block.expr.unwrap())
|
||||
},
|
||||
);
|
||||
self.parse_block_decls(block_decls.iter().copied())?;
|
||||
|
||||
let (local_decls, rest) = parse_by_kind!(self, rest, "body with local decls",
|
||||
ExprKind::Block { block } => {
|
||||
let block = &self.thir[*block];
|
||||
(&block.stmts, block.expr.unwrap())
|
||||
},
|
||||
);
|
||||
self.parse_local_decls(local_decls.iter().copied())?;
|
||||
|
||||
let block_defs = parse_by_kind!(self, rest, "body with block defs",
|
||||
ExprKind::Block { block } => &self.thir[*block].stmts,
|
||||
);
|
||||
for (i, block_def) in block_defs.iter().enumerate() {
|
||||
let block = self.parse_block_def(self.statement_as_expr(*block_def)?)?;
|
||||
self.body.basic_blocks_mut()[BasicBlock::from_usize(i)] = block;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn parse_block_decls(&mut self, stmts: impl Iterator<Item = StmtId>) -> PResult<()> {
|
||||
for stmt in stmts {
|
||||
let (var, _, _) = self.parse_let_statement(stmt)?;
|
||||
let data = BasicBlockData::new(None);
|
||||
let block = self.body.basic_blocks_mut().push(data);
|
||||
self.block_map.insert(var, block);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn parse_local_decls(&mut self, mut stmts: impl Iterator<Item = StmtId>) -> PResult<()> {
|
||||
let (ret_var, ..) = self.parse_let_statement(stmts.next().unwrap())?;
|
||||
self.local_map.insert(ret_var, Local::from_u32(0));
|
||||
|
||||
for stmt in stmts {
|
||||
let (var, ty, span) = self.parse_let_statement(stmt)?;
|
||||
let decl = LocalDecl::new(ty, span);
|
||||
let local = self.body.local_decls.push(decl);
|
||||
self.local_map.insert(var, local);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn parse_let_statement(&mut self, stmt_id: StmtId) -> PResult<(LocalVarId, Ty<'tcx>, Span)> {
|
||||
let pattern = match &self.thir[stmt_id].kind {
|
||||
StmtKind::Let { pattern, .. } => pattern,
|
||||
StmtKind::Expr { expr, .. } => {
|
||||
return Err(self.expr_error(*expr, "let statement"));
|
||||
}
|
||||
};
|
||||
|
||||
self.parse_var(pattern)
|
||||
}
|
||||
|
||||
fn parse_var(&mut self, mut pat: &Pat<'tcx>) -> PResult<(LocalVarId, Ty<'tcx>, Span)> {
|
||||
// Make sure we throw out any `AscribeUserType` we find
|
||||
loop {
|
||||
match &pat.kind {
|
||||
PatKind::Binding { var, ty, .. } => break Ok((*var, *ty, pat.span)),
|
||||
PatKind::AscribeUserType { subpattern, .. } => {
|
||||
pat = subpattern;
|
||||
}
|
||||
_ => {
|
||||
break Err(ParseError {
|
||||
span: pat.span,
|
||||
item_description: format!("{:?}", pat.kind),
|
||||
expected: "local".to_string(),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_block_def(&self, expr_id: ExprId) -> PResult<BasicBlockData<'tcx>> {
|
||||
let block = parse_by_kind!(self, expr_id, "basic block",
|
||||
ExprKind::Block { block } => &self.thir[*block],
|
||||
);
|
||||
|
||||
let mut data = BasicBlockData::new(None);
|
||||
for stmt_id in &*block.stmts {
|
||||
let stmt = self.statement_as_expr(*stmt_id)?;
|
||||
let statement = self.parse_statement(stmt)?;
|
||||
data.statements.push(Statement { source_info: self.source_info, kind: statement });
|
||||
}
|
||||
|
||||
let Some(trailing) = block.expr else {
|
||||
return Err(self.expr_error(expr_id, "terminator"))
|
||||
};
|
||||
let terminator = self.parse_terminator(trailing)?;
|
||||
data.terminator = Some(Terminator { source_info: self.source_info, kind: terminator });
|
||||
|
||||
Ok(data)
|
||||
}
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
use rustc_middle::{mir::*, thir::*, ty};
|
||||
|
||||
use super::{parse_by_kind, PResult, ParseCtxt};
|
||||
|
||||
impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
|
||||
pub fn parse_statement(&self, expr_id: ExprId) -> PResult<StatementKind<'tcx>> {
|
||||
parse_by_kind!(self, expr_id, "statement",
|
||||
@call("mir_retag", args) => {
|
||||
Ok(StatementKind::Retag(RetagKind::Default, Box::new(self.parse_place(args[0])?)))
|
||||
},
|
||||
@call("mir_retag_raw", args) => {
|
||||
Ok(StatementKind::Retag(RetagKind::Raw, Box::new(self.parse_place(args[0])?)))
|
||||
},
|
||||
ExprKind::Assign { lhs, rhs } => {
|
||||
let lhs = self.parse_place(*lhs)?;
|
||||
let rhs = self.parse_rvalue(*rhs)?;
|
||||
Ok(StatementKind::Assign(Box::new((lhs, rhs))))
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
pub fn parse_terminator(&self, expr_id: ExprId) -> PResult<TerminatorKind<'tcx>> {
|
||||
parse_by_kind!(self, expr_id, "terminator",
|
||||
@call("mir_return", _args) => {
|
||||
Ok(TerminatorKind::Return)
|
||||
},
|
||||
@call("mir_goto", args) => {
|
||||
Ok(TerminatorKind::Goto { target: self.parse_block(args[0])? } )
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fn parse_rvalue(&self, expr_id: ExprId) -> PResult<Rvalue<'tcx>> {
|
||||
parse_by_kind!(self, expr_id, "rvalue",
|
||||
ExprKind::Borrow { borrow_kind, arg } => Ok(
|
||||
Rvalue::Ref(self.tcx.lifetimes.re_erased, *borrow_kind, self.parse_place(*arg)?)
|
||||
),
|
||||
ExprKind::AddressOf { mutability, arg } => Ok(
|
||||
Rvalue::AddressOf(*mutability, self.parse_place(*arg)?)
|
||||
),
|
||||
_ => self.parse_operand(expr_id).map(Rvalue::Use),
|
||||
)
|
||||
}
|
||||
|
||||
fn parse_operand(&self, expr_id: ExprId) -> PResult<Operand<'tcx>> {
|
||||
parse_by_kind!(self, expr_id, "operand",
|
||||
@call("mir_move", args) => self.parse_place(args[0]).map(Operand::Move),
|
||||
_ => self.parse_place(expr_id).map(Operand::Copy),
|
||||
)
|
||||
}
|
||||
|
||||
fn parse_place(&self, expr_id: ExprId) -> PResult<Place<'tcx>> {
|
||||
parse_by_kind!(self, expr_id, "place",
|
||||
ExprKind::Deref { arg } => Ok(
|
||||
self.parse_place(*arg)?.project_deeper(&[PlaceElem::Deref], self.tcx)
|
||||
),
|
||||
_ => self.parse_local(expr_id).map(Place::from),
|
||||
)
|
||||
}
|
||||
|
||||
fn parse_local(&self, expr_id: ExprId) -> PResult<Local> {
|
||||
parse_by_kind!(self, expr_id, "local",
|
||||
ExprKind::VarRef { id } => Ok(self.local_map[id]),
|
||||
)
|
||||
}
|
||||
|
||||
fn parse_block(&self, expr_id: ExprId) -> PResult<BasicBlock> {
|
||||
parse_by_kind!(self, expr_id, "basic block",
|
||||
ExprKind::VarRef { id } => Ok(self.block_map[id]),
|
||||
)
|
||||
}
|
||||
}
|
@ -481,6 +481,22 @@ fn construct_fn<'tcx>(
|
||||
(None, fn_sig.output())
|
||||
};
|
||||
|
||||
if let Some(custom_mir_attr) =
|
||||
tcx.hir().attrs(fn_id).iter().find(|attr| attr.name_or_empty() == sym::custom_mir)
|
||||
{
|
||||
return custom::build_custom_mir(
|
||||
tcx,
|
||||
fn_def.did.to_def_id(),
|
||||
thir,
|
||||
expr,
|
||||
arguments,
|
||||
return_ty,
|
||||
return_ty_span,
|
||||
span,
|
||||
custom_mir_attr,
|
||||
);
|
||||
}
|
||||
|
||||
let infcx = tcx.infer_ctxt().build();
|
||||
let mut builder = Builder::new(
|
||||
thir,
|
||||
@ -1033,6 +1049,7 @@ pub(crate) fn parse_float_into_scalar(
|
||||
|
||||
mod block;
|
||||
mod cfg;
|
||||
mod custom;
|
||||
mod expr;
|
||||
mod matches;
|
||||
mod misc;
|
||||
|
@ -51,11 +51,17 @@ impl<'tcx> Cx<'tcx> {
|
||||
trace!(?expr.ty);
|
||||
|
||||
// Now apply adjustments, if any.
|
||||
for adjustment in self.typeck_results.expr_adjustments(hir_expr) {
|
||||
trace!(?expr, ?adjustment);
|
||||
let span = expr.span;
|
||||
expr =
|
||||
self.apply_adjustment(hir_expr, expr, adjustment, adjustment_span.unwrap_or(span));
|
||||
if self.apply_adjustments {
|
||||
for adjustment in self.typeck_results.expr_adjustments(hir_expr) {
|
||||
trace!(?expr, ?adjustment);
|
||||
let span = expr.span;
|
||||
expr = self.apply_adjustment(
|
||||
hir_expr,
|
||||
expr,
|
||||
adjustment,
|
||||
adjustment_span.unwrap_or(span),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
trace!(?expr.ty, "after adjustments");
|
||||
|
@ -80,6 +80,9 @@ struct Cx<'tcx> {
|
||||
/// for the receiver.
|
||||
adjustment_span: Option<(HirId, Span)>,
|
||||
|
||||
/// False to indicate that adjustments should not be applied. Only used for `custom_mir`
|
||||
apply_adjustments: bool,
|
||||
|
||||
/// The `DefId` of the owner of this body.
|
||||
body_owner: DefId,
|
||||
}
|
||||
@ -87,6 +90,8 @@ struct Cx<'tcx> {
|
||||
impl<'tcx> Cx<'tcx> {
|
||||
fn new(tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam<LocalDefId>) -> Cx<'tcx> {
|
||||
let typeck_results = tcx.typeck_opt_const_arg(def);
|
||||
let did = def.did;
|
||||
let hir = tcx.hir();
|
||||
Cx {
|
||||
tcx,
|
||||
thir: Thir::new(),
|
||||
@ -94,8 +99,12 @@ impl<'tcx> Cx<'tcx> {
|
||||
region_scope_tree: tcx.region_scope_tree(def.did),
|
||||
typeck_results,
|
||||
rvalue_scopes: &typeck_results.rvalue_scopes,
|
||||
body_owner: def.did.to_def_id(),
|
||||
body_owner: did.to_def_id(),
|
||||
adjustment_span: None,
|
||||
apply_adjustments: hir
|
||||
.attrs(hir.local_def_id_to_hir_id(did))
|
||||
.iter()
|
||||
.all(|attr| attr.name_or_empty() != rustc_span::sym::custom_mir),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -471,6 +471,14 @@ fn unsafety_check_result<'tcx>(
|
||||
// `mir_built` force this.
|
||||
let body = &tcx.mir_built(def).borrow();
|
||||
|
||||
if body.should_skip() {
|
||||
return tcx.arena.alloc(UnsafetyCheckResult {
|
||||
violations: Vec::new(),
|
||||
used_unsafe_blocks: FxHashSet::default(),
|
||||
unused_unsafes: Some(Vec::new()),
|
||||
});
|
||||
}
|
||||
|
||||
let param_env = tcx.param_env(def.did);
|
||||
|
||||
let mut checker = UnsafetyChecker::new(body, def.did, tcx, param_env);
|
||||
|
@ -96,45 +96,48 @@ fn run_passes_inner<'tcx>(
|
||||
phase_change: Option<MirPhase>,
|
||||
validate_each: bool,
|
||||
) {
|
||||
let validate = validate_each & tcx.sess.opts.unstable_opts.validate_mir;
|
||||
let validate = validate_each & tcx.sess.opts.unstable_opts.validate_mir & !body.should_skip();
|
||||
let overridden_passes = &tcx.sess.opts.unstable_opts.mir_enable_passes;
|
||||
trace!(?overridden_passes);
|
||||
|
||||
for pass in passes {
|
||||
let name = pass.name();
|
||||
if !body.should_skip() {
|
||||
for pass in passes {
|
||||
let name = pass.name();
|
||||
|
||||
let overridden =
|
||||
overridden_passes.iter().rev().find(|(s, _)| s == &*name).map(|(_name, polarity)| {
|
||||
trace!(
|
||||
pass = %name,
|
||||
"{} as requested by flag",
|
||||
if *polarity { "Running" } else { "Not running" },
|
||||
);
|
||||
*polarity
|
||||
});
|
||||
if !overridden.unwrap_or_else(|| pass.is_enabled(&tcx.sess)) {
|
||||
continue;
|
||||
let overridden = overridden_passes.iter().rev().find(|(s, _)| s == &*name).map(
|
||||
|(_name, polarity)| {
|
||||
trace!(
|
||||
pass = %name,
|
||||
"{} as requested by flag",
|
||||
if *polarity { "Running" } else { "Not running" },
|
||||
);
|
||||
*polarity
|
||||
},
|
||||
);
|
||||
if !overridden.unwrap_or_else(|| pass.is_enabled(&tcx.sess)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let dump_enabled = pass.is_mir_dump_enabled();
|
||||
|
||||
if dump_enabled {
|
||||
dump_mir_for_pass(tcx, body, &name, false);
|
||||
}
|
||||
if validate {
|
||||
validate_body(tcx, body, format!("before pass {}", name));
|
||||
}
|
||||
|
||||
pass.run_pass(tcx, body);
|
||||
|
||||
if dump_enabled {
|
||||
dump_mir_for_pass(tcx, body, &name, true);
|
||||
}
|
||||
if validate {
|
||||
validate_body(tcx, body, format!("after pass {}", name));
|
||||
}
|
||||
|
||||
body.pass_count += 1;
|
||||
}
|
||||
|
||||
let dump_enabled = pass.is_mir_dump_enabled();
|
||||
|
||||
if dump_enabled {
|
||||
dump_mir_for_pass(tcx, body, &name, false);
|
||||
}
|
||||
if validate {
|
||||
validate_body(tcx, body, format!("before pass {}", name));
|
||||
}
|
||||
|
||||
pass.run_pass(tcx, body);
|
||||
|
||||
if dump_enabled {
|
||||
dump_mir_for_pass(tcx, body, &name, true);
|
||||
}
|
||||
if validate {
|
||||
validate_body(tcx, body, format!("after pass {}", name));
|
||||
}
|
||||
|
||||
body.pass_count += 1;
|
||||
}
|
||||
|
||||
if let Some(new_phase) = phase_change {
|
||||
|
@ -584,6 +584,7 @@ symbols! {
|
||||
custom_attribute,
|
||||
custom_derive,
|
||||
custom_inner_attributes,
|
||||
custom_mir,
|
||||
custom_test_frameworks,
|
||||
d,
|
||||
d32,
|
||||
|
@ -1,26 +1,25 @@
|
||||
use super::apple_base::{macos_link_env_remove, macos_llvm_target, opts, Arch};
|
||||
use crate::spec::{FramePointer, SanitizerSet, Target, TargetOptions};
|
||||
|
||||
pub fn target() -> Target {
|
||||
let arch = "arm64";
|
||||
let mut base = super::apple_base::opts("macos", arch, "");
|
||||
let arch = Arch::Arm64;
|
||||
let mut base = opts("macos", arch);
|
||||
base.cpu = "apple-a14".into();
|
||||
base.max_atomic_width = Some(128);
|
||||
|
||||
// FIXME: The leak sanitizer currently fails the tests, see #88132.
|
||||
base.supported_sanitizers = SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::THREAD;
|
||||
|
||||
base.link_env_remove.to_mut().extend(super::apple_base::macos_link_env_remove());
|
||||
|
||||
// Clang automatically chooses a more specific target based on
|
||||
// MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work
|
||||
// correctly, we do too.
|
||||
let llvm_target = super::apple_base::macos_llvm_target(arch);
|
||||
base.link_env_remove.to_mut().extend(macos_link_env_remove());
|
||||
|
||||
Target {
|
||||
llvm_target: llvm_target.into(),
|
||||
// Clang automatically chooses a more specific target based on
|
||||
// MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work
|
||||
// correctly, we do too.
|
||||
llvm_target: macos_llvm_target(arch).into(),
|
||||
pointer_width: 64,
|
||||
data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(),
|
||||
arch: "aarch64".into(),
|
||||
arch: arch.target_arch(),
|
||||
options: TargetOptions {
|
||||
mcount: "\u{1}mcount".into(),
|
||||
frame_pointer: FramePointer::NonLeaf,
|
||||
|
@ -1,19 +1,17 @@
|
||||
use super::apple_sdk_base::{opts, Arch};
|
||||
use super::apple_base::{ios_llvm_target, opts, Arch};
|
||||
use crate::spec::{FramePointer, Target, TargetOptions};
|
||||
|
||||
pub fn target() -> Target {
|
||||
// Clang automatically chooses a more specific target based on
|
||||
// IPHONEOS_DEPLOYMENT_TARGET.
|
||||
// This is required for the target to pick the right
|
||||
// MACH-O commands, so we do too.
|
||||
let arch = "arm64";
|
||||
let llvm_target = super::apple_base::ios_llvm_target(arch);
|
||||
|
||||
let arch = Arch::Arm64;
|
||||
Target {
|
||||
llvm_target: llvm_target.into(),
|
||||
// Clang automatically chooses a more specific target based on
|
||||
// IPHONEOS_DEPLOYMENT_TARGET.
|
||||
// This is required for the target to pick the right
|
||||
// MACH-O commands, so we do too.
|
||||
llvm_target: ios_llvm_target(arch).into(),
|
||||
pointer_width: 64,
|
||||
data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(),
|
||||
arch: "aarch64".into(),
|
||||
arch: arch.target_arch(),
|
||||
options: TargetOptions {
|
||||
features: "+neon,+fp-armv8,+apple-a7".into(),
|
||||
max_atomic_width: Some(128),
|
||||
@ -30,7 +28,7 @@ pub fn target() -> Target {
|
||||
darwinpcs\0\
|
||||
-Os\0"
|
||||
.into(),
|
||||
..opts("ios", Arch::Arm64)
|
||||
..opts("ios", arch)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -1,17 +1,18 @@
|
||||
use super::apple_sdk_base::{opts, Arch};
|
||||
use super::apple_base::{opts, Arch};
|
||||
use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, Target, TargetOptions};
|
||||
|
||||
pub fn target() -> Target {
|
||||
let llvm_target = "arm64-apple-ios14.0-macabi";
|
||||
|
||||
let mut base = opts("ios", Arch::Arm64_macabi);
|
||||
let arch = Arch::Arm64_macabi;
|
||||
let mut base = opts("ios", arch);
|
||||
base.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-target", llvm_target]);
|
||||
|
||||
Target {
|
||||
llvm_target: llvm_target.into(),
|
||||
pointer_width: 64,
|
||||
data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(),
|
||||
arch: "aarch64".into(),
|
||||
arch: arch.target_arch(),
|
||||
options: TargetOptions {
|
||||
features: "+neon,+fp-armv8,+apple-a12".into(),
|
||||
max_atomic_width: Some(128),
|
||||
|
@ -1,21 +1,17 @@
|
||||
use super::apple_sdk_base::{opts, Arch};
|
||||
use super::apple_base::{ios_sim_llvm_target, opts, Arch};
|
||||
use crate::spec::{FramePointer, Target, TargetOptions};
|
||||
|
||||
pub fn target() -> Target {
|
||||
let base = opts("ios", Arch::Arm64_sim);
|
||||
|
||||
// Clang automatically chooses a more specific target based on
|
||||
// IPHONEOS_DEPLOYMENT_TARGET.
|
||||
// This is required for the simulator target to pick the right
|
||||
// MACH-O commands, so we do too.
|
||||
let arch = "arm64";
|
||||
let llvm_target = super::apple_base::ios_sim_llvm_target(arch);
|
||||
|
||||
let arch = Arch::Arm64_sim;
|
||||
Target {
|
||||
llvm_target: llvm_target.into(),
|
||||
// Clang automatically chooses a more specific target based on
|
||||
// IPHONEOS_DEPLOYMENT_TARGET.
|
||||
// This is required for the simulator target to pick the right
|
||||
// MACH-O commands, so we do too.
|
||||
llvm_target: ios_sim_llvm_target(arch).into(),
|
||||
pointer_width: 64,
|
||||
data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(),
|
||||
arch: "aarch64".into(),
|
||||
arch: arch.target_arch(),
|
||||
options: TargetOptions {
|
||||
features: "+neon,+fp-armv8,+apple-a7".into(),
|
||||
max_atomic_width: Some(128),
|
||||
@ -32,7 +28,7 @@ pub fn target() -> Target {
|
||||
darwinpcs\0\
|
||||
-Os\0"
|
||||
.into(),
|
||||
..base
|
||||
..opts("ios", arch)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -1,18 +1,19 @@
|
||||
use super::apple_sdk_base::{opts, Arch};
|
||||
use super::apple_base::{opts, Arch};
|
||||
use crate::spec::{FramePointer, Target, TargetOptions};
|
||||
|
||||
pub fn target() -> Target {
|
||||
let arch = Arch::Arm64;
|
||||
Target {
|
||||
llvm_target: "arm64-apple-tvos".into(),
|
||||
pointer_width: 64,
|
||||
data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(),
|
||||
arch: "aarch64".into(),
|
||||
arch: arch.target_arch(),
|
||||
options: TargetOptions {
|
||||
features: "+neon,+fp-armv8,+apple-a7".into(),
|
||||
max_atomic_width: Some(128),
|
||||
forces_embed_bitcode: true,
|
||||
frame_pointer: FramePointer::NonLeaf,
|
||||
..opts("tvos", Arch::Arm64)
|
||||
..opts("tvos", arch)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -1,21 +1,17 @@
|
||||
use super::apple_sdk_base::{opts, Arch};
|
||||
use super::apple_base::{opts, watchos_sim_llvm_target, Arch};
|
||||
use crate::spec::{FramePointer, Target, TargetOptions};
|
||||
|
||||
pub fn target() -> Target {
|
||||
let base = opts("watchos", Arch::Arm64_sim);
|
||||
|
||||
// Clang automatically chooses a more specific target based on
|
||||
// WATCHOS_DEPLOYMENT_TARGET.
|
||||
// This is required for the simulator target to pick the right
|
||||
// MACH-O commands, so we do too.
|
||||
let arch = "arm64";
|
||||
let llvm_target = super::apple_base::watchos_sim_llvm_target(arch);
|
||||
|
||||
let arch = Arch::Arm64_sim;
|
||||
Target {
|
||||
llvm_target: llvm_target.into(),
|
||||
// Clang automatically chooses a more specific target based on
|
||||
// WATCHOS_DEPLOYMENT_TARGET.
|
||||
// This is required for the simulator target to pick the right
|
||||
// MACH-O commands, so we do too.
|
||||
llvm_target: watchos_sim_llvm_target(arch).into(),
|
||||
pointer_width: 64,
|
||||
data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(),
|
||||
arch: "aarch64".into(),
|
||||
arch: arch.target_arch(),
|
||||
options: TargetOptions {
|
||||
features: "+neon,+fp-armv8,+apple-a7".into(),
|
||||
max_atomic_width: Some(128),
|
||||
@ -32,7 +28,7 @@ pub fn target() -> Target {
|
||||
darwinpcs\0\
|
||||
-Os\0"
|
||||
.into(),
|
||||
..base
|
||||
..opts("watchos", arch)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,88 @@ use std::{borrow::Cow, env};
|
||||
use crate::spec::{cvs, Cc, DebuginfoKind, FramePointer, LinkArgs};
|
||||
use crate::spec::{LinkerFlavor, Lld, SplitDebuginfo, StaticCow, TargetOptions};
|
||||
|
||||
fn pre_link_args(os: &'static str, arch: &'static str, abi: &'static str) -> LinkArgs {
|
||||
#[cfg(test)]
|
||||
#[path = "apple/tests.rs"]
|
||||
mod tests;
|
||||
|
||||
use Arch::*;
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum Arch {
|
||||
Armv7,
|
||||
Armv7k,
|
||||
Armv7s,
|
||||
Arm64,
|
||||
Arm64_32,
|
||||
I386,
|
||||
I686,
|
||||
X86_64,
|
||||
X86_64_sim,
|
||||
X86_64_macabi,
|
||||
Arm64_macabi,
|
||||
Arm64_sim,
|
||||
}
|
||||
|
||||
impl Arch {
|
||||
pub fn target_name(self) -> &'static str {
|
||||
match self {
|
||||
Armv7 => "armv7",
|
||||
Armv7k => "armv7k",
|
||||
Armv7s => "armv7s",
|
||||
Arm64 | Arm64_macabi | Arm64_sim => "arm64",
|
||||
Arm64_32 => "arm64_32",
|
||||
I386 => "i386",
|
||||
I686 => "i686",
|
||||
X86_64 | X86_64_sim | X86_64_macabi => "x86_64",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn target_arch(self) -> Cow<'static, str> {
|
||||
Cow::Borrowed(match self {
|
||||
Armv7 | Armv7k | Armv7s => "arm",
|
||||
Arm64 | Arm64_32 | Arm64_macabi | Arm64_sim => "aarch64",
|
||||
I386 | I686 => "x86",
|
||||
X86_64 | X86_64_sim | X86_64_macabi => "x86_64",
|
||||
})
|
||||
}
|
||||
|
||||
fn target_abi(self) -> &'static str {
|
||||
match self {
|
||||
Armv7 | Armv7k | Armv7s | Arm64 | Arm64_32 | I386 | I686 | X86_64 => "",
|
||||
X86_64_macabi | Arm64_macabi => "macabi",
|
||||
// x86_64-apple-ios is a simulator target, even though it isn't
|
||||
// declared that way in the target like the other ones...
|
||||
Arm64_sim | X86_64_sim => "sim",
|
||||
}
|
||||
}
|
||||
|
||||
fn target_cpu(self) -> &'static str {
|
||||
match self {
|
||||
Armv7 => "cortex-a8", // iOS7 is supported on iPhone 4 and higher
|
||||
Armv7k => "cortex-a8",
|
||||
Armv7s => "cortex-a9",
|
||||
Arm64 => "apple-a7",
|
||||
Arm64_32 => "apple-s4",
|
||||
I386 | I686 => "yonah",
|
||||
X86_64 | X86_64_sim => "core2",
|
||||
X86_64_macabi => "core2",
|
||||
Arm64_macabi => "apple-a12",
|
||||
Arm64_sim => "apple-a12",
|
||||
}
|
||||
}
|
||||
|
||||
fn link_env_remove(self) -> StaticCow<[StaticCow<str>]> {
|
||||
match self {
|
||||
Armv7 | Armv7k | Armv7s | Arm64 | Arm64_32 | I386 | I686 | X86_64 | X86_64_sim
|
||||
| Arm64_sim => {
|
||||
cvs!["MACOSX_DEPLOYMENT_TARGET"]
|
||||
}
|
||||
X86_64_macabi | Arm64_macabi => cvs!["IPHONEOS_DEPLOYMENT_TARGET"],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn pre_link_args(os: &'static str, arch: Arch, abi: &'static str) -> LinkArgs {
|
||||
let platform_name: StaticCow<str> = match abi {
|
||||
"sim" => format!("{}-simulator", os).into(),
|
||||
"macabi" => "mac-catalyst".into(),
|
||||
@ -19,6 +100,8 @@ fn pre_link_args(os: &'static str, arch: &'static str, abi: &'static str) -> Lin
|
||||
}
|
||||
.into();
|
||||
|
||||
let arch = arch.target_name();
|
||||
|
||||
let mut args = TargetOptions::link_args(
|
||||
LinkerFlavor::Darwin(Cc::No, Lld::No),
|
||||
&["-arch", arch, "-platform_version"],
|
||||
@ -35,24 +118,29 @@ fn pre_link_args(os: &'static str, arch: &'static str, abi: &'static str) -> Lin
|
||||
args
|
||||
}
|
||||
|
||||
pub fn opts(os: &'static str, arch: &'static str, abi: &'static str) -> TargetOptions {
|
||||
// ELF TLS is only available in macOS 10.7+. If you try to compile for 10.6
|
||||
pub fn opts(os: &'static str, arch: Arch) -> TargetOptions {
|
||||
// Static TLS is only available in macOS 10.7+. If you try to compile for 10.6
|
||||
// either the linker will complain if it is used or the binary will end up
|
||||
// segfaulting at runtime when run on 10.6. Rust by default supports macOS
|
||||
// 10.7+, but there is a standard environment variable,
|
||||
// MACOSX_DEPLOYMENT_TARGET, which is used to signal targeting older
|
||||
// versions of macOS. For example compiling on 10.10 with
|
||||
// MACOSX_DEPLOYMENT_TARGET set to 10.6 will cause the linker to generate
|
||||
// warnings about the usage of ELF TLS.
|
||||
// warnings about the usage of static TLS.
|
||||
//
|
||||
// Here we detect what version is being requested, defaulting to 10.7. ELF
|
||||
// Here we detect what version is being requested, defaulting to 10.7. Static
|
||||
// TLS is flagged as enabled if it looks to be supported. The architecture
|
||||
// only matters for default deployment target which is 11.0 for ARM64 and
|
||||
// 10.7 for everything else.
|
||||
let has_thread_local = macos_deployment_target("x86_64") >= (10, 7);
|
||||
let has_thread_local = os == "macos" && macos_deployment_target(Arch::X86_64) >= (10, 7);
|
||||
|
||||
let abi = arch.target_abi();
|
||||
|
||||
TargetOptions {
|
||||
abi: abi.into(),
|
||||
os: os.into(),
|
||||
cpu: arch.target_cpu().into(),
|
||||
link_env_remove: arch.link_env_remove(),
|
||||
vendor: "apple".into(),
|
||||
linker_flavor: LinkerFlavor::Darwin(Cc::Yes, Lld::No),
|
||||
// macOS has -dead_strip, which doesn't rely on function_sections
|
||||
@ -103,23 +191,24 @@ fn deployment_target(var_name: &str) -> Option<(u32, u32)> {
|
||||
.and_then(|(a, b)| a.parse::<u32>().and_then(|a| b.parse::<u32>().map(|b| (a, b))).ok())
|
||||
}
|
||||
|
||||
fn macos_default_deployment_target(arch: &str) -> (u32, u32) {
|
||||
if arch == "arm64" { (11, 0) } else { (10, 7) }
|
||||
fn macos_default_deployment_target(arch: Arch) -> (u32, u32) {
|
||||
// Note: Arm64_sim is not included since macOS has no simulator.
|
||||
if matches!(arch, Arm64 | Arm64_macabi) { (11, 0) } else { (10, 7) }
|
||||
}
|
||||
|
||||
fn macos_deployment_target(arch: &str) -> (u32, u32) {
|
||||
fn macos_deployment_target(arch: Arch) -> (u32, u32) {
|
||||
deployment_target("MACOSX_DEPLOYMENT_TARGET")
|
||||
.unwrap_or_else(|| macos_default_deployment_target(arch))
|
||||
}
|
||||
|
||||
fn macos_lld_platform_version(arch: &str) -> String {
|
||||
fn macos_lld_platform_version(arch: Arch) -> String {
|
||||
let (major, minor) = macos_deployment_target(arch);
|
||||
format!("{}.{}", major, minor)
|
||||
}
|
||||
|
||||
pub fn macos_llvm_target(arch: &str) -> String {
|
||||
pub fn macos_llvm_target(arch: Arch) -> String {
|
||||
let (major, minor) = macos_deployment_target(arch);
|
||||
format!("{}-apple-macosx{}.{}.0", arch, major, minor)
|
||||
format!("{}-apple-macosx{}.{}.0", arch.target_name(), major, minor)
|
||||
}
|
||||
|
||||
pub fn macos_link_env_remove() -> Vec<StaticCow<str>> {
|
||||
@ -142,7 +231,7 @@ fn ios_deployment_target() -> (u32, u32) {
|
||||
deployment_target("IPHONEOS_DEPLOYMENT_TARGET").unwrap_or((7, 0))
|
||||
}
|
||||
|
||||
pub fn ios_llvm_target(arch: &str) -> String {
|
||||
pub fn ios_llvm_target(arch: Arch) -> String {
|
||||
// Modern iOS tooling extracts information about deployment target
|
||||
// from LC_BUILD_VERSION. This load command will only be emitted when
|
||||
// we build with a version specific `llvm_target`, with the version
|
||||
@ -150,7 +239,7 @@ pub fn ios_llvm_target(arch: &str) -> String {
|
||||
// to pick it up (since std and core are still built with the fallback
|
||||
// of version 7.0 and hence emit the old LC_IPHONE_MIN_VERSION).
|
||||
let (major, minor) = ios_deployment_target();
|
||||
format!("{}-apple-ios{}.{}.0", arch, major, minor)
|
||||
format!("{}-apple-ios{}.{}.0", arch.target_name(), major, minor)
|
||||
}
|
||||
|
||||
fn ios_lld_platform_version() -> String {
|
||||
@ -158,9 +247,9 @@ fn ios_lld_platform_version() -> String {
|
||||
format!("{}.{}", major, minor)
|
||||
}
|
||||
|
||||
pub fn ios_sim_llvm_target(arch: &str) -> String {
|
||||
pub fn ios_sim_llvm_target(arch: Arch) -> String {
|
||||
let (major, minor) = ios_deployment_target();
|
||||
format!("{}-apple-ios{}.{}.0-simulator", arch, major, minor)
|
||||
format!("{}-apple-ios{}.{}.0-simulator", arch.target_name(), major, minor)
|
||||
}
|
||||
|
||||
fn tvos_deployment_target() -> (u32, u32) {
|
||||
@ -181,7 +270,7 @@ fn watchos_lld_platform_version() -> String {
|
||||
format!("{}.{}", major, minor)
|
||||
}
|
||||
|
||||
pub fn watchos_sim_llvm_target(arch: &str) -> String {
|
||||
pub fn watchos_sim_llvm_target(arch: Arch) -> String {
|
||||
let (major, minor) = watchos_deployment_target();
|
||||
format!("{}-apple-watchos{}.{}.0-simulator", arch, major, minor)
|
||||
format!("{}-apple-watchos{}.{}.0-simulator", arch.target_name(), major, minor)
|
||||
}
|
||||
|
@ -1,81 +0,0 @@
|
||||
use crate::spec::{cvs, TargetOptions};
|
||||
use std::borrow::Cow;
|
||||
|
||||
#[cfg(test)]
|
||||
#[path = "apple/tests.rs"]
|
||||
mod tests;
|
||||
|
||||
use Arch::*;
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum Arch {
|
||||
Armv7,
|
||||
Armv7k,
|
||||
Armv7s,
|
||||
Arm64,
|
||||
Arm64_32,
|
||||
I386,
|
||||
#[allow(dead_code)] // Some targets don't use this enum...
|
||||
X86_64,
|
||||
X86_64_sim,
|
||||
X86_64_macabi,
|
||||
Arm64_macabi,
|
||||
Arm64_sim,
|
||||
}
|
||||
|
||||
fn target_arch_name(arch: Arch) -> &'static str {
|
||||
match arch {
|
||||
Armv7 => "armv7",
|
||||
Armv7k => "armv7k",
|
||||
Armv7s => "armv7s",
|
||||
Arm64 | Arm64_macabi | Arm64_sim => "arm64",
|
||||
Arm64_32 => "arm64_32",
|
||||
I386 => "i386",
|
||||
X86_64 | X86_64_sim | X86_64_macabi => "x86_64",
|
||||
}
|
||||
}
|
||||
|
||||
fn target_abi(arch: Arch) -> &'static str {
|
||||
match arch {
|
||||
Armv7 | Armv7k | Armv7s | Arm64 | Arm64_32 | I386 | X86_64 => "",
|
||||
X86_64_macabi | Arm64_macabi => "macabi",
|
||||
// x86_64-apple-ios is a simulator target, even though it isn't
|
||||
// declared that way in the target like the other ones...
|
||||
Arm64_sim | X86_64_sim => "sim",
|
||||
}
|
||||
}
|
||||
|
||||
fn target_cpu(arch: Arch) -> &'static str {
|
||||
match arch {
|
||||
Armv7 => "cortex-a8", // iOS7 is supported on iPhone 4 and higher
|
||||
Armv7k => "cortex-a8",
|
||||
Armv7s => "cortex-a9",
|
||||
Arm64 => "apple-a7",
|
||||
Arm64_32 => "apple-s4",
|
||||
I386 => "yonah",
|
||||
X86_64 | X86_64_sim => "core2",
|
||||
X86_64_macabi => "core2",
|
||||
Arm64_macabi => "apple-a12",
|
||||
Arm64_sim => "apple-a12",
|
||||
}
|
||||
}
|
||||
|
||||
fn link_env_remove(arch: Arch) -> Cow<'static, [Cow<'static, str>]> {
|
||||
match arch {
|
||||
Armv7 | Armv7k | Armv7s | Arm64 | Arm64_32 | I386 | X86_64 | X86_64_sim | Arm64_sim => {
|
||||
cvs!["MACOSX_DEPLOYMENT_TARGET"]
|
||||
}
|
||||
X86_64_macabi | Arm64_macabi => cvs!["IPHONEOS_DEPLOYMENT_TARGET"],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn opts(os: &'static str, arch: Arch) -> TargetOptions {
|
||||
let abi = target_abi(arch);
|
||||
TargetOptions {
|
||||
abi: abi.into(),
|
||||
cpu: target_cpu(arch).into(),
|
||||
link_env_remove: link_env_remove(arch),
|
||||
has_thread_local: false,
|
||||
..super::apple_base::opts(os, target_arch_name(arch), abi)
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
use super::apple_sdk_base::{opts, Arch};
|
||||
use super::apple_base::{opts, Arch};
|
||||
use crate::spec::{Target, TargetOptions};
|
||||
|
||||
pub fn target() -> Target {
|
||||
|
@ -1,18 +1,21 @@
|
||||
use super::apple_sdk_base::{opts, Arch};
|
||||
use super::apple_base::{ios_llvm_target, opts, Arch};
|
||||
use crate::spec::{Target, TargetOptions};
|
||||
|
||||
pub fn target() -> Target {
|
||||
let llvm_target = super::apple_base::ios_llvm_target("armv7");
|
||||
|
||||
let arch = Arch::Armv7;
|
||||
Target {
|
||||
llvm_target: llvm_target.into(),
|
||||
// Clang automatically chooses a more specific target based on
|
||||
// IPHONEOS_DEPLOYMENT_TARGET.
|
||||
// This is required for the target to pick the right
|
||||
// MACH-O commands, so we do too.
|
||||
llvm_target: ios_llvm_target(arch).into(),
|
||||
pointer_width: 32,
|
||||
data_layout: "e-m:o-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32".into(),
|
||||
arch: "arm".into(),
|
||||
arch: arch.target_arch(),
|
||||
options: TargetOptions {
|
||||
features: "+v7,+vfp3,+neon".into(),
|
||||
max_atomic_width: Some(64),
|
||||
..opts("ios", Arch::Armv7)
|
||||
..opts("ios", arch)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +1,13 @@
|
||||
use super::apple_sdk_base::{opts, Arch};
|
||||
use super::apple_base::{opts, Arch};
|
||||
use crate::spec::{Target, TargetOptions};
|
||||
|
||||
pub fn target() -> Target {
|
||||
let base = opts("watchos", Arch::Armv7k);
|
||||
let arch = Arch::Armv7k;
|
||||
Target {
|
||||
llvm_target: "armv7k-apple-watchos".into(),
|
||||
pointer_width: 32,
|
||||
data_layout: "e-m:o-p:32:32-Fi8-i64:64-a:0:32-n32-S128".into(),
|
||||
arch: "arm".into(),
|
||||
arch: arch.target_arch(),
|
||||
options: TargetOptions {
|
||||
features: "+v7,+vfp4,+neon".into(),
|
||||
max_atomic_width: Some(64),
|
||||
@ -22,7 +22,7 @@ pub fn target() -> Target {
|
||||
darwinpcs\0\
|
||||
-Os\0"
|
||||
.into(),
|
||||
..base
|
||||
..opts("watchos", arch)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +1,17 @@
|
||||
use super::apple_sdk_base::{opts, Arch};
|
||||
use super::apple_base::{opts, Arch};
|
||||
use crate::spec::{Target, TargetOptions};
|
||||
|
||||
pub fn target() -> Target {
|
||||
let arch = Arch::Armv7s;
|
||||
Target {
|
||||
llvm_target: "armv7s-apple-ios".into(),
|
||||
pointer_width: 32,
|
||||
data_layout: "e-m:o-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32".into(),
|
||||
arch: "arm".into(),
|
||||
arch: arch.target_arch(),
|
||||
options: TargetOptions {
|
||||
features: "+v7,+vfp4,+neon".into(),
|
||||
max_atomic_width: Some(64),
|
||||
..opts("ios", Arch::Armv7s)
|
||||
..opts("ios", arch)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -1,21 +1,23 @@
|
||||
use super::apple_sdk_base::{opts, Arch};
|
||||
use super::apple_base::{ios_sim_llvm_target, opts, Arch};
|
||||
use crate::spec::{StackProbeType, Target, TargetOptions};
|
||||
|
||||
pub fn target() -> Target {
|
||||
let base = opts("ios", Arch::I386);
|
||||
let llvm_target = super::apple_base::ios_sim_llvm_target("i386");
|
||||
|
||||
let arch = Arch::I386;
|
||||
Target {
|
||||
llvm_target: llvm_target.into(),
|
||||
// Clang automatically chooses a more specific target based on
|
||||
// IPHONEOS_DEPLOYMENT_TARGET.
|
||||
// This is required for the target to pick the right
|
||||
// MACH-O commands, so we do too.
|
||||
llvm_target: ios_sim_llvm_target(arch).into(),
|
||||
pointer_width: 32,
|
||||
data_layout: "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
|
||||
f64:32:64-f80:128-n8:16:32-S128"
|
||||
.into(),
|
||||
arch: "x86".into(),
|
||||
arch: arch.target_arch(),
|
||||
options: TargetOptions {
|
||||
max_atomic_width: Some(64),
|
||||
stack_probes: StackProbeType::X86,
|
||||
..base
|
||||
..opts("ios", arch)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -1,28 +1,28 @@
|
||||
use super::apple_base::{macos_link_env_remove, macos_llvm_target, opts, Arch};
|
||||
use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions};
|
||||
|
||||
pub fn target() -> Target {
|
||||
// ld64 only understand i386 and not i686
|
||||
let mut base = super::apple_base::opts("macos", "i386", "");
|
||||
base.cpu = "yonah".into();
|
||||
// ld64 only understands i386 and not i686
|
||||
let arch = Arch::I386;
|
||||
let mut base = opts("macos", arch);
|
||||
base.max_atomic_width = Some(64);
|
||||
base.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m32"]);
|
||||
base.link_env_remove.to_mut().extend(super::apple_base::macos_link_env_remove());
|
||||
base.link_env_remove.to_mut().extend(macos_link_env_remove());
|
||||
base.stack_probes = StackProbeType::X86;
|
||||
base.frame_pointer = FramePointer::Always;
|
||||
|
||||
// Clang automatically chooses a more specific target based on
|
||||
// MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work
|
||||
// correctly, we do too.
|
||||
let arch = "i686";
|
||||
let llvm_target = super::apple_base::macos_llvm_target(&arch);
|
||||
|
||||
Target {
|
||||
llvm_target: llvm_target.into(),
|
||||
// Clang automatically chooses a more specific target based on
|
||||
// MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work
|
||||
// correctly, we do too.
|
||||
//
|
||||
// While ld64 doesn't understand i686, LLVM does.
|
||||
llvm_target: macos_llvm_target(Arch::I686).into(),
|
||||
pointer_width: 32,
|
||||
data_layout: "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
|
||||
f64:32:64-f80:128-n8:16:32-S128"
|
||||
.into(),
|
||||
arch: "x86".into(),
|
||||
arch: arch.target_arch(),
|
||||
options: TargetOptions { mcount: "\u{1}mcount".into(), ..base },
|
||||
}
|
||||
}
|
||||
|
@ -1,18 +0,0 @@
|
||||
use crate::spec::TargetOptions;
|
||||
use crate::spec::{FramePointer, PanicStrategy, RelocModel, RelroLevel, StackProbeType};
|
||||
|
||||
pub fn opts() -> TargetOptions {
|
||||
TargetOptions {
|
||||
env: "gnu".into(),
|
||||
disable_redzone: true,
|
||||
panic_strategy: PanicStrategy::Abort,
|
||||
stack_probes: StackProbeType::X86,
|
||||
frame_pointer: FramePointer::Always,
|
||||
position_independent_executables: true,
|
||||
needs_plt: true,
|
||||
relro_level: RelroLevel::Full,
|
||||
relocation_model: RelocModel::Static,
|
||||
|
||||
..Default::default()
|
||||
}
|
||||
}
|
@ -59,7 +59,6 @@ pub mod crt_objects;
|
||||
|
||||
mod android_base;
|
||||
mod apple_base;
|
||||
mod apple_sdk_base;
|
||||
mod avr_gnu_base;
|
||||
mod bpf_base;
|
||||
mod dragonfly_base;
|
||||
@ -71,7 +70,6 @@ mod illumos_base;
|
||||
mod l4re_base;
|
||||
mod linux_base;
|
||||
mod linux_gnu_base;
|
||||
mod linux_kernel_base;
|
||||
mod linux_musl_base;
|
||||
mod linux_uclibc_base;
|
||||
mod msvc_base;
|
||||
@ -1003,7 +1001,7 @@ macro_rules! supported_targets {
|
||||
$(
|
||||
#[test] // `#[test]`
|
||||
fn $module() {
|
||||
tests_impl::test_target(super::$module::target(), $triple);
|
||||
tests_impl::test_target(super::$module::target());
|
||||
}
|
||||
)+
|
||||
}
|
||||
@ -1071,8 +1069,6 @@ supported_targets! {
|
||||
("thumbv7neon-linux-androideabi", thumbv7neon_linux_androideabi),
|
||||
("aarch64-linux-android", aarch64_linux_android),
|
||||
|
||||
("x86_64-unknown-none-linuxkernel", x86_64_unknown_none_linuxkernel),
|
||||
|
||||
("aarch64-unknown-freebsd", aarch64_unknown_freebsd),
|
||||
("armv6-unknown-freebsd", armv6_unknown_freebsd),
|
||||
("armv7-unknown-freebsd", armv7_unknown_freebsd),
|
||||
@ -1941,8 +1937,10 @@ impl Target {
|
||||
| PlatformIntrinsic
|
||||
| Unadjusted
|
||||
| Cdecl { .. }
|
||||
| EfiApi
|
||||
| RustCold => true,
|
||||
EfiApi => {
|
||||
["arm", "aarch64", "riscv32", "riscv64", "x86", "x86_64"].contains(&&self.arch[..])
|
||||
}
|
||||
X86Interrupt => ["x86", "x86_64"].contains(&&self.arch[..]),
|
||||
Aapcs { .. } => "arm" == self.arch,
|
||||
CCmseNonSecureCall => ["arm", "aarch64"].contains(&&self.arch[..]),
|
||||
|
@ -2,15 +2,15 @@ use super::super::*;
|
||||
use std::assert_matches::assert_matches;
|
||||
|
||||
// Test target self-consistency and JSON encoding/decoding roundtrip.
|
||||
pub(super) fn test_target(mut target: Target, triple: &str) {
|
||||
pub(super) fn test_target(mut target: Target) {
|
||||
let recycled_target = Target::from_json(target.to_json()).map(|(j, _)| j);
|
||||
target.update_to_cli();
|
||||
target.check_consistency(triple);
|
||||
target.check_consistency();
|
||||
assert_eq!(recycled_target, Ok(target));
|
||||
}
|
||||
|
||||
impl Target {
|
||||
fn check_consistency(&self, triple: &str) {
|
||||
fn check_consistency(&self) {
|
||||
assert_eq!(self.is_like_osx, self.vendor == "apple");
|
||||
assert_eq!(self.is_like_solaris, self.os == "solaris" || self.os == "illumos");
|
||||
assert_eq!(self.is_like_windows, self.os == "windows" || self.os == "uefi");
|
||||
@ -129,8 +129,7 @@ impl Target {
|
||||
if self.dynamic_linking && !(self.is_like_wasm && self.os != "emscripten") {
|
||||
assert_eq!(self.relocation_model, RelocModel::Pic);
|
||||
}
|
||||
// PIEs are supported but not enabled by default with linuxkernel target.
|
||||
if self.position_independent_executables && !triple.ends_with("-linuxkernel") {
|
||||
if self.position_independent_executables {
|
||||
assert_eq!(self.relocation_model, RelocModel::Pic);
|
||||
}
|
||||
// The UEFI targets do not support dynamic linking but still require PIC (#101377).
|
||||
|
@ -1,29 +1,27 @@
|
||||
use super::apple_base::{macos_link_env_remove, macos_llvm_target, opts, Arch};
|
||||
use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, SanitizerSet};
|
||||
use crate::spec::{StackProbeType, Target, TargetOptions};
|
||||
|
||||
pub fn target() -> Target {
|
||||
let arch = "x86_64";
|
||||
let mut base = super::apple_base::opts("macos", arch, "");
|
||||
base.cpu = "core2".into();
|
||||
base.max_atomic_width = Some(128); // core2 support cmpxchg16b
|
||||
let arch = Arch::X86_64;
|
||||
let mut base = opts("macos", arch);
|
||||
base.max_atomic_width = Some(128); // core2 supports cmpxchg16b
|
||||
base.frame_pointer = FramePointer::Always;
|
||||
base.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-m64"]);
|
||||
base.link_env_remove.to_mut().extend(super::apple_base::macos_link_env_remove());
|
||||
base.link_env_remove.to_mut().extend(macos_link_env_remove());
|
||||
base.stack_probes = StackProbeType::X86;
|
||||
base.supported_sanitizers =
|
||||
SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::LEAK | SanitizerSet::THREAD;
|
||||
|
||||
// Clang automatically chooses a more specific target based on
|
||||
// MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work
|
||||
// correctly, we do too.
|
||||
let llvm_target = super::apple_base::macos_llvm_target(&arch);
|
||||
|
||||
Target {
|
||||
llvm_target: llvm_target.into(),
|
||||
// Clang automatically chooses a more specific target based on
|
||||
// MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work
|
||||
// correctly, we do too.
|
||||
llvm_target: macos_llvm_target(arch).into(),
|
||||
pointer_width: 64,
|
||||
data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
|
||||
.into(),
|
||||
arch: arch.into(),
|
||||
arch: arch.target_arch(),
|
||||
options: TargetOptions { mcount: "\u{1}mcount".into(), ..base },
|
||||
}
|
||||
}
|
||||
|
@ -1,20 +1,18 @@
|
||||
use super::apple_sdk_base::{opts, Arch};
|
||||
use super::apple_base::{ios_sim_llvm_target, opts, Arch};
|
||||
use crate::spec::{StackProbeType, Target, TargetOptions};
|
||||
|
||||
pub fn target() -> Target {
|
||||
let base = opts("ios", Arch::X86_64_sim);
|
||||
let llvm_target = super::apple_base::ios_sim_llvm_target("x86_64");
|
||||
|
||||
let arch = Arch::X86_64_sim;
|
||||
Target {
|
||||
llvm_target: llvm_target.into(),
|
||||
llvm_target: ios_sim_llvm_target(arch).into(),
|
||||
pointer_width: 64,
|
||||
data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
|
||||
.into(),
|
||||
arch: "x86_64".into(),
|
||||
arch: arch.target_arch(),
|
||||
options: TargetOptions {
|
||||
max_atomic_width: Some(64),
|
||||
stack_probes: StackProbeType::X86,
|
||||
..base
|
||||
..opts("ios", arch)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,11 @@
|
||||
use super::apple_sdk_base::{opts, Arch};
|
||||
use super::apple_base::{opts, Arch};
|
||||
use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions};
|
||||
|
||||
pub fn target() -> Target {
|
||||
let llvm_target = "x86_64-apple-ios13.0-macabi";
|
||||
|
||||
let mut base = opts("ios", Arch::X86_64_macabi);
|
||||
let arch = Arch::X86_64_macabi;
|
||||
let mut base = opts("ios", arch);
|
||||
base.add_pre_link_args(LinkerFlavor::Darwin(Cc::Yes, Lld::No), &["-target", llvm_target]);
|
||||
|
||||
Target {
|
||||
@ -12,7 +13,7 @@ pub fn target() -> Target {
|
||||
pointer_width: 64,
|
||||
data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
|
||||
.into(),
|
||||
arch: "x86_64".into(),
|
||||
arch: arch.target_arch(),
|
||||
options: TargetOptions {
|
||||
max_atomic_width: Some(64),
|
||||
stack_probes: StackProbeType::X86,
|
||||
|
@ -1,17 +1,17 @@
|
||||
use super::apple_sdk_base::{opts, Arch};
|
||||
use super::apple_base::{opts, Arch};
|
||||
use crate::spec::{StackProbeType, Target, TargetOptions};
|
||||
|
||||
pub fn target() -> Target {
|
||||
let base = opts("tvos", Arch::X86_64_sim);
|
||||
let arch = Arch::X86_64_sim;
|
||||
Target {
|
||||
llvm_target: "x86_64-apple-tvos".into(),
|
||||
pointer_width: 64,
|
||||
data_layout: "e-m:o-i64:64-f80:128-n8:16:32:64-S128".into(),
|
||||
arch: "x86_64".into(),
|
||||
arch: arch.target_arch(),
|
||||
options: TargetOptions {
|
||||
max_atomic_width: Some(64),
|
||||
stack_probes: StackProbeType::X86,
|
||||
..base
|
||||
..opts("tvos", arch)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -1,18 +1,14 @@
|
||||
use super::apple_sdk_base::{opts, Arch};
|
||||
use super::apple_base::{opts, watchos_sim_llvm_target, Arch};
|
||||
use crate::spec::{StackProbeType, Target, TargetOptions};
|
||||
|
||||
pub fn target() -> Target {
|
||||
let base = opts("watchos", Arch::X86_64_sim);
|
||||
|
||||
let arch = "x86_64";
|
||||
let llvm_target = super::apple_base::watchos_sim_llvm_target(arch);
|
||||
|
||||
let arch = Arch::X86_64_sim;
|
||||
Target {
|
||||
llvm_target: llvm_target.into(),
|
||||
llvm_target: watchos_sim_llvm_target(arch).into(),
|
||||
pointer_width: 64,
|
||||
data_layout: "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
|
||||
.into(),
|
||||
arch: "x86_64".into(),
|
||||
arch: arch.target_arch(),
|
||||
options: TargetOptions {
|
||||
max_atomic_width: Some(64),
|
||||
stack_probes: StackProbeType::X86,
|
||||
@ -28,7 +24,7 @@ pub fn target() -> Target {
|
||||
darwinpcs\0\
|
||||
-Os\0"
|
||||
.into(),
|
||||
..base
|
||||
..opts("watchos", arch)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -1,28 +0,0 @@
|
||||
// This defines the amd64 target for the Linux Kernel. See the linux-kernel-base module for
|
||||
// generic Linux kernel options.
|
||||
|
||||
use crate::spec::{Cc, CodeModel, LinkerFlavor, Lld, Target};
|
||||
|
||||
pub fn target() -> Target {
|
||||
let mut base = super::linux_kernel_base::opts();
|
||||
base.cpu = "x86-64".into();
|
||||
base.max_atomic_width = Some(64);
|
||||
base.features =
|
||||
"-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2,+soft-float".into();
|
||||
base.code_model = Some(CodeModel::Kernel);
|
||||
base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
|
||||
|
||||
Target {
|
||||
// FIXME: Some dispute, the linux-on-clang folks think this should use
|
||||
// "Linux". We disagree because running *on* Linux is nothing like
|
||||
// running *as" linux, and historically the "os" component as has always
|
||||
// been used to mean the "on" part.
|
||||
llvm_target: "x86_64-unknown-none-elf".into(),
|
||||
pointer_width: 64,
|
||||
data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
|
||||
.into(),
|
||||
arch: "x86_64".into(),
|
||||
|
||||
options: base,
|
||||
}
|
||||
}
|
@ -27,7 +27,6 @@ pub struct Autoderef<'a, 'tcx> {
|
||||
// Meta infos:
|
||||
infcx: &'a InferCtxt<'tcx>,
|
||||
span: Span,
|
||||
overloaded_span: Span,
|
||||
body_id: hir::HirId,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
|
||||
@ -99,12 +98,10 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
|
||||
body_id: hir::HirId,
|
||||
span: Span,
|
||||
base_ty: Ty<'tcx>,
|
||||
overloaded_span: Span,
|
||||
) -> Autoderef<'a, 'tcx> {
|
||||
Autoderef {
|
||||
infcx,
|
||||
span,
|
||||
overloaded_span,
|
||||
body_id,
|
||||
param_env,
|
||||
state: AutoderefSnapshot {
|
||||
@ -193,10 +190,6 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
|
||||
self.span
|
||||
}
|
||||
|
||||
pub fn overloaded_span(&self) -> Span {
|
||||
self.overloaded_span
|
||||
}
|
||||
|
||||
pub fn reached_recursion_limit(&self) -> bool {
|
||||
self.state.reached_recursion_limit
|
||||
}
|
||||
|
@ -714,7 +714,6 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
|
||||
obligation.cause.body_id,
|
||||
span,
|
||||
base_ty,
|
||||
span,
|
||||
);
|
||||
if let Some(steps) = autoderef.find_map(|(ty, steps)| {
|
||||
// Re-add the `&`
|
||||
|
@ -59,6 +59,9 @@ use crate::marker::DiscriminantKind;
|
||||
use crate::marker::Tuple;
|
||||
use crate::mem;
|
||||
|
||||
#[cfg(not(bootstrap))]
|
||||
pub mod mir;
|
||||
|
||||
// These imports are used for simplifying intra-doc links
|
||||
#[allow(unused_imports)]
|
||||
#[cfg(all(target_has_atomic = "8", target_has_atomic = "32", target_has_atomic = "ptr"))]
|
||||
|
123
library/core/src/intrinsics/mir.rs
Normal file
123
library/core/src/intrinsics/mir.rs
Normal file
@ -0,0 +1,123 @@
|
||||
//! Rustc internal tooling for hand-writing MIR.
|
||||
//!
|
||||
//! If for some reasons you are not writing rustc tests and have found yourself considering using
|
||||
//! this feature, turn back. This is *exceptionally* unstable. There is no attempt at all to make
|
||||
//! anything work besides those things which the rustc test suite happened to need. If you make a
|
||||
//! typo you'll probably ICE. Really, this is not the solution to your problems. Consider instead
|
||||
//! supporting the [stable MIR project group](https://github.com/rust-lang/project-stable-mir).
|
||||
//!
|
||||
//! The documentation for this module describes how to use this feature. If you are interested in
|
||||
//! hacking on the implementation, most of that documentation lives at
|
||||
//! `rustc_mir_building/src/build/custom/mod.rs`.
|
||||
//!
|
||||
//! Typical usage will look like this:
|
||||
//!
|
||||
//! ```rust
|
||||
//! #![feature(core_intrinsics, custom_mir)]
|
||||
//!
|
||||
//! extern crate core;
|
||||
//! use core::intrinsics::mir::*;
|
||||
//!
|
||||
//! #[custom_mir(dialect = "built")]
|
||||
//! pub fn simple(x: i32) -> i32 {
|
||||
//! mir!(
|
||||
//! let temp1: i32;
|
||||
//! let temp2: _;
|
||||
//!
|
||||
//! {
|
||||
//! temp1 = x;
|
||||
//! Goto(exit)
|
||||
//! }
|
||||
//!
|
||||
//! exit = {
|
||||
//! temp2 = Move(temp1);
|
||||
//! RET = temp2;
|
||||
//! Return()
|
||||
//! }
|
||||
//! )
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! Hopefully most of this is fairly self-explanatory. Expanding on some notable details:
|
||||
//!
|
||||
//! - The `custom_mir` attribute tells the compiler to treat the function as being custom MIR. This
|
||||
//! attribute only works on functions - there is no way to insert custom MIR into the middle of
|
||||
//! another function.
|
||||
//! - The `dialect` and `phase` parameters indicate which version of MIR you are inserting here.
|
||||
//! This will normally be the phase that corresponds to the thing you are trying to test. The
|
||||
//! phase can be omitted for dialects that have just one.
|
||||
//! - You should define your function signature like you normally would. Externally, this function
|
||||
//! can be called like any other function.
|
||||
//! - Type inference works - you don't have to spell out the type of all of your locals.
|
||||
//!
|
||||
//! For now, all statements and terminators are parsed from nested invocations of the special
|
||||
//! functions provided in this module. We additionally want to (but do not yet) support more
|
||||
//! "normal" Rust syntax in places where it makes sense. Also, most kinds of instructions are not
|
||||
//! supported yet.
|
||||
//!
|
||||
|
||||
#![unstable(
|
||||
feature = "custom_mir",
|
||||
reason = "MIR is an implementation detail and extremely unstable",
|
||||
issue = "none"
|
||||
)]
|
||||
#![allow(unused_variables, non_snake_case, missing_debug_implementations)]
|
||||
|
||||
/// Type representing basic blocks.
|
||||
///
|
||||
/// All terminators will have this type as a return type. It helps achieve some type safety.
|
||||
pub struct BasicBlock;
|
||||
|
||||
macro_rules! define {
|
||||
($name:literal, $($sig:tt)*) => {
|
||||
#[rustc_diagnostic_item = $name]
|
||||
pub $($sig)* { panic!() }
|
||||
}
|
||||
}
|
||||
|
||||
define!("mir_return", fn Return() -> BasicBlock);
|
||||
define!("mir_goto", fn Goto(destination: BasicBlock) -> BasicBlock);
|
||||
define!("mir_retag", fn Retag<T>(place: T));
|
||||
define!("mir_retag_raw", fn RetagRaw<T>(place: T));
|
||||
define!("mir_move", fn Move<T>(place: T) -> T);
|
||||
|
||||
/// Convenience macro for generating custom MIR.
|
||||
///
|
||||
/// See the module documentation for syntax details. This macro is not magic - it only transforms
|
||||
/// your MIR into something that is easier to parse in the compiler.
|
||||
#[rustc_macro_transparency = "transparent"]
|
||||
pub macro mir {
|
||||
(
|
||||
$(let $local_decl:ident $(: $local_decl_ty:ty)? ;)*
|
||||
|
||||
$entry_block:block
|
||||
|
||||
$(
|
||||
$block_name:ident = $block:block
|
||||
)*
|
||||
) => {{
|
||||
// First, we declare all basic blocks.
|
||||
$(
|
||||
let $block_name: ::core::intrinsics::mir::BasicBlock;
|
||||
)*
|
||||
|
||||
{
|
||||
// Now all locals
|
||||
#[allow(non_snake_case)]
|
||||
let RET;
|
||||
$(
|
||||
let $local_decl $(: $local_decl_ty)? ;
|
||||
)*
|
||||
|
||||
{
|
||||
// Finally, the contents of the basic blocks
|
||||
$entry_block;
|
||||
$(
|
||||
$block;
|
||||
)*
|
||||
|
||||
RET
|
||||
}
|
||||
}
|
||||
}}
|
||||
}
|
@ -1059,7 +1059,7 @@ impl<P, U> DispatchFromDyn<Pin<U>> for Pin<P> where P: DispatchFromDyn<U> {}
|
||||
/// 8 | let x: Pin<&mut Foo> = {
|
||||
/// | - borrow later stored here
|
||||
/// 9 | let x: Pin<&mut Foo> = pin!(Foo { /* … */ });
|
||||
/// | ^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
|
||||
/// | ^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
|
||||
/// 10 | x
|
||||
/// 11 | }; // <- Foo is dropped
|
||||
/// | - temporary value is freed at the end of this statement
|
||||
|
@ -15,7 +15,6 @@ cfg_if::cfg_if! {
|
||||
target_os = "espidf",
|
||||
))] {
|
||||
// These "unix" family members do not have unwinder.
|
||||
// Note this also matches x86_64-unknown-none-linuxkernel.
|
||||
} else if #[cfg(any(
|
||||
unix,
|
||||
windows,
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit aa5ee485bd6bd80d205da7c82fcdd776f92fdd51
|
||||
Subproject commit 3f64052c048c6def93b94a2b514ee88bba918744
|
@ -1 +1 @@
|
||||
Subproject commit 9c73283775466d22208a0b28afcab44db4c0cc10
|
||||
Subproject commit 05532356e7a4dbea2330aabb77611f5179493bb8
|
@ -1 +1 @@
|
||||
Subproject commit 4ea7c5def38ac81df33a9e48e5637a82a5ac404d
|
||||
Subproject commit 9f0cc13ffcd27c1fbe1ab766a9491e15ddcf4d19
|
@ -1 +1 @@
|
||||
Subproject commit 03491f33375c5a2a1661c7fa4be671fe95ce1249
|
||||
Subproject commit 2b15c0abf2bada6e00553814336bc3e2d8399097
|
@ -1 +1 @@
|
||||
Subproject commit 51a37ad19a15709d0601afbac6581f5aea6a45da
|
||||
Subproject commit d0dc6c97a6486f68bac782fff135086eae6d77ec
|
@ -310,7 +310,6 @@ target | std | host | notes
|
||||
`x86_64-unknown-haiku` | ✓ | ✓ | 64-bit Haiku
|
||||
`x86_64-unknown-hermit` | ✓ | | HermitCore
|
||||
`x86_64-unknown-l4re-uclibc` | ? | |
|
||||
`x86_64-unknown-none-linuxkernel` | * | | Linux kernel modules
|
||||
[`x86_64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | 64-bit OpenBSD
|
||||
`x86_64-uwp-windows-gnu` | ✓ | |
|
||||
`x86_64-uwp-windows-msvc` | ✓ | |
|
||||
|
@ -326,7 +326,7 @@ impl Options {
|
||||
crate::usage("rustdoc");
|
||||
return Err(0);
|
||||
} else if matches.opt_present("version") {
|
||||
rustc_driver::version("rustdoc", matches);
|
||||
rustc_driver::version!("rustdoc", matches);
|
||||
return Err(0);
|
||||
}
|
||||
|
||||
|
@ -71,7 +71,7 @@ pub(crate) fn render<T: Print, S: Print>(
|
||||
let mut themes: Vec<String> = style_files.iter().map(|s| s.basename().unwrap()).collect();
|
||||
themes.sort();
|
||||
|
||||
let rustdoc_version = rustc_interface::util::version_str().unwrap_or("unknown version");
|
||||
let rustdoc_version = rustc_interface::util::version_str!().unwrap_or("unknown version");
|
||||
let content = Buffer::html().to_display(t); // Note: This must happen before making the sidebar.
|
||||
let sidebar = Buffer::html().to_display(sidebar);
|
||||
PageLayout {
|
||||
|
@ -0,0 +1,14 @@
|
||||
// MIR for `immut_ref` after built
|
||||
|
||||
fn immut_ref(_1: &i32) -> &i32 {
|
||||
let mut _0: &i32; // return place in scope 0 at $DIR/references.rs:+0:30: +0:34
|
||||
let mut _2: *const i32; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
|
||||
|
||||
bb0: {
|
||||
_2 = &raw const (*_1); // scope 0 at $DIR/references.rs:+0:1: +0:34
|
||||
Retag([raw] _2); // scope 0 at $DIR/references.rs:+0:1: +0:34
|
||||
_0 = &(*_2); // scope 0 at $DIR/references.rs:+0:1: +0:34
|
||||
Retag(_0); // scope 0 at $DIR/references.rs:+0:1: +0:34
|
||||
return; // scope 0 at $DIR/references.rs:+0:1: +0:34
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
// MIR for `mut_ref` after built
|
||||
|
||||
fn mut_ref(_1: &mut i32) -> &mut i32 {
|
||||
let mut _0: &mut i32; // return place in scope 0 at $DIR/references.rs:+0:32: +0:40
|
||||
let mut _2: *mut i32; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
|
||||
|
||||
bb0: {
|
||||
_2 = &raw mut (*_1); // scope 0 at $DIR/references.rs:+0:1: +0:40
|
||||
Retag([raw] _2); // scope 0 at $DIR/references.rs:+0:1: +0:40
|
||||
_0 = &mut (*_2); // scope 0 at $DIR/references.rs:+0:1: +0:40
|
||||
Retag(_0); // scope 0 at $DIR/references.rs:+0:1: +0:40
|
||||
return; // scope 0 at $DIR/references.rs:+0:1: +0:40
|
||||
}
|
||||
}
|
43
src/test/mir-opt/building/custom/references.rs
Normal file
43
src/test/mir-opt/building/custom/references.rs
Normal file
@ -0,0 +1,43 @@
|
||||
#![feature(custom_mir, core_intrinsics)]
|
||||
|
||||
extern crate core;
|
||||
use core::intrinsics::mir::*;
|
||||
use core::ptr::{addr_of, addr_of_mut};
|
||||
|
||||
// EMIT_MIR references.mut_ref.built.after.mir
|
||||
#[custom_mir(dialect = "runtime", phase = "optimized")]
|
||||
pub fn mut_ref(x: &mut i32) -> &mut i32 {
|
||||
mir!(
|
||||
let t: *mut i32;
|
||||
|
||||
{
|
||||
t = addr_of_mut!(*x);
|
||||
RetagRaw(t);
|
||||
RET = &mut *t;
|
||||
Retag(RET);
|
||||
Return()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
// EMIT_MIR references.immut_ref.built.after.mir
|
||||
#[custom_mir(dialect = "runtime", phase = "optimized")]
|
||||
pub fn immut_ref(x: &i32) -> &i32 {
|
||||
mir!(
|
||||
let t: *const i32;
|
||||
|
||||
{
|
||||
t = addr_of!(*x);
|
||||
RetagRaw(t);
|
||||
RET = & *t;
|
||||
Retag(RET);
|
||||
Return()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut x = 5;
|
||||
assert_eq!(*mut_ref(&mut x), 5);
|
||||
assert_eq!(*immut_ref(&x), 5);
|
||||
}
|
37
src/test/mir-opt/building/custom/simple_assign.rs
Normal file
37
src/test/mir-opt/building/custom/simple_assign.rs
Normal file
@ -0,0 +1,37 @@
|
||||
#![feature(custom_mir, core_intrinsics)]
|
||||
|
||||
extern crate core;
|
||||
use core::intrinsics::mir::*;
|
||||
|
||||
// EMIT_MIR simple_assign.simple.built.after.mir
|
||||
#[custom_mir(dialect = "built")]
|
||||
pub fn simple(x: i32) -> i32 {
|
||||
mir!(
|
||||
let temp1: i32;
|
||||
let temp2: _;
|
||||
|
||||
{
|
||||
temp1 = x;
|
||||
Goto(exit)
|
||||
}
|
||||
|
||||
exit = {
|
||||
temp2 = Move(temp1);
|
||||
RET = temp2;
|
||||
Return()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
// EMIT_MIR simple_assign.simple_ref.built.after.mir
|
||||
#[custom_mir(dialect = "built")]
|
||||
pub fn simple_ref(x: &mut i32) -> &mut i32 {
|
||||
mir!({
|
||||
RET = Move(x);
|
||||
Return()
|
||||
})
|
||||
}
|
||||
|
||||
fn main() {
|
||||
assert_eq!(5, simple(5));
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
// MIR for `simple` after built
|
||||
|
||||
fn simple(_1: i32) -> i32 {
|
||||
let mut _0: i32; // return place in scope 0 at $DIR/simple_assign.rs:+0:26: +0:29
|
||||
let mut _2: i32; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
|
||||
let mut _3: i32; // in scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
|
||||
|
||||
bb0: {
|
||||
_2 = _1; // scope 0 at $DIR/simple_assign.rs:+0:1: +0:29
|
||||
goto -> bb1; // scope 0 at $DIR/simple_assign.rs:+0:1: +0:29
|
||||
}
|
||||
|
||||
bb1: {
|
||||
_3 = move _2; // scope 0 at $DIR/simple_assign.rs:+0:1: +0:29
|
||||
_0 = _3; // scope 0 at $DIR/simple_assign.rs:+0:1: +0:29
|
||||
return; // scope 0 at $DIR/simple_assign.rs:+0:1: +0:29
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
// MIR for `simple_ref` after built
|
||||
|
||||
fn simple_ref(_1: &mut i32) -> &mut i32 {
|
||||
let mut _0: &mut i32; // return place in scope 0 at $DIR/simple_assign.rs:+0:35: +0:43
|
||||
|
||||
bb0: {
|
||||
_0 = move _1; // scope 0 at $DIR/simple_assign.rs:+0:1: +0:43
|
||||
return; // scope 0 at $DIR/simple_assign.rs:+0:1: +0:43
|
||||
}
|
||||
}
|
@ -4,7 +4,7 @@ error[E0716]: temporary value dropped while borrowed
|
||||
LL | let x = defer(&vec!["Goodbye", "world!"]);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ - temporary value is freed at the end of this statement
|
||||
| |
|
||||
| creates a temporary which is freed while still in use
|
||||
| creates a temporary value which is freed while still in use
|
||||
LL | x.x[0];
|
||||
| ------ borrow later used here
|
||||
|
|
||||
|
@ -4,7 +4,7 @@ error[E0716]: temporary value dropped while borrowed
|
||||
LL | buggy_map.insert(42, &*Box::new(1));
|
||||
| ^^^^^^^^^^^ - temporary value is freed at the end of this statement
|
||||
| |
|
||||
| creates a temporary which is freed while still in use
|
||||
| creates a temporary value which is freed while still in use
|
||||
...
|
||||
LL | buggy_map.insert(43, &*tmp);
|
||||
| --------------------------- borrow later used here
|
||||
|
@ -4,7 +4,7 @@ error[E0716]: temporary value dropped while borrowed
|
||||
LL | let y = x.as_ref().unwrap_or(&id(5));
|
||||
| ^^^^^ - temporary value is freed at the end of this statement
|
||||
| |
|
||||
| creates a temporary which is freed while still in use
|
||||
| creates a temporary value which is freed while still in use
|
||||
LL | let _ = &y;
|
||||
| -- borrow later used here
|
||||
|
|
||||
|
@ -5,7 +5,7 @@ LL | pub fn foo<'a, F: Fn(&'a ())>(bar: F) {
|
||||
| -- lifetime `'a` defined here
|
||||
LL | / bar.call((
|
||||
LL | | &id(()),
|
||||
| | ^^^^^^ creates a temporary which is freed while still in use
|
||||
| | ^^^^^^ creates a temporary value which is freed while still in use
|
||||
LL | | ));
|
||||
| | -- temporary value is freed at the end of this statement
|
||||
| |______|
|
||||
|
@ -10,7 +10,7 @@ fn main() {
|
||||
let val: &_ = binding.0;
|
||||
//~^ ERROR temporary value dropped while borrowed [E0716]
|
||||
//~| NOTE temporary value is freed at the end of this statement
|
||||
//~| NOTE creates a temporary which is freed while still in use
|
||||
//~| NOTE creates a temporary value which is freed while still in use
|
||||
//~| HELP consider using a `let` binding to create a longer lived value
|
||||
println!("{}", val);
|
||||
//~^ borrow later used here
|
||||
|
@ -9,7 +9,7 @@ fn main() {
|
||||
let val: &_ = x.borrow().0;
|
||||
//~^ ERROR temporary value dropped while borrowed [E0716]
|
||||
//~| NOTE temporary value is freed at the end of this statement
|
||||
//~| NOTE creates a temporary which is freed while still in use
|
||||
//~| NOTE creates a temporary value which is freed while still in use
|
||||
//~| HELP consider using a `let` binding to create a longer lived value
|
||||
println!("{}", val);
|
||||
//~^ borrow later used here
|
||||
|
@ -4,7 +4,7 @@ error[E0716]: temporary value dropped while borrowed
|
||||
LL | let val: &_ = x.borrow().0;
|
||||
| ^^^^^^^^^^ - temporary value is freed at the end of this statement
|
||||
| |
|
||||
| creates a temporary which is freed while still in use
|
||||
| creates a temporary value which is freed while still in use
|
||||
...
|
||||
LL | println!("{}", val);
|
||||
| --- borrow later used here
|
||||
|
@ -4,7 +4,7 @@ error[E0716]: temporary value dropped while borrowed
|
||||
LL | let x1 = arg(&AddFlags(1));
|
||||
| ^^^^^^^^^^^ - temporary value is freed at the end of this statement
|
||||
| |
|
||||
| creates a temporary which is freed while still in use
|
||||
| creates a temporary value which is freed while still in use
|
||||
...
|
||||
LL | (x1, x2, x3, x4, x5, x6, x7);
|
||||
| -- borrow later used here
|
||||
@ -21,7 +21,7 @@ error[E0716]: temporary value dropped while borrowed
|
||||
LL | let x2 = AddFlags(1).get();
|
||||
| ^^^^^^^^^^^ - temporary value is freed at the end of this statement
|
||||
| |
|
||||
| creates a temporary which is freed while still in use
|
||||
| creates a temporary value which is freed while still in use
|
||||
...
|
||||
LL | (x1, x2, x3, x4, x5, x6, x7);
|
||||
| -- borrow later used here
|
||||
@ -38,7 +38,7 @@ error[E0716]: temporary value dropped while borrowed
|
||||
LL | let x3 = &*arg(&AddFlags(1));
|
||||
| ^^^^^^^^^^^ - temporary value is freed at the end of this statement
|
||||
| |
|
||||
| creates a temporary which is freed while still in use
|
||||
| creates a temporary value which is freed while still in use
|
||||
...
|
||||
LL | (x1, x2, x3, x4, x5, x6, x7);
|
||||
| -- borrow later used here
|
||||
@ -55,7 +55,7 @@ error[E0716]: temporary value dropped while borrowed
|
||||
LL | let ref x4 = *arg(&AddFlags(1));
|
||||
| ^^^^^^^^^^^ - temporary value is freed at the end of this statement
|
||||
| |
|
||||
| creates a temporary which is freed while still in use
|
||||
| creates a temporary value which is freed while still in use
|
||||
...
|
||||
LL | (x1, x2, x3, x4, x5, x6, x7);
|
||||
| -- borrow later used here
|
||||
@ -72,7 +72,7 @@ error[E0716]: temporary value dropped while borrowed
|
||||
LL | let &ref x5 = arg(&AddFlags(1));
|
||||
| ^^^^^^^^^^^ - temporary value is freed at the end of this statement
|
||||
| |
|
||||
| creates a temporary which is freed while still in use
|
||||
| creates a temporary value which is freed while still in use
|
||||
...
|
||||
LL | (x1, x2, x3, x4, x5, x6, x7);
|
||||
| -- borrow later used here
|
||||
@ -89,7 +89,7 @@ error[E0716]: temporary value dropped while borrowed
|
||||
LL | let x6 = AddFlags(1).get();
|
||||
| ^^^^^^^^^^^ - temporary value is freed at the end of this statement
|
||||
| |
|
||||
| creates a temporary which is freed while still in use
|
||||
| creates a temporary value which is freed while still in use
|
||||
...
|
||||
LL | (x1, x2, x3, x4, x5, x6, x7);
|
||||
| -- borrow later used here
|
||||
@ -106,7 +106,7 @@ error[E0716]: temporary value dropped while borrowed
|
||||
LL | let StackBox { f: x7 } = StackBox { f: AddFlags(1).get() };
|
||||
| ^^^^^^^^^^^ - temporary value is freed at the end of this statement
|
||||
| |
|
||||
| creates a temporary which is freed while still in use
|
||||
| creates a temporary value which is freed while still in use
|
||||
LL |
|
||||
LL | (x1, x2, x3, x4, x5, x6, x7);
|
||||
| -- borrow later used here
|
||||
|
@ -4,7 +4,7 @@ error[E0716]: temporary value dropped while borrowed
|
||||
LL | let x: &'static usize =
|
||||
| -------------- type annotation requires that borrow lasts for `'static`
|
||||
LL | &std::intrinsics::size_of::<i32>();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
|
||||
LL | }
|
||||
| - temporary value is freed at the end of this statement
|
||||
|
||||
|
@ -10,7 +10,7 @@ error[E0716]: temporary value dropped while borrowed
|
||||
--> $DIR/dont_promote_unstable_const_fn.rs:17:28
|
||||
|
|
||||
LL | let _: &'static u32 = &foo();
|
||||
| ------------ ^^^^^ creates a temporary which is freed while still in use
|
||||
| ------------ ^^^^^ creates a temporary value which is freed while still in use
|
||||
| |
|
||||
| type annotation requires that borrow lasts for `'static`
|
||||
LL | }
|
||||
@ -20,7 +20,7 @@ error[E0716]: temporary value dropped while borrowed
|
||||
--> $DIR/dont_promote_unstable_const_fn.rs:21:28
|
||||
|
|
||||
LL | let _: &'static u32 = &meh();
|
||||
| ------------ ^^^^^ creates a temporary which is freed while still in use
|
||||
| ------------ ^^^^^ creates a temporary value which is freed while still in use
|
||||
| |
|
||||
| type annotation requires that borrow lasts for `'static`
|
||||
...
|
||||
@ -31,7 +31,7 @@ error[E0716]: temporary value dropped while borrowed
|
||||
--> $DIR/dont_promote_unstable_const_fn.rs:22:26
|
||||
|
|
||||
LL | let x: &'static _ = &std::time::Duration::from_millis(42).subsec_millis();
|
||||
| ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
|
||||
| ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
|
||||
| |
|
||||
| type annotation requires that borrow lasts for `'static`
|
||||
LL |
|
||||
|
@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed
|
||||
--> $DIR/dont_promote_unstable_const_fn_cross_crate.rs:8:28
|
||||
|
|
||||
LL | let _: &'static u32 = &foo();
|
||||
| ------------ ^^^^^ creates a temporary which is freed while still in use
|
||||
| ------------ ^^^^^ creates a temporary value which is freed while still in use
|
||||
| |
|
||||
| type annotation requires that borrow lasts for `'static`
|
||||
LL | let _x: &'static u32 = &foo();
|
||||
@ -13,7 +13,7 @@ error[E0716]: temporary value dropped while borrowed
|
||||
--> $DIR/dont_promote_unstable_const_fn_cross_crate.rs:9:29
|
||||
|
|
||||
LL | let _x: &'static u32 = &foo();
|
||||
| ------------ ^^^^^ creates a temporary which is freed while still in use
|
||||
| ------------ ^^^^^ creates a temporary value which is freed while still in use
|
||||
| |
|
||||
| type annotation requires that borrow lasts for `'static`
|
||||
LL | }
|
||||
|
@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed
|
||||
--> $DIR/promoted_const_fn_fail.rs:17:27
|
||||
|
|
||||
LL | let x: &'static u8 = &(bar() + 1);
|
||||
| ----------- ^^^^^^^^^^^ creates a temporary which is freed while still in use
|
||||
| ----------- ^^^^^^^^^^^ creates a temporary value which is freed while still in use
|
||||
| |
|
||||
| type annotation requires that borrow lasts for `'static`
|
||||
...
|
||||
|
@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed
|
||||
--> $DIR/promoted_const_fn_fail_deny_const_err.rs:18:27
|
||||
|
|
||||
LL | let x: &'static u8 = &(bar() + 1);
|
||||
| ----------- ^^^^^^^^^^^ creates a temporary which is freed while still in use
|
||||
| ----------- ^^^^^^^^^^^ creates a temporary value which is freed while still in use
|
||||
| |
|
||||
| type annotation requires that borrow lasts for `'static`
|
||||
...
|
||||
|
@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed
|
||||
--> $DIR/promoted_raw_ptr_ops.rs:2:29
|
||||
|
|
||||
LL | let x: &'static bool = &(42 as *const i32 == 43 as *const i32);
|
||||
| ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
|
||||
| ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
|
||||
| |
|
||||
| type annotation requires that borrow lasts for `'static`
|
||||
...
|
||||
@ -13,7 +13,7 @@ error[E0716]: temporary value dropped while borrowed
|
||||
--> $DIR/promoted_raw_ptr_ops.rs:4:30
|
||||
|
|
||||
LL | let y: &'static usize = &(&1 as *const i32 as usize + 1);
|
||||
| -------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
|
||||
| -------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
|
||||
| |
|
||||
| type annotation requires that borrow lasts for `'static`
|
||||
...
|
||||
@ -24,7 +24,7 @@ error[E0716]: temporary value dropped while borrowed
|
||||
--> $DIR/promoted_raw_ptr_ops.rs:6:28
|
||||
|
|
||||
LL | let z: &'static i32 = &(unsafe { *(42 as *const i32) });
|
||||
| ------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
|
||||
| ------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
|
||||
| |
|
||||
| type annotation requires that borrow lasts for `'static`
|
||||
...
|
||||
@ -35,7 +35,7 @@ error[E0716]: temporary value dropped while borrowed
|
||||
--> $DIR/promoted_raw_ptr_ops.rs:8:29
|
||||
|
|
||||
LL | let a: &'static bool = &(main as fn() == main as fn());
|
||||
| ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
|
||||
| ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
|
||||
| |
|
||||
| type annotation requires that borrow lasts for `'static`
|
||||
LL |
|
||||
|
@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed
|
||||
--> $DIR/transmute-const-promotion.rs:4:37
|
||||
|
|
||||
LL | let x: &'static u32 = unsafe { &mem::transmute(3.0f32) };
|
||||
| ------------ ^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
|
||||
| ------------ ^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
|
||||
| |
|
||||
| type annotation requires that borrow lasts for `'static`
|
||||
LL |
|
||||
|
@ -7,7 +7,7 @@ LL | let x: &'static bool = &unsafe {
|
||||
| | type annotation requires that borrow lasts for `'static`
|
||||
LL | | Foo { a: &1 }.b == Foo { a: &2 }.b
|
||||
LL | | };
|
||||
| |_____^ creates a temporary which is freed while still in use
|
||||
| |_____^ creates a temporary value which is freed while still in use
|
||||
LL | }
|
||||
| - temporary value is freed at the end of this statement
|
||||
|
||||
|
@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed
|
||||
--> $DIR/const-int-conversion.rs:2:28
|
||||
|
|
||||
LL | let x: &'static i32 = &(5_i32.reverse_bits());
|
||||
| ------------ ^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
|
||||
| ------------ ^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
|
||||
| |
|
||||
| type annotation requires that borrow lasts for `'static`
|
||||
...
|
||||
@ -13,7 +13,7 @@ error[E0716]: temporary value dropped while borrowed
|
||||
--> $DIR/const-int-conversion.rs:4:28
|
||||
|
|
||||
LL | let y: &'static i32 = &(i32::from_be_bytes([0x12, 0x34, 0x56, 0x78]));
|
||||
| ------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
|
||||
| ------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
|
||||
| |
|
||||
| type annotation requires that borrow lasts for `'static`
|
||||
...
|
||||
@ -24,7 +24,7 @@ error[E0716]: temporary value dropped while borrowed
|
||||
--> $DIR/const-int-conversion.rs:6:28
|
||||
|
|
||||
LL | let z: &'static i32 = &(i32::from_le_bytes([0x12, 0x34, 0x56, 0x78]));
|
||||
| ------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
|
||||
| ------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
|
||||
| |
|
||||
| type annotation requires that borrow lasts for `'static`
|
||||
...
|
||||
@ -35,7 +35,7 @@ error[E0716]: temporary value dropped while borrowed
|
||||
--> $DIR/const-int-conversion.rs:8:28
|
||||
|
|
||||
LL | let a: &'static i32 = &(i32::from_be(i32::from_ne_bytes([0x80, 0, 0, 0])));
|
||||
| ------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
|
||||
| ------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
|
||||
| |
|
||||
| type annotation requires that borrow lasts for `'static`
|
||||
...
|
||||
@ -46,7 +46,7 @@ error[E0716]: temporary value dropped while borrowed
|
||||
--> $DIR/const-int-conversion.rs:10:29
|
||||
|
|
||||
LL | let b: &'static [u8] = &(0x12_34_56_78_i32.to_be_bytes());
|
||||
| ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
|
||||
| ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
|
||||
| |
|
||||
| type annotation requires that borrow lasts for `'static`
|
||||
...
|
||||
@ -57,7 +57,7 @@ error[E0716]: temporary value dropped while borrowed
|
||||
--> $DIR/const-int-conversion.rs:12:29
|
||||
|
|
||||
LL | let c: &'static [u8] = &(0x12_34_56_78_i32.to_le_bytes());
|
||||
| ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
|
||||
| ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
|
||||
| |
|
||||
| type annotation requires that borrow lasts for `'static`
|
||||
...
|
||||
@ -68,7 +68,7 @@ error[E0716]: temporary value dropped while borrowed
|
||||
--> $DIR/const-int-conversion.rs:14:29
|
||||
|
|
||||
LL | let d: &'static [u8] = &(i32::MIN.to_be().to_ne_bytes());
|
||||
| ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
|
||||
| ------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
|
||||
| |
|
||||
| type annotation requires that borrow lasts for `'static`
|
||||
LL |
|
||||
|
@ -2,7 +2,7 @@ error[E0716]: temporary value dropped while borrowed
|
||||
--> $DIR/const-int-overflowing.rs:2:36
|
||||
|
|
||||
LL | let x: &'static (i32, bool) = &(5_i32.overflowing_add(3));
|
||||
| -------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
|
||||
| -------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
|
||||
| |
|
||||
| type annotation requires that borrow lasts for `'static`
|
||||
...
|
||||
@ -13,7 +13,7 @@ error[E0716]: temporary value dropped while borrowed
|
||||
--> $DIR/const-int-overflowing.rs:4:36
|
||||
|
|
||||
LL | let y: &'static (i32, bool) = &(5_i32.overflowing_sub(3));
|
||||
| -------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
|
||||
| -------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
|
||||
| |
|
||||
| type annotation requires that borrow lasts for `'static`
|
||||
...
|
||||
@ -24,7 +24,7 @@ error[E0716]: temporary value dropped while borrowed
|
||||
--> $DIR/const-int-overflowing.rs:6:36
|
||||
|
|
||||
LL | let z: &'static (i32, bool) = &(5_i32.overflowing_mul(3));
|
||||
| -------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
|
||||
| -------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
|
||||
| |
|
||||
| type annotation requires that borrow lasts for `'static`
|
||||
LL |
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user