]> git.lizzy.rs Git - rust.git/commitdiff
Merge commit '1411a98352ba6bee8ba3b0131c9243e5db1e6a2e' into sync_cg_clif-2021-12-31
authorbjorn3 <bjorn3@users.noreply.github.com>
Fri, 31 Dec 2021 15:26:32 +0000 (16:26 +0100)
committerbjorn3 <bjorn3@users.noreply.github.com>
Fri, 31 Dec 2021 15:26:32 +0000 (16:26 +0100)
18 files changed:
compiler/rustc_codegen_gcc/Cargo.lock
compiler/rustc_codegen_gcc/Cargo.toml
compiler/rustc_codegen_gcc/Readme.md
compiler/rustc_codegen_gcc/patches/0023-core-Ignore-failing-tests.patch
compiler/rustc_codegen_gcc/patches/0024-core-Disable-portable-simd-test.patch [new file with mode: 0644]
compiler/rustc_codegen_gcc/patches/0028-core-Disable-long-running-tests.patch [new file with mode: 0644]
compiler/rustc_codegen_gcc/rust-toolchain
compiler/rustc_codegen_gcc/src/asm.rs
compiler/rustc_codegen_gcc/src/back/write.rs
compiler/rustc_codegen_gcc/src/base.rs
compiler/rustc_codegen_gcc/src/builder.rs
compiler/rustc_codegen_gcc/src/common.rs
compiler/rustc_codegen_gcc/src/consts.rs
compiler/rustc_codegen_gcc/src/context.rs
compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
compiler/rustc_codegen_gcc/src/lib.rs
compiler/rustc_codegen_gcc/src/type_.rs
compiler/rustc_codegen_gcc/tests/run/asm.rs

