add support for building LLVM 7.0 from downloaded source
authorJacob Lifshay <programmerjake@gmail.com>
Mon, 15 Oct 2018 05:45:57 +0000 (22:45 -0700)
committerJacob Lifshay <programmerjake@gmail.com>
Mon, 15 Oct 2018 23:16:30 +0000 (16:16 -0700)
.dockerignore
.gitignore
Dockerfile
shader-compiler-llvm-7/Cargo.toml
shader-compiler-llvm-7/build.rs [new file with mode: 0644]
shader-compiler-llvm-7/src/backend.rs
shader-compiler-llvm-7/src/lib.rs
shader-compiler/src/backend/mod.rs

index d4c901f955d6a91adea709dd478b2f2e341ea384..0c49855b7d94a87ff1405315b427c3e7c97ef54c 100644 (file)
@@ -5,3 +5,4 @@
 /VK-GL-CTS
 /TestResults.qpa
 /.git
+/external/llvm-7
index 8889c73214a696488957670ff4596cc58affa8a9..5a9610fec5013d868cf3d0f946a46d7271f307dc 100644 (file)
@@ -4,4 +4,5 @@
 /Cargo.lock
 /VK-GL-CTS
 /TestResults.qpa
-/.vscode
\ No newline at end of file
+/.vscode
+/external/llvm-7
index c3509d3f724669d9f244bfaa47aaf7bee83ddacd..6a57621ec8dbd6609d7be00b8b72b2a3745c10a2 100644 (file)
@@ -1,19 +1,15 @@
 # SPDX-License-Identifier: LGPL-2.1-or-later
 # Copyright 2018 Jacob Lifshay
 FROM rust:stretch
-# Note that APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE makes apt-key ignore the output not being a terminal
 RUN set -e; \
-    printf "deb http://apt.llvm.org/stretch/ llvm-toolchain-stretch-7 main\ndeb-src http://apt.llvm.org/stretch/ llvm-toolchain-stretch-7 main" > /etc/apt/sources.list.d/llvm.list; \
-    (wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=1 apt-key add -) 2>&1; \
     apt-get update; \
     apt-get install -y \
-        clang-7 \
-        libclang-7-dev \
-        llvm-7-dev \
         cmake \
         ninja-build \
         libgl1-mesa-dev \
         libxcb-shm0 \
+        libclang-dev \
+        clang \
         ; \
     rm -rf /var/lib/apt/lists/*
 WORKDIR /build
@@ -35,7 +31,7 @@ RUN set -e; \
     echo "// empty" > vulkan-driver/src/lib.rs; \
     echo "// empty" > shader-compiler/src/lib.rs; \
     echo "// empty" > shader-compiler-llvm-7/src/lib.rs; \
-    cargo build; \
+    cargo build -vv; \
     rm */src/lib.rs
 COPY . .
 RUN touch -c */src/lib.rs && cargo build
index 676d9d94f1b2d3297081785499cd1256a28bedb1..b3535590d133cdc63b61631606b596dcc7ef1717 100644 (file)
@@ -11,4 +11,14 @@ crate-type = ["rlib"]
 
 [dependencies]
 shader-compiler = {path = "../shader-compiler"}
