mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-15 05:26:47 +00:00
Auto merge of #92471 - matthiaskrgr:rollup-lmduxwh, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - #88310 (Lock bootstrap (x.py) build directory) - #92097 (Implement split_at_spare_mut without Deref to a slice so that the spare slice is valid) - #92412 (Fix double space in pretty printed TryBlock) - #92420 (Fix whitespace in pretty printed PatKind::Range) - #92457 (Sync rustc_codegen_gcc) - #92460 ([rustc_builtin_macros] add indices to format_foreign::printf::Substitution::Escape) - #92469 (Make tidy check for magic numbers that spell things) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
028c6f1454
@ -2241,7 +2241,6 @@ impl<'a> State<'a> {
|
||||
}
|
||||
ast::ExprKind::TryBlock(ref blk) => {
|
||||
self.head("try");
|
||||
self.space();
|
||||
self.print_block_with_attrs(blk, attrs)
|
||||
}
|
||||
ast::ExprKind::Err => {
|
||||
@ -2517,7 +2516,6 @@ impl<'a> State<'a> {
|
||||
PatKind::Range(ref begin, ref end, Spanned { node: ref end_kind, .. }) => {
|
||||
if let Some(e) = begin {
|
||||
self.print_expr(e);
|
||||
self.space();
|
||||
}
|
||||
match *end_kind {
|
||||
RangeEnd::Included(RangeSyntax::DotDotDot) => self.word("..."),
|
||||
|
@ -7,28 +7,29 @@ pub(crate) mod printf {
|
||||
pub enum Substitution<'a> {
|
||||
/// A formatted output substitution with its internal byte offset.
|
||||
Format(Format<'a>),
|
||||
/// A literal `%%` escape.
|
||||
Escape,
|
||||
/// A literal `%%` escape, with its start and end indices.
|
||||
Escape((usize, usize)),
|
||||
}
|
||||
|
||||
impl<'a> Substitution<'a> {
|
||||
pub fn as_str(&self) -> &str {
|
||||
match *self {
|
||||
Substitution::Format(ref fmt) => fmt.span,
|
||||
Substitution::Escape => "%%",
|
||||
Substitution::Escape(_) => "%%",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn position(&self) -> Option<InnerSpan> {
|
||||
match *self {
|
||||
Substitution::Format(ref fmt) => Some(fmt.position),
|
||||
_ => None,
|
||||
Substitution::Escape((start, end)) => Some(InnerSpan::new(start, end)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_position(&mut self, start: usize, end: usize) {
|
||||
if let Substitution::Format(ref mut fmt) = self {
|
||||
fmt.position = InnerSpan::new(start, end);
|
||||
match self {
|
||||
Substitution::Format(ref mut fmt) => fmt.position = InnerSpan::new(start, end),
|
||||
Substitution::Escape(ref mut pos) => *pos = (start, end),
|
||||
}
|
||||
}
|
||||
|
||||
@ -39,7 +40,7 @@ pub(crate) mod printf {
|
||||
pub fn translate(&self) -> Result<String, Option<String>> {
|
||||
match *self {
|
||||
Substitution::Format(ref fmt) => fmt.translate(),
|
||||
Substitution::Escape => Err(None),
|
||||
Substitution::Escape(_) => Err(None),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -304,14 +305,9 @@ pub(crate) mod printf {
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let (mut sub, tail) = parse_next_substitution(self.s)?;
|
||||
self.s = tail;
|
||||
match sub {
|
||||
Substitution::Format(_) => {
|
||||
if let Some(inner_span) = sub.position() {
|
||||
sub.set_position(inner_span.start + self.pos, inner_span.end + self.pos);
|
||||
self.pos += inner_span.end;
|
||||
}
|
||||
}
|
||||
Substitution::Escape => self.pos += 2,
|
||||
if let Some(InnerSpan { start, end }) = sub.position() {
|
||||
sub.set_position(start + self.pos, end + self.pos);
|
||||
self.pos += end;
|
||||
}
|
||||
Some(sub)
|
||||
}
|
||||
@ -340,7 +336,7 @@ pub(crate) mod printf {
|
||||
let at = {
|
||||
let start = s.find('%')?;
|
||||
if let '%' = s[start + 1..].chars().next()? {
|
||||
return Some((Substitution::Escape, &s[start + 2..]));
|
||||
return Some((Substitution::Escape((start, start + 2)), &s[start + 2..]));
|
||||
}
|
||||
|
||||
Cur::new_at(s, start)
|
||||
|
@ -13,9 +13,9 @@ macro_rules! assert_eq_pnsat {
|
||||
fn test_escape() {
|
||||
assert_eq!(pns("has no escapes"), None);
|
||||
assert_eq!(pns("has no escapes, either %"), None);
|
||||
assert_eq!(pns("*so* has a %% escape"), Some((S::Escape, " escape")));
|
||||
assert_eq!(pns("%% leading escape"), Some((S::Escape, " leading escape")));
|
||||
assert_eq!(pns("trailing escape %%"), Some((S::Escape, "")));
|
||||
assert_eq!(pns("*so* has a %% escape"), Some((S::Escape((11, 13)), " escape")));
|
||||
assert_eq!(pns("%% leading escape"), Some((S::Escape((0, 2)), " leading escape")));
|
||||
assert_eq!(pns("trailing escape %%"), Some((S::Escape((16, 18)), "")));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -17,12 +17,6 @@ version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "450575f58f7bee32816abbff470cbc47797397c2a81e0eaced4b98436daf52e1"
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
@ -35,15 +29,6 @@ version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "crc32fast"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fm"
|
||||
version = "0.1.4"
|
||||
@ -56,7 +41,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "gccjit"
|
||||
version = "1.0.0"
|
||||
source = "git+https://github.com/antoyo/gccjit.rs#2d4fea7319f80531b2e5d264fca9f1c498a3a62e"
|
||||
source = "git+https://github.com/antoyo/gccjit.rs#0672b78d162d65b6f36ea4062947253affe9fdef"
|
||||
dependencies = [
|
||||
"gccjit_sys",
|
||||
]
|
||||
@ -64,7 +49,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "gccjit_sys"
|
||||
version = "0.0.1"
|
||||
source = "git+https://github.com/antoyo/gccjit.rs#2d4fea7319f80531b2e5d264fca9f1c498a3a62e"
|
||||
source = "git+https://github.com/antoyo/gccjit.rs#0672b78d162d65b6f36ea4062947253affe9fdef"
|
||||
dependencies = [
|
||||
"libc 0.1.12",
|
||||
]
|
||||
@ -85,33 +70,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc 0.2.102",
|
||||
"libc 0.2.112",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.11.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.1.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
|
||||
dependencies = [
|
||||
"libc 0.2.102",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"hashbrown",
|
||||
"libc 0.2.112",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -122,7 +91,7 @@ checksum = "96bd995a092cac79868250589869b5a5d656b02a02bd74c8ebdc566dc7203090"
|
||||
dependencies = [
|
||||
"fm",
|
||||
"getopts",
|
||||
"libc 0.2.102",
|
||||
"libc 0.2.112",
|
||||
"num_cpus",
|
||||
"termcolor",
|
||||
"threadpool",
|
||||
@ -138,9 +107,9 @@ checksum = "e32a70cf75e5846d53a673923498228bbec6a8624708a9ea5645f075d6276122"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.102"
|
||||
version = "0.2.112"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2a5ac8f984bfcf3a823267e5fde638acc3325f6496633a5da6bb6eb2171e103"
|
||||
checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
@ -155,25 +124,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc 0.2.102",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.25.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a38f2be3697a57b4060074ff41b44c16870d916ad7877c17696e063257482bc7"
|
||||
dependencies = [
|
||||
"crc32fast",
|
||||
"indexmap",
|
||||
"memchr",
|
||||
"libc 0.2.112",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.10"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
|
||||
checksum = "ed0cfbc8191465bed66e1718596ee0b0b35d5ee1f41c5df2189d0fe8bde535ba"
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
@ -181,7 +139,7 @@ version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8"
|
||||
dependencies = [
|
||||
"libc 0.2.102",
|
||||
"libc 0.2.112",
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
"rand_hc",
|
||||
@ -257,7 +215,6 @@ dependencies = [
|
||||
"ar",
|
||||
"gccjit",
|
||||
"lang_tester",
|
||||
"object",
|
||||
"target-lexicon",
|
||||
"tempfile",
|
||||
]
|
||||
@ -284,7 +241,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc 0.2.102",
|
||||
"libc 0.2.112",
|
||||
"rand",
|
||||
"redox_syscall",
|
||||
"remove_dir_all",
|
||||
@ -321,7 +278,7 @@ version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6"
|
||||
dependencies = [
|
||||
"libc 0.2.102",
|
||||
"libc 0.2.112",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -23,11 +23,6 @@ target-lexicon = "0.10.0"
|
||||
|
||||
ar = "0.8.0"
|
||||
|
||||
[dependencies.object]
|
||||
version = "0.25.0"
|
||||
default-features = false
|
||||
features = ["read", "std", "write"] # We don't need WASM support.
|
||||
|
||||
[dev-dependencies]
|
||||
lang_tester = "0.3.9"
|
||||
tempfile = "3.1.0"
|
||||
|
@ -111,6 +111,8 @@ Or add a breakpoint to `add_error` in gdb and print the line number using:
|
||||
p loc->m_line
|
||||
```
|
||||
|
||||
To get the `rustc` command to run in `gdb`, add the `--verbose` flag to `cargo build`.
|
||||
|
||||
### How to use a custom-build rustc
|
||||
|
||||
* Build the stage2 compiler (`rustup toolchain link debug-current build/x86_64-unknown-linux-gnu/stage2`).
|
||||
|
@ -46,4 +46,24 @@ index 4bc44e9..8e3c7a4 100644
|
||||
|
||||
#[test]
|
||||
fn cell_allows_array_cycle() {
|
||||
diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs
|
||||
index 3e00e0a..8e5663b 100644
|
||||
--- a/library/core/tests/slice.rs
|
||||
+++ b/library/core/tests/slice.rs
|
||||
@@ -2108,6 +2108,7 @@ fn test_copy_within_panics_src_out_of_bounds() {
|
||||
bytes.copy_within(usize::MAX..=usize::MAX, 0);
|
||||
}
|
||||
|
||||
+/*
|
||||
#[test]
|
||||
fn test_is_sorted() {
|
||||
let empty: [i32; 0] = [];
|
||||
@@ -2122,6 +2123,7 @@ fn test_is_sorted() {
|
||||
assert!(!["c", "bb", "aaa"].is_sorted());
|
||||
assert!(["c", "bb", "aaa"].is_sorted_by_key(|s| s.len()));
|
||||
}
|
||||
+*/
|
||||
|
||||
#[test]
|
||||
fn test_slice_run_destructors() {
|
||||
-- 2.21.0 (Apple Git-122)
|
||||
|
@ -0,0 +1,24 @@
|
||||
From b1ae000f6da1abd3b8e9b80c40bc11c89b8ae93c Mon Sep 17 00:00:00 2001
|
||||
From: bjorn3 <bjorn3@users.noreply.github.com>
|
||||
Date: Thu, 30 Dec 2021 16:54:40 +0100
|
||||
Subject: [PATCH] [core] Disable portable-simd test
|
||||
|
||||
---
|
||||
library/core/tests/lib.rs | 1 -
|
||||
1 file changed, 1 deletion(-)
|
||||
|
||||
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
|
||||
index ec70034..7cd9e21 100644
|
||||
--- a/library/core/tests/lib.rs
|
||||
+++ b/library/core/tests/lib.rs
|
||||
@@ -121,7 +121,6 @@ mod pattern;
|
||||
mod pin;
|
||||
mod ptr;
|
||||
mod result;
|
||||
-mod simd;
|
||||
mod slice;
|
||||
mod str;
|
||||
mod str_lossy;
|
||||
--
|
||||
2.26.2.7.g19db9cfb68
|
||||
|
@ -0,0 +1,30 @@
|
||||
From 0ffdd8eda8df364391c8ac6e1ce92c73ba9254d4 Mon Sep 17 00:00:00 2001
|
||||
From: bjorn3 <bjorn3@users.noreply.github.com>
|
||||
Date: Fri, 3 Dec 2021 12:16:30 +0100
|
||||
Subject: [PATCH] Disable long running tests
|
||||
|
||||
---
|
||||
library/core/tests/slice.rs | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs
|
||||
index 2c8f00a..44847ee 100644
|
||||
--- a/library/core/tests/slice.rs
|
||||
+++ b/library/core/tests/slice.rs
|
||||
@@ -2332,7 +2332,8 @@ macro_rules! empty_max_mut {
|
||||
};
|
||||
}
|
||||
|
||||
+/*
|
||||
#[cfg(not(miri))] // Comparing usize::MAX many elements takes forever in Miri (and in rustc without optimizations)
|
||||
take_tests! {
|
||||
slice: &[(); usize::MAX], method: take,
|
||||
(take_in_bounds_max_range_to, (..usize::MAX), Some(EMPTY_MAX), &[(); 0]),
|
||||
@@ -2345,3 +2347,4 @@ take_tests! {
|
||||
(take_mut_oob_max_range_to_inclusive, (..=usize::MAX), None, empty_max_mut!()),
|
||||
(take_mut_in_bounds_max_range_from, (usize::MAX..), Some(&mut [] as _), empty_max_mut!()),
|
||||
}
|
||||
+*/
|
||||
--
|
||||
2.26.2.7.g19db9cfb68
|
||||
|
@ -1 +1 @@
|
||||
nightly-2021-09-28
|
||||
nightly-2021-12-30
|
||||
|
@ -18,30 +18,30 @@ use crate::type_of::LayoutGccExt;
|
||||
|
||||
// Rust asm! and GCC Extended Asm semantics differ substantially.
|
||||
//
|
||||
// 1. Rust asm operands go along as one list of operands. Operands themselves indicate
|
||||
// if they're "in" or "out". "In" and "out" operands can interleave. One operand can be
|
||||
// 1. Rust asm operands go along as one list of operands. Operands themselves indicate
|
||||
// if they're "in" or "out". "In" and "out" operands can interleave. One operand can be
|
||||
// both "in" and "out" (`inout(reg)`).
|
||||
//
|
||||
// GCC asm has two different lists for "in" and "out" operands. In terms of gccjit,
|
||||
// this means that all "out" operands must go before "in" operands. "In" and "out" operands
|
||||
// GCC asm has two different lists for "in" and "out" operands. In terms of gccjit,
|
||||
// this means that all "out" operands must go before "in" operands. "In" and "out" operands
|
||||
// cannot interleave.
|
||||
//
|
||||
// 2. Operand lists in both Rust and GCC are indexed. Index starts from 0. Indexes are important
|
||||
// 2. Operand lists in both Rust and GCC are indexed. Index starts from 0. Indexes are important
|
||||
// because the asm template refers to operands by index.
|
||||
//
|
||||
// Mapping from Rust to GCC index would be 1-1 if it wasn't for...
|
||||
//
|
||||
// 3. Clobbers. GCC has a separate list of clobbers, and clobbers don't have indexes.
|
||||
// Contrary, Rust expresses clobbers through "out" operands that aren't tied to
|
||||
// 3. Clobbers. GCC has a separate list of clobbers, and clobbers don't have indexes.
|
||||
// Contrary, Rust expresses clobbers through "out" operands that aren't tied to
|
||||
// a variable (`_`), and such "clobbers" do have index.
|
||||
//
|
||||
// 4. Furthermore, GCC Extended Asm does not support explicit register constraints
|
||||
// (like `out("eax")`) directly, offering so-called "local register variables"
|
||||
// as a workaround. These variables need to be declared and initialized *before*
|
||||
// the Extended Asm block but *after* normal local variables
|
||||
// 4. Furthermore, GCC Extended Asm does not support explicit register constraints
|
||||
// (like `out("eax")`) directly, offering so-called "local register variables"
|
||||
// as a workaround. These variables need to be declared and initialized *before*
|
||||
// the Extended Asm block but *after* normal local variables
|
||||
// (see comment in `codegen_inline_asm` for explanation).
|
||||
//
|
||||
// With that in mind, let's see how we translate Rust syntax to GCC
|
||||
// With that in mind, let's see how we translate Rust syntax to GCC
|
||||
// (from now on, `CC` stands for "constraint code"):
|
||||
//
|
||||
// * `out(reg_class) var` -> translated to output operand: `"=CC"(var)`
|
||||
@ -52,18 +52,17 @@ use crate::type_of::LayoutGccExt;
|
||||
//
|
||||
// * `out("explicit register") _` -> not translated to any operands, register is simply added to clobbers list
|
||||
//
|
||||
// * `inout(reg_class) in_var => out_var` -> translated to two operands:
|
||||
// * `inout(reg_class) in_var => out_var` -> translated to two operands:
|
||||
// output: `"=CC"(in_var)`
|
||||
// input: `"num"(out_var)` where num is the GCC index
|
||||
// input: `"num"(out_var)` where num is the GCC index
|
||||
// of the corresponding output operand
|
||||
//
|
||||
// * `inout(reg_class) in_var => _` -> same as `inout(reg_class) in_var => tmp`,
|
||||
// * `inout(reg_class) in_var => _` -> same as `inout(reg_class) in_var => tmp`,
|
||||
// where "tmp" is a temporary unused variable
|
||||
//
|
||||
// * `out/in/inout("explicit register") var` -> translated to one or two operands as described above
|
||||
// with `"r"(var)` constraint,
|
||||
// * `out/in/inout("explicit register") var` -> translated to one or two operands as described above
|
||||
// with `"r"(var)` constraint,
|
||||
// and one register variable assigned to the desired register.
|
||||
//
|
||||
|
||||
const ATT_SYNTAX_INS: &str = ".att_syntax noprefix\n\t";
|
||||
const INTEL_SYNTAX_INS: &str = "\n\t.intel_syntax noprefix";
|
||||
@ -131,7 +130,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
|
||||
let att_dialect = is_x86 && options.contains(InlineAsmOptions::ATT_SYNTAX);
|
||||
let intel_dialect = is_x86 && !options.contains(InlineAsmOptions::ATT_SYNTAX);
|
||||
|
||||
// GCC index of an output operand equals its position in the array
|
||||
// GCC index of an output operand equals its position in the array
|
||||
let mut outputs = vec![];
|
||||
|
||||
// GCC index of an input operand equals its position in the array
|
||||
@ -145,9 +144,9 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
|
||||
let mut constants_len = 0;
|
||||
|
||||
// There are rules we must adhere to if we want GCC to do the right thing:
|
||||
//
|
||||
//
|
||||
// * Every local variable that the asm block uses as an output must be declared *before*
|
||||
// the asm block.
|
||||
// the asm block.
|
||||
// * There must be no instructions whatsoever between the register variables and the asm.
|
||||
//
|
||||
// Therefore, the backend must generate the instructions strictly in this order:
|
||||
@ -159,7 +158,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
|
||||
// We also must make sure that no input operands are emitted before output operands.
|
||||
//
|
||||
// This is why we work in passes, first emitting local vars, then local register vars.
|
||||
// Also, we don't emit any asm operands immediately; we save them to
|
||||
// Also, we don't emit any asm operands immediately; we save them to
|
||||
// the one of the buffers to be emitted later.
|
||||
|
||||
// 1. Normal variables (and saving operands to buffers).
|
||||
@ -172,7 +171,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
|
||||
(Constraint(constraint), Some(place)) => (constraint, place.layout.gcc_type(self.cx, false)),
|
||||
// When `reg` is a class and not an explicit register but the out place is not specified,
|
||||
// we need to create an unused output variable to assign the output to. This var
|
||||
// needs to be of a type that's "compatible" with the register class, but specific type
|
||||
// needs to be of a type that's "compatible" with the register class, but specific type
|
||||
// doesn't matter.
|
||||
(Constraint(constraint), None) => (constraint, dummy_output_type(self.cx, reg.reg_class())),
|
||||
(Register(_), Some(_)) => {
|
||||
@ -200,7 +199,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
|
||||
|
||||
let tmp_var = self.current_func().new_local(None, ty, "output_register");
|
||||
outputs.push(AsmOutOperand {
|
||||
constraint,
|
||||
constraint,
|
||||
rust_idx,
|
||||
late,
|
||||
readwrite: false,
|
||||
@ -211,12 +210,12 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
|
||||
|
||||
InlineAsmOperandRef::In { reg, value } => {
|
||||
if let ConstraintOrRegister::Constraint(constraint) = reg_to_gcc(reg) {
|
||||
inputs.push(AsmInOperand {
|
||||
constraint: Cow::Borrowed(constraint),
|
||||
rust_idx,
|
||||
inputs.push(AsmInOperand {
|
||||
constraint: Cow::Borrowed(constraint),
|
||||
rust_idx,
|
||||
val: value.immediate()
|
||||
});
|
||||
}
|
||||
}
|
||||
else {
|
||||
// left for the next pass
|
||||
continue
|
||||
@ -226,7 +225,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
|
||||
InlineAsmOperandRef::InOut { reg, late, in_value, out_place } => {
|
||||
let constraint = if let ConstraintOrRegister::Constraint(constraint) = reg_to_gcc(reg) {
|
||||
constraint
|
||||
}
|
||||
}
|
||||
else {
|
||||
// left for the next pass
|
||||
continue
|
||||
@ -235,22 +234,22 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
|
||||
// Rustc frontend guarantees that input and output types are "compatible",
|
||||
// so we can just use input var's type for the output variable.
|
||||
//
|
||||
// This decision is also backed by the fact that LLVM needs in and out
|
||||
// values to be of *exactly the same type*, not just "compatible".
|
||||
// This decision is also backed by the fact that LLVM needs in and out
|
||||
// values to be of *exactly the same type*, not just "compatible".
|
||||
// I'm not sure if GCC is so picky too, but better safe than sorry.
|
||||
let ty = in_value.layout.gcc_type(self.cx, false);
|
||||
let tmp_var = self.current_func().new_local(None, ty, "output_register");
|
||||
|
||||
// If the out_place is None (i.e `inout(reg) _` syntax was used), we translate
|
||||
// it to one "readwrite (+) output variable", otherwise we translate it to two
|
||||
// it to one "readwrite (+) output variable", otherwise we translate it to two
|
||||
// "out and tied in" vars as described above.
|
||||
let readwrite = out_place.is_none();
|
||||
outputs.push(AsmOutOperand {
|
||||
constraint,
|
||||
constraint,
|
||||
rust_idx,
|
||||
late,
|
||||
readwrite,
|
||||
tmp_var,
|
||||
tmp_var,
|
||||
out_place,
|
||||
});
|
||||
|
||||
@ -259,8 +258,8 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
|
||||
let constraint = Cow::Owned(out_gcc_idx.to_string());
|
||||
|
||||
inputs.push(AsmInOperand {
|
||||
constraint,
|
||||
rust_idx,
|
||||
constraint,
|
||||
rust_idx,
|
||||
val: in_value.immediate()
|
||||
});
|
||||
}
|
||||
@ -287,7 +286,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
|
||||
if let ConstraintOrRegister::Register(reg_name) = reg_to_gcc(reg) {
|
||||
let out_place = if let Some(place) = place {
|
||||
place
|
||||
}
|
||||
}
|
||||
else {
|
||||
// processed in the previous pass
|
||||
continue
|
||||
@ -298,7 +297,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
|
||||
tmp_var.set_register_name(reg_name);
|
||||
|
||||
outputs.push(AsmOutOperand {
|
||||
constraint: "r".into(),
|
||||
constraint: "r".into(),
|
||||
rust_idx,
|
||||
late,
|
||||
readwrite: false,
|
||||
@ -318,9 +317,9 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
|
||||
reg_var.set_register_name(reg_name);
|
||||
self.llbb().add_assignment(None, reg_var, value.immediate());
|
||||
|
||||
inputs.push(AsmInOperand {
|
||||
constraint: "r".into(),
|
||||
rust_idx,
|
||||
inputs.push(AsmInOperand {
|
||||
constraint: "r".into(),
|
||||
rust_idx,
|
||||
val: reg_var.to_rvalue()
|
||||
});
|
||||
}
|
||||
@ -331,31 +330,23 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
|
||||
// `inout("explicit register") in_var => out_var`
|
||||
InlineAsmOperandRef::InOut { reg, late, in_value, out_place } => {
|
||||
if let ConstraintOrRegister::Register(reg_name) = reg_to_gcc(reg) {
|
||||
let out_place = if let Some(place) = out_place {
|
||||
place
|
||||
}
|
||||
else {
|
||||
// processed in the previous pass
|
||||
continue
|
||||
};
|
||||
|
||||
// See explanation in the first pass.
|
||||
let ty = in_value.layout.gcc_type(self.cx, false);
|
||||
let tmp_var = self.current_func().new_local(None, ty, "output_register");
|
||||
tmp_var.set_register_name(reg_name);
|
||||
|
||||
outputs.push(AsmOutOperand {
|
||||
constraint: "r".into(),
|
||||
constraint: "r".into(),
|
||||
rust_idx,
|
||||
late,
|
||||
readwrite: false,
|
||||
tmp_var,
|
||||
out_place: Some(out_place)
|
||||
out_place,
|
||||
});
|
||||
|
||||
let constraint = Cow::Owned((outputs.len() - 1).to_string());
|
||||
inputs.push(AsmInOperand {
|
||||
constraint,
|
||||
inputs.push(AsmInOperand {
|
||||
constraint,
|
||||
rust_idx,
|
||||
val: in_value.immediate()
|
||||
});
|
||||
@ -364,8 +355,8 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
|
||||
// processed in the previous pass
|
||||
}
|
||||
|
||||
InlineAsmOperandRef::Const { .. }
|
||||
| InlineAsmOperandRef::SymFn { .. }
|
||||
InlineAsmOperandRef::Const { .. }
|
||||
| InlineAsmOperandRef::SymFn { .. }
|
||||
| InlineAsmOperandRef::SymStatic { .. } => {
|
||||
// processed in the previous pass
|
||||
}
|
||||
@ -460,7 +451,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
|
||||
if !intel_dialect {
|
||||
template_str.push_str(INTEL_SYNTAX_INS);
|
||||
}
|
||||
|
||||
|
||||
// 4. Generate Extended Asm block
|
||||
|
||||
let block = self.llbb();
|
||||
@ -479,7 +470,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
|
||||
}
|
||||
|
||||
if !options.contains(InlineAsmOptions::PRESERVES_FLAGS) {
|
||||
// TODO(@Commeownist): I'm not 100% sure this one clobber is sufficient
|
||||
// TODO(@Commeownist): I'm not 100% sure this one clobber is sufficient
|
||||
// on all architectures. For instance, what about FP stack?
|
||||
extended_asm.add_clobber("cc");
|
||||
}
|
||||
@ -498,10 +489,10 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
|
||||
self.call(self.type_void(), builtin_unreachable, &[], None);
|
||||
}
|
||||
|
||||
// Write results to outputs.
|
||||
// Write results to outputs.
|
||||
//
|
||||
// We need to do this because:
|
||||
// 1. Turning `PlaceRef` into `RValue` is error-prone and has nasty edge cases
|
||||
// 1. Turning `PlaceRef` into `RValue` is error-prone and has nasty edge cases
|
||||
// (especially with current `rustc_backend_ssa` API).
|
||||
// 2. Not every output operand has an `out_place`, and it's required by `add_output_operand`.
|
||||
//
|
||||
@ -509,7 +500,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
|
||||
// generates `out_place = tmp_var;` assignments if out_place exists.
|
||||
for op in &outputs {
|
||||
if let Some(place) = op.out_place {
|
||||
OperandValue::Immediate(op.tmp_var.to_rvalue()).store(self, place);
|
||||
OperandValue::Immediate(op.tmp_var.to_rvalue()).store(self, place);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
use std::fs;
|
||||
use std::{env, fs};
|
||||
|
||||
use gccjit::OutputKind;
|
||||
use rustc_codegen_ssa::{CompiledModule, ModuleCodegen};
|
||||
@ -42,17 +42,17 @@ pub(crate) unsafe fn codegen(cgcx: &CodegenContext<GccCodegenBackend>, _diag_han
|
||||
let _timer = cgcx
|
||||
.prof
|
||||
.generic_activity_with_arg("LLVM_module_codegen_emit_obj", &*module.name);
|
||||
match &*module.name {
|
||||
"std_example.7rcbfp3g-cgu.15" => {
|
||||
println!("Dumping reproducer {}", module.name);
|
||||
let _ = fs::create_dir("/tmp/reproducers");
|
||||
// FIXME(antoyo): segfault in dump_reproducer_to_file() might be caused by
|
||||
// transmuting an rvalue to an lvalue.
|
||||
// Segfault is actually in gcc::jit::reproducer::get_identifier_as_lvalue
|
||||
context.dump_reproducer_to_file(&format!("/tmp/reproducers/{}.c", module.name));
|
||||
println!("Dumped reproducer {}", module.name);
|
||||
},
|
||||
_ => (),
|
||||
if env::var("CG_GCCJIT_DUMP_MODULE_NAMES").as_deref() == Ok("1") {
|
||||
println!("Module {}", module.name);
|
||||
}
|
||||
if env::var("CG_GCCJIT_DUMP_MODULE").as_deref() == Ok(&module.name) {
|
||||
println!("Dumping reproducer {}", module.name);
|
||||
let _ = fs::create_dir("/tmp/reproducers");
|
||||
// FIXME(antoyo): segfault in dump_reproducer_to_file() might be caused by
|
||||
// transmuting an rvalue to an lvalue.
|
||||
// Segfault is actually in gcc::jit::reproducer::get_identifier_as_lvalue
|
||||
context.dump_reproducer_to_file(&format!("/tmp/reproducers/{}.c", module.name));
|
||||
println!("Dumped reproducer {}", module.name);
|
||||
}
|
||||
context.compile_to_file(OutputKind::ObjectFile, obj_out.to_str().expect("path to str"));
|
||||
}
|
||||
|
@ -81,7 +81,10 @@ pub fn compile_codegen_unit<'tcx>(tcx: TyCtxt<'tcx>, cgu_name: Symbol) -> (Modul
|
||||
for arg in &tcx.sess.opts.cg.llvm_args {
|
||||
context.add_command_line_option(arg);
|
||||
}
|
||||
// NOTE: an optimization (https://github.com/rust-lang/rustc_codegen_gcc/issues/53).
|
||||
context.add_command_line_option("-fno-semantic-interposition");
|
||||
// NOTE: Rust relies on LLVM not doing TBAA (https://github.com/rust-lang/unsafe-code-guidelines/issues/292).
|
||||
context.add_command_line_option("-fno-strict-aliasing");
|
||||
if env::var("CG_GCCJIT_DUMP_CODE").as_deref() == Ok("1") {
|
||||
context.set_dump_code_on_compile(true);
|
||||
}
|
||||
|
@ -200,7 +200,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
||||
fn check_ptr_call<'b>(&mut self, _typ: &str, func_ptr: RValue<'gcc>, args: &'b [RValue<'gcc>]) -> Cow<'b, [RValue<'gcc>]> {
|
||||
let mut all_args_match = true;
|
||||
let mut param_types = vec![];
|
||||
let gcc_func = func_ptr.get_type().is_function_ptr_type().expect("function ptr");
|
||||
let gcc_func = func_ptr.get_type().dyncast_function_ptr_type().expect("function ptr");
|
||||
for (index, arg) in args.iter().enumerate().take(gcc_func.get_param_count()) {
|
||||
let param = gcc_func.get_param_type(index);
|
||||
if param != arg.get_type() {
|
||||
@ -277,7 +277,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
||||
|
||||
// gccjit requires to use the result of functions, even when it's not used.
|
||||
// That's why we assign the result to a local or call add_eval().
|
||||
let gcc_func = func_ptr.get_type().is_function_ptr_type().expect("function ptr");
|
||||
let gcc_func = func_ptr.get_type().dyncast_function_ptr_type().expect("function ptr");
|
||||
let mut return_type = gcc_func.get_return_type();
|
||||
let current_block = self.current_block.borrow().expect("block");
|
||||
let void_type = self.context.new_type::<()>();
|
||||
@ -605,22 +605,17 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
|
||||
}
|
||||
|
||||
fn and(&mut self, a: RValue<'gcc>, mut b: RValue<'gcc>) -> RValue<'gcc> {
|
||||
// FIXME(antoyo): hack by putting the result in a variable to workaround this bug:
|
||||
// https://gcc.gnu.org/bugzilla//show_bug.cgi?id=95498
|
||||
if a.get_type() != b.get_type() {
|
||||
b = self.context.new_cast(None, b, a.get_type());
|
||||
}
|
||||
let res = self.current_func().new_local(None, b.get_type(), "andResult");
|
||||
self.llbb().add_assignment(None, res, a & b);
|
||||
res.to_rvalue()
|
||||
a & b
|
||||
}
|
||||
|
||||
fn or(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
|
||||
// FIXME(antoyo): hack by putting the result in a variable to workaround this bug:
|
||||
// https://gcc.gnu.org/bugzilla//show_bug.cgi?id=95498
|
||||
let res = self.current_func().new_local(None, b.get_type(), "orResult");
|
||||
self.llbb().add_assignment(None, res, a | b);
|
||||
res.to_rvalue()
|
||||
fn or(&mut self, a: RValue<'gcc>, mut b: RValue<'gcc>) -> RValue<'gcc> {
|
||||
if a.get_type() != b.get_type() {
|
||||
b = self.context.new_cast(None, b, a.get_type());
|
||||
}
|
||||
a | b
|
||||
}
|
||||
|
||||
fn xor(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
|
||||
@ -628,8 +623,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
|
||||
}
|
||||
|
||||
fn neg(&mut self, a: RValue<'gcc>) -> RValue<'gcc> {
|
||||
// TODO(antoyo): use new_unary_op()?
|
||||
self.cx.context.new_rvalue_from_long(a.get_type(), 0) - a
|
||||
self.cx.context.new_unary_op(None, UnaryOp::Minus, a.get_type(), a)
|
||||
}
|
||||
|
||||
fn fneg(&mut self, a: RValue<'gcc>) -> RValue<'gcc> {
|
||||
@ -816,7 +810,10 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
|
||||
let atomic_load = self.context.get_builtin_function(&format!("__atomic_load_{}", size.bytes()));
|
||||
let ordering = self.context.new_rvalue_from_int(self.i32_type, order.to_gcc());
|
||||
|
||||
let volatile_const_void_ptr_type = self.context.new_type::<*mut ()>().make_const().make_volatile();
|
||||
let volatile_const_void_ptr_type = self.context.new_type::<()>()
|
||||
.make_const()
|
||||
.make_volatile()
|
||||
.make_pointer();
|
||||
let ptr = self.context.new_cast(None, ptr, volatile_const_void_ptr_type);
|
||||
self.context.new_call(None, atomic_load, &[ptr, ordering])
|
||||
}
|
||||
@ -941,7 +938,9 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
|
||||
// TODO(antoyo): handle alignment.
|
||||
let atomic_store = self.context.get_builtin_function(&format!("__atomic_store_{}", size.bytes()));
|
||||
let ordering = self.context.new_rvalue_from_int(self.i32_type, order.to_gcc());
|
||||
let volatile_const_void_ptr_type = self.context.new_type::<*mut ()>().make_const().make_volatile();
|
||||
let volatile_const_void_ptr_type = self.context.new_type::<()>()
|
||||
.make_volatile()
|
||||
.make_pointer();
|
||||
let ptr = self.context.new_cast(None, ptr, volatile_const_void_ptr_type);
|
||||
|
||||
// FIXME(antoyo): fix libgccjit to allow comparing an integer type with an aligned integer type because
|
||||
@ -981,12 +980,12 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
|
||||
assert_eq!(idx as usize as u64, idx);
|
||||
let value = ptr.dereference(None).to_rvalue();
|
||||
|
||||
if value_type.is_array().is_some() {
|
||||
if value_type.dyncast_array().is_some() {
|
||||
let index = self.context.new_rvalue_from_long(self.u64_type, i64::try_from(idx).expect("i64::try_from"));
|
||||
let element = self.context.new_array_access(None, value, index);
|
||||
element.get_address(None)
|
||||
}
|
||||
else if let Some(vector_type) = value_type.is_vector() {
|
||||
else if let Some(vector_type) = value_type.dyncast_vector() {
|
||||
let array_type = vector_type.get_element_type().make_pointer();
|
||||
let array = self.bitcast(ptr, array_type);
|
||||
let index = self.context.new_rvalue_from_long(self.u64_type, i64::try_from(idx).expect("i64::try_from"));
|
||||
@ -1009,7 +1008,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
|
||||
|
||||
fn sext(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
|
||||
// TODO(antoyo): check that it indeed sign extend the value.
|
||||
if dest_ty.is_vector().is_some() {
|
||||
if dest_ty.dyncast_vector().is_some() {
|
||||
// TODO(antoyo): nothing to do as it is only for LLVM?
|
||||
return value;
|
||||
}
|
||||
@ -1081,7 +1080,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
|
||||
let right_type = rhs.get_type();
|
||||
if left_type != right_type {
|
||||
// NOTE: because libgccjit cannot compare function pointers.
|
||||
if left_type.is_function_ptr_type().is_some() && right_type.is_function_ptr_type().is_some() {
|
||||
if left_type.dyncast_function_ptr_type().is_some() && right_type.dyncast_function_ptr_type().is_some() {
|
||||
lhs = self.context.new_cast(None, lhs, self.usize_type.make_pointer());
|
||||
rhs = self.context.new_cast(None, rhs, self.usize_type.make_pointer());
|
||||
}
|
||||
@ -1189,12 +1188,12 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
|
||||
assert_eq!(idx as usize as u64, idx);
|
||||
let value_type = aggregate_value.get_type();
|
||||
|
||||
if value_type.is_array().is_some() {
|
||||
if value_type.dyncast_array().is_some() {
|
||||
let index = self.context.new_rvalue_from_long(self.u64_type, i64::try_from(idx).expect("i64::try_from"));
|
||||
let element = self.context.new_array_access(None, aggregate_value, index);
|
||||
element.get_address(None)
|
||||
}
|
||||
else if value_type.is_vector().is_some() {
|
||||
else if value_type.dyncast_vector().is_some() {
|
||||
panic!();
|
||||
}
|
||||
else if let Some(pointer_type) = value_type.get_pointee() {
|
||||
@ -1221,11 +1220,11 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
|
||||
let value_type = aggregate_value.get_type();
|
||||
|
||||
let lvalue =
|
||||
if value_type.is_array().is_some() {
|
||||
if value_type.dyncast_array().is_some() {
|
||||
let index = self.context.new_rvalue_from_long(self.u64_type, i64::try_from(idx).expect("i64::try_from"));
|
||||
self.context.new_array_access(None, aggregate_value, index)
|
||||
}
|
||||
else if value_type.is_vector().is_some() {
|
||||
else if value_type.dyncast_vector().is_some() {
|
||||
panic!();
|
||||
}
|
||||
else if let Some(pointer_type) = value_type.get_pointee() {
|
||||
|
@ -1,5 +1,4 @@
|
||||
use std::convert::TryFrom;
|
||||
use std::convert::TryInto;
|
||||
|
||||
use gccjit::LValue;
|
||||
use gccjit::{Block, CType, RValue, Type, ToRValue};
|
||||
@ -44,7 +43,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
||||
let string = self.context.new_string_literal(&*string);
|
||||
let sym = self.generate_local_symbol_name("str");
|
||||
let global = self.declare_private_global(&sym, self.val_ty(string));
|
||||
global.global_set_initializer_value(string);
|
||||
global.global_set_initializer_rvalue(string);
|
||||
global
|
||||
// TODO(antoyo): set linkage.
|
||||
}
|
||||
@ -79,7 +78,7 @@ pub fn bytes_in_context<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, bytes: &[u8]) ->
|
||||
bytes.iter()
|
||||
.map(|&byte| context.new_rvalue_from_int(byte_type, byte as i32))
|
||||
.collect();
|
||||
context.new_rvalue_from_array(None, typ, &elements)
|
||||
context.new_array_constructor(None, typ, &elements)
|
||||
}
|
||||
|
||||
pub fn type_is_pointer<'gcc>(typ: Type<'gcc>) -> bool {
|
||||
@ -120,13 +119,6 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
||||
}
|
||||
|
||||
fn const_uint_big(&self, typ: Type<'gcc>, num: u128) -> RValue<'gcc> {
|
||||
let num64: Result<i64, _> = num.try_into();
|
||||
if let Ok(num) = num64 {
|
||||
// FIXME(antoyo): workaround for a bug where libgccjit is expecting a constant.
|
||||
// The operations >> 64 and | low are making the normal case a non-constant.
|
||||
return self.context.new_rvalue_from_long(typ, num as i64);
|
||||
}
|
||||
|
||||
if num >> 64 != 0 {
|
||||
// FIXME(antoyo): use a new function new_rvalue_from_unsigned_long()?
|
||||
let low = self.context.new_rvalue_from_long(self.u64_type, num as u64 as i64);
|
||||
@ -193,7 +185,7 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
||||
// TODO(antoyo): cache the type? It's anonymous, so probably not.
|
||||
let typ = self.type_struct(&fields, packed);
|
||||
let struct_type = typ.is_struct().expect("struct type");
|
||||
self.context.new_rvalue_from_struct(None, struct_type, values)
|
||||
self.context.new_struct_constructor(None, struct_type.as_type(), None, values)
|
||||
}
|
||||
|
||||
fn const_to_opt_uint(&self, _v: RValue<'gcc>) -> Option<u64> {
|
||||
|
@ -20,7 +20,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
||||
pub fn const_bitcast(&self, value: RValue<'gcc>, typ: Type<'gcc>) -> RValue<'gcc> {
|
||||
if value.get_type() == self.bool_type.make_pointer() {
|
||||
if let Some(pointee) = typ.get_pointee() {
|
||||
if pointee.is_vector().is_some() {
|
||||
if pointee.dyncast_vector().is_some() {
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
@ -31,9 +31,13 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
||||
|
||||
impl<'gcc, 'tcx> StaticMethods for CodegenCx<'gcc, 'tcx> {
|
||||
fn static_addr_of(&self, cv: RValue<'gcc>, align: Align, kind: Option<&str>) -> RValue<'gcc> {
|
||||
if let Some(global_value) = self.const_globals.borrow().get(&cv) {
|
||||
// TODO(antoyo): upgrade alignment.
|
||||
return *global_value;
|
||||
// TODO(antoyo): implement a proper rvalue comparison in libgccjit instead of doing the
|
||||
// following:
|
||||
for (value, variable) in &*self.const_globals.borrow() {
|
||||
if format!("{:?}", value) == format!("{:?}", cv) {
|
||||
// TODO(antoyo): upgrade alignment.
|
||||
return *variable;
|
||||
}
|
||||
}
|
||||
let global_value = self.static_addr_of_mut(cv, align, kind);
|
||||
// TODO(antoyo): set global constant.
|
||||
@ -77,7 +81,7 @@ impl<'gcc, 'tcx> StaticMethods for CodegenCx<'gcc, 'tcx> {
|
||||
else {
|
||||
value
|
||||
};
|
||||
global.global_set_initializer_value(value);
|
||||
global.global_set_initializer_rvalue(value);
|
||||
|
||||
// As an optimization, all shared statics which do not have interior
|
||||
// mutability are placed into read-only memory.
|
||||
@ -176,7 +180,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
||||
};
|
||||
// FIXME(antoyo): I think the name coming from generate_local_symbol_name() above cannot be used
|
||||
// globally.
|
||||
global.global_set_initializer_value(cv);
|
||||
global.global_set_initializer_rvalue(cv);
|
||||
// TODO(antoyo): set unnamed address.
|
||||
global.get_address(None)
|
||||
}
|
||||
@ -371,7 +375,7 @@ fn check_and_apply_linkage<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, attrs: &Codeg
|
||||
real_name.push_str(&sym);
|
||||
let global2 = cx.define_global(&real_name, llty, is_tls, attrs.link_section);
|
||||
// TODO(antoyo): set linkage.
|
||||
global2.global_set_initializer_value(global1.get_address(None));
|
||||
global2.global_set_initializer_rvalue(global1.get_address(None));
|
||||
// TODO(antoyo): use global_set_initializer() when it will work.
|
||||
global2
|
||||
}
|
||||
|
@ -1,16 +1,6 @@
|
||||
use std::cell::{Cell, RefCell};
|
||||
|
||||
use gccjit::{
|
||||
Block,
|
||||
Context,
|
||||
CType,
|
||||
Function,
|
||||
FunctionType,
|
||||
LValue,
|
||||
RValue,
|
||||
Struct,
|
||||
Type,
|
||||
};
|
||||
use gccjit::{Block, CType, Context, Function, FunctionType, LValue, RValue, Struct, Type};
|
||||
use rustc_codegen_ssa::base::wants_msvc_seh;
|
||||
use rustc_codegen_ssa::traits::{
|
||||
BackendTypes,
|
||||
|
@ -526,7 +526,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
||||
|
||||
let value =
|
||||
if result_type.is_signed(self.cx) {
|
||||
self.context.new_bitcast(None, value, typ)
|
||||
self.context.new_cast(None, value, typ)
|
||||
}
|
||||
else {
|
||||
value
|
||||
@ -690,7 +690,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
||||
},
|
||||
};
|
||||
|
||||
self.context.new_bitcast(None, result, result_type)
|
||||
self.context.new_cast(None, result, result_type)
|
||||
}
|
||||
|
||||
fn count_leading_zeroes(&self, width: u64, arg: RValue<'gcc>) -> RValue<'gcc> {
|
||||
@ -741,6 +741,11 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
||||
let not_low = self.context.new_unary_op(None, UnaryOp::LogicalNegate, self.u64_type, low);
|
||||
let not_low_and_not_high = not_low & not_high;
|
||||
let index = not_high + not_low_and_not_high;
|
||||
// NOTE: the following cast is necessary to avoid a GIMPLE verification failure in
|
||||
// gcc.
|
||||
// TODO(antoyo): do the correct verification in libgccjit to avoid an error at the
|
||||
// compilation stage.
|
||||
let index = self.context.new_cast(None, index, self.i32_type);
|
||||
|
||||
let res = self.context.new_array_access(None, result, index);
|
||||
|
||||
@ -764,7 +769,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
||||
let arg =
|
||||
if result_type.is_signed(self.cx) {
|
||||
let new_type = result_type.to_unsigned(self.cx);
|
||||
self.context.new_bitcast(None, arg, new_type)
|
||||
self.context.new_cast(None, arg, new_type)
|
||||
}
|
||||
else {
|
||||
arg
|
||||
@ -816,10 +821,15 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
||||
let not_high = self.context.new_unary_op(None, UnaryOp::LogicalNegate, self.u64_type, high);
|
||||
let not_low_and_not_high = not_low & not_high;
|
||||
let index = not_low + not_low_and_not_high;
|
||||
// NOTE: the following cast is necessary to avoid a GIMPLE verification failure in
|
||||
// gcc.
|
||||
// TODO(antoyo): do the correct verification in libgccjit to avoid an error at the
|
||||
// compilation stage.
|
||||
let index = self.context.new_cast(None, index, self.i32_type);
|
||||
|
||||
let res = self.context.new_array_access(None, result, index);
|
||||
|
||||
return self.context.new_bitcast(None, res, result_type);
|
||||
return self.context.new_cast(None, res, result_type);
|
||||
}
|
||||
else {
|
||||
unimplemented!("count_trailing_zeroes for {:?}", arg_type);
|
||||
@ -833,7 +843,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
||||
arg
|
||||
};
|
||||
let res = self.context.new_call(None, count_trailing_zeroes, &[arg]);
|
||||
self.context.new_bitcast(None, res, result_type)
|
||||
self.context.new_cast(None, res, result_type)
|
||||
}
|
||||
|
||||
fn int_width(&self, typ: Type<'gcc>) -> i64 {
|
||||
@ -847,7 +857,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
||||
|
||||
let value =
|
||||
if result_type.is_signed(self.cx) {
|
||||
self.context.new_bitcast(None, value, value_type)
|
||||
self.context.new_cast(None, value, value_type)
|
||||
}
|
||||
else {
|
||||
value
|
||||
@ -863,7 +873,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
||||
let low = self.context.new_cast(None, value, self.cx.ulonglong_type);
|
||||
let low = self.context.new_call(None, popcount, &[low]);
|
||||
let res = high + low;
|
||||
return self.context.new_bitcast(None, res, result_type);
|
||||
return self.context.new_cast(None, res, result_type);
|
||||
}
|
||||
|
||||
// First step.
|
||||
@ -888,7 +898,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
||||
let value = left + right;
|
||||
|
||||
if value_type.is_u8(&self.cx) {
|
||||
return self.context.new_bitcast(None, value, result_type);
|
||||
return self.context.new_cast(None, value, result_type);
|
||||
}
|
||||
|
||||
// Fourth step.
|
||||
@ -899,7 +909,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
||||
let value = left + right;
|
||||
|
||||
if value_type.is_u16(&self.cx) {
|
||||
return self.context.new_bitcast(None, value, result_type);
|
||||
return self.context.new_cast(None, value, result_type);
|
||||
}
|
||||
|
||||
// Fifth step.
|
||||
@ -910,7 +920,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
||||
let value = left + right;
|
||||
|
||||
if value_type.is_u32(&self.cx) {
|
||||
return self.context.new_bitcast(None, value, result_type);
|
||||
return self.context.new_cast(None, value, result_type);
|
||||
}
|
||||
|
||||
// Sixth step.
|
||||
@ -920,7 +930,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
|
||||
let right = shifted & mask;
|
||||
let value = left + right;
|
||||
|
||||
self.context.new_bitcast(None, value, result_type)
|
||||
self.context.new_cast(None, value, result_type)
|
||||
}
|
||||
|
||||
// Algorithm from: https://blog.regehr.org/archives/1063
|
||||
|
@ -20,7 +20,6 @@ extern crate rustc_metadata;
|
||||
extern crate rustc_middle;
|
||||
extern crate rustc_session;
|
||||
extern crate rustc_span;
|
||||
extern crate rustc_symbol_mangling;
|
||||
extern crate rustc_target;
|
||||
|
||||
// This prevents duplicating functions and statics that are already part of the host rustc process.
|
||||
@ -91,8 +90,6 @@ impl CodegenBackend for GccCodegenBackend {
|
||||
let target_cpu = target_cpu(tcx.sess);
|
||||
let res = codegen_crate(self.clone(), tcx, target_cpu.to_string(), metadata, need_metadata_module);
|
||||
|
||||
rustc_symbol_mangling::test::report_symbol_names(tcx);
|
||||
|
||||
Box::new(res)
|
||||
}
|
||||
|
||||
|
@ -122,7 +122,7 @@ impl<'gcc, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
||||
if typ.is_integral() {
|
||||
TypeKind::Integer
|
||||
}
|
||||
else if typ.is_vector().is_some() {
|
||||
else if typ.dyncast_vector().is_some() {
|
||||
TypeKind::Vector
|
||||
}
|
||||
else {
|
||||
@ -141,10 +141,10 @@ impl<'gcc, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
||||
}
|
||||
|
||||
fn element_type(&self, ty: Type<'gcc>) -> Type<'gcc> {
|
||||
if let Some(typ) = ty.is_array() {
|
||||
if let Some(typ) = ty.dyncast_array() {
|
||||
typ
|
||||
}
|
||||
else if let Some(vector_type) = ty.is_vector() {
|
||||
else if let Some(vector_type) = ty.dyncast_vector() {
|
||||
vector_type.get_element_type()
|
||||
}
|
||||
else if let Some(typ) = ty.get_pointee() {
|
||||
|
@ -3,6 +3,10 @@
|
||||
// Run-time:
|
||||
// status: 0
|
||||
|
||||
#![feature(asm_const, asm_sym)]
|
||||
|
||||
use std::arch::{asm, global_asm};
|
||||
|
||||
global_asm!("
|
||||
.global add_asm
|
||||
add_asm:
|
||||
@ -15,6 +19,16 @@ extern "C" {
|
||||
fn add_asm(a: i64, b: i64) -> i64;
|
||||
}
|
||||
|
||||
pub unsafe fn mem_cpy(dst: *mut u8, src: *const u8, len: usize) {
|
||||
asm!(
|
||||
"rep movsb",
|
||||
inout("rdi") dst => _,
|
||||
inout("rsi") src => _,
|
||||
inout("rcx") len => _,
|
||||
options(preserves_flags, nostack)
|
||||
);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
asm!("nop");
|
||||
@ -60,11 +74,11 @@ fn main() {
|
||||
}
|
||||
assert_eq!(x, 43);
|
||||
|
||||
// check inout(reg_class) x
|
||||
// check inout(reg_class) x
|
||||
let mut x: u64 = 42;
|
||||
unsafe {
|
||||
asm!("add {0}, {0}",
|
||||
inout(reg) x
|
||||
inout(reg) x
|
||||
);
|
||||
}
|
||||
assert_eq!(x, 84);
|
||||
@ -73,7 +87,7 @@ fn main() {
|
||||
let mut x: u64 = 42;
|
||||
unsafe {
|
||||
asm!("add r11, r11",
|
||||
inout("r11") x
|
||||
inout("r11") x
|
||||
);
|
||||
}
|
||||
assert_eq!(x, 84);
|
||||
@ -96,12 +110,12 @@ fn main() {
|
||||
assert_eq!(res, 7);
|
||||
assert_eq!(rem, 2);
|
||||
|
||||
// check const
|
||||
// check const
|
||||
let mut x: u64 = 42;
|
||||
unsafe {
|
||||
asm!("add {}, {}",
|
||||
inout(reg) x,
|
||||
const 1
|
||||
const 1
|
||||
);
|
||||
}
|
||||
assert_eq!(x, 43);
|
||||
@ -148,4 +162,11 @@ fn main() {
|
||||
assert_eq!(x, 42);
|
||||
|
||||
assert_eq!(unsafe { add_asm(40, 2) }, 42);
|
||||
|
||||
let array1 = [1u8, 2, 3];
|
||||
let mut array2 = [0u8, 0, 0];
|
||||
unsafe {
|
||||
mem_cpy(array2.as_mut_ptr(), array1.as_ptr(), 3);
|
||||
}
|
||||
assert_eq!(array1, array2);
|
||||
}
|
||||
|
@ -1948,7 +1948,6 @@ impl<'a> State<'a> {
|
||||
PatKind::Range(ref begin, ref end, ref end_kind) => {
|
||||
if let Some(expr) = begin {
|
||||
self.print_expr(expr);
|
||||
self.space();
|
||||
}
|
||||
match *end_kind {
|
||||
RangeEnd::Included => self.word("..."),
|
||||
|
@ -2141,12 +2141,17 @@ impl<T, A: Allocator> Vec<T, A> {
|
||||
unsafe fn split_at_spare_mut_with_len(
|
||||
&mut self,
|
||||
) -> (&mut [T], &mut [MaybeUninit<T>], &mut usize) {
|
||||
let Range { start: ptr, end: spare_ptr } = self.as_mut_ptr_range();
|
||||
let ptr = self.as_mut_ptr();
|
||||
// SAFETY:
|
||||
// - `ptr` is guaranteed to be valid for `self.len` elements
|
||||
// - but the allocation extends out to `self.buf.capacity()` elements, possibly
|
||||
// uninitialized
|
||||
let spare_ptr = unsafe { ptr.add(self.len) };
|
||||
let spare_ptr = spare_ptr.cast::<MaybeUninit<T>>();
|
||||
let spare_len = self.buf.capacity() - self.len;
|
||||
|
||||
// SAFETY:
|
||||
// - `ptr` is guaranteed to be valid for `len` elements
|
||||
// - `ptr` is guaranteed to be valid for `self.len` elements
|
||||
// - `spare_ptr` is pointing one element past the buffer, so it doesn't overlap with `initialized`
|
||||
unsafe {
|
||||
let initialized = slice::from_raw_parts_mut(ptr, self.len);
|
||||
|
@ -1140,8 +1140,8 @@ impl From<Ipv4Addr> for u32 {
|
||||
/// ```
|
||||
/// use std::net::Ipv4Addr;
|
||||
///
|
||||
/// let addr = Ipv4Addr::new(0xca, 0xfe, 0xba, 0xbe);
|
||||
/// assert_eq!(0xcafebabe, u32::from(addr));
|
||||
/// let addr = Ipv4Addr::new(0x12, 0x34, 0x56, 0x78);
|
||||
/// assert_eq!(0x12345678, u32::from(addr));
|
||||
/// ```
|
||||
#[inline]
|
||||
fn from(ip: Ipv4Addr) -> u32 {
|
||||
@ -1159,8 +1159,8 @@ impl From<u32> for Ipv4Addr {
|
||||
/// ```
|
||||
/// use std::net::Ipv4Addr;
|
||||
///
|
||||
/// let addr = Ipv4Addr::from(0xcafebabe);
|
||||
/// assert_eq!(Ipv4Addr::new(0xca, 0xfe, 0xba, 0xbe), addr);
|
||||
/// let addr = Ipv4Addr::from(0x12345678);
|
||||
/// assert_eq!(Ipv4Addr::new(0x12, 0x34, 0x56, 0x78), addr);
|
||||
/// ```
|
||||
#[inline]
|
||||
fn from(ip: u32) -> Ipv4Addr {
|
||||
|
@ -15,6 +15,42 @@ import tempfile
|
||||
|
||||
from time import time
|
||||
|
||||
# Acquire a lock on the build directory to make sure that
|
||||
# we don't cause a race condition while building
|
||||
# Lock is created in `build_dir/lock.db`
|
||||
def acquire_lock(build_dir):
|
||||
try:
|
||||
import sqlite3
|
||||
|
||||
path = os.path.join(build_dir, "lock.db")
|
||||
try:
|
||||
con = sqlite3.Connection(path, timeout=0)
|
||||
curs = con.cursor()
|
||||
curs.execute("BEGIN EXCLUSIVE")
|
||||
# The lock is released when the cursor is dropped
|
||||
return curs
|
||||
# If the database is busy then lock has already been acquired
|
||||
# so we wait for the lock.
|
||||
# We retry every quarter second so that execution is passed back to python
|
||||
# so that it can handle signals
|
||||
except sqlite3.OperationalError:
|
||||
del con
|
||||
del curs
|
||||
print("Waiting for lock on build directory")
|
||||
con = sqlite3.Connection(path, timeout=0.25)
|
||||
curs = con.cursor()
|
||||
while True:
|
||||
try:
|
||||
curs.execute("BEGIN EXCLUSIVE")
|
||||
except sqlite3.OperationalError:
|
||||
pass
|
||||
return curs
|
||||
except ImportError:
|
||||
print("warning: sqlite3 not available in python, skipping build directory lock")
|
||||
print("please file an issue on rust-lang/rust")
|
||||
print("this is not a problem for non-concurrent x.py invocations")
|
||||
return None
|
||||
|
||||
def support_xz():
|
||||
try:
|
||||
with tempfile.NamedTemporaryFile(delete=False) as temp_file:
|
||||
@ -1228,6 +1264,12 @@ def bootstrap(help_triggered):
|
||||
build.set_dist_environment(data["dist_server"])
|
||||
|
||||
build.build = args.build or build.build_triple()
|
||||
|
||||
# Acquire the lock before doing any build actions
|
||||
# The lock is released when `lock` is dropped
|
||||
if not os.path.exists(build.build_dir):
|
||||
os.makedirs(build.build_dir)
|
||||
lock = acquire_lock(build.build_dir)
|
||||
build.update_submodules()
|
||||
|
||||
# Fetch/build the bootstrap
|
||||
|
@ -2,7 +2,7 @@ error: the range pattern here has ambiguous interpretation
|
||||
--> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:8:10
|
||||
|
|
||||
LL | &0.. | _ => {}
|
||||
| ^^^ help: add parentheses to clarify the precedence: `(0 ..)`
|
||||
| ^^^ help: add parentheses to clarify the precedence: `(0..)`
|
||||
|
||||
error[E0586]: inclusive range with no end
|
||||
--> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:10:11
|
||||
@ -16,7 +16,7 @@ error: the range pattern here has ambiguous interpretation
|
||||
--> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:10:10
|
||||
|
|
||||
LL | &0..= | _ => {}
|
||||
| ^^^^ help: add parentheses to clarify the precedence: `(0 ..=)`
|
||||
| ^^^^ help: add parentheses to clarify the precedence: `(0..=)`
|
||||
|
||||
error[E0586]: inclusive range with no end
|
||||
--> $DIR/half-open-range-pats-ref-ambiguous-interp.rs:13:11
|
||||
|
@ -31,7 +31,7 @@ static mut frobulator: usize = 0xdeadbeef;
|
||||
|
||||
pub fn main() {
|
||||
unsafe {
|
||||
frobulator = 0xcafebabe;
|
||||
frobulator = 0x12345678;
|
||||
println!("{} {} {}", i_live_in_more_text(), magic, frobulator);
|
||||
}
|
||||
}
|
||||
|
3
src/test/ui/macros/issue-92267.rs
Normal file
3
src/test/ui/macros/issue-92267.rs
Normal file
@ -0,0 +1,3 @@
|
||||
// check-fail
|
||||
|
||||
pub fn main() { println!("🦀%%%", 0) } //~ ERROR argument never used
|
16
src/test/ui/macros/issue-92267.stderr
Normal file
16
src/test/ui/macros/issue-92267.stderr
Normal file
@ -0,0 +1,16 @@
|
||||
error: argument never used
|
||||
--> $DIR/issue-92267.rs:3:34
|
||||
|
|
||||
LL | pub fn main() { println!("🦀%%%", 0) }
|
||||
| ^ argument never used
|
||||
|
|
||||
note: format specifiers use curly braces, and the conversion specifier `
|
||||
` is unknown or unsupported
|
||||
--> $DIR/issue-92267.rs:3:30
|
||||
|
|
||||
LL | pub fn main() { println!("🦀%%%", 0) }
|
||||
| ^^
|
||||
= note: printf formatting not supported; see the documentation for `std::fmt`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -256,7 +256,7 @@ fn test_expr() {
|
||||
assert_eq!(stringify_expr!(expr.await), "expr.await");
|
||||
|
||||
// ExprKind::TryBlock
|
||||
assert_eq!(stringify_expr!(try {}), "try {}"); // FIXME
|
||||
assert_eq!(stringify_expr!(try {}), "try {}");
|
||||
|
||||
// ExprKind::Assign
|
||||
assert_eq!(stringify_expr!(expr = true), "expr = true");
|
||||
@ -712,10 +712,10 @@ fn test_pat() {
|
||||
|
||||
// PatKind::Range
|
||||
assert_eq!(stringify_pat!(..1), "..1");
|
||||
assert_eq!(stringify_pat!(0..), "0 .."); // FIXME
|
||||
assert_eq!(stringify_pat!(0..1), "0 ..1");
|
||||
assert_eq!(stringify_pat!(0..=1), "0 ..=1");
|
||||
assert_eq!(stringify_pat!(-2..=-1), "-2 ..=-1");
|
||||
assert_eq!(stringify_pat!(0..), "0..");
|
||||
assert_eq!(stringify_pat!(0..1), "0..1");
|
||||
assert_eq!(stringify_pat!(0..=1), "0..=1");
|
||||
assert_eq!(stringify_pat!(-2..=-1), "-2..=-1");
|
||||
|
||||
// PatKind::Slice
|
||||
assert_eq!(stringify_pat!([]), "[]");
|
||||
|
@ -34,7 +34,7 @@ fn main() {
|
||||
//~| pattern on the left, should be on the right
|
||||
//~| binding on the right, should be on the left
|
||||
//~| HELP switch the order
|
||||
//~| SUGGESTION e @ 1 ..=5
|
||||
//~| SUGGESTION e @ 1..=5
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ LL | 1 ..= 5 @ e => {}
|
||||
| | |
|
||||
| | binding on the right, should be on the left
|
||||
| pattern on the left, should be on the right
|
||||
| help: switch the order: `e @ 1 ..=5`
|
||||
| help: switch the order: `e @ 1..=5`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
@ -12,7 +12,7 @@ pub fn main() {
|
||||
//~^ WARN `...` range patterns are deprecated
|
||||
//~| WARN this is accepted in the current edition
|
||||
//~| HELP use `..=` for an inclusive range
|
||||
&(10 ..=15) => {}
|
||||
&(10..=15) => {}
|
||||
//~^ ERROR the range pattern here has ambiguous interpretation
|
||||
//~| HELP add parentheses to clarify the precedence
|
||||
&(16..=20) => {}
|
||||
|
@ -2,7 +2,7 @@ error: the range pattern here has ambiguous interpretation
|
||||
--> $DIR/range-inclusive-pattern-precedence.rs:15:10
|
||||
|
|
||||
LL | &10..=15 => {}
|
||||
| ^^^^^^^ help: add parentheses to clarify the precedence: `(10 ..=15)`
|
||||
| ^^^^^^^ help: add parentheses to clarify the precedence: `(10..=15)`
|
||||
|
||||
warning: `...` range patterns are deprecated
|
||||
--> $DIR/range-inclusive-pattern-precedence.rs:11:9
|
||||
|
@ -2,7 +2,7 @@ error: the range pattern here has ambiguous interpretation
|
||||
--> $DIR/range-inclusive-pattern-precedence2.rs:14:13
|
||||
|
|
||||
LL | box 10..=15 => {}
|
||||
| ^^^^^^^ help: add parentheses to clarify the precedence: `(10 ..=15)`
|
||||
| ^^^^^^^ help: add parentheses to clarify the precedence: `(10..=15)`
|
||||
|
||||
warning: `...` range patterns are deprecated
|
||||
--> $DIR/range-inclusive-pattern-precedence2.rs:10:14
|
||||
|
@ -14,4 +14,4 @@ extern crate std;
|
||||
|
||||
fn main() ({ } as ())
|
||||
|
||||
fn foo((-(128 as i8) as i8) ...(127 as i8): i8) ({ } as ())
|
||||
fn foo((-(128 as i8) as i8)...(127 as i8): i8) ({ } as ())
|
||||
|
@ -30,7 +30,7 @@ fn main() {
|
||||
1_234.123_f32,
|
||||
1.123_4_f32,
|
||||
);
|
||||
let _bad = (0b11_0110_i64, 0xcafe_babe_usize, 123_456_f32, 1.234_567_f32);
|
||||
let _bad = (0b11_0110_i64, 0x1234_5678_usize, 123_456_f32, 1.234_567_f32);
|
||||
let _good_sci = 1.1234e1;
|
||||
let _bad_sci = 1.123_456e1;
|
||||
|
||||
|
@ -30,7 +30,7 @@ fn main() {
|
||||
1_234.123_f32,
|
||||
1.123_4_f32,
|
||||
);
|
||||
let _bad = (0b110110_i64, 0xcafebabe_usize, 123456_f32, 1.234567_f32);
|
||||
let _bad = (0b110110_i64, 0x12345678_usize, 123456_f32, 1.234567_f32);
|
||||
let _good_sci = 1.1234e1;
|
||||
let _bad_sci = 1.123456e1;
|
||||
|
||||
|
@ -9,7 +9,7 @@ LL | 0x1_234_567,
|
||||
error: long literal lacking separators
|
||||
--> $DIR/unreadable_literal.rs:33:17
|
||||
|
|
||||
LL | let _bad = (0b110110_i64, 0xcafebabe_usize, 123456_f32, 1.234567_f32);
|
||||
LL | let _bad = (0b110110_i64, 0x12345678_usize, 123456_f32, 1.234567_f32);
|
||||
| ^^^^^^^^^^^^ help: consider: `0b11_0110_i64`
|
||||
|
|
||||
= note: `-D clippy::unreadable-literal` implied by `-D warnings`
|
||||
@ -17,19 +17,19 @@ LL | let _bad = (0b110110_i64, 0xcafebabe_usize, 123456_f32, 1.234567_f32);
|
||||
error: long literal lacking separators
|
||||
--> $DIR/unreadable_literal.rs:33:31
|
||||
|
|
||||
LL | let _bad = (0b110110_i64, 0xcafebabe_usize, 123456_f32, 1.234567_f32);
|
||||
| ^^^^^^^^^^^^^^^^ help: consider: `0xcafe_babe_usize`
|
||||
LL | let _bad = (0b110110_i64, 0x12345678_usize, 123456_f32, 1.234567_f32);
|
||||
| ^^^^^^^^^^^^^^^^ help: consider: `0x1234_5678_usize`
|
||||
|
||||
error: long literal lacking separators
|
||||
--> $DIR/unreadable_literal.rs:33:49
|
||||
|
|
||||
LL | let _bad = (0b110110_i64, 0xcafebabe_usize, 123456_f32, 1.234567_f32);
|
||||
LL | let _bad = (0b110110_i64, 0x12345678_usize, 123456_f32, 1.234567_f32);
|
||||
| ^^^^^^^^^^ help: consider: `123_456_f32`
|
||||
|
||||
error: long literal lacking separators
|
||||
--> $DIR/unreadable_literal.rs:33:61
|
||||
|
|
||||
LL | let _bad = (0b110110_i64, 0xcafebabe_usize, 123456_f32, 1.234567_f32);
|
||||
LL | let _bad = (0b110110_i64, 0x12345678_usize, 123456_f32, 1.234567_f32);
|
||||
| ^^^^^^^^^^^^ help: consider: `1.234_567_f32`
|
||||
|
||||
error: long literal lacking separators
|
||||
|
@ -56,6 +56,12 @@ const ANNOTATIONS_TO_IGNORE: &[&str] = &[
|
||||
"// normalize-stderr-test",
|
||||
];
|
||||
|
||||
// Intentionally written in decimal rather than hex
|
||||
const PROBLEMATIC_CONSTS: &[u32] = &[
|
||||
184594741, 2880289470, 2881141438, 2965027518, 2976579765, 3203381950, 3405691582, 3405697037,
|
||||
3735927486, 4027431614, 4276992702,
|
||||
];
|
||||
|
||||
/// Parser states for `line_is_url`.
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
#[allow(non_camel_case_types)]
|
||||
@ -217,6 +223,10 @@ pub fn check(path: &Path, bad: &mut bool) {
|
||||
fn skip(path: &Path) -> bool {
|
||||
super::filter_dirs(path) || skip_markdown_path(path)
|
||||
}
|
||||
let problematic_consts_strings: Vec<String> = (PROBLEMATIC_CONSTS.iter().map(u32::to_string))
|
||||
.chain(PROBLEMATIC_CONSTS.iter().map(|v| format!("{:x}", v)))
|
||||
.chain(PROBLEMATIC_CONSTS.iter().map(|v| format!("{:X}", v)))
|
||||
.collect();
|
||||
super::walk(path, &mut skip, &mut |entry, contents| {
|
||||
let file = entry.path();
|
||||
let filename = file.file_name().unwrap().to_string_lossy();
|
||||
@ -306,6 +316,11 @@ pub fn check(path: &Path, bad: &mut bool) {
|
||||
if line.contains("//") && line.contains(" XXX") {
|
||||
err("XXX is deprecated; use FIXME")
|
||||
}
|
||||
for s in problematic_consts_strings.iter() {
|
||||
if line.contains(s) {
|
||||
err("Don't use magic numbers that spell things (consider 0x12345678)");
|
||||
}
|
||||
}
|
||||
}
|
||||
let is_test = || file.components().any(|c| c.as_os_str() == "tests");
|
||||
// for now we just check libcore
|
||||
|
Loading…
Reference in New Issue
Block a user