From 14f488ee7d05c39b8d6ea2855da274157555df0b Mon Sep 17 00:00:00 2001
From: Artyom Pavlov <newpavlov@gmail.com>
Date: Sat, 10 Feb 2018 19:22:04 +0300
Subject: [PATCH 1/6] Whitelist pclmul x86 feature flag

Relevant `stdsimd` [issue](https://github.com/rust-lang-nursery/stdsimd/issues/318).
---
 src/librustc_trans/llvm_util.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/librustc_trans/llvm_util.rs b/src/librustc_trans/llvm_util.rs
index 843231d376f6c..f719562b47647 100644
--- a/src/librustc_trans/llvm_util.rs
+++ b/src/librustc_trans/llvm_util.rs
@@ -88,7 +88,7 @@ const X86_WHITELIST: &'static [&'static str] = &["avx\0", "avx2\0", "bmi\0", "bm
                                                  "ssse3\0", "tbm\0", "lzcnt\0", "popcnt\0",
                                                  "sse4a\0", "rdrnd\0", "rdseed\0", "fma\0",
                                                  "xsave\0", "xsaveopt\0", "xsavec\0",
-                                                 "xsaves\0", "aes\0",
+                                                 "xsaves\0", "aes\0", "pclmul\0"
                                                  "avx512bw\0", "avx512cd\0",
                                                  "avx512dq\0", "avx512er\0",
                                                  "avx512f\0", "avx512ifma\0",

From 877272ba066dd81d9d920b851d0300bb3e7ee2b3 Mon Sep 17 00:00:00 2001
From: Artyom Pavlov <newpavlov@gmail.com>
Date: Sat, 10 Feb 2018 20:07:37 +0300
Subject: [PATCH 2/6] typo fix

---
 src/librustc_trans/llvm_util.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/librustc_trans/llvm_util.rs b/src/librustc_trans/llvm_util.rs
index f719562b47647..21def37e5e6e5 100644
--- a/src/librustc_trans/llvm_util.rs
+++ b/src/librustc_trans/llvm_util.rs
@@ -88,7 +88,7 @@ const X86_WHITELIST: &'static [&'static str] = &["avx\0", "avx2\0", "bmi\0", "bm
                                                  "ssse3\0", "tbm\0", "lzcnt\0", "popcnt\0",
                                                  "sse4a\0", "rdrnd\0", "rdseed\0", "fma\0",
                                                  "xsave\0", "xsaveopt\0", "xsavec\0",
-                                                 "xsaves\0", "aes\0", "pclmul\0"
+                                                 "xsaves\0", "aes\0", "pclmul\0",
                                                  "avx512bw\0", "avx512cd\0",
                                                  "avx512dq\0", "avx512er\0",
                                                  "avx512f\0", "avx512ifma\0",

From 8be306840f89b92ee49d2c0fae2b189c45706b2a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9F=D0=B0=D0=B2=D0=BB?=
 =?UTF-8?q?=D0=BE=D0=B2=20=5BArtyom=20Pavlov=5D?= <newpavlov@gmail.com>
Date: Sun, 11 Feb 2018 02:27:21 +0300
Subject: [PATCH 3/6] added conversion from Rust feature to LLVM feature

---
 src/librustc_trans/attributes.rs |  5 ++-
 src/librustc_trans/llvm_util.rs  | 72 +++++++++++++++++---------------
 2 files changed, 42 insertions(+), 35 deletions(-)

diff --git a/src/librustc_trans/attributes.rs b/src/librustc_trans/attributes.rs
index 6c8088375c4b0..8309c91ab2573 100644
--- a/src/librustc_trans/attributes.rs
+++ b/src/librustc_trans/attributes.rs
@@ -142,7 +142,7 @@ pub fn provide(providers: &mut Providers) {
         assert_eq!(cnum, LOCAL_CRATE);
         Rc::new(llvm_util::target_feature_whitelist(tcx.sess)
             .iter()
-            .map(|c| c.to_str().unwrap().to_string())
+            .map(|c| c.to_string())
             .collect())
     };
 
@@ -212,7 +212,8 @@ fn from_target_feature(
         let value = value.as_str();
         for feature in value.split(',') {
             if whitelist.contains(feature) {
-                target_features.push(format!("+{}", feature));
+                let llvm_feature = llvm_util::to_llvm_feature(feature);
+                target_features.push(format!("+{}", llvm_feature));
                 continue
             }
 
diff --git a/src/librustc_trans/llvm_util.rs b/src/librustc_trans/llvm_util.rs
index 21def37e5e6e5..61eefb32e099a 100644
--- a/src/librustc_trans/llvm_util.rs
+++ b/src/librustc_trans/llvm_util.rs
@@ -79,45 +79,54 @@ unsafe fn configure_llvm(sess: &Session) {
 // detection code will walk past the end of the feature array,
 // leading to crashes.
 
-const ARM_WHITELIST: &'static [&'static str] = &["neon\0", "v7\0", "vfp2\0", "vfp3\0", "vfp4\0"];
-
-const AARCH64_WHITELIST: &'static [&'static str] = &["neon\0", "v7\0"];
-
-const X86_WHITELIST: &'static [&'static str] = &["avx\0", "avx2\0", "bmi\0", "bmi2\0", "sse\0",
-                                                 "sse2\0", "sse3\0", "sse4.1\0", "sse4.2\0",
-                                                 "ssse3\0", "tbm\0", "lzcnt\0", "popcnt\0",
-                                                 "sse4a\0", "rdrnd\0", "rdseed\0", "fma\0",
-                                                 "xsave\0", "xsaveopt\0", "xsavec\0",
-                                                 "xsaves\0", "aes\0", "pclmul\0",
-                                                 "avx512bw\0", "avx512cd\0",
-                                                 "avx512dq\0", "avx512er\0",
-                                                 "avx512f\0", "avx512ifma\0",
-                                                 "avx512pf\0", "avx512vbmi\0",
-                                                 "avx512vl\0", "avx512vpopcntdq\0",
-                                                 "mmx\0", "fxsr\0"];
-
-const HEXAGON_WHITELIST: &'static [&'static str] = &["hvx\0", "hvx-double\0"];
-
-const POWERPC_WHITELIST: &'static [&'static str] = &["altivec\0",
-                                                     "power8-altivec\0", "power9-altivec\0",
-                                                     "power8-vector\0", "power9-vector\0",
-                                                     "vsx\0"];
-
-const MIPS_WHITELIST: &'static [&'static str] = &["msa\0"];
+const ARM_WHITELIST: &'static [&'static str] = &["neon", "v7", "vfp2", "vfp3", "vfp4"];
+
+const AARCH64_WHITELIST: &'static [&'static str] = &["neon", "v7"];
+
+const X86_WHITELIST: &'static [&'static str] = &["avx", "avx2", "bmi", "bmi2", "sse",
+                                                 "sse2", "sse3", "sse4.1", "sse4.2",
+                                                 "ssse3", "tbm", "lzcnt", "popcnt",
+                                                 "sse4a", "rdrnd", "rdseed", "fma",
+                                                 "xsave", "xsaveopt", "xsavec",
+                                                 "xsaves", "aes", "pclmulqdq",
+                                                 "avx512bw", "avx512cd",
+                                                 "avx512dq", "avx512er",
+                                                 "avx512f", "avx512ifma",
+                                                 "avx512pf", "avx512vbmi",
+                                                 "avx512vl", "avx512vpopcntdq",
+                                                 "mmx", "fxsr"];
+
+const HEXAGON_WHITELIST: &'static [&'static str] = &["hvx", "hvx-double"];
+
+const POWERPC_WHITELIST: &'static [&'static str] = &["altivec",
+                                                     "power8-altivec", "power9-altivec",
+                                                     "power8-vector", "power9-vector",
+                                                     "vsx"];
+
+const MIPS_WHITELIST: &'static [&'static str] = &["msa"];
+
+pub fn to_llvm_feature(s: &str) -> &str {
+    match s {
+        "pclmulqdq" => "pclmul",
+        s => s,
+    }
+}
 
 pub fn target_features(sess: &Session) -> Vec<Symbol> {
     let whitelist = target_feature_whitelist(sess);
     let target_machine = create_target_machine(sess);
     let mut features = Vec::new();
-    for feat in whitelist {
-        if unsafe { llvm::LLVMRustHasFeature(target_machine, feat.as_ptr()) } {
-            features.push(Symbol::intern(feat.to_str().unwrap()));
+    for feature in whitelist {
+        let llvm_feature = to_llvm_feature(feature);
+        let ptr = CString::new(llvm_feature).as_ptr();
+        if unsafe { llvm::LLVMRustHasFeature(target_machine, ptr) } {
+            features.push(Symbol::intern(feature));
         }
     }
     features
 }
 
-pub fn target_feature_whitelist(sess: &Session) -> Vec<&CStr> {
+pub fn target_feature_whitelist(sess: &Session) -> &'static [&'static str] {
     let whitelist = match &*sess.target.target.arch {
         "arm" => ARM_WHITELIST,
         "aarch64" => AARCH64_WHITELIST,
@@ -126,10 +135,7 @@ pub fn target_feature_whitelist(sess: &Session) -> Vec<&CStr> {
         "mips" | "mips64" => MIPS_WHITELIST,
         "powerpc" | "powerpc64" => POWERPC_WHITELIST,
         _ => &[],
-    };
-    whitelist.iter().map(|m| {
-        CStr::from_bytes_with_nul(m.as_bytes()).unwrap()
-    }).collect()
+    }
 }
 
 pub fn print_version() {

From c97aa0911785fc1c1306b38e978093b3153666ec Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9F=D0=B0=D0=B2=D0=BB?=
 =?UTF-8?q?=D0=BE=D0=B2=20=5BArtyom=20Pavlov=5D?= <newpavlov@gmail.com>
Date: Sun, 11 Feb 2018 02:36:22 +0300
Subject: [PATCH 4/6] iterator instead loop

---
 src/librustc_trans/llvm_util.rs | 18 ++++++++----------
 1 file changed, 8 insertions(+), 10 deletions(-)

diff --git a/src/librustc_trans/llvm_util.rs b/src/librustc_trans/llvm_util.rs
index 61eefb32e099a..8839129f3f88e 100644
--- a/src/librustc_trans/llvm_util.rs
+++ b/src/librustc_trans/llvm_util.rs
@@ -113,17 +113,15 @@ pub fn to_llvm_feature(s: &str) -> &str {
 }
 
 pub fn target_features(sess: &Session) -> Vec<Symbol> {
-    let whitelist = target_feature_whitelist(sess);
     let target_machine = create_target_machine(sess);
-    let mut features = Vec::new();
-    for feature in whitelist {
-        let llvm_feature = to_llvm_feature(feature);
-        let ptr = CString::new(llvm_feature).as_ptr();
-        if unsafe { llvm::LLVMRustHasFeature(target_machine, ptr) } {
-            features.push(Symbol::intern(feature));
-        }
-    }
-    features
+    target_feature_whitelist(sess)
+        .iter()
+        .filter(|feature| {
+            let llvm_feature = to_llvm_feature(feature);
+            let ptr = CString::new(llvm_feature).as_ptr();
+            unsafe { llvm::LLVMRustHasFeature(target_machine, ptr) }
+        })
+        .map(Symbol::intern).collect()
 }
 
 pub fn target_feature_whitelist(sess: &Session) -> &'static [&'static str] {

From 7c6adb475abef794cc6b81f6a21094f3257ee37b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9F=D0=B0=D0=B2=D0=BB?=
 =?UTF-8?q?=D0=BE=D0=B2=20=5BArtyom=20Pavlov=5D?= <newpavlov@gmail.com>
Date: Sun, 11 Feb 2018 03:27:04 +0300
Subject: [PATCH 5/6] fixed errors

---
 src/librustc_trans/llvm_util.rs | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/librustc_trans/llvm_util.rs b/src/librustc_trans/llvm_util.rs
index 8839129f3f88e..1f921513fe628 100644
--- a/src/librustc_trans/llvm_util.rs
+++ b/src/librustc_trans/llvm_util.rs
@@ -14,7 +14,7 @@ use llvm;
 use rustc::session::Session;
 use rustc::session::config::PrintRequest;
 use libc::c_int;
-use std::ffi::{CStr, CString};
+use std::ffi::CString;
 
 use std::sync::atomic::{AtomicBool, Ordering};
 use std::sync::Once;
@@ -118,14 +118,14 @@ pub fn target_features(sess: &Session) -> Vec<Symbol> {
         .iter()
         .filter(|feature| {
             let llvm_feature = to_llvm_feature(feature);
-            let ptr = CString::new(llvm_feature).as_ptr();
+            let ptr = CString::new(llvm_feature).unwrap().as_ptr();
             unsafe { llvm::LLVMRustHasFeature(target_machine, ptr) }
         })
-        .map(Symbol::intern).collect()
+        .map(|feature| Symbol::intern(feature)).collect()
 }
 
 pub fn target_feature_whitelist(sess: &Session) -> &'static [&'static str] {
-    let whitelist = match &*sess.target.target.arch {
+    match &*sess.target.target.arch {
         "arm" => ARM_WHITELIST,
         "aarch64" => AARCH64_WHITELIST,
         "x86" | "x86_64" => X86_WHITELIST,

From c2a31dee835c2312a9e527b1f9ea1b77c24beeab Mon Sep 17 00:00:00 2001
From: Artyom Pavlov <newpavlov@gmail.com>
Date: Sun, 11 Feb 2018 15:57:07 +0300
Subject: [PATCH 6/6] Dangling pointer fix

---
 src/librustc_trans/llvm_util.rs | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/librustc_trans/llvm_util.rs b/src/librustc_trans/llvm_util.rs
index 1f921513fe628..b25562252e72e 100644
--- a/src/librustc_trans/llvm_util.rs
+++ b/src/librustc_trans/llvm_util.rs
@@ -118,8 +118,8 @@ pub fn target_features(sess: &Session) -> Vec<Symbol> {
         .iter()
         .filter(|feature| {
             let llvm_feature = to_llvm_feature(feature);
-            let ptr = CString::new(llvm_feature).unwrap().as_ptr();
-            unsafe { llvm::LLVMRustHasFeature(target_machine, ptr) }
+            let cstr = CString::new(llvm_feature).unwrap();
+            unsafe { llvm::LLVMRustHasFeature(target_machine, cstr.as_ptr()) }
         })
         .map(|feature| Symbol::intern(feature)).collect()
 }