Browse Source

replace sdl2-sys and llvm-sys with our own bindings

master
Alison Watson 1 month ago
parent
commit
26f753a999
15 changed files with 666 additions and 299 deletions
  1. +31
    -126
      Cargo.lock
  2. +38
    -11
      Cargo.toml
  3. +36
    -0
      source/framework/build.rs
  4. +32
    -2
      source/framework/ffi.rs
  5. +3
    -4
      source/framework/hal.rs
  6. +7
    -8
      source/framework/hal/ctx.rs
  7. +15
    -9
      source/framework/hal/evt.rs
  8. +183
    -0
      source/framework/hal/sdl.rs
  9. +21
    -24
      source/framework/hal/win.rs
  10. +0
    -1
      source/framework/render/conf.rs
  11. +47
    -47
      source/framework/vire/compiler.rs
  12. +48
    -37
      source/framework/vire/compiler/function.rs
  13. +176
    -0
      source/framework/vire/compiler/llvm.rs
  14. +24
    -26
      source/framework/vire/compiler/types.rs
  15. +5
    -4
      source/macros/lib.rs

+ 31
- 126
Cargo.lock View File

@@ -1,19 +1,10 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "aho-corasick"
version = "0.7.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5"
dependencies = [
"memchr",
]

[[package]]
name = "ash"
version = "0.32.0"
version = "0.32.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77ea56be8250318e64923c7e65b82a35b5c29dfb6dc1c7d1c0b288c4b1bbb084"
checksum = "06063a002a77d2734631db74e8f4ce7148b77fe522e6bca46f2ae7774fd48112"
dependencies = [
"libloading",
]
@@ -24,19 +15,25 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"

[[package]]
name = "bitflags"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"

