Skip to content

Commit d92e1fe

Browse files
authored
Rollup merge of #145206 - scrabsha:push-uxovoqzrxnlx, r=jdonszelmann
Port `#[custom_mir(..)]` to the new attribute system r? ``````````@jdonszelmann``````````
2 parents b94842d + 51bccdd commit d92e1fe

15 files changed

Lines changed: 318 additions & 91 deletions

File tree

‎compiler/rustc_attr_parsing/src/attributes/mod.rs‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ pub(crate) mod no_implicit_prelude;
4343
pub(crate)mod non_exhaustive;
4444
pub(crate)mod path;
4545
pub(crate)mod proc_macro_attrs;
46+
pub(crate)mod prototype;
4647
pub(crate)mod repr;
4748
pub(crate)mod rustc_internal;
4849
pub(crate)mod semantics;
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
//! Attributes that are only used on function prototypes.
2+
3+
use rustc_feature::{AttributeTemplate, template};
4+
use rustc_hir::Target;
5+
use rustc_hir::attrs::{AttributeKind,MirDialect,MirPhase};
6+
use rustc_span::{Span,Symbol, sym};
7+
8+
usesuper::{AttributeOrder,OnDuplicate};
9+
usecrate::attributes::SingleAttributeParser;
10+
usecrate::context::{AcceptContext,AllowedTargets,MaybeWarn,Stage};
11+
usecrate::parser::ArgParser;
12+
13+
pub(crate)structCustomMirParser;
14+
15+
impl<S:Stage>SingleAttributeParser<S>forCustomMirParser{
16+
constPATH:&[rustc_span::Symbol] = &[sym::custom_mir];
17+
18+
constATTRIBUTE_ORDER:AttributeOrder = AttributeOrder::KeepOutermost;
19+
20+
constON_DUPLICATE:OnDuplicate<S> = OnDuplicate::Error;
21+
22+
constALLOWED_TARGETS:AllowedTargets =
23+
AllowedTargets::AllowList(&[MaybeWarn::Allow(Target::Fn)]);
24+
25+
constTEMPLATE:AttributeTemplate = template!(List:&[r#"dialect = "...", phase = "...""#]);
26+
27+
fnconvert(cx:&mutAcceptContext<'_,'_,S>,args:&ArgParser<'_>) -> Option<AttributeKind>{
28+
letSome(list) = args.list()else{
29+
cx.expected_list(cx.attr_span);
30+
returnNone;
31+
};
32+
33+
letmut dialect = None;
34+
letmut phase = None;
35+
letmut failed = false;
36+
37+
for item in list.mixed(){
38+
letSome(meta_item) = item.meta_item()else{
39+
cx.expected_name_value(item.span(),None);
40+
failed = true;
41+
break;
42+
};
43+
44+
ifletSome(arg) = meta_item.word_is(sym::dialect){
45+
extract_value(cx, sym::dialect, arg, meta_item.span(),&mut dialect,&mut failed);
46+
}elseifletSome(arg) = meta_item.word_is(sym::phase){
47+
extract_value(cx, sym::phase, arg, meta_item.span(),&mut phase,&mut failed);
48+
}elseifletSome(word) = meta_item.path().word(){
49+
let word = word.to_string();
50+
cx.unknown_key(meta_item.span(), word,&["dialect","phase"]);
51+
failed = true;
52+
}else{
53+
cx.expected_name_value(meta_item.span(),None);
54+
failed = true;
55+
};
56+
}
57+
58+
let dialect = parse_dialect(cx, dialect,&mut failed);
59+
let phase = parse_phase(cx, phase,&mut failed);
60+
61+
if failed {
62+
returnNone;
63+
}
64+
65+
Some(AttributeKind::CustomMir(dialect, phase, cx.attr_span))
66+
}
67+
}
68+
69+
fnextract_value<S:Stage>(
70+
cx:&mutAcceptContext<'_,'_,S>,
71+
key:Symbol,
72+
arg:&ArgParser<'_>,
73+
span:Span,
74+
out_val:&mutOption<(Symbol,Span)>,
75+
failed:&mutbool,
76+
){
77+
if out_val.is_some(){
78+
cx.duplicate_key(span, key);
79+
*failed = true;
80+
return;
81+
}
82+
83+
letSome(val) = arg.name_value()else{
84+
cx.expected_single_argument(arg.span().unwrap_or(span));
85+
*failed = true;
86+
return;
87+
};
88+
89+
letSome(value_sym) = val.value_as_str()else{
90+
cx.expected_string_literal(val.value_span,Some(val.value_as_lit()));
91+
*failed = true;
92+
return;
93+
};
94+
95+
*out_val = Some((value_sym, val.value_span));
96+
}
97+
98+
fnparse_dialect<S:Stage>(
99+
cx:&mutAcceptContext<'_,'_,S>,
100+
dialect:Option<(Symbol,Span)>,
101+
failed:&mutbool,
102+
) -> Option<(MirDialect,Span)>{
103+
let(dialect, span) = dialect?;
104+
105+
let dialect = match dialect {
106+
sym::analysis => MirDialect::Analysis,
107+
sym::built => MirDialect::Built,
108+
sym::runtime => MirDialect::Runtime,
109+
110+
_ => {
111+
cx.expected_specific_argument(span,vec!["analysis","built","runtime"]);
112+
*failed = true;
113+
returnNone;
114+
}
115+
};
116+
117+
Some((dialect, span))
118+
}
119+
120+
fnparse_phase<S:Stage>(
121+
cx:&mutAcceptContext<'_,'_,S>,
122+
phase:Option<(Symbol,Span)>,
123+
failed:&mutbool,
124+
) -> Option<(MirPhase,Span)>{
125+
let(phase, span) = phase?;
126+
127+
let phase = match phase {
128+
sym::initial => MirPhase::Initial,
129+
sym::post_cleanup => MirPhase::PostCleanup,
130+
sym::optimized => MirPhase::Optimized,
131+
132+
_ => {
133+
cx.expected_specific_argument(span,vec!["initial","post-cleanup","optimized"]);
134+
*failed = true;
135+
returnNone;
136+
}
137+
};
138+
139+
Some((phase, span))
140+
}

‎compiler/rustc_attr_parsing/src/context.rs‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ use crate::attributes::path::PathParser as PathAttributeParser;
4646
usecrate::attributes::proc_macro_attrs::{
4747
ProcMacroAttributeParser,ProcMacroDeriveParser,ProcMacroParser,RustcBuiltinMacroParser,
4848
};
49+
usecrate::attributes::prototype::CustomMirParser;
4950
usecrate::attributes::repr::{AlignParser,ReprParser};
5051
usecrate::attributes::rustc_internal::{
5152
RustcLayoutScalarValidRangeEnd,RustcLayoutScalarValidRangeStart,
@@ -167,6 +168,7 @@ attribute_parsers!(
167168

168169
// tidy-alphabetical-start
169170
Single<CoverageParser>,
171+
Single<CustomMirParser>,
170172
Single<DeprecationParser>,
171173
Single<DummyParser>,
172174
Single<ExportNameParser>,

‎compiler/rustc_errors/src/diagnostic_impls.rs‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use rustc_abi::TargetDataLayoutErrors;
99
use rustc_ast::util::parser::ExprPrecedence;
1010
use rustc_ast_pretty::pprust;
1111
use rustc_hir::RustcVersion;
12+
use rustc_hir::attrs::{MirDialect,MirPhase};
1213
use rustc_macros::Subdiagnostic;
1314
use rustc_span::edition::Edition;
1415
use rustc_span::{Ident,MacroRulesNormalizedIdent,Span,Symbol};
@@ -312,6 +313,28 @@ impl IntoDiagArg for ExprPrecedence {
312313
}
313314
}
314315

316+
implIntoDiagArgforMirDialect{
317+
fninto_diag_arg(self,_path:&mutOption<PathBuf>) -> DiagArgValue{
318+
let arg = matchself{
319+
MirDialect::Analysis => "analysis",
320+
MirDialect::Built => "built",
321+
MirDialect::Runtime => "runtime",
322+
};
323+
DiagArgValue::Str(Cow::Borrowed(arg))
324+
}
325+
}
326+
327+
implIntoDiagArgforMirPhase{
328+
fninto_diag_arg(self,_path:&mutOption<PathBuf>) -> DiagArgValue{
329+
let arg = matchself{
330+
MirPhase::Initial => "initial",
331+
MirPhase::PostCleanup => "post-cleanup",
332+
MirPhase::Optimized => "optimized",
333+
};
334+
DiagArgValue::Str(Cow::Borrowed(arg))
335+
}
336+
}
337+
315338
#[derive(Clone)]
316339
pubstructDiagSymbolList<S = Symbol>(Vec<S>);
317340

‎compiler/rustc_hir/src/attrs/data_structures.rs‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,22 @@ pub enum Linkage {
205205
WeakODR,
206206
}
207207

208+
#[derive(Clone,Copy,Decodable,Debug,Encodable,PartialEq)]
209+
#[derive(HashStable_Generic,PrintAttribute)]
210+
pubenumMirDialect{
211+
Analysis,
212+
Built,
213+
Runtime,
214+
}
215+
216+
#[derive(Clone,Copy,Decodable,Debug,Encodable,PartialEq)]
217+
#[derive(HashStable_Generic,PrintAttribute)]
218+
pubenumMirPhase{
219+
Initial,
220+
PostCleanup,
221+
Optimized,
222+
}
223+
208224
/// Represents parsed *built-in* inert attributes.
209225
///
210226
/// ## Overview
@@ -324,6 +340,9 @@ pub enum AttributeKind {
324340
/// Represents `#[coverage(..)]`.
325341
Coverage(Span,CoverageAttrKind),
326342

343+
/// Represents `#[custom_mir]`.
344+
CustomMir(Option<(MirDialect,Span)>,Option<(MirPhase,Span)>,Span),
345+
327346
///Represents `#[rustc_deny_explicit_impl]`.
328347
DenyExplicitImpl(Span),
329348

‎compiler/rustc_hir/src/attrs/encode_cross_crate.rs‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ impl AttributeKind {
3131
ConstTrait(..) => No,
3232
Coroutine(..) => No,
3333
Coverage(..) => No,
34+
CustomMir(_, _, _) => Yes,
3435
DenyExplicitImpl(..) => No,
3536
Deprecation{ .. } => Yes,
3637
DoNotImplementViaObject(..) => No,

‎compiler/rustc_middle/src/mir/mod.rs‎

Lines changed: 0 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -115,48 +115,6 @@ impl MirPhase {
115115
MirPhase::Runtime(runtime_phase) => (3,1 + runtime_phase asusize),
116116
}
117117
}
118-
119-
/// Parses a `MirPhase` from a pair of strings. Panics if this isn't possible for any reason.
120-
pubfnparse(dialect:String,phase:Option<String>) -> Self{
121-
match&*dialect.to_ascii_lowercase(){
122-
"built" => {
123-
assert!(phase.is_none(),"Cannot specify a phase for `Built` MIR");
124-
MirPhase::Built
125-
}
126-
"analysis" => Self::Analysis(AnalysisPhase::parse(phase)),
127-
"runtime" => Self::Runtime(RuntimePhase::parse(phase)),
128-
_ => bug!("Unknown MIR dialect: '{}'", dialect),
129-
}
130-
}
131-
}
132-
133-
implAnalysisPhase{
134-
pubfnparse(phase:Option<String>) -> Self{
135-
letSome(phase) = phase else{
136-
returnSelf::Initial;
137-
};
138-
139-
match&*phase.to_ascii_lowercase(){
140-
"initial" => Self::Initial,
141-
"post_cleanup" | "post-cleanup" | "postcleanup" => Self::PostCleanup,
142-
_ => bug!("Unknown analysis phase: '{}'", phase),
143-
}
144-
}
145-
}
146-
147-
implRuntimePhase{
148-
pubfnparse(phase:Option<String>) -> Self{
149-
letSome(phase) = phase else{
150-
returnSelf::Initial;
151-
};
152-
153-
match&*phase.to_ascii_lowercase(){
154-
"initial" => Self::Initial,
155-
"post_cleanup" | "post-cleanup" | "postcleanup" => Self::PostCleanup,
156-
"optimized" => Self::Optimized,
157-
_ => bug!("Unknown runtime phase: '{}'", phase),
158-
}
159-
}
160118
}
161119

162120
/// Where a specific `mir::Body` comes from.

‎compiler/rustc_mir_build/src/builder/custom/mod.rs‎

Lines changed: 32 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@
1919
2020
use rustc_data_structures::fx::FxHashMap;
2121
use rustc_hir::def_id::DefId;
22-
use rustc_hir::{Attribute,HirId};
22+
use rustc_hir::{HirId, attrs};
2323
use rustc_index::{IndexSlice,IndexVec};
24+
use rustc_middle::bug;
2425
use rustc_middle::mir::*;
25-
use rustc_middle::span_bug;
2626
use rustc_middle::thir::*;
2727
use rustc_middle::ty::{self,Ty,TyCtxt};
2828
use rustc_span::Span;
@@ -39,7 +39,8 @@ pub(super) fn build_custom_mir<'tcx>(
3939
return_ty:Ty<'tcx>,
4040
return_ty_span:Span,
4141
span:Span,
42-
attr:&Attribute,
42+
dialect:Option<attrs::MirDialect>,
43+
phase:Option<attrs::MirPhase>,
4344
) -> Body<'tcx>{
4445
letmut body = Body{
4546
basic_blocks:BasicBlocks::new(IndexVec::new()),
@@ -72,7 +73,7 @@ pub(super) fn build_custom_mir<'tcx>(
7273
inlined_parent_scope:None,
7374
local_data:ClearCrossCrate::Set(SourceScopeLocalData{lint_root: hir_id }),
7475
});
75-
body.injection_phase = Some(parse_attribute(attr));
76+
body.injection_phase = Some(parse_attribute(dialect, phase));
7677

7778
letmut pctxt = ParseCtxt{
7879
tcx,
@@ -98,40 +99,38 @@ pub(super) fn build_custom_mir<'tcx>(
9899
body
99100
}
100101

101-
fnparse_attribute(attr:&Attribute) -> MirPhase{
102-
let meta_items = attr.meta_item_list().unwrap();
103-
letmut dialect:Option<String> = None;
104-
letmut phase:Option<String> = None;
105-
106-
// Not handling errors properly for this internal attribute; will just abort on errors.
107-
for nested in meta_items {
108-
let name = nested.name().unwrap();
109-
let value = nested.value_str().unwrap().as_str().to_string();
110-
match name.as_str(){
111-
"dialect" => {
112-
assert!(dialect.is_none());
113-
dialect = Some(value);
114-
}
115-
"phase" => {
116-
assert!(phase.is_none());
117-
phase = Some(value);
118-
}
119-
other => {
120-
span_bug!(
121-
nested.span(),
122-
"Unexpected key while parsing custom_mir attribute: '{}'",
123-
other
124-
);
125-
}
126-
}
127-
}
128-
102+
/// Turns the arguments passed to `#[custom_mir(..)]` into a proper
103+
/// [`MirPhase`]. Panics if this isn't possible for any reason.
104+
fnparse_attribute(dialect:Option<attrs::MirDialect>,phase:Option<attrs::MirPhase>) -> MirPhase{
129105
letSome(dialect) = dialect else{
106+
// Caught during attribute checking.
130107
assert!(phase.is_none());
131108
returnMirPhase::Built;
132109
};
133110

134-
MirPhase::parse(dialect, phase)
111+
match dialect {
112+
attrs::MirDialect::Built => {
113+
// Caught during attribute checking.
114+
assert!(phase.is_none(),"Cannot specify a phase for `Built` MIR");
115+
MirPhase::Built
116+
}
117+
attrs::MirDialect::Analysis => match phase {
118+
None | Some(attrs::MirPhase::Initial) => MirPhase::Analysis(AnalysisPhase::Initial),
119+
120+
Some(attrs::MirPhase::PostCleanup) => MirPhase::Analysis(AnalysisPhase::PostCleanup),
121+
122+
Some(attrs::MirPhase::Optimized) => {
123+
// Caught during attribute checking.
124+
bug!("`optimized` dialect is not compatible with the `analysis` dialect")
125+
}
126+
},
127+
128+
attrs::MirDialect::Runtime => match phase {
129+
None | Some(attrs::MirPhase::Initial) => MirPhase::Runtime(RuntimePhase::Initial),
130+
Some(attrs::MirPhase::PostCleanup) => MirPhase::Runtime(RuntimePhase::PostCleanup),
131+
Some(attrs::MirPhase::Optimized) => MirPhase::Runtime(RuntimePhase::Optimized),
132+
},
133+
}
135134
}
136135

137136
structParseCtxt<'a,'tcx>{

0 commit comments

Comments
 (0)