| Age | Commit message (Collapse) | Author | Lines | |
|---|---|---|---|---|
| 2020-07-01 | Rollup merge of #73569 - Aaron1011:fix/macro-rules-group, r=petrochenkov | Manish Goregaokar | -0/+25 | |
| Handle `macro_rules!` tokens consistently across crates When we serialize a `macro_rules!` macro, we used a 'lowered' `TokenStream` for its body, which has all `Nonterminal`s expanded in-place via `nt_to_tokenstream`. This matters when an 'outer' `macro_rules!` macro expands to an 'inner' `macro_rules!` macro - the inner macro may use tokens captured from the 'outer' macro in its definition. This means that invoking a foreign `macro_rules!` macro may use a different body `TokenStream` than when the same `macro_rules!` macro is invoked in the same crate. This difference is observable by proc-macros invoked by a `macro_rules!` macro - a `None`-delimited group will be seen in the same-crate case (inserted when convering `Nonterminal`s to the `proc_macro` crate's structs), but no `None`-delimited group in the cross-crate case. To fix this inconsistency, we now insert `None`-delimited groups when 'lowering' a `Nonterminal` `macro_rules!` body, just as we do in `proc_macro_server`. Additionally, we no longer print extra spaces for `None`-delimited groups - as far as pretty-printing is concerned, they don't exist (only their contents do). This ensures that `Display` output of a `TokenStream` does not depend on which crate a `macro_rules!` macro was invoked from. This PR is necessary in order to patch the `solana-genesis-programs` for the upcoming hygiene serialization breakage (https://github.com/rust-lang/rust/pull/72121#issuecomment-646924847). The `solana-genesis-programs` crate will need to use a proc macro to re-span certain tokens in a nested `macro_rules!`, which requires us to consistently use a `None`-delimited group. See `src/test/ui/proc-macro/nested-macro-rules.rs` for an example of the kind of nested `macro_rules!` affected by this crate. | ||||
| 2020-07-01 | Insert NoDelim groups around nonterminals when lowering macro_rules | Aaron Hill | -0/+25 | |
| 2020-06-30 | Stabilize `#[track_caller]`. | Adam Perry | -5/+3 | |
| Does not yet make its constness stable, though. Use of `Location::caller` in const contexts is still gated by `#![feature(const_caller_location)]`. | ||||
| 2020-05-26 | expand `env!` with def-site context | Andy Russell | -0/+2 | |
| 2020-05-19 | Auto merge of #69171 - Amanieu:new-asm, r=nagisa,nikomatsakis | bors | -17/+24 | |
| Implement new asm! syntax from RFC 2850 This PR implements the new `asm!` syntax proposed in https://github.com/rust-lang/rfcs/pull/2850. # Design A large part of this PR revolves around taking an `asm!` macro invocation and plumbing it through all of the compiler layers down to LLVM codegen. Throughout the various stages, an `InlineAsm` generally consists of 3 components: - The template string, which is stored as an array of `InlineAsmTemplatePiece`. Each piece represents either a literal or a placeholder for an operand (just like format strings). ```rust pub enum InlineAsmTemplatePiece { String(String), Placeholder { operand_idx: usize, modifier: Option<char>, span: Span }, } ``` - The list of operands to the `asm!` (`in`, `[late]out`, `in[late]out`, `sym`, `const`). These are represented differently at each stage of lowering, but follow a common pattern: - `in`, `out` and `inout` all have an associated register class (`reg`) or explicit register (`"eax"`). - `inout` has 2 forms: one with a single expression that is both read from and written to, and one with two separate expressions for the input and output parts. - `out` and `inout` have a `late` flag (`lateout` / `inlateout`) to indicate that the register allocator is allowed to reuse an input register for this output. - `out` and the split variant of `inout` allow `_` to be specified for an output, which means that the output is discarded. This is used to allocate scratch registers for assembly code. - `sym` is a bit special since it only accepts a path expression, which must point to a `static` or a `fn`. - The options set at the end of the `asm!` macro. The only one that is particularly of interest to rustc is `NORETURN` which makes `asm!` return `!` instead of `()`. ```rust bitflags::bitflags! { pub struct InlineAsmOptions: u8 { const PURE = 1 << 0; const NOMEM = 1 << 1; const READONLY = 1 << 2; const PRESERVES_FLAGS = 1 << 3; const NORETURN = 1 << 4; const NOSTACK = 1 << 5; } } ``` ## AST `InlineAsm` is represented as an expression in the AST: ```rust pub struct InlineAsm { pub template: Vec<InlineAsmTemplatePiece>, pub operands: Vec<(InlineAsmOperand, Span)>, pub options: InlineAsmOptions, } pub enum InlineAsmRegOrRegClass { Reg(Symbol), RegClass(Symbol), } pub enum InlineAsmOperand { In { reg: InlineAsmRegOrRegClass, expr: P<Expr>, }, Out { reg: InlineAsmRegOrRegClass, late: bool, expr: Option<P<Expr>>, }, InOut { reg: InlineAsmRegOrRegClass, late: bool, expr: P<Expr>, }, SplitInOut { reg: InlineAsmRegOrRegClass, late: bool, in_expr: P<Expr>, out_expr: Option<P<Expr>>, }, Const { expr: P<Expr>, }, Sym { expr: P<Expr>, }, } ``` The `asm!` macro is implemented in librustc_builtin_macros and outputs an `InlineAsm` AST node. The template string is parsed using libfmt_macros, positional and named operands are resolved to explicit operand indicies. Since target information is not available to macro invocations, validation of the registers and register classes is deferred to AST lowering. ## HIR `InlineAsm` is represented as an expression in the HIR: ```rust pub struct InlineAsm<'hir> { pub template: &'hir [InlineAsmTemplatePiece], pub operands: &'hir [InlineAsmOperand<'hir>], pub options: InlineAsmOptions, } pub enum InlineAsmRegOrRegClass { Reg(InlineAsmReg), RegClass(InlineAsmRegClass), } pub enum InlineAsmOperand<'hir> { In { reg: InlineAsmRegOrRegClass, expr: Expr<'hir>, }, Out { reg: InlineAsmRegOrRegClass, late: bool, expr: Option<Expr<'hir>>, }, InOut { reg: InlineAsmRegOrRegClass, late: bool, expr: Expr<'hir>, }, SplitInOut { reg: InlineAsmRegOrRegClass, late: bool, in_expr: Expr<'hir>, out_expr: Option<Expr<'hir>>, }, Const { expr: Expr<'hir>, }, Sym { expr: Expr<'hir>, }, } ``` AST lowering is where `InlineAsmRegOrRegClass` is converted from `Symbol`s to an actual register or register class. If any modifiers are specified for a template string placeholder, these are validated against the set allowed for that operand type. Finally, explicit registers for inputs and outputs are checked for conflicts (same register used for different operands). ## Type checking Each register class has a whitelist of types that it may be used with. After the types of all operands have been determined, the `intrinsicck` pass will check that these types are in the whitelist. It also checks that split `inout` operands have compatible types and that `const` operands are integers or floats. Suggestions are emitted where needed if a template modifier should be used for an operand based on the type that was passed into it. ## HAIR `InlineAsm` is represented as an expression in the HAIR: ```rust crate enum ExprKind<'tcx> { // [..] InlineAsm { template: &'tcx [InlineAsmTemplatePiece], operands: Vec<InlineAsmOperand<'tcx>>, options: InlineAsmOptions, }, } crate enum InlineAsmOperand<'tcx> { In { reg: InlineAsmRegOrRegClass, expr: ExprRef<'tcx>, }, Out { reg: InlineAsmRegOrRegClass, late: bool, expr: Option<ExprRef<'tcx>>, }, InOut { reg: InlineAsmRegOrRegClass, late: bool, expr: ExprRef<'tcx>, }, SplitInOut { reg: InlineAsmRegOrRegClass, late: bool, in_expr: ExprRef<'tcx>, out_expr: Option<ExprRef<'tcx>>, }, Const { expr: ExprRef<'tcx>, }, SymFn { expr: ExprRef<'tcx>, }, SymStatic { expr: ExprRef<'tcx>, }, } ``` The only significant change compared to HIR is that `Sym` has been lowered to either a `SymFn` whose `expr` is a `Literal` ZST of the `fn`, or a `SymStatic` whose `expr` is a `StaticRef`. ## MIR `InlineAsm` is represented as a `Terminator` in the MIR: ```rust pub enum TerminatorKind<'tcx> { // [..] /// Block ends with an inline assembly block. This is a terminator since /// inline assembly is allowed to diverge. InlineAsm { /// The template for the inline assembly, with placeholders. template: &'tcx [InlineAsmTemplatePiece], /// The operands for the inline assembly, as `Operand`s or `Place`s. operands: Vec<InlineAsmOperand<'tcx>>, /// Miscellaneous options for the inline assembly. options: InlineAsmOptions, /// Destination block after the inline assembly returns, unless it is /// diverging (InlineAsmOptions::NORETURN). destination: Option<BasicBlock>, }, } pub enum InlineAsmOperand<'tcx> { In { reg: InlineAsmRegOrRegClass, value: Operand<'tcx>, }, Out { reg: InlineAsmRegOrRegClass, late: bool, place: Option<Place<'tcx>>, }, InOut { reg: InlineAsmRegOrRegClass, late: bool, in_value: Operand<'tcx>, out_place: Option<Place<'tcx>>, }, Const { value: Operand<'tcx>, }, SymFn { value: Box<Constant<'tcx>>, }, SymStatic { value: Box<Constant<'tcx>>, }, } ``` As part of HAIR lowering, `InOut` and `SplitInOut` operands are lowered to a split form with a separate `in_value` and `out_place`. Semantically, the `InlineAsm` terminator is similar to the `Call` terminator except that it has multiple output places where a `Call` only has a single return place output. The constant promotion pass is used to ensure that `const` operands are actually constants (using the same logic as `#[rustc_args_required_const]`). ## Codegen Operands are lowered one more time before being passed to LLVM codegen: ```rust pub enum InlineAsmOperandRef<'tcx, B: BackendTypes + ?Sized> { In { reg: InlineAsmRegOrRegClass, value: OperandRef<'tcx, B::Value>, }, Out { reg: InlineAsmRegOrRegClass, late: bool, place: Option<PlaceRef<'tcx, B::Value>>, }, InOut { reg: InlineAsmRegOrRegClass, late: bool, in_value: OperandRef<'tcx, B::Value>, out_place: Option<PlaceRef<'tcx, B::Value>>, }, Const { string: String, }, SymFn { instance: Instance<'tcx>, }, SymStatic { def_id: DefId, }, } ``` The operands are lowered to LLVM operands and constraint codes as follow: - `out` and the output part of `inout` operands are added first, as required by LLVM. Late output operands have a `=` prefix added to their constraint code, non-late output operands have a `=&` prefix added to their constraint code. - `in` operands are added normally. - `inout` operands are tied to the matching output operand. - `sym` operands are passed as function pointers or pointers, using the `"s"` constraint. - `const` operands are formatted to a string and directly inserted in the template string. The template string is converted to LLVM form: - `$` characters are escaped as `$$`. - `const` operands are converted to strings and inserted directly. - Placeholders are formatted as `${X:M}` where `X` is the operand index and `M` is the modifier character. Modifiers are converted from the Rust form to the LLVM form. The various options are converted to clobber constraints or LLVM attributes, refer to the [RFC](https://github.com/Amanieu/rfcs/blob/inline-asm/text/0000-inline-asm.md#mapping-to-llvm-ir) for more details. Note that LLVM is sometimes rather picky about what types it accepts for certain constraint codes so we sometimes need to insert conversions to/from a supported type. See the target-specific ISelLowering.cpp files in LLVM for details. # Adding support for new architectures Adding inline assembly support to an architecture is mostly a matter of defining the registers and register classes for that architecture. All the definitions for register classes are located in `src/librustc_target/asm/`. Additionally you will need to implement lowering of these register classes to LLVM constraint codes in `src/librustc_codegen_llvm/asm.rs`. | ||||
| 2020-05-19 | Auto merge of #68717 - petrochenkov:stabexpat, r=varkor | bors | -1/+1 | |
| Stabilize fn-like proc macros in expression, pattern and statement positions I.e. all the positions in which stable `macro_rules` macros are supported. Depends on https://github.com/rust-lang/rust/pull/68716 ("Stabilize `Span::mixed_site`"). cc https://github.com/rust-lang/rust/issues/54727 cc https://github.com/rust-lang/rust/issues/54727#issuecomment-580647446 Stabilization report: https://github.com/rust-lang/rust/pull/68717#issuecomment-623197503. | ||||
| 2020-05-18 | Add tests for asm! | Amanieu d'Antras | -17/+24 | |
| 2020-05-09 | Rollup merge of #71185 - JohnTitor:run-fail, r=petrochenkov | Ralf Jung | -0/+113 | |
| Move tests from `test/run-fail` to UI Fixes #65440 cc #65865 #65506 r? @nikomatsakis | ||||
| 2020-05-08 | Skip tests on emscripten | Yuki Okushi | -0/+15 | |
| 2020-05-07 | reword "possible candidate" import suggestion | Andy Russell | -1/+1 | |
| 2020-05-06 | Move tests from `test/run-fail` to UI | Yuki Okushi | -0/+98 | |
| 2020-05-03 | Stabilize fn-like proc macros in expression, pattern and statement positions | Vadim Petrochenkov | -1/+1 | |
| 2020-05-01 | Add new tests and bless old tests | LeSeulArtichaut | -3/+7 | |
| 2020-04-30 | Rollup merge of #71205 - NeoRaider:check_attr, r=jonas-schievink | Dylan DPC | -5/+3 | |
| rustc: fix check_attr() for methods, closures and foreign functions This fixes an issue that previously turned up for methods in https://github.com/rust-lang/rust/pull/69274, but also exists for closures and foreign function: `check_attr` does not call `codegen_fn_attrs()` for these types when it should, meaning that incorrectly used function attributes are not diagnosed without codegen. The issue affects our UI tests, as they run with `--emit=metadata` by default, but as it turns out, this is not the only case: Function attributes are not checked on any dead code without this fix! This makes the fix a **breaking change**. The following very silly Rust programs compiles fine on stable Rust when it should not, which is fixed by this PR. ```rust fn main() { #[target_feature(enable = "sse2")] || {}; } ``` I assume any real-world program which may trigger this issue would at least emit a dead code warning, but of course that is no guarantee that such code does not exist... Fixes #70307 | ||||
| 2020-04-23 | Moving more build-pass tests to check-pass | Val Markovic | -1/+1 | |
| One or two tests became build-pass without the FIXME because they really needed build-pass (were failing without it). Helps with #62277 | ||||
| 2020-04-16 | rustc: fix check_attr() for methods, closures and foreign functions | Matthias Schiffer | -5/+3 | |
| UI tests are updated with additional error messages that were missing before. | ||||
| 2020-04-11 | rustc: Add a warning count upon completion | RoccoDev | -1/+9 | |
| 2020-04-04 | macro_rules: `NtLifetime` cannot start with an identifier | Vadim Petrochenkov | -0/+13 | |
| 2020-04-02 | tests: remove ignore directives from tests that mention core/alloc/std spans. | Eduard-Mihai Burtescu | -16/+3 | |
| 2020-03-27 | Rollup merge of #70434 - Centril:fix-34421, r=estebank | Mazdak Farrokhzad | -0/+55 | |
| suggest `;` on expr `mac!()` which is good as stmt `mac!()` Fixes https://github.com/rust-lang/rust/issues/34421 by implementing @jseyfried's suggestion in https://github.com/rust-lang/rust/issues/34421#issuecomment-301578683. r? @petrochenkov | ||||
| 2020-03-27 | suggest semi on expr mac!() good as stmt mac!(). | Mazdak Farrokhzad | -0/+55 | |
| 2020-03-26 | Update tests to use llvm_asm! | Amanieu d'Antras | -8/+8 | |
| 2020-03-24 | fix rebase fallout due to #69497. | Mazdak Farrokhzad | -10/+25 | |
| 2020-03-24 | defatalize `compile_declarative_macro` | Mazdak Farrokhzad | -0/+22 | |
| 2020-03-24 | mbe::transcribe: defatalize errors. | Mazdak Farrokhzad | -4/+33 | |
| 2020-03-24 | generic_extension: defatalize Error case | Mazdak Farrokhzad | -5/+22 | |
| 2020-03-24 | nix panictry! in ParserAnyMacro::make | Mazdak Farrokhzad | -1/+27 | |
| 2020-03-23 | Rollup merge of #69942 - estebank:sized-verbose-sugg, r=matthewjasper | Mazdak Farrokhzad | -1/+1 | |
| Increase verbosity when suggesting subtle code changes Do not suggest changes that are actually quite small inline, to minimize the likelihood of confusion. Fix #69243. | ||||
| 2020-03-23 | Rollup merge of #70227 - LeSeulArtichaut:typo-def, r=Centril | Mazdak Farrokhzad | -6/+4 | |
| Only display definition when suggesting a typo Closes #70206 r? @Centril | ||||
| 2020-03-22 | Normalize wording of privacy access labels | Esteban Küber | -1/+1 | |
| 2020-03-21 | Bless tests | LeSeulArtichaut | -6/+4 | |
| 2020-03-21 | Rollup merge of #69497 - Zoxc:ast-fragment-error, r=petrochenkov | Dylan DPC | -2/+13 | |
| Don't unwind when hitting the macro expansion recursion limit This removes one use of `FatalError.raise()`. r? @petrochenkov | ||||
| 2020-03-20 | expand_include: set `.directory` to dir of included file. | Mazdak Farrokhzad | -0/+13 | |
| 2020-03-19 | Update test | John Kåre Alsaker | -2/+13 | |
| 2020-03-17 | Update pretty tests | Guillaume Gomez | -1/+1 | |
| 2020-03-13 | Auto merge of #67502 - Mark-Simulacrum:opt-catch, r=Mark-Simulacrum | bors | -18/+17 | |
| Optimize catch_unwind to match C++ try/catch This refactors the implementation of catching unwinds to allow LLVM to inline the "try" closure directly into the happy path, avoiding indirection. This means that the catch_unwind implementation is (after this PR) zero-cost unless a panic is thrown. https://rust.godbolt.org/z/cZcUSB is an example of the current codegen in a simple case. Notably, the codegen is *exactly the same* if `-Cpanic=abort` is passed, which is clearly not great. This PR, on the other hand, generates the following assembly: ```asm # -Cpanic=unwind: push rbx mov ebx,0x2a call QWORD PTR [rip+0x1c53c] # <happy> mov eax,ebx pop rbx ret mov rdi,rax call QWORD PTR [rip+0x1c537] # cleanup function call call QWORD PTR [rip+0x1c539] # <unfortunate> mov ebx,0xd mov eax,ebx pop rbx ret # -Cpanic=abort: push rax call QWORD PTR [rip+0x20a1] # <happy> mov eax,0x2a pop rcx ret ``` Fixes #64224, and resolves #64222. | ||||
| 2020-03-13 | Add test for issue-58490 | Yuki Okushi | -0/+40 | |
| 2020-03-10 | macros/unknown-builtin: use hack for musl problems | Mazdak Farrokhzad | -1/+6 | |
| 2020-03-10 | --bless some tests | Mazdak Farrokhzad | -3/+7 | |
| 2020-03-06 | Turn trailing tokens in `assert!()` into hard errors | LeSeulArtichaut | -13/+7 | |
| 2020-03-05 | Remove eh_unwind_resume lang item | Amanieu d'Antras | -18/+17 | |
| 2020-02-24 | parse: use `parse_item_common` in `parse_foreign_item`. | Mazdak Farrokhzad | -9/+10 | |
| 2020-02-15 | fuse extern & associated item parsing up to defaultness | Mazdak Farrokhzad | -3/+3 | |
| 2020-02-15 | Avoid calling `fn_sig` on closures | Yuki Okushi | -0/+40 | |
| 2020-02-13 | parser: misc small item related improvements & cleanups. | Mazdak Farrokhzad | -10/+9 | |
| 2020-02-06 | rustc_macros: don't limit the -Zmacro-backtrace suggestion to extern macros. | Eduard-Mihai Burtescu | -4/+64 | |
| 2020-02-06 | rustc_errors: hide "in this macro invocation" when redundant, more explicitly. | Eduard-Mihai Burtescu | -4/+1 | |
| 2020-02-06 | rustc: rename -Zexternal-macro-backtrace to -Zmacro-backtrace. | Eduard-Mihai Burtescu | -4/+4 | |
| 2020-02-06 | Rollup merge of #68788 - Centril:unified-fn-bodies, r=petrochenkov | Dylan DPC | -2/+2 | |
| Towards unified `fn` grammar Part of https://github.com/rust-lang/rust/pull/68728. - Syntactically, `fn` items in `extern { ... }` blocks can now have bodies (`fn foo() { ... }` as opposed to `fn foo();`). As above, we use semantic restrictions instead. - Syntactically, `fn` items in free contexts (directly in a file or a module) can now be without bodies (`fn foo();` as opposed to `fn foo() { ... }`. As above, we use semantic restrictions instead, including for non-ident parameter patterns. - We move towards unifying the `fn` front matter; this is fully realized in https://github.com/rust-lang/rust/pull/68728. r? @petrochenkov | ||||
| 2020-02-05 | `#![recursion_limit = "X"]`: note current crate name. | Mazdak Farrokhzad | -1/+1 | |
