diff options
| author | bors <bors@rust-lang.org> | 2020-11-12 23:23:56 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2020-11-12 23:23:56 +0000 |
| commit | e80ee05bfc135d7d800f3fcc89bc005d6858cd9b (patch) | |
| tree | 4b8950bc77d07a409c0c444ac07d6816785eede1 /compiler | |
| parent | 9722952f0bed5815cb22cb4878be09fb39f92804 (diff) | |
| parent | 38ca6e3561dbd2465cd604feeed93cf82580745c (diff) | |
| download | rust-e80ee05bfc135d7d800f3fcc89bc005d6858cd9b.tar.gz rust-e80ee05bfc135d7d800f3fcc89bc005d6858cd9b.zip | |
Auto merge of #78998 - m-ou-se:rollup-6r4pt9m, r=m-ou-se
Rollup of 7 pull requests Successful merges: - #76730 (Fix rustdoc rendering of by-value mutable arguments in async fn) - #78836 (Implement destructuring assignment for structs and slices) - #78857 (Improve BinaryHeap performance) - #78950 (Add asm register information for SPIR-V) - #78970 (update rustfmt to v1.4.25) - #78972 (Update cargo) - #78987 (extend min_const_generics param ty tests) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_ast/src/ast.rs | 19 | ||||
| -rw-r--r-- | compiler/rustc_ast/src/mut_visit.rs | 6 | ||||
| -rw-r--r-- | compiler/rustc_ast/src/visit.rs | 6 | ||||
| -rw-r--r-- | compiler/rustc_ast_lowering/src/expr.rs | 126 | ||||
| -rw-r--r-- | compiler/rustc_ast_lowering/src/item.rs | 14 | ||||
| -rw-r--r-- | compiler/rustc_ast_passes/src/feature_gate.rs | 1 | ||||
| -rw-r--r-- | compiler/rustc_ast_pretty/src/pprust/state.rs | 21 | ||||
| -rw-r--r-- | compiler/rustc_codegen_llvm/src/asm.rs | 12 | ||||
| -rw-r--r-- | compiler/rustc_expand/src/build.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_hir/src/def.rs | 5 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/expr.rs | 10 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/late.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_save_analysis/src/dump_visitor.rs | 10 | ||||
| -rw-r--r-- | compiler/rustc_target/src/asm/mod.rs | 21 | ||||
| -rw-r--r-- | compiler/rustc_target/src/asm/spirv.rs | 46 |
15 files changed, 265 insertions, 38 deletions
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 6961905038f..3e953729aab 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1061,7 +1061,7 @@ pub struct Expr { // `Expr` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(target_arch = "x86_64")] -rustc_data_structures::static_assert_size!(Expr, 112); +rustc_data_structures::static_assert_size!(Expr, 120); impl Expr { /// Returns `true` if this expression would be valid somewhere that expects a value; @@ -1219,6 +1219,16 @@ pub enum RangeLimits { } #[derive(Clone, Encodable, Decodable, Debug)] +pub enum StructRest { + /// `..x`. + Base(P<Expr>), + /// `..`. + Rest(Span), + /// No trailing `..` or expression. + None, +} + +#[derive(Clone, Encodable, Decodable, Debug)] pub enum ExprKind { /// A `box x` expression. Box(P<Expr>), @@ -1312,7 +1322,7 @@ pub enum ExprKind { Field(P<Expr>, Ident), /// An indexing operation (e.g., `foo[2]`). Index(P<Expr>, P<Expr>), - /// A range (e.g., `1..2`, `1..`, `..2`, `1..=2`, `..=2`). + /// A range (e.g., `1..2`, `1..`, `..2`, `1..=2`, `..=2`; and `..` in destructuring assingment). Range(Option<P<Expr>>, Option<P<Expr>>, RangeLimits), /// Variable reference, possibly containing `::` and/or type @@ -1340,9 +1350,8 @@ pub enum ExprKind { /// A struct literal expression. /// - /// E.g., `Foo {x: 1, y: 2}`, or `Foo {x: 1, .. base}`, - /// where `base` is the `Option<Expr>`. - Struct(Path, Vec<Field>, Option<P<Expr>>), + /// E.g., `Foo {x: 1, y: 2}`, or `Foo {x: 1, .. rest}`. + Struct(Path, Vec<Field>, StructRest), /// An array literal constructed from one repeated element. /// diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 2697b017572..26097980e8b 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -1288,7 +1288,11 @@ pub fn noop_visit_expr<T: MutVisitor>( ExprKind::Struct(path, fields, expr) => { vis.visit_path(path); fields.flat_map_in_place(|field| vis.flat_map_field(field)); - visit_opt(expr, |expr| vis.visit_expr(expr)); + match expr { + StructRest::Base(expr) => vis.visit_expr(expr), + StructRest::Rest(_span) => {} + StructRest::None => {} + } } ExprKind::Paren(expr) => { vis.visit_expr(expr); diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 72e901fb90f..49b521afcdc 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -719,7 +719,11 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) { ExprKind::Struct(ref path, ref fields, ref optional_base) => { visitor.visit_path(path, expression.id); walk_list!(visitor, visit_field, fields); - walk_list!(visitor, visit_expr, optional_base); + match optional_base { + StructRest::Base(expr) => visitor.visit_expr(expr), + StructRest::Rest(_span) => {} + StructRest::None => {} + } } ExprKind::Tup(ref subexpressions) => { walk_list!(visitor, visit_expr, subexpressions); diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 1f2aba2b27e..330776fc8c5 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -187,8 +187,18 @@ impl<'hir> LoweringContext<'_, 'hir> { } ExprKind::InlineAsm(ref asm) => self.lower_expr_asm(e.span, asm), ExprKind::LlvmInlineAsm(ref asm) => self.lower_expr_llvm_asm(asm), - ExprKind::Struct(ref path, ref fields, ref maybe_expr) => { - let maybe_expr = maybe_expr.as_ref().map(|x| self.lower_expr(x)); + ExprKind::Struct(ref path, ref fields, ref rest) => { + let rest = match rest { + StructRest::Base(e) => Some(self.lower_expr(e)), + StructRest::Rest(sp) => { + self.sess + .struct_span_err(*sp, "base expression required after `..`") + .span_label(*sp, "add a base expression here") + .emit(); + Some(&*self.arena.alloc(self.expr_err(*sp))) + } + StructRest::None => None, + }; hir::ExprKind::Struct( self.arena.alloc(self.lower_qpath( e.id, @@ -198,7 +208,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ImplTraitContext::disallowed(), )), self.arena.alloc_from_iter(fields.iter().map(|x| self.lower_field(x))), - maybe_expr, + rest, ) } ExprKind::Yield(ref opt_expr) => self.lower_expr_yield(e.span, opt_expr.as_deref()), @@ -851,20 +861,22 @@ impl<'hir> LoweringContext<'_, 'hir> { whole_span: Span, ) -> hir::ExprKind<'hir> { // Return early in case of an ordinary assignment. - fn is_ordinary(lhs: &Expr) -> bool { + fn is_ordinary(lower_ctx: &mut LoweringContext<'_, '_>, lhs: &Expr) -> bool { match &lhs.kind { - ExprKind::Tup(..) => false, + ExprKind::Array(..) | ExprKind::Struct(..) | ExprKind::Tup(..) => false, + // Check for tuple struct constructor. + ExprKind::Call(callee, ..) => lower_ctx.extract_tuple_struct_path(callee).is_none(), ExprKind::Paren(e) => { match e.kind { // We special-case `(..)` for consistency with patterns. ExprKind::Range(None, None, RangeLimits::HalfOpen) => false, - _ => is_ordinary(e), + _ => is_ordinary(lower_ctx, e), } } _ => true, } } - if is_ordinary(lhs) { + if is_ordinary(self, lhs) { return hir::ExprKind::Assign(self.lower_expr(lhs), self.lower_expr(rhs), eq_sign_span); } if !self.sess.features_untracked().destructuring_assignment { @@ -902,6 +914,26 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::ExprKind::Block(&self.block_all(whole_span, stmts, None), None) } + /// If the given expression is a path to a tuple struct, returns that path. + /// It is not a complete check, but just tries to reject most paths early + /// if they are not tuple structs. + /// Type checking will take care of the full validation later. + fn extract_tuple_struct_path<'a>(&mut self, expr: &'a Expr) -> Option<&'a Path> { + // For tuple struct destructuring, it must be a non-qualified path (like in patterns). + if let ExprKind::Path(None, path) = &expr.kind { + // Does the path resolves to something disallowed in a tuple struct/variant pattern? + if let Some(partial_res) = self.resolver.get_partial_res(expr.id) { + if partial_res.unresolved_segments() == 0 + && !partial_res.base_res().expected_in_tuple_struct_pat() + { + return None; + } + } + return Some(path); + } + None + } + /// Convert the LHS of a destructuring assignment to a pattern. /// Each sub-assignment is recorded in `assignments`. fn destructure_assign( @@ -911,6 +943,86 @@ impl<'hir> LoweringContext<'_, 'hir> { assignments: &mut Vec<hir::Stmt<'hir>>, ) -> &'hir hir::Pat<'hir> { match &lhs.kind { + // Slice patterns. + ExprKind::Array(elements) => { + let (pats, rest) = + self.destructure_sequence(elements, "slice", eq_sign_span, assignments); + let slice_pat = if let Some((i, span)) = rest { + let (before, after) = pats.split_at(i); + hir::PatKind::Slice( + before, + Some(self.pat_without_dbm(span, hir::PatKind::Wild)), + after, + ) + } else { + hir::PatKind::Slice(pats, None, &[]) + }; + return self.pat_without_dbm(lhs.span, slice_pat); + } + // Tuple structs. + ExprKind::Call(callee, args) => { + if let Some(path) = self.extract_tuple_struct_path(callee) { + let (pats, rest) = self.destructure_sequence( + args, + "tuple struct or variant", + eq_sign_span, + assignments, + ); + let qpath = self.lower_qpath( + callee.id, + &None, + path, + ParamMode::Optional, + ImplTraitContext::disallowed(), + ); + // Destructure like a tuple struct. + let tuple_struct_pat = + hir::PatKind::TupleStruct(qpath, pats, rest.map(|r| r.0)); + return self.pat_without_dbm(lhs.span, tuple_struct_pat); + } + } + // Structs. + ExprKind::Struct(path, fields, rest) => { + let field_pats = self.arena.alloc_from_iter(fields.iter().map(|f| { + let pat = self.destructure_assign(&f.expr, eq_sign_span, assignments); + hir::FieldPat { + hir_id: self.next_id(), + ident: f.ident, + pat, + is_shorthand: f.is_shorthand, + span: f.span, + } + })); + let qpath = self.lower_qpath( + lhs.id, + &None, + path, + ParamMode::Optional, + ImplTraitContext::disallowed(), + ); + let fields_omitted = match rest { + StructRest::Base(e) => { + self.sess + .struct_span_err( + e.span, + "functional record updates are not allowed in destructuring \ + assignments", + ) + .span_suggestion( + e.span, + "consider removing the trailing pattern", + String::new(), + rustc_errors::Applicability::MachineApplicable, + ) + .emit(); + true + } + StructRest::Rest(_) => true, + StructRest::None => false, + }; + let struct_pat = hir::PatKind::Struct(qpath, field_pats, fields_omitted); + return self.pat_without_dbm(lhs.span, struct_pat); + } // Tuples. ExprKind::Tup(elements) => { let (pats, rest) = diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 617cacee0e7..d353bc19f7a 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1096,8 +1096,18 @@ impl<'hir> LoweringContext<'_, 'hir> { // Check if this is a binding pattern, if so, we can optimize and avoid adding a // `let <pat> = __argN;` statement. In this case, we do not rename the parameter. let (ident, is_simple_parameter) = match parameter.pat.kind { - hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, _, ident, _) => { - (ident, true) + hir::PatKind::Binding( + hir::BindingAnnotation::Unannotated | hir::BindingAnnotation::Mutable, + _, + ident, + _, + ) => (ident, true), + // For `ref mut` or wildcard arguments, we can't reuse the binding, but + // we can keep the same name for the parameter. + // This lets rustdoc render it correctly in documentation. + hir::PatKind::Binding(_, _, ident, _) => (ident, false), + hir::PatKind::Wild => { + (Ident::with_dummy_span(rustc_span::symbol::kw::Underscore), false) } _ => { // Replace the ident for bindings that aren't simple. diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index f2008449767..2831675cb36 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -630,6 +630,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) { gate_all!(const_trait_impl, "const trait impls are experimental"); gate_all!(half_open_range_patterns, "half-open range patterns are unstable"); gate_all!(inline_const, "inline-const is experimental"); + gate_all!(destructuring_assignment, "destructuring assignments are unstable"); // All uses of `gate_all!` below this point were added in #65742, // and subsequently disabled (with the non-early gating readded). diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index a64014f5acb..a566200c338 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1729,7 +1729,7 @@ impl<'a> State<'a> { &mut self, path: &ast::Path, fields: &[ast::Field], - wth: &Option<P<ast::Expr>>, + rest: &ast::StructRest, attrs: &[ast::Attribute], ) { self.print_path(path, true, 0); @@ -1750,22 +1750,21 @@ impl<'a> State<'a> { }, |f| f.span, ); - match *wth { - Some(ref expr) => { + match rest { + ast::StructRest::Base(_) | ast::StructRest::Rest(_) => { self.ibox(INDENT_UNIT); if !fields.is_empty() { self.s.word(","); self.s.space(); } self.s.word(".."); - self.print_expr(expr); - self.end(); - } - _ => { - if !fields.is_empty() { - self.s.word(",") + if let ast::StructRest::Base(ref expr) = *rest { + self.print_expr(expr); } + self.end(); } + ast::StructRest::None if !fields.is_empty() => self.s.word(","), + _ => {} } self.s.word("}"); } @@ -1891,8 +1890,8 @@ impl<'a> State<'a> { ast::ExprKind::Repeat(ref element, ref count) => { self.print_expr_repeat(element, count, attrs); } - ast::ExprKind::Struct(ref path, ref fields, ref wth) => { - self.print_expr_struct(path, &fields[..], wth, attrs); + ast::ExprKind::Struct(ref path, ref fields, ref rest) => { + self.print_expr_struct(path, &fields[..], rest, attrs); } ast::ExprKind::Tup(ref exprs) => { self.print_expr_tup(&exprs[..], attrs); diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index d856280158f..b5d279eeb6f 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -12,8 +12,8 @@ use rustc_codegen_ssa::mir::place::PlaceRef; use rustc_codegen_ssa::traits::*; use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; -use rustc_middle::span_bug; use rustc_middle::ty::layout::TyAndLayout; +use rustc_middle::{bug, span_bug}; use rustc_span::{Pos, Span}; use rustc_target::abi::*; use rustc_target::asm::*; @@ -260,6 +260,7 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { InlineAsmArch::Nvptx64 => {} InlineAsmArch::Hexagon => {} InlineAsmArch::Mips | InlineAsmArch::Mips64 => {} + InlineAsmArch::SpirV => {} } } if !options.contains(InlineAsmOptions::NOMEM) { @@ -518,6 +519,9 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'tcx>>) | InlineAsmRegClass::X86(X86InlineAsmRegClass::ymm_reg) => "x", InlineAsmRegClass::X86(X86InlineAsmRegClass::zmm_reg) => "v", InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => "^Yk", + InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => { + bug!("LLVM backend does not support SPIR-V") + } } .to_string(), } @@ -580,6 +584,9 @@ fn modifier_to_llvm( _ => unreachable!(), }, InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => None, + InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => { + bug!("LLVM backend does not support SPIR-V") + } } } @@ -619,6 +626,9 @@ fn dummy_output_type(cx: &CodegenCx<'ll, 'tcx>, reg: InlineAsmRegClass) -> &'ll | InlineAsmRegClass::X86(X86InlineAsmRegClass::ymm_reg) | InlineAsmRegClass::X86(X86InlineAsmRegClass::zmm_reg) => cx.type_f32(), InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => cx.type_i16(), + InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => { + bug!("LLVM backend does not support SPIR-V") + } } } diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index 1c9bfb902d6..30f0fc6cddf 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -298,7 +298,7 @@ impl<'a> ExtCtxt<'a> { path: ast::Path, fields: Vec<ast::Field>, ) -> P<ast::Expr> { - self.expr(span, ast::ExprKind::Struct(path, fields, None)) + self.expr(span, ast::ExprKind::Struct(path, fields, ast::StructRest::None)) } pub fn expr_struct_ident( &self, diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index 193247af584..298cfcc254c 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -484,4 +484,9 @@ impl<Id> Res<Id> { pub fn matches_ns(&self, ns: Namespace) -> bool { self.ns().map_or(true, |actual_ns| actual_ns == ns) } + + /// Returns whether such a resolved path can occur in a tuple struct/variant pattern + pub fn expected_in_tuple_struct_pat(&self) -> bool { + matches!(self, Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) | Res::SelfCtor(..)) + } } diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index c2a13d4b0de..188bf227c42 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2087,7 +2087,7 @@ impl<'a> Parser<'a> { recover: bool, ) -> PResult<'a, P<Expr>> { let mut fields = Vec::new(); - let mut base = None; + let mut base = ast::StructRest::None; let mut recover_async = false; attrs.extend(self.parse_inner_attributes()?); @@ -2102,8 +2102,14 @@ impl<'a> Parser<'a> { while self.token != token::CloseDelim(token::Brace) { if self.eat(&token::DotDot) { let exp_span = self.prev_token.span; + // We permit `.. }` on the left-hand side of a destructuring assignment. + if self.check(&token::CloseDelim(token::Brace)) { + self.sess.gated_spans.gate(sym::destructuring_assignment, self.prev_token.span); + base = ast::StructRest::Rest(self.prev_token.span.shrink_to_hi()); + break; + } match self.parse_expr() { - Ok(e) => base = Some(e), + Ok(e) => base = ast::StructRest::Base(e), Err(mut e) if recover => { e.emit(); self.recover_stmt(); diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 2337f0d09ab..2149fd7e011 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -298,9 +298,7 @@ impl<'a> PathSource<'a> { _, ) | Res::SelfCtor(..)), - PathSource::TupleStruct(..) => { - matches!(res, Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) | Res::SelfCtor(..)) - } + PathSource::TupleStruct(..) => res.expected_in_tuple_struct_pat(), PathSource::Struct => matches!(res, Res::Def( DefKind::Struct | DefKind::Union diff --git a/compiler/rustc_save_analysis/src/dump_visitor.rs b/compiler/rustc_save_analysis/src/dump_visitor.rs index dbb5e3cc9f0..40d60a8394b 100644 --- a/compiler/rustc_save_analysis/src/dump_visitor.rs +++ b/compiler/rustc_save_analysis/src/dump_visitor.rs @@ -816,7 +816,7 @@ impl<'tcx> DumpVisitor<'tcx> { path: &'tcx hir::QPath<'tcx>, fields: &'tcx [hir::Field<'tcx>], variant: &'tcx ty::VariantDef, - base: Option<&'tcx hir::Expr<'tcx>>, + rest: Option<&'tcx hir::Expr<'tcx>>, ) { if let Some(struct_lit_data) = self.save_ctxt.get_expr_data(ex) { if let hir::QPath::Resolved(_, path) = path { @@ -836,7 +836,9 @@ impl<'tcx> DumpVisitor<'tcx> { } } - walk_list!(self, visit_expr, base); + if let Some(base) = rest { + self.visit_expr(&base); + } } fn process_method_call( @@ -1399,7 +1401,7 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> { debug!("visit_expr {:?}", ex.kind); self.process_macro_use(ex.span); match ex.kind { - hir::ExprKind::Struct(ref path, ref fields, ref base) => { + hir::ExprKind::Struct(ref path, ref fields, ref rest) => { let hir_expr = self.save_ctxt.tcx.hir().expect_expr(ex.hir_id); let adt = match self.save_ctxt.typeck_results().expr_ty_opt(&hir_expr) { Some(ty) if ty.ty_adt_def().is_some() => ty.ty_adt_def().unwrap(), @@ -1409,7 +1411,7 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> { } }; let res = self.save_ctxt.get_path_res(hir_expr.hir_id); - self.process_struct_lit(ex, path, fields, adt.variant_of_res(res), *base) + self.process_struct_lit(ex, path, fields, adt.variant_of_res(res), *rest) } hir::ExprKind::MethodCall(ref seg, _, args, _) => { self.process_method_call(ex, seg, args) diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs index 8e60085262a..5ebd6c4a234 100644 --- a/compiler/rustc_target/src/asm/mod.rs +++ b/compiler/rustc_target/src/asm/mod.rs @@ -155,6 +155,7 @@ mod hexagon; mod mips; mod nvptx; mod riscv; +mod spirv; mod x86; pub use aarch64::{AArch64InlineAsmReg, AArch64InlineAsmRegClass}; @@ -163,6 +164,7 @@ pub use hexagon::{HexagonInlineAsmReg, HexagonInlineAsmRegClass}; pub use mips::{MipsInlineAsmReg, MipsInlineAsmRegClass}; pub use nvptx::{NvptxInlineAsmReg, NvptxInlineAsmRegClass}; pub use riscv::{RiscVInlineAsmReg, RiscVInlineAsmRegClass}; +pub use spirv::{SpirVInlineAsmReg, SpirVInlineAsmRegClass}; pub use x86::{X86InlineAsmReg, X86InlineAsmRegClass}; #[derive(Copy, Clone, Encodable, Decodable, Debug, Eq, PartialEq, Hash)] @@ -177,6 +179,7 @@ pub enum InlineAsmArch { Hexagon, Mips, Mips64, + SpirV, } impl FromStr for InlineAsmArch { @@ -194,6 +197,7 @@ impl FromStr for InlineAsmArch { "hexagon" => Ok(Self::Hexagon), "mips" => Ok(Self::Mips), "mips64" => Ok(Self::Mips64), + "spirv" => Ok(Self::SpirV), _ => Err(()), } } @@ -208,6 +212,7 @@ pub enum InlineAsmReg { Nvptx(NvptxInlineAsmReg), Hexagon(HexagonInlineAsmReg), Mips(MipsInlineAsmReg), + SpirV(SpirVInlineAsmReg), } impl InlineAsmReg { @@ -264,6 +269,9 @@ impl InlineAsmReg { InlineAsmArch::Mips | InlineAsmArch::Mips64 => { Self::Mips(MipsInlineAsmReg::parse(arch, has_feature, target, &name)?) } + InlineAsmArch::SpirV => { + Self::SpirV(SpirVInlineAsmReg::parse(arch, has_feature, target, &name)?) + } }) } @@ -306,6 +314,7 @@ pub enum InlineAsmRegClass { Nvptx(NvptxInlineAsmRegClass), Hexagon(HexagonInlineAsmRegClass), Mips(MipsInlineAsmRegClass), + SpirV(SpirVInlineAsmRegClass), } impl InlineAsmRegClass { @@ -318,6 +327,7 @@ impl InlineAsmRegClass { Self::Nvptx(r) => r.name(), Self::Hexagon(r) => r.name(), Self::Mips(r) => r.name(), + Self::SpirV(r) => r.name(), } } @@ -333,6 +343,7 @@ impl InlineAsmRegClass { Self::Nvptx(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Nvptx), Self::Hexagon(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Hexagon), Self::Mips(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Mips), + Self::SpirV(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::SpirV), } } @@ -355,6 +366,7 @@ impl InlineAsmRegClass { Self::Nvptx(r) => r.suggest_modifier(arch, ty), Self::Hexagon(r) => r.suggest_modifier(arch, ty), Self::Mips(r) => r.suggest_modifier(arch, ty), + Self::SpirV(r) => r.suggest_modifier(arch, ty), } } @@ -373,6 +385,7 @@ impl InlineAsmRegClass { Self::Nvptx(r) => r.default_modifier(arch), Self::Hexagon(r) => r.default_modifier(arch), Self::Mips(r) => r.default_modifier(arch), + Self::SpirV(r) => r.default_modifier(arch), } } @@ -390,6 +403,7 @@ impl InlineAsmRegClass { Self::Nvptx(r) => r.supported_types(arch), Self::Hexagon(r) => r.supported_types(arch), Self::Mips(r) => r.supported_types(arch), + Self::SpirV(r) => r.supported_types(arch), } } @@ -414,6 +428,7 @@ impl InlineAsmRegClass { InlineAsmArch::Mips | InlineAsmArch::Mips64 => { Self::Mips(MipsInlineAsmRegClass::parse(arch, name)?) } + InlineAsmArch::SpirV => Self::SpirV(SpirVInlineAsmRegClass::parse(arch, name)?), }) }) } @@ -429,6 +444,7 @@ impl InlineAsmRegClass { Self::Nvptx(r) => r.valid_modifiers(arch), Self::Hexagon(r) => r.valid_modifiers(arch), Self::Mips(r) => r.valid_modifiers(arch), + Self::SpirV(r) => r.valid_modifiers(arch), } } } @@ -571,5 +587,10 @@ pub fn allocatable_registers( mips::fill_reg_map(arch, has_feature, target, &mut map); map } + InlineAsmArch::SpirV => { + let mut map = spirv::regclass_map(); + spirv::fill_reg_map(arch, has_feature, target, &mut map); + map + } } } diff --git a/compiler/rustc_target/src/asm/spirv.rs b/compiler/rustc_target/src/asm/spirv.rs new file mode 100644 index 00000000000..da82749e96a --- /dev/null +++ b/compiler/rustc_target/src/asm/spirv.rs @@ -0,0 +1,46 @@ +use super::{InlineAsmArch, InlineAsmType}; +use rustc_macros::HashStable_Generic; + +def_reg_class! { + SpirV SpirVInlineAsmRegClass { + reg, + } +} + +impl SpirVInlineAsmRegClass { + pub fn valid_modifiers(self, _arch: super::InlineAsmArch) -> &'static [char] { + &[] + } + + pub fn suggest_class(self, _arch: InlineAsmArch, _ty: InlineAsmType) -> Option<Self> { + None + } + + pub fn suggest_modifier( + self, + _arch: InlineAsmArch, + _ty: InlineAsmType, + ) -> Option<(char, &'static str)> { + None + } + + pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<(char, &'static str)> { + None + } + + pub fn supported_types( + self, + _arch: InlineAsmArch, + ) -> &'static [(InlineAsmType, Option<&'static str>)] { + match self { + Self::reg => { + types! { _: I8, I16, I32, I64, F32, F64; } + } + } + } +} + +def_regs! { + // SPIR-V is SSA-based, it does not have registers. + SpirV SpirVInlineAsmReg SpirVInlineAsmRegClass {} +} |
