split shader compiler backend into separate crate
authorJacob Lifshay <programmerjake@gmail.com>
Fri, 19 Oct 2018 04:52:39 +0000 (21:52 -0700)
committerJacob Lifshay <programmerjake@gmail.com>
Fri, 19 Oct 2018 04:52:39 +0000 (21:52 -0700)
20 files changed:
Cargo.toml
shader-compiler-backend-llvm-7/Cargo.toml [new file with mode: 0644]
shader-compiler-backend-llvm-7/build.rs [new file with mode: 0644]
shader-compiler-backend-llvm-7/src/backend.rs [new file with mode: 0644]
shader-compiler-backend-llvm-7/src/lib.rs [new file with mode: 0644]
shader-compiler-backend-llvm-7/src/tests.rs [new file with mode: 0644]
shader-compiler-backend/Cargo.toml [new file with mode: 0644]
shader-compiler-backend/src/lib.rs [new file with mode: 0644]
shader-compiler-backend/src/types.rs [new file with mode: 0644]
shader-compiler-llvm-7/Cargo.toml [deleted file]
shader-compiler-llvm-7/build.rs [deleted file]
shader-compiler-llvm-7/src/backend.rs [deleted file]
shader-compiler-llvm-7/src/lib.rs [deleted file]
shader-compiler-llvm-7/src/tests.rs [deleted file]
shader-compiler/Cargo.toml [deleted file]
shader-compiler/src/backend/mod.rs [deleted file]
shader-compiler/src/backend/types.rs [deleted file]
shader-compiler/src/lib.rs [deleted file]
vulkan-driver/Cargo.toml
vulkan-driver/src/lib.rs

index e4c4905306f43811edc1fd5bc43270a4bc849cd8..be9c38487793a93f85e8f5407b971e0859140542 100644 (file)
@@ -2,8 +2,8 @@
 # Copyright 2018 Jacob Lifshay
 [workspace]
 members = [
-    "shader-compiler",
-    "shader-compiler-llvm-7",
+    "shader-compiler-backend",
+    "shader-compiler-backend-llvm-7",
     "vulkan-driver",
 ]
 