-llvm-sys = "70"
+
+[build-dependencies]
+cmake = "0.1.35"
+bindgen = "0.42"
+tar = "0.4.17"
+reqwest = "0.9"
+xz2 = "0.1.6"
+ring = "0.13"
+cc = "1.0"
+fs2 = "0.4.3"
+which = "2.0.0"
diff --git a/shader-compiler-llvm-7/build.rs b/shader-compiler-llvm-7/build.rs
new file mode 100644 (file)
index 0000000..df7bceb
--- /dev/null
@@ -0,0 +1,298 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+// Copyright 2018 Jacob Lifshay
+
+// Partially based on llvm-sys; llvm-sys's license is reproduced below:
+
+// Copyright (c) 2015 Peter Marheine
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files (the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+// of the Software, and to permit persons to whom the Software is furnished to do
+// so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+extern crate bindgen;
+extern crate cc;
+extern crate cmake;
+extern crate fs2;
+extern crate reqwest;
+extern crate ring;
+extern crate tar;
+extern crate which;
+extern crate xz2;
+use fs2::FileExt;
+use std::env;
+use std::ffi::OsStr;
+use std::fs;
+use std::io;
+use std::io::prelude::*;
+use std::path::{Path, PathBuf};
+use std::process::Command;
+
+const LLVM_7_SOURCE_TAR_XZ_URL: &'static str =
+    "http://releases.llvm.org/7.0.0/llvm-7.0.0.src.tar.xz";
+
+const LLVM_7_SOURCE_TAR_XZ_SHA256_HASH: &'static [u8; 32] = &[
+    0x8b, 0xc1, 0xf8, 0x44, 0xe6, 0xcb, 0xde, 0x1b, 0x65, 0x2c, 0x19, 0xc1, 0xed, 0xeb, 0xc1, 0x86,
+    0x44, 0x56, 0xfd, 0x9c, 0x78, 0xb8, 0xc1, 0xbe, 0xa0, 0x38, 0xe5, 0x1b, 0x36, 0x3f, 0xe2, 0x22,
+];
+
+const LLVM_7_SOURCE_DIR_SUFFIX: &'static str = "llvm-7.0.0.src";
+
+fn verify_sha256(mut f: fs::File, file_path: &Path) -> fs::File {
+    f.seek(io::SeekFrom::Start(0)).unwrap();
+    let mut context = ring::digest::Context::new(&ring::digest::SHA256);
+    let mut buffer = [0; 1 << 12]; // 4KiB
+    loop {
+        let count = f.read(&mut buffer).unwrap();
+        if count == 0 {
+            break;
+        }
+        context.update(&buffer[..count]);
+    }
+    let hash = context.finish();
+    if hash.as_ref() != LLVM_7_SOURCE_TAR_XZ_SHA256_HASH {
+        panic!(
+            "file is corrupted: SHA256 doesn't match; try deleting {} and rerunning cargo",
+            file_path.display(),
+        );
+    }
+    f.seek(io::SeekFrom::Start(0)).unwrap();
+    f
+}
+
+fn download_llvm_7(out_dir: &Path) -> io::Result<fs::File> {
+    let filename = LLVM_7_SOURCE_TAR_XZ_URL.rsplit('/').next().unwrap();
+    let file_path = out_dir.join(filename);
+    match fs::File::open(&file_path) {
+        Ok(file) => return Ok(verify_sha256(file, &file_path)),
+        Err(ref error) if error.kind() == io::ErrorKind::NotFound => {}
+        Err(error) => return Err(error),
+    };
+    let response = reqwest::get(LLVM_7_SOURCE_TAR_XZ_URL)
+        .map_err(|v| io::Error::new(io::ErrorKind::Other, v))?;
+    let file = fs::OpenOptions::new()
+        .write(true)
+        .create_new(true)
+        .open(&file_path)?;
+    { response }
+        .copy_to(&mut { file })
+        .map_err(|v| io::Error::new(io::ErrorKind::Other, v))?;
+    Ok(verify_sha256(fs::File::open(&file_path)?, &file_path))
+}
+
+fn extract_tar_xz<R: Read, T: AsRef<Path>>(r: R, target_path: T) -> io::Result<()> {
+    tar::Archive::new(xz2::read::XzDecoder::new(r)).unpack(target_path)
+}
+
+fn download_and_extract_llvm_7_if_needed(llvm_dir: &Path) -> io::Result<PathBuf> {
+    let source_dir = llvm_dir.join(LLVM_7_SOURCE_DIR_SUFFIX);
+    match fs::File::open(source_dir.join("CMakeLists.txt")) {
+        Ok(_) => return Ok(source_dir),
+        Err(ref error) if error.kind() == io::ErrorKind::NotFound => {}
+        Err(error) => return Err(error),
+    }
+    extract_tar_xz(download_llvm_7(llvm_dir)?, llvm_dir)?;
+    Ok(source_dir)
+}
+
+fn make_config(llvm_dir: &Path) -> cmake::Config {
+    let mut retval = cmake::Config::new(llvm_dir.join(LLVM_7_SOURCE_DIR_SUFFIX));
+    let found_ccache = match which::which("ccache") {
+        Err(ref error) if error.kind() == which::ErrorKind::CannotFindBinaryPath => false,
+        result => {
+            result.unwrap();
+            true
+        }
+    };
+    retval
+        .generator("Ninja")
+        .define("LLVM_TARGETS_TO_BUILD", "host")
+        .define("LLVM_CCACHE_BUILD", if found_ccache { "ON" } else { "OFF" })
+        .define(
+            "LLVM_TARGET_ARCH",
+            env::var("TARGET").unwrap().split("-").next().unwrap(),
+        )
+        .out_dir(llvm_dir)
+        .profile("RelWithDebInfo")
+        .always_configure(false);
+    retval
+}
+
+fn llvm_config<A: IntoIterator<Item = S>, S: AsRef<OsStr>>(
+    llvm_config_path: &Path,
+    args: A,
+) -> String {
+    String::from_utf8(
+        Command::new(llvm_config_path)
+            .arg("--link-static")
+            .args(args)
+            .output()
+            .unwrap()
+            .stdout,
+    )
+    .unwrap()
+}
+
+fn get_libs<A: IntoIterator<Item = S>, S: AsRef<OsStr>>(
+    llvm_config_path: &Path,
+    args: A,
+) -> Vec<String> {
+    llvm_config(&llvm_config_path, args)
+        .split_whitespace()
+        .filter_map(|flag| {
+            if flag == "" {
+                None
+            } else if cfg!(target_env = "msvc") {
+                // Same as --libnames, foo.lib
+                assert!(flag.ends_with(".lib"));
+                Some(&flag[..flag.len() - 4])
+            } else {
+                // Linker flags style, -lfoo
+                assert!(flag.starts_with("-l"));
+                Some(&flag[2..])
+            }
+        })
+        .map(Into::into)
+        .collect()
+}
+
+struct LockedFile(fs::File);
+
+impl Drop for LockedFile {
+    fn drop(&mut self) {
+        let _ = self.0.unlock();
+    }
+}
+
+impl LockedFile {
+    fn new<T: AsRef<Path>>(file_path: T) -> io::Result<Self> {
+        let file = fs::OpenOptions::new()
+            .read(true)
+            .write(true)
+            .create(true)
+            .open(file_path)?;
+        file.lock_exclusive()?;
+        Ok(LockedFile(file))
+    }
+}
+
+fn build_llvm() -> PathBuf {
+    assert_eq!(
+        env::var_os("TARGET"),
+        env::var_os("HOST"),
+        "cross-compilation is not supported"
+    );
+    let llvm_dir = env::current_dir()
+        .unwrap()
+        .join("..")
+        .join("external")
+        .join("llvm-7")
+        .join(env::var_os("TARGET").unwrap());
+    fs::create_dir_all(&llvm_dir).unwrap();
+    let _locked_file = LockedFile::new(llvm_dir.join(".build-lock")).unwrap();
+    download_and_extract_llvm_7_if_needed(&llvm_dir).unwrap();
+    make_config(&llvm_dir).build_target("install").build();
+    #[cfg(windows)]
+    let llvm_config_path = llvm_dir.join("bin").join("llvm-config.exe");
+    #[cfg(not(windows))]
+    let llvm_config_path = llvm_dir.join("bin").join("llvm-config");
+    llvm_config_path
+}
+
+fn main() {
+    let out_dir = Path::new(&env::var_os("OUT_DIR").unwrap()).to_path_buf();
+    let llvm_config_path = build_llvm();
+    println!(
+        "cargo:rustc-link-search=native={}",
+        llvm_config(&llvm_config_path, Some("--libdir"))
+    );
+    let llvm_libs = get_libs(&llvm_config_path, Some("--libs"));
+    for lib in llvm_libs {
+        println!("cargo:rustc-link-lib=static={}", lib);
+    }
+    let header = r#"
+#include "llvm-c/Core.h"
+#include "llvm-c/OrcBindings.h"
+#include "llvm-c/Target.h"
+#include "llvm-c/Analysis.h"
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+void LLVM_InitializeNativeTarget(void);
+void LLVM_InitializeNativeAsmParser(void);
+void LLVM_InitializeNativeAsmPrinter(void);
+void LLVM_InitializeNativeDisassembler(void);
+
+#ifdef __cplusplus
+}
+#endif
+"#;
+    let header_path = out_dir.join("llvm_bindings.h");
+    fs::write(&header_path, header).unwrap();
+    let llvm_bindings_source = format!("#include {:?}\n", header_path) + r#"
+void LLVM_InitializeNativeTarget(void)
+{
+    LLVM_NATIVE_TARGETINFO();
+    LLVM_NATIVE_TARGET();
+    LLVM_NATIVE_TARGETMC();
+}
+
+void LLVM_InitializeNativeAsmParser(void)
+{
+    LLVM_NATIVE_ASMPARSER();
+}
+
+void LLVM_InitializeNativeAsmPrinter(void)
+{
+    LLVM_NATIVE_ASMPRINTER();
+}
+
+void LLVM_InitializeNativeDisassembler(void)
+{
+    LLVM_NATIVE_DISASSEMBLER();
+}
+"#;
+    let llvm_bindings_path = out_dir.join("llvm_bindings.c");
+    fs::write(&llvm_bindings_path, llvm_bindings_source).unwrap();
+    let include_dir: String = llvm_config(&llvm_config_path, Some("--includedir"))
+        .trim_right()
+        .into();
+    let builder = bindgen::Builder::default()
+        .header(header_path.to_str().unwrap())
+        .clang_arg("-I")
+        .clang_arg(&include_dir as &str)
+        .rustfmt_bindings(true)
+        .whitelist_type("LLVM.*")
+        .whitelist_function("LLVM.*")
+        .whitelist_var("LLVM.*")
+        .blacklist_type("^__.*")
+        .prepend_enum_name(false)
+        .constified_enum("LLVM.*");
+    builder
+        .generate()
+        .unwrap()
+        .write_to_file(out_dir.join("llvm_c.rs"))
+        .unwrap();
+    cc::Build::new()
+        .cpp(true)
+        .file(llvm_bindings_path)
+        .include(&include_dir)
+        .compile("llvm_bindings");
+}
index cbb7b51365c9edb16faa12208311fb29cb4e2516..a1c3af53822f623ecb0acd5559bec1219035faf8 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: LGPL-2.1-or-later
 // Copyright 2018 Jacob Lifshay