[[package]]
name = "blonkus"
version = "0.1.0"
dependencies = [
"ash",
"bitflags",
"blonkus_ma",
"glam",
"intaglio",
"llvm-sys",
"memchr",
"sdl2-sys",
"half",
"libc",
"serde",
"shh",
"smallvec",
"smol_str",
"thiserror",
"toml",
@@ -52,12 +49,6 @@ dependencies = [
"syn",
]

[[package]]
name = "cc"
version = "1.0.67"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd"

[[package]]
name = "cfg-if"
version = "0.1.10"
@@ -80,22 +71,16 @@ dependencies = [
]

[[package]]
name = "intaglio"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "967a032d0341206335b103da5445b3816370c644af65ca3ca1af9999dca7ea0f"

[[package]]
name = "lazy_static"
version = "1.4.0"
name = "half"
version = "1.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
checksum = "62aca2aba2d62b4a7f5b33f3712cb1b0692779a56fb510499d5c0aa594daeaf3"

[[package]]
name = "libc"
version = "0.2.91"
version = "0.2.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8916b1f6ca17130ec6568feccee27c156ad12037880833a3b842a823236502e7"
checksum = "9385f66bf6105b241aa65a61cb923ef20efc665cb9f9bb50ac2f0c4b7f378d41"

[[package]]
name = "libloading"
@@ -113,25 +98,6 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7d73b3f436185384286bd8098d17ec07c9a7d2388a6599f824d8502b529702a"

[[package]]
name = "llvm-sys"
version = "110.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21ede189444b8c78907e5d36da5dabcf153170fcff9c1dba48afc4b33c7e19f0"
dependencies = [
"cc",
"lazy_static",
"libc",
"regex",
"semver",
]

[[package]]
name = "memchr"
version = "2.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"

[[package]]
name = "num-traits"
version = "0.2.14"
@@ -142,20 +108,11 @@ dependencies = [
"libm",
]

[[package]]
name = "pest"
version = "2.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53"
dependencies = [
"ucd-trie",
]

[[package]]
name = "proc-macro2"
version = "1.0.24"
version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec"
dependencies = [
"unicode-xid",
]
@@ -169,52 +126,6 @@ dependencies = [
"proc-macro2",
]

[[package]]
name = "regex"
version = "1.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "957056ecddbeba1b26965114e191d2e8589ce74db242b6ea25fc4062427a5c19"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]

[[package]]
name = "regex-syntax"
version = "0.6.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5f089152e60f62d28b835fbff2cd2e8dc0baf1ac13343bef92ab7eed84548"

[[package]]
name = "sdl2-sys"
version = "0.34.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28d81feded049b9c14eceb4a4f6d596a98cebbd59abdba949c5552a015466d33"
dependencies = [
"cfg-if 0.1.10",
"libc",
"version-compare",
]

[[package]]
name = "semver"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6"
dependencies = [
"semver-parser",
]

[[package]]
name = "semver-parser"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7"
dependencies = [
"pest",
]

[[package]]
name = "serde"
version = "1.0.125"
@@ -245,6 +156,12 @@ dependencies = [
"winapi",
]

[[package]]
name = "smallvec"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e"

[[package]]
name = "smol_str"
version = "0.1.17"
@@ -253,9 +170,9 @@ checksum = "6ca0f7ce3a29234210f0f4f0b56f8be2e722488b95cb522077943212da3b32eb"

[[package]]
name = "spirv-std"
version = "0.4.0-alpha.2"
version = "0.4.0-alpha.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1dff3b92a316f3be955de023f86c2a0f91057f7eb69f5991df81eceb85edfd10"
checksum = "895a86b30e3dab8b15ca414bdf1d5d3f132374debb8bf03ca5e89109f674a171"
dependencies = [
"num-traits",
"spirv-std-macros",
@@ -263,9 +180,9 @@ dependencies = [

[[package]]
name = "spirv-std-macros"
version = "0.4.0-alpha.2"
version = "0.4.0-alpha.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8a0b7070980d04781535bff719f9db79745df78ffbf1e45aba5a0e6ed7079dd"
checksum = "5b76d9abb9f30d0da7c54e164efecbfab6c8af3493ae41d43c38ebfbb80b9894"
dependencies = [
"proc-macro2",
"quote",
@@ -280,9 +197,9 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"

[[package]]
name = "syn"
version = "1.0.65"
version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3a1d708c221c5a612956ef9f75b37e454e88d1f7b899fbd3a18d4252012d663"
checksum = "48fe99c6bd8b1cc636890bcc071842de909d902c81ac7dab53ba33c421ab8ffb"
dependencies = [
"proc-macro2",
"quote",
@@ -328,24 +245,12 @@ dependencies = [
"static_assertions",
]

[[package]]
name = "ucd-trie"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c"

[[package]]
name = "unicode-xid"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"

[[package]]
name = "version-compare"
version = "0.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d63556a25bae6ea31b52e640d7c41d1ab27faba4ccb600013837a3d0b3994ca1"

[[package]]
name = "winapi"
version = "0.3.9"


+ 38
- 11
Cargo.toml View File

@@ -12,22 +12,49 @@ publish = false
keywords = ["gamedev", "engine"]
categories = ["game-development"]
resolver = "2"
build = "source/framework/build.rs"

[dependencies]
ash = "~0.32"
blonkus_ma = { path = "source/macros" }
glam = "~0.13"
intaglio = "~1.2"
llvm-sys = "~110"
memchr = "~2.3"
sdl2-sys = "~0.34"
serde = { version = "~1.0", features = ["derive"] }
shh = "~1.0"
smol_str = "~0.1"
thiserror = "~1.0"
toml = "~0.5"

# types:
# - bitflags for FFI usage
# - smallvec for potentially small dynamic arrays
# - smol_str for potentially small immutable strings
# - thiserror for implementing error types
bitflags = "~1.2"
smallvec = { version = "~1.6", features = ["const_generics", "union"] }
smol_str = "~0.1"
thiserror = "~1.0"

# i/o:
# - serde for serializing and deserializing our own formats
# - shh for hacking around LLVM crimes
# - toml for config / description files
serde = { version = "~1.0", features = ["derive"] }
shh = "~1.0"
toml = "~0.5"

# math:
# - glam for linear algebra
# - half for half-floats in certain areas
glam = "~0.13"
half = "~1.7"

# hashing:
# - intaglio for symbol tables?
# - rustc-hash for things like mesh names?
# - twox-hash for file deduplication
#intaglio = "~1.2"
#rustc-hash = { version = "~1.1", default-features = false }
twox-hash = { version = "~1.6", default-features = false }

# bindings:
# - ash for the renderer implementation
# - libc for binding SDL2 and LLVM
ash = "~0.32"
libc = "~0.2"

[profile.dev]
opt-level = 1



+ 36
- 0
source/framework/build.rs View File

@@ -0,0 +1,36 @@
fn llvm_config(opt: &str) -> String {
std::process::Command::new("llvm-config")
.arg(opt)
.arg("--link-static")
.arg("engine")
.output()
.map(|out| String::from_utf8(out.stdout).unwrap())
.unwrap()
}

fn llvm_config_array(opt: &str) -> Vec<String> {
llvm_config(opt)
.split(' ')
.filter(|lib| !lib.is_empty())
.map(|lib| lib.to_owned())
.collect()
}

fn main() {
let lib_dir = llvm_config("--libdir");
let libs = llvm_config_array("--libs");
let sys_libs = llvm_config_array("--system-libs");

println!("cargo:rustc-link-search=native={}", lib_dir);
for lib in libs.into_iter().chain(sys_libs.into_iter()) {
println!("cargo:rustc-flags={}", lib);
}

#[cfg(any(target_os = "macos", target_os = "freebsd"))]
println!("cargo:rustc-link-lib=c++");

#[cfg(target_os = "linux")]
println!("cargo:rustc-link-lib=stdc++");
}

// EOF

+ 32
- 2
source/framework/ffi.rs View File

@@ -1,5 +1,6 @@
use std::{
ffi::{CStr, CString},
os::raw,
ptr::null,
};

@@ -11,7 +12,36 @@ macro_rules! c_str {
};
}

pub type Nts = *const std::os::raw::c_char;
#[macro_export]
macro_rules! opaque_struct {
(pub $s:ident) => {
#[repr(C)]
pub struct $s {
_private: [u8; 0],
}
};
($s:ident) => {
#[repr(C)]
struct $s {
_private: [u8; 0],
}
};
}

#[repr(C)]
pub enum Bool {
False = 0,
True,
}

impl Bool {
#[inline]
pub const fn is_true(&self) -> bool {
matches!(self, Self::True)
}
}

pub type Nts = *const raw::c_char;

#[inline]
pub fn cstr_from_slice(s: &[u8]) -> Option<&str> {
@@ -33,7 +63,7 @@ pub unsafe fn cstr_from_ptr(s: Nts) -> Option<&'static str> {

#[inline]
pub fn end_of_cstr(s: &[u8]) -> usize {
if let Some(n) = memchr::memchr(0, s) {
if let Some(n) = s.iter().position(|&b| b == b'\0') {
n
} else {
0


+ 3
- 4
source/framework/hal.rs View File

@@ -2,7 +2,8 @@ pub mod ctx;
pub mod evt;
pub mod win;

pub(self) use sdl2_sys as sdl;
#[doc(hidden)]
pub mod sdl;

#[derive(Error, Debug)]
pub enum Err {
@@ -18,9 +19,7 @@ impl Err {
/// This function will cause undefined behaviour if used from
/// multiple threads.
pub(self) unsafe fn new_sdl() -> Self {
Self::Sdl(
std::ffi::CStr::from_ptr(sdl::SDL_GetError()).to_string_lossy(),
)
Self::Sdl(std::ffi::CStr::from_ptr(sdl::get_error()).to_string_lossy())
}
}



+ 7
- 8
source/framework/hal/ctx.rs View File

@@ -4,14 +4,13 @@ pub struct Context;

impl Context {
pub fn new() -> Result<Self, Err> {
let init_flags = sdl::SDL_INIT_VIDEO;
unsafe {
sdl::SDL_SetMainReady();
}
if unsafe { sdl::SDL_Init(init_flags) } == 0 {
Ok(Self)
} else {
Err(unsafe { Err::new_sdl() })
sdl::set_main_ready();
if sdl::init(sdl::InitFlags::VIDEO) == 0 {
Ok(Self)
} else {
Err(Err::new_sdl())
}
}
}
}
@@ -19,7 +18,7 @@ impl Context {
impl Drop for Context {
fn drop(&mut self) {
unsafe {
sdl::SDL_Quit();
sdl::quit();
}
}
}


+ 15
- 9
source/framework/hal/evt.rs View File

@@ -10,20 +10,26 @@ impl Iterator for EventIterator {
type Item = Event;

fn next(&mut self) -> Option<Self::Item> {
let mut event = unsafe { std::mem::MaybeUninit::uninit().assume_init() };
while unsafe { sdl::SDL_PollEvent(&mut event) } == 1 {
if let Some(evt) = read_in(event) {
return Some(evt);
unsafe {
loop {
let mut event = std::mem::MaybeUninit::uninit();

if sdl::poll_event(event.as_mut_ptr()) != 1 {
break;
}

if let Some(evt) = read_in(event.assume_init()) {
return Some(evt);
}
}
None
}
None
}
}

fn read_in(evt: sdl::SDL_Event) -> Option<Event> {
let typ = unsafe { std::mem::transmute(evt.type_) };
match typ {
| sdl::SDL_EventType::SDL_QUIT => Some(Event::Quit),
fn read_in(evt: sdl::Event) -> Option<Event> {
match unsafe { evt.ty } {
| sdl::EventType::Quit => Some(Event::Quit),
| _ => None,
}
}


+ 183
- 0
source/framework/hal/sdl.rs View File

@@ -0,0 +1,183 @@
use bitflags::bitflags;
use crate::ffi::Bool;
use std::os::raw;

pub const WINDOW_POS_UNDEF: raw::c_int = 0x1FFF0000;

bitflags! {
#[repr(transparent)]
pub struct InitFlags: u32 {
const TIMER = 0x01;
const AUDIO = 0x10;
const VIDEO = 0x20;
const JOYSTICK = 0x200;
const HAPTIC = 0x1000;
const GAME_CONTROLLER = 0x2000;
const EVENTS = 0x4000;
const SENSOR = 0x8000;
}
}

bitflags! {
#[repr(transparent)]
pub struct WindowFlags: u32 {
const FULLSCREEN = 0x00000001;
const OPENGL = 0x00000002;
const SHOWN = 0x00000004;
const HIDDEN = 0x00000008;
const BORDERLESS = 0x00000010;
const RESIZABLE = 0x00000020;
const MINIMIZED = 0x00000040;
const MAXIMIZED = 0x00000080;
const INPUT_GRABBED = 0x00000100;
const INPUT_FOCUS = 0x00000200;
const MOUSE_FOCUS = 0x00000400;
const FULLSCREEN_DESKTOP = Self::FULLSCREEN.bits | 0x00001000;
const FOREIGN = 0x00000800;
const ALLOW_HIGH_DPI = 0x00002000;
const MOUSE_CAPTURE = 0x00004000;
const ALWAYS_ON_TOP = 0x00008000;
const SKIP_TASKBAR = 0x00010000;
const UTILITY = 0x00020000;
const TOOLTIP = 0x00040000;
const POPUP_MENU = 0x00080000;
const VULKAN = 0x10000000;
const METAL = 0x20000000;
}
}

#[repr(u32)]
#[derive(Clone, Copy)]
pub enum EventType {
Quit = 0x100,

AppTerminating,
AppLowMemory,
AppWillEnterBackground,
AppDidEnterBackground,
AppWillEnterForeground,
AppDidEnterForeground,

LocaleChanged,

DisplayEvent = 0x150,

WindowEvent = 0x200,
SysWmEvent,

KeyDown = 0x300,
KeyUp,
TextEditing,
TextInput,
KeyMapChanged,

MouseMotion = 0x400,
MouseButtonDown,
MouseButtonUp,
MouseWheel,

JoyAxisMotion = 0x600,
JoyBallMotion,
JoyHatMotion,
JoyButtonDown,
JoyButtonUp,
JoyDeviceAdded,
JoyDeviceRemoved,

ControllerAxisMotion = 0x650,
ControllerButtonDown,
ControllerButtonUp,
ControllerDeviceAdded,
ControllerDeviceRemoved,
ControllerDeviceRemapped,
ControllerTouchPadDown,
ControllerTouchPadMotion,
ControllerTouchPadUp,
ControllerSensorUpdate,

FingerDown = 0x700,
FingerUp,
FingerMotion,

DollarGesture = 0x800,
DollarRecord,
MultiGesture,

ClipboardUpdate = 0x900,

DropFile = 0x1000,
DropText,
DropBegin,
DropComplete,

AudioDeviceAdded = 0x1100,
AudioDeviceRemoved,

SensorUpdate = 0x1200,

RenderTargetsReset = 0x2000,
RenderDeviceReset,
}

#[repr(C)]
#[derive(Copy, Clone)]
pub struct CommonEvent {
pub ty: EventType,
pub time_stamp: u32,
}

#[repr(C)]
pub union Event {
pub ty: EventType,
pub common: CommonEvent,

_forced_size: [u8; 56],
}

opaque_struct!(pub Window);

#[link(name = "SDL2")]
extern "C" {
// initialization
#[link_name = "SDL_SetMainReady"]
pub fn set_main_ready();

#[link_name = "SDL_Init"]
pub fn init(flags: InitFlags) -> raw::c_int;

#[link_name = "SDL_Quit"]
pub fn quit();

// errors
#[link_name = "SDL_GetError"]
pub fn get_error() -> *const raw::c_char;

// events
#[link_name = "SDL_PollEvent"]
pub fn poll_event(event: *mut Event) -> raw::c_int;

// windows
#[link_name = "SDL_CreateWindow"]
pub fn create_window(
title: *const raw::c_char, x: raw::c_int, y: raw::c_int, w: raw::c_int,
h: raw::c_int, flags: WindowFlags,
) -> *mut Window;

#[link_name = "SDL_DestroyWindow"]
pub fn destroy_window(window: *mut Window);

// vulkan
#[link_name = "SDL_Vulkan_GetInstanceExtensions"]
pub fn vulkan_get_instance_extensions(
window: *mut Window, p_count: *mut raw::c_uint,
p_names: *mut *const raw::c_char,
) -> Bool;

#[link_name = "SDL_Vulkan_CreateSurface"]
pub fn vulkan_create_surface(
window: *mut Window, instance: ash::vk::Instance,
surface: *mut ash::vk::SurfaceKHR,
) -> Bool;
}

// EOF

+ 21
- 24
source/framework/hal/win.rs View File

@@ -1,33 +1,30 @@
use super::*;
use crate::ffi;
use ash::{
version::InstanceV1_0,
vk::{self, Handle},
};
use std::{marker::PhantomData, os::raw::c_int};
use ash::{version::InstanceV1_0, vk};
use std::marker::PhantomData;

pub struct Window<'a> {
handle: *mut sdl::Window,
hal: PhantomData<&'a ctx::Context>,
handle: *mut sdl::SDL_Window,
}

impl<'a> Window<'a> {
pub fn new(
_hal: &'a ctx::Context, title: ffi::Nts, w: i16, h: i16,
_hal: &'a ctx::Context, title: ffi::Nts, w: u16, h: u16,
) -> Result<Self, Err> {
unsafe {
let handle = sdl::SDL_CreateWindow(
let handle = sdl::create_window(
title,
sdl::SDL_WINDOWPOS_UNDEFINED_MASK as c_int,
sdl::SDL_WINDOWPOS_UNDEFINED_MASK as c_int,
sdl::WINDOW_POS_UNDEF,
sdl::WINDOW_POS_UNDEF,
w.into(),
h.into(),
sdl::SDL_WindowFlags::SDL_WINDOW_SHOWN as u32
| sdl::SDL_WindowFlags::SDL_WINDOW_VULKAN as u32
| sdl::SDL_WindowFlags::SDL_WINDOW_RESIZABLE as u32,
sdl::WindowFlags::SHOWN
| sdl::WindowFlags::VULKAN
| sdl::WindowFlags::RESIZABLE,
);
if !handle.is_null() {
Ok(Self { hal: PhantomData, handle })
Ok(Self { handle, hal: PhantomData })
} else {
Err(Err::new_sdl())
}
@@ -38,19 +35,19 @@ impl<'a> Window<'a> {
&self,
) -> Result<Vec<ffi::Nts>, Err> {
let mut count = 0;
let res = sdl::SDL_Vulkan_GetInstanceExtensions(
let res = sdl::vulkan_get_instance_extensions(
self.handle,
&mut count,
std::ptr::null_mut(),
);
if res != sdl::SDL_bool::SDL_FALSE {
if res.is_true() {
let mut names = vec![std::ptr::null(); count as usize];
let res = sdl::SDL_Vulkan_GetInstanceExtensions(
let res = sdl::vulkan_get_instance_extensions(
self.handle,
&mut count,
names.as_mut_ptr(),
);
if res != sdl::SDL_bool::SDL_FALSE {
if res.is_true() {
Ok(names)
} else {
Err(Err::new_sdl())
@@ -63,14 +60,14 @@ impl<'a> Window<'a> {
pub unsafe fn vulkan_create_surface(
&self, instance: &ash::Instance,
) -> Result<vk::SurfaceKHR, Err> {
let mut surface = 0;
let res = sdl::SDL_Vulkan_CreateSurface(
let mut surface = vk::SurfaceKHR::null();
let res = sdl::vulkan_create_surface(
self.handle,
instance.handle().as_raw() as usize,
instance.handle(),
&mut surface,
);
if res != sdl::SDL_bool::SDL_FALSE {
Ok(vk::SurfaceKHR::from_raw(surface))
if res.is_true() {
Ok(surface)
} else {
Err(Err::new_sdl())
}
@@ -80,7 +77,7 @@ impl<'a> Window<'a> {
impl Drop for Window<'_> {
fn drop(&mut self) {
unsafe {
sdl::SDL_DestroyWindow(self.handle);
sdl::destroy_window(self.handle);
}
}
}


+ 0
- 1
source/framework/render/conf.rs View File

@@ -2,7 +2,6 @@ use ash::vk;
use std::num::NonZeroUsize;

#[blonkus_ma::serialize_config]
#[derive(Clone, Copy)]
pub enum PresentMode {
Fifo,
FifoRelaxed,


+ 47
- 47
source/framework/vire/compiler.rs View File

@@ -1,14 +1,12 @@
pub mod function;
pub mod nat;
pub mod types;
#[doc(hidden)]
pub mod llvm;

pub(self) use self::{function::*, types::*};
pub(self) use super::parser::Datum;
pub(self) use crate::ffi;
pub(self) use llvm_sys::{
analysis::*, core::*, execution_engine::*, prelude::*, target::*,
target_machine::*,
};
pub(self) use crate::ffi::{self, Bool};

#[derive(Error, Debug)]
pub enum Err {
@@ -23,10 +21,10 @@ pub enum Err {
}

pub struct Context {
contx: LLVMContextRef,
modul: LLVMModuleRef,
build: LLVMBuilderRef,
engin: LLVMExecutionEngineRef,
contx: *mut llvm::Context,
modul: *mut llvm::Module,
build: *mut llvm::Builder,
engin: *mut llvm::ExecutionEngine,
types: Vec<ComplType>,
funcs: Vec<Function>,
}
@@ -44,27 +42,27 @@ impl Context {
];

unsafe {
init_llvm();
}
//init_llvm();

let contx = unsafe { LLVMContextCreate() };
let modul = unsafe { LLVMModuleCreateWithNameInContext(MODULE, contx) };
let build = unsafe { LLVMCreateBuilderInContext(contx) };
let engin = unsafe { jit_engine(modul)? };
let types = Vec::new();
let funcs = Vec::new();
let contx = llvm::context_new();
let modul = llvm::module_new_with_name_in_context(MODULE, contx);
let build = llvm::builder_new_in_context(contx);
let engin = jit_engine(modul)?;
let types = Vec::new();
let funcs = Vec::new();

let mut c = Self { contx, modul, build, engin, types, funcs };
let mut c = Self { contx, modul, build, engin, types, funcs };

for ty in types::Basic::iter() {
c.types.push(types::ComplType::Basic(types::BasicType::new(ty)));
}
for ty in types::Basic::iter() {
c.types.push(types::ComplType::Basic(types::BasicType::new(ty)));
}

for decl in NAT_FUNCTIONS.iter() {
decl(&mut c);
}
for decl in NAT_FUNCTIONS.iter() {
decl(&mut c);
}

Ok(c)
Ok(c)
}
}

pub fn basic_type(&self, ty: Basic) -> &ComplType {
@@ -93,7 +91,7 @@ impl Context {
pub fn execute(&self) -> Result<(), Err> {
unsafe {
let func: unsafe extern "C" fn() = std::mem::transmute(
LLVMGetFunctionAddress(self.engin, c_str!("-main")),
llvm::engine_get_function_address(self.engin, c_str!("-main")),
);
func();
}
@@ -104,53 +102,55 @@ impl Context {
impl Drop for Context {
fn drop(&mut self) {
unsafe {
LLVMDisposeExecutionEngine(self.engin);
LLVMDisposeBuilder(self.build);
LLVMContextDispose(self.contx);
llvm::engine_drop(self.engin);
llvm::builder_drop(self.build);
llvm::context_drop(self.contx);
}
}
}

unsafe fn jit_engine(
modul: LLVMModuleRef,
) -> Result<LLVMExecutionEngineRef, Err> {
let mut opt = LLVMMCJITCompilerOptions {
OptLevel: LLVMCodeGenOptLevel::LLVMCodeGenLevelAggressive as _,
CodeModel: LLVMCodeModel::LLVMCodeModelJITDefault,
NoFramePointerElim: 0,
EnableFastISel: 0,
MCJMM: std::ptr::null_mut(),
modul: *mut llvm::Module,
) -> Result<*mut llvm::ExecutionEngine, Err> {
let mut opt = llvm::McJitCompilerOptions {
opt_level: llvm::CodeGenOptLevel::Aggressive,
code_model: llvm::CodeModel::JitDefault,
no_frame_pointer_elim: Bool::False,
enable_fast_i_sel: Bool::False,
mc_jmm: std::ptr::null_mut(),
};
let mut jit = std::ptr::null_mut();
let mut msg = std::ptr::null_mut();

let res = LLVMCreateMCJITCompilerForModule(
let res = llvm::engine_new_mcjit_compiler_for_module(
&mut jit,
modul,
&mut opt,
std::mem::size_of::<LLVMMCJITCompilerOptions>(),
std::mem::size_of::<llvm::McJitCompilerOptions>(),
&mut msg,
);

if res != 0 {
let msg =
ffi::cstr_from_ptr(msg).unwrap_or("Couldn't parse error").to_owned();
Err(Err::JitInit(msg))
if res.is_true() {
Err(Err::JitInit(
ffi::cstr_from_ptr(msg).unwrap_or("Couldn't parse error").to_owned()
))
} else {
Ok(jit)
}
}

/*
unsafe fn init_llvm() {
static INIT: std::sync::Once = std::sync::Once::new();

INIT.call_once(|| {
LLVMLinkInMCJIT();
llvm::link_jit();

LLVM_InitializeNativeTarget();
LLVM_InitializeNativeAsmPrinter();
LLVM_InitializeNativeAsmParser();
_InitializeNativeTarget();
_InitializeNativeAsmPrinter();
_InitializeNativeAsmParser();
});
}
*/

// EOF

+ 48
- 37
source/framework/vire/compiler/function.rs View File

@@ -10,26 +10,29 @@ enum ErrCapture {
}

pub struct IncompleteFunction<'a> {
value: LLVMValueRef,
block: LLVMBasicBlockRef,
value: *mut llvm::Value,
block: *mut llvm::BasicBlock,
contx: &'a Context,
in_context: bool,
}

pub struct Function {
value: LLVMValueRef,
value: *mut llvm::Value,
}

impl<'a> IncompleteFunction<'a> {
pub fn new(c: &'a Context, name: ffi::Nts, ftyp: &FunctType) -> Self {
const ENT: ffi::Nts = c_str!("entry");
let value = unsafe { LLVMAddFunction(c.modul, name, ftyp.handle()) };
let block =
unsafe { LLVMAppendBasicBlockInContext(c.contx, value, ENT) };
Self { value, block, contx: c, in_context: false }
unsafe {
let value = llvm::module_add_function(c.modul, name, ftyp.handle());
let block = llvm::context_append_basic_block(c.contx, value, ENT);
Self { value, block, contx: c, in_context: false }
}
}

pub fn compile(&mut self, datum: &Datum) -> Result<LLVMValueRef, Err> {
pub fn compile(
&mut self, datum: &Datum
) -> Result<(*mut llvm::Type, *mut llvm::Value), Err> {
if !self.in_context {
return Err(Err::Context);
}
@@ -37,18 +40,20 @@ impl<'a> IncompleteFunction<'a> {
unsafe {
match datum {
| Datum::Null => {
Ok(LLVMGetUndef(self.contx.basic_type(Basic::Void).handle()))
let ty = self.contx.basic_type(Basic::Void).handle();
let vl = llvm::value_undef(ty);
Ok((ty, vl))
}
| Datum::Bool(val) => {
let ty = self.contx.basic_type(Basic::Bool).handle();
let vl = llvm::value_const_int(ty, *val as _, Bool::False);
Ok((ty, vl))
}
| Datum::Char(chr) => {
let ty = self.contx.basic_type(Basic::Q32_0U).handle();
let vl = llvm::value_const_int(ty, *chr as _, Bool::False);
Ok((ty, vl))
}
| Datum::Bool(value) => Ok(LLVMConstInt(
self.contx.basic_type(Basic::Bool).handle(),
*value as _,
0,
)),
| Datum::Char(character) => Ok(LLVMConstInt(
self.contx.basic_type(Basic::Q32_0U).handle(),
*character as _,
0,
)),
| Datum::Strn(_) => {
// TODO
Err(Err::Syntax)
@@ -56,33 +61,39 @@ impl<'a> IncompleteFunction<'a> {
| Datum::Symb(name) => {
// TODO: must support more than global function symbols
let name = CString::new(name.as_bytes()).unwrap().into_raw();
let func = LLVMGetNamedFunction(self.contx.modul, name);
let func = llvm::module_get_named_function(
self.contx.modul,
name,
);
CString::from_raw(name);
Ok(func)
Ok((llvm::value_type(func), func))
}
| Datum::Numb(num) => {
let ty = self.contx.basic_type(Basic::Q64_0).handle();
let vl = llvm::value_const_int(ty, *num as _, Bool::False);
Ok((ty, vl))
}
| Datum::Numb(number) => Ok(LLVMConstInt(
self.contx.basic_type(Basic::Q64_0).handle(),
*number as _,
0,
)),
| Datum::Cons { cdr, car } => {
// function call
let func = self.compile(car)?;
let (ftyp, func) = self.compile(car)?;
let mut args = Vec::new();

let mut cdr = cdr.as_ref();
while let Datum::Cons { cdr: cdr_next, car: car_next } = cdr {
args.push(self.compile(car_next)?);
args.push(self.compile(car_next)?.1);
cdr = cdr_next.as_ref();
}

Ok(LLVMBuildCall(
let call = llvm::builder_call(
self.contx.build,
ftyp,
func,
args.as_mut_ptr(),
args.len() as u32,
args.len() as _,
c_str!(""),
))
);

Ok((llvm::value_type(call), call))
}
}
}
@@ -92,7 +103,7 @@ impl<'a> IncompleteFunction<'a> {
&mut self, block: impl FnOnce(&mut Self) -> Result<(), Err>,
) -> Result<(), Err> {
unsafe {
LLVMPositionBuilderAtEnd(self.contx.build, self.block);
llvm::builder_position_at_end(self.contx.build, self.block);
}
self.in_context = true;
let res = block(self);
@@ -103,7 +114,7 @@ impl<'a> IncompleteFunction<'a> {
pub fn complete(self) -> Result<Function, Err> {
// insert ret void
unsafe {
LLVMBuildRetVoid(self.contx.build);
llvm::builder_ret_void(self.contx.build);
}

// redirect stderr to a buffer so we can actually see what
@@ -130,10 +141,10 @@ impl<'a> IncompleteFunction<'a> {

// verify
let verified = unsafe {
LLVMVerifyFunction(
!llvm::value_verify_func(
self.value,
LLVMVerifierFailureAction::LLVMPrintMessageAction,
) != 1
llvm::VerifierFailureAction::PrintMessage,
).is_true()
};

// it's okay if the sender errors because the receiver will only
@@ -158,7 +169,7 @@ impl<'a> IncompleteFunction<'a> {
}

impl Function {
pub fn new(value: LLVMValueRef) -> Self {
pub fn new(value: *mut llvm::Value) -> Self {
Self { value }
}
}


+ 176
- 0
source/framework/vire/compiler/llvm.rs View File

@@ -0,0 +1,176 @@
use crate::ffi::Bool;
use std::os::raw;

opaque_struct!(pub BasicBlock);
opaque_struct!(pub Builder);
opaque_struct!(pub Context);
opaque_struct!(pub ExecutionEngine);
opaque_struct!(pub McJitMemoryManager);
opaque_struct!(pub Module);
opaque_struct!(pub Type);
opaque_struct!(pub Value);

#[repr(C)]
pub enum CodeGenOptLevel {
None,
Less,
Default,
Aggressive,
}

#[repr(C)]
pub enum CodeModel {
Default,
JitDefault,
Tiny,
Small,
Kernel,
Medium,
Large,
}

#[repr(C)]
pub enum VerifierFailureAction {
AbortProcess,
PrintMessage,
ReturnStatus,
}

#[repr(C)]
pub struct McJitCompilerOptions {
pub opt_level: CodeGenOptLevel,
pub code_model: CodeModel,
pub no_frame_pointer_elim: Bool,
pub enable_fast_i_sel: Bool,
pub mc_jmm: *mut McJitMemoryManager,
}

extern "C" {
// contexts
#[link_name = "LLVMContextCreate"]
pub fn context_new() -> *mut Context;

#[link_name = "LLVMContextDispose"]
pub fn context_drop(contx: *mut Context);

#[link_name = "LLVMAppendBasicBlockInContext"]
pub fn context_append_basic_block(
contx: *mut Context, func: *mut Value, name: *const raw::c_char
) -> *mut BasicBlock;

// modules
#[link_name = "LLVMModuleCreateWithNameInContext"]
pub fn module_new_with_name_in_context(
module_id: *const raw::c_char, contx: *mut Context
) -> *mut Module;

#[link_name = "LLVMAddFunction"]
pub fn module_add_function(
modul: *mut Module, name: *const raw::c_char, func_ty: *mut Type
) -> *mut Value;

#[link_name = "LLVMGetNamedFunction"]
pub fn module_get_named_function(
modul: *mut Module, name: *const raw::c_char
) -> *mut Value;

// builders
#[link_name = "LLVMCreateBuilderInContext"]
pub fn builder_new_in_context(contx: *mut Context) -> *mut Builder;

#[link_name = "LLVMDisposeBuilder"]
pub fn builder_drop(build: *mut Builder);

#[link_name = "LLVMBuildCall2"]
pub fn builder_call(
build: *mut Builder, ftyp: *mut Type, func: *mut Value,
args: *mut *mut Value, count: raw::c_uint, name: *const raw::c_char
) -> *mut Value;

#[link_name = "LLVMBuildRetVoid"]
pub fn builder_ret_void(build: *mut Builder) -> *mut Value;

#[link_name = "LLVMBuildRet"]
pub fn builder_ret(build: *mut Builder, retn: *mut Value) -> *mut Value;

#[link_name = "LLVMPositionBuilderAtEnd"]
pub fn builder_position_at_end(build: *mut Builder, block: *mut BasicBlock);

// execution engines
#[link_name = "LLVMCreateMCJITCompilerForModule"]
pub fn engine_new_mcjit_compiler_for_module(
engin: *mut *mut ExecutionEngine, modul: *mut Module,
options: *mut McJitCompilerOptions, size_of_options: libc::size_t,
out_error: *mut *mut raw::c_char
) -> Bool;

#[link_name = "LLVMDisposeExecutionEngine"]
pub fn engine_drop(engin: *mut ExecutionEngine);

#[link_name = "LLVMAddGlobalMapping"]
pub fn engine_add_global_mapping(
engin: *mut ExecutionEngine, value: *mut Value, addr: *mut raw::c_void
);

#[link_name = "LLVMGetFunctionAddress"]
pub fn engine_get_function_address(
engin: *mut ExecutionEngine, name: *const raw::c_char
) -> u64;

// types
#[link_name = "LLVMPrintTypeToString"]
pub fn type_print_to_string(handle: *mut Type) -> *mut raw::c_char;

#[link_name = "LLVMArrayType"]
pub fn type_array(element: *mut Type, count: raw::c_uint) -> *mut Type;

#[link_name = "LLVMFunctionType"]
pub fn type_function(
retn: *mut Type, params: *mut *mut Type, count: raw::c_uint,
is_var_arg: Bool
) -> *mut Type;

#[link_name = "LLVMVoidType"]
pub fn type_void() -> *mut Type;

#[link_name = "LLVMInt1Type"]
pub fn type_int1() -> *mut Type;

#[link_name = "LLVMInt8Type"]
pub fn type_int8() -> *mut Type;

#[link_name = "LLVMInt16Type"]
pub fn type_int16() -> *mut Type;

#[link_name = "LLVMInt32Type"]
pub fn type_int32() -> *mut Type;

#[link_name = "LLVMInt64Type"]
pub fn type_int64() -> *mut Type;

// values
#[link_name = "LLVMGetUndef"]
pub fn value_undef(ty: *mut Type) -> *mut Value;

#[link_name = "LLVMConstInt"]
pub fn value_const_int(
ty: *mut Type, num: libc::c_ulonglong, sign_extend: Bool
) -> *mut Value;

#[link_name = "LLVMTypeOf"]
pub fn value_type(value: *mut Value) -> *mut Type;

#[link_name = "LLVMVerifyFunction"]
pub fn value_verify_func(
func: *mut Value, action: VerifierFailureAction
) -> Bool;

// errors
#[link_name = "LLVMCreateMessage"]
pub fn message_new(msg: *const raw::c_char) -> *mut raw::c_char;

#[link_name = "LLVMDisposeMessage"]
pub fn message_drop(msg: *mut raw::c_char);
}

// EOF

+ 24
- 26
source/framework/vire/compiler/types.rs View File

@@ -34,27 +34,27 @@ impl Basic {
#[derive(Clone, Copy)]
pub struct BasicType {
btyp: Basic,
handle: LLVMTypeRef,
handle: *mut llvm::Type,
}

#[derive(Clone)]
pub struct ArrayType {
size: usize,
memb: Box<ComplType>,
handle: LLVMTypeRef,
handle: *mut llvm::Type,
}

#[derive(Clone)]
pub struct StrucType {
memb: Vec<ComplType>,
handle: LLVMTypeRef,
handle: *mut llvm::Type,
}

#[derive(Clone)]
pub struct FunctType {
args: Vec<ComplType>,
retn: Box<ComplType>,
handle: LLVMTypeRef,
handle: *mut llvm::Type,
}

#[derive(Clone)]
@@ -66,15 +66,15 @@ pub enum ComplType {
}

pub trait TypeHandle {
fn handle(&self) -> LLVMTypeRef;
fn handle(&self) -> *mut llvm::Type;
}

impl std::fmt::Debug for dyn TypeHandle {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
unsafe {
let ptr = LLVMPrintTypeToString(self.handle());
let res = std::ffi::CStr::from_ptr(ptr).fmt(f);
LLVMDisposeMessage(ptr);
let msg = llvm::type_print_to_string(self.handle());
let res = std::ffi::CStr::from_ptr(msg).fmt(f);
llvm::message_drop(msg);
res
}
}
@@ -84,16 +84,14 @@ impl BasicType {
pub fn new(btyp: Basic) -> Self {
let handle = unsafe {
match btyp {
| Basic::Void => LLVMVoidType(),
| Basic::Bool => LLVMInt1Type(),
| Basic::Q8_0 | Basic::Q8_0U => LLVMInt8Type(),
| Basic::Q16_0 | Basic::Q16_0U | Basic::Q16 | Basic::Q16U => {
LLVMInt16Type()
}
| Basic::Q32_0 | Basic::Q32_0U | Basic::Q24_8 | Basic::Q24_8U => {
LLVMInt32Type()
}
| Basic::Q64_0 | Basic::Q64_0U => LLVMInt64Type(),
| Basic::Void => llvm::type_void(),
| Basic::Bool => llvm::type_int1(),
| Basic::Q8_0 | Basic::Q8_0U => llvm::type_int8(),
| Basic::Q16_0 | Basic::Q16_0U
| Basic::Q16 | Basic::Q16U => llvm::type_int16(),
| Basic::Q32_0 | Basic::Q32_0U
| Basic::Q24_8 | Basic::Q24_8U => llvm::type_int32(),
| Basic::Q64_0 | Basic::Q64_0U => llvm::type_int64(),
}
};
Self { btyp, handle }
@@ -107,7 +105,7 @@ impl BasicType {
impl ArrayType {
pub fn new(size: usize, memb: &ComplType) -> Self {
let memb = Box::new(memb.clone());
let handle = unsafe { LLVMArrayType(memb.handle(), size as _) };
let handle = unsafe { llvm::type_array(memb.handle(), size as _) };
Self { size, memb, handle }
}

@@ -127,11 +125,11 @@ impl FunctType {
let args = args.iter().map(|&arg| arg.clone()).collect();
let retn = Box::new(retn.clone());
let handle = unsafe {
LLVMFunctionType(
llvm::type_function(
retn.handle(),
arg_handles.as_mut_ptr(),
arg_handles.len() as _,
0,
Bool::False,
)
};
Self { args, retn, handle }
@@ -139,27 +137,27 @@ impl FunctType {
}

impl TypeHandle for BasicType {
fn handle(&self) -> LLVMTypeRef {
fn handle(&self) -> *mut llvm::Type {
self.handle
}
}
impl TypeHandle for ArrayType {
fn handle(&self) -> LLVMTypeRef {
fn handle(&self) -> *mut llvm::Type {
self.handle
}
}
impl TypeHandle for StrucType {
fn handle(&self) -> LLVMTypeRef {
fn handle(&self) -> *mut llvm::Type {
self.handle
}
}
impl TypeHandle for FunctType {
fn handle(&self) -> LLVMTypeRef {
fn handle(&self) -> *mut llvm::Type {
self.handle
}
}
impl TypeHandle for ComplType {
fn handle(&self) -> LLVMTypeRef {
fn handle(&self) -> *mut llvm::Type {
match self {
| Self::Basic(t) => t.handle(),
| Self::Array(t) => t.handle(),


+ 5
- 4
source/macros/lib.rs View File

@@ -172,7 +172,7 @@ pub fn serialize_config(
let item = match item {
Item::Struct(mut item) => {
item.attrs.push(syn::parse_quote! {
#[derive(serde::Deserialize, serde::Serialize)]
#[derive(serde::Deserialize, serde::Serialize, Clone, Copy)]
});
item.attrs.push(syn::parse_quote! {
#[serde(rename_all = "kebab-case", deny_unknown_fields, default)]
@@ -181,7 +181,7 @@ pub fn serialize_config(
}
Item::Enum(mut item) => {
item.attrs.push(syn::parse_quote! {
#[derive(serde::Deserialize, serde::Serialize)]
#[derive(serde::Deserialize, serde::Serialize, Clone, Copy)]
});
item.attrs.push(syn::parse_quote! {
#[serde(deny_unknown_fields)]
@@ -227,8 +227,9 @@ pub fn nat_call(
let ftyp = #funct_type;
let fdef = #i_name as _;
unsafe {
let func = LLVMAddFunction(c.modul, name, ftyp.handle());
LLVMAddGlobalMapping(c.engin, func, fdef);
let func =
llvm::module_add_function(c.modul, name, ftyp.handle());
llvm::engine_add_global_mapping(c.engin, func, fdef);
c.funcs.push(Function::new(func));
}
}


Loading…
Cancel
Save