diff --git a/shader-compiler-backend-llvm-7/Cargo.toml b/shader-compiler-backend-llvm-7/Cargo.toml
new file mode 100644 (file)
index 0000000..323b2b8
--- /dev/null
@@ -0,0 +1,24 @@
+# SPDX-License-Identifier: LGPL-2.1-or-later
+# Copyright 2018 Jacob Lifshay
+[package]
+name = "shader-compiler-backend-llvm-7"
+version = "0.1.0"
+authors = ["Jacob Lifshay <programmerjake@gmail.com>"]
+license = "LGPL-2.1-or-later"
+
+[lib]
+crate-type = ["rlib"]
+
+[dependencies]
+shader-compiler-backend = {path = "../shader-compiler-backend"}
+
+[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-backend-llvm-7/build.rs b/shader-compiler-backend-llvm-7/build.rs
new file mode 100644 (file)
index 0000000..c45929b
--- /dev/null
@@ -0,0 +1,310 @@
+// 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("Debug")
+        .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()
+        .chain(llvm_config(llvm_config_path, Some("--system-libs")).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,
+        &["--libs", "orcjit", "native", "analysis"],
+    );
+    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();
+    let build_llvm_bindings = || {
+        let mut retval = cc::Build::new();
+        retval
+            .cpp(true)
+            .file(&llvm_bindings_path)
+            .include(&include_dir);
+        retval
+    };
+    build_llvm_bindings()
+        .cpp_link_stdlib(None)
+        .compile("llvm_bindings");
+    for lib in llvm_libs {
+        println!("cargo:rustc-link-lib={}", lib);
+    }
+    // build twice to get the c++ standard library linked after LLVM with llvm_bindings before LLVM
+    build_llvm_bindings().compile("llvm_bindings");
+}
diff --git a/shader-compiler-backend-llvm-7/src/backend.rs b/shader-compiler-backend-llvm-7/src/backend.rs
new file mode 100644 (file)
index 0000000..95bfa5a
--- /dev/null
@@ -0,0 +1,655 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+// Copyright 2018 Jacob Lifshay
+use llvm;
+use shader_compiler_backend as backend;
+use std::cell::RefCell;
+use std::collections::HashMap;
+use std::collections::HashSet;
+use std::ffi::{CStr, CString};
+use std::fmt;
+use std::hash::Hash;
+use std::mem;
+use std::mem::ManuallyDrop;
+use std::ops::Deref;
+use std::os::raw::{c_char, c_uint};
+use std::ptr::null_mut;
+use std::ptr::NonNull;
+use std::sync::{Once, ONCE_INIT};
+
+fn to_bool(v: llvm::LLVMBool) -> bool {
+    v != 0
+}
+
+#[derive(Clone)]
+pub struct LLVM7CompilerConfig {
+    pub variable_vector_length_multiplier: u32,
+    pub optimization_mode: backend::OptimizationMode,
+}
+
+impl Default for LLVM7CompilerConfig {
+    fn default() -> Self {
+        backend::CompilerIndependentConfig::default().into()
+    }
+}
+
+impl From<backend::CompilerIndependentConfig> for LLVM7CompilerConfig {
+    fn from(v: backend::CompilerIndependentConfig) -> Self {
+        let backend::CompilerIndependentConfig { optimization_mode } = v;
+        Self {
+            variable_vector_length_multiplier: 1,
+            optimization_mode,
+        }
+    }
+}
+
+#[repr(transparent)]
+struct LLVM7String(NonNull<c_char>);
+
+impl Drop for LLVM7String {
+    fn drop(&mut self) {
+        unsafe {
+            llvm::LLVMDisposeMessage(self.0.as_ptr());
+        }
+    }
+}
+
+impl Deref for LLVM7String {
+    type Target = CStr;
+    fn deref(&self) -> &CStr {
+        unsafe { CStr::from_ptr(self.0.as_ptr()) }
+    }
+}
+
+impl Clone for LLVM7String {
+    fn clone(&self) -> Self {
+        Self::new(self)
+    }
+}
+
+impl LLVM7String {
+    fn new(v: &CStr) -> Self {
+        unsafe { Self::from_ptr(llvm::LLVMCreateMessage(v.as_ptr())).unwrap() }
+    }
+    unsafe fn from_nonnull(v: NonNull<c_char>) -> Self {
+        LLVM7String(v)
+    }
+    unsafe fn from_ptr(v: *mut c_char) -> Option<Self> {
+        NonNull::new(v).map(|v| Self::from_nonnull(v))
+    }
+}
+
+impl fmt::Debug for LLVM7String {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        (**self).fmt(f)
+    }
+}
+
+#[derive(Clone, Eq, PartialEq, Hash)]
+#[repr(transparent)]
+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::LLVMPrintTypeToString(self.0)).ok_or(fmt::Error)?;
+            f.write_str(&string.to_string_lossy())
+        }
+    }
+}
+
+impl<'a> backend::types::Type<'a> for LLVM7Type {
+    type Context = LLVM7Context;
+}
+
+pub struct LLVM7TypeBuilder {
+    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::LLVMInt1TypeInContext(self.context)) }
+    }
+    fn build_i8(&self) -> LLVM7Type {
+        unsafe { LLVM7Type(llvm::LLVMInt8TypeInContext(self.context)) }
+    }
+    fn build_i16(&self) -> LLVM7Type {
+        unsafe { LLVM7Type(llvm::LLVMInt16TypeInContext(self.context)) }
+    }
+    fn build_i32(&self) -> LLVM7Type {
+        unsafe { LLVM7Type(llvm::LLVMInt32TypeInContext(self.context)) }
+    }
+    fn build_i64(&self) -> LLVM7Type {
+        unsafe { LLVM7Type(llvm::LLVMInt64TypeInContext(self.context)) }
+    }
+    fn build_f32(&self) -> LLVM7Type {
+        unsafe { LLVM7Type(llvm::LLVMFloatTypeInContext(self.context)) }
+    }
+    fn build_f64(&self) -> LLVM7Type {
+        unsafe { LLVM7Type(llvm::LLVMDoubleTypeInContext(self.context)) }
+    }
+    fn build_pointer(&self, target: LLVM7Type) -> LLVM7Type {
+        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::LLVMArrayType(element.0, count as u32)) }
+    }
+    fn build_vector(&self, element: LLVM7Type, length: backend::types::VectorLength) -> LLVM7Type {
+        use self::backend::types::VectorLength::*;
+        let length = match length {
+            Fixed { length } => length,
+            Variable { base_length } => base_length
+                .checked_mul(self.variable_vector_length_multiplier)
+                .unwrap(),
+        };
+        assert_ne!(length, 0);
+        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::LLVMStructTypeInContext(
+                self.context,
+                members.as_ptr() as *mut llvm::LLVMTypeRef,
+                members.len() as c_uint,
+                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::LLVMFunctionType(
+                return_type
+                    .unwrap_or_else(|| LLVM7Type(llvm::LLVMVoidTypeInContext(self.context)))
+                    .0,
+                arguments.as_ptr() as *mut llvm::LLVMTypeRef,
+                arguments.len() as c_uint,
+                false as llvm::LLVMBool,
+            ))
+        }
+    }
+}
+
+#[derive(Clone)]
+#[repr(transparent)]
+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::LLVMPrintValueToString(self.0)).ok_or(fmt::Error)?;
+            f.write_str(&string.to_string_lossy())
+        }
+    }
+}
+
+impl<'a> backend::Value<'a> for LLVM7Value {
+    type Context = LLVM7Context;
+}
+
+#[derive(Clone)]
+#[repr(transparent)]
+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::LLVMPrintValueToString(self.as_value().0))
+                .ok_or(fmt::Error)?;
+            f.write_str(&string.to_string_lossy())
+        }
+    }
+}
+
+impl<'a> backend::BasicBlock<'a> for LLVM7BasicBlock {
+    type Context = LLVM7Context;
+    fn as_value(&self) -> LLVM7Value {
+        unsafe { LLVM7Value(llvm::LLVMBasicBlockAsValue(self.0)) }
+    }
+}
+
+impl<'a> backend::BuildableBasicBlock<'a> for LLVM7BasicBlock {
+    type Context = LLVM7Context;
+    fn as_basic_block(&self) -> LLVM7BasicBlock {
+        self.clone()
+    }
+}
+
+pub struct LLVM7Function {
+    context: llvm::LLVMContextRef,
+    function: llvm::LLVMValueRef,
+    parameters: Box<[LLVM7Value]>,
+}
+
+impl fmt::Debug for LLVM7Function {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        unsafe {
+            let string = LLVM7String::from_ptr(llvm::LLVMPrintValueToString(self.function))
+                .ok_or(fmt::Error)?;
+            f.write_str(&string.to_string_lossy())
+        }
+    }
+}
+
+impl<'a> backend::Function<'a> for LLVM7Function {
+    type Context = LLVM7Context;
+    fn as_value(&self) -> LLVM7Value {
+        LLVM7Value(self.function)
+    }
+    fn append_new_basic_block(&mut self, name: Option<&str>) -> LLVM7BasicBlock {
+        let name = CString::new(name.unwrap_or("")).unwrap();
+        unsafe {
+            LLVM7BasicBlock(llvm::LLVMAppendBasicBlockInContext(
+                self.context,
+                self.function,
+                name.as_ptr(),
+            ))
+        }
+    }
+    fn parameters(&self) -> &[LLVM7Value] {
+        &self.parameters
+    }
+}
+
+pub struct LLVM7Context {
+    context: Option<ManuallyDrop<OwnedContext>>,
+    modules: ManuallyDrop<RefCell<Vec<OwnedModule>>>,
+    config: LLVM7CompilerConfig,
+}
+
+impl Drop for LLVM7Context {
+    fn drop(&mut self) {
+        unsafe {
+            ManuallyDrop::drop(&mut self.modules);
+            if let Some(context) = &mut self.context {
+                ManuallyDrop::drop(context);
+            }
+        }
+    }
+}
+
+impl<'a> backend::Context<'a> for LLVM7Context {
+    type Value = LLVM7Value;
+    type BasicBlock = LLVM7BasicBlock;
+    type BuildableBasicBlock = LLVM7BasicBlock;
+    type Function = LLVM7Function;
+    type Type = LLVM7Type;
+    type TypeBuilder = LLVM7TypeBuilder;
+    type Module = LLVM7Module;
+    type VerifiedModule = LLVM7Module;
+    type AttachedBuilder = LLVM7Builder;
+    type DetachedBuilder = LLVM7Builder;
+    fn create_module(&self, name: &str) -> LLVM7Module {
+        let name = CString::new(name).unwrap();
+        let mut modules = self.modules.borrow_mut();
+        unsafe {
+            let module = OwnedModule(llvm::LLVMModuleCreateWithNameInContext(
+                name.as_ptr(),
+                self.context.as_ref().unwrap().0,
+            ));
+            let module_ref = module.0;
+            modules.push(module);
+            LLVM7Module {
+                context: self.context.as_ref().unwrap().0,
+                module: module_ref,
+                name_set: HashSet::new(),
+            }
+        }
+    }
+    fn create_builder(&self) -> LLVM7Builder {
+        unsafe {
+            LLVM7Builder(llvm::LLVMCreateBuilderInContext(
+                self.context.as_ref().unwrap().0,
+            ))
+        }
+    }
+    fn create_type_builder(&self) -> LLVM7TypeBuilder {
+        LLVM7TypeBuilder {
+            context: self.context.as_ref().unwrap().0,
+            variable_vector_length_multiplier: self.config.variable_vector_length_multiplier,
+        }
+    }
+}
+
+#[repr(transparent)]
+pub struct LLVM7Builder(llvm::LLVMBuilderRef);
+
+impl Drop for LLVM7Builder {
+    fn drop(&mut self) {
+        unsafe {
+            llvm::LLVMDisposeBuilder(self.0);
+        }
+    }
+}
+
+impl<'a> backend::AttachedBuilder<'a> for LLVM7Builder {
+    type Context = LLVM7Context;
+    fn current_basic_block(&self) -> LLVM7BasicBlock {
+        unsafe { LLVM7BasicBlock(llvm::LLVMGetInsertBlock(self.0)) }
+    }
+    fn build_return(self, value: Option<LLVM7Value>) -> LLVM7Builder {
+        unsafe {
+            match value {
+                Some(value) => llvm::LLVMBuildRet(self.0, value.0),
+                None => llvm::LLVMBuildRetVoid(self.0),
+            };
+            llvm::LLVMClearInsertionPosition(self.0);
+        }
+        self
+    }
+}
+
+impl<'a> backend::DetachedBuilder<'a> for LLVM7Builder {
+    type Context = LLVM7Context;
+    fn attach(self, basic_block: LLVM7BasicBlock) -> LLVM7Builder {
+        unsafe {
+            llvm::LLVMPositionBuilderAtEnd(self.0, basic_block.0);
+        }
+        self
+    }
+}
+
+struct OwnedModule(llvm::LLVMModuleRef);
+
+impl Drop for OwnedModule {
+    fn drop(&mut self) {
+        unsafe {
+            llvm::LLVMDisposeModule(self.0);
+        }
+    }
+}
+
+impl OwnedModule {
+    unsafe fn take(mut self) -> llvm::LLVMModuleRef {
+        let retval = self.0;
+        self.0 = null_mut();
+        retval
+    }
+}
+
+struct OwnedContext(llvm::LLVMContextRef);
+
+impl Drop for OwnedContext {
+    fn drop(&mut self) {
+        unsafe {
+            llvm::LLVMContextDispose(self.0);
+        }
+    }
+}
+
+pub struct LLVM7Module {
+    context: llvm::LLVMContextRef,
+    module: llvm::LLVMModuleRef,
+    name_set: HashSet<String>,
+}
+
+impl fmt::Debug for LLVM7Module {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        unsafe {
+            let string = LLVM7String::from_ptr(llvm::LLVMPrintModuleToString(self.module))
+                .ok_or(fmt::Error)?;
+            f.write_str(&string.to_string_lossy())
+        }
+    }
+}
+
+impl<'a> backend::Module<'a> for LLVM7Module {
+    type Context = LLVM7Context;
+    fn set_source_file_name(&mut self, source_file_name: &str) {
+        unsafe {
+            llvm::LLVMSetSourceFileName(
+                self.module,
+                source_file_name.as_ptr() as *const c_char,
+                source_file_name.len(),
+            )
+        }
+    }
+    fn add_function(&mut self, name: &str, ty: LLVM7Type) -> LLVM7Function {
+        fn is_start_char(c: char) -> bool {
+            if c.is_ascii_alphabetic() {
+                true
+            } else {
+                match c {
+                    '_' | '.' | '$' | '-' => true,
+                    _ => false,
+                }
+            }
+        }
+        fn is_continue_char(c: char) -> bool {
+            is_start_char(c) || c.is_ascii_digit()
+        }
+        assert!(is_start_char(name.chars().next().unwrap()));
+        assert!(name.chars().all(is_continue_char));
+        assert!(self.name_set.insert(name.into()));
+        let name = CString::new(name).unwrap();
+        unsafe {
+            let function = llvm::LLVMAddFunction(self.module, name.as_ptr(), ty.0);
+            let mut parameters = Vec::new();
+            parameters.resize(llvm::LLVMCountParams(function) as usize, null_mut());
+            llvm::LLVMGetParams(function, parameters.as_mut_ptr());
+            let parameters: Vec<_> = parameters.into_iter().map(LLVM7Value).collect();
+            LLVM7Function {
+                context: self.context,
+                function: llvm::LLVMAddFunction(self.module, name.as_ptr(), ty.0),
+                parameters: parameters.into_boxed_slice(),
+            }
+        }
+    }
+    fn verify(self) -> Result<LLVM7Module, backend::VerificationFailure<'a, LLVM7Module>> {
+        unsafe {
+            let mut message = null_mut();
+            let broken = to_bool(llvm::LLVMVerifyModule(
+                self.module,
+                llvm::LLVMReturnStatusAction,
+                &mut message,
+            ));
+            if broken {
+                let message = LLVM7String::from_ptr(message).unwrap();
+                let message = message.to_string_lossy();
+                Err(backend::VerificationFailure::new(self, message.as_ref()))
+            } else {
+                Ok(self)
+            }
+        }
+    }
+    unsafe fn to_verified_module_unchecked(self) -> LLVM7Module {
+        self
+    }
+}
+
+impl<'a> backend::VerifiedModule<'a> for LLVM7Module {
+    type Context = LLVM7Context;
+    fn into_module(self) -> LLVM7Module {
+        self
+    }
+}
+
+struct LLVM7TargetMachine(llvm::LLVMTargetMachineRef);
+
+impl Drop for LLVM7TargetMachine {
+    fn drop(&mut self) {
+        unsafe {
+            llvm::LLVMDisposeTargetMachine(self.0);
+        }
+    }
+}
+
+impl LLVM7TargetMachine {
+    fn take(mut self) -> llvm::LLVMTargetMachineRef {
+        let retval = self.0;
+        self.0 = null_mut();
+        retval
+    }
+}
+
+struct LLVM7OrcJITStack(llvm::LLVMOrcJITStackRef);
+
+impl Drop for LLVM7OrcJITStack {
+    fn drop(&mut self) {
+        unsafe {
+            match llvm::LLVMOrcDisposeInstance(self.0) {
+                llvm::LLVMOrcErrSuccess => {}
+                _ => {
+                    panic!("LLVMOrcDisposeInstance failed");
+                }
+            }
+        }
+    }
+}
+
+fn initialize_native_target() {
+    static ONCE: Once = ONCE_INIT;
+    ONCE.call_once(|| unsafe {
+        llvm::LLVM_InitializeNativeTarget();
+        llvm::LLVM_InitializeNativeAsmPrinter();
+        llvm::LLVM_InitializeNativeAsmParser();
+    });
+}
+
+extern "C" fn symbol_resolver_fn<Void>(name: *const c_char, _lookup_context: *mut Void) -> u64 {
+    let name = unsafe { CStr::from_ptr(name) };
+    panic!("symbol_resolver_fn is unimplemented: name = {:?}", name)
+}
+
+#[derive(Copy, Clone)]
+pub struct LLVM7Compiler;
+
+impl backend::Compiler for LLVM7Compiler {
+    type Config = LLVM7CompilerConfig;
+    fn name(self) -> &'static str {
+        "LLVM 7"
+    }
+    fn run<U: backend::CompilerUser>(
+        self,
+        user: U,
+        config: LLVM7CompilerConfig,
+    ) -> Result<Box<dyn backend::CompiledCode<U::FunctionKey>>, U::Error> {
+        unsafe {
+            initialize_native_target();
+            let context = OwnedContext(llvm::LLVMContextCreate());
+            let modules = Vec::new();
+            let mut context = LLVM7Context {
+                context: Some(ManuallyDrop::new(context)),
+                modules: ManuallyDrop::new(RefCell::new(modules)),
+                config: config.clone(),
+            };
+            let backend::CompileInputs {
+                module,
+                callable_functions,
+            } = user.run(&context)?;
+            let callable_functions: Vec<_> = callable_functions
+                .into_iter()
+                .map(|(key, callable_function)| {
+                    assert_eq!(
+                        llvm::LLVMGetGlobalParent(callable_function.function),
+                        module.module
+                    );
+                    let name: CString =
+                        CStr::from_ptr(llvm::LLVMGetValueName(callable_function.function)).into();
+                    assert_ne!(name.to_bytes().len(), 0);
+                    (key, name)
+                })
+                .collect();
+            let module = context
+                .modules
+                .get_mut()
+                .drain(..)
+                .find(|v| v.0 == module.module)
+                .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::LLVMGetTargetFromTriple(
+                target_triple.as_ptr(),
+                &mut target,
+                &mut error,
+            ));
+            if !success {
+                let error = LLVM7String::from_ptr(error).unwrap();
+                return Err(U::create_error(error.to_string_lossy().into()));
+            }
+            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::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::LLVMOrcCreateInstance(target_machine.take()));
+            let mut module_handle = 0;
+            if llvm::LLVMOrcErrSuccess != llvm::LLVMOrcAddEagerlyCompiledIR(
+                orc_jit_stack.0,
+                &mut module_handle,
+                module.take(),
+                Some(symbol_resolver_fn),
+                null_mut(),
+            ) {
+                return Err(U::create_error("compilation failed".into()));
+            }
+            let mut functions: HashMap<_, _> = HashMap::new();
+            for (key, name) in callable_functions {
+                let mut address: llvm::LLVMOrcTargetAddress = mem::zeroed();
+                if llvm::LLVMOrcErrSuccess != llvm::LLVMOrcGetSymbolAddressIn(
+                    orc_jit_stack.0,
+                    &mut address,
+                    module_handle,
+                    name.as_ptr(),
+                ) {
+                    return Err(U::create_error(format!(
+                        "function not found in compiled module: {:?}",
+                        name
+                    )));
+                }
+                let address: Option<unsafe extern "C" fn()> = mem::transmute(address as usize);
+                if functions.insert(key, address.unwrap()).is_some() {
+                    return Err(U::create_error(format!("duplicate function: {:?}", name)));
+                }
+            }
+            struct CompiledCode<K: Hash + Eq + Send + Sync + 'static> {
+                functions: HashMap<K, unsafe extern "C" fn()>,
+                orc_jit_stack: ManuallyDrop<LLVM7OrcJITStack>,
+                context: ManuallyDrop<OwnedContext>,
+            }
+            unsafe impl<K: Hash + Eq + Send + Sync + 'static> Send for CompiledCode<K> {}
+            unsafe impl<K: Hash + Eq + Send + Sync + 'static> Sync for CompiledCode<K> {}
+            impl<K: Hash + Eq + Send + Sync + 'static> Drop for CompiledCode<K> {
+                fn drop(&mut self) {
+                    unsafe {
+                        ManuallyDrop::drop(&mut self.orc_jit_stack);
+                        ManuallyDrop::drop(&mut self.context);
+                    }
+                }
+            }
+            impl<K: Hash + Eq + Send + Sync + 'static> backend::CompiledCode<K> for CompiledCode<K> {
+                fn get(&self, key: &K) -> Option<unsafe extern "C" fn()> {
+                    Some(*self.functions.get(key)?)
+                }
+            }
+            Ok(Box::new(CompiledCode {
+                functions,
+                orc_jit_stack: ManuallyDrop::new(orc_jit_stack),
+                context: context.context.take().unwrap(),
+            }))
+        }
+    }
+}
diff --git a/shader-compiler-backend-llvm-7/src/lib.rs b/shader-compiler-backend-llvm-7/src/lib.rs
new file mode 100644 (file)
index 0000000..c840645
--- /dev/null
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+// Copyright 2018 Jacob Lifshay
+extern crate shader_compiler_backend;
+
+#[cfg_attr(
+    feature = "cargo-clippy",
+    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;
+
+pub use backend::LLVM7CompilerConfig;
+
+pub const LLVM_7_SHADER_COMPILER: backend::LLVM7Compiler = backend::LLVM7Compiler;
diff --git a/shader-compiler-backend-llvm-7/src/tests.rs b/shader-compiler-backend-llvm-7/src/tests.rs
new file mode 100644 (file)
index 0000000..a679e71
--- /dev/null
@@ -0,0 +1,100 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+// Copyright 2018 Jacob Lifshay
+#[cfg(test)]
+// we have a tests module inside a tests module to have rls parse this tests.rs file
+#[cfg_attr(feature = "cargo-clippy", allow(clippy::module_inception))]
+mod tests {
+    use shader_compiler_backend::types::TypeBuilder;
+    use shader_compiler_backend::*;
+    use std::mem;
+
+    fn make_compiler() -> impl Compiler {
+        ::LLVM_7_SHADER_COMPILER
+    }
+
+    #[test]
+    fn test_basic() {
+        type GeneratedFunctionType = unsafe extern "C" fn(u32);
+        #[derive(Copy, Clone, Hash, Eq, PartialEq, Debug)]
+        enum FunctionKey {
+            Function,
+        }
+        struct Test;
+        impl CompilerUser for Test {
+            type FunctionKey = FunctionKey;
+            type Error = String;
+            fn create_error(message: String) -> String {
+                message
+            }
+            fn run<'a, C: Context<'a>>(
+                self,
+                context: &'a C,
+            ) -> Result<CompileInputs<'a, C, FunctionKey>, String> {
+                let type_builder = context.create_type_builder();
+                let mut module = context.create_module("test_module");
+                let mut function = module.add_function(
+                    "test_function",
+                    type_builder.build::<GeneratedFunctionType>(),
+                );
+                let builder = context.create_builder();
+                let builder = builder.attach(function.append_new_basic_block(None));
+                builder.build_return(None);
+                let module = module.verify().unwrap();
+                Ok(CompileInputs {
+                    module,
+                    callable_functions: vec![(FunctionKey::Function, function)]
+                        .into_iter()
+                        .collect(),
+                })
+            }
+        }
+        let compiled_code = make_compiler().run(Test, Default::default()).unwrap();
+        let function = compiled_code.get(&FunctionKey::Function).unwrap();
+        unsafe {
+            let function: GeneratedFunctionType = mem::transmute(function);
+            function(0);
+        }
+    }
+
+    #[test]
+    fn test_names() {
+        const NAMES: &[&str] = &["main", "abc123-$._"];
+        type GeneratedFunctionType = unsafe extern "C" fn(u32);
+        #[derive(Copy, Clone, Hash, Eq, PartialEq, Debug)]
+        struct Test;
+        impl CompilerUser for Test {
+            type FunctionKey = String;
+            type Error = String;
+            fn create_error(message: String) -> String {
+                message
+            }
+            fn run<'a, C: Context<'a>>(
+                self,
+                context: &'a C,
+            ) -> Result<CompileInputs<'a, C, String>, String> {
+                let type_builder = context.create_type_builder();
+                let mut module = context.create_module("test_module");
+                let mut functions = Vec::new();
+                let mut detached_builder = context.create_builder();
+                for name in NAMES {
+                    let mut function =
+                        module.add_function(name, type_builder.build::<GeneratedFunctionType>());
+                    let builder = detached_builder.attach(function.append_new_basic_block(None));
+                    detached_builder = builder.build_return(None);
+                    functions.push((name.to_string(), function));
+                }
+                let module = module.verify().unwrap();
+                Ok(CompileInputs {
+                    module,
+                    callable_functions: functions.into_iter().collect(),
+                })
+            }
+        }
+        let compiled_code = make_compiler().run(Test, Default::default()).unwrap();
+        let function = compiled_code.get(&"main".to_string()).unwrap();
+        unsafe {
+            let function: GeneratedFunctionType = mem::transmute(function);
+            function(0);
+        }
+    }
+}
diff --git a/shader-compiler-backend/Cargo.toml b/shader-compiler-backend/Cargo.toml
new file mode 100644 (file)
index 0000000..ec8fc80
--- /dev/null
@@ -0,0 +1,12 @@
+# SPDX-License-Identifier: LGPL-2.1-or-later
+# Copyright 2018 Jacob Lifshay
+[package]
+name = "shader-compiler-backend"
+version = "0.1.0"
+authors = ["Jacob Lifshay <programmerjake@gmail.com>"]
+license = "LGPL-2.1-or-later"
+
+[lib]
+crate-type = ["rlib"]
+
+[dependencies]
diff --git a/shader-compiler-backend/src/lib.rs b/shader-compiler-backend/src/lib.rs
new file mode 100644 (file)
index 0000000..0c3e1c3
--- /dev/null
@@ -0,0 +1,275 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+// Copyright 2018 Jacob Lifshay
+#![deny(missing_docs)]
+
+//! Shader Compiler Backend Traits for Kazan
+
+use std::collections::HashMap;
+use std::error::Error;
+use std::fmt;
+use std::fmt::Debug;
+use std::hash::Hash;
+use std::io;
+use std::marker::PhantomData;
+
+#[macro_use]
+pub mod types;
+
+/// equivalent to LLVM's 'IRBuilder'
+pub trait AttachedBuilder<'a>: Sized {
+    /// the `Context` type
+    type Context: Context<'a>;
+    /// get the current `BasicBlock`
+    fn current_basic_block(&self) -> <Self::Context as Context<'a>>::BasicBlock;
+    /// build a return instruction
+    fn build_return(
+        self,
+        value: Option<<Self::Context as Context<'a>>::Value>,
+    ) -> <Self::Context as Context<'a>>::DetachedBuilder;
+}
+
+/// equivalent to LLVM's 'IRBuilder'
+pub trait DetachedBuilder<'a>: Sized {
+    /// the `Context` type
+    type Context: Context<'a>;
+    /// attach `basic_block` to `Self`, converting into an `AttachedBuilder`
+    fn attach(
+        self,
+        basic_block: <Self::Context as Context<'a>>::BuildableBasicBlock,
+    ) -> <Self::Context as Context<'a>>::AttachedBuilder;
+}
+
+/// equivalent to LLVM's 'Value'
+pub trait Value<'a>: Clone + Debug {
+    /// the `Context` type
+    type Context: Context<'a>;
+}
+
+/// equivalent to LLVM's 'BasicBlock'
+pub trait BasicBlock<'a>: Clone + Debug {
+    /// the `Context` type
+    type Context: Context<'a>;
+    /// get the `Value` corresponding to `Self`
+    fn as_value(&self) -> <Self::Context as Context<'a>>::Value;
+}
+
+/// equivalent to LLVM's 'BasicBlock'
+pub trait BuildableBasicBlock<'a>: Debug + Sized {
+    /// the `Context` type
+    type Context: Context<'a>;
+    /// get the `BasicBlock` corresponding to `Self`
+    fn as_basic_block(&self) -> <Self::Context as Context<'a>>::BasicBlock;
+    /// get the `Value` corresponding to `Self`
+    fn as_value(&self) -> <Self::Context as Context<'a>>::Value {
+        self.as_basic_block().as_value()
+    }
+}
+
+/// equivalent to LLVM's 'Function'
+pub trait Function<'a>: Debug + Sized {
+    /// the `Context` type
+    type Context: Context<'a>;
+    /// get the `Value` corresponding to `Self`
+    fn as_value(&self) -> <Self::Context as Context<'a>>::Value;
+    /// append a new `BasicBlock` to `Self`
+    fn append_new_basic_block(
+        &mut self,
+        name: Option<&str>,
+    ) -> <Self::Context as Context<'a>>::BuildableBasicBlock;
+    /// get this function's parameters
+    fn parameters(&self) -> &[<Self::Context as Context<'a>>::Value];
+}
+
+/// module verification failure; returned from `Module::verify`
+pub struct VerificationFailure<'a, M: Module<'a>> {
+    module: M,
+    message: String,
+    _phantom_data: PhantomData<&'a ()>,
+}
+
+impl<'a, M: Module<'a>> VerificationFailure<'a, M> {
+    /// create a new `VerificationFailure`
+    pub fn new<T: ToString + ?Sized>(module: M, message: &T) -> Self {
+        VerificationFailure {
+            module,
+            message: message.to_string(),
+            _phantom_data: PhantomData,
+        }
+    }
+    /// get the `Module` that failed verification
+    pub fn into_module(self) -> M {
+        self.module
+    }
+}
+
+impl<'a, M: Module<'a>> fmt::Display for VerificationFailure<'a, M> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "module verification failure: {}", self.message,)
+    }
+}
+
+impl<'a, M: Module<'a>> Debug for VerificationFailure<'a, M> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_struct("VerificationFailure")
+            .field("message", &self.message)
+            .field("module", &self.module)
+            .finish()
+    }
+}
+
+impl<'a, M: Module<'a>> Error for VerificationFailure<'a, M> {}
+
+impl<'a, M: Module<'a>> From<VerificationFailure<'a, M>> for io::Error {
+    fn from(v: VerificationFailure<'a, M>) -> Self {
+        io::Error::new(io::ErrorKind::Other, format!("{}", v))
+    }
+}
+
+/// equivalent to LLVM's 'Module'
+pub trait Module<'a>: Debug + Sized {
+    /// the `Context` type
+    type Context: Context<'a>;
+    /// set's the source file name for this module
+    fn set_source_file_name(&mut self, source_file_name: &str);
+    /// add a new empty function to `Self`
+    fn add_function(
+        &mut self,
+        name: &str,
+        ty: <Self::Context as Context<'a>>::Type,
+    ) -> <Self::Context as Context<'a>>::Function;
+    /// verify `Self`, converting into a `VerifiedModule`
+    fn verify(
+        self,
+    ) -> Result<<Self::Context as Context<'a>>::VerifiedModule, VerificationFailure<'a, Self>>;
+    /// convert into a `VerifiedModule` without verifing
+    unsafe fn to_verified_module_unchecked(self) -> <Self::Context as Context<'a>>::VerifiedModule;
+}
+
+/// equivalent to LLVM's 'Module'; create using `Module::verify` or `Module::to_verified_module_unchecked`
+pub trait VerifiedModule<'a>: Debug + Sized {
+    /// the `Context` type
+    type Context: Context<'a>;
+    /// convert back to an unverified module
+    fn into_module(self) -> <Self::Context as Context<'a>>::Module;
+}
+
+/// instance of a compiler backend; equivalent to LLVM's `LLVMContext`
+pub trait Context<'a>: Sized {
+    /// the `Value` type
+    type Value: Value<'a, Context = Self>;
+    /// the `BasicBlock` type
+    type BasicBlock: BasicBlock<'a, Context = Self>;
+    /// the `BuildableBasicBlock` type
+    type BuildableBasicBlock: BuildableBasicBlock<'a, Context = Self>;
+    /// the `Function` type
+    type Function: Function<'a, Context = Self>;
+    /// the `Module` type
+    type Module: Module<'a, Context = Self>;
+    /// the `VerifiedModule` type
+    type VerifiedModule: VerifiedModule<'a, Context = Self>;
+    /// the `AttachedBuilder` type
+    type AttachedBuilder: AttachedBuilder<'a, Context = Self>;
+    /// the `DetachedBuilder` type
+    type DetachedBuilder: DetachedBuilder<'a, Context = Self>;
+    /// the `Type` type
+    type Type: types::Type<'a, Context = Self>;
+    /// the `TypeBuilder` type
+    type TypeBuilder: types::TypeBuilder<'a, Self::Type>;
+    /// create a new `Module`
+    fn create_module(&self, name: &str) -> Self::Module;
+    /// create a new `DetachedBuilder`
+    fn create_builder(&self) -> Self::DetachedBuilder;
+    /// create a new `TypeBuilder`
+    fn create_type_builder(&self) -> Self::TypeBuilder;
+}
+
+/// inputs to the final compilation
+pub struct CompileInputs<'a, C: Context<'a>, K: Hash + Eq + Send + Sync + 'static> {
+    /// the input module
+    pub module: C::VerifiedModule,
+    /// the list of functions that can be called from the final `CompiledCode`
+    pub callable_functions: HashMap<K, C::Function>,
+}
+
+/// the final compiled code
+pub trait CompiledCode<K: Hash + Eq + Send + Sync + 'static>: Send + Sync {
+    /// get a function in the final compiled code.
+    /// the returned function needs to be cast to the correct type and
+    /// `Self` needs to still exist while the returned function exists
+    fn get(&self, which: &K) -> Option<unsafe extern "C" fn()>;
+}
+
+/// trait that the user of `Compiler` implements
+pub trait CompilerUser {
+    /// the type used as a key for visible functions
+    type FunctionKey: Hash + Eq + Send + Sync + 'static;
+    /// the user's error type
+    type Error;
+    /// create an instance of `Error`
+    fn create_error(message: String) -> Self::Error;
+    /// the function that the user of `Compiler` implements
+    fn run<'a, C: Context<'a>>(
+        self,
+        context: &'a C,
+    ) -> Result<CompileInputs<'a, C, Self::FunctionKey>, Self::Error>;
+}
+
+/// optimization mode
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+pub enum OptimizationMode {
+    /// no optimizations are enabled
+    NoOptimizations,
+    /// default optimizations are enabled
+    Normal,
+}
+
+impl Default for OptimizationMode {
+    fn default() -> Self {
+        OptimizationMode::Normal
+    }
+}
+
+/// compiler independent config options
+#[derive(Clone, Debug, Default)]
+pub struct CompilerIndependentConfig {
+    /// optimization mode
+    pub optimization_mode: OptimizationMode,
+}
+
+/// main compiler backend trait
+pub trait Compiler: Copy + Send + Sync + 'static {
+    /// the compiler's configuration
+    type Config: Default + Clone + From<CompilerIndependentConfig> + Send + Sync;
+    /// get shader compiler's name
+    fn name(self) -> &'static str;
+    /// run a passed-in function with a new compiler context.
+    /// this round-about method is used because generic associated types are not in stable Rust yet
+    fn run<U: CompilerUser>(
+        self,
+        user: U,
+        config: Self::Config,
+    ) -> Result<Box<dyn CompiledCode<U::FunctionKey>>, U::Error>;
+}
+
+#[cfg(test)]
+mod test {
+    #![allow(dead_code)]
+
+    buildable_struct!{
+        struct S1 {
+        }
+    }
+
+    buildable_struct!{
+        pub struct S2 {
+            v: u32,
+        }
+    }
+
+    buildable_struct!{
+        struct S3 {
+            p: *mut S2,
+            v: ::types::VecNx4<f32>,
+        }
+    }
+}
diff --git a/shader-compiler-backend/src/types.rs b/shader-compiler-backend/src/types.rs
new file mode 100644 (file)
index 0000000..19167c8
--- /dev/null
@@ -0,0 +1,553 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+// Copyright 2018 Jacob Lifshay
+
+//! types in backend IR
+
+use super::Context;
+use std::cell::UnsafeCell;
+use std::fmt::Debug;
+use std::hash::Hash;
+use std::marker::PhantomData;
+use std::ops::{Deref, DerefMut};
+use std::ptr::NonNull;
+
+#[macro_export]
+macro_rules! buildable_struct_helper {
+    {
+        struct $name:ident {
+            $($member_name:ident: $member_type:ty,)*
+        }
+    } => {
+        impl $crate::types::BuildableType for $name {
+            fn build<'a, Ty: $crate::types::Type<'a>, TB: $crate::types::TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
+                type_builder.build_struct(&[$(<$member_type as $crate::types::BuildableType>::build(type_builder),)*])
+            }
+        }
+
+        impl $crate::types::BuildableStruct for $name {
+            fn get_members(
+            ) -> &'static [$crate::types::BuildableStructMemberDescriptor] {
+                #[allow(dead_code, non_camel_case_types)]
+                #[repr(usize)]
+                enum MemberIndices {
+                    $($member_name,)*
+                    __Last,
+                }
+                const MEMBERS: &'static [$crate::types::BuildableStructMemberDescriptor] = &[
+                    $($crate::types::BuildableStructMemberDescriptor {
+                        name: stringify!($member_name),
+                        index: MemberIndices::$member_name as usize,
+                    },)*
+                ];
+                MEMBERS
+            }
+        }
+    }
+}
+
+#[macro_export]
+macro_rules! buildable_struct {
+    {
+        $(#[derive($derives:ident)])*
+        pub struct $name:ident {
+            $($member_name:ident: $member_type:ty,)*
+        }
+    } => {
+        $(#[derive($derives)])*
+        #[repr(C)]
+        pub struct $name {
+            $($member_name: $member_type,)*
+        }
+
+        buildable_struct_helper!{
+            struct $name {
+                $($member_name: $member_type,)*
+            }
+        }
+    };
+    {
+        $(#[derive($derives:ident)])*
+        struct $name:ident {
+            $($member_name:ident: $member_type:ty,)*
+        }
+    } => {
+        $(#[derive($derives)])*
+        #[repr(C)]
+        struct $name {
+            $($member_name: $member_type,)*
+        }
+
+        buildable_struct_helper!{
+            struct $name {
+                $($member_name: $member_type,)*
+            }
+        }
+    };
+}
+
+/// length of a vector
+pub enum VectorLength {
+    /// fixed length vector
+    Fixed {
+        /// length in elements
+        length: u32,
+    },
+    /// variable length vector
+    Variable {
+        /// base length in elements which the runtime vector length is a multiple of
+        base_length: u32,
+    },
+}
+
+/// equivalent to LLVM's 'Type'
+pub trait Type<'a>: Clone + Eq + Hash + Debug {
+    /// the `Context` type
+    type Context: Context<'a>;
+}
+
+/// trait for building types
+pub trait TypeBuilder<'a, Ty: Type<'a>> {
+    /// build a `bool` type
+    fn build_bool(&self) -> Ty;
+    /// build an 8-bit sign-agnostic integer type
+    fn build_i8(&self) -> Ty;
+    /// build an 16-bit sign-agnostic integer type
+    fn build_i16(&self) -> Ty;
+    /// build an 32-bit sign-agnostic integer type
+    fn build_i32(&self) -> Ty;
+    /// build an 64-bit sign-agnostic integer type
+    fn build_i64(&self) -> Ty;
+    /// build an 32-bit IEEE 754 floating-point type
+    fn build_f32(&self) -> Ty;
+    /// build an 64-bit IEEE 754 floating-point type
+    fn build_f64(&self) -> Ty;
+    /// build a pointer
+    fn build_pointer(&self, target: Ty) -> Ty;
+    /// build an array
+    fn build_array(&self, element: Ty, count: usize) -> Ty;
+    /// build a vector
+    fn build_vector(&self, element: Ty, length: VectorLength) -> Ty;
+    /// build a struct
+    fn build_struct(&self, members: &[Ty]) -> Ty;
+    /// build a function type
+    fn build_function(&self, arguments: &[Ty], return_type: Option<Ty>) -> Ty;
+    /// build a type
+    fn build<T: BuildableType>(&self) -> Ty
+    where
+        Self: Sized,
+    {
+        T::build(self)
+    }
+}
+
+impl<'a, 'b, Ty: Type<'a>> TypeBuilder<'a, Ty> for &'b TypeBuilder<'a, Ty> {
+    fn build_bool(&self) -> Ty {
+        (*self).build_bool()
+    }
+    fn build_i8(&self) -> Ty {
+        (*self).build_i8()
+    }
+    fn build_i16(&self) -> Ty {
+        (*self).build_i16()
+    }
+    fn build_i32(&self) -> Ty {
+        (*self).build_i32()
+    }
+    fn build_i64(&self) -> Ty {
+        (*self).build_i64()
+    }
+    fn build_f32(&self) -> Ty {
+        (*self).build_f32()
+    }
+    fn build_f64(&self) -> Ty {
+        (*self).build_f64()
+    }
+    fn build_pointer(&self, target: Ty) -> Ty {
+        (*self).build_pointer(target)
+    }
+    fn build_array(&self, element: Ty, count: usize) -> Ty {
+        (*self).build_array(element, count)
+    }
+    fn build_vector(&self, element: Ty, length: VectorLength) -> Ty {
+        (*self).build_vector(element, length)
+    }
+    fn build_struct(&self, members: &[Ty]) -> Ty {
+        (*self).build_struct(members)
+    }
+    fn build_function(&self, arguments: &[Ty], return_type: Option<Ty>) -> Ty {
+        (*self).build_function(arguments, return_type)
+    }
+}
+
+/// trait for rust types that can be built using `TypeBuilder`
+pub trait BuildableType {
+    /// build the type represented by `Self`
+    fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty;
+}
+
+impl<T: BuildableType> BuildableType for UnsafeCell<T> {
+    fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
+        T::build(type_builder)
+    }
+}
+
+mod hidden {
+    pub trait ScalarBuildableTypeBase {}
+}
+
+impl<T: hidden::ScalarBuildableTypeBase> hidden::ScalarBuildableTypeBase for UnsafeCell<T> {}
+
+/// trait for rust types that can be an element of a vector and be built using `TypeBuilder`
+pub trait ScalarBuildableType: BuildableType + hidden::ScalarBuildableTypeBase {}
+
+impl<T: ScalarBuildableType> ScalarBuildableType for UnsafeCell<T> {}
+
+/// descriptor for members of types implementing `BuildableStruct`
+pub struct BuildableStructMemberDescriptor {
+    /// name of member
+    pub name: &'static str,
+    /// index of member
+    pub index: usize,
+}
+
+/// trait for structs that can be built using TypeBuilder
+/// implementing types are usually created using `buildable_struct!`
+pub trait BuildableStruct: BuildableType {
+    /// get the list of members for `Self`
+    fn get_members() -> &'static [BuildableStructMemberDescriptor];
+    /// get the member for `Self` that is named `name`
+    fn get_member_by_name(name: &str) -> &'static BuildableStructMemberDescriptor {
+        for member in Self::get_members() {
+            if name == member.name {
+                return member;
+            }
+        }
+        unreachable!("{} is not a member", name);
+    }
+}
+
+macro_rules! build_basic_scalar {
+    ($type:ty, $build_fn:ident) => {
+        impl BuildableType for $type {
+            fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
+                type_builder.$build_fn()
+            }
+        }
+
+        impl hidden::ScalarBuildableTypeBase for $type {}
+
+        impl ScalarBuildableType for $type {}
+    };
+}
+
+build_basic_scalar!(bool, build_bool);
+build_basic_scalar!(u8, build_i8);
+build_basic_scalar!(i8, build_i8);
+build_basic_scalar!(u16, build_i16);
+build_basic_scalar!(i16, build_i16);
+build_basic_scalar!(u32, build_i32);
+build_basic_scalar!(i32, build_i32);
+build_basic_scalar!(u64, build_i64);
+build_basic_scalar!(i64, build_i64);
+build_basic_scalar!(f32, build_f32);
+build_basic_scalar!(f64, build_f64);
+
+impl<'b, T: BuildableType> BuildableType for Option<&'b T> {
+    fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
+        type_builder.build_pointer(T::build(type_builder))
+    }
+}
+
+impl<'b, T: BuildableType> hidden::ScalarBuildableTypeBase for Option<&'b T> {}
+
+impl<'b, T: BuildableType> ScalarBuildableType for Option<&'b T> {}
+
+impl<'b, T: BuildableType> BuildableType for Option<&'b mut T> {
+    fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
+        type_builder.build_pointer(T::build(type_builder))
+    }
+}
+
+impl<'b, T: BuildableType> hidden::ScalarBuildableTypeBase for Option<&'b mut T> {}
+
+impl<'b, T: BuildableType> ScalarBuildableType for Option<&'b mut T> {}
+
+impl<'b, T: BuildableType> BuildableType for &'b T {
+    fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
+        type_builder.build_pointer(T::build(type_builder))
+    }
+}
+
+impl<'b, T: BuildableType> hidden::ScalarBuildableTypeBase for &'b T {}
+
+impl<'b, T: BuildableType> ScalarBuildableType for &'b T {}
+
+impl<'b, T: BuildableType> BuildableType for &'b mut T {
+    fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
+        type_builder.build_pointer(T::build(type_builder))
+    }
+}
+
+impl<'b, T: BuildableType> hidden::ScalarBuildableTypeBase for &'b mut T {}
+
+impl<'b, T: BuildableType> ScalarBuildableType for &'b mut T {}
+
+impl<T: BuildableType> BuildableType for *mut T {
+    fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
+        type_builder.build_pointer(T::build(type_builder))
+    }
+}
+
+impl<'b, T: BuildableType> hidden::ScalarBuildableTypeBase for *mut T {}
+
+impl<'b, T: BuildableType> ScalarBuildableType for *mut T {}
+
+impl<T: BuildableType> BuildableType for *const T {
+    fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
+        type_builder.build_pointer(T::build(type_builder))
+    }
+}
+
+impl<'b, T: BuildableType> hidden::ScalarBuildableTypeBase for *const T {}
+
+impl<'b, T: BuildableType> ScalarBuildableType for *const T {}
+
+impl<T: BuildableType> BuildableType for NonNull<T> {
+    fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
+        type_builder.build_pointer(T::build(type_builder))
+    }
+}
+
+impl<'b, T: BuildableType> hidden::ScalarBuildableTypeBase for NonNull<T> {}
+
+impl<'b, T: BuildableType> ScalarBuildableType for NonNull<T> {}
+
+impl<T: BuildableType> BuildableType for Option<NonNull<T>> {
+    fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
+        type_builder.build_pointer(T::build(type_builder))
+    }
+}
+
+impl<'b, T: BuildableType> hidden::ScalarBuildableTypeBase for Option<NonNull<T>> {}
+
+impl<'b, T: BuildableType> ScalarBuildableType for Option<NonNull<T>> {}
+
+macro_rules! build_unit_function_type {
+        ($($arguments:ident,)*) => {
+            impl<$($arguments: BuildableType),*> BuildableType for Option<unsafe extern "C" fn($($arguments,)*)> {
+                fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
+                    type_builder.build_function(&[$($arguments::build(type_builder),)*], None)
+                }
+            }
+
+            impl<$($arguments: BuildableType),*> hidden::ScalarBuildableTypeBase for Option<unsafe extern "C" fn($($arguments,)*)> {}
+
+            impl<$($arguments: BuildableType),*> ScalarBuildableType for Option<unsafe extern "C" fn($($arguments,)*)> {}
+
+            impl<$($arguments: BuildableType),*> BuildableType for unsafe extern "C" fn($($arguments,)*) {
+                fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
+                    type_builder.build_function(&[$($arguments::build(type_builder),)*], None)
+                }
+            }
+
+            impl<$($arguments: BuildableType),*> hidden::ScalarBuildableTypeBase for unsafe extern "C" fn($($arguments,)*) {}
+
+            impl<$($arguments: BuildableType),*> ScalarBuildableType for unsafe extern "C" fn($($arguments,)*) {}
+        };
+    }
+
+macro_rules! build_function_type {
+        ($($arguments:ident,)*) => {
+            impl<R: BuildableType, $($arguments: BuildableType),*> BuildableType for Option<unsafe extern "C" fn($($arguments,)*) -> R> {
+                fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
+                    type_builder.build_function(&[$($arguments::build(type_builder),)*], Some(R::build(type_builder)))
+                }
+            }
+
+            impl<R: BuildableType, $($arguments: BuildableType),*> hidden::ScalarBuildableTypeBase for Option<unsafe extern "C" fn($($arguments,)*) -> R> {}
+
+            impl<R: BuildableType, $($arguments: BuildableType),*> ScalarBuildableType for Option<unsafe extern "C" fn($($arguments,)*) -> R> {}
+
+            impl<R: BuildableType, $($arguments: BuildableType),*> BuildableType for unsafe extern "C" fn($($arguments,)*) -> R {
+                fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
+                    type_builder.build_function(&[$($arguments::build(type_builder),)*], Some(R::build(type_builder)))
+                }
+            }
+
+            impl<R: BuildableType, $($arguments: BuildableType),*> hidden::ScalarBuildableTypeBase for unsafe extern "C" fn($($arguments,)*) -> R {}
+
+            impl<R: BuildableType, $($arguments: BuildableType),*> ScalarBuildableType for unsafe extern "C" fn($($arguments,)*) -> R {}
+
+        };
+    }
+
+macro_rules! build_function_types {
+        () => {
+            build_unit_function_type!();
+            build_function_type!();
+        };
+        ($first_argument:ident, $($arguments:ident,)*) => {
+            build_unit_function_type!($first_argument, $($arguments,)*);
+            build_function_type!($first_argument, $($arguments,)*);
+            build_function_types!($($arguments,)*);
+        }
+    }
+
+build_function_types!(
+    T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19,
+);
+
+macro_rules! build_array0 {
+    ($length:expr) => {
+        impl<T: BuildableType> BuildableType for [T; $length + 1] {
+            fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
+                type_builder.build_array(T::build(type_builder), $length + 1)
+            }
+        }
+    };
+}
+
+macro_rules! build_array1 {
+    ($length:expr) => {
+        build_array0!($length * 2);
+        build_array0!($length * 2 + 1);
+    };
+}
+
+macro_rules! build_array2 {
+    ($length:expr) => {
+        build_array1!($length * 2);
+        build_array1!($length * 2 + 1);
+    };
+}
+
+macro_rules! build_array3 {
+    ($length:expr) => {
+        build_array2!($length * 2);
+        build_array2!($length * 2 + 1);
+    };
+}
+
+macro_rules! build_array4 {
+    ($length:expr) => {
+        build_array3!($length * 2);
+        build_array3!($length * 2 + 1);
+    };
+}
+
+macro_rules! build_array5 {
+    ($length:expr) => {
+        build_array4!($length * 2);
+        build_array4!($length * 2 + 1);
+    };
+}
+
+build_array5!(0);
+build_array5!(1);
+
+/// buildable vector types
+pub trait Vector: BuildableType {
+    /// element type
+    type Element: ScalarBuildableType;
+    /// vector length
+    const LENGTH: VectorLength;
+}
+
+#[doc(hidden)]
+pub enum __VectorNeverType {}
+
+macro_rules! build_fixed_vector {
+    ($name:ident, $length:expr) => {
+        /// Vector of elements `Element`
+        #[derive(Copy, Clone)]
+        pub struct $name<Element: ScalarBuildableType> {
+            /// elements of the vector `Self`
+            pub elements: [Element; $length],
+        }
+
+        impl<Element: ScalarBuildableType> Deref for $name<Element> {
+            type Target = [Element; $length];
+            fn deref(&self) -> &Self::Target {
+                &self.elements
+            }
+        }
+
+        impl<Element: ScalarBuildableType> DerefMut for $name<Element> {
+            fn deref_mut(&mut self) -> &mut Self::Target {
+                &mut self.elements
+            }
+        }
+
+        impl<Element: ScalarBuildableType> BuildableType for $name<Element> {
+            fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
+                type_builder.build_vector(Element::build(type_builder), Self::LENGTH)
+            }
+        }
+
+        impl<Element: ScalarBuildableType> Vector for $name<Element> {
+            type Element = Element;
+            const LENGTH: VectorLength = { VectorLength::Fixed { length: $length } };
+        }
+    };
+}
+
+macro_rules! build_variable_vector {
+    ($name:ident, $base_length:expr) => {
+        /// Vector of elements `Element`
+        pub enum $name<Element: ScalarBuildableType> {
+            #[doc(hidden)]
+            __Dummy(__VectorNeverType, PhantomData<Element>),
+        }
+
+        impl<Element: ScalarBuildableType> BuildableType for $name<Element> {
+            fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
+                type_builder.build_vector(Element::build(type_builder), Self::LENGTH)
+            }
+        }
+
+        impl<Element: ScalarBuildableType> Vector for $name<Element> {
+            type Element = Element;
+            const LENGTH: VectorLength = {
+                VectorLength::Variable {
+                    base_length: $base_length,
+                }
+            };
+        }
+    };
+}
+
+/// alternate name for `VecNx1`
+pub type VecN<Element> = VecNx1<Element>;
+
+build_fixed_vector!(Vec1, 1);
+build_fixed_vector!(Vec2, 2);
+build_fixed_vector!(Vec3, 3);
+build_fixed_vector!(Vec4, 4);
+build_fixed_vector!(Vec5, 5);
+build_fixed_vector!(Vec6, 6);
+build_fixed_vector!(Vec7, 7);
+build_fixed_vector!(Vec8, 8);
+build_fixed_vector!(Vec9, 9);
+build_fixed_vector!(Vec10, 10);
+build_fixed_vector!(Vec11, 11);
+build_fixed_vector!(Vec12, 12);
+build_fixed_vector!(Vec13, 13);
+build_fixed_vector!(Vec14, 14);
+build_fixed_vector!(Vec15, 15);
+build_fixed_vector!(Vec16, 16);
+build_variable_vector!(VecNx1, 1);
+build_variable_vector!(VecNx2, 2);
+build_variable_vector!(VecNx3, 3);
+build_variable_vector!(VecNx4, 4);
+build_variable_vector!(VecNx5, 5);
+build_variable_vector!(VecNx6, 6);
+build_variable_vector!(VecNx7, 7);
+build_variable_vector!(VecNx8, 8);
+build_variable_vector!(VecNx9, 9);
+build_variable_vector!(VecNx10, 10);
+build_variable_vector!(VecNx11, 11);
+build_variable_vector!(VecNx12, 12);
+build_variable_vector!(VecNx13, 13);
+build_variable_vector!(VecNx14, 14);
+build_variable_vector!(VecNx15, 15);
+build_variable_vector!(VecNx16, 16);
diff --git a/shader-compiler-llvm-7/Cargo.toml b/shader-compiler-llvm-7/Cargo.toml
deleted file mode 100644 (file)
index b353559..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-# SPDX-License-Identifier: LGPL-2.1-or-later
-# Copyright 2018 Jacob Lifshay
-[package]
-name = "shader-compiler-llvm-7"
-version = "0.1.0"
-authors = ["Jacob Lifshay <programmerjake@gmail.com>"]
-license = "LGPL-2.1-or-later"
-
-[lib]
-crate-type = ["rlib"]
-
-[dependencies]
-shader-compiler = {path = "../shader-compiler"}
-
-[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
deleted file mode 100644 (file)
index c45929b..0000000
+++ /dev/null
@@ -1,310 +0,0 @@
-// 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("Debug")
-        .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()
-        .chain(llvm_config(llvm_config_path, Some("--system-libs")).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,
-        &["--libs", "orcjit", "native", "analysis"],
-    );
-    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();
-    let build_llvm_bindings = || {
-        let mut retval = cc::Build::new();
-        retval
-            .cpp(true)
-            .file(&llvm_bindings_path)
-            .include(&include_dir);
-        retval
-    };
-    build_llvm_bindings()
-        .cpp_link_stdlib(None)
-        .compile("llvm_bindings");
-    for lib in llvm_libs {
-        println!("cargo:rustc-link-lib={}", lib);
-    }
-    // build twice to get the c++ standard library linked after LLVM with llvm_bindings before LLVM
-    build_llvm_bindings().compile("llvm_bindings");
-}
diff --git a/shader-compiler-llvm-7/src/backend.rs b/shader-compiler-llvm-7/src/backend.rs
deleted file mode 100644 (file)
index 26964bf..0000000
+++ /dev/null
@@ -1,655 +0,0 @@
-// SPDX-License-Identifier: LGPL-2.1-or-later
-// Copyright 2018 Jacob Lifshay
-use llvm;
-use shader_compiler::backend;
-use std::cell::RefCell;
-use std::collections::HashMap;
-use std::collections::HashSet;
-use std::ffi::{CStr, CString};
-use std::fmt;
-use std::hash::Hash;
-use std::mem;
-use std::mem::ManuallyDrop;
-use std::ops::Deref;
-use std::os::raw::{c_char, c_uint};
-use std::ptr::null_mut;
-use std::ptr::NonNull;
-use std::sync::{Once, ONCE_INIT};
-
-fn to_bool(v: llvm::LLVMBool) -> bool {
-    v != 0
-}
-
-#[derive(Clone)]
-pub struct LLVM7CompilerConfig {
-    pub variable_vector_length_multiplier: u32,
-    pub optimization_mode: backend::OptimizationMode,
-}
-
-impl Default for LLVM7CompilerConfig {
-    fn default() -> Self {
-        backend::CompilerIndependentConfig::default().into()
-    }
-}
-
-impl From<backend::CompilerIndependentConfig> for LLVM7CompilerConfig {
-    fn from(v: backend::CompilerIndependentConfig) -> Self {
-        let backend::CompilerIndependentConfig { optimization_mode } = v;
-        Self {
-            variable_vector_length_multiplier: 1,
-            optimization_mode,
-        }
-    }
-}
-
-#[repr(transparent)]
-struct LLVM7String(NonNull<c_char>);
-
-impl Drop for LLVM7String {
-    fn drop(&mut self) {
-        unsafe {
-            llvm::LLVMDisposeMessage(self.0.as_ptr());
-        }
-    }
-}
-
-impl Deref for LLVM7String {
-    type Target = CStr;
-    fn deref(&self) -> &CStr {
-        unsafe { CStr::from_ptr(self.0.as_ptr()) }
-    }
-}
-
-impl Clone for LLVM7String {
-    fn clone(&self) -> Self {
-        Self::new(self)
-    }
-}
-
-impl LLVM7String {
-    fn new(v: &CStr) -> Self {
-        unsafe { Self::from_ptr(llvm::LLVMCreateMessage(v.as_ptr())).unwrap() }
-    }
-    unsafe fn from_nonnull(v: NonNull<c_char>) -> Self {
-        LLVM7String(v)
-    }
-    unsafe fn from_ptr(v: *mut c_char) -> Option<Self> {
-        NonNull::new(v).map(|v| Self::from_nonnull(v))
-    }
-}
-
-impl fmt::Debug for LLVM7String {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        (**self).fmt(f)
-    }
-}
-
-#[derive(Clone, Eq, PartialEq, Hash)]
-#[repr(transparent)]
-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::LLVMPrintTypeToString(self.0)).ok_or(fmt::Error)?;
-            f.write_str(&string.to_string_lossy())
-        }
-    }
-}
-
-impl<'a> backend::types::Type<'a> for LLVM7Type {
-    type Context = LLVM7Context;
-}
-
-pub struct LLVM7TypeBuilder {
-    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::LLVMInt1TypeInContext(self.context)) }
-    }
-    fn build_i8(&self) -> LLVM7Type {
-        unsafe { LLVM7Type(llvm::LLVMInt8TypeInContext(self.context)) }
-    }
-    fn build_i16(&self) -> LLVM7Type {
-        unsafe { LLVM7Type(llvm::LLVMInt16TypeInContext(self.context)) }
-    }
-    fn build_i32(&self) -> LLVM7Type {
-        unsafe { LLVM7Type(llvm::LLVMInt32TypeInContext(self.context)) }
-    }
-    fn build_i64(&self) -> LLVM7Type {
-        unsafe { LLVM7Type(llvm::LLVMInt64TypeInContext(self.context)) }
-    }
-    fn build_f32(&self) -> LLVM7Type {
-        unsafe { LLVM7Type(llvm::LLVMFloatTypeInContext(self.context)) }
-    }
-    fn build_f64(&self) -> LLVM7Type {
-        unsafe { LLVM7Type(llvm::LLVMDoubleTypeInContext(self.context)) }
-    }
-    fn build_pointer(&self, target: LLVM7Type) -> LLVM7Type {
-        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::LLVMArrayType(element.0, count as u32)) }
-    }
-    fn build_vector(&self, element: LLVM7Type, length: backend::types::VectorLength) -> LLVM7Type {
-        use self::backend::types::VectorLength::*;
-        let length = match length {
-            Fixed { length } => length,
-            Variable { base_length } => base_length
-                .checked_mul(self.variable_vector_length_multiplier)
-                .unwrap(),
-        };
-        assert_ne!(length, 0);
-        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::LLVMStructTypeInContext(
-                self.context,
-                members.as_ptr() as *mut llvm::LLVMTypeRef,
-                members.len() as c_uint,
-                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::LLVMFunctionType(
-                return_type
-                    .unwrap_or_else(|| LLVM7Type(llvm::LLVMVoidTypeInContext(self.context)))
-                    .0,
-                arguments.as_ptr() as *mut llvm::LLVMTypeRef,
-                arguments.len() as c_uint,
-                false as llvm::LLVMBool,
-            ))
-        }
-    }
-}
-
-#[derive(Clone)]
-#[repr(transparent)]
-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::LLVMPrintValueToString(self.0)).ok_or(fmt::Error)?;
-            f.write_str(&string.to_string_lossy())
-        }
-    }
-}
-
-impl<'a> backend::Value<'a> for LLVM7Value {
-    type Context = LLVM7Context;
-}
-
-#[derive(Clone)]
-#[repr(transparent)]
-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::LLVMPrintValueToString(self.as_value().0))
-                .ok_or(fmt::Error)?;
-            f.write_str(&string.to_string_lossy())
-        }
-    }
-}
-
-impl<'a> backend::BasicBlock<'a> for LLVM7BasicBlock {
-    type Context = LLVM7Context;
-    fn as_value(&self) -> LLVM7Value {
-        unsafe { LLVM7Value(llvm::LLVMBasicBlockAsValue(self.0)) }
-    }
-}
-
-impl<'a> backend::BuildableBasicBlock<'a> for LLVM7BasicBlock {
-    type Context = LLVM7Context;
-    fn as_basic_block(&self) -> LLVM7BasicBlock {
-        self.clone()
-    }
-}
-
-pub struct LLVM7Function {
-    context: llvm::LLVMContextRef,
-    function: llvm::LLVMValueRef,
-    parameters: Box<[LLVM7Value]>,
-}
-
-impl fmt::Debug for LLVM7Function {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        unsafe {
-            let string = LLVM7String::from_ptr(llvm::LLVMPrintValueToString(self.function))
-                .ok_or(fmt::Error)?;
-            f.write_str(&string.to_string_lossy())
-        }
-    }
-}
-
-impl<'a> backend::Function<'a> for LLVM7Function {
-    type Context = LLVM7Context;
-    fn as_value(&self) -> LLVM7Value {
-        LLVM7Value(self.function)
-    }
-    fn append_new_basic_block(&mut self, name: Option<&str>) -> LLVM7BasicBlock {
-        let name = CString::new(name.unwrap_or("")).unwrap();
-        unsafe {
-            LLVM7BasicBlock(llvm::LLVMAppendBasicBlockInContext(
-                self.context,
-                self.function,
-                name.as_ptr(),
-            ))
-        }
-    }
-    fn parameters(&self) -> &[LLVM7Value] {
-        &self.parameters
-    }
-}
-
-pub struct LLVM7Context {
-    context: Option<ManuallyDrop<OwnedContext>>,
-    modules: ManuallyDrop<RefCell<Vec<OwnedModule>>>,
-    config: LLVM7CompilerConfig,
-}
-
-impl Drop for LLVM7Context {
-    fn drop(&mut self) {
-        unsafe {
-            ManuallyDrop::drop(&mut self.modules);
-            if let Some(context) = &mut self.context {
-                ManuallyDrop::drop(context);
-            }
-        }
-    }
-}
-
-impl<'a> backend::Context<'a> for LLVM7Context {
-    type Value = LLVM7Value;
-    type BasicBlock = LLVM7BasicBlock;
-    type BuildableBasicBlock = LLVM7BasicBlock;
-    type Function = LLVM7Function;
-    type Type = LLVM7Type;
-    type TypeBuilder = LLVM7TypeBuilder;
-    type Module = LLVM7Module;
-    type VerifiedModule = LLVM7Module;
-    type AttachedBuilder = LLVM7Builder;
-    type DetachedBuilder = LLVM7Builder;
-    fn create_module(&self, name: &str) -> LLVM7Module {
-        let name = CString::new(name).unwrap();
-        let mut modules = self.modules.borrow_mut();
-        unsafe {
-            let module = OwnedModule(llvm::LLVMModuleCreateWithNameInContext(
-                name.as_ptr(),
-                self.context.as_ref().unwrap().0,
-            ));
-            let module_ref = module.0;
-            modules.push(module);
-            LLVM7Module {
-                context: self.context.as_ref().unwrap().0,
-                module: module_ref,
-                name_set: HashSet::new(),
-            }
-        }
-    }
-    fn create_builder(&self) -> LLVM7Builder {
-        unsafe {
-            LLVM7Builder(llvm::LLVMCreateBuilderInContext(
-                self.context.as_ref().unwrap().0,
-            ))
-        }
-    }
-    fn create_type_builder(&self) -> LLVM7TypeBuilder {
-        LLVM7TypeBuilder {
-            context: self.context.as_ref().unwrap().0,
-            variable_vector_length_multiplier: self.config.variable_vector_length_multiplier,
-        }
-    }
-}
-
-#[repr(transparent)]
-pub struct LLVM7Builder(llvm::LLVMBuilderRef);
-
-impl Drop for LLVM7Builder {
-    fn drop(&mut self) {
-        unsafe {
-            llvm::LLVMDisposeBuilder(self.0);
-        }
-    }
-}
-
-impl<'a> backend::AttachedBuilder<'a> for LLVM7Builder {
-    type Context = LLVM7Context;
-    fn current_basic_block(&self) -> LLVM7BasicBlock {
-        unsafe { LLVM7BasicBlock(llvm::LLVMGetInsertBlock(self.0)) }
-    }
-    fn build_return(self, value: Option<LLVM7Value>) -> LLVM7Builder {
-        unsafe {
-            match value {
-                Some(value) => llvm::LLVMBuildRet(self.0, value.0),
-                None => llvm::LLVMBuildRetVoid(self.0),
-            };
-            llvm::LLVMClearInsertionPosition(self.0);
-        }
-        self
-    }
-}
-
-impl<'a> backend::DetachedBuilder<'a> for LLVM7Builder {
-    type Context = LLVM7Context;
-    fn attach(self, basic_block: LLVM7BasicBlock) -> LLVM7Builder {
-        unsafe {
-            llvm::LLVMPositionBuilderAtEnd(self.0, basic_block.0);
-        }
-        self
-    }
-}
-
-struct OwnedModule(llvm::LLVMModuleRef);
-
-impl Drop for OwnedModule {
-    fn drop(&mut self) {
-        unsafe {
-            llvm::LLVMDisposeModule(self.0);
-        }
-    }
-}
-
-impl OwnedModule {
-    unsafe fn take(mut self) -> llvm::LLVMModuleRef {
-        let retval = self.0;
-        self.0 = null_mut();
-        retval
-    }
-}
-
-struct OwnedContext(llvm::LLVMContextRef);
-
-impl Drop for OwnedContext {
-    fn drop(&mut self) {
-        unsafe {
-            llvm::LLVMContextDispose(self.0);
-        }
-    }
-}
-
-pub struct LLVM7Module {
-    context: llvm::LLVMContextRef,
-    module: llvm::LLVMModuleRef,
-    name_set: HashSet<String>,
-}
-
-impl fmt::Debug for LLVM7Module {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        unsafe {
-            let string = LLVM7String::from_ptr(llvm::LLVMPrintModuleToString(self.module))
-                .ok_or(fmt::Error)?;
-            f.write_str(&string.to_string_lossy())
-        }
-    }
-}
-
-impl<'a> backend::Module<'a> for LLVM7Module {
-    type Context = LLVM7Context;
-    fn set_source_file_name(&mut self, source_file_name: &str) {
-        unsafe {
-            llvm::LLVMSetSourceFileName(
-                self.module,
-                source_file_name.as_ptr() as *const c_char,
-                source_file_name.len(),
-            )
-        }
-    }
-    fn add_function(&mut self, name: &str, ty: LLVM7Type) -> LLVM7Function {
-        fn is_start_char(c: char) -> bool {
-            if c.is_ascii_alphabetic() {
-                true
-            } else {
-                match c {
-                    '_' | '.' | '$' | '-' => true,
-                    _ => false,
-                }
-            }
-        }
-        fn is_continue_char(c: char) -> bool {
-            is_start_char(c) || c.is_ascii_digit()
-        }
-        assert!(is_start_char(name.chars().next().unwrap()));
-        assert!(name.chars().all(is_continue_char));
-        assert!(self.name_set.insert(name.into()));
-        let name = CString::new(name).unwrap();
-        unsafe {
-            let function = llvm::LLVMAddFunction(self.module, name.as_ptr(), ty.0);
-            let mut parameters = Vec::new();
-            parameters.resize(llvm::LLVMCountParams(function) as usize, null_mut());
-            llvm::LLVMGetParams(function, parameters.as_mut_ptr());
-            let parameters: Vec<_> = parameters.into_iter().map(LLVM7Value).collect();
-            LLVM7Function {
-                context: self.context,
-                function: llvm::LLVMAddFunction(self.module, name.as_ptr(), ty.0),
-                parameters: parameters.into_boxed_slice(),
-            }
-        }
-    }
-    fn verify(self) -> Result<LLVM7Module, backend::VerificationFailure<'a, LLVM7Module>> {
-        unsafe {
-            let mut message = null_mut();
-            let broken = to_bool(llvm::LLVMVerifyModule(
-                self.module,
-                llvm::LLVMReturnStatusAction,
-                &mut message,
-            ));
-            if broken {
-                let message = LLVM7String::from_ptr(message).unwrap();
-                let message = message.to_string_lossy();
-                Err(backend::VerificationFailure::new(self, message.as_ref()))
-            } else {
-                Ok(self)
-            }
-        }
-    }
-    unsafe fn to_verified_module_unchecked(self) -> LLVM7Module {
-        self
-    }
-}
-
-impl<'a> backend::VerifiedModule<'a> for LLVM7Module {
-    type Context = LLVM7Context;
-    fn into_module(self) -> LLVM7Module {
-        self
-    }
-}
-
-struct LLVM7TargetMachine(llvm::LLVMTargetMachineRef);
-
-impl Drop for LLVM7TargetMachine {
-    fn drop(&mut self) {
-        unsafe {
-            llvm::LLVMDisposeTargetMachine(self.0);
-        }
-    }
-}
-
-impl LLVM7TargetMachine {
-    fn take(mut self) -> llvm::LLVMTargetMachineRef {
-        let retval = self.0;
-        self.0 = null_mut();
-        retval
-    }
-}
-
-struct LLVM7OrcJITStack(llvm::LLVMOrcJITStackRef);
-
-impl Drop for LLVM7OrcJITStack {
-    fn drop(&mut self) {
-        unsafe {
-            match llvm::LLVMOrcDisposeInstance(self.0) {
-                llvm::LLVMOrcErrSuccess => {}
-                _ => {
-                    panic!("LLVMOrcDisposeInstance failed");
-                }
-            }
-        }
-    }
-}
-
-fn initialize_native_target() {
-    static ONCE: Once = ONCE_INIT;
-    ONCE.call_once(|| unsafe {
-        llvm::LLVM_InitializeNativeTarget();
-        llvm::LLVM_InitializeNativeAsmPrinter();
-        llvm::LLVM_InitializeNativeAsmParser();
-    });
-}
-
-extern "C" fn symbol_resolver_fn<Void>(name: *const c_char, _lookup_context: *mut Void) -> u64 {
-    let name = unsafe { CStr::from_ptr(name) };
-    panic!("symbol_resolver_fn is unimplemented: name = {:?}", name)
-}
-
-#[derive(Copy, Clone)]
-pub struct LLVM7Compiler;
-
-impl backend::Compiler for LLVM7Compiler {
-    type Config = LLVM7CompilerConfig;
-    fn name(self) -> &'static str {
-        "LLVM 7"
-    }
-    fn run<U: backend::CompilerUser>(
-        self,
-        user: U,
-        config: LLVM7CompilerConfig,
-    ) -> Result<Box<dyn backend::CompiledCode<U::FunctionKey>>, U::Error> {
-        unsafe {
-            initialize_native_target();
-            let context = OwnedContext(llvm::LLVMContextCreate());
-            let modules = Vec::new();
-            let mut context = LLVM7Context {
-                context: Some(ManuallyDrop::new(context)),
-                modules: ManuallyDrop::new(RefCell::new(modules)),
-                config: config.clone(),
-            };
-            let backend::CompileInputs {
-                module,
-                callable_functions,
-            } = user.run(&context)?;
-            let callable_functions: Vec<_> = callable_functions
-                .into_iter()
-                .map(|(key, callable_function)| {
-                    assert_eq!(
-                        llvm::LLVMGetGlobalParent(callable_function.function),
-                        module.module
-                    );
-                    let name: CString =
-                        CStr::from_ptr(llvm::LLVMGetValueName(callable_function.function)).into();
-                    assert_ne!(name.to_bytes().len(), 0);
-                    (key, name)
-                })
-                .collect();
-            let module = context
-                .modules
-                .get_mut()
-                .drain(..)
-                .find(|v| v.0 == module.module)
-                .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::LLVMGetTargetFromTriple(
-                target_triple.as_ptr(),
-                &mut target,
-                &mut error,
-            ));
-            if !success {
-                let error = LLVM7String::from_ptr(error).unwrap();
-                return Err(U::create_error(error.to_string_lossy().into()));
-            }
-            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::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::LLVMOrcCreateInstance(target_machine.take()));
-            let mut module_handle = 0;
-            if llvm::LLVMOrcErrSuccess != llvm::LLVMOrcAddEagerlyCompiledIR(
-                orc_jit_stack.0,
-                &mut module_handle,
-                module.take(),
-                Some(symbol_resolver_fn),
-                null_mut(),
-            ) {
-                return Err(U::create_error("compilation failed".into()));
-            }
-            let mut functions: HashMap<_, _> = HashMap::new();
-            for (key, name) in callable_functions {
-                let mut address: llvm::LLVMOrcTargetAddress = mem::zeroed();
-                if llvm::LLVMOrcErrSuccess != llvm::LLVMOrcGetSymbolAddressIn(
-                    orc_jit_stack.0,
-                    &mut address,
-                    module_handle,
-                    name.as_ptr(),
-                ) {
-                    return Err(U::create_error(format!(
-                        "function not found in compiled module: {:?}",
-                        name
-                    )));
-                }
-                let address: Option<unsafe extern "C" fn()> = mem::transmute(address as usize);
-                if functions.insert(key, address.unwrap()).is_some() {
-                    return Err(U::create_error(format!("duplicate function: {:?}", name)));
-                }
-            }
-            struct CompiledCode<K: Hash + Eq + Send + Sync + 'static> {
-                functions: HashMap<K, unsafe extern "C" fn()>,
-                orc_jit_stack: ManuallyDrop<LLVM7OrcJITStack>,
-                context: ManuallyDrop<OwnedContext>,
-            }
-            unsafe impl<K: Hash + Eq + Send + Sync + 'static> Send for CompiledCode<K> {}
-            unsafe impl<K: Hash + Eq + Send + Sync + 'static> Sync for CompiledCode<K> {}
-            impl<K: Hash + Eq + Send + Sync + 'static> Drop for CompiledCode<K> {
-                fn drop(&mut self) {
-                    unsafe {
-                        ManuallyDrop::drop(&mut self.orc_jit_stack);
-                        ManuallyDrop::drop(&mut self.context);
-                    }
-                }
-            }
-            impl<K: Hash + Eq + Send + Sync + 'static> backend::CompiledCode<K> for CompiledCode<K> {
-                fn get(&self, key: &K) -> Option<unsafe extern "C" fn()> {
-                    Some(*self.functions.get(key)?)
-                }
-            }
-            Ok(Box::new(CompiledCode {
-                functions,
-                orc_jit_stack: ManuallyDrop::new(orc_jit_stack),
-                context: context.context.take().unwrap(),
-            }))
-        }
-    }
-}
diff --git a/shader-compiler-llvm-7/src/lib.rs b/shader-compiler-llvm-7/src/lib.rs
deleted file mode 100644 (file)
index d797122..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-// SPDX-License-Identifier: LGPL-2.1-or-later
-// Copyright 2018 Jacob Lifshay
-extern crate shader_compiler;
-
-#[cfg_attr(feature = "cargo-clippy", 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;
-
-pub use backend::LLVM7CompilerConfig;
-
-pub const LLVM_7_SHADER_COMPILER: backend::LLVM7Compiler = backend::LLVM7Compiler;
diff --git a/shader-compiler-llvm-7/src/tests.rs b/shader-compiler-llvm-7/src/tests.rs
deleted file mode 100644 (file)
index ac532cf..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-// SPDX-License-Identifier: LGPL-2.1-or-later
-// Copyright 2018 Jacob Lifshay
-#[cfg(test)]
-// we have a tests module inside a tests module to have rls parse this tests.rs file
-#[cfg_attr(feature = "cargo-clippy", allow(clippy::module_inception))]
-mod tests {
-    use shader_compiler::backend::types::TypeBuilder;
-    use shader_compiler::backend::*;
-    use std::mem;
-
-    fn make_compiler() -> impl Compiler {
-        ::LLVM_7_SHADER_COMPILER
-    }
-
-    #[test]
-    fn test_basic() {
-        type GeneratedFunctionType = unsafe extern "C" fn(u32);
-        #[derive(Copy, Clone, Hash, Eq, PartialEq, Debug)]
-        enum FunctionKey {
-            Function,
-        }
-        struct Test;
-        impl CompilerUser for Test {
-            type FunctionKey = FunctionKey;
-            type Error = String;
-            fn create_error(message: String) -> String {
-                message
-            }
-            fn run<'a, C: Context<'a>>(
-                self,
-                context: &'a C,
-            ) -> Result<CompileInputs<'a, C, FunctionKey>, String> {
-                let type_builder = context.create_type_builder();
-                let mut module = context.create_module("test_module");
-                let mut function = module.add_function(
-                    "test_function",
-                    type_builder.build::<GeneratedFunctionType>(),
-                );
-                let builder = context.create_builder();
-                let builder = builder.attach(function.append_new_basic_block(None));
-                builder.build_return(None);
-                let module = module.verify().unwrap();
-                Ok(CompileInputs {
-                    module,
-                    callable_functions: vec![(FunctionKey::Function, function)]
-                        .into_iter()
-                        .collect(),
-                })
-            }
-        }
-        let compiled_code = make_compiler().run(Test, Default::default()).unwrap();
-        let function = compiled_code.get(&FunctionKey::Function).unwrap();
-        unsafe {
-            let function: GeneratedFunctionType = mem::transmute(function);
-            function(0);
-        }
-    }
-
-    #[test]
-    fn test_names() {
-        const NAMES: &[&str] = &["main", "abc123-$._"];
-        type GeneratedFunctionType = unsafe extern "C" fn(u32);
-        #[derive(Copy, Clone, Hash, Eq, PartialEq, Debug)]
-        struct Test;
-        impl CompilerUser for Test {
-            type FunctionKey = String;
-            type Error = String;
-            fn create_error(message: String) -> String {
-                message
-            }
-            fn run<'a, C: Context<'a>>(
-                self,
-                context: &'a C,
-            ) -> Result<CompileInputs<'a, C, String>, String> {
-                let type_builder = context.create_type_builder();
-                let mut module = context.create_module("test_module");
-                let mut functions = Vec::new();
-                let mut detached_builder = context.create_builder();
-                for name in NAMES {
-                    let mut function =
-                        module.add_function(name, type_builder.build::<GeneratedFunctionType>());
-                    let builder = detached_builder.attach(function.append_new_basic_block(None));
-                    detached_builder = builder.build_return(None);
-                    functions.push((name.to_string(), function));
-                }
-                let module = module.verify().unwrap();
-                Ok(CompileInputs {
-                    module,
-                    callable_functions: functions.into_iter().collect(),
-                })
-            }
-        }
-        let compiled_code = make_compiler().run(Test, Default::default()).unwrap();
-        let function = compiled_code.get(&"main".to_string()).unwrap();
-        unsafe {
-            let function: GeneratedFunctionType = mem::transmute(function);
-            function(0);
-        }
-    }
-}
diff --git a/shader-compiler/Cargo.toml b/shader-compiler/Cargo.toml
deleted file mode 100644 (file)
index 25f1138..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-# SPDX-License-Identifier: LGPL-2.1-or-later
-# Copyright 2018 Jacob Lifshay
-[package]
-name = "shader-compiler"
-version = "0.1.0"
-authors = ["Jacob Lifshay <programmerjake@gmail.com>"]
-license = "LGPL-2.1-or-later"
-
-[lib]
-crate-type = ["rlib"]
-
-[dependencies]
diff --git a/shader-compiler/src/backend/mod.rs b/shader-compiler/src/backend/mod.rs
deleted file mode 100644 (file)
index 97f7441..0000000
+++ /dev/null
@@ -1,251 +0,0 @@
-// SPDX-License-Identifier: LGPL-2.1-or-later
-// Copyright 2018 Jacob Lifshay
-
-//! Shader Compiler Backend traits
-
-use std::collections::HashMap;
-use std::error::Error;
-use std::fmt;
-use std::fmt::Debug;
-use std::hash::Hash;
-use std::io;
-use std::marker::PhantomData;
-
-#[macro_use]
-pub mod types;
-
-/// equivalent to LLVM's 'IRBuilder'
-pub trait AttachedBuilder<'a>: Sized {
-    /// the `Context` type
-    type Context: Context<'a>;
-    /// get the current `BasicBlock`
-    fn current_basic_block(&self) -> <Self::Context as Context<'a>>::BasicBlock;
-    /// build a return instruction
-    fn build_return(
-        self,
-        value: Option<<Self::Context as Context<'a>>::Value>,
-    ) -> <Self::Context as Context<'a>>::DetachedBuilder;
-}
-
-/// equivalent to LLVM's 'IRBuilder'
-pub trait DetachedBuilder<'a>: Sized {
-    /// the `Context` type
-    type Context: Context<'a>;
-    /// attach `basic_block` to `Self`, converting into an `AttachedBuilder`
-    fn attach(
-        self,
-        basic_block: <Self::Context as Context<'a>>::BuildableBasicBlock,
-    ) -> <Self::Context as Context<'a>>::AttachedBuilder;
-}
-
-/// equivalent to LLVM's 'Value'
-pub trait Value<'a>: Clone + Debug {
-    /// the `Context` type
-    type Context: Context<'a>;
-}
-
-/// equivalent to LLVM's 'BasicBlock'
-pub trait BasicBlock<'a>: Clone + Debug {
-    /// the `Context` type
-    type Context: Context<'a>;
-    /// get the `Value` corresponding to `Self`
-    fn as_value(&self) -> <Self::Context as Context<'a>>::Value;
-}
-
-/// equivalent to LLVM's 'BasicBlock'
-pub trait BuildableBasicBlock<'a>: Debug + Sized {
-    /// the `Context` type
-    type Context: Context<'a>;
-    /// get the `BasicBlock` corresponding to `Self`
-    fn as_basic_block(&self) -> <Self::Context as Context<'a>>::BasicBlock;
-    /// get the `Value` corresponding to `Self`
-    fn as_value(&self) -> <Self::Context as Context<'a>>::Value {
-        self.as_basic_block().as_value()
-    }
-}
-
-/// equivalent to LLVM's 'Function'
-pub trait Function<'a>: Debug + Sized {
-    /// the `Context` type
-    type Context: Context<'a>;
-    /// get the `Value` corresponding to `Self`
-    fn as_value(&self) -> <Self::Context as Context<'a>>::Value;
-    /// append a new `BasicBlock` to `Self`
-    fn append_new_basic_block(
-        &mut self,
-        name: Option<&str>,
-    ) -> <Self::Context as Context<'a>>::BuildableBasicBlock;
-    /// get this function's parameters
-    fn parameters(&self) -> &[<Self::Context as Context<'a>>::Value];
-}
-
-/// module verification failure; returned from `Module::verify`
-pub struct VerificationFailure<'a, M: Module<'a>> {
-    module: M,
-    message: String,
-    _phantom_data: PhantomData<&'a ()>,
-}
-
-impl<'a, M: Module<'a>> VerificationFailure<'a, M> {
-    /// create a new `VerificationFailure`
-    pub fn new<T: ToString + ?Sized>(module: M, message: &T) -> Self {
-        VerificationFailure {
-            module,
-            message: message.to_string(),
-            _phantom_data: PhantomData,
-        }
-    }
-    /// get the `Module` that failed verification
-    pub fn into_module(self) -> M {
-        self.module
-    }
-}
-
-impl<'a, M: Module<'a>> fmt::Display for VerificationFailure<'a, M> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "module verification failure: {}", self.message,)
-    }
-}
-
-impl<'a, M: Module<'a>> Debug for VerificationFailure<'a, M> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_struct("VerificationFailure")
-            .field("message", &self.message)
-            .field("module", &self.module)
-            .finish()
-    }
-}
-
-impl<'a, M: Module<'a>> Error for VerificationFailure<'a, M> {}
-
-impl<'a, M: Module<'a>> From<VerificationFailure<'a, M>> for io::Error {
-    fn from(v: VerificationFailure<'a, M>) -> Self {
-        io::Error::new(io::ErrorKind::Other, format!("{}", v))
-    }
-}
-
-/// equivalent to LLVM's 'Module'
-pub trait Module<'a>: Debug + Sized {
-    /// the `Context` type
-    type Context: Context<'a>;
-    /// set's the source file name for this module
-    fn set_source_file_name(&mut self, source_file_name: &str);
-    /// add a new empty function to `Self`
-    fn add_function(
-        &mut self,
-        name: &str,
-        ty: <Self::Context as Context<'a>>::Type,
-    ) -> <Self::Context as Context<'a>>::Function;
-    /// verify `Self`, converting into a `VerifiedModule`
-    fn verify(
-        self,
-    ) -> Result<<Self::Context as Context<'a>>::VerifiedModule, VerificationFailure<'a, Self>>;
-    /// convert into a `VerifiedModule` without verifing
-    unsafe fn to_verified_module_unchecked(self) -> <Self::Context as Context<'a>>::VerifiedModule;
-}
-
-/// equivalent to LLVM's 'Module'; create using `Module::verify` or `Module::to_verified_module_unchecked`
-pub trait VerifiedModule<'a>: Debug + Sized {
-    /// the `Context` type
-    type Context: Context<'a>;
-    /// convert back to an unverified module
-    fn into_module(self) -> <Self::Context as Context<'a>>::Module;
-}
-
-/// instance of a compiler backend; equivalent to LLVM's `LLVMContext`
-pub trait Context<'a>: Sized {
-    /// the `Value` type
-    type Value: Value<'a, Context = Self>;
-    /// the `BasicBlock` type
-    type BasicBlock: BasicBlock<'a, Context = Self>;
-    /// the `BuildableBasicBlock` type
-    type BuildableBasicBlock: BuildableBasicBlock<'a, Context = Self>;
-    /// the `Function` type
-    type Function: Function<'a, Context = Self>;
-    /// the `Module` type
-    type Module: Module<'a, Context = Self>;
-    /// the `VerifiedModule` type
-    type VerifiedModule: VerifiedModule<'a, Context = Self>;
-    /// the `AttachedBuilder` type
-    type AttachedBuilder: AttachedBuilder<'a, Context = Self>;
-    /// the `DetachedBuilder` type
-    type DetachedBuilder: DetachedBuilder<'a, Context = Self>;
-    /// the `Type` type
-    type Type: types::Type<'a, Context = Self>;
-    /// the `TypeBuilder` type
-    type TypeBuilder: types::TypeBuilder<'a, Self::Type>;
-    /// create a new `Module`
-    fn create_module(&self, name: &str) -> Self::Module;
-    /// create a new `DetachedBuilder`
-    fn create_builder(&self) -> Self::DetachedBuilder;
-    /// create a new `TypeBuilder`
-    fn create_type_builder(&self) -> Self::TypeBuilder;
-}
-
-/// inputs to the final compilation
-pub struct CompileInputs<'a, C: Context<'a>, K: Hash + Eq + Send + Sync + 'static> {
-    /// the input module
-    pub module: C::VerifiedModule,
-    /// the list of functions that can be called from the final `CompiledCode`
-    pub callable_functions: HashMap<K, C::Function>,
-}
-
-/// the final compiled code
-pub trait CompiledCode<K: Hash + Eq + Send + Sync + 'static>: Send + Sync {
-    /// get a function in the final compiled code.
-    /// the returned function needs to be cast to the correct type and
-    /// `Self` needs to still exist while the returned function exists
-    fn get(&self, which: &K) -> Option<unsafe extern "C" fn()>;
-}
-
-/// trait that the user of `Compiler` implements
-pub trait CompilerUser {
-    /// the type used as a key for visible functions
-    type FunctionKey: Hash + Eq + Send + Sync + 'static;
-    /// the user's error type
-    type Error;
-    /// create an instance of `Error`
-    fn create_error(message: String) -> Self::Error;
-    /// the function that the user of `Compiler` implements
-    fn run<'a, C: Context<'a>>(
-        self,
-        context: &'a C,
-    ) -> Result<CompileInputs<'a, C, Self::FunctionKey>, Self::Error>;
-}
-
-/// optimization mode
-#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
-pub enum OptimizationMode {
-    /// no optimizations are enabled
-    NoOptimizations,
-    /// default optimizations are enabled
-    Normal,
-}
-
-impl Default for OptimizationMode {
-    fn default() -> Self {
-        OptimizationMode::Normal
-    }
-}
-
-/// compiler independent config options
-#[derive(Clone, Debug, Default)]
-pub struct CompilerIndependentConfig {
-    /// optimization mode
-    pub optimization_mode: OptimizationMode,
-}
-
-/// main compiler backend trait
-pub trait Compiler: Copy + Send + Sync + 'static {
-    /// the compiler's configuration
-    type Config: Default + Clone + From<CompilerIndependentConfig> + Send + Sync;
-    /// get shader compiler's name
-    fn name(self) -> &'static str;
-    /// run a passed-in function with a new compiler context.
-    /// this round-about method is used because generic associated types are not in stable Rust yet
-    fn run<U: CompilerUser>(
-        self,
-        user: U,
-        config: Self::Config,
-    ) -> Result<Box<dyn CompiledCode<U::FunctionKey>>, U::Error>;
-}
diff --git a/shader-compiler/src/backend/types.rs b/shader-compiler/src/backend/types.rs
deleted file mode 100644 (file)
index c364796..0000000
+++ /dev/null
@@ -1,553 +0,0 @@
-// SPDX-License-Identifier: LGPL-2.1-or-later
-// Copyright 2018 Jacob Lifshay
-
-//! types in backend IR
-
-use backend::Context;
-use std::cell::UnsafeCell;
-use std::fmt::Debug;
-use std::hash::Hash;
-use std::marker::PhantomData;
-use std::ops::{Deref, DerefMut};
-use std::ptr::NonNull;
-
-#[macro_export]
-macro_rules! buildable_struct_helper {
-    {
-        struct $name:ident {
-            $($member_name:ident: $member_type:ty,)*
-        }
-    } => {
-        impl $crate::backend::types::BuildableType for $name {
-            fn build<'a, Ty: $crate::backend::types::Type<'a>, TB: $crate::backend::types::TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
-                type_builder.build_struct(&[$(<$member_type as $crate::backend::types::BuildableType>::build(type_builder),)*])
-            }
-        }
-
-        impl $crate::backend::types::BuildableStruct for $name {
-            fn get_members(
-            ) -> &'static [$crate::backend::types::BuildableStructMemberDescriptor] {
-                #[allow(dead_code, non_camel_case_types)]
-                #[repr(usize)]
-                enum MemberIndices {
-                    $($member_name,)*
-                    __Last,
-                }
-                const MEMBERS: &'static [$crate::backend::types::BuildableStructMemberDescriptor] = &[
-                    $($crate::backend::types::BuildableStructMemberDescriptor {
-                        name: stringify!($member_name),
-                        index: MemberIndices::$member_name as usize,
-                    },)*
-                ];
-                MEMBERS
-            }
-        }
-    }
-}
-
-#[macro_export]
-macro_rules! buildable_struct {
-    {
-        $(#[derive($derives:ident)])*
-        pub struct $name:ident {
-            $($member_name:ident: $member_type:ty,)*
-        }
-    } => {
-        $(#[derive($derives)])*
-        #[repr(C)]
-        pub struct $name {
-            $($member_name: $member_type,)*
-        }
-
-        buildable_struct_helper!{
-            struct $name {
-                $($member_name: $member_type,)*
-            }
-        }
-    };
-    {
-        $(#[derive($derives:ident)])*
-        struct $name:ident {
-            $($member_name:ident: $member_type:ty,)*
-        }
-    } => {
-        $(#[derive($derives)])*
-        #[repr(C)]
-        struct $name {
-            $($member_name: $member_type,)*
-        }
-
-        buildable_struct_helper!{
-            struct $name {
-                $($member_name: $member_type,)*
-            }
-        }
-    };
-}
-
-/// length of a vector
-pub enum VectorLength {
-    /// fixed length vector
-    Fixed {
-        /// length in elements
-        length: u32,
-    },
-    /// variable length vector
-    Variable {
-        /// base length in elements which the runtime vector length is a multiple of
-        base_length: u32,
-    },
-}
-
-/// equivalent to LLVM's 'Type'
-pub trait Type<'a>: Clone + Eq + Hash + Debug {
-    /// the `Context` type
-    type Context: Context<'a>;
-}
-
-/// trait for building types
-pub trait TypeBuilder<'a, Ty: Type<'a>> {
-    /// build a `bool` type
-    fn build_bool(&self) -> Ty;
-    /// build an 8-bit sign-agnostic integer type
-    fn build_i8(&self) -> Ty;
-    /// build an 16-bit sign-agnostic integer type
-    fn build_i16(&self) -> Ty;
-    /// build an 32-bit sign-agnostic integer type
-    fn build_i32(&self) -> Ty;
-    /// build an 64-bit sign-agnostic integer type
-    fn build_i64(&self) -> Ty;
-    /// build an 32-bit IEEE 754 floating-point type
-    fn build_f32(&self) -> Ty;
-    /// build an 64-bit IEEE 754 floating-point type
-    fn build_f64(&self) -> Ty;
-    /// build a pointer
-    fn build_pointer(&self, target: Ty) -> Ty;
-    /// build an array
-    fn build_array(&self, element: Ty, count: usize) -> Ty;
-    /// build a vector
-    fn build_vector(&self, element: Ty, length: VectorLength) -> Ty;
-    /// build a struct
-    fn build_struct(&self, members: &[Ty]) -> Ty;
-    /// build a function type
-    fn build_function(&self, arguments: &[Ty], return_type: Option<Ty>) -> Ty;
-    /// build a type
-    fn build<T: BuildableType>(&self) -> Ty
-    where
-        Self: Sized,
-    {
-        T::build(self)
-    }
-}
-
-impl<'a, 'b, Ty: Type<'a>> TypeBuilder<'a, Ty> for &'b TypeBuilder<'a, Ty> {
-    fn build_bool(&self) -> Ty {
-        (*self).build_bool()
-    }
-    fn build_i8(&self) -> Ty {
-        (*self).build_i8()
-    }
-    fn build_i16(&self) -> Ty {
-        (*self).build_i16()
-    }
-    fn build_i32(&self) -> Ty {
-        (*self).build_i32()
-    }
-    fn build_i64(&self) -> Ty {
-        (*self).build_i64()
-    }
-    fn build_f32(&self) -> Ty {
-        (*self).build_f32()
-    }
-    fn build_f64(&self) -> Ty {
-        (*self).build_f64()
-    }
-    fn build_pointer(&self, target: Ty) -> Ty {
-        (*self).build_pointer(target)
-    }
-    fn build_array(&self, element: Ty, count: usize) -> Ty {
-        (*self).build_array(element, count)
-    }
-    fn build_vector(&self, element: Ty, length: VectorLength) -> Ty {
-        (*self).build_vector(element, length)
-    }
-    fn build_struct(&self, members: &[Ty]) -> Ty {
-        (*self).build_struct(members)
-    }
-    fn build_function(&self, arguments: &[Ty], return_type: Option<Ty>) -> Ty {
-        (*self).build_function(arguments, return_type)
-    }
-}
-
-/// trait for rust types that can be built using `TypeBuilder`
-pub trait BuildableType {
-    /// build the type represented by `Self`
-    fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty;
-}
-
-impl<T: BuildableType> BuildableType for UnsafeCell<T> {
-    fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
-        T::build(type_builder)
-    }
-}
-
-mod hidden {
-    pub trait ScalarBuildableTypeBase {}
-}
-
-impl<T: hidden::ScalarBuildableTypeBase> hidden::ScalarBuildableTypeBase for UnsafeCell<T> {}
-
-/// trait for rust types that can be an element of a vector and be built using `TypeBuilder`
-pub trait ScalarBuildableType: BuildableType + hidden::ScalarBuildableTypeBase {}
-
-impl<T: ScalarBuildableType> ScalarBuildableType for UnsafeCell<T> {}
-
-/// descriptor for members of types implementing `BuildableStruct`
-pub struct BuildableStructMemberDescriptor {
-    /// name of member
-    pub name: &'static str,
-    /// index of member
-    pub index: usize,
-}
-
-/// trait for structs that can be built using TypeBuilder
-/// implementing types are usually created using `buildable_struct!`
-pub trait BuildableStruct: BuildableType {
-    /// get the list of members for `Self`
-    fn get_members() -> &'static [BuildableStructMemberDescriptor];
-    /// get the member for `Self` that is named `name`
-    fn get_member_by_name(name: &str) -> &'static BuildableStructMemberDescriptor {
-        for member in Self::get_members() {
-            if name == member.name {
-                return member;
-            }
-        }
-        unreachable!("{} is not a member", name);
-    }
-}
-
-macro_rules! build_basic_scalar {
-    ($type:ty, $build_fn:ident) => {
-        impl BuildableType for $type {
-            fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
-                type_builder.$build_fn()
-            }
-        }
-
-        impl hidden::ScalarBuildableTypeBase for $type {}
-
-        impl ScalarBuildableType for $type {}
-    };
-}
-
-build_basic_scalar!(bool, build_bool);
-build_basic_scalar!(u8, build_i8);
-build_basic_scalar!(i8, build_i8);
-build_basic_scalar!(u16, build_i16);
-build_basic_scalar!(i16, build_i16);
-build_basic_scalar!(u32, build_i32);
-build_basic_scalar!(i32, build_i32);
-build_basic_scalar!(u64, build_i64);
-build_basic_scalar!(i64, build_i64);
-build_basic_scalar!(f32, build_f32);
-build_basic_scalar!(f64, build_f64);
-
-impl<'b, T: BuildableType> BuildableType for Option<&'b T> {
-    fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
-        type_builder.build_pointer(T::build(type_builder))
-    }
-}
-
-impl<'b, T: BuildableType> hidden::ScalarBuildableTypeBase for Option<&'b T> {}
-
-impl<'b, T: BuildableType> ScalarBuildableType for Option<&'b T> {}
-
-impl<'b, T: BuildableType> BuildableType for Option<&'b mut T> {
-    fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
-        type_builder.build_pointer(T::build(type_builder))
-    }
-}
-
-impl<'b, T: BuildableType> hidden::ScalarBuildableTypeBase for Option<&'b mut T> {}
-
-impl<'b, T: BuildableType> ScalarBuildableType for Option<&'b mut T> {}
-
-impl<'b, T: BuildableType> BuildableType for &'b T {
-    fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
-        type_builder.build_pointer(T::build(type_builder))
-    }
-}
-
-impl<'b, T: BuildableType> hidden::ScalarBuildableTypeBase for &'b T {}
-
-impl<'b, T: BuildableType> ScalarBuildableType for &'b T {}
-
-impl<'b, T: BuildableType> BuildableType for &'b mut T {
-    fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
-        type_builder.build_pointer(T::build(type_builder))
-    }
-}
-
-impl<'b, T: BuildableType> hidden::ScalarBuildableTypeBase for &'b mut T {}
-
-impl<'b, T: BuildableType> ScalarBuildableType for &'b mut T {}
-
-impl<T: BuildableType> BuildableType for *mut T {
-    fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
-        type_builder.build_pointer(T::build(type_builder))
-    }
-}
-
-impl<'b, T: BuildableType> hidden::ScalarBuildableTypeBase for *mut T {}
-
-impl<'b, T: BuildableType> ScalarBuildableType for *mut T {}
-
-impl<T: BuildableType> BuildableType for *const T {
-    fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
-        type_builder.build_pointer(T::build(type_builder))
-    }
-}
-
-impl<'b, T: BuildableType> hidden::ScalarBuildableTypeBase for *const T {}
-
-impl<'b, T: BuildableType> ScalarBuildableType for *const T {}
-
-impl<T: BuildableType> BuildableType for NonNull<T> {
-    fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
-        type_builder.build_pointer(T::build(type_builder))
-    }
-}
-
-impl<'b, T: BuildableType> hidden::ScalarBuildableTypeBase for NonNull<T> {}
-
-impl<'b, T: BuildableType> ScalarBuildableType for NonNull<T> {}
-
-impl<T: BuildableType> BuildableType for Option<NonNull<T>> {
-    fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
-        type_builder.build_pointer(T::build(type_builder))
-    }
-}
-
-impl<'b, T: BuildableType> hidden::ScalarBuildableTypeBase for Option<NonNull<T>> {}
-
-impl<'b, T: BuildableType> ScalarBuildableType for Option<NonNull<T>> {}
-
-macro_rules! build_unit_function_type {
-        ($($arguments:ident,)*) => {
-            impl<$($arguments: BuildableType),*> BuildableType for Option<unsafe extern "C" fn($($arguments,)*)> {
-                fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
-                    type_builder.build_function(&[$($arguments::build(type_builder),)*], None)
-                }
-            }
-
-            impl<$($arguments: BuildableType),*> hidden::ScalarBuildableTypeBase for Option<unsafe extern "C" fn($($arguments,)*)> {}
-
-            impl<$($arguments: BuildableType),*> ScalarBuildableType for Option<unsafe extern "C" fn($($arguments,)*)> {}
-
-            impl<$($arguments: BuildableType),*> BuildableType for unsafe extern "C" fn($($arguments,)*) {
-                fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
-                    type_builder.build_function(&[$($arguments::build(type_builder),)*], None)
-                }
-            }
-
-            impl<$($arguments: BuildableType),*> hidden::ScalarBuildableTypeBase for unsafe extern "C" fn($($arguments,)*) {}
-
-            impl<$($arguments: BuildableType),*> ScalarBuildableType for unsafe extern "C" fn($($arguments,)*) {}
-        };
-    }
-
-macro_rules! build_function_type {
-        ($($arguments:ident,)*) => {
-            impl<R: BuildableType, $($arguments: BuildableType),*> BuildableType for Option<unsafe extern "C" fn($($arguments,)*) -> R> {
-                fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
-                    type_builder.build_function(&[$($arguments::build(type_builder),)*], Some(R::build(type_builder)))
-                }
-            }
-
-            impl<R: BuildableType, $($arguments: BuildableType),*> hidden::ScalarBuildableTypeBase for Option<unsafe extern "C" fn($($arguments,)*) -> R> {}
-
-            impl<R: BuildableType, $($arguments: BuildableType),*> ScalarBuildableType for Option<unsafe extern "C" fn($($arguments,)*) -> R> {}
-
-            impl<R: BuildableType, $($arguments: BuildableType),*> BuildableType for unsafe extern "C" fn($($arguments,)*) -> R {
-                fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
-                    type_builder.build_function(&[$($arguments::build(type_builder),)*], Some(R::build(type_builder)))
-                }
-            }
-
-            impl<R: BuildableType, $($arguments: BuildableType),*> hidden::ScalarBuildableTypeBase for unsafe extern "C" fn($($arguments,)*) -> R {}
-
-            impl<R: BuildableType, $($arguments: BuildableType),*> ScalarBuildableType for unsafe extern "C" fn($($arguments,)*) -> R {}
-
-        };
-    }
-
-macro_rules! build_function_types {
-        () => {
-            build_unit_function_type!();
-            build_function_type!();
-        };
-        ($first_argument:ident, $($arguments:ident,)*) => {
-            build_unit_function_type!($first_argument, $($arguments,)*);
-            build_function_type!($first_argument, $($arguments,)*);
-            build_function_types!($($arguments,)*);
-        }
-    }
-
-build_function_types!(
-    T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19,
-);
-
-macro_rules! build_array0 {
-    ($length:expr) => {
-        impl<T: BuildableType> BuildableType for [T; $length + 1] {
-            fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
-                type_builder.build_array(T::build(type_builder), $length + 1)
-            }
-        }
-    };
-}
-
-macro_rules! build_array1 {
-    ($length:expr) => {
-        build_array0!($length * 2);
-        build_array0!($length * 2 + 1);
-    };
-}
-
-macro_rules! build_array2 {
-    ($length:expr) => {
-        build_array1!($length * 2);
-        build_array1!($length * 2 + 1);
-    };
-}
-
-macro_rules! build_array3 {
-    ($length:expr) => {
-        build_array2!($length * 2);
-        build_array2!($length * 2 + 1);
-    };
-}
-
-macro_rules! build_array4 {
-    ($length:expr) => {
-        build_array3!($length * 2);
-        build_array3!($length * 2 + 1);
-    };
-}
-
-macro_rules! build_array5 {
-    ($length:expr) => {
-        build_array4!($length * 2);
-        build_array4!($length * 2 + 1);
-    };
-}
-
-build_array5!(0);
-build_array5!(1);
-
-/// buildable vector types
-pub trait Vector: BuildableType {
-    /// element type
-    type Element: ScalarBuildableType;
-    /// vector length
-    const LENGTH: VectorLength;
-}
-
-#[doc(hidden)]
-pub enum __VectorNeverType {}
-
-macro_rules! build_fixed_vector {
-    ($name:ident, $length:expr) => {
-        /// Vector of elements `Element`
-        #[derive(Copy, Clone)]
-        pub struct $name<Element: ScalarBuildableType> {
-            /// elements of the vector `Self`
-            pub elements: [Element; $length],
-        }
-
-        impl<Element: ScalarBuildableType> Deref for $name<Element> {
-            type Target = [Element; $length];
-            fn deref(&self) -> &Self::Target {
-                &self.elements
-            }
-        }
-
-        impl<Element: ScalarBuildableType> DerefMut for $name<Element> {
-            fn deref_mut(&mut self) -> &mut Self::Target {
-                &mut self.elements
-            }
-        }
-
-        impl<Element: ScalarBuildableType> BuildableType for $name<Element> {
-            fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
-                type_builder.build_vector(Element::build(type_builder), Self::LENGTH)
-            }
-        }
-
-        impl<Element: ScalarBuildableType> Vector for $name<Element> {
-            type Element = Element;
-            const LENGTH: VectorLength = { VectorLength::Fixed { length: $length } };
-        }
-    };
-}
-
-macro_rules! build_variable_vector {
-    ($name:ident, $base_length:expr) => {
-        /// Vector of elements `Element`
-        pub enum $name<Element: ScalarBuildableType> {
-            #[doc(hidden)]
-            __Dummy(__VectorNeverType, PhantomData<Element>),
-        }
-
-        impl<Element: ScalarBuildableType> BuildableType for $name<Element> {
-            fn build<'a, Ty: Type<'a>, TB: TypeBuilder<'a, Ty>>(type_builder: &TB) -> Ty {
-                type_builder.build_vector(Element::build(type_builder), Self::LENGTH)
-            }
-        }
-
-        impl<Element: ScalarBuildableType> Vector for $name<Element> {
-            type Element = Element;
-            const LENGTH: VectorLength = {
-                VectorLength::Variable {
-                    base_length: $base_length,
-                }
-            };
-        }
-    };
-}
-
-/// alternate name for `VecNx1`
-pub type VecN<Element> = VecNx1<Element>;
-
-build_fixed_vector!(Vec1, 1);
-build_fixed_vector!(Vec2, 2);
-build_fixed_vector!(Vec3, 3);
-build_fixed_vector!(Vec4, 4);
-build_fixed_vector!(Vec5, 5);
-build_fixed_vector!(Vec6, 6);
-build_fixed_vector!(Vec7, 7);
-build_fixed_vector!(Vec8, 8);
-build_fixed_vector!(Vec9, 9);
-build_fixed_vector!(Vec10, 10);
-build_fixed_vector!(Vec11, 11);
-build_fixed_vector!(Vec12, 12);
-build_fixed_vector!(Vec13, 13);
-build_fixed_vector!(Vec14, 14);
-build_fixed_vector!(Vec15, 15);
-build_fixed_vector!(Vec16, 16);
-build_variable_vector!(VecNx1, 1);
-build_variable_vector!(VecNx2, 2);
-build_variable_vector!(VecNx3, 3);
-build_variable_vector!(VecNx4, 4);
-build_variable_vector!(VecNx5, 5);
-build_variable_vector!(VecNx6, 6);
-build_variable_vector!(VecNx7, 7);
-build_variable_vector!(VecNx8, 8);
-build_variable_vector!(VecNx9, 9);
-build_variable_vector!(VecNx10, 10);
-build_variable_vector!(VecNx11, 11);
-build_variable_vector!(VecNx12, 12);
-build_variable_vector!(VecNx13, 13);
-build_variable_vector!(VecNx14, 14);
-build_variable_vector!(VecNx15, 15);
-build_variable_vector!(VecNx16, 16);
diff --git a/shader-compiler/src/lib.rs b/shader-compiler/src/lib.rs
deleted file mode 100644 (file)
index bcbb3f0..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-// SPDX-License-Identifier: LGPL-2.1-or-later
-// Copyright 2018 Jacob Lifshay
-#![deny(missing_docs)]
-
-//! Shader Compiler for Kazan
-
-#[macro_use]
-pub mod backend;
-
-#[cfg(test)]
-mod test {
-    #![allow(dead_code)]
-
-    buildable_struct!{
-        struct S1 {
-        }
-    }
-
-    buildable_struct!{
-        pub struct S2 {
-            v: u32,
-        }
-    }
-
-    buildable_struct!{
-        struct S3 {
-            p: *mut S2,
-            v: ::backend::types::VecNx4<f32>,
-        }
-    }
-}
index b9013264b4395036d875a6792ca57dc68ae790fa..ac2666dbdeba1cd4b38678d6992398990eff08c2 100644 (file)
@@ -14,8 +14,8 @@ crate-type = ["cdylib"]
 enum-map = "0.4"
 uuid = {version = "0.7", features = ["v5"]}
 sys-info = "0.5"
-shader-compiler = {path = "../shader-compiler"}
-shader-compiler-llvm-7 = {path = "../shader-compiler-llvm-7"}
+shader-compiler-backend = {path = "../shader-compiler-backend"}
+shader-compiler-backend-llvm-7 = {path = "../shader-compiler-backend-llvm-7"}
 
 [target.'cfg(unix)'.dependencies]
 xcb = {version = "0.8", features = ["shm"]}
index 66fa5a752b6bdb8d86c278a5c374e7c440870f28..8f297d98e2e561662e0501f9313e1d21b5f8c5fd 100644 (file)
@@ -7,7 +7,7 @@ extern crate enum_map;
 extern crate errno;
 #[cfg(unix)]
 extern crate libc;
-extern crate shader_compiler;
+extern crate shader_compiler_backend;
 extern crate sys_info;
 extern crate uuid;
 #[cfg(unix)]