-use llvm_sys;
+use llvm;
 use shader_compiler::backend;
 use std::cell::Cell;
 use std::ffi::{CStr, CString};
@@ -11,7 +11,7 @@ use std::ptr::null_mut;
 use std::ptr::NonNull;
 use std::sync::{Once, ONCE_INIT};
 
-fn to_bool(v: llvm_sys::prelude::LLVMBool) -> bool {
+fn to_bool(v: llvm::LLVMBool) -> bool {
     v != 0
 }
 
@@ -43,7 +43,7 @@ struct LLVM7String(NonNull<c_char>);
 impl Drop for LLVM7String {
     fn drop(&mut self) {
         unsafe {
-            llvm_sys::core::LLVMDisposeMessage(self.0.as_ptr());
+            llvm::LLVMDisposeMessage(self.0.as_ptr());
         }
     }
 }
@@ -63,7 +63,7 @@ impl Clone for LLVM7String {
 
 impl LLVM7String {
     fn new(v: &CStr) -> Self {
-        unsafe { Self::from_ptr(llvm_sys::core::LLVMCreateMessage(v.as_ptr())).unwrap() }
+        unsafe { Self::from_ptr(llvm::LLVMCreateMessage(v.as_ptr())).unwrap() }
     }
     unsafe fn from_nonnull(v: NonNull<c_char>) -> Self {
         LLVM7String(v)
@@ -81,13 +81,13 @@ impl fmt::Debug for LLVM7String {
 
 #[derive(Clone, Eq, PartialEq, Hash)]
 #[repr(transparent)]
-pub struct LLVM7Type(llvm_sys::prelude::LLVMTypeRef);
+pub struct LLVM7Type(llvm::LLVMTypeRef);
 
 impl fmt::Debug for LLVM7Type {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         unsafe {
-            let string = LLVM7String::from_ptr(llvm_sys::core::LLVMPrintTypeToString(self.0))
-                .ok_or(fmt::Error)?;
+            let string =
+                LLVM7String::from_ptr(llvm::LLVMPrintTypeToString(self.0)).ok_or(fmt::Error)?;
             f.write_str(&string.to_string_lossy())
         }
     }
@@ -98,38 +98,38 @@ impl<'a> backend::types::Type<'a> for LLVM7Type {
 }
 
 pub struct LLVM7TypeBuilder {
-    context: llvm_sys::prelude::LLVMContextRef,
+    context: llvm::LLVMContextRef,
     variable_vector_length_multiplier: u32,
 }
 
 impl<'a> backend::types::TypeBuilder<'a, LLVM7Type> for LLVM7TypeBuilder {
     fn build_bool(&self) -> LLVM7Type {
-        unsafe { LLVM7Type(llvm_sys::core::LLVMInt1TypeInContext(self.context)) }
+        unsafe { LLVM7Type(llvm::LLVMInt1TypeInContext(self.context)) }
     }
     fn build_i8(&self) -> LLVM7Type {
-        unsafe { LLVM7Type(llvm_sys::core::LLVMInt8TypeInContext(self.context)) }
+        unsafe { LLVM7Type(llvm::LLVMInt8TypeInContext(self.context)) }
     }
     fn build_i16(&self) -> LLVM7Type {
-        unsafe { LLVM7Type(llvm_sys::core::LLVMInt16TypeInContext(self.context)) }
+        unsafe { LLVM7Type(llvm::LLVMInt16TypeInContext(self.context)) }
     }
     fn build_i32(&self) -> LLVM7Type {
-        unsafe { LLVM7Type(llvm_sys::core::LLVMInt32TypeInContext(self.context)) }
+        unsafe { LLVM7Type(llvm::LLVMInt32TypeInContext(self.context)) }
     }
     fn build_i64(&self) -> LLVM7Type {
-        unsafe { LLVM7Type(llvm_sys::core::LLVMInt64TypeInContext(self.context)) }
+        unsafe { LLVM7Type(llvm::LLVMInt64TypeInContext(self.context)) }
     }
     fn build_f32(&self) -> LLVM7Type {
-        unsafe { LLVM7Type(llvm_sys::core::LLVMFloatTypeInContext(self.context)) }
+        unsafe { LLVM7Type(llvm::LLVMFloatTypeInContext(self.context)) }
     }
     fn build_f64(&self) -> LLVM7Type {
-        unsafe { LLVM7Type(llvm_sys::core::LLVMDoubleTypeInContext(self.context)) }
+        unsafe { LLVM7Type(llvm::LLVMDoubleTypeInContext(self.context)) }
     }
     fn build_pointer(&self, target: LLVM7Type) -> LLVM7Type {
-        unsafe { LLVM7Type(llvm_sys::core::LLVMPointerType(target.0, 0)) }
+        unsafe { LLVM7Type(llvm::LLVMPointerType(target.0, 0)) }
     }
     fn build_array(&self, element: LLVM7Type, count: usize) -> LLVM7Type {
         assert_eq!(count as u32 as usize, count);
-        unsafe { LLVM7Type(llvm_sys::core::LLVMArrayType(element.0, count as u32)) }
+        unsafe { LLVM7Type(llvm::LLVMArrayType(element.0, count as u32)) }
     }
     fn build_vector(&self, element: LLVM7Type, length: backend::types::VectorLength) -> LLVM7Type {
         use self::backend::types::VectorLength::*;
@@ -140,31 +140,29 @@ impl<'a> backend::types::TypeBuilder<'a, LLVM7Type> for LLVM7TypeBuilder {
                 .unwrap(),
         };
         assert_ne!(length, 0);
-        unsafe { LLVM7Type(llvm_sys::core::LLVMVectorType(element.0, length)) }
+        unsafe { LLVM7Type(llvm::LLVMVectorType(element.0, length)) }
     }
     fn build_struct(&self, members: &[LLVM7Type]) -> LLVM7Type {
         assert_eq!(members.len() as c_uint as usize, members.len());
         unsafe {
-            LLVM7Type(llvm_sys::core::LLVMStructTypeInContext(
+            LLVM7Type(llvm::LLVMStructTypeInContext(
                 self.context,
-                members.as_ptr() as *mut llvm_sys::prelude::LLVMTypeRef,
+                members.as_ptr() as *mut llvm::LLVMTypeRef,
                 members.len() as c_uint,
-                false as llvm_sys::prelude::LLVMBool,
+                false as llvm::LLVMBool,
             ))
         }
     }
     fn build_function(&self, arguments: &[LLVM7Type], return_type: Option<LLVM7Type>) -> LLVM7Type {
         assert_eq!(arguments.len() as c_uint as usize, arguments.len());
         unsafe {
-            LLVM7Type(llvm_sys::core::LLVMFunctionType(
+            LLVM7Type(llvm::LLVMFunctionType(
                 return_type
-                    .unwrap_or_else(|| {
-                        LLVM7Type(llvm_sys::core::LLVMVoidTypeInContext(self.context))
-                    })
+                    .unwrap_or_else(|| LLVM7Type(llvm::LLVMVoidTypeInContext(self.context)))
                     .0,
-                arguments.as_ptr() as *mut llvm_sys::prelude::LLVMTypeRef,
+                arguments.as_ptr() as *mut llvm::LLVMTypeRef,
                 arguments.len() as c_uint,
-                false as llvm_sys::prelude::LLVMBool,
+                false as llvm::LLVMBool,
             ))
         }
     }
@@ -172,13 +170,13 @@ impl<'a> backend::types::TypeBuilder<'a, LLVM7Type> for LLVM7TypeBuilder {
 
 #[derive(Clone)]
 #[repr(transparent)]
-pub struct LLVM7Value(llvm_sys::prelude::LLVMValueRef);
+pub struct LLVM7Value(llvm::LLVMValueRef);
 
 impl fmt::Debug for LLVM7Value {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         unsafe {
-            let string = LLVM7String::from_ptr(llvm_sys::core::LLVMPrintValueToString(self.0))
-                .ok_or(fmt::Error)?;
+            let string =
+                LLVM7String::from_ptr(llvm::LLVMPrintValueToString(self.0)).ok_or(fmt::Error)?;
             f.write_str(&string.to_string_lossy())
         }
     }
@@ -190,15 +188,14 @@ impl<'a> backend::Value<'a> for LLVM7Value {
 
 #[derive(Clone)]
 #[repr(transparent)]
-pub struct LLVM7BasicBlock(llvm_sys::prelude::LLVMBasicBlockRef);
+pub struct LLVM7BasicBlock(llvm::LLVMBasicBlockRef);
 
 impl fmt::Debug for LLVM7BasicBlock {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         use self::backend::BasicBlock;
         unsafe {
-            let string =
-                LLVM7String::from_ptr(llvm_sys::core::LLVMPrintValueToString(self.as_value().0))
-                    .ok_or(fmt::Error)?;
+            let string = LLVM7String::from_ptr(llvm::LLVMPrintValueToString(self.as_value().0))
+                .ok_or(fmt::Error)?;
             f.write_str(&string.to_string_lossy())
         }
     }
@@ -207,7 +204,7 @@ impl fmt::Debug for LLVM7BasicBlock {
 impl<'a> backend::BasicBlock<'a> for LLVM7BasicBlock {
     type Context = LLVM7Context;
     fn as_value(&self) -> LLVM7Value {
-        unsafe { LLVM7Value(llvm_sys::core::LLVMBasicBlockAsValue(self.0)) }
+        unsafe { LLVM7Value(llvm::LLVMBasicBlockAsValue(self.0)) }
     }
 }
 
@@ -219,16 +216,15 @@ impl<'a> backend::BuildableBasicBlock<'a> for LLVM7BasicBlock {
 }
 
 pub struct LLVM7Function {
-    context: llvm_sys::prelude::LLVMContextRef,
-    function: llvm_sys::prelude::LLVMValueRef,
+    context: llvm::LLVMContextRef,
+    function: llvm::LLVMValueRef,
 }
 
 impl fmt::Debug for LLVM7Function {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         unsafe {
-            let string =
-                LLVM7String::from_ptr(llvm_sys::core::LLVMPrintValueToString(self.function))
-                    .ok_or(fmt::Error)?;
+            let string = LLVM7String::from_ptr(llvm::LLVMPrintValueToString(self.function))
+                .ok_or(fmt::Error)?;
             f.write_str(&string.to_string_lossy())
         }
     }
@@ -242,7 +238,7 @@ impl<'a> backend::Function<'a> for LLVM7Function {
     fn append_new_basic_block(&mut self, name: Option<&str>) -> LLVM7BasicBlock {
         let name = CString::new(name.unwrap_or("")).unwrap();
         unsafe {
-            LLVM7BasicBlock(llvm_sys::core::LLVMAppendBasicBlockInContext(
+            LLVM7BasicBlock(llvm::LLVMAppendBasicBlockInContext(
                 self.context,
                 self.function,
                 name.as_ptr(),
@@ -252,8 +248,8 @@ impl<'a> backend::Function<'a> for LLVM7Function {
 }
 
 pub struct LLVM7Context {
-    context: llvm_sys::prelude::LLVMContextRef,
-    modules: Cell<Vec<llvm_sys::prelude::LLVMModuleRef>>,
+    context: llvm::LLVMContextRef,
+    modules: Cell<Vec<llvm::LLVMModuleRef>>,
     config: LLVM7CompilerConfig,
 }
 
@@ -261,9 +257,9 @@ impl Drop for LLVM7Context {
     fn drop(&mut self) {
         unsafe {
             for module in self.modules.get_mut().drain(..) {
-                llvm_sys::core::LLVMDisposeModule(module);
+                llvm::LLVMDisposeModule(module);
             }
-            llvm_sys::core::LLVMContextDispose(self.context);
+            llvm::LLVMContextDispose(self.context);
         }
     }
 }
@@ -284,8 +280,7 @@ impl<'a> backend::Context<'a> for LLVM7Context {
         let mut modules = self.modules.take();
         modules.reserve(1); // so we don't unwind without freeing the new module
         unsafe {
-            let module =
-                llvm_sys::core::LLVMModuleCreateWithNameInContext(name.as_ptr(), self.context);
+            let module = llvm::LLVMModuleCreateWithNameInContext(name.as_ptr(), self.context);
             modules.push(module);
             self.modules.set(modules);
             LLVM7Module {
@@ -295,7 +290,7 @@ impl<'a> backend::Context<'a> for LLVM7Context {
         }
     }
     fn create_builder(&self) -> LLVM7Builder {
-        unsafe { LLVM7Builder(llvm_sys::core::LLVMCreateBuilderInContext(self.context)) }
+        unsafe { LLVM7Builder(llvm::LLVMCreateBuilderInContext(self.context)) }
     }
     fn create_type_builder(&self) -> LLVM7TypeBuilder {
         LLVM7TypeBuilder {
@@ -306,12 +301,12 @@ impl<'a> backend::Context<'a> for LLVM7Context {
 }
 
 #[repr(transparent)]
-pub struct LLVM7Builder(llvm_sys::prelude::LLVMBuilderRef);
+pub struct LLVM7Builder(llvm::LLVMBuilderRef);
 
 impl Drop for LLVM7Builder {
     fn drop(&mut self) {
         unsafe {
-            llvm_sys::core::LLVMDisposeBuilder(self.0);
+            llvm::LLVMDisposeBuilder(self.0);
         }
     }
 }
@@ -319,15 +314,15 @@ impl Drop for LLVM7Builder {
 impl<'a> backend::AttachedBuilder<'a> for LLVM7Builder {
     type Context = LLVM7Context;
     fn current_basic_block(&self) -> LLVM7BasicBlock {
-        unsafe { LLVM7BasicBlock(llvm_sys::core::LLVMGetInsertBlock(self.0)) }
+        unsafe { LLVM7BasicBlock(llvm::LLVMGetInsertBlock(self.0)) }
     }
     fn build_return(self, value: Option<LLVM7Value>) -> LLVM7Builder {
         unsafe {
             match value {
-                Some(value) => llvm_sys::core::LLVMBuildRet(self.0, value.0),
-                None => llvm_sys::core::LLVMBuildRetVoid(self.0),
+                Some(value) => llvm::LLVMBuildRet(self.0, value.0),
+                None => llvm::LLVMBuildRetVoid(self.0),
             };
-            llvm_sys::core::LLVMClearInsertionPosition(self.0);
+            llvm::LLVMClearInsertionPosition(self.0);
         }
         self
     }
@@ -337,23 +332,22 @@ impl<'a> backend::DetachedBuilder<'a> for LLVM7Builder {
     type Context = LLVM7Context;
     fn attach(self, basic_block: LLVM7BasicBlock) -> LLVM7Builder {
         unsafe {
-            llvm_sys::core::LLVMPositionBuilderAtEnd(self.0, basic_block.0);
+            llvm::LLVMPositionBuilderAtEnd(self.0, basic_block.0);
         }
         self
     }
 }
 
 pub struct LLVM7Module {
-    context: llvm_sys::prelude::LLVMContextRef,
-    module: llvm_sys::prelude::LLVMModuleRef,
+    context: llvm::LLVMContextRef,
+    module: llvm::LLVMModuleRef,
 }
 
 impl fmt::Debug for LLVM7Module {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         unsafe {
-            let string =
-                LLVM7String::from_ptr(llvm_sys::core::LLVMPrintModuleToString(self.module))
-                    .ok_or(fmt::Error)?;
+            let string = LLVM7String::from_ptr(llvm::LLVMPrintModuleToString(self.module))
+                .ok_or(fmt::Error)?;
             f.write_str(&string.to_string_lossy())
         }
     }
@@ -363,7 +357,7 @@ impl<'a> backend::Module<'a> for LLVM7Module {
     type Context = LLVM7Context;
     fn set_source_file_name(&mut self, source_file_name: &str) {
         unsafe {
-            llvm_sys::core::LLVMSetSourceFileName(
+            llvm::LLVMSetSourceFileName(
                 self.module,
                 source_file_name.as_ptr() as *const c_char,
                 source_file_name.len(),
@@ -375,25 +369,22 @@ impl<'a> backend::Module<'a> for LLVM7Module {
         unsafe {
             LLVM7Function {
                 context: self.context,
-                function: llvm_sys::core::LLVMAddFunction(self.module, name.as_ptr(), ty.0),
+                function: llvm::LLVMAddFunction(self.module, name.as_ptr(), ty.0),
             }
         }
     }
     fn verify(self) -> Result<LLVM7Module, backend::VerificationFailure<'a, LLVM7Module>> {
         unsafe {
             let mut message = null_mut();
-            match to_bool(llvm_sys::analysis::LLVMVerifyModule(
+            match to_bool(llvm::LLVMVerifyModule(
                 self.module,
-                llvm_sys::analysis::LLVMVerifierFailureAction::LLVMReturnStatusAction,
+                llvm::LLVMReturnStatusAction,
                 &mut message,
             )) {
                 broken if broken != false => {
                     let message = LLVM7String::from_ptr(message).unwrap();
                     let message = message.to_string_lossy();
-                    Err(backend::VerificationFailure::new(
-                        self,
-                        message.into_owned(),
-                    ))
+                    Err(backend::VerificationFailure::new(self, message.as_ref()))
                 }
                 _ => Ok(self),
             }
@@ -411,32 +402,32 @@ impl<'a> backend::VerifiedModule<'a> for LLVM7Module {
     }
 }
 
-struct LLVM7TargetMachine(llvm_sys::target_machine::LLVMTargetMachineRef);
+struct LLVM7TargetMachine(llvm::LLVMTargetMachineRef);
 
 impl Drop for LLVM7TargetMachine {
     fn drop(&mut self) {
         unsafe {
-            llvm_sys::target_machine::LLVMDisposeTargetMachine(self.0);
+            llvm::LLVMDisposeTargetMachine(self.0);
         }
     }
 }
 
 impl LLVM7TargetMachine {
-    fn take(mut self) -> llvm_sys::target_machine::LLVMTargetMachineRef {
+    fn take(mut self) -> llvm::LLVMTargetMachineRef {
         let retval = self.0;
         self.0 = null_mut();
         retval
     }
 }
 
-struct LLVM7OrcJITStack(llvm_sys::orc::LLVMOrcJITStackRef);
+struct LLVM7OrcJITStack(llvm::LLVMOrcJITStackRef);
 
 impl Drop for LLVM7OrcJITStack {
     fn drop(&mut self) {
         unsafe {
-            match llvm_sys::orc::LLVMOrcDisposeInstance(self.0) {
-                llvm_sys::orc::LLVMOrcErrorCode::LLVMOrcErrSuccess => {}
-                llvm_sys::orc::LLVMOrcErrorCode::LLVMOrcErrGeneric => {
+            match llvm::LLVMOrcDisposeInstance(self.0) {
+                llvm::LLVMOrcErrSuccess => {}
+                _ => {
                     panic!("LLVMOrcDisposeInstance failed");
                 }
             }
@@ -447,8 +438,8 @@ impl Drop for LLVM7OrcJITStack {
 fn initialize_native_target() {
     static ONCE: Once = ONCE_INIT;
     ONCE.call_once(|| unsafe {
-        assert_eq!(llvm_sys::target::LLVM_InitializeNativeTarget(), 0);
-        assert_eq!(llvm_sys::target::LLVM_InitializeNativeAsmParser(), 0);
+        llvm::LLVM_InitializeNativeTarget();
+        llvm::LLVM_InitializeNativeAsmParser();
     });
 }
 
@@ -473,7 +464,7 @@ impl backend::Compiler for LLVM7Compiler {
         unsafe {
             initialize_native_target();
             let context = LLVM7Context {
-                context: llvm_sys::core::LLVMContextCreate(),
+                context: llvm::LLVMContextCreate(),
                 modules: Vec::new().into(),
                 config: config.clone(),
             };
@@ -483,16 +474,14 @@ impl backend::Compiler for LLVM7Compiler {
             } = user.run(&context)?;
             for callable_function in callable_functions.values() {
                 assert_eq!(
-                    llvm_sys::core::LLVMGetGlobalParent(callable_function.function),
+                    llvm::LLVMGetGlobalParent(callable_function.function),
                     module.module
                 );
             }
-            let target_triple =
-                LLVM7String::from_ptr(llvm_sys::target_machine::LLVMGetDefaultTargetTriple())
-                    .unwrap();
+            let target_triple = LLVM7String::from_ptr(llvm::LLVMGetDefaultTargetTriple()).unwrap();
             let mut target = null_mut();
             let mut error = null_mut();
-            let success = !to_bool(llvm_sys::target_machine::LLVMGetTargetFromTriple(
+            let success = !to_bool(llvm::LLVMGetTargetFromTriple(
                 target_triple.as_ptr(),
                 &mut target,
                 &mut error,
@@ -501,38 +490,31 @@ impl backend::Compiler for LLVM7Compiler {
                 let error = LLVM7String::from_ptr(error).unwrap();
                 return Err(U::create_error(error.to_string_lossy().into()));
             }
-            if !to_bool(llvm_sys::target_machine::LLVMTargetHasJIT(target)) {
+            if !to_bool(llvm::LLVMTargetHasJIT(target)) {
                 return Err(U::create_error(format!(
                     "target {:?} doesn't support JIT",
                     target_triple
                 )));
             }
-            let host_cpu_name =
-                LLVM7String::from_ptr(llvm_sys::target_machine::LLVMGetHostCPUName()).unwrap();
-            let host_cpu_features =
-                LLVM7String::from_ptr(llvm_sys::target_machine::LLVMGetHostCPUFeatures()).unwrap();
-            let target_machine =
-                LLVM7TargetMachine(llvm_sys::target_machine::LLVMCreateTargetMachine(
-                    target,
-                    target_triple.as_ptr(),
-                    host_cpu_name.as_ptr(),
-                    host_cpu_features.as_ptr(),
-                    match config.optimization_mode {
-                        backend::OptimizationMode::NoOptimizations => {
-                            llvm_sys::target_machine::LLVMCodeGenOptLevel::LLVMCodeGenLevelNone
-                        }
-                        backend::OptimizationMode::Normal => {
-                            llvm_sys::target_machine::LLVMCodeGenOptLevel::LLVMCodeGenLevelDefault
-                        }
-                    },
-                    llvm_sys::target_machine::LLVMRelocMode::LLVMRelocDefault,
-                    llvm_sys::target_machine::LLVMCodeModel::LLVMCodeModelJITDefault,
-                ));
+            let host_cpu_name = LLVM7String::from_ptr(llvm::LLVMGetHostCPUName()).unwrap();
+            let host_cpu_features = LLVM7String::from_ptr(llvm::LLVMGetHostCPUFeatures()).unwrap();
+            let target_machine = LLVM7TargetMachine(llvm::LLVMCreateTargetMachine(
+                target,
+                target_triple.as_ptr(),
+                host_cpu_name.as_ptr(),
+                host_cpu_features.as_ptr(),
+                match config.optimization_mode {
+                    backend::OptimizationMode::NoOptimizations => llvm::LLVMCodeGenLevelNone,
+                    backend::OptimizationMode::Normal => llvm::LLVMCodeGenLevelDefault,
+                },
+                llvm::LLVMRelocDefault,
+                llvm::LLVMCodeModelJITDefault,
+            ));
             assert!(!target_machine.0.is_null());
             let orc_jit_stack =
-                LLVM7OrcJITStack(llvm_sys::orc::LLVMOrcCreateInstance(target_machine.take()));
+                LLVM7OrcJITStack(llvm::LLVMOrcCreateInstance(target_machine.take()));
             let mut orc_module_handle = 0;
-            llvm_sys::orc::LLVMOrcAddEagerlyCompiledIR(
+            llvm::LLVMOrcAddEagerlyCompiledIR(
                 orc_jit_stack.0,
                 &mut orc_module_handle,
                 module.module,
index c582f509d0e2c6eeb321481b47ef87f035d3a073..7b2e37553d4375794390686f225b96654b9ec589 100644 (file)
@@ -1,8 +1,15 @@
 // SPDX-License-Identifier: LGPL-2.1-or-later
 // Copyright 2018 Jacob Lifshay
-extern crate llvm_sys;
 extern crate shader_compiler;
 
+// TODO: #[allow(clippy::const_static_lifetime)]
+#[allow(dead_code)]
+#[allow(non_upper_case_globals)]
+#[allow(non_camel_case_types)]
+mod llvm {
+    include!(concat!(env!("OUT_DIR"), "/llvm_c.rs"));
+}
+
 mod backend;
 mod tests;
 
index 1ff6b9e140c6aeccb83026da06c8ce08beaba3e9..0ba1b6cb76f8bc0e4b763240f833acf391e34f87 100644 (file)
@@ -3,7 +3,6 @@
 
 //! Shader Compiler Backend traits
 
-use std::borrow::Borrow;
 use std::collections::HashMap;
 use std::error::Error;
 use std::fmt;
@@ -11,8 +10,6 @@ use std::fmt::Debug;
 use std::hash::Hash;
 use std::io;
 use std::marker::PhantomData;
-use std::os::raw::c_void;
-use std::ptr::NonNull;
 
 #[macro_use]
 pub mod types;
@@ -89,7 +86,7 @@ pub struct VerificationFailure<'a, M: Module<'a>> {
 
 impl<'a, M: Module<'a>> VerificationFailure<'a, M> {
     /// create a new `VerificationFailure`
-    pub fn new<T: ToString>(module: M, message: T) -> Self {
+    pub fn new<T: ToString + ?Sized>(module: M, message: &T) -> Self {
         VerificationFailure {
             module,
             message: message.to_string(),