mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-28 02:57:37 +00:00
Auto merge of #127819 - matthiaskrgr:rollup-djdffkl, r=matthiaskrgr
Rollup of 8 pull requests Successful merges: - #127669 (Fix the issue of invalid suggestion for a reference of iterator) - #127707 (match lowering: Use an iterator to find `expand_until`) - #127730 (Fix and enforce `unsafe_op_in_unsafe_fn` in compiler) - #127789 (delete #![allow(unsafe_op_in_unsafe_fn)] in teeos) - #127805 (run-make-support: update gimli to 0.31.0) - #127808 (Make ErrorGuaranteed discoverable outside types, consts, and lifetimes) - #127817 (Fix a bunch of sites that were walking instead of visiting, making it impossible for visitor impls to look at these values) - #127818 (Various ast validation simplifications) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
16b569057e
13
Cargo.lock
13
Cargo.lock
@ -1618,6 +1618,17 @@ dependencies = [
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gimli"
|
||||
version = "0.31.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64"
|
||||
dependencies = [
|
||||
"fallible-iterator",
|
||||
"indexmap",
|
||||
"stable_deref_trait",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glob"
|
||||
version = "0.3.1"
|
||||
@ -3421,7 +3432,7 @@ dependencies = [
|
||||
"ar",
|
||||
"bstr",
|
||||
"build_helper",
|
||||
"gimli 0.28.1",
|
||||
"gimli 0.31.0",
|
||||
"object 0.34.0",
|
||||
"regex",
|
||||
"similar",
|
||||
|
@ -627,7 +627,7 @@ impl Step for Size {
|
||||
|
||||
#[inline]
|
||||
unsafe fn forward_unchecked(start: Self, count: usize) -> Self {
|
||||
Self::from_bytes(u64::forward_unchecked(start.bytes(), count))
|
||||
Self::from_bytes(unsafe { u64::forward_unchecked(start.bytes(), count) })
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -642,7 +642,7 @@ impl Step for Size {
|
||||
|
||||
#[inline]
|
||||
unsafe fn backward_unchecked(start: Self, count: usize) -> Self {
|
||||
Self::from_bytes(u64::backward_unchecked(start.bytes(), count))
|
||||
Self::from_bytes(unsafe { u64::backward_unchecked(start.bytes(), count) })
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -482,7 +482,7 @@ pub fn noop_visit_ty<T: MutVisitor>(ty: &mut P<Ty>, vis: &mut T) {
|
||||
TyKind::Slice(ty) => vis.visit_ty(ty),
|
||||
TyKind::Ptr(mt) => vis.visit_mt(mt),
|
||||
TyKind::Ref(lt, mt) => {
|
||||
visit_opt(lt, |lt| noop_visit_lifetime(lt, vis));
|
||||
visit_opt(lt, |lt| vis.visit_lifetime(lt));
|
||||
vis.visit_mt(mt);
|
||||
}
|
||||
TyKind::BareFn(bft) => {
|
||||
@ -925,7 +925,7 @@ pub fn noop_flat_map_generic_param<T: MutVisitor>(
|
||||
vis.visit_id(id);
|
||||
visit_attrs(attrs, vis);
|
||||
vis.visit_ident(ident);
|
||||
visit_vec(bounds, |bound| noop_visit_param_bound(bound, vis));
|
||||
visit_vec(bounds, |bound| vis.visit_param_bound(bound));
|
||||
match kind {
|
||||
GenericParamKind::Lifetime => {}
|
||||
GenericParamKind::Type { default } => {
|
||||
@ -983,7 +983,7 @@ fn noop_visit_where_predicate<T: MutVisitor>(pred: &mut WherePredicate, vis: &mu
|
||||
}
|
||||
WherePredicate::RegionPredicate(rp) => {
|
||||
let WhereRegionPredicate { span, lifetime, bounds } = rp;
|
||||
noop_visit_lifetime(lifetime, vis);
|
||||
vis.visit_lifetime(lifetime);
|
||||
visit_vec(bounds, |bound| noop_visit_param_bound(bound, vis));
|
||||
vis.visit_span(span);
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ use std::mem;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use thin_vec::thin_vec;
|
||||
|
||||
use crate::errors;
|
||||
use crate::errors::{self, TildeConstReason};
|
||||
|
||||
/// Is `self` allowed semantically as the first parameter in an `FnDecl`?
|
||||
enum SelfSemantic {
|
||||
@ -46,27 +46,12 @@ enum SelfSemantic {
|
||||
No,
|
||||
}
|
||||
|
||||
/// What is the context that prevents using `~const`?
|
||||
// FIXME(effects): Consider getting rid of this in favor of `errors::TildeConstReason`, they're
|
||||
// almost identical. This gets rid of an abstraction layer which might be considered bad.
|
||||
enum DisallowTildeConstContext<'a> {
|
||||
TraitObject,
|
||||
Fn(FnKind<'a>),
|
||||
Trait(Span),
|
||||
TraitImpl(Span),
|
||||
Impl(Span),
|
||||
TraitAssocTy(Span),
|
||||
TraitImplAssocTy(Span),
|
||||
InherentAssocTy(Span),
|
||||
Item,
|
||||
}
|
||||
|
||||
enum TraitOrTraitImpl<'a> {
|
||||
enum TraitOrTraitImpl {
|
||||
Trait { span: Span, constness: Option<Span> },
|
||||
TraitImpl { constness: Const, polarity: ImplPolarity, trait_ref: &'a TraitRef },
|
||||
TraitImpl { constness: Const, polarity: ImplPolarity, trait_ref: Span },
|
||||
}
|
||||
|
||||
impl<'a> TraitOrTraitImpl<'a> {
|
||||
impl TraitOrTraitImpl {
|
||||
fn constness(&self) -> Option<Span> {
|
||||
match self {
|
||||
Self::Trait { constness: Some(span), .. }
|
||||
@ -81,9 +66,9 @@ struct AstValidator<'a> {
|
||||
features: &'a Features,
|
||||
|
||||
/// The span of the `extern` in an `extern { ... }` block, if any.
|
||||
extern_mod: Option<&'a Item>,
|
||||
extern_mod: Option<Span>,
|
||||
|
||||
outer_trait_or_trait_impl: Option<TraitOrTraitImpl<'a>>,
|
||||
outer_trait_or_trait_impl: Option<TraitOrTraitImpl>,
|
||||
|
||||
has_proc_macro_decls: bool,
|
||||
|
||||
@ -92,7 +77,7 @@ struct AstValidator<'a> {
|
||||
/// e.g., `impl Iterator<Item = impl Debug>`.
|
||||
outer_impl_trait: Option<Span>,
|
||||
|
||||
disallow_tilde_const: Option<DisallowTildeConstContext<'a>>,
|
||||
disallow_tilde_const: Option<TildeConstReason>,
|
||||
|
||||
/// Used to ban `impl Trait` in path projections like `<impl Iterator>::Item`
|
||||
/// or `Foo::Bar<impl Trait>`
|
||||
@ -115,7 +100,7 @@ impl<'a> AstValidator<'a> {
|
||||
trait_.map(|(constness, polarity, trait_ref)| TraitOrTraitImpl::TraitImpl {
|
||||
constness,
|
||||
polarity,
|
||||
trait_ref,
|
||||
trait_ref: trait_ref.path.span,
|
||||
}),
|
||||
);
|
||||
f(self);
|
||||
@ -145,7 +130,7 @@ impl<'a> AstValidator<'a> {
|
||||
|
||||
fn with_tilde_const(
|
||||
&mut self,
|
||||
disallowed: Option<DisallowTildeConstContext<'a>>,
|
||||
disallowed: Option<TildeConstReason>,
|
||||
f: impl FnOnce(&mut Self),
|
||||
) {
|
||||
let old = mem::replace(&mut self.disallow_tilde_const, disallowed);
|
||||
@ -224,7 +209,7 @@ impl<'a> AstValidator<'a> {
|
||||
}
|
||||
}
|
||||
TyKind::TraitObject(..) => self
|
||||
.with_tilde_const(Some(DisallowTildeConstContext::TraitObject), |this| {
|
||||
.with_tilde_const(Some(TildeConstReason::TraitObject), |this| {
|
||||
visit::walk_ty(this, t)
|
||||
}),
|
||||
TyKind::Path(qself, path) => {
|
||||
@ -354,7 +339,7 @@ impl<'a> AstValidator<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_trait_fn_not_const(&self, constness: Const, parent: &TraitOrTraitImpl<'a>) {
|
||||
fn check_trait_fn_not_const(&self, constness: Const, parent: &TraitOrTraitImpl) {
|
||||
let Const::Yes(span) = constness else {
|
||||
return;
|
||||
};
|
||||
@ -367,7 +352,7 @@ impl<'a> AstValidator<'a> {
|
||||
..
|
||||
} = parent
|
||||
{
|
||||
Some(trait_ref.path.span.shrink_to_lo())
|
||||
Some(trait_ref.shrink_to_lo())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
@ -579,7 +564,7 @@ impl<'a> AstValidator<'a> {
|
||||
}
|
||||
|
||||
fn current_extern_span(&self) -> Span {
|
||||
self.session.source_map().guess_head_span(self.extern_mod.unwrap().span)
|
||||
self.session.source_map().guess_head_span(self.extern_mod.unwrap())
|
||||
}
|
||||
|
||||
/// An `fn` in `extern { ... }` cannot have qualifiers, e.g. `async fn`.
|
||||
@ -980,7 +965,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||
this.visit_vis(&item.vis);
|
||||
this.visit_ident(item.ident);
|
||||
let disallowed = matches!(constness, Const::No)
|
||||
.then(|| DisallowTildeConstContext::TraitImpl(item.span));
|
||||
.then(|| TildeConstReason::TraitImpl { span: item.span });
|
||||
this.with_tilde_const(disallowed, |this| this.visit_generics(generics));
|
||||
this.visit_trait_ref(t);
|
||||
this.visit_ty(self_ty);
|
||||
@ -1035,7 +1020,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||
this.visit_vis(&item.vis);
|
||||
this.visit_ident(item.ident);
|
||||
this.with_tilde_const(
|
||||
Some(DisallowTildeConstContext::Impl(item.span)),
|
||||
Some(TildeConstReason::Impl { span: item.span }),
|
||||
|this| this.visit_generics(generics),
|
||||
);
|
||||
this.visit_ty(self_ty);
|
||||
@ -1080,7 +1065,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||
}
|
||||
ItemKind::ForeignMod(ForeignMod { abi, safety, .. }) => {
|
||||
self.with_in_extern_mod(*safety, |this| {
|
||||
let old_item = mem::replace(&mut this.extern_mod, Some(item));
|
||||
let old_item = mem::replace(&mut this.extern_mod, Some(item.span));
|
||||
this.visibility_not_permitted(
|
||||
&item.vis,
|
||||
errors::VisibilityNotPermittedNote::IndividualForeignItems,
|
||||
@ -1154,7 +1139,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||
this.visit_ident(item.ident);
|
||||
let disallowed = is_const_trait
|
||||
.is_none()
|
||||
.then(|| DisallowTildeConstContext::Trait(item.span));
|
||||
.then(|| TildeConstReason::Trait { span: item.span });
|
||||
this.with_tilde_const(disallowed, |this| {
|
||||
this.visit_generics(generics);
|
||||
walk_list!(this, visit_param_bound, bounds, BoundKind::SuperTraits)
|
||||
@ -1399,40 +1384,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||
self.dcx().emit_err(errors::ConstBoundTraitObject { span: trait_ref.span });
|
||||
}
|
||||
(_, BoundConstness::Maybe(span), BoundPolarity::Positive)
|
||||
if let Some(reason) = &self.disallow_tilde_const =>
|
||||
if let Some(reason) = self.disallow_tilde_const =>
|
||||
{
|
||||
let reason = match reason {
|
||||
DisallowTildeConstContext::Fn(FnKind::Closure(..)) => {
|
||||
errors::TildeConstReason::Closure
|
||||
}
|
||||
DisallowTildeConstContext::Fn(FnKind::Fn(_, ident, ..)) => {
|
||||
errors::TildeConstReason::Function { ident: ident.span }
|
||||
}
|
||||
&DisallowTildeConstContext::Trait(span) => {
|
||||
errors::TildeConstReason::Trait { span }
|
||||
}
|
||||
&DisallowTildeConstContext::TraitImpl(span) => {
|
||||
errors::TildeConstReason::TraitImpl { span }
|
||||
}
|
||||
&DisallowTildeConstContext::Impl(span) => {
|
||||
// FIXME(effects): Consider providing a help message or even a structured
|
||||
// suggestion for moving such bounds to the assoc const fns if available.
|
||||
errors::TildeConstReason::Impl { span }
|
||||
}
|
||||
&DisallowTildeConstContext::TraitAssocTy(span) => {
|
||||
errors::TildeConstReason::TraitAssocTy { span }
|
||||
}
|
||||
&DisallowTildeConstContext::TraitImplAssocTy(span) => {
|
||||
errors::TildeConstReason::TraitImplAssocTy { span }
|
||||
}
|
||||
&DisallowTildeConstContext::InherentAssocTy(span) => {
|
||||
errors::TildeConstReason::InherentAssocTy { span }
|
||||
}
|
||||
DisallowTildeConstContext::TraitObject => {
|
||||
errors::TildeConstReason::TraitObject
|
||||
}
|
||||
DisallowTildeConstContext::Item => errors::TildeConstReason::Item,
|
||||
};
|
||||
self.dcx().emit_err(errors::TildeConstDisallowed { span, reason });
|
||||
}
|
||||
(
|
||||
@ -1569,7 +1522,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||
.and_then(TraitOrTraitImpl::constness)
|
||||
.is_some();
|
||||
|
||||
let disallowed = (!tilde_const_allowed).then(|| DisallowTildeConstContext::Fn(fk));
|
||||
let disallowed = (!tilde_const_allowed).then(|| match fk {
|
||||
FnKind::Fn(_, ident, _, _, _, _) => TildeConstReason::Function { ident: ident.span },
|
||||
FnKind::Closure(_, _, _) => TildeConstReason::Closure,
|
||||
});
|
||||
self.with_tilde_const(disallowed, |this| visit::walk_fn(this, fk));
|
||||
}
|
||||
|
||||
@ -1664,12 +1620,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||
AssocItemKind::Type(_) => {
|
||||
let disallowed = (!parent_is_const).then(|| match self.outer_trait_or_trait_impl {
|
||||
Some(TraitOrTraitImpl::Trait { .. }) => {
|
||||
DisallowTildeConstContext::TraitAssocTy(item.span)
|
||||
TildeConstReason::TraitAssocTy { span: item.span }
|
||||
}
|
||||
Some(TraitOrTraitImpl::TraitImpl { .. }) => {
|
||||
DisallowTildeConstContext::TraitImplAssocTy(item.span)
|
||||
TildeConstReason::TraitImplAssocTy { span: item.span }
|
||||
}
|
||||
None => DisallowTildeConstContext::InherentAssocTy(item.span),
|
||||
None => TildeConstReason::InherentAssocTy { span: item.span },
|
||||
});
|
||||
self.with_tilde_const(disallowed, |this| {
|
||||
this.with_in_trait_impl(None, |this| visit::walk_assoc_item(this, item, ctxt))
|
||||
@ -1852,7 +1808,7 @@ pub fn check_crate(
|
||||
outer_trait_or_trait_impl: None,
|
||||
has_proc_macro_decls: false,
|
||||
outer_impl_trait: None,
|
||||
disallow_tilde_const: Some(DisallowTildeConstContext::Item),
|
||||
disallow_tilde_const: Some(TildeConstReason::Item),
|
||||
is_impl_trait_banned: false,
|
||||
extern_mod_safety: None,
|
||||
lint_buffer: lints,
|
||||
|
@ -612,7 +612,7 @@ pub struct TildeConstDisallowed {
|
||||
pub reason: TildeConstReason,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[derive(Subdiagnostic, Copy, Clone)]
|
||||
pub enum TildeConstReason {
|
||||
#[note(ast_passes_closure)]
|
||||
Closure,
|
||||
|
@ -21,14 +21,16 @@ pub(crate) unsafe fn codegen(
|
||||
) {
|
||||
let llcx = &*module_llvm.llcx;
|
||||
let llmod = module_llvm.llmod();
|
||||
let usize = match tcx.sess.target.pointer_width {
|
||||
16 => llvm::LLVMInt16TypeInContext(llcx),
|
||||
32 => llvm::LLVMInt32TypeInContext(llcx),
|
||||
64 => llvm::LLVMInt64TypeInContext(llcx),
|
||||
tws => bug!("Unsupported target word size for int: {}", tws),
|
||||
let usize = unsafe {
|
||||
match tcx.sess.target.pointer_width {
|
||||
16 => llvm::LLVMInt16TypeInContext(llcx),
|
||||
32 => llvm::LLVMInt32TypeInContext(llcx),
|
||||
64 => llvm::LLVMInt64TypeInContext(llcx),
|
||||
tws => bug!("Unsupported target word size for int: {}", tws),
|
||||
}
|
||||
};
|
||||
let i8 = llvm::LLVMInt8TypeInContext(llcx);
|
||||
let i8p = llvm::LLVMPointerTypeInContext(llcx, 0);
|
||||
let i8 = unsafe { llvm::LLVMInt8TypeInContext(llcx) };
|
||||
let i8p = unsafe { llvm::LLVMPointerTypeInContext(llcx, 0) };
|
||||
|
||||
if kind == AllocatorKind::Default {
|
||||
for method in ALLOCATOR_METHODS {
|
||||
@ -73,23 +75,25 @@ pub(crate) unsafe fn codegen(
|
||||
true,
|
||||
);
|
||||
|
||||
// __rust_alloc_error_handler_should_panic
|
||||
let name = OomStrategy::SYMBOL;
|
||||
let ll_g = llvm::LLVMRustGetOrInsertGlobal(llmod, name.as_ptr().cast(), name.len(), i8);
|
||||
if tcx.sess.default_hidden_visibility() {
|
||||
llvm::LLVMRustSetVisibility(ll_g, llvm::Visibility::Hidden);
|
||||
}
|
||||
let val = tcx.sess.opts.unstable_opts.oom.should_panic();
|
||||
let llval = llvm::LLVMConstInt(i8, val as u64, False);
|
||||
llvm::LLVMSetInitializer(ll_g, llval);
|
||||
unsafe {
|
||||
// __rust_alloc_error_handler_should_panic
|
||||
let name = OomStrategy::SYMBOL;
|
||||
let ll_g = llvm::LLVMRustGetOrInsertGlobal(llmod, name.as_ptr().cast(), name.len(), i8);
|
||||
if tcx.sess.default_hidden_visibility() {
|
||||
llvm::LLVMRustSetVisibility(ll_g, llvm::Visibility::Hidden);
|
||||
}
|
||||
let val = tcx.sess.opts.unstable_opts.oom.should_panic();
|
||||
let llval = llvm::LLVMConstInt(i8, val as u64, False);
|
||||
llvm::LLVMSetInitializer(ll_g, llval);
|
||||
|
||||
let name = NO_ALLOC_SHIM_IS_UNSTABLE;
|
||||
let ll_g = llvm::LLVMRustGetOrInsertGlobal(llmod, name.as_ptr().cast(), name.len(), i8);
|
||||
if tcx.sess.default_hidden_visibility() {
|
||||
llvm::LLVMRustSetVisibility(ll_g, llvm::Visibility::Hidden);
|
||||
let name = NO_ALLOC_SHIM_IS_UNSTABLE;
|
||||
let ll_g = llvm::LLVMRustGetOrInsertGlobal(llmod, name.as_ptr().cast(), name.len(), i8);
|
||||
if tcx.sess.default_hidden_visibility() {
|
||||
llvm::LLVMRustSetVisibility(ll_g, llvm::Visibility::Hidden);
|
||||
}
|
||||
let llval = llvm::LLVMConstInt(i8, 0, False);
|
||||
llvm::LLVMSetInitializer(ll_g, llval);
|
||||
}
|
||||
let llval = llvm::LLVMConstInt(i8, 0, False);
|
||||
llvm::LLVMSetInitializer(ll_g, llval);
|
||||
|
||||
if tcx.sess.opts.debuginfo != DebugInfo::None {
|
||||
let dbg_cx = debuginfo::CodegenUnitDebugContext::new(llmod);
|
||||
|
@ -727,7 +727,7 @@ pub unsafe fn optimize_thin_module(
|
||||
// into that context. One day, however, we may do this for upstream
|
||||
// crates but for locally codegened modules we may be able to reuse
|
||||
// that LLVM Context and Module.
|
||||
let llcx = llvm::LLVMRustContextCreate(cgcx.fewer_names);
|
||||
let llcx = unsafe { llvm::LLVMRustContextCreate(cgcx.fewer_names) };
|
||||
let llmod_raw = parse_module(llcx, module_name, thin_module.data(), dcx)? as *const _;
|
||||
let mut module = ModuleCodegen {
|
||||
module_llvm: ModuleLlvm { llmod_raw, llcx, tm: ManuallyDrop::new(tm) },
|
||||
@ -750,7 +750,9 @@ pub unsafe fn optimize_thin_module(
|
||||
{
|
||||
let _timer =
|
||||
cgcx.prof.generic_activity_with_arg("LLVM_thin_lto_rename", thin_module.name());
|
||||
if !llvm::LLVMRustPrepareThinLTORename(thin_module.shared.data.0, llmod, target) {
|
||||
if unsafe {
|
||||
!llvm::LLVMRustPrepareThinLTORename(thin_module.shared.data.0, llmod, target)
|
||||
} {
|
||||
return Err(write::llvm_err(dcx, LlvmError::PrepareThinLtoModule));
|
||||
}
|
||||
save_temp_bitcode(cgcx, &module, "thin-lto-after-rename");
|
||||
@ -760,7 +762,8 @@ pub unsafe fn optimize_thin_module(
|
||||
let _timer = cgcx
|
||||
.prof
|
||||
.generic_activity_with_arg("LLVM_thin_lto_resolve_weak", thin_module.name());
|
||||
if !llvm::LLVMRustPrepareThinLTOResolveWeak(thin_module.shared.data.0, llmod) {
|
||||
if unsafe { !llvm::LLVMRustPrepareThinLTOResolveWeak(thin_module.shared.data.0, llmod) }
|
||||
{
|
||||
return Err(write::llvm_err(dcx, LlvmError::PrepareThinLtoModule));
|
||||
}
|
||||
save_temp_bitcode(cgcx, &module, "thin-lto-after-resolve");
|
||||
@ -770,7 +773,8 @@ pub unsafe fn optimize_thin_module(
|
||||
let _timer = cgcx
|
||||
.prof
|
||||
.generic_activity_with_arg("LLVM_thin_lto_internalize", thin_module.name());
|
||||
if !llvm::LLVMRustPrepareThinLTOInternalize(thin_module.shared.data.0, llmod) {
|
||||
if unsafe { !llvm::LLVMRustPrepareThinLTOInternalize(thin_module.shared.data.0, llmod) }
|
||||
{
|
||||
return Err(write::llvm_err(dcx, LlvmError::PrepareThinLtoModule));
|
||||
}
|
||||
save_temp_bitcode(cgcx, &module, "thin-lto-after-internalize");
|
||||
@ -779,7 +783,9 @@ pub unsafe fn optimize_thin_module(
|
||||
{
|
||||
let _timer =
|
||||
cgcx.prof.generic_activity_with_arg("LLVM_thin_lto_import", thin_module.name());
|
||||
if !llvm::LLVMRustPrepareThinLTOImport(thin_module.shared.data.0, llmod, target) {
|
||||
if unsafe {
|
||||
!llvm::LLVMRustPrepareThinLTOImport(thin_module.shared.data.0, llmod, target)
|
||||
} {
|
||||
return Err(write::llvm_err(dcx, LlvmError::PrepareThinLtoModule));
|
||||
}
|
||||
save_temp_bitcode(cgcx, &module, "thin-lto-after-import");
|
||||
|
@ -46,13 +46,15 @@ pub unsafe extern "C" fn selfprofile_before_pass_callback(
|
||||
pass_name: *const c_char,
|
||||
ir_name: *const c_char,
|
||||
) {
|
||||
let llvm_self_profiler = &mut *(llvm_self_profiler as *mut LlvmSelfProfiler<'_>);
|
||||
let pass_name = CStr::from_ptr(pass_name).to_str().expect("valid UTF-8");
|
||||
let ir_name = CStr::from_ptr(ir_name).to_str().expect("valid UTF-8");
|
||||
llvm_self_profiler.before_pass_callback(pass_name, ir_name);
|
||||
unsafe {
|
||||
let llvm_self_profiler = &mut *(llvm_self_profiler as *mut LlvmSelfProfiler<'_>);
|
||||
let pass_name = CStr::from_ptr(pass_name).to_str().expect("valid UTF-8");
|
||||
let ir_name = CStr::from_ptr(ir_name).to_str().expect("valid UTF-8");
|
||||
llvm_self_profiler.before_pass_callback(pass_name, ir_name);
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe extern "C" fn selfprofile_after_pass_callback(llvm_self_profiler: *mut c_void) {
|
||||
let llvm_self_profiler = &mut *(llvm_self_profiler as *mut LlvmSelfProfiler<'_>);
|
||||
let llvm_self_profiler = unsafe { &mut *(llvm_self_profiler as *mut LlvmSelfProfiler<'_>) };
|
||||
llvm_self_profiler.after_pass_callback();
|
||||
}
|
||||
|
@ -428,9 +428,10 @@ unsafe extern "C" fn diagnostic_handler(info: &DiagnosticInfo, user: *mut c_void
|
||||
if user.is_null() {
|
||||
return;
|
||||
}
|
||||
let (cgcx, dcx) = *(user as *const (&CodegenContext<LlvmCodegenBackend>, DiagCtxtHandle<'_>));
|
||||
let (cgcx, dcx) =
|
||||
unsafe { *(user as *const (&CodegenContext<LlvmCodegenBackend>, DiagCtxtHandle<'_>)) };
|
||||
|
||||
match llvm::diagnostic::Diagnostic::unpack(info) {
|
||||
match unsafe { llvm::diagnostic::Diagnostic::unpack(info) } {
|
||||
llvm::diagnostic::InlineAsm(inline) => {
|
||||
report_inline_asm(cgcx, inline.message, inline.level, inline.cookie, inline.source);
|
||||
}
|
||||
@ -454,14 +455,14 @@ unsafe extern "C" fn diagnostic_handler(info: &DiagnosticInfo, user: *mut c_void
|
||||
});
|
||||
}
|
||||
llvm::diagnostic::PGO(diagnostic_ref) | llvm::diagnostic::Linker(diagnostic_ref) => {
|
||||
let message = llvm::build_string(|s| {
|
||||
let message = llvm::build_string(|s| unsafe {
|
||||
llvm::LLVMRustWriteDiagnosticInfoToString(diagnostic_ref, s)
|
||||
})
|
||||
.expect("non-UTF8 diagnostic");
|
||||
dcx.emit_warn(FromLlvmDiag { message });
|
||||
}
|
||||
llvm::diagnostic::Unsupported(diagnostic_ref) => {
|
||||
let message = llvm::build_string(|s| {
|
||||
let message = llvm::build_string(|s| unsafe {
|
||||
llvm::LLVMRustWriteDiagnosticInfoToString(diagnostic_ref, s)
|
||||
})
|
||||
.expect("non-UTF8 diagnostic");
|
||||
@ -564,37 +565,39 @@ pub(crate) unsafe fn llvm_optimize(
|
||||
|
||||
let llvm_plugins = config.llvm_plugins.join(",");
|
||||
|
||||
let result = llvm::LLVMRustOptimize(
|
||||
module.module_llvm.llmod(),
|
||||
&*module.module_llvm.tm,
|
||||
to_pass_builder_opt_level(opt_level),
|
||||
opt_stage,
|
||||
cgcx.opts.cg.linker_plugin_lto.enabled(),
|
||||
config.no_prepopulate_passes,
|
||||
config.verify_llvm_ir,
|
||||
using_thin_buffers,
|
||||
config.merge_functions,
|
||||
unroll_loops,
|
||||
config.vectorize_slp,
|
||||
config.vectorize_loop,
|
||||
config.no_builtins,
|
||||
config.emit_lifetime_markers,
|
||||
sanitizer_options.as_ref(),
|
||||
pgo_gen_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()),
|
||||
pgo_use_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()),
|
||||
config.instrument_coverage,
|
||||
instr_profile_output_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()),
|
||||
config.instrument_gcov,
|
||||
pgo_sample_use_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()),
|
||||
config.debug_info_for_profiling,
|
||||
llvm_selfprofiler,
|
||||
selfprofile_before_pass_callback,
|
||||
selfprofile_after_pass_callback,
|
||||
extra_passes.as_ptr().cast(),
|
||||
extra_passes.len(),
|
||||
llvm_plugins.as_ptr().cast(),
|
||||
llvm_plugins.len(),
|
||||
);
|
||||
let result = unsafe {
|
||||
llvm::LLVMRustOptimize(
|
||||
module.module_llvm.llmod(),
|
||||
&*module.module_llvm.tm,
|
||||
to_pass_builder_opt_level(opt_level),
|
||||
opt_stage,
|
||||
cgcx.opts.cg.linker_plugin_lto.enabled(),
|
||||
config.no_prepopulate_passes,
|
||||
config.verify_llvm_ir,
|
||||
using_thin_buffers,
|
||||
config.merge_functions,
|
||||
unroll_loops,
|
||||
config.vectorize_slp,
|
||||
config.vectorize_loop,
|
||||
config.no_builtins,
|
||||
config.emit_lifetime_markers,
|
||||
sanitizer_options.as_ref(),
|
||||
pgo_gen_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()),
|
||||
pgo_use_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()),
|
||||
config.instrument_coverage,
|
||||
instr_profile_output_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()),
|
||||
config.instrument_gcov,
|
||||
pgo_sample_use_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()),
|
||||
config.debug_info_for_profiling,
|
||||
llvm_selfprofiler,
|
||||
selfprofile_before_pass_callback,
|
||||
selfprofile_after_pass_callback,
|
||||
extra_passes.as_ptr().cast(),
|
||||
extra_passes.len(),
|
||||
llvm_plugins.as_ptr().cast(),
|
||||
llvm_plugins.len(),
|
||||
)
|
||||
};
|
||||
result.into_result().map_err(|()| llvm_err(dcx, LlvmError::RunLlvmPasses))
|
||||
}
|
||||
|
||||
@ -617,7 +620,7 @@ pub(crate) unsafe fn optimize(
|
||||
if config.emit_no_opt_bc {
|
||||
let out = cgcx.output_filenames.temp_path_ext("no-opt.bc", module_name);
|
||||
let out = path_to_c_string(&out);
|
||||
llvm::LLVMWriteBitcodeToFile(llmod, out.as_ptr());
|
||||
unsafe { llvm::LLVMWriteBitcodeToFile(llmod, out.as_ptr()) };
|
||||
}
|
||||
|
||||
if let Some(opt_level) = config.opt_level {
|
||||
@ -627,7 +630,7 @@ pub(crate) unsafe fn optimize(
|
||||
_ if cgcx.opts.cg.linker_plugin_lto.enabled() => llvm::OptStage::PreLinkThinLTO,
|
||||
_ => llvm::OptStage::PreLinkNoLTO,
|
||||
};
|
||||
return llvm_optimize(cgcx, dcx, module, config, opt_level, opt_stage);
|
||||
return unsafe { llvm_optimize(cgcx, dcx, module, config, opt_level, opt_stage) };
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@ -692,10 +695,12 @@ pub(crate) unsafe fn codegen(
|
||||
where
|
||||
F: FnOnce(&'ll mut PassManager<'ll>) -> R,
|
||||
{
|
||||
let cpm = llvm::LLVMCreatePassManager();
|
||||
llvm::LLVMAddAnalysisPasses(tm, cpm);
|
||||
llvm::LLVMRustAddLibraryInfo(cpm, llmod, no_builtins);
|
||||
f(cpm)
|
||||
unsafe {
|
||||
let cpm = llvm::LLVMCreatePassManager();
|
||||
llvm::LLVMAddAnalysisPasses(tm, cpm);
|
||||
llvm::LLVMRustAddLibraryInfo(cpm, llmod, no_builtins);
|
||||
f(cpm)
|
||||
}
|
||||
}
|
||||
|
||||
// Two things to note:
|
||||
@ -757,7 +762,9 @@ pub(crate) unsafe fn codegen(
|
||||
let _timer = cgcx
|
||||
.prof
|
||||
.generic_activity_with_arg("LLVM_module_codegen_embed_bitcode", &*module.name);
|
||||
embed_bitcode(cgcx, llcx, llmod, &config.bc_cmdline, data);
|
||||
unsafe {
|
||||
embed_bitcode(cgcx, llcx, llmod, &config.bc_cmdline, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -793,7 +800,8 @@ pub(crate) unsafe fn codegen(
|
||||
cursor.position() as size_t
|
||||
}
|
||||
|
||||
let result = llvm::LLVMRustPrintModule(llmod, out_c.as_ptr(), demangle_callback);
|
||||
let result =
|
||||
unsafe { llvm::LLVMRustPrintModule(llmod, out_c.as_ptr(), demangle_callback) };
|
||||
|
||||
if result == llvm::LLVMRustResult::Success {
|
||||
record_artifact_size(&cgcx.prof, "llvm_ir", &out);
|
||||
@ -812,22 +820,24 @@ pub(crate) unsafe fn codegen(
|
||||
// binaries. So we must clone the module to produce the asm output
|
||||
// if we are also producing object code.
|
||||
let llmod = if let EmitObj::ObjectCode(_) = config.emit_obj {
|
||||
llvm::LLVMCloneModule(llmod)
|
||||
unsafe { llvm::LLVMCloneModule(llmod) }
|
||||
} else {
|
||||
llmod
|
||||
};
|
||||
with_codegen(tm, llmod, config.no_builtins, |cpm| {
|
||||
write_output_file(
|
||||
dcx,
|
||||
tm,
|
||||
cpm,
|
||||
llmod,
|
||||
&path,
|
||||
None,
|
||||
llvm::FileType::AssemblyFile,
|
||||
&cgcx.prof,
|
||||
)
|
||||
})?;
|
||||
unsafe {
|
||||
with_codegen(tm, llmod, config.no_builtins, |cpm| {
|
||||
write_output_file(
|
||||
dcx,
|
||||
tm,
|
||||
cpm,
|
||||
llmod,
|
||||
&path,
|
||||
None,
|
||||
llvm::FileType::AssemblyFile,
|
||||
&cgcx.prof,
|
||||
)
|
||||
})?;
|
||||
}
|
||||
}
|
||||
|
||||
match config.emit_obj {
|
||||
@ -851,18 +861,20 @@ pub(crate) unsafe fn codegen(
|
||||
(_, SplitDwarfKind::Split) => Some(dwo_out.as_path()),
|
||||
};
|
||||
|
||||
with_codegen(tm, llmod, config.no_builtins, |cpm| {
|
||||
write_output_file(
|
||||
dcx,
|
||||
tm,
|
||||
cpm,
|
||||
llmod,
|
||||
&obj_out,
|
||||
dwo_out,
|
||||
llvm::FileType::ObjectFile,
|
||||
&cgcx.prof,
|
||||
)
|
||||
})?;
|
||||
unsafe {
|
||||
with_codegen(tm, llmod, config.no_builtins, |cpm| {
|
||||
write_output_file(
|
||||
dcx,
|
||||
tm,
|
||||
cpm,
|
||||
llmod,
|
||||
&obj_out,
|
||||
dwo_out,
|
||||
llvm::FileType::ObjectFile,
|
||||
&cgcx.prof,
|
||||
)
|
||||
})?;
|
||||
}
|
||||
}
|
||||
|
||||
EmitObj::Bitcode => {
|
||||
@ -1013,44 +1025,46 @@ unsafe fn embed_bitcode(
|
||||
// reason (see issue #90326 for historical background).
|
||||
let is_aix = target_is_aix(cgcx);
|
||||
let is_apple = target_is_apple(cgcx);
|
||||
if is_apple || is_aix || cgcx.opts.target_triple.triple().starts_with("wasm") {
|
||||
// We don't need custom section flags, create LLVM globals.
|
||||
let llconst = common::bytes_in_context(llcx, bitcode);
|
||||
let llglobal = llvm::LLVMAddGlobal(
|
||||
llmod,
|
||||
common::val_ty(llconst),
|
||||
c"rustc.embedded.module".as_ptr().cast(),
|
||||
);
|
||||
llvm::LLVMSetInitializer(llglobal, llconst);
|
||||
unsafe {
|
||||
if is_apple || is_aix || cgcx.opts.target_triple.triple().starts_with("wasm") {
|
||||
// We don't need custom section flags, create LLVM globals.
|
||||
let llconst = common::bytes_in_context(llcx, bitcode);
|
||||
let llglobal = llvm::LLVMAddGlobal(
|
||||
llmod,
|
||||
common::val_ty(llconst),
|
||||
c"rustc.embedded.module".as_ptr().cast(),
|
||||
);
|
||||
llvm::LLVMSetInitializer(llglobal, llconst);
|
||||
|
||||
let section = bitcode_section_name(cgcx);
|
||||
llvm::LLVMSetSection(llglobal, section.as_ptr().cast());
|
||||
llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage);
|
||||
llvm::LLVMSetGlobalConstant(llglobal, llvm::True);
|
||||
let section = bitcode_section_name(cgcx);
|
||||
llvm::LLVMSetSection(llglobal, section.as_ptr().cast());
|
||||
llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage);
|
||||
llvm::LLVMSetGlobalConstant(llglobal, llvm::True);
|
||||
|
||||
let llconst = common::bytes_in_context(llcx, cmdline.as_bytes());
|
||||
let llglobal = llvm::LLVMAddGlobal(
|
||||
llmod,
|
||||
common::val_ty(llconst),
|
||||
c"rustc.embedded.cmdline".as_ptr().cast(),
|
||||
);
|
||||
llvm::LLVMSetInitializer(llglobal, llconst);
|
||||
let section = if is_apple {
|
||||
c"__LLVM,__cmdline"
|
||||
} else if is_aix {
|
||||
c".info"
|
||||
let llconst = common::bytes_in_context(llcx, cmdline.as_bytes());
|
||||
let llglobal = llvm::LLVMAddGlobal(
|
||||
llmod,
|
||||
common::val_ty(llconst),
|
||||
c"rustc.embedded.cmdline".as_ptr().cast(),
|
||||
);
|
||||
llvm::LLVMSetInitializer(llglobal, llconst);
|
||||
let section = if is_apple {
|
||||
c"__LLVM,__cmdline"
|
||||
} else if is_aix {
|
||||
c".info"
|
||||
} else {
|
||||
c".llvmcmd"
|
||||
};
|
||||
llvm::LLVMSetSection(llglobal, section.as_ptr().cast());
|
||||
llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage);
|
||||
} else {
|
||||
c".llvmcmd"
|
||||
};
|
||||
llvm::LLVMSetSection(llglobal, section.as_ptr().cast());
|
||||
llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage);
|
||||
} else {
|
||||
// We need custom section flags, so emit module-level inline assembly.
|
||||
let section_flags = if cgcx.is_pe_coff { "n" } else { "e" };
|
||||
let asm = create_section_with_flags_asm(".llvmbc", section_flags, bitcode);
|
||||
llvm::LLVMAppendModuleInlineAsm(llmod, asm.as_ptr().cast(), asm.len());
|
||||
let asm = create_section_with_flags_asm(".llvmcmd", section_flags, cmdline.as_bytes());
|
||||
llvm::LLVMAppendModuleInlineAsm(llmod, asm.as_ptr().cast(), asm.len());
|
||||
// We need custom section flags, so emit module-level inline assembly.
|
||||
let section_flags = if cgcx.is_pe_coff { "n" } else { "e" };
|
||||
let asm = create_section_with_flags_asm(".llvmbc", section_flags, bitcode);
|
||||
llvm::LLVMAppendModuleInlineAsm(llmod, asm.as_ptr().cast(), asm.len());
|
||||
let asm = create_section_with_flags_asm(".llvmcmd", section_flags, cmdline.as_bytes());
|
||||
llvm::LLVMAppendModuleInlineAsm(llmod, asm.as_ptr().cast(), asm.len());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -120,7 +120,7 @@ pub unsafe fn create_module<'ll>(
|
||||
) -> &'ll llvm::Module {
|
||||
let sess = tcx.sess;
|
||||
let mod_name = SmallCStr::new(mod_name);
|
||||
let llmod = llvm::LLVMModuleCreateWithNameInContext(mod_name.as_ptr(), llcx);
|
||||
let llmod = unsafe { llvm::LLVMModuleCreateWithNameInContext(mod_name.as_ptr(), llcx) };
|
||||
|
||||
let mut target_data_layout = sess.target.data_layout.to_string();
|
||||
let llvm_version = llvm_util::get_version();
|
||||
@ -153,11 +153,14 @@ pub unsafe fn create_module<'ll>(
|
||||
// Ensure the data-layout values hardcoded remain the defaults.
|
||||
{
|
||||
let tm = crate::back::write::create_informational_target_machine(tcx.sess);
|
||||
llvm::LLVMRustSetDataLayoutFromTargetMachine(llmod, &tm);
|
||||
unsafe {
|
||||
llvm::LLVMRustSetDataLayoutFromTargetMachine(llmod, &tm);
|
||||
}
|
||||
|
||||
let llvm_data_layout = llvm::LLVMGetDataLayoutStr(llmod);
|
||||
let llvm_data_layout = str::from_utf8(CStr::from_ptr(llvm_data_layout).to_bytes())
|
||||
.expect("got a non-UTF8 data-layout from LLVM");
|
||||
let llvm_data_layout = unsafe { llvm::LLVMGetDataLayoutStr(llmod) };
|
||||
let llvm_data_layout =
|
||||
str::from_utf8(unsafe { CStr::from_ptr(llvm_data_layout) }.to_bytes())
|
||||
.expect("got a non-UTF8 data-layout from LLVM");
|
||||
|
||||
if target_data_layout != llvm_data_layout {
|
||||
tcx.dcx().emit_err(crate::errors::MismatchedDataLayout {
|
||||
@ -170,20 +173,28 @@ pub unsafe fn create_module<'ll>(
|
||||
}
|
||||
|
||||
let data_layout = SmallCStr::new(&target_data_layout);
|
||||
llvm::LLVMSetDataLayout(llmod, data_layout.as_ptr());
|
||||
unsafe {
|
||||
llvm::LLVMSetDataLayout(llmod, data_layout.as_ptr());
|
||||
}
|
||||
|
||||
let llvm_target = SmallCStr::new(&sess.target.llvm_target);
|
||||
llvm::LLVMRustSetNormalizedTarget(llmod, llvm_target.as_ptr());
|
||||
unsafe {
|
||||
llvm::LLVMRustSetNormalizedTarget(llmod, llvm_target.as_ptr());
|
||||
}
|
||||
|
||||
let reloc_model = sess.relocation_model();
|
||||
if matches!(reloc_model, RelocModel::Pic | RelocModel::Pie) {
|
||||
llvm::LLVMRustSetModulePICLevel(llmod);
|
||||
unsafe {
|
||||
llvm::LLVMRustSetModulePICLevel(llmod);
|
||||
}
|
||||
// PIE is potentially more effective than PIC, but can only be used in executables.
|
||||
// If all our outputs are executables, then we can relax PIC to PIE.
|
||||
if reloc_model == RelocModel::Pie
|
||||
|| tcx.crate_types().iter().all(|ty| *ty == CrateType::Executable)
|
||||
{
|
||||
llvm::LLVMRustSetModulePIELevel(llmod);
|
||||
unsafe {
|
||||
llvm::LLVMRustSetModulePIELevel(llmod);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -192,95 +203,109 @@ pub unsafe fn create_module<'ll>(
|
||||
// longer jumps) if a larger code model is used with a smaller one.
|
||||
//
|
||||
// See https://reviews.llvm.org/D52322 and https://reviews.llvm.org/D52323.
|
||||
llvm::LLVMRustSetModuleCodeModel(llmod, to_llvm_code_model(sess.code_model()));
|
||||
unsafe {
|
||||
llvm::LLVMRustSetModuleCodeModel(llmod, to_llvm_code_model(sess.code_model()));
|
||||
}
|
||||
|
||||
// If skipping the PLT is enabled, we need to add some module metadata
|
||||
// to ensure intrinsic calls don't use it.
|
||||
if !sess.needs_plt() {
|
||||
let avoid_plt = c"RtLibUseGOT".as_ptr().cast();
|
||||
llvm::LLVMRustAddModuleFlagU32(llmod, llvm::LLVMModFlagBehavior::Warning, avoid_plt, 1);
|
||||
unsafe {
|
||||
llvm::LLVMRustAddModuleFlagU32(llmod, llvm::LLVMModFlagBehavior::Warning, avoid_plt, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Enable canonical jump tables if CFI is enabled. (See https://reviews.llvm.org/D65629.)
|
||||
if sess.is_sanitizer_cfi_canonical_jump_tables_enabled() && sess.is_sanitizer_cfi_enabled() {
|
||||
let canonical_jump_tables = c"CFI Canonical Jump Tables".as_ptr().cast();
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Override,
|
||||
canonical_jump_tables,
|
||||
1,
|
||||
);
|
||||
unsafe {
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Override,
|
||||
canonical_jump_tables,
|
||||
1,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Enable LTO unit splitting if specified or if CFI is enabled. (See https://reviews.llvm.org/D53891.)
|
||||
if sess.is_split_lto_unit_enabled() || sess.is_sanitizer_cfi_enabled() {
|
||||
let enable_split_lto_unit = c"EnableSplitLTOUnit".as_ptr().cast();
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Override,
|
||||
enable_split_lto_unit,
|
||||
1,
|
||||
);
|
||||
unsafe {
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Override,
|
||||
enable_split_lto_unit,
|
||||
1,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Add "kcfi" module flag if KCFI is enabled. (See https://reviews.llvm.org/D119296.)
|
||||
if sess.is_sanitizer_kcfi_enabled() {
|
||||
let kcfi = c"kcfi".as_ptr().cast();
|
||||
llvm::LLVMRustAddModuleFlagU32(llmod, llvm::LLVMModFlagBehavior::Override, kcfi, 1);
|
||||
unsafe {
|
||||
llvm::LLVMRustAddModuleFlagU32(llmod, llvm::LLVMModFlagBehavior::Override, kcfi, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Control Flow Guard is currently only supported by the MSVC linker on Windows.
|
||||
if sess.target.is_like_msvc {
|
||||
match sess.opts.cg.control_flow_guard {
|
||||
CFGuard::Disabled => {}
|
||||
CFGuard::NoChecks => {
|
||||
// Set `cfguard=1` module flag to emit metadata only.
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Warning,
|
||||
c"cfguard".as_ptr() as *const _,
|
||||
1,
|
||||
)
|
||||
}
|
||||
CFGuard::Checks => {
|
||||
// Set `cfguard=2` module flag to emit metadata and checks.
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Warning,
|
||||
c"cfguard".as_ptr() as *const _,
|
||||
2,
|
||||
)
|
||||
unsafe {
|
||||
match sess.opts.cg.control_flow_guard {
|
||||
CFGuard::Disabled => {}
|
||||
CFGuard::NoChecks => {
|
||||
// Set `cfguard=1` module flag to emit metadata only.
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Warning,
|
||||
c"cfguard".as_ptr() as *const _,
|
||||
1,
|
||||
)
|
||||
}
|
||||
CFGuard::Checks => {
|
||||
// Set `cfguard=2` module flag to emit metadata and checks.
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Warning,
|
||||
c"cfguard".as_ptr() as *const _,
|
||||
2,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(BranchProtection { bti, pac_ret }) = sess.opts.unstable_opts.branch_protection {
|
||||
if sess.target.arch == "aarch64" {
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Min,
|
||||
c"branch-target-enforcement".as_ptr().cast(),
|
||||
bti.into(),
|
||||
);
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Min,
|
||||
c"sign-return-address".as_ptr().cast(),
|
||||
pac_ret.is_some().into(),
|
||||
);
|
||||
let pac_opts = pac_ret.unwrap_or(PacRet { leaf: false, key: PAuthKey::A });
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Min,
|
||||
c"sign-return-address-all".as_ptr().cast(),
|
||||
pac_opts.leaf.into(),
|
||||
);
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Min,
|
||||
c"sign-return-address-with-bkey".as_ptr().cast(),
|
||||
u32::from(pac_opts.key == PAuthKey::B),
|
||||
);
|
||||
unsafe {
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Min,
|
||||
c"branch-target-enforcement".as_ptr().cast(),
|
||||
bti.into(),
|
||||
);
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Min,
|
||||
c"sign-return-address".as_ptr().cast(),
|
||||
pac_ret.is_some().into(),
|
||||
);
|
||||
let pac_opts = pac_ret.unwrap_or(PacRet { leaf: false, key: PAuthKey::A });
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Min,
|
||||
c"sign-return-address-all".as_ptr().cast(),
|
||||
pac_opts.leaf.into(),
|
||||
);
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Min,
|
||||
c"sign-return-address-with-bkey".as_ptr().cast(),
|
||||
u32::from(pac_opts.key == PAuthKey::B),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
bug!(
|
||||
"branch-protection used on non-AArch64 target; \
|
||||
@ -291,39 +316,47 @@ pub unsafe fn create_module<'ll>(
|
||||
|
||||
// Pass on the control-flow protection flags to LLVM (equivalent to `-fcf-protection` in Clang).
|
||||
if let CFProtection::Branch | CFProtection::Full = sess.opts.unstable_opts.cf_protection {
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Override,
|
||||
c"cf-protection-branch".as_ptr().cast(),
|
||||
1,
|
||||
)
|
||||
unsafe {
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Override,
|
||||
c"cf-protection-branch".as_ptr().cast(),
|
||||
1,
|
||||
);
|
||||
}
|
||||
}
|
||||
if let CFProtection::Return | CFProtection::Full = sess.opts.unstable_opts.cf_protection {
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Override,
|
||||
c"cf-protection-return".as_ptr().cast(),
|
||||
1,
|
||||
)
|
||||
unsafe {
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Override,
|
||||
c"cf-protection-return".as_ptr().cast(),
|
||||
1,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if sess.opts.unstable_opts.virtual_function_elimination {
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Error,
|
||||
c"Virtual Function Elim".as_ptr().cast(),
|
||||
1,
|
||||
);
|
||||
unsafe {
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Error,
|
||||
c"Virtual Function Elim".as_ptr().cast(),
|
||||
1,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Set module flag to enable Windows EHCont Guard (/guard:ehcont).
|
||||
if sess.opts.unstable_opts.ehcont_guard {
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Warning,
|
||||
c"ehcontguard".as_ptr() as *const _,
|
||||
1,
|
||||
)
|
||||
unsafe {
|
||||
llvm::LLVMRustAddModuleFlagU32(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Warning,
|
||||
c"ehcontguard".as_ptr() as *const _,
|
||||
1,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Insert `llvm.ident` metadata.
|
||||
@ -333,16 +366,20 @@ pub unsafe fn create_module<'ll>(
|
||||
#[allow(clippy::option_env_unwrap)]
|
||||
let rustc_producer =
|
||||
format!("rustc version {}", option_env!("CFG_VERSION").expect("CFG_VERSION"));
|
||||
let name_metadata = llvm::LLVMMDStringInContext(
|
||||
llcx,
|
||||
rustc_producer.as_ptr().cast(),
|
||||
rustc_producer.as_bytes().len() as c_uint,
|
||||
);
|
||||
llvm::LLVMAddNamedMetadataOperand(
|
||||
llmod,
|
||||
c"llvm.ident".as_ptr(),
|
||||
llvm::LLVMMDNodeInContext(llcx, &name_metadata, 1),
|
||||
);
|
||||
let name_metadata = unsafe {
|
||||
llvm::LLVMMDStringInContext(
|
||||
llcx,
|
||||
rustc_producer.as_ptr().cast(),
|
||||
rustc_producer.as_bytes().len() as c_uint,
|
||||
)
|
||||
};
|
||||
unsafe {
|
||||
llvm::LLVMAddNamedMetadataOperand(
|
||||
llmod,
|
||||
c"llvm.ident".as_ptr(),
|
||||
llvm::LLVMMDNodeInContext(llcx, &name_metadata, 1),
|
||||
);
|
||||
}
|
||||
|
||||
// Emit RISC-V specific target-abi metadata
|
||||
// to workaround lld as the LTO plugin not
|
||||
@ -351,13 +388,15 @@ pub unsafe fn create_module<'ll>(
|
||||
// If llvm_abiname is empty, emit nothing.
|
||||
let llvm_abiname = &sess.target.options.llvm_abiname;
|
||||
if matches!(sess.target.arch.as_ref(), "riscv32" | "riscv64") && !llvm_abiname.is_empty() {
|
||||
llvm::LLVMRustAddModuleFlagString(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Error,
|
||||
c"target-abi".as_ptr(),
|
||||
llvm_abiname.as_ptr().cast(),
|
||||
llvm_abiname.len(),
|
||||
);
|
||||
unsafe {
|
||||
llvm::LLVMRustAddModuleFlagString(
|
||||
llmod,
|
||||
llvm::LLVMModFlagBehavior::Error,
|
||||
c"target-abi".as_ptr(),
|
||||
llvm_abiname.as_ptr().cast(),
|
||||
llvm_abiname.len(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Add module flags specified via -Z llvm_module_flag
|
||||
@ -375,7 +414,7 @@ pub unsafe fn create_module<'ll>(
|
||||
// We already checked this during option parsing
|
||||
_ => unreachable!(),
|
||||
};
|
||||
llvm::LLVMRustAddModuleFlagU32(llmod, behavior, key.as_ptr().cast(), *value)
|
||||
unsafe { llvm::LLVMRustAddModuleFlagU32(llmod, behavior, key.as_ptr().cast(), *value) }
|
||||
}
|
||||
|
||||
llmod
|
||||
|
@ -216,7 +216,7 @@ impl WriteBackendMethods for LlvmCodegenBackend {
|
||||
module: &ModuleCodegen<Self::Module>,
|
||||
config: &ModuleConfig,
|
||||
) -> Result<(), FatalError> {
|
||||
back::write::optimize(cgcx, dcx, module, config)
|
||||
unsafe { back::write::optimize(cgcx, dcx, module, config) }
|
||||
}
|
||||
fn optimize_fat(
|
||||
cgcx: &CodegenContext<Self>,
|
||||
@ -230,7 +230,7 @@ impl WriteBackendMethods for LlvmCodegenBackend {
|
||||
cgcx: &CodegenContext<Self>,
|
||||
thin: ThinModule<Self>,
|
||||
) -> Result<ModuleCodegen<Self::Module>, FatalError> {
|
||||
back::lto::optimize_thin_module(thin, cgcx)
|
||||
unsafe { back::lto::optimize_thin_module(thin, cgcx) }
|
||||
}
|
||||
unsafe fn codegen(
|
||||
cgcx: &CodegenContext<Self>,
|
||||
@ -238,7 +238,7 @@ impl WriteBackendMethods for LlvmCodegenBackend {
|
||||
module: ModuleCodegen<Self::Module>,
|
||||
config: &ModuleConfig,
|
||||
) -> Result<CompiledModule, FatalError> {
|
||||
back::write::codegen(cgcx, dcx, module, config)
|
||||
unsafe { back::write::codegen(cgcx, dcx, module, config) }
|
||||
}
|
||||
fn prepare_thin(
|
||||
module: ModuleCodegen<Self::Module>,
|
||||
|
@ -40,7 +40,7 @@ impl<'ll> OptimizationDiagnostic<'ll> {
|
||||
let mut filename = None;
|
||||
let pass_name = super::build_string(|pass_name| {
|
||||
message = super::build_string(|message| {
|
||||
filename = super::build_string(|filename| {
|
||||
filename = super::build_string(|filename| unsafe {
|
||||
super::LLVMRustUnpackOptimizationDiagnostic(
|
||||
di,
|
||||
pass_name,
|
||||
@ -91,7 +91,7 @@ impl SrcMgrDiagnostic {
|
||||
let mut ranges = [0; 8];
|
||||
let mut num_ranges = ranges.len() / 2;
|
||||
let message = super::build_string(|message| {
|
||||
buffer = super::build_string(|buffer| {
|
||||
buffer = super::build_string(|buffer| unsafe {
|
||||
have_source = super::LLVMRustUnpackSMDiagnostic(
|
||||
diag,
|
||||
message,
|
||||
@ -134,7 +134,9 @@ impl InlineAsmDiagnostic {
|
||||
let mut message = None;
|
||||
let mut level = super::DiagnosticLevel::Error;
|
||||
|
||||
super::LLVMRustUnpackInlineAsmDiagnostic(di, &mut level, &mut cookie, &mut message);
|
||||
unsafe {
|
||||
super::LLVMRustUnpackInlineAsmDiagnostic(di, &mut level, &mut cookie, &mut message);
|
||||
}
|
||||
|
||||
InlineAsmDiagnostic {
|
||||
level,
|
||||
@ -146,7 +148,8 @@ impl InlineAsmDiagnostic {
|
||||
|
||||
unsafe fn unpackSrcMgr(di: &DiagnosticInfo) -> Self {
|
||||
let mut cookie = 0;
|
||||
let smdiag = SrcMgrDiagnostic::unpack(super::LLVMRustGetSMDiagnostic(di, &mut cookie));
|
||||
let smdiag =
|
||||
unsafe { SrcMgrDiagnostic::unpack(super::LLVMRustGetSMDiagnostic(di, &mut cookie)) };
|
||||
InlineAsmDiagnostic {
|
||||
level: smdiag.level,
|
||||
cookie: cookie.into(),
|
||||
@ -170,44 +173,46 @@ pub enum Diagnostic<'ll> {
|
||||
impl<'ll> Diagnostic<'ll> {
|
||||
pub unsafe fn unpack(di: &'ll DiagnosticInfo) -> Self {
|
||||
use super::DiagnosticKind as Dk;
|
||||
let kind = super::LLVMRustGetDiagInfoKind(di);
|
||||
|
||||
match kind {
|
||||
Dk::InlineAsm => InlineAsm(InlineAsmDiagnostic::unpackInlineAsm(di)),
|
||||
unsafe {
|
||||
let kind = super::LLVMRustGetDiagInfoKind(di);
|
||||
match kind {
|
||||
Dk::InlineAsm => InlineAsm(InlineAsmDiagnostic::unpackInlineAsm(di)),
|
||||
|
||||
Dk::OptimizationRemark => {
|
||||
Optimization(OptimizationDiagnostic::unpack(OptimizationRemark, di))
|
||||
Dk::OptimizationRemark => {
|
||||
Optimization(OptimizationDiagnostic::unpack(OptimizationRemark, di))
|
||||
}
|
||||
Dk::OptimizationRemarkOther => {
|
||||
Optimization(OptimizationDiagnostic::unpack(OptimizationRemarkOther, di))
|
||||
}
|
||||
Dk::OptimizationRemarkMissed => {
|
||||
Optimization(OptimizationDiagnostic::unpack(OptimizationMissed, di))
|
||||
}
|
||||
|
||||
Dk::OptimizationRemarkAnalysis => {
|
||||
Optimization(OptimizationDiagnostic::unpack(OptimizationAnalysis, di))
|
||||
}
|
||||
|
||||
Dk::OptimizationRemarkAnalysisFPCommute => {
|
||||
Optimization(OptimizationDiagnostic::unpack(OptimizationAnalysisFPCommute, di))
|
||||
}
|
||||
|
||||
Dk::OptimizationRemarkAnalysisAliasing => {
|
||||
Optimization(OptimizationDiagnostic::unpack(OptimizationAnalysisAliasing, di))
|
||||
}
|
||||
|
||||
Dk::OptimizationFailure => {
|
||||
Optimization(OptimizationDiagnostic::unpack(OptimizationFailure, di))
|
||||
}
|
||||
|
||||
Dk::PGOProfile => PGO(di),
|
||||
Dk::Linker => Linker(di),
|
||||
Dk::Unsupported => Unsupported(di),
|
||||
|
||||
Dk::SrcMgr => InlineAsm(InlineAsmDiagnostic::unpackSrcMgr(di)),
|
||||
|
||||
_ => UnknownDiagnostic(di),
|
||||
}
|
||||
Dk::OptimizationRemarkOther => {
|
||||
Optimization(OptimizationDiagnostic::unpack(OptimizationRemarkOther, di))
|
||||
}
|
||||
Dk::OptimizationRemarkMissed => {
|
||||
Optimization(OptimizationDiagnostic::unpack(OptimizationMissed, di))
|
||||
}
|
||||
|
||||
Dk::OptimizationRemarkAnalysis => {
|
||||
Optimization(OptimizationDiagnostic::unpack(OptimizationAnalysis, di))
|
||||
}
|
||||
|
||||
Dk::OptimizationRemarkAnalysisFPCommute => {
|
||||
Optimization(OptimizationDiagnostic::unpack(OptimizationAnalysisFPCommute, di))
|
||||
}
|
||||
|
||||
Dk::OptimizationRemarkAnalysisAliasing => {
|
||||
Optimization(OptimizationDiagnostic::unpack(OptimizationAnalysisAliasing, di))
|
||||
}
|
||||
|
||||
Dk::OptimizationFailure => {
|
||||
Optimization(OptimizationDiagnostic::unpack(OptimizationFailure, di))
|
||||
}
|
||||
|
||||
Dk::PGOProfile => PGO(di),
|
||||
Dk::Linker => Linker(di),
|
||||
Dk::Unsupported => Unsupported(di),
|
||||
|
||||
Dk::SrcMgr => InlineAsm(InlineAsmDiagnostic::unpackSrcMgr(di)),
|
||||
|
||||
_ => UnknownDiagnostic(di),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -49,12 +49,16 @@ unsafe fn configure_llvm(sess: &Session) {
|
||||
let mut llvm_c_strs = Vec::with_capacity(n_args + 1);
|
||||
let mut llvm_args = Vec::with_capacity(n_args + 1);
|
||||
|
||||
llvm::LLVMRustInstallErrorHandlers();
|
||||
unsafe {
|
||||
llvm::LLVMRustInstallErrorHandlers();
|
||||
}
|
||||
// On Windows, an LLVM assertion will open an Abort/Retry/Ignore dialog
|
||||
// box for the purpose of launching a debugger. However, on CI this will
|
||||
// cause it to hang until it times out, which can take several hours.
|
||||
if std::env::var_os("CI").is_some() {
|
||||
llvm::LLVMRustDisableSystemDialogsOnCrash();
|
||||
unsafe {
|
||||
llvm::LLVMRustDisableSystemDialogsOnCrash();
|
||||
}
|
||||
}
|
||||
|
||||
fn llvm_arg_to_arg_name(full_arg: &str) -> &str {
|
||||
@ -124,12 +128,12 @@ unsafe fn configure_llvm(sess: &Session) {
|
||||
}
|
||||
|
||||
if sess.opts.unstable_opts.llvm_time_trace {
|
||||
llvm::LLVMRustTimeTraceProfilerInitialize();
|
||||
unsafe { llvm::LLVMRustTimeTraceProfilerInitialize() };
|
||||
}
|
||||
|
||||
rustc_llvm::initialize_available_targets();
|
||||
|
||||
llvm::LLVMRustSetLLVMOptions(llvm_args.len() as c_int, llvm_args.as_ptr());
|
||||
unsafe { llvm::LLVMRustSetLLVMOptions(llvm_args.len() as c_int, llvm_args.as_ptr()) };
|
||||
}
|
||||
|
||||
pub fn time_trace_profiler_finish(file_name: &Path) {
|
||||
@ -442,8 +446,8 @@ pub(crate) fn print(req: &PrintRequest, mut out: &mut String, sess: &Session) {
|
||||
let cpu_cstring = CString::new(handle_native(sess.target.cpu.as_ref()))
|
||||
.unwrap_or_else(|e| bug!("failed to convert to cstring: {}", e));
|
||||
unsafe extern "C" fn callback(out: *mut c_void, string: *const c_char, len: usize) {
|
||||
let out = &mut *(out as *mut &mut String);
|
||||
let bytes = slice::from_raw_parts(string as *const u8, len);
|
||||
let out = unsafe { &mut *(out as *mut &mut String) };
|
||||
let bytes = unsafe { slice::from_raw_parts(string as *const u8, len) };
|
||||
write!(out, "{}", String::from_utf8_lossy(bytes)).unwrap();
|
||||
}
|
||||
unsafe {
|
||||
|
@ -108,8 +108,8 @@ impl CodegenCx<'_, '_> {
|
||||
llval: &llvm::Value,
|
||||
is_declaration: bool,
|
||||
) -> bool {
|
||||
let linkage = llvm::LLVMRustGetLinkage(llval);
|
||||
let visibility = llvm::LLVMRustGetVisibility(llval);
|
||||
let linkage = unsafe { llvm::LLVMRustGetLinkage(llval) };
|
||||
let visibility = unsafe { llvm::LLVMRustGetVisibility(llval) };
|
||||
|
||||
if matches!(linkage, llvm::Linkage::InternalLinkage | llvm::Linkage::PrivateLinkage) {
|
||||
return true;
|
||||
@ -145,8 +145,8 @@ impl CodegenCx<'_, '_> {
|
||||
}
|
||||
|
||||
// Thread-local variables generally don't support copy relocations.
|
||||
let is_thread_local_var = llvm::LLVMIsAGlobalVariable(llval)
|
||||
.is_some_and(|v| llvm::LLVMIsThreadLocal(v) == llvm::True);
|
||||
let is_thread_local_var = unsafe { llvm::LLVMIsAGlobalVariable(llval) }
|
||||
.is_some_and(|v| unsafe { llvm::LLVMIsThreadLocal(v) } == llvm::True);
|
||||
if is_thread_local_var {
|
||||
return false;
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ impl<B: WriteBackendMethods> LtoModuleCodegen<B> {
|
||||
B::optimize_fat(cgcx, &mut module)?;
|
||||
Ok(module)
|
||||
}
|
||||
LtoModuleCodegen::Thin(thin) => B::optimize_thin(cgcx, thin),
|
||||
LtoModuleCodegen::Thin(thin) => unsafe { B::optimize_thin(cgcx, thin) },
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -33,7 +33,7 @@ pub unsafe extern "C" fn LLVMRustStringWriteImpl(
|
||||
ptr: *const c_char,
|
||||
size: size_t,
|
||||
) {
|
||||
let slice = slice::from_raw_parts(ptr as *const u8, size);
|
||||
let slice = unsafe { slice::from_raw_parts(ptr as *const u8, size) };
|
||||
|
||||
sr.bytes.borrow_mut().extend_from_slice(slice);
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ fn erase(context: &ImplicitCtxt<'_, '_>) -> *const () {
|
||||
|
||||
#[inline]
|
||||
unsafe fn downcast<'a, 'tcx>(context: *const ()) -> &'a ImplicitCtxt<'a, 'tcx> {
|
||||
&*(context as *const ImplicitCtxt<'a, 'tcx>)
|
||||
unsafe { &*(context as *const ImplicitCtxt<'a, 'tcx>) }
|
||||
}
|
||||
|
||||
/// Sets `context` as the new current `ImplicitCtxt` for the duration of the function `f`.
|
||||
|
@ -257,7 +257,6 @@ TrivialTypeTraversalImpls! {
|
||||
crate::ty::adjustment::PointerCoercion,
|
||||
::rustc_span::Span,
|
||||
::rustc_span::symbol::Ident,
|
||||
::rustc_errors::ErrorGuaranteed,
|
||||
ty::BoundVar,
|
||||
ty::ValTree<'tcx>,
|
||||
}
|
||||
@ -443,13 +442,14 @@ impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for Ty<'tcx> {
|
||||
pat.visit_with(visitor)
|
||||
}
|
||||
|
||||
ty::Error(guar) => guar.visit_with(visitor),
|
||||
|
||||
ty::Bool
|
||||
| ty::Char
|
||||
| ty::Str
|
||||
| ty::Int(_)
|
||||
| ty::Uint(_)
|
||||
| ty::Float(_)
|
||||
| ty::Error(_)
|
||||
| ty::Infer(_)
|
||||
| ty::Bound(..)
|
||||
| ty::Placeholder(..)
|
||||
@ -602,6 +602,21 @@ impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for ty::Const<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for rustc_span::ErrorGuaranteed {
|
||||
fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
|
||||
visitor.visit_error(*self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for rustc_span::ErrorGuaranteed {
|
||||
fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
|
||||
self,
|
||||
_folder: &mut F,
|
||||
) -> Result<Self, F::Error> {
|
||||
Ok(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for InferConst {
|
||||
fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
|
||||
self,
|
||||
@ -617,12 +632,6 @@ impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for InferConst {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for ty::UnevaluatedConst<'tcx> {
|
||||
fn super_visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
|
||||
self.args.visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for TyAndLayout<'tcx, Ty<'tcx>> {
|
||||
fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
|
||||
visitor.visit_ty(self.ty)
|
||||
|
@ -1547,10 +1547,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
start_block: BasicBlock,
|
||||
candidates: &'b mut [&'c mut Candidate<'pat, 'tcx>],
|
||||
) -> BlockAnd<&'b mut [&'c mut Candidate<'pat, 'tcx>]> {
|
||||
// We can't expand or-patterns freely. The rule is: if the candidate has an
|
||||
// or-pattern as its only remaining match pair, we can expand it freely. If it has
|
||||
// other match pairs, we can expand it but we can't process more candidates after
|
||||
// it.
|
||||
// We can't expand or-patterns freely. The rule is:
|
||||
// - If a candidate doesn't start with an or-pattern, we include it in
|
||||
// the expansion list as-is (i.e. it "expands" to itself).
|
||||
// - If a candidate has an or-pattern as its only remaining match pair,
|
||||
// we can expand it.
|
||||
// - If it starts with an or-pattern but also has other match pairs,
|
||||
// we can expand it, but we can't process more candidates after it.
|
||||
//
|
||||
// If we didn't stop, the `otherwise` cases could get mixed up. E.g. in the
|
||||
// following, or-pattern simplification (in `merge_trivial_subcandidates`) makes it
|
||||
@ -1567,17 +1570,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
// }
|
||||
// ```
|
||||
//
|
||||
// We therefore split the `candidates` slice in two, expand or-patterns in the first half,
|
||||
// We therefore split the `candidates` slice in two, expand or-patterns in the first part,
|
||||
// and process the rest separately.
|
||||
let mut expand_until = 0;
|
||||
for (i, candidate) in candidates.iter().enumerate() {
|
||||
expand_until = i + 1;
|
||||
if candidate.match_pairs.len() > 1 && candidate.starts_with_or_pattern() {
|
||||
// The candidate has an or-pattern as well as more match pairs: we must
|
||||
// split the candidates list here.
|
||||
break;
|
||||
}
|
||||
}
|
||||
let expand_until = candidates
|
||||
.iter()
|
||||
.position(|candidate| {
|
||||
// If a candidate starts with an or-pattern and has more match pairs,
|
||||
// we can expand it, but we must stop expanding _after_ it.
|
||||
candidate.match_pairs.len() > 1 && candidate.starts_with_or_pattern()
|
||||
})
|
||||
.map(|pos| pos + 1) // Stop _after_ the found candidate
|
||||
.unwrap_or(candidates.len()); // Otherwise, include all candidates
|
||||
let (candidates_to_expand, remaining_candidates) = candidates.split_at_mut(expand_until);
|
||||
|
||||
// Expand one level of or-patterns for each candidate in `candidates_to_expand`.
|
||||
@ -1592,6 +1595,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
expanded_candidates.push(subcandidate);
|
||||
}
|
||||
} else {
|
||||
// A candidate that doesn't start with an or-pattern has nothing to
|
||||
// expand, so it is included in the post-expansion list as-is.
|
||||
expanded_candidates.push(candidate);
|
||||
}
|
||||
}
|
||||
|
@ -35,25 +35,25 @@ pub fn analyze_source_file(
|
||||
|
||||
cfg_match! {
|
||||
cfg(any(target_arch = "x86", target_arch = "x86_64")) => {
|
||||
fn analyze_source_file_dispatch(src: &str,
|
||||
lines: &mut Vec<RelativeBytePos>,
|
||||
multi_byte_chars: &mut Vec<MultiByteChar>,
|
||||
non_narrow_chars: &mut Vec<NonNarrowChar>) {
|
||||
fn analyze_source_file_dispatch(
|
||||
src: &str,
|
||||
lines: &mut Vec<RelativeBytePos>,
|
||||
multi_byte_chars: &mut Vec<MultiByteChar>,
|
||||
non_narrow_chars: &mut Vec<NonNarrowChar>,
|
||||
) {
|
||||
if is_x86_feature_detected!("sse2") {
|
||||
unsafe {
|
||||
analyze_source_file_sse2(src,
|
||||
lines,
|
||||
multi_byte_chars,
|
||||
non_narrow_chars);
|
||||
analyze_source_file_sse2(src, lines, multi_byte_chars, non_narrow_chars);
|
||||
}
|
||||
} else {
|
||||
analyze_source_file_generic(src,
|
||||
src.len(),
|
||||
RelativeBytePos::from_u32(0),
|
||||
lines,
|
||||
multi_byte_chars,
|
||||
non_narrow_chars);
|
||||
|
||||
analyze_source_file_generic(
|
||||
src,
|
||||
src.len(),
|
||||
RelativeBytePos::from_u32(0),
|
||||
lines,
|
||||
multi_byte_chars,
|
||||
non_narrow_chars,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -62,10 +62,12 @@ cfg_match! {
|
||||
/// function falls back to the generic implementation. Otherwise it uses
|
||||
/// SSE2 intrinsics to quickly find all newlines.
|
||||
#[target_feature(enable = "sse2")]
|
||||
unsafe fn analyze_source_file_sse2(src: &str,
|
||||
lines: &mut Vec<RelativeBytePos>,
|
||||
multi_byte_chars: &mut Vec<MultiByteChar>,
|
||||
non_narrow_chars: &mut Vec<NonNarrowChar>) {
|
||||
unsafe fn analyze_source_file_sse2(
|
||||
src: &str,
|
||||
lines: &mut Vec<RelativeBytePos>,
|
||||
multi_byte_chars: &mut Vec<MultiByteChar>,
|
||||
non_narrow_chars: &mut Vec<NonNarrowChar>,
|
||||
) {
|
||||
#[cfg(target_arch = "x86")]
|
||||
use std::arch::x86::*;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
@ -83,17 +85,17 @@ cfg_match! {
|
||||
// handled it.
|
||||
let mut intra_chunk_offset = 0;
|
||||
|
||||
for chunk_index in 0 .. chunk_count {
|
||||
for chunk_index in 0..chunk_count {
|
||||
let ptr = src_bytes.as_ptr() as *const __m128i;
|
||||
// We don't know if the pointer is aligned to 16 bytes, so we
|
||||
// use `loadu`, which supports unaligned loading.
|
||||
let chunk = _mm_loadu_si128(ptr.add(chunk_index));
|
||||
let chunk = unsafe { _mm_loadu_si128(ptr.add(chunk_index)) };
|
||||
|
||||
// For character in the chunk, see if its byte value is < 0, which
|
||||
// indicates that it's part of a UTF-8 char.
|
||||
let multibyte_test = _mm_cmplt_epi8(chunk, _mm_set1_epi8(0));
|
||||
let multibyte_test = unsafe { _mm_cmplt_epi8(chunk, _mm_set1_epi8(0)) };
|
||||
// Create a bit mask from the comparison results.
|
||||
let multibyte_mask = _mm_movemask_epi8(multibyte_test);
|
||||
let multibyte_mask = unsafe { _mm_movemask_epi8(multibyte_test) };
|
||||
|
||||
// If the bit mask is all zero, we only have ASCII chars here:
|
||||
if multibyte_mask == 0 {
|
||||
@ -102,19 +104,19 @@ cfg_match! {
|
||||
// Check if there are any control characters in the chunk. All
|
||||
// control characters that we can encounter at this point have a
|
||||
// byte value less than 32 or ...
|
||||
let control_char_test0 = _mm_cmplt_epi8(chunk, _mm_set1_epi8(32));
|
||||
let control_char_mask0 = _mm_movemask_epi8(control_char_test0);
|
||||
let control_char_test0 = unsafe { _mm_cmplt_epi8(chunk, _mm_set1_epi8(32)) };
|
||||
let control_char_mask0 = unsafe { _mm_movemask_epi8(control_char_test0) };
|
||||
|
||||
// ... it's the ASCII 'DEL' character with a value of 127.
|
||||
let control_char_test1 = _mm_cmpeq_epi8(chunk, _mm_set1_epi8(127));
|
||||
let control_char_mask1 = _mm_movemask_epi8(control_char_test1);
|
||||
let control_char_test1 = unsafe { _mm_cmpeq_epi8(chunk, _mm_set1_epi8(127)) };
|
||||
let control_char_mask1 = unsafe { _mm_movemask_epi8(control_char_test1) };
|
||||
|
||||
let control_char_mask = control_char_mask0 | control_char_mask1;
|
||||
|
||||
if control_char_mask != 0 {
|
||||
// Check for newlines in the chunk
|
||||
let newlines_test = _mm_cmpeq_epi8(chunk, _mm_set1_epi8(b'\n' as i8));
|
||||
let newlines_mask = _mm_movemask_epi8(newlines_test);
|
||||
let newlines_test = unsafe { _mm_cmpeq_epi8(chunk, _mm_set1_epi8(b'\n' as i8)) };
|
||||
let newlines_mask = unsafe { _mm_movemask_epi8(newlines_test) };
|
||||
|
||||
if control_char_mask == newlines_mask {
|
||||
// All control characters are newlines, record them
|
||||
@ -126,7 +128,7 @@ cfg_match! {
|
||||
|
||||
if index >= CHUNK_SIZE as u32 {
|
||||
// We have arrived at the end of the chunk.
|
||||
break
|
||||
break;
|
||||
}
|
||||
|
||||
lines.push(RelativeBytePos(index) + output_offset);
|
||||
@ -137,14 +139,14 @@ cfg_match! {
|
||||
|
||||
// We are done for this chunk. All control characters were
|
||||
// newlines and we took care of those.
|
||||
continue
|
||||
continue;
|
||||
} else {
|
||||
// Some of the control characters are not newlines,
|
||||
// fall through to the slow path below.
|
||||
}
|
||||
} else {
|
||||
// No control characters, nothing to record for this chunk
|
||||
continue
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
@ -152,43 +154,48 @@ cfg_match! {
|
||||
// There are control chars in here, fallback to generic decoding.
|
||||
let scan_start = chunk_index * CHUNK_SIZE + intra_chunk_offset;
|
||||
intra_chunk_offset = analyze_source_file_generic(
|
||||
&src[scan_start .. ],
|
||||
&src[scan_start..],
|
||||
CHUNK_SIZE - intra_chunk_offset,
|
||||
RelativeBytePos::from_usize(scan_start),
|
||||
lines,
|
||||
multi_byte_chars,
|
||||
non_narrow_chars
|
||||
non_narrow_chars,
|
||||
);
|
||||
}
|
||||
|
||||
// There might still be a tail left to analyze
|
||||
let tail_start = chunk_count * CHUNK_SIZE + intra_chunk_offset;
|
||||
if tail_start < src.len() {
|
||||
analyze_source_file_generic(&src[tail_start ..],
|
||||
src.len() - tail_start,
|
||||
RelativeBytePos::from_usize(tail_start),
|
||||
lines,
|
||||
multi_byte_chars,
|
||||
non_narrow_chars);
|
||||
analyze_source_file_generic(
|
||||
&src[tail_start..],
|
||||
src.len() - tail_start,
|
||||
RelativeBytePos::from_usize(tail_start),
|
||||
lines,
|
||||
multi_byte_chars,
|
||||
non_narrow_chars,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
// The target (or compiler version) does not support SSE2 ...
|
||||
fn analyze_source_file_dispatch(src: &str,
|
||||
lines: &mut Vec<RelativeBytePos>,
|
||||
multi_byte_chars: &mut Vec<MultiByteChar>,
|
||||
non_narrow_chars: &mut Vec<NonNarrowChar>) {
|
||||
analyze_source_file_generic(src,
|
||||
src.len(),
|
||||
RelativeBytePos::from_u32(0),
|
||||
lines,
|
||||
multi_byte_chars,
|
||||
non_narrow_chars);
|
||||
fn analyze_source_file_dispatch(
|
||||
src: &str,
|
||||
lines: &mut Vec<RelativeBytePos>,
|
||||
multi_byte_chars: &mut Vec<MultiByteChar>,
|
||||
non_narrow_chars: &mut Vec<NonNarrowChar>,
|
||||
) {
|
||||
analyze_source_file_generic(
|
||||
src,
|
||||
src.len(),
|
||||
RelativeBytePos::from_u32(0),
|
||||
lines,
|
||||
multi_byte_chars,
|
||||
non_narrow_chars,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// `scan_len` determines the number of bytes in `src` to scan. Note that the
|
||||
// function can read past `scan_len` if a multi-byte character start within the
|
||||
// range but extends past it. The overflow is returned by the function.
|
||||
|
@ -466,7 +466,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||
&& let Some(arg_ty) = typeck_results.expr_ty_adjusted_opt(expr)
|
||||
{
|
||||
// Suggest dereferencing the argument to a function/method call if possible
|
||||
|
||||
let mut real_trait_pred = trait_pred;
|
||||
while let Some((parent_code, parent_trait_pred)) = code.parent() {
|
||||
code = parent_code;
|
||||
@ -553,6 +552,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
||||
);
|
||||
if self.predicate_may_hold(&obligation)
|
||||
&& self.predicate_must_hold_modulo_regions(&sized_obligation)
|
||||
// Do not suggest * if it is already a reference,
|
||||
// will suggest removing the borrow instead in that case.
|
||||
&& !matches!(expr.kind, hir::ExprKind::AddrOf(..))
|
||||
{
|
||||
let call_node = self.tcx.hir_node(*call_hir_id);
|
||||
let msg = "consider dereferencing here";
|
||||
|
@ -101,8 +101,12 @@ pub trait TypeVisitor<I: Interner>: Sized {
|
||||
|
||||
// The default region visitor is a no-op because `Region` is non-recursive
|
||||
// and has no `super_visit_with` method to call.
|
||||
fn visit_region(&mut self, _r: I::Region) -> Self::Result {
|
||||
Self::Result::output()
|
||||
fn visit_region(&mut self, r: I::Region) -> Self::Result {
|
||||
if let ty::ReError(guar) = r.kind() {
|
||||
self.visit_error(guar)
|
||||
} else {
|
||||
Self::Result::output()
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_const(&mut self, c: I::Const) -> Self::Result {
|
||||
@ -116,6 +120,10 @@ pub trait TypeVisitor<I: Interner>: Sized {
|
||||
fn visit_clauses(&mut self, p: I::Clauses) -> Self::Result {
|
||||
p.super_visit_with(self)
|
||||
}
|
||||
|
||||
fn visit_error(&mut self, _guar: I::ErrorGuaranteed) -> Self::Result {
|
||||
Self::Result::output()
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
@ -439,6 +447,15 @@ impl<I: Interner> TypeVisitor<I> for HasTypeFlagsVisitor {
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_error(&mut self, _guar: <I as Interner>::ErrorGuaranteed) -> Self::Result {
|
||||
if self.flags.intersects(TypeFlags::HAS_ERROR) {
|
||||
ControlFlow::Break(FoundFlags)
|
||||
} else {
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
||||
@ -547,27 +564,7 @@ struct HasErrorVisitor;
|
||||
impl<I: Interner> TypeVisitor<I> for HasErrorVisitor {
|
||||
type Result = ControlFlow<I::ErrorGuaranteed>;
|
||||
|
||||
fn visit_ty(&mut self, t: <I as Interner>::Ty) -> Self::Result {
|
||||
if let ty::Error(guar) = t.kind() {
|
||||
ControlFlow::Break(guar)
|
||||
} else {
|
||||
t.super_visit_with(self)
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_const(&mut self, c: <I as Interner>::Const) -> Self::Result {
|
||||
if let ty::ConstKind::Error(guar) = c.kind() {
|
||||
ControlFlow::Break(guar)
|
||||
} else {
|
||||
c.super_visit_with(self)
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_region(&mut self, r: <I as Interner>::Region) -> Self::Result {
|
||||
if let ty::ReError(guar) = r.kind() {
|
||||
ControlFlow::Break(guar)
|
||||
} else {
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
fn visit_error(&mut self, guar: <I as Interner>::ErrorGuaranteed) -> Self::Result {
|
||||
ControlFlow::Break(guar)
|
||||
}
|
||||
}
|
||||
|
@ -11,9 +11,9 @@ unsafe impl GlobalAlloc for System {
|
||||
// Also see <https://github.com/rust-lang/rust/issues/45955> and
|
||||
// <https://github.com/rust-lang/rust/issues/62251#issuecomment-507580914>.
|
||||
if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() {
|
||||
libc::malloc(layout.size()) as *mut u8
|
||||
unsafe { libc::malloc(layout.size()) as *mut u8 }
|
||||
} else {
|
||||
aligned_malloc(&layout)
|
||||
unsafe { aligned_malloc(&layout) }
|
||||
}
|
||||
}
|
||||
|
||||
@ -21,11 +21,11 @@ unsafe impl GlobalAlloc for System {
|
||||
unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
|
||||
// See the comment above in `alloc` for why this check looks the way it does.
|
||||
if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() {
|
||||
libc::calloc(layout.size(), 1) as *mut u8
|
||||
unsafe { libc::calloc(layout.size(), 1) as *mut u8 }
|
||||
} else {
|
||||
let ptr = self.alloc(layout);
|
||||
let ptr = unsafe { self.alloc(layout) };
|
||||
if !ptr.is_null() {
|
||||
ptr::write_bytes(ptr, 0, layout.size());
|
||||
unsafe { ptr::write_bytes(ptr, 0, layout.size()) };
|
||||
}
|
||||
ptr
|
||||
}
|
||||
@ -33,15 +33,15 @@ unsafe impl GlobalAlloc for System {
|
||||
|
||||
#[inline]
|
||||
unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) {
|
||||
libc::free(ptr as *mut libc::c_void)
|
||||
unsafe { libc::free(ptr as *mut libc::c_void) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
|
||||
if layout.align() <= MIN_ALIGN && layout.align() <= new_size {
|
||||
libc::realloc(ptr as *mut libc::c_void, new_size) as *mut u8
|
||||
unsafe { libc::realloc(ptr as *mut libc::c_void, new_size) as *mut u8 }
|
||||
} else {
|
||||
realloc_fallback(self, ptr, layout, new_size)
|
||||
unsafe { realloc_fallback(self, ptr, layout, new_size) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -52,6 +52,6 @@ unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 {
|
||||
// posix_memalign requires that the alignment be a multiple of `sizeof(void*)`.
|
||||
// Since these are all powers of 2, we can just use max.
|
||||
let align = layout.align().max(crate::mem::size_of::<usize>());
|
||||
let ret = libc::posix_memalign(&mut out, align, layout.size());
|
||||
let ret = unsafe { libc::posix_memalign(&mut out, align, layout.size()) };
|
||||
if ret != 0 { ptr::null_mut() } else { out as *mut u8 }
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
//!
|
||||
//! This module contains the facade (aka platform-specific) implementations of
|
||||
//! OS level functionality for Teeos.
|
||||
#![allow(unsafe_op_in_unsafe_fn)]
|
||||
#![deny(unsafe_op_in_unsafe_fn)]
|
||||
#![allow(unused_variables)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
|
@ -28,22 +28,24 @@ impl Thread {
|
||||
// unsafe: see thread::Builder::spawn_unchecked for safety requirements
|
||||
pub unsafe fn new(stack: usize, p: Box<dyn FnOnce()>) -> io::Result<Thread> {
|
||||
let p = Box::into_raw(Box::new(p));
|
||||
let mut native: libc::pthread_t = mem::zeroed();
|
||||
let mut attr: libc::pthread_attr_t = mem::zeroed();
|
||||
assert_eq!(libc::pthread_attr_init(&mut attr), 0);
|
||||
let mut native: libc::pthread_t = unsafe { mem::zeroed() };
|
||||
let mut attr: libc::pthread_attr_t = unsafe { mem::zeroed() };
|
||||
assert_eq!(unsafe { libc::pthread_attr_init(&mut attr) }, 0);
|
||||
assert_eq!(
|
||||
libc::pthread_attr_settee(
|
||||
&mut attr,
|
||||
libc::TEESMP_THREAD_ATTR_CA_INHERIT,
|
||||
libc::TEESMP_THREAD_ATTR_TASK_ID_INHERIT,
|
||||
libc::TEESMP_THREAD_ATTR_HAS_SHADOW,
|
||||
),
|
||||
unsafe {
|
||||
libc::pthread_attr_settee(
|
||||
&mut attr,
|
||||
libc::TEESMP_THREAD_ATTR_CA_INHERIT,
|
||||
libc::TEESMP_THREAD_ATTR_TASK_ID_INHERIT,
|
||||
libc::TEESMP_THREAD_ATTR_HAS_SHADOW,
|
||||
)
|
||||
},
|
||||
0,
|
||||
);
|
||||
|
||||
let stack_size = cmp::max(stack, min_stack_size(&attr));
|
||||
|
||||
match libc::pthread_attr_setstacksize(&mut attr, stack_size) {
|
||||
match unsafe { libc::pthread_attr_setstacksize(&mut attr, stack_size) } {
|
||||
0 => {}
|
||||
n => {
|
||||
assert_eq!(n, libc::EINVAL);
|
||||
@ -54,7 +56,7 @@ impl Thread {
|
||||
let page_size = os::page_size();
|
||||
let stack_size =
|
||||
(stack_size + page_size - 1) & (-(page_size as isize - 1) as usize - 1);
|
||||
assert_eq!(libc::pthread_attr_setstacksize(&mut attr, stack_size), 0);
|
||||
assert_eq!(unsafe { libc::pthread_attr_setstacksize(&mut attr, stack_size) }, 0);
|
||||
}
|
||||
};
|
||||
|
||||
@ -62,12 +64,12 @@ impl Thread {
|
||||
// Note: if the thread creation fails and this assert fails, then p will
|
||||
// be leaked. However, an alternative design could cause double-free
|
||||
// which is clearly worse.
|
||||
assert_eq!(libc::pthread_attr_destroy(&mut attr), 0);
|
||||
assert_eq!(unsafe { libc::pthread_attr_destroy(&mut attr) }, 0);
|
||||
|
||||
return if ret != 0 {
|
||||
// The thread failed to start and as a result p was not consumed. Therefore, it is
|
||||
// safe to reconstruct the box so that it gets deallocated.
|
||||
drop(Box::from_raw(p));
|
||||
drop(unsafe { Box::from_raw(p) });
|
||||
Err(io::Error::from_raw_os_error(ret))
|
||||
} else {
|
||||
// The new thread will start running earliest after the next yield.
|
||||
|
@ -76,16 +76,16 @@ impl Condvar {
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn wait(&self, mutex: &Mutex) {
|
||||
let mutex = mutex::raw(mutex);
|
||||
let mutex = unsafe { mutex::raw(mutex) };
|
||||
self.verify(mutex);
|
||||
let r = libc::pthread_cond_wait(raw(self), mutex);
|
||||
let r = unsafe { libc::pthread_cond_wait(raw(self), mutex) };
|
||||
debug_assert_eq!(r, 0);
|
||||
}
|
||||
|
||||
pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
|
||||
use crate::sys::time::Timespec;
|
||||
|
||||
let mutex = mutex::raw(mutex);
|
||||
let mutex = unsafe { mutex::raw(mutex) };
|
||||
self.verify(mutex);
|
||||
|
||||
let timeout = Timespec::now(libc::CLOCK_MONOTONIC)
|
||||
@ -93,7 +93,7 @@ impl Condvar {
|
||||
.and_then(|t| t.to_timespec())
|
||||
.unwrap_or(TIMESPEC_MAX);
|
||||
|
||||
let r = pthread_cond_timedwait(raw(self), mutex, &timeout);
|
||||
let r = unsafe { pthread_cond_timedwait(raw(self), mutex, &timeout) };
|
||||
assert!(r == libc::ETIMEDOUT || r == 0);
|
||||
r == 0
|
||||
}
|
||||
|
@ -2001,6 +2001,7 @@ impl<'a> Builder<'a> {
|
||||
// FIXME(edition_2024): Change this to `-Wrust_2024_idioms` when all
|
||||
// of the individual lints are satisfied.
|
||||
rustflags.arg("-Wkeyword_idents_2024");
|
||||
rustflags.arg("-Wunsafe_op_in_unsafe_fn");
|
||||
}
|
||||
|
||||
if self.config.rust_frame_pointers {
|
||||
|
@ -9,7 +9,7 @@ object = "0.34.0"
|
||||
similar = "2.5.0"
|
||||
wasmparser = "0.118.2"
|
||||
regex = "1.8" # 1.8 to avoid memchr 2.6.0, as 2.5.0 is pinned in the workspace
|
||||
gimli = "0.28.1"
|
||||
gimli = "0.31.0"
|
||||
ar = "0.9.0"
|
||||
|
||||
build_helper = { path = "../build_helper" }
|
||||
|
@ -0,0 +1,18 @@
|
||||
fn main() {
|
||||
let fields = vec![1];
|
||||
let variant = vec![2];
|
||||
|
||||
// should not suggest `*&variant.iter()`
|
||||
for (src, dest) in std::iter::zip(fields.iter(), &variant.iter()) {
|
||||
//~^ ERROR `&std::slice::Iter<'_, {integer}>` is not an iterator
|
||||
//~| ERROR `&std::slice::Iter<'_, {integer}>` is not an iterator
|
||||
eprintln!("{} {}", src, dest);
|
||||
}
|
||||
|
||||
// don't suggest add `variant.iter().clone().clone()`
|
||||
for (src, dest) in std::iter::zip(fields.iter(), &variant.iter().clone()) {
|
||||
//~^ ERROR `&std::slice::Iter<'_, {integer}>` is not an iterator
|
||||
//~| ERROR `&std::slice::Iter<'_, {integer}>` is not an iterator
|
||||
eprintln!("{} {}", src, dest);
|
||||
}
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
error[E0277]: `&std::slice::Iter<'_, {integer}>` is not an iterator
|
||||
--> $DIR/invalid-suggest-deref-issue-127590.rs:6:54
|
||||
|
|
||||
LL | for (src, dest) in std::iter::zip(fields.iter(), &variant.iter()) {
|
||||
| -------------- ^^^^^^^^^^^^^^^ `&std::slice::Iter<'_, {integer}>` is not an iterator
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= help: the trait `Iterator` is not implemented for `&std::slice::Iter<'_, {integer}>`, which is required by `&std::slice::Iter<'_, {integer}>: IntoIterator`
|
||||
= note: required for `&std::slice::Iter<'_, {integer}>` to implement `IntoIterator`
|
||||
note: required by a bound in `std::iter::zip`
|
||||
--> $SRC_DIR/core/src/iter/adapters/zip.rs:LL:COL
|
||||
help: consider removing the leading `&`-reference
|
||||
|
|
||||
LL - for (src, dest) in std::iter::zip(fields.iter(), &variant.iter()) {
|
||||
LL + for (src, dest) in std::iter::zip(fields.iter(), variant.iter()) {
|
||||
|
|
||||
|
||||
error[E0277]: `&std::slice::Iter<'_, {integer}>` is not an iterator
|
||||
--> $DIR/invalid-suggest-deref-issue-127590.rs:6:24
|
||||
|
|
||||
LL | for (src, dest) in std::iter::zip(fields.iter(), &variant.iter()) {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&std::slice::Iter<'_, {integer}>` is not an iterator
|
||||
|
|
||||
= help: the trait `Iterator` is not implemented for `&std::slice::Iter<'_, {integer}>`, which is required by `Zip<std::slice::Iter<'_, {integer}>, &std::slice::Iter<'_, {integer}>>: IntoIterator`
|
||||
= help: the trait `Iterator` is implemented for `std::slice::Iter<'a, T>`
|
||||
= note: required for `Zip<std::slice::Iter<'_, {integer}>, &std::slice::Iter<'_, {integer}>>` to implement `Iterator`
|
||||
= note: required for `Zip<std::slice::Iter<'_, {integer}>, &std::slice::Iter<'_, {integer}>>` to implement `IntoIterator`
|
||||
|
||||
error[E0277]: `&std::slice::Iter<'_, {integer}>` is not an iterator
|
||||
--> $DIR/invalid-suggest-deref-issue-127590.rs:13:54
|
||||
|
|
||||
LL | for (src, dest) in std::iter::zip(fields.iter(), &variant.iter().clone()) {
|
||||
| -------------- ^^^^^^^^^^^^^^^^^^^^^^^ `&std::slice::Iter<'_, {integer}>` is not an iterator
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= help: the trait `Iterator` is not implemented for `&std::slice::Iter<'_, {integer}>`, which is required by `&std::slice::Iter<'_, {integer}>: IntoIterator`
|
||||
= note: required for `&std::slice::Iter<'_, {integer}>` to implement `IntoIterator`
|
||||
note: required by a bound in `std::iter::zip`
|
||||
--> $SRC_DIR/core/src/iter/adapters/zip.rs:LL:COL
|
||||
help: consider removing the leading `&`-reference
|
||||
|
|
||||
LL - for (src, dest) in std::iter::zip(fields.iter(), &variant.iter().clone()) {
|
||||
LL + for (src, dest) in std::iter::zip(fields.iter(), variant.iter().clone()) {
|
||||
|
|
||||
|
||||
error[E0277]: `&std::slice::Iter<'_, {integer}>` is not an iterator
|
||||
--> $DIR/invalid-suggest-deref-issue-127590.rs:13:24
|
||||
|
|
||||
LL | for (src, dest) in std::iter::zip(fields.iter(), &variant.iter().clone()) {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `&std::slice::Iter<'_, {integer}>` is not an iterator
|
||||
|
|
||||
= help: the trait `Iterator` is not implemented for `&std::slice::Iter<'_, {integer}>`, which is required by `Zip<std::slice::Iter<'_, {integer}>, &std::slice::Iter<'_, {integer}>>: IntoIterator`
|
||||
= help: the trait `Iterator` is implemented for `std::slice::Iter<'a, T>`
|
||||
= note: required for `Zip<std::slice::Iter<'_, {integer}>, &std::slice::Iter<'_, {integer}>>` to implement `Iterator`
|
||||
= note: required for `Zip<std::slice::Iter<'_, {integer}>, &std::slice::Iter<'_, {integer}>>` to implement `IntoIterator`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
Loading…
Reference in New Issue
Block a user