Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 82 additions & 2 deletions compiler/rustc_ast_pretty/src/pprust/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1649,6 +1649,85 @@ impl<'a> State<'a> {
);
}

fn inline_asm_template_and_operands<'asm>(
asm: &'asm ast::InlineAsm,
) -> (String, Vec<&'asm InlineAsmOperand>) {
fn is_explicit_reg(op: &InlineAsmOperand) -> bool {
match op {
InlineAsmOperand::In { reg, .. }
| InlineAsmOperand::Out { reg, .. }
| InlineAsmOperand::InOut { reg, .. }
| InlineAsmOperand::SplitInOut { reg, .. } => {
matches!(reg, InlineAsmRegOrRegClass::Reg(_))
}
InlineAsmOperand::Const { .. }
| InlineAsmOperand::Sym { .. }
| InlineAsmOperand::Label { .. } => false,
}
}

// After macro expansion, named operands become positional. The grammar
// requires positional operands to precede explicit register operands,
// so we must reorder when any non-explicit operand follows an explicit
// one. When no reordering is needed, we use the original template
// string and operand order to avoid duplicating the Display logic in
// InlineAsmTemplatePiece.
let needs_reorder = {
let mut seen_explicit = false;
asm.operands.iter().any(|(op, _)| {
if is_explicit_reg(op) {
seen_explicit = true;
false
} else {
seen_explicit
}
})
};

if !needs_reorder {
let template = InlineAsmTemplatePiece::to_string(&asm.template);
let operands = asm.operands.iter().map(|(op, _)| op).collect();
return (template, operands);
}

let mut non_explicit = Vec::new();
let mut explicit = Vec::new();
for (i, (op, _)) in asm.operands.iter().enumerate() {
if is_explicit_reg(op) {
explicit.push(i);
} else {
non_explicit.push(i);
}
}
let order = non_explicit.into_iter().chain(explicit).collect::<Vec<_>>();

// Build old-index -> new-index mapping for template renumbering.
let mut old_to_new = vec![0usize; asm.operands.len()];
for (new_idx, old_idx) in order.iter().copied().enumerate() {
old_to_new[old_idx] = new_idx;
}

// Remap template placeholder indices and reuse the existing Display
// impl to build the template string.
let remapped = asm
.template
.iter()
.map(|piece| match piece {
InlineAsmTemplatePiece::Placeholder { operand_idx, modifier, span } => {
InlineAsmTemplatePiece::Placeholder {
operand_idx: old_to_new[*operand_idx],
modifier: *modifier,
span: *span,
}
}
other => other.clone(),
})
.collect::<Vec<_>>();
let template = InlineAsmTemplatePiece::to_string(&remapped);
let operands = order.iter().map(|&idx| &asm.operands[idx].0).collect();
(template, operands)
}