index 60a2101c689cc2d1d6102a682956e61190f370cd..47925f72c2cbdd30b6964213f60da8da3dc26d2f 100644 (file)
@@ -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]]
index 9e8c195c15f6054084ba875ebb26f8c349b9906c..21f0bfbf69d7fac441bccb879999fbc80bd801b5 100644 (file)
@@ -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"
index 709d93c6edb054f384fd2c9a4823597e827753e9..1fcfb5f6e20a108661fce85ecbc8fa36ab5d7820 100644 (file)
@@ -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`).
index ee5ba449fb8e6bb0ee310eea54ac65a01ec8842a..73e9c858caf2b6dbb51419d804152e83045a3ab8 100644 (file)
@@ -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)
diff --git a/compiler/rustc_codegen_gcc/patches/0024-core-Disable-portable-simd-test.patch b/compiler/rustc_codegen_gcc/patches/0024-core-Disable-portable-simd-test.patch
new file mode 100644 (file)
index 0000000..8954f91
--- /dev/null
@@ -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
+
diff --git a/compiler/rustc_codegen_gcc/patches/0028-core-Disable-long-running-tests.patch b/compiler/rustc_codegen_gcc/patches/0028-core-Disable-long-running-tests.patch
new file mode 100644 (file)
index 0000000..bf74a74
--- /dev/null
@@ -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
+
index d311a33f807b7e238422d21f43fdc22e2998c7df..ee0822f6c31457c6b4f125a765e613221d466537 100644 (file)
@@ -1 +1 @@
-nightly-2021-09-28
+nightly-2021-12-30
index 10edcf36955da78eceb762ad518b01924b1ef20e..453bcd601d3fe51b391b5627930c4350190d5bcc 100644 (file)
 
 // 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)`
 //
 // * `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 @@ fn codegen_inline_asm(&mut self, template: &[InlineAsmTemplatePiece], rust_opera
         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 @@ fn codegen_inline_asm(&mut self, template: &[InlineAsmTemplatePiece], rust_opera
         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 @@ fn codegen_inline_asm(&mut self, template: &[InlineAsmTemplatePiece], rust_opera
         // 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 @@ fn codegen_inline_asm(&mut self, template: &[InlineAsmTemplatePiece], rust_opera
                         (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 @@ fn codegen_inline_asm(&mut self, template: &[InlineAsmTemplatePiece], rust_opera
 
                     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 @@ fn codegen_inline_asm(&mut self, template: &[InlineAsmTemplatePiece], rust_opera
 
                 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 @@ fn codegen_inline_asm(&mut self, template: &[InlineAsmTemplatePiece], rust_opera
                 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 @@ fn codegen_inline_asm(&mut self, template: &[InlineAsmTemplatePiece], rust_opera
                     // 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 @@ fn codegen_inline_asm(&mut self, template: &[InlineAsmTemplatePiece], rust_opera
                         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 @@ fn codegen_inline_asm(&mut self, template: &[InlineAsmTemplatePiece], rust_opera
                     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 @@ fn codegen_inline_asm(&mut self, template: &[InlineAsmTemplatePiece], rust_opera
                         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 @@ fn codegen_inline_asm(&mut self, template: &[InlineAsmTemplatePiece], rust_opera
                         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 @@ fn codegen_inline_asm(&mut self, template: &[InlineAsmTemplatePiece], rust_opera
                 // `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 @@ fn codegen_inline_asm(&mut self, template: &[InlineAsmTemplatePiece], rust_opera
                     // processed in the previous pass
                 }
 
-                InlineAsmOperandRef::Const { .. } 
-                | InlineAsmOperandRef::SymFn { .. } 
+                InlineAsmOperandRef::Const { .. }
+                | InlineAsmOperandRef::SymFn { .. }
                 | InlineAsmOperandRef::SymStatic { .. } => {
                     // processed in the previous pass
                 }
@@ -460,7 +451,7 @@ fn codegen_inline_asm(&mut self, template: &[InlineAsmTemplatePiece], rust_opera
         if !intel_dialect {
             template_str.push_str(INTEL_SYNTAX_INS);
         }
-        
+
         // 4. Generate Extended Asm block
 
         let block = self.llbb();
@@ -479,7 +470,7 @@ fn codegen_inline_asm(&mut self, template: &[InlineAsmTemplatePiece], rust_opera
         }
 
         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 @@ fn codegen_inline_asm(&mut self, template: &[InlineAsmTemplatePiece], rust_opera
             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 @@ fn codegen_inline_asm(&mut self, template: &[InlineAsmTemplatePiece], rust_opera
         // 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);
             }
         }
 
index 4962d0161525631d28dc2adb19655c3e24ae8725..334ef32f1d1d7471f7bb6b2bf0b511974cfeae9b 100644 (file)
@@ -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"));
             }
index dee70bf75369d6aa59bcce209cdc597731a068c8..8b23e96066eed1307ffd46982cfe8e0c65b06252 100644 (file)
@@ -81,7 +81,10 @@ fn module_codegen(tcx: TyCtxt<'_>, cgu_name: Symbol) -> ModuleCodegen<GccContext
         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);
         }
index fff2aa6df7c725ab53bcd2a2c9ba5008c15b72e2..ccf8123000cf83ec0fff9c58bb09d28fb31f6e71 100644 (file)
@@ -200,7 +200,7 @@ fn check_call<'b>(&mut self, _typ: &str, func: Function<'gcc>, args: &'b [RValue
     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 @@ fn function_ptr_call(&mut self, func_ptr: RValue<'gcc>, args: &[RValue<'gcc>], _
 
         // 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 @@ fn ashr(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
     }
 
     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 @@ fn xor(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
     }
 
     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 @@ fn atomic_load(&mut self, _ty: Type<'gcc>, ptr: RValue<'gcc>, order: AtomicOrder
         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 @@ fn atomic_store(&mut self, value: RValue<'gcc>, ptr: RValue<'gcc>, order: Atomic
         // 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 @@ fn struct_gep(&mut self, value_type: Type<'gcc>, ptr: RValue<'gcc>, idx: u64) ->
         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 @@ fn trunc(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
 
     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 @@ fn icmp(&mut self, op: IntPredicate, mut lhs: RValue<'gcc>, mut rhs: RValue<'gcc
         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 @@ fn extract_value(&mut self, aggregate_value: RValue<'gcc>, idx: u64) -> RValue<'
         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 @@ fn insert_value(&mut self, aggregate_value: RValue<'gcc>, value: RValue<'gcc>, i
         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() {
index ec542e55681e5be898ab0be9f2c4671b40c7950c..5851826147dfac9fd5cedacf1d9120f406be702b 100644 (file)
@@ -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 @@ fn global_string(&self, string: &str) -> LValue<'gcc> {
         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 @@ fn const_uint(&self, typ: Type<'gcc>, int: u64) -> RValue<'gcc> {
     }
 
     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 @@ fn const_struct(&self, values: &[RValue<'gcc>], packed: bool) -> RValue<'gcc> {
         // 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> {
index 205498acc3187beb9260e194db2e3de1c06d5426..ba4589bd810255be742e27f90a908bd54d4135f8 100644 (file)
@@ -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 @@ pub fn const_bitcast(&self, value: RValue<'gcc>, typ: Type<'gcc>) -> RValue<'gcc
 
 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 @@ fn codegen_static(&self, def_id: DefId, is_mutable: bool) {
             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 @@ pub fn static_addr_of_mut(&self, cv: RValue<'gcc>, align: Align, kind: Option<&s
             };
         // 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
     }
index 7677ade7314e52d1ce8af86ad1fbc54d3b45c39b..dfcd1b6231216cb49acc361bdb83e054a43e058d 100644 (file)
@@ -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,
index 0782adeb6a175bad86a826ab561d2dbe17c60f99..572ac559d09dfb89fb5842cab86c7903d900dae7 100644 (file)
@@ -526,7 +526,7 @@ fn bit_reverse(&mut self, width: u64, value: RValue<'gcc>) -> RValue<'gcc> {
 
         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 @@ fn bit_reverse(&mut self, width: u64, value: RValue<'gcc>) -> RValue<'gcc> {
                 },
             };
 
-        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 @@ fn count_leading_zeroes(&self, width: u64, arg: RValue<'gcc>) -> RValue<'gcc> {
                 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 @@ fn count_trailing_zeroes(&self, _width: u64, arg: RValue<'gcc>) -> RValue<'gcc>
         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 @@ fn count_trailing_zeroes(&self, _width: u64, arg: RValue<'gcc>) -> RValue<'gcc>
                 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 @@ fn count_trailing_zeroes(&self, _width: u64, arg: RValue<'gcc>) -> RValue<'gcc>
                 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 @@ fn pop_count(&self, value: RValue<'gcc>) -> RValue<'gcc> {
 
         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 @@ fn pop_count(&self, value: RValue<'gcc>) -> RValue<'gcc> {
             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 @@ fn pop_count(&self, value: RValue<'gcc>) -> RValue<'gcc> {
         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 @@ fn pop_count(&self, value: RValue<'gcc>) -> RValue<'gcc> {
         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 @@ fn pop_count(&self, value: RValue<'gcc>) -> RValue<'gcc> {
         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 @@ fn pop_count(&self, value: RValue<'gcc>) -> RValue<'gcc> {
         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
index 30a33b99e5053f4dac1d5422eb473502811bfce1..034558a879dbd882459e946a09a118c6b1b9eff0 100644 (file)
@@ -91,8 +91,6 @@ fn codegen_crate<'tcx>(&self, tcx: TyCtxt<'tcx>, metadata: EncodedMetadata, need
         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)
     }
 
index 3545e1b628105870b333bd2030dbf30ad79c4ed5..28e2adc492bbeb49f86be0c3037610c3d0fd53a2 100644 (file)
@@ -122,7 +122,7 @@ fn type_kind(&self, typ: Type<'gcc>) -> TypeKind {
         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 @@ fn type_ptr_to_ext(&self, ty: Type<'gcc>, _address_space: AddressSpace) -> Type<
     }
 
     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() {
index 48c0203d594a33a326956812f4fcc662dbbe7ffc..46abbb553bf2f6e257d61bc39e399161a5654553 100644 (file)
@@ -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:
     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 @@ extern "C" fn foo() -> u64 { 42 }
     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);
 }