From 5dfdc548fe9d94e0eca80441dbfb6f75acdbfd20 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ma=C3=ABlle=20MARTIN?= <maelle.martin@proton.me>
Date: Wed, 14 Aug 2024 10:10:10 +0200
Subject: [PATCH] SCRIPT: Begin to implement the new layer over LLVM + Cargo
 update

---
 src/Rust/Cargo.lock                           | 306 ++++++++----------
 src/Rust/VVLib.h                              |  14 +-
 src/Rust/vvs_cli/Cargo.toml                   |   4 +-
 src/Rust/vvs_cli/src/main.rs                  |   7 +-
 src/Rust/vvs_codegen/Cargo.toml               |   3 +-
 src/Rust/vvs_codegen/src/context.rs           |   2 +-
 src/Rust/vvs_codegen/src/lib.rs               |   6 +-
 src/Rust/vvs_codegen/src/lowerer/drops.rs     |   2 +-
 .../vvs_codegen/src/lowerer/expression.rs     |   2 +-
 src/Rust/vvs_codegen/src/value.rs             |   6 +-
 src/Rust/vvs_llvm/Cargo.toml                  |   4 +
 src/Rust/vvs_llvm/src/bindings/basic_block.rs |  99 ++++++
 src/Rust/vvs_llvm/src/bindings/builder.rs     |  44 +++
 src/Rust/vvs_llvm/src/bindings/context.rs     |  59 ++++
 src/Rust/vvs_llvm/src/bindings/function.rs    | 145 +++++++++
 src/Rust/vvs_llvm/src/bindings/mod.rs         |  56 ++++
 src/Rust/vvs_llvm/src/bindings/module.rs      |  28 ++
 src/Rust/vvs_llvm/src/bindings/types.rs       |  53 +++
 src/Rust/vvs_llvm/src/bindings/value.rs       |  34 ++
 src/Rust/vvs_llvm/src/iter.rs                 |   2 +-
 src/Rust/vvs_llvm/src/lib.rs                  |  41 ++-
 src/Rust/vvs_procmacro/src/vvrt/gen.rs        |   2 +-
 src/Rust/vvs_runtime/src/jit.rs               |   4 +-
 src/Rust/vvs_runtime_types/Cargo.toml         |   3 +-
 src/Rust/vvs_runtime_types/src/mangle.rs      |   2 +-
 src/Rust/vvs_runtime_types/src/types/mod.rs   |   2 +-
 src/Rust/vvs_runtime_types/src/vvll.rs        |   2 +-
 27 files changed, 708 insertions(+), 224 deletions(-)
 create mode 100644 src/Rust/vvs_llvm/src/bindings/basic_block.rs
 create mode 100644 src/Rust/vvs_llvm/src/bindings/builder.rs
 create mode 100644 src/Rust/vvs_llvm/src/bindings/context.rs
 create mode 100644 src/Rust/vvs_llvm/src/bindings/function.rs
 create mode 100644 src/Rust/vvs_llvm/src/bindings/mod.rs
 create mode 100644 src/Rust/vvs_llvm/src/bindings/module.rs
 create mode 100644 src/Rust/vvs_llvm/src/bindings/types.rs
 create mode 100644 src/Rust/vvs_llvm/src/bindings/value.rs

diff --git a/src/Rust/Cargo.lock b/src/Rust/Cargo.lock
index 724c516d..e4d015d1 100644
--- a/src/Rust/Cargo.lock
+++ b/src/Rust/Cargo.lock
@@ -51,6 +51,21 @@ version = "0.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299"
 
+[[package]]
+name = "anstream"
+version = "0.6.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526"
+dependencies = [
+ "anstyle",
+ "anstyle-parse",
+ "anstyle-query",
+ "anstyle-wincon",
+ "colorchoice",
+ "is_terminal_polyfill",
+ "utf8parse",
+]
+
 [[package]]
 name = "anstyle"
 version = "1.0.8"
@@ -58,33 +73,44 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1"
 
 [[package]]
-name = "anyhow"
-version = "1.0.86"
+name = "anstyle-parse"
+version = "0.2.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
+checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb"
+dependencies = [
+ "utf8parse",
+]
 
 [[package]]
-name = "atty"
-version = "0.2.14"
+name = "anstyle-query"
+version = "1.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
+checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a"
 dependencies = [
- "hermit-abi 0.1.19",
- "libc",
- "winapi",
+ "windows-sys 0.52.0",
 ]
 
 [[package]]
-name = "autocfg"
-version = "1.3.0"
+name = "anstyle-wincon"
+version = "3.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
+checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8"
+dependencies = [
+ "anstyle",
+ "windows-sys 0.52.0",
+]
 
 [[package]]
-name = "bitflags"
-version = "1.3.2"
+name = "anyhow"
+version = "1.0.86"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da"
+
+[[package]]
+name = "autocfg"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
 
 [[package]]
 name = "bitflags"
@@ -122,28 +148,28 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
 
 [[package]]
 name = "cbindgen"
-version = "0.26.0"
+version = "0.27.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "da6bc11b07529f16944307272d5bd9b22530bc7d05751717c9d416586cedab49"
+checksum = "3fce8dd7fcfcbf3a0a87d8f515194b49d6135acab73e18bd380d1d93bb1a15eb"
 dependencies = [
- "clap 3.2.25",
+ "clap",
  "heck 0.4.1",
- "indexmap 1.9.3",
+ "indexmap",
  "log",
  "proc-macro2",
  "quote",
  "serde",
  "serde_json",
- "syn 1.0.109",
+ "syn 2.0.74",
  "tempfile",
- "toml 0.5.11",
+ "toml",
 ]
 
 [[package]]
 name = "cc"
-version = "1.1.8"
+version = "1.1.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "504bdec147f2cc13c8b57ed9401fd8a147cc66b67ad5cb241394244f2c947549"
+checksum = "e9e8aabfac534be767c909e0690571677d49f41bd8465ae876fe043d52ba5292"
 
 [[package]]
 name = "cfg-if"