fn print_inline_asm(&mut self, asm: &ast::InlineAsm) {
enum AsmArg<'a> {
Template(String),
Expand All @@ -1657,8 +1736,9 @@ impl<'a> State<'a> {
Options(InlineAsmOptions),
}

let mut args = vec![AsmArg::Template(InlineAsmTemplatePiece::to_string(&asm.template))];
args.extend(asm.operands.iter().map(|(o, _)| AsmArg::Operand(o)));
let (template, operands) = Self::inline_asm_template_and_operands(asm);
let mut args = vec![AsmArg::Template(template)];
args.extend(operands.into_iter().map(AsmArg::Operand));
for (abi, _) in &asm.clobber_abis {
args.push(AsmArg::ClobberAbi(*abi));
}
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_target/src/spec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1826,6 +1826,8 @@ supported_targets! {
("x86_64-pc-cygwin", x86_64_pc_cygwin),

("x86_64-unknown-linux-gnuasan", x86_64_unknown_linux_gnuasan),
("x86_64-unknown-linux-gnumsan", x86_64_unknown_linux_gnumsan),
("x86_64-unknown-linux-gnutsan", x86_64_unknown_linux_gnutsan),
}

/// Cow-Vec-Str: Cow<'static, [Cow<'static, str>]>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
use crate::spec::{SanitizerSet, Target, TargetMetadata};

pub(crate) fn target() -> Target {
let mut base = super::x86_64_unknown_linux_gnu::target();
base.metadata = TargetMetadata {
description: Some(
"64-bit Linux (kernel 3.2+, glibc 2.17+) with MSAN enabled by default".into(),
),
tier: Some(2),
host_tools: Some(false),
std: Some(true),
};
base.supported_sanitizers = SanitizerSet::MEMORY;
base.default_sanitizers = SanitizerSet::MEMORY;
base
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
use crate::spec::{SanitizerSet, Target, TargetMetadata};

pub(crate) fn target() -> Target {
let mut base = super::x86_64_unknown_linux_gnu::target();
base.metadata = TargetMetadata {
description: Some(
"64-bit Linux (kernel 3.2+, glibc 2.17+) with TSAN enabled by default".into(),
),
tier: Some(2),
host_tools: Some(false),
std: Some(true),
};
base.supported_sanitizers = SanitizerSet::THREAD;
base.default_sanitizers = SanitizerSet::THREAD;
base
}
6 changes: 3 additions & 3 deletions library/core/src/macros/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,6 @@ macro_rules! assert_ne {
};
}

// FIXME add back debug_assert_matches doc link after bootstrap.

/// Asserts that an expression matches the provided pattern.
///
/// This macro is generally preferable to `assert!(matches!(value, pattern))`, because it can print
Expand All @@ -137,9 +135,11 @@ macro_rules! assert_ne {
/// otherwise this macro will panic.
///
/// Assertions are always checked in both debug and release builds, and cannot
/// be disabled. See `debug_assert_matches!` for assertions that are disabled in
/// be disabled. See [`debug_assert_matches!`] for assertions that are disabled in
/// release builds by default.
///
/// [`debug_assert_matches!`]: crate::debug_assert_matches
///
/// On panic, this macro will print the value of the expression with its debug representation.
///
/// Like [`assert!`], this macro has a second form, where a custom panic message can be provided.
Expand Down
2 changes: 2 additions & 0 deletions src/bootstrap/src/core/build_steps/llvm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1558,6 +1558,8 @@ fn supported_sanitizers(
&["asan", "dfsan", "lsan", "msan", "safestack", "tsan", "rtsan"],
),
"x86_64-unknown-linux-gnuasan" => common_libs("linux", "x86_64", &["asan"]),
"x86_64-unknown-linux-gnumsan" => common_libs("linux", "x86_64", &["msan"]),
"x86_64-unknown-linux-gnutsan" => common_libs("linux", "x86_64", &["tsan"]),
"x86_64-unknown-linux-musl" => {
common_libs("linux", "x86_64", &["asan", "lsan", "msan", "tsan"])
}
Expand Down
2 changes: 2 additions & 0 deletions src/bootstrap/src/core/sanity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ pub struct Finder {
/// when the newly-bumped stage 0 compiler now knows about the formerly-missing targets.
const STAGE0_MISSING_TARGETS: &[&str] = &[
// just a dummy comment so the list doesn't get onelined
"x86_64-unknown-linux-gnumsan",
"x86_64-unknown-linux-gnutsan",
];

/// Minimum version threshold for libstdc++ required when using prebuilt LLVM
Expand Down
2 changes: 2 additions & 0 deletions src/ci/docker/host-x86_64/dist-various-2/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@ ENV TARGETS=$TARGETS,x86_64-unknown-uefi
ENV TARGETS=$TARGETS,riscv64gc-unknown-linux-musl

ENV TARGETS_SANITIZERS=x86_64-unknown-linux-gnuasan
ENV TARGETS_SANITIZERS=$TARGETS_SANITIZERS,x86_64-unknown-linux-gnumsan
ENV TARGETS_SANITIZERS=$TARGETS_SANITIZERS,x86_64-unknown-linux-gnutsan

# As per https://bugs.launchpad.net/ubuntu/+source/gcc-defaults/+bug/1300211
# we need asm in the search path for gcc-9 (for gnux32) but not in the search path of the
Expand Down
2 changes: 2 additions & 0 deletions src/doc/rustc/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,5 +155,7 @@
- [x86_64-unknown-linux-none](platform-support/x86_64-unknown-linux-none.md)
- [x86_64-unknown-none](platform-support/x86_64-unknown-none.md)
- [x86_64-unknown-linux-gnuasan](platform-support/x86_64-unknown-linux-gnuasan.md)
- [x86_64-unknown-linux-gnumsan](platform-support/x86_64-unknown-linux-gnumsan.md)
- [x86_64-unknown-linux-gnutsan](platform-support/x86_64-unknown-linux-gnutsan.md)
- [xtensa-\*-none-elf](platform-support/xtensa.md)
- [\*-nuttx-\*](platform-support/nuttx.md)
2 changes: 2 additions & 0 deletions src/doc/rustc/src/platform-support.md
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,8 @@ target | std | notes
[`x86_64-fortanix-unknown-sgx`](platform-support/x86_64-fortanix-unknown-sgx.md) | ✓ | [Fortanix ABI] for 64-bit Intel SGX
[`x86_64-linux-android`](platform-support/android.md) | ✓ | 64-bit x86 Android
[`x86_64-unknown-linux-gnuasan`](platform-support/x86_64-unknown-linux-gnuasan.md) | ✓ | 64-bit Linux (kernel 3.2+, glibc 2.17+) with ASAN enabled by default
[`x86_64-unknown-linux-gnumsan`](platform-support/x86_64-unknown-linux-gnumsan.md) | ✓ | 64-bit Linux (kernel 3.2+, glibc 2.17+) with MSAN enabled by default
[`x86_64-unknown-linux-gnutsan`](platform-support/x86_64-unknown-linux-gnutsan.md) | ✓ | 64-bit Linux (kernel 3.2+, glibc 2.17+) with TSAN enabled by default
[`x86_64-unknown-fuchsia`](platform-support/fuchsia.md) | ✓ | 64-bit x86 Fuchsia
`x86_64-unknown-linux-gnux32` | ✓ | 64-bit Linux (x32 ABI) (kernel 4.15+, glibc 2.27)
[`x86_64-unknown-none`](platform-support/x86_64-unknown-none.md) | * | Freestanding/bare-metal x86_64, softfloat
Expand Down
56 changes: 56 additions & 0 deletions src/doc/rustc/src/platform-support/x86_64-unknown-linux-gnumsan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# `x86_64-unknown-linux-gnumsan`

**Tier: 2**

Target mirroring `x86_64-unknown-linux-gnu` with MemorySanitizer enabled by
default.
The goal of this target is to allow shipping MSAN-instrumented standard
libraries through rustup, enabling a fully instrumented binary without requiring
nightly features (build-std).
Once build-std stabilizes, this target is no longer needed and will be removed.

## Target maintainers

- [@jakos-sec](https://github.com/jakos-sec)
- [@1c3t3a](https://github.com/1c3t3a)
- [@rust-lang/project-exploit-mitigations][project-exploit-mitigations]

## Requirements

The target is for cross-compilation only. Host tools are not supported, since
there is no need to have the host tools instrumented with MSAN. std is fully
supported.

In all other aspects the target is equivalent to `x86_64-unknown-linux-gnu`.

## Building the target

The target can be built by enabling it for a rustc build:

```toml
[build]
target = ["x86_64-unknown-linux-gnumsan"]
```

## Building Rust programs

Rust programs can be compiled by adding this target via rustup:

```sh
$ rustup target add x86_64-unknown-linux-gnumsan
```

and then compiling with the target:

```sh
$ rustc foo.rs --target x86_64-unknown-linux-gnumsan
```

## Testing

Created binaries will run on Linux without any external requirements.

## Cross-compilation toolchains and C code

The target supports C code and should use the same toolchain target as
`x86_64-unknown-linux-gnu`.
56 changes: 56 additions & 0 deletions src/doc/rustc/src/platform-support/x86_64-unknown-linux-gnutsan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# `x86_64-unknown-linux-gnutsan`

**Tier: 2**

Target mirroring `x86_64-unknown-linux-gnu` with ThreadSanitizer enabled by
default.
The goal of this target is to allow shipping TSAN-instrumented standard
libraries through rustup, enabling a fully instrumented binary without requiring
nightly features (build-std).
Once build-std stabilizes, this target is no longer needed and will be removed.

## Target maintainers

- [@jakos-sec](https://github.com/jakos-sec)
- [@1c3t3a](https://github.com/1c3t3a)
- [@rust-lang/project-exploit-mitigations][project-exploit-mitigations]

## Requirements

The target is for cross-compilation only. Host tools are not supported, since
there is no need to have the host tools instrumented with TSAN. std is fully
supported.

In all other aspects the target is equivalent to `x86_64-unknown-linux-gnu`.

## Building the target

The target can be built by enabling it for a rustc build:

```toml
[build]
target = ["x86_64-unknown-linux-gnutsan"]
```

## Building Rust programs

Rust programs can be compiled by adding this target via rustup:

```sh
$ rustup target add x86_64-unknown-linux-gnutsan
```

and then compiling with the target:

```sh
$ rustc foo.rs --target x86_64-unknown-linux-gnutsan
```

## Testing

Created binaries will run on Linux without any external requirements.

## Cross-compilation toolchains and C code

The target supports C code and should use the same toolchain target as
`x86_64-unknown-linux-gnu`.
6 changes: 6 additions & 0 deletions tests/assembly-llvm/targets/targets-elf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -709,6 +709,12 @@
//@ revisions: x86_64_unknown_linux_gnuasan
//@ [x86_64_unknown_linux_gnuasan] compile-flags: --target x86_64-unknown-linux-gnuasan
//@ [x86_64_unknown_linux_gnuasan] needs-llvm-components: x86
//@ revisions: x86_64_unknown_linux_gnumsan
//@ [x86_64_unknown_linux_gnumsan] compile-flags: --target x86_64-unknown-linux-gnumsan
//@ [x86_64_unknown_linux_gnumsan] needs-llvm-components: x86
//@ revisions: x86_64_unknown_linux_gnutsan
//@ [x86_64_unknown_linux_gnutsan] compile-flags: --target x86_64-unknown-linux-gnutsan
//@ [x86_64_unknown_linux_gnutsan] needs-llvm-components: x86
//@ revisions: x86_64_unknown_linux_musl
//@ [x86_64_unknown_linux_musl] compile-flags: --target x86_64-unknown-linux-musl
//@ [x86_64_unknown_linux_musl] needs-llvm-components: x86
Expand Down
19 changes: 19 additions & 0 deletions tests/pretty/asm-operand-order.pp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#![feature(prelude_import)]
#![no_std]
extern crate std;
#[prelude_import]
use ::std::prelude::rust_2015::*;
//@ pretty-mode:expanded
//@ pp-exact:asm-operand-order.pp
//@ only-x86_64

use std::arch::asm;

pub fn main() {
unsafe {
asm!("{0}", in(reg) 4, out("rax") _);
asm!("{0}", in(reg) 4, out("rax") _, options(nostack));
asm!("{0} {1}", in(reg) 4, in(reg) 5, out("rax") _);
asm!("{0}", const 5, out("rax") _);
}
}
14 changes: 14 additions & 0 deletions tests/pretty/asm-operand-order.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//@ pretty-mode:expanded
//@ pp-exact:asm-operand-order.pp
//@ only-x86_64

use std::arch::asm;

pub fn main() {
unsafe {
asm!("{val}", out("rax") _, val = in(reg) 4);
asm!("{val}", out("rax") _, val = in(reg) 4, options(nostack));
asm!("{a} {b}", out("rax") _, a = in(reg) 4, b = in(reg) 5);
asm!("{val}", out("rax") _, val = const 5);
}
}
Loading
Loading