@@ -180,24 +206,9 @@ dependencies = [
 
 [[package]]
 name = "clap"
-version = "3.2.25"
+version = "4.5.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123"
-dependencies = [
- "atty",
- "bitflags 1.3.2",
- "clap_lex 0.2.4",
- "indexmap 1.9.3",
- "strsim 0.10.0",
- "termcolor",
- "textwrap",
-]
-
-[[package]]
-name = "clap"
-version = "4.5.13"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0fbb260a053428790f3de475e304ff84cdbc4face759ea7a3e64c1edd938a7fc"
+checksum = "11d8838454fda655dafd3accb2b6e2bea645b9e4078abe84a22ceb947235c5cc"
 dependencies = [
  "clap_builder",
  "clap_derive",
@@ -205,23 +216,24 @@ dependencies = [
 
 [[package]]
 name = "clap_builder"
-version = "4.5.13"
+version = "4.5.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "64b17d7ea74e9f833c7dbf2cbe4fb12ff26783eda4782a8975b72f895c9b4d99"
+checksum = "216aec2b177652e3846684cbfe25c9964d18ec45234f0f5da5157b207ed1aab6"
 dependencies = [
+ "anstream",
  "anstyle",
- "clap_lex 0.7.2",
- "strsim 0.11.1",
+ "clap_lex",
+ "strsim",
  "terminal_size",
 ]
 
 [[package]]
 name = "clap_complete"
-version = "4.5.12"
+version = "4.5.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a8670053e87c316345e384ca1f3eba3006fc6355ed8b8a1140d104e109e3df34"
+checksum = "9c677cd0126f3026d8b093fa29eae5d812fde5c05bc66dbb29d0374eea95113a"
 dependencies = [
- "clap 4.5.13",
+ "clap",
 ]
 
 [[package]]
@@ -233,16 +245,7 @@ dependencies = [
  "heck 0.5.0",
  "proc-macro2",
  "quote",
- "syn 2.0.72",
-]
-
-[[package]]
-name = "clap_lex"
-version = "0.2.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5"
-dependencies = [
- "os_str_bytes",
+ "syn 2.0.74",
 ]
 
 [[package]]
@@ -257,7 +260,7 @@ version = "0.2.23"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f17415fd4dfbea46e3274fcd8d368284519b358654772afb700dc2e8d2b24eeb"
 dependencies = [
- "clap 4.5.13",
+ "clap",
  "roff",
 ]
 
@@ -280,6 +283,12 @@ dependencies = [
  "unicode-width",
 ]
 
+[[package]]
+name = "colorchoice"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0"
+
 [[package]]
 name = "console"
 version = "0.15.8"
@@ -310,7 +319,7 @@ dependencies = [
  "anes",
  "cast",
  "ciborium",
- "clap 4.5.13",
+ "clap",
  "criterion-plot",
  "is-terminal",
  "itertools",
@@ -386,7 +395,7 @@ dependencies = [
  "convert_case",
  "proc-macro2",
  "quote",
- "syn 2.0.72",
+ "syn 2.0.74",
  "unicode-xid",
 ]
 
@@ -447,12 +456,6 @@ dependencies = [
  "crunchy",
 ]
 
-[[package]]
-name = "hashbrown"
-version = "0.12.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
-
 [[package]]
 name = "hashbrown"
 version = "0.14.5"
@@ -475,15 +478,6 @@ version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
 
-[[package]]
-name = "hermit-abi"
-version = "0.1.19"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
-dependencies = [
- "libc",
-]
-
 [[package]]
 name = "hermit-abi"
 version = "0.3.9"
@@ -492,22 +486,12 @@ checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
 
 [[package]]
 name = "indexmap"
-version = "1.9.3"
+version = "2.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
-dependencies = [
- "autocfg",
- "hashbrown 0.12.3",
-]
-
-[[package]]
-name = "indexmap"
-version = "2.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "de3fc2e30ba82dd1b3911c8de1ffc143c74a914a14e99514d7637e3099df5ea0"
+checksum = "93ead53efc7ea8ed3cfb0c79fc8023fbb782a5432b52830b6518941cebe6505c"
 dependencies = [
  "equivalent",
- "hashbrown 0.14.5",
+ "hashbrown",
 ]
 
 [[package]]
@@ -531,11 +515,17 @@ version = "0.4.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b"
 dependencies = [
- "hermit-abi 0.3.9",
+ "hermit-abi",
  "libc",
  "windows-sys 0.52.0",
 ]
 
+[[package]]
+name = "is_terminal_polyfill"
+version = "1.70.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
+
 [[package]]
 name = "itertools"
 version = "0.10.5"
@@ -553,9 +543,9 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
 
 [[package]]
 name = "js-sys"
-version = "0.3.69"
+version = "0.3.70"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d"
+checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a"
 dependencies = [
  "wasm-bindgen",
 ]
@@ -631,12 +621,6 @@ version = "11.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9"
 
-[[package]]
-name = "os_str_bytes"
-version = "6.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1"
-
 [[package]]
 name = "owned_ttf_parser"
 version = "0.24.0"
@@ -765,7 +749,7 @@ version = "0.38.34"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f"
 dependencies = [
- "bitflags 2.6.0",
+ "bitflags",
  "errno",
  "libc",
  "linux-raw-sys",
@@ -795,31 +779,31 @@ checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b"
 
 [[package]]
 name = "serde"
-version = "1.0.205"
+version = "1.0.207"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e33aedb1a7135da52b7c21791455563facbbcc43d0f0f66165b42c21b3dfb150"
+checksum = "5665e14a49a4ea1b91029ba7d3bca9f299e1f7cfa194388ccc20f14743e784f2"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.205"
+version = "1.0.207"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "692d6f5ac90220161d6774db30c662202721e64aed9058d2c394f451261420c1"
+checksum = "6aea2634c86b0e8ef2cfdc0c340baede54ec27b1e46febd7f80dffb2aa44a00e"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.72",
+ "syn 2.0.74",
 ]
 
 [[package]]
 name = "serde_json"
-version = "1.0.122"
+version = "1.0.124"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "784b6203951c57ff748476b126ccb5e8e2959a5c19e5c617ab1956be3dbc68da"
+checksum = "66ad62847a56b3dba58cc891acd13884b9c61138d330c0d7b6181713d4fce38d"
 dependencies = [
- "indexmap 2.3.0",
+ "indexmap",
  "itoa",
  "memchr",
  "ryu",
@@ -850,12 +834,6 @@ dependencies = [
  "serde",
 ]
 
-[[package]]
-name = "strsim"
-version = "0.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
-
 [[package]]
 name = "strsim"
 version = "0.11.1"
@@ -875,9 +853,9 @@ dependencies = [
 
 [[package]]
 name = "syn"
-version = "2.0.72"
+version = "2.0.74"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af"
+checksum = "1fceb41e3d546d0bd83421d3409b1460cc7444cd389341a4c880fe7a042cb3d7"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -916,12 +894,6 @@ dependencies = [
  "windows-sys 0.48.0",
 ]
 
-[[package]]
-name = "textwrap"
-version = "0.16.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9"
-
 [[package]]
 name = "thiserror"
 version = "1.0.63"
@@ -939,7 +911,7 @@ checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.72",
+ "syn 2.0.74",
 ]
 
 [[package]]
@@ -952,15 +924,6 @@ dependencies = [
  "serde_json",
 ]
 
-[[package]]
-name = "toml"
-version = "0.5.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234"
-dependencies = [
- "serde",
-]
-
 [[package]]
 name = "toml"
 version = "0.8.19"
@@ -988,7 +951,7 @@ version = "0.22.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d"
 dependencies = [
- "indexmap 2.3.0",
+ "indexmap",
  "serde",
  "serde_spanned",
  "toml_datetime",
@@ -1025,6 +988,12 @@ version = "0.2.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
 
+[[package]]
+name = "utf8parse"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
+
 [[package]]
 name = "version_check"
 version = "0.9.5"
@@ -1050,15 +1019,14 @@ name = "vvs_cli"
 version = "0.5.0"
 dependencies = [
  "anyhow",
- "clap 4.5.13",
+ "clap",
  "clap_complete",
  "clap_mangen",
  "log",
  "serde",
  "thiserror",
- "toml 0.8.19",
+ "toml",
  "vvs_ass",
- "vvs_codegen",
  "vvs_font",
  "vvs_llvm",
  "vvs_parser",
@@ -1071,7 +1039,7 @@ name = "vvs_codegen"
 version = "0.5.0"
 dependencies = [
  "anyhow",
- "hashbrown 0.14.5",
+ "hashbrown",
  "log",
  "serde",
  "serde_json",
@@ -1097,13 +1065,13 @@ version = "0.5.0"
 dependencies = [
  "anyhow",
  "derive_more",
- "hashbrown 0.14.5",
+ "hashbrown",
  "log",
  "paste",
  "regex",
  "serde",
  "thiserror",
- "toml 0.8.19",
+ "toml",
  "vvs_parser",
  "vvs_utils",
 ]
@@ -1113,7 +1081,7 @@ name = "vvs_lib"
 version = "0.5.0"
 dependencies = [
  "cbindgen",
- "hashbrown 0.14.5",
+ "hashbrown",
  "log",
  "serde",
  "serde_json",
@@ -1127,6 +1095,7 @@ dependencies = [
  "anyhow",
  "llvm-sys",
  "log",
+ "paste",
 ]
 
 [[package]]
@@ -1140,7 +1109,7 @@ dependencies = [
  "codespan-reporting",
  "criterion",
  "derive_more",
- "hashbrown 0.14.5",
+ "hashbrown",
  "insta",
  "log",
  "paste",
@@ -1154,7 +1123,7 @@ dependencies = [
 name = "vvs_parser_derive"
 version = "0.5.0"
 dependencies = [
- "indexmap 2.3.0",
+ "indexmap",
  "proc-macro2",
  "quote",
  "syn 1.0.109",
@@ -1167,7 +1136,7 @@ dependencies = [
  "anyhow",
  "proc-macro2",
  "quote",
- "syn 2.0.72",
+ "syn 2.0.74",
 ]
 
 [[package]]
@@ -1188,7 +1157,7 @@ name = "vvs_runtime_types"
 version = "0.5.0"
 dependencies = [
  "anyhow",
- "hashbrown 0.14.5",
+ "hashbrown",
  "log",
  "serde",
  "serde_json",
@@ -1222,34 +1191,35 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen"
-version = "0.2.92"
+version = "0.2.93"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8"
+checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5"
 dependencies = [
  "cfg-if",
+ "once_cell",
  "wasm-bindgen-macro",
 ]
 
 [[package]]
 name = "wasm-bindgen-backend"
-version = "0.2.92"
+version = "0.2.93"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da"
+checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b"
 dependencies = [
  "bumpalo",
  "log",
  "once_cell",
  "proc-macro2",
  "quote",
- "syn 2.0.72",
+ "syn 2.0.74",
  "wasm-bindgen-shared",
 ]
 
 [[package]]
 name = "wasm-bindgen-macro"
-version = "0.2.92"
+version = "0.2.93"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726"
+checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf"
 dependencies = [
  "quote",
  "wasm-bindgen-macro-support",
@@ -1257,49 +1227,33 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen-macro-support"
-version = "0.2.92"
+version = "0.2.93"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
+checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.72",
+ "syn 2.0.74",
  "wasm-bindgen-backend",
  "wasm-bindgen-shared",
 ]
 
 [[package]]
 name = "wasm-bindgen-shared"
-version = "0.2.92"
+version = "0.2.93"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
+checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484"
 
 [[package]]
 name = "web-sys"
-version = "0.3.69"
+version = "0.3.70"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef"
+checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0"
 dependencies = [
  "js-sys",
  "wasm-bindgen",
 ]
 
-[[package]]
-name = "winapi"
-version = "0.3.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
-dependencies = [
- "winapi-i686-pc-windows-gnu",
- "winapi-x86_64-pc-windows-gnu",
-]
-
-[[package]]
-name = "winapi-i686-pc-windows-gnu"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
-
 [[package]]
 name = "winapi-util"
 version = "0.1.9"
@@ -1309,12 +1263,6 @@ dependencies = [
  "windows-sys 0.59.0",
 ]
 
-[[package]]
-name = "winapi-x86_64-pc-windows-gnu"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
-
 [[package]]
 name = "windows-sys"
 version = "0.48.0"
@@ -1489,5 +1437,5 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.72",
+ "syn 2.0.74",
 ]
diff --git a/src/Rust/VVLib.h b/src/Rust/VVLib.h
index 7dcc900c..29866723 100644
--- a/src/Rust/VVLib.h
+++ b/src/Rust/VVLib.h
@@ -2,14 +2,14 @@
 
 #pragma once
 
-/* Generated with cbindgen:0.26.0 */
+/* Generated with cbindgen:0.27.0 */
 
 #include <inttypes.h>
 
 #ifdef __cplusplus
 namespace VVLib {
 namespace C {
-#endif // __cplusplus
+#endif  // __cplusplus
 
 /**
  * Wraps the container that holds all the content of the ASS file / Vivy file.
@@ -178,10 +178,10 @@ void ASSContainerDrop(struct ASSContainer *this_);
 struct StringSlice ASSStyleGetName(const struct ASSStyle *this_);
 
 #ifdef __cplusplus
-} // extern "C"
-#endif // __cplusplus
+}  // extern "C"
+#endif  // __cplusplus
 
 #ifdef __cplusplus
-} // namespace C
-} // namespace VVLib
-#endif // __cplusplus
+}  // namespace C
+}  // namespace VVLib
+#endif  // __cplusplus
diff --git a/src/Rust/vvs_cli/Cargo.toml b/src/Rust/vvs_cli/Cargo.toml
index 2f958d4b..36de30fc 100644
--- a/src/Rust/vvs_cli/Cargo.toml
+++ b/src/Rust/vvs_cli/Cargo.toml
@@ -16,7 +16,7 @@ vvs_font.workspace    = true
 vvs_utils.workspace   = true
 vvs_parser.workspace  = true
 vvs_runtime.workspace = true
-vvs_codegen.workspace = true
+# vvs_codegen.workspace = true
 
 thiserror.workspace = true
 anyhow.workspace    = true
@@ -30,4 +30,4 @@ clap.workspace          = true
 
 [build-dependencies]
 anyhow.workspace   = true
-vvs_llvm.workspace = true
+vvs_llvm = { workspace = true, features = ["link"] }
diff --git a/src/Rust/vvs_cli/src/main.rs b/src/Rust/vvs_cli/src/main.rs
index 345a2bbe..8c6cbf0b 100644
--- a/src/Rust/vvs_cli/src/main.rs
+++ b/src/Rust/vvs_cli/src/main.rs
@@ -10,7 +10,6 @@ use vvs_cli::{
     config::{Config, ConfigFile},
     logger,
 };
-use vvs_codegen::LowererBuilder;
 use vvs_parser::prelude::*;
 use vvs_runtime::{types::VVRTTable, JIT};
 use vvs_utils::xdg::*;
@@ -122,9 +121,9 @@ fn main() -> Result<()> {
             )
             .context("failed to parse the subtitle file")?;
 
-            let jit = JIT::new()?;
-            let module = unsafe { LowererBuilder::new(script.name(), jit.ctx()) }.build().lower();
-            unsafe { jit.add_module(module)? };
+            // let jit = JIT::new()?;
+            // let module = unsafe { LowererBuilder::new(script.name(), jit.ctx()) }.build().lower();
+            // unsafe { jit.add_module(module)? };
 
             log::error!("use the ASS container and insert it into the JIT: {ass:#?}");
 
diff --git a/src/Rust/vvs_codegen/Cargo.toml b/src/Rust/vvs_codegen/Cargo.toml
index 39d9009a..8e67079a 100644
--- a/src/Rust/vvs_codegen/Cargo.toml
+++ b/src/Rust/vvs_codegen/Cargo.toml
@@ -15,9 +15,10 @@ hashbrown.workspace  = true
 
 vvs_runtime_types.workspace = true
 vvs_utils.workspace         = true
-vvs_llvm.workspace          = true
 vvs_lang.workspace          = true
 
+vvs_llvm = { workspace = true, features = ["bindings"] }
+
 [build-dependencies]
 vvs_llvm = { workspace = true, features = ["link"] }
 anyhow.workspace = true
diff --git a/src/Rust/vvs_codegen/src/context.rs b/src/Rust/vvs_codegen/src/context.rs
index 6088a633..9ba934ef 100644
--- a/src/Rust/vvs_codegen/src/context.rs
+++ b/src/Rust/vvs_codegen/src/context.rs
@@ -1,6 +1,6 @@
 use crate::Value;
 use hashbrown::HashMap;
-use vvs_llvm::*;
+use vvs_llvm::sys::*;
 use vvs_runtime_types::vvll::LLVMTypeIsManaged;
 
 /// Just a hashmap used to store values in scope.
diff --git a/src/Rust/vvs_codegen/src/lib.rs b/src/Rust/vvs_codegen/src/lib.rs
index 8f74fd9d..6da3d4ee 100644
--- a/src/Rust/vvs_codegen/src/lib.rs
+++ b/src/Rust/vvs_codegen/src/lib.rs
@@ -2,16 +2,16 @@
 
 mod context;
 mod graph;
-mod lowerer;
+// mod lowerer;
 mod value;
 
 // Exports in this crate.
 use crate::{context::*, graph::*, value::*};
 
 // Re-exports.
-pub use lowerer::{Lowerer, LowererBuilder};
+// pub use lowerer::{Lowerer, LowererBuilder};
 
-type LLVMLowerContext = (vvs_llvm::LLVMModuleRef, vvs_llvm::LLVMContextRef, vvs_llvm::LLVMBuilderRef);
+type LLVMLowerContext = (vvs_llvm::sys::LLVMModuleRef, vvs_llvm::sys::LLVMContextRef, vvs_llvm::sys::LLVMBuilderRef);
 
 /// The number of temp / unnamed values.
 static mut TEMP_NAME_COUNTER: u64 = 0;
diff --git a/src/Rust/vvs_codegen/src/lowerer/drops.rs b/src/Rust/vvs_codegen/src/lowerer/drops.rs
index 3c56022c..9b556da8 100644
--- a/src/Rust/vvs_codegen/src/lowerer/drops.rs
+++ b/src/Rust/vvs_codegen/src/lowerer/drops.rs
@@ -1,6 +1,6 @@
 use crate::{value::Value, Graph, ValueContext};
 use std::collections::BTreeSet;
-use vvs_llvm::*;
+use vvs_llvm::sys::*;
 
 /// Drop all the values in the correct order at the end of a given basic block. We take into
 /// account any terminator of said basic block.
diff --git a/src/Rust/vvs_codegen/src/lowerer/expression.rs b/src/Rust/vvs_codegen/src/lowerer/expression.rs
index 6caad5f2..d3a82d2e 100644
--- a/src/Rust/vvs_codegen/src/lowerer/expression.rs
+++ b/src/Rust/vvs_codegen/src/lowerer/expression.rs
@@ -1,6 +1,6 @@
 use crate::{lowerer::*, Value, ValueContext};
 use vvs_lang::ast::*;
-use vvs_llvm::{LLVMIntPredicate::*, LLVMRealPredicate::*, *};
+use vvs_llvm::sys::{LLVMIntPredicate::*, LLVMRealPredicate::*, *};
 use vvs_runtime_types::{
     types::{VVRTString, VVRTTable},
     vvll::LLVMExported,
diff --git a/src/Rust/vvs_codegen/src/value.rs b/src/Rust/vvs_codegen/src/value.rs
index d7302af0..8ad8ed92 100644
--- a/src/Rust/vvs_codegen/src/value.rs
+++ b/src/Rust/vvs_codegen/src/value.rs
@@ -1,6 +1,6 @@
-use crate::{cstr, lowerer};
+use crate::{cstr /*lowerer*/};
 use vvs_lang::ast::{ASTConst, ASTType, Typed};
-use vvs_llvm::*;
+use vvs_llvm::sys::*;
 
 #[derive(Debug, Default, Clone, PartialEq, Eq)]
 pub(crate) enum Value {
@@ -48,7 +48,7 @@ impl Value {
 
     pub fn loaded(&self, c: LLVMContextRef, b: LLVMBuilderRef) -> LLVMValueRef {
         match self {
-            Value::Nil => lowerer::ConstantLowerer::new(c, &ASTConst::Nil).lower().loaded(c, b),
+            Value::Nil => todo!(), // lowerer::ConstantLowerer::new(c, &ASTConst::Nil).lower().loaded(c, b),
             Value::Const(_, val) => *val,
             Value::Alloca(_, ty, ptr) => unsafe { LLVMBuildLoad2(b, *ty, *ptr, cstr!()) },
             Value::Function(_, _, func_ptr) => *func_ptr,
diff --git a/src/Rust/vvs_llvm/Cargo.toml b/src/Rust/vvs_llvm/Cargo.toml
index 98bd38c9..41ce7c7a 100644
--- a/src/Rust/vvs_llvm/Cargo.toml
+++ b/src/Rust/vvs_llvm/Cargo.toml
@@ -8,6 +8,7 @@ license.workspace = true
 
 [dependencies]
 anyhow.workspace = true
+paste.workspace  = true
 log.workspace    = true
 llvm-sys = { version = "181", features = [
     "strict-versioning",       # Be strict about versions, we do want the lattest thing
@@ -16,4 +17,7 @@ llvm-sys = { version = "181", features = [
 ] }
 
 [features]
+sys = []
 link = []
+init = []
+bindings = ["init"]
diff --git a/src/Rust/vvs_llvm/src/bindings/basic_block.rs b/src/Rust/vvs_llvm/src/bindings/basic_block.rs
new file mode 100644
index 00000000..16883051
--- /dev/null
+++ b/src/Rust/vvs_llvm/src/bindings/basic_block.rs
@@ -0,0 +1,99 @@
+use crate::prelude::*;
+use llvm_sys::{core::*, prelude::*};
+
+crate::bindings::declare! { mut LLVMBasicBlockRef as BB<'a> }
+
+impl<'a> BB<'a> {
+    /// Get the insturction count of this basic block.
+    pub fn len(&self) -> usize {
+        let len = unsafe { LLVMGetLastInstruction(self.as_ptr()).offset_from(LLVMGetFirstInstruction(self.as_ptr())) };
+        assert!(len >= 0, "something went really wrong");
+        len as usize
+    }
+
+    /// Tells wether there are any instructions in this basic block.
+    pub fn is_empty(&self) -> bool {
+        self.len() == 0
+    }
+
+    /// Iterate over the instructions of a basic block.
+    pub fn iter(&'a self) -> BBIter<'a, &'a BB<'a>> {
+        match self.is_empty() {
+            true => BBIter { curr: None, last: None, bb: self },
+            false => todo!(),
+        }
+    }
+
+    /// Iterate over the instructions of a basic block in a mutable way.
+    pub fn iter_mut(&'a mut self) -> BBIter<'a, &'a mut BB<'a>> {
+        match self.is_empty() {
+            true => BBIter { curr: None, last: None, bb: self },
+            false => todo!(),
+        }
+    }
+}
+
+impl Eq for BB<'_> {}
+impl PartialEq for BB<'_> {
+    fn eq(&self, other: &Self) -> bool {
+        self.inner == other.inner
+    }
+}
+
+mod sealed {
+    pub trait BBRef<'a>: AsRef<super::BB<'a>> {}
+}
+
+impl<'a> sealed::BBRef<'a> for &'a BB<'a> {}
+impl<'a> sealed::BBRef<'a> for &'a mut BB<'a> {}
+
+impl<'a> AsRef<BB<'a>> for &'a BB<'a> {
+    fn as_ref(&self) -> &BB<'a> {
+        self
+    }
+}
+
+impl<'a> AsRef<BB<'a>> for &'a mut BB<'a> {
+    fn as_ref(&self) -> &BB<'a> {
+        self
+    }
+}
+
+/// Iterate over the instructions in a basic block.
+pub struct BBIter<'a, B: sealed::BBRef<'a>> {
+    curr: Option<Value<'a>>,
+    last: Option<Value<'a>>,
+    bb: B,
+}
+
+impl<'a, B: sealed::BBRef<'a>> Iterator for BBIter<'a, B> {
+    type Item = Value<'a>;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        match (self.curr.take(), self.last.as_ref()) {
+            (Some(_), None) | (None, Some(_)) => unreachable!(),
+            (None, None) => None,
+            (Some(curr), Some(last)) if curr == *last => {
+                self.last = None;
+                Some(curr)
+            }
+            (Some(curr), Some(_)) => unsafe {
+                self.curr = Some(Value::from_ptr(LLVMGetNextInstruction(curr.as_ptr())));
+                Some(curr)
+            },
+        }
+    }
+
+    fn last(self) -> Option<Self::Item> {
+        self.last
+    }
+
+    fn count(self) -> usize {
+        self.bb.as_ref().len()
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        let size = self.bb.as_ref().len();
+        (size, Some(size))
+    }
+}
diff --git a/src/Rust/vvs_llvm/src/bindings/builder.rs b/src/Rust/vvs_llvm/src/bindings/builder.rs
new file mode 100644
index 00000000..2b9b23c8
--- /dev/null
+++ b/src/Rust/vvs_llvm/src/bindings/builder.rs
@@ -0,0 +1,44 @@
+use crate::prelude::*;
+use llvm_sys::{core::*, prelude::*};
+
+crate::bindings::declare! { mut LLVMBuilderRef as Builder<'a> }
+
+macro_rules! build {
+    ($name:ident ($b:ident $(, $arg:ident : $ty:ty)*$(,)?) $doc:literal $expr:expr) => {
+        paste::paste! {
+            #[doc = concat!($doc,
+                "\nUsage: `b.build_", stringify!($name), "(" $(, concat!(stringify!($arg), ","))*, ")`"
+            )]
+            pub fn [< build_$name >](&mut self $(, $arg: $ty)*) -> Value {
+                let $b = self.as_ptr();
+                unsafe { Value::from_ptr($expr) }
+            }
+        }
+    };
+}
+
+impl<'a> Builder<'a> {
+    /// Position the builder at the end of a basic block.
+    pub fn position_at_end(&mut self, bb: &BB) -> &mut Self {
+        unsafe { LLVMPositionBuilderAtEnd(self.as_ptr(), bb.as_ptr()) };
+        self
+    }
+
+    /// Position the builder before a value
+    pub fn position_before(&mut self, value: &Value) -> &mut Self {
+        unsafe { LLVMPositionBuilderBefore(self.as_ptr(), value.as_ptr()) };
+        self
+    }
+
+    build! { cond_jump(b, cond: Value, then_bb: &BB, else_bb: &BB) "Build a conditional jump to another basic block" {
+        LLVMBuildCondBr(b, cond.as_ptr(), then_bb.as_ptr(), else_bb.as_ptr())
+    }}
+    build! { jump(b, bb: &BB) "Build a jump to another basic block" LLVMBuildBr(b, bb.as_ptr()) }
+    build! { ret_void(b)      "Build a `return void` instruction"   LLVMBuildRetVoid(b) }
+}
+
+impl Drop for Builder<'_> {
+    fn drop(&mut self) {
+        unsafe { LLVMDisposeBuilder(self.inner) }
+    }
+}
diff --git a/src/Rust/vvs_llvm/src/bindings/context.rs b/src/Rust/vvs_llvm/src/bindings/context.rs
new file mode 100644
index 00000000..c0d2f472
--- /dev/null
+++ b/src/Rust/vvs_llvm/src/bindings/context.rs
@@ -0,0 +1,59 @@
+use crate::prelude::*;
+use llvm_sys::{core::*, prelude::*};
+use std::{
+    ffi::{CString, NulError},
+    marker,
+};
+
+crate::bindings::declare! { mut LLVMContextRef as Context<'a> }
+
+macro_rules! get_type {
+    ($llvm:ident as $name:ident) => {
+        paste::paste! {
+            #[doc = "Get the type for " $llvm "."]
+            pub fn [< type_ $name >](&self) -> Type {
+                unsafe { Type::from_ptr([< LLVM $llvm TypeInContext >](self.inner)) }
+            }
+        }
+    };
+}
+
+impl Default for Context<'_> {
+    fn default() -> Self {
+        Self::new()
+    }
+}
+
+impl Context<'_> {
+    /// Create a new context from scratch. This will automatically initialize LLVM if needed.
+    pub fn new() -> Self {
+        if let Err(err) = crate::init::initialize_llvm() {
+            // Should fail only on re-init. If a real problem occured, we would have already
+            // aborted the program.
+            log::debug!("{err}");
+        }
+        Self { inner: unsafe { LLVMContextCreate() }, marker: marker::PhantomData }
+    }
+
+    /// Create a new builder for this context.
+    pub fn create_builder(&self) -> Builder {
+        unsafe { Builder::from_ptr(LLVMCreateBuilderInContext(self.inner)) }
+    }
+
+    /// Create a new module in this context.
+    pub fn create_module(&self, name: impl AsRef<str>) -> Result<Module, NulError> {
+        let name = CString::new(name.as_ref())?;
+        Ok(unsafe { Module::from_ptr(LLVMModuleCreateWithName(name.as_ptr())) })
+    }
+
+    get_type! {  Int8 as   i8 }
+    get_type! { Int32 as  i32 }
+    get_type! { Float as  f32 }
+    get_type! {  Void as void }
+}
+
+impl Drop for Context<'_> {
+    fn drop(&mut self) {
+        unsafe { LLVMContextDispose(self.inner) }
+    }
+}
diff --git a/src/Rust/vvs_llvm/src/bindings/function.rs b/src/Rust/vvs_llvm/src/bindings/function.rs
new file mode 100644
index 00000000..07c8be65
--- /dev/null
+++ b/src/Rust/vvs_llvm/src/bindings/function.rs
@@ -0,0 +1,145 @@
+use crate::prelude::*;
+use llvm_sys::{core::*, prelude::*, LLVMLinkage, LLVMVisibility};
+
+crate::bindings::declare! { mut LLVMValueRef as FunctionDeclaration<'a> }
+crate::bindings::declare! { mut LLVMValueRef as Function<'a> {
+    entry_point: BB<'a>,
+} }
+
+impl<'a> FunctionDeclaration<'a> {
+    /// Set the [LLVMLinkage] and [LLVMVisibility] accordingly.
+    pub fn into_public(self, public: bool) -> Self {
+        match public {
+            true => unsafe {
+                LLVMSetLinkage(self.as_ptr(), LLVMLinkage::LLVMCommonLinkage);
+                LLVMSetVisibility(self.as_ptr(), LLVMVisibility::LLVMProtectedVisibility);
+            },
+            false => unsafe {
+                LLVMSetLinkage(self.as_ptr(), LLVMLinkage::LLVMLinkerPrivateLinkage);
+                LLVMSetVisibility(self.as_ptr(), LLVMVisibility::LLVMHiddenVisibility);
+            },
+        }
+        self
+    }
+
+    /// Get the type of this function declaration.
+    pub fn ty(&self) -> FunctionType {
+        unsafe { FunctionType::from_ptr(LLVMTypeOf(self.as_ptr())) }
+    }
+
+    /// Transform the function declaration into a proper function, with a function body, or at
+    /// lease an entry point.
+    pub fn into_function(self) -> Function<'a> {
+        unsafe {
+            let entry_point = BB::from_ptr(LLVMAppendBasicBlockInContext(
+                LLVMGetTypeContext(self.ty().as_ptr()),
+                self.as_ptr(),
+                crate::bindings::cstr(b"entrypoint\0").as_ptr(),
+            ));
+            Function::from_ptr(self.as_ptr(), entry_point)
+        }
+    }
+}
+
+impl<'a> Function<'a> {
+    /// Get the type of this function.
+    pub fn ty(&self) -> FunctionType {
+        unsafe { FunctionType::from_ptr(LLVMTypeOf(self.as_ptr())) }
+    }
+
+    /// Get the entry point of the function.
+    pub fn entry_point(&self) -> &BB {
+        &self.entry_point
+    }
+
+    /// Get the entry point of the function in a mutable way.
+    pub fn entry_point_mut(&'a mut self) -> &'a mut BB {
+        &mut self.entry_point
+    }
+
+    /// Iterate over all the basic blocks of the function.
+    pub fn iter(&'a self) -> FunctionIter<'a, &'a Function> {
+        unsafe {
+            match LLVMCountBasicBlocks(self.as_ptr()) {
+                0 => FunctionIter { curr: None, last: None, func: self },
+                _ => FunctionIter {
+                    curr: Some(BB::from_ptr(LLVMGetFirstBasicBlock(self.inner))),
+                    last: Some(BB::from_ptr(LLVMGetLastBasicBlock(self.inner))),
+                    func: self,
+                },
+            }
+        }
+    }
+
+    /// Iterate over all the basic blocks of the function in a mutable way.
+    pub fn iter_mut(&'a mut self) -> FunctionIter<'a, &'a mut Function> {
+        unsafe {
+            match LLVMCountBasicBlocks(self.as_ptr()) {
+                0 => FunctionIter { curr: None, last: None, func: self },
+                _ => FunctionIter {
+                    curr: Some(BB::from_ptr(LLVMGetFirstBasicBlock(self.inner))),
+                    last: Some(BB::from_ptr(LLVMGetLastBasicBlock(self.inner))),
+                    func: self,
+                },
+            }
+        }
+    }
+}
+
+mod sealed {
+    pub trait FuncRef<'a>: AsRef<super::Function<'a>> {}
+}
+
+impl<'a> sealed::FuncRef<'a> for &'a Function<'a> {}
+impl<'a> sealed::FuncRef<'a> for &'a mut Function<'a> {}
+
+impl<'a> AsRef<Function<'a>> for &'a Function<'a> {
+    fn as_ref(&self) -> &Function<'a> {
+        self
+    }
+}
+
+impl<'a> AsRef<Function<'a>> for &'a mut Function<'a> {
+    fn as_ref(&self) -> &Function<'a> {
+        self
+    }
+}
+
+/// Iterate over the basic blocks in a function.
+pub struct FunctionIter<'a, F: sealed::FuncRef<'a>> {
+    curr: Option<BB<'a>>,
+    last: Option<BB<'a>>,
+    func: F,
+}
+
+impl<'a, F: sealed::FuncRef<'a>> Iterator for FunctionIter<'a, F> {
+    type Item = BB<'a>;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        match (self.curr.take(), self.last.as_ref()) {
+            (Some(_), None) | (None, Some(_)) => unreachable!(),
+            (None, None) => None,
+            (Some(curr), Some(last)) if curr == *last => {
+                self.last = None;
+                Some(curr)
+            }
+            (Some(curr), Some(_)) => unsafe {
+                self.curr = Some(BB::from_ptr(LLVMGetNextBasicBlock(curr.as_ptr())));
+                Some(curr)
+            },
+        }
+    }
+
+    fn last(self) -> Option<Self::Item> {
+        self.last
+    }
+
+    fn count(self) -> usize {
+        (unsafe { LLVMCountBasicBlocks(self.func.as_ref().as_ptr()) }) as usize
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        let count = (unsafe { LLVMCountBasicBlocks(self.func.as_ref().as_ptr()) }) as usize;
+        (count, Some(count))
+    }
+}
diff --git a/src/Rust/vvs_llvm/src/bindings/mod.rs b/src/Rust/vvs_llvm/src/bindings/mod.rs
new file mode 100644
index 00000000..3fed3a15
--- /dev/null
+++ b/src/Rust/vvs_llvm/src/bindings/mod.rs
@@ -0,0 +1,56 @@
+#![forbid(missing_docs)]
+
+//! Bindings for the C-API of LLVM. Documentation can be found here: https://llvm.org/doxygen/group__LLVMCCore.html
+
+pub mod basic_block;
+pub mod builder;
+pub mod context;
+pub mod function;
+pub mod module;
+pub mod types;
+pub mod value;
+
+macro_rules! declare {
+    ($owned: tt $llvm:ident as $name:ident <$lifetime:lifetime> $({
+        $($field:ident: $ty:ty,)*
+    })?) => {
+        #[doc = concat!("A ", stringify!($name), ", to safely use functions for ", stringify!($llvm))]
+        pub struct $name<$lifetime> {
+            inner: $llvm,
+            marker: $crate::bindings::declare!(@marker $owned $llvm $lifetime),
+            $($($field: $ty)*)?
+        }
+
+        #[allow(dead_code)]
+        impl<$lifetime> $name<$lifetime> {
+            /// Create a new instance from a pointer.
+            ///
+            /// # Safety
+            /// Must be used from functions of the [crate::bindings::context::Context] to be sure that the
+            /// usage is correct...
+            pub(super) unsafe fn from_ptr(inner: $llvm $($(, $field: $ty)*)?) -> Self {
+                Self {
+                    inner $($(, $field)*)?,
+                    marker: core::marker::PhantomData
+                }
+            }
+
+            /// Get the inner pointer.
+            pub(super) fn as_ptr(&self) -> $llvm {
+                self.inner
+            }
+
+        }
+    };
+
+    (@marker mut   $llvm:ident $lifetime:lifetime) => { core::marker::PhantomData<&$lifetime mut $llvm> };
+    (@marker const $llvm:ident $lifetime:lifetime) => { core::marker::PhantomData<&$lifetime     $llvm> };
+}
+use declare;
+
+const fn cstr(content: &[u8]) -> &std::ffi::CStr {
+    match std::ffi::CStr::from_bytes_with_nul(content) {
+        Ok(string) => string,
+        Err(_) => panic!("you forgot the null byte at the end"),
+    }
+}
diff --git a/src/Rust/vvs_llvm/src/bindings/module.rs b/src/Rust/vvs_llvm/src/bindings/module.rs
new file mode 100644
index 00000000..4205010b
--- /dev/null
+++ b/src/Rust/vvs_llvm/src/bindings/module.rs
@@ -0,0 +1,28 @@
+use crate::prelude::*;
+use llvm_sys::{core::*, prelude::*, LLVMLinkage, LLVMVisibility};
+use std::ffi::{CString, NulError};
+
+crate::bindings::declare! { mut LLVMModuleRef as Module<'a> }
+
+impl Module<'_> {
+    /// Add a new function in this module.
+    ///
+    /// Note that by default all functions are private.
+    pub fn add_function(&mut self, name: impl AsRef<str>, ty: FunctionType) -> Result<FunctionDeclaration, NulError> {
+        let function = unsafe { LLVMAddFunction(self.inner, CString::new(name.as_ref())?.as_ptr(), ty.as_ptr()) };
+
+        // All the functions are private to the module!
+        unsafe {
+            LLVMSetLinkage(function, LLVMLinkage::LLVMLinkerPrivateLinkage);
+            LLVMSetVisibility(function, LLVMVisibility::LLVMHiddenVisibility);
+        }
+
+        Ok(unsafe { FunctionDeclaration::from_ptr(function) })
+    }
+}
+
+impl Drop for Module<'_> {
+    fn drop(&mut self) {
+        unsafe { LLVMDisposeModule(self.inner) }
+    }
+}
diff --git a/src/Rust/vvs_llvm/src/bindings/types.rs b/src/Rust/vvs_llvm/src/bindings/types.rs
new file mode 100644
index 00000000..5969d4c9
--- /dev/null
+++ b/src/Rust/vvs_llvm/src/bindings/types.rs
@@ -0,0 +1,53 @@
+use llvm_sys::{core::*, prelude::*, LLVMTypeKind};
+
+crate::bindings::declare! { const LLVMTypeRef as Type<'a> }
+crate::bindings::declare! { const LLVMTypeRef as FunctionType<'a> }
+
+impl FunctionType<'_> {
+    /// Create a new function type.
+    pub fn new<const N: usize>(args: [Type; N], returns: Type) -> Self {
+        unsafe {
+            Self::from_ptr(LLVMFunctionType(returns.as_ptr(), args.map(|ty| ty.as_ptr()).as_mut_ptr(), N as u32, 0))
+        }
+    }
+
+    /// Get the returned type of the function.
+    pub fn returns(&self) -> Type {
+        unsafe { Type::from_ptr(LLVMGetReturnType(self.as_ptr())) }
+    }
+
+    /// Get the number of arguments.
+    pub fn args_len(&self) -> usize {
+        (unsafe { LLVMCountParamTypes(self.as_ptr()) }) as usize
+    }
+
+    /// Get the arguments of the function type.
+    pub fn args(&self) -> Vec<Type> {
+        let params_count = self.args_len();
+        let mut params = Vec::with_capacity(params_count);
+        params.resize(params_count, std::ptr::null_mut());
+        unsafe { LLVMGetParamTypes(self.as_ptr(), params.as_mut_ptr()) };
+        params.into_iter().map(|ptr| unsafe { Type::from_ptr(ptr) }).collect()
+    }
+}
+
+macro_rules! type_is {
+    ($llvm:ident as $name:ident) => {
+        paste::paste! {
+            #[doc = "Tells wether the type is " $name " or not."]
+            pub fn [< is_$name >](&self) -> bool {
+                (unsafe { LLVMGetTypeKind(self.as_ptr()) }) == LLVMTypeKind::$llvm
+            }
+        }
+    };
+}
+
+impl Type<'_> {
+    type_is! { LLVMIntegerTypeKind  as int   }
+    type_is! { LLVMVoidTypeKind     as void  }
+    type_is! { LLVMArrayTypeKind    as array }
+    type_is! { LLVMFloatTypeKind    as f32   }
+    type_is! { LLVMLabelTypeKind    as label }
+    type_is! { LLVMPointerTypeKind  as ptr   }
+    type_is! { LLVMVectorTypeKind   as vec   }
+}
diff --git a/src/Rust/vvs_llvm/src/bindings/value.rs b/src/Rust/vvs_llvm/src/bindings/value.rs
new file mode 100644
index 00000000..98d8496d
--- /dev/null
+++ b/src/Rust/vvs_llvm/src/bindings/value.rs
@@ -0,0 +1,34 @@
+use crate::prelude::*;
+use llvm_sys::{core::*, prelude::*};
+
+crate::bindings::declare! { mut LLVMValueRef as Value<'a> }
+
+impl Value<'_> {
+    /// Get the type of the value.
+    pub fn ty(&self) -> Type {
+        unsafe { Type::from_ptr(LLVMTypeOf(self.as_ptr())) }
+    }
+
+    /// Create a clone of the value. Because we don't follow the semantic of rust for LLVM values,
+    /// we won't call clone to not be confusing.
+    ///
+    /// If the cloned instruction is not inserted, you must call [Value::delete]
+    pub fn create_clone(&self) -> Self {
+        unsafe { Self::from_ptr(LLVMInstructionClone(self.as_ptr())) }
+    }
+
+    /// Delete an instruction.
+    ///
+    /// # Safety
+    /// The instruction must not be inserted into any basic block.
+    pub unsafe fn delete(self) {
+        unsafe { LLVMDeleteInstruction(self.as_ptr()) }
+    }
+}
+
+impl Eq for Value<'_> {}
+impl PartialEq for Value<'_> {
+    fn eq(&self, other: &Self) -> bool {
+        self.inner == other.inner
+    }
+}
diff --git a/src/Rust/vvs_llvm/src/iter.rs b/src/Rust/vvs_llvm/src/iter.rs
index e1fae55f..b94dbaf3 100644
--- a/src/Rust/vvs_llvm/src/iter.rs
+++ b/src/Rust/vvs_llvm/src/iter.rs
@@ -1,6 +1,6 @@
 //! Utility functions and structures to iterate over an LLVM function and in the basic blocks.
 
-use crate::*;
+use llvm_sys::{core::*, prelude::*};
 use std::ptr;
 
 /// Iterate over the basic blocks in a function.
diff --git a/src/Rust/vvs_llvm/src/lib.rs b/src/Rust/vvs_llvm/src/lib.rs
index 92320ada..e2f7b5f4 100644
--- a/src/Rust/vvs_llvm/src/lib.rs
+++ b/src/Rust/vvs_llvm/src/lib.rs
@@ -61,20 +61,33 @@ pub mod build {
     }
 }
 
-pub use llvm_sys::{
-    analysis::*,
-    core::*,
-    error::*,
-    orc2::{ee::*, lljit::*, *},
-    prelude::*,
-    target::*,
-    target_machine::*,
-    transforms::pass_builder::*,
-    *,
-};
+#[cfg(feature = "sys")]
+pub mod sys {
+    pub use llvm_sys::{
+        analysis::*,
+        core::*,
+        error::*,
+        orc2::{ee::*, lljit::*, *},
+        prelude::*,
+        target::*,
+        target_machine::*,
+        transforms::pass_builder::*,
+        *,
+    };
+}
 
-mod init;
-mod iter;
+#[cfg(feature = "bindings")]
+pub mod prelude {
+    pub use crate::bindings::{basic_block::*, builder::*, context::*, function::*, module::*, types::*, value::*};
+}
 
-pub use init::*;
+#[cfg(feature = "bindings")]
+mod bindings;
+
+#[cfg(feature = "init")]
+pub mod init;
+
+#[cfg(feature = "bindings")]
+mod iter;
+#[cfg(feature = "bindings")]
 pub use iter::*;
diff --git a/src/Rust/vvs_procmacro/src/vvrt/gen.rs b/src/Rust/vvs_procmacro/src/vvrt/gen.rs
index 6ad18aa2..77a6e0f2 100644
--- a/src/Rust/vvs_procmacro/src/vvrt/gen.rs
+++ b/src/Rust/vvs_procmacro/src/vvrt/gen.rs
@@ -99,7 +99,7 @@ pub(crate) fn gen_method_infos(name: syn::Ident, infos: Vec<MethodInfo>) -> anyh
             let func: unsafe extern "C" fn() = unsafe { std::mem::transmute(#func as *const ()) };
             let mut llvm_args = #llvm_args; // We compute the vector here for safety.
             let ast_type = ASTType::Function(#ast_args, Box::new(#ast_returns)); // Also needs the ast type.
-            let functy = vvs_llvm::LLVMFunctionType(
+            let functy = vvs_llvm::sys::LLVMFunctionType(
                 #llvm_returns,                          // Should be Ok there.
                 llvm_args.as_mut_ptr(), #llvm_args_len, // We pre-computed the length here.
                 0                                       // No variadic functions there.
diff --git a/src/Rust/vvs_runtime/src/jit.rs b/src/Rust/vvs_runtime/src/jit.rs
index 953bc4ae..b642be58 100644
--- a/src/Rust/vvs_runtime/src/jit.rs
+++ b/src/Rust/vvs_runtime/src/jit.rs
@@ -8,7 +8,7 @@ use std::{
         Arc,
     },
 };
-use vvs_llvm::*;
+use vvs_llvm::sys::*;
 use vvs_runtime_types::VVRTSymbol;
 
 #[allow(dead_code)]
@@ -65,7 +65,7 @@ extern "C" fn orc_sym_filter(_: *mut c_void, sym: LLVMOrcSymbolStringPoolEntryRe
 impl JIT {
     /// Create a new JIT thingy to execute Vivy Script code.
     pub fn new() -> anyhow::Result<JIT> {
-        if let Err(err) = vvs_llvm::initialize_llvm() {
+        if let Err(err) = vvs_llvm::init::initialize_llvm() {
             log::error!("{err}");
         }
 
diff --git a/src/Rust/vvs_runtime_types/Cargo.toml b/src/Rust/vvs_runtime_types/Cargo.toml
index 1e1ab1a6..7c652ec6 100644
--- a/src/Rust/vvs_runtime_types/Cargo.toml
+++ b/src/Rust/vvs_runtime_types/Cargo.toml
@@ -18,9 +18,10 @@ unicode-segmentation.workspace = true
 vvs_procmacro.workspace = true
 vvs_utils.workspace     = true
 vvs_lang.workspace      = true
-vvs_llvm.workspace      = true
 vvs_ass.workspace       = true
 
+vvs_llvm = { workspace = true, features = ["sys"] }
+
 [build-dependencies]
 anyhow.workspace = true
 vvs_llvm = { workspace = true, features = ["link"] }
diff --git a/src/Rust/vvs_runtime_types/src/mangle.rs b/src/Rust/vvs_runtime_types/src/mangle.rs
index 2945a334..3003f418 100644
--- a/src/Rust/vvs_runtime_types/src/mangle.rs
+++ b/src/Rust/vvs_runtime_types/src/mangle.rs
@@ -1,7 +1,7 @@
 use anyhow::{anyhow, bail};
 use std::{ffi::CString, str::FromStr};
 use vvs_lang::ast::ASTType;
-use vvs_llvm::*;
+use vvs_llvm::sys::*;
 
 /// Materialize which type of symbol we have.
 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
diff --git a/src/Rust/vvs_runtime_types/src/types/mod.rs b/src/Rust/vvs_runtime_types/src/types/mod.rs
index 1e8972a6..12991564 100644
--- a/src/Rust/vvs_runtime_types/src/types/mod.rs
+++ b/src/Rust/vvs_runtime_types/src/types/mod.rs
@@ -24,7 +24,7 @@ mod number;
 use self::{any::*, line::*, number::*, sequence::*, string::*, syllabe::*, table::*, variant::*};
 use crate::vvll::*;
 use std::sync::OnceLock;
-use vvs_llvm::*;
+use vvs_llvm::sys::*;
 
 #[cfg(test)]
 mod test;
diff --git a/src/Rust/vvs_runtime_types/src/vvll.rs b/src/Rust/vvs_runtime_types/src/vvll.rs
index cbaaeed3..b10ea344 100644
--- a/src/Rust/vvs_runtime_types/src/vvll.rs
+++ b/src/Rust/vvs_runtime_types/src/vvll.rs
@@ -3,7 +3,7 @@
 use hashbrown::{HashMap, HashSet};
 use std::{ffi::CString, sync::OnceLock};
 use vvs_lang::ast::ASTType;
-use vvs_llvm::*;
+use vvs_llvm::sys::*;
 
 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
 pub struct ManageFunctions {
-- 
GitLab