diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 266f8cbb..83164285 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,7 +9,7 @@ jobs: build: strategy: matrix: - os: [ubuntu-latest] + os: [ubuntu-22.04] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v2 @@ -30,23 +30,36 @@ jobs: - name: Set up the Linux env run: | set -eux - sudo apt install -y llvm-12 clang-12 libgc-dev - if: matrix.os == 'ubuntu-latest' + sudo apt install -y libgc-dev + + - name: Cache LLVM and Clang + id: cache-llvm + uses: actions/cache@v3 + with: + path: | + C:/Program Files/LLVM + ./llvm + key: llvm-16.0 + - name: Install LLVM and Clang + uses: KyleMayes/install-llvm-action@v1 + with: + version: "16.0" + cached: ${{ steps.cache-llvm.outputs.cache-hit }} - name: Output versions run: | set -eux rustc --version cargo --version - clang-12 --version + clang --version - name: Build and test run: | set -eux cd lib/skc_rustlib; cargo build; cd ../../ - env -- LLC=llc-12 CLANG=clang-12 cargo run -- build-corelib - env -- LLC=llc-12 CLANG=clang-12 cargo test - env -- LLC=llc-12 CLANG=clang-12 bash release_test.sh + env -- cargo run -- build-corelib + env -- cargo test + env -- bash release_test.sh # Run cargo fmt --all -- --check format: diff --git a/Cargo.lock b/Cargo.lock index 404d2c46..53f3ba3a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3,10 +3,25 @@ version = 3 [[package]] -name = "aho-corasick" +name = "addr2line" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "aho-corasick" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8f9420f797f2d9e935edf629310eb938a0d839f984e25327f3c7eed22300c" dependencies = [ "memchr", ] @@ -28,9 +43,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.71" +version = "1.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" +checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854" [[package]] name = "ariadne" @@ -43,9 +58,9 @@ dependencies = [ [[package]] name = "async-channel" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf46fee83e5ccffc220104713af3292ff9bc7c64c7de289f66dae8e38d826833" +checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" dependencies = [ "concurrent-queue", "event-listener", @@ -54,13 +69,13 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.68" +version = "0.1.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842" +checksum = "cc6dde6e4ed435a4c1ee4e73592f5ba9da2151af10076cc04858746af9352d09" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn 2.0.28", ] [[package]] @@ -92,11 +107,26 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "backtrace" +version = "0.3.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + [[package]] name = "bdwgc-alloc" -version = "0.6.5" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de9975f97d317cec0a7cda72f866ca96c49acfccf5fe2fa97c6d5ab0c35be6dc" +checksum = "cb37b71074dee620cbac64874a9d1e19cd6a25d5c48e8cc0e69fd1cbd0e341b8" dependencies = [ "cmake", "libc", @@ -131,9 +161,12 @@ checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" [[package]] name = "cc" -version = "1.0.79" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +checksum = "305fe645edc1442a0fa8b6726ba61d422798d37a52e12eaecf4b022ebbb88f01" +dependencies = [ + "libc", +] [[package]] name = "cfg-if" @@ -169,12 +202,12 @@ dependencies = [ [[package]] name = "chrono-tz" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9cc2b23599e6d7479755f3594285efb3f74a1bdca7a7374948bc831e23a552" +checksum = "f1369bc6b9e9a7dfdae2055f6ec151fe9c554a9d23d357c0237cee2e25eaabb7" dependencies = [ "chrono", - "chrono-tz-build 0.1.0", + "chrono-tz-build 0.2.0", "phf", ] @@ -191,9 +224,9 @@ dependencies = [ [[package]] name = "chrono-tz-build" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9998fb9f7e9b2111641485bf8beb32f92945f97f92a3d061f744cfef335f751" +checksum = "e2f5ebdc942f57ed96d560a6d1a459bae5851102a25d5bf89dc04ae453e31ecf" dependencies = [ "parse-zoneinfo", "phf", @@ -265,18 +298,18 @@ checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" [[package]] name = "cpufeatures" -version = "0.2.7" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e4c1eaa2012c47becbbad2ab175484c2a84d1185b566fb2cc5b8707343dfe58" +checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" dependencies = [ "libc", ] [[package]] name = "crossbeam-utils" -version = "0.8.15" +version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b" +checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" dependencies = [ "cfg-if", ] @@ -293,12 +326,12 @@ dependencies = [ [[package]] name = "dashmap" -version = "5.4.0" +version = "5.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "907076dfda823b0b36d2a1bb5f90c96660a5bbcd7729e10727f07858f22c4edc" +checksum = "6943ae99c34386c84a470c499d3414f66502a41340aa895406e0d2e4a207b91d" dependencies = [ "cfg-if", - "hashbrown", + "hashbrown 0.14.0", "lock_api", "once_cell", "parking_lot_core", @@ -316,9 +349,9 @@ dependencies = [ [[package]] name = "either" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "env_logger" @@ -392,7 +425,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn 2.0.28", ] [[package]] @@ -446,12 +479,24 @@ dependencies = [ "wasi 0.11.0+wasi-snapshot-preview1", ] +[[package]] +name = "gimli" +version = "0.27.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" + [[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.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" + [[package]] name = "heck" version = "0.4.1" @@ -469,12 +514,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.2.6" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" -dependencies = [ - "libc", -] +checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" [[package]] name = "httparse" @@ -528,13 +570,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg", - "hashbrown", + "hashbrown 0.12.3", ] [[package]] name = "inkwell" -version = "0.1.0" -source = "git+https://github.com/TheDan64/inkwell?rev=845270c99ee6268385b79b2e178a872ab4b1b1a8#845270c99ee6268385b79b2e178a872ab4b1b1a8" +version = "0.2.0" +source = "git+https://github.com/TheDan64/inkwell?rev=4030f76#4030f764f1c889f36429ac02ef32e04fcfa8ce33" dependencies = [ "either", "inkwell_internals", @@ -546,25 +588,25 @@ dependencies = [ [[package]] name = "inkwell_internals" -version = "0.5.0" -source = "git+https://github.com/TheDan64/inkwell?rev=845270c99ee6268385b79b2e178a872ab4b1b1a8#845270c99ee6268385b79b2e178a872ab4b1b1a8" +version = "0.8.0" +source = "git+https://github.com/TheDan64/inkwell?rev=4030f76#4030f764f1c889f36429ac02ef32e04fcfa8ce33" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.28", ] [[package]] name = "itoa" -version = "1.0.6" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" [[package]] name = "js-sys" -version = "0.3.63" +version = "0.3.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f37a4a5928311ac501dee68b3c7613a1037d0edb30c8e5427bd832d55d1b790" +checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" dependencies = [ "wasm-bindgen", ] @@ -588,15 +630,15 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.146" +version = "0.2.147" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b" +checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" [[package]] name = "llvm-sys" -version = "120.3.0" +version = "160.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b44721270d140699646701a91b0e982b7ca858da96d8886629cc79f13c191c6d" +checksum = "0bf51981ac0622b10fe4790763e3de1f3d68a0ee4222e03accaaab6731bd508d" dependencies = [ "cc", "lazy_static", @@ -617,15 +659,15 @@ dependencies = [ [[package]] name = "log" -version = "0.4.18" +version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "518ef76f2f87365916b142844c16d8fefd85039bc5699050210a7778ee1cd1de" +checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" [[package]] name = "lsp-types" -version = "0.94.0" +version = "0.94.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b63735a13a1f9cd4f4835223d828ed9c2e35c8c5e61837774399f558b6a1237" +checksum = "c66bfd44a06ae10647fe3f8214762e9369fd4248df1350924b4ef9e770a85ea1" dependencies = [ "bitflags", "serde", @@ -646,6 +688,15 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" +[[package]] +name = "miniz_oxide" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +dependencies = [ + "adler", +] + [[package]] name = "mio" version = "0.8.8" @@ -669,23 +720,32 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" dependencies = [ "autocfg", ] [[package]] name = "num_cpus" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi 0.2.6", + "hermit-abi 0.3.2", "libc", ] +[[package]] +name = "object" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" +dependencies = [ + "memchr", +] + [[package]] name = "once_cell" version = "1.18.0" @@ -705,9 +765,9 @@ dependencies = [ [[package]] name = "os_str_bytes" -version = "6.5.0" +version = "6.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ceedf44fb00f2d1984b0bc98102627ce622e083e49a5bacdb3e514fa4238e267" +checksum = "4d5d9eb14b174ee9aa2ef96dc2b94637a2d4b6e7cb873c7e171f0c20c6cf3eac" [[package]] name = "parking_lot" @@ -749,9 +809,9 @@ checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" [[package]] name = "pest" -version = "2.6.0" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e68e84bfb01f0507134eac1e9b410a12ba379d064eab48c50ba4ce329a527b70" +checksum = "1acb4a4365a13f749a93f1a094a7805e5cfa0955373a9de860d962eaa3a5fe5a" dependencies = [ "thiserror", "ucd-trie", @@ -759,9 +819,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.6.0" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b79d4c71c865a25a4322296122e3924d30bc8ee0834c8bfc8b95f7f054afbfb" +checksum = "666d00490d4ac815001da55838c500eafb0320019bbaa44444137c48b443a853" dependencies = [ "pest", "pest_generator", @@ -769,22 +829,22 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.6.0" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c435bf1076437b851ebc8edc3a18442796b30f1728ffea6262d59bbe28b077e" +checksum = "68ca01446f50dbda87c1786af8770d535423fa8a53aec03b8f4e3d7eb10e0929" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.18", + "syn 2.0.28", ] [[package]] name = "pest_meta" -version = "2.6.0" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "745a452f8eb71e39ffd8ee32b3c5f51d03845f99786fa9b68db6ff509c505411" +checksum = "56af0a30af74d0445c0bf6d9d051c979b516a1a5af790d251daee76005420a48" dependencies = [ "once_cell", "pest", @@ -793,18 +853,18 @@ dependencies = [ [[package]] name = "phf" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "928c6535de93548188ef63bb7c4036bd415cd8f36ad25af44b9789b2ee72a48c" +checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" dependencies = [ "phf_shared", ] [[package]] name = "phf_codegen" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56ac890c5e3ca598bbdeaa99964edb5b0258a583a9eb6ef4e89fc85d9224770" +checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a" dependencies = [ "phf_generator", "phf_shared", @@ -812,9 +872,9 @@ dependencies = [ [[package]] name = "phf_generator" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1181c94580fa345f50f19d738aaa39c0ed30a600d95cb2d3e23f94266f14fbf" +checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" dependencies = [ "phf_shared", "rand", @@ -822,9 +882,9 @@ dependencies = [ [[package]] name = "phf_shared" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1fb5f6f826b772a8d4c0394209441e7d37cbbb967ae9c7e0e8134365c9ee676" +checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" dependencies = [ "siphasher", "uncased", @@ -832,29 +892,29 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.1.0" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c95a7476719eab1e366eaf73d0260af3021184f18177925b07f54b30089ceead" +checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.0" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39407670928234ebc5e6e580247dd567ad73a3578460c5990f9503df207e8f07" +checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn 2.0.28", ] [[package]] name = "pin-project-lite" -version = "0.2.9" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" +checksum = "12cc1b0bf1727a77a54b6654e7b5f1af8604923edc8b81885f8ec92f9e3f0a05" [[package]] name = "pin-utils" @@ -900,18 +960,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.59" +version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6aeca18b86b413c660b781aa319e4e2648a3e6f9eadc9b47e9038e6fe9f3451b" +checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.28" +version = "1.0.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488" +checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965" dependencies = [ "proc-macro2", ] @@ -957,9 +1017,21 @@ dependencies = [ [[package]] name = "regex" -version = "1.8.4" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81bc1d4caf89fac26a70747fe603c130093b53c773888797a6329091246d651a" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0ab3ca65655bb1e41f2a8c8cd662eb4fb035e67c3f78da1d61dffe89d07300f" +checksum = "fed1ceff11a1dddaee50c9dc8e4938bd106e9d89ae372f192311e7da498e3b69" dependencies = [ "aho-corasick", "memchr", @@ -968,65 +1040,59 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" +checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" + +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "ryu" -version = "1.0.13" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" [[package]] name = "scopeguard" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "semver" -version = "0.11.0" +version = "1.0.18" 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", -] +checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918" [[package]] name = "serde" -version = "1.0.163" +version = "1.0.183" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2113ab51b87a539ae008b5c6c02dc020ffa39afd2d83cffcb3f4eb2722cebec2" +checksum = "32ac8da02677876d532745a130fc9d8e6edfa81a269b107c5b00829b91d8eb3c" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.163" +version = "1.0.183" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e" +checksum = "aafe972d60b0b9bee71a91b92fee2d4fb3c9d7e8f6b179aa99f27203d99a4816" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn 2.0.28", ] [[package]] name = "serde_json" -version = "1.0.96" +version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" +checksum = "076066c5f1078eac5b722a31827a8832fe108bed65dfa75e233c89f8206e976c" dependencies = [ "itoa", "ryu", @@ -1035,20 +1101,20 @@ dependencies = [ [[package]] name = "serde_repr" -version = "0.1.12" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcec881020c684085e55a25f7fd888954d56609ef363479dc5a1305eb0d40cab" +checksum = "8725e1dfadb3a50f7e5ce0b1a540466f6ed3fe7a0fca2ac2b8b831d31316bd00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn 2.0.28", ] [[package]] name = "sha2" -version = "0.10.6" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" +checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" dependencies = [ "cfg-if", "cpufeatures", @@ -1062,7 +1128,7 @@ dependencies = [ "anyhow", "ariadne", "chrono", - "chrono-tz 0.8.2", + "chrono-tz 0.8.3", "clap", "either", "env_logger", @@ -1247,18 +1313,18 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" [[package]] name = "socket2" -version = "0.4.9" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +checksum = "2538b18701741680e0322a2302176d3253a35388e2e62f172f64f4f16605f877" dependencies = [ "libc", - "winapi", + "windows-sys", ] [[package]] @@ -1280,9 +1346,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.18" +version = "2.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32d41677bcbe24c20c52e7c70b0d8db04134c5d1066bf98662e2871ad200ea3e" +checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567" dependencies = [ "proc-macro2", "quote", @@ -1306,22 +1372,22 @@ checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" [[package]] name = "thiserror" -version = "1.0.40" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" +checksum = "611040a08a0439f8248d1990b111c95baa9c704c805fa1f62104b39655fd7f90" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.40" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" +checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn 2.0.28", ] [[package]] @@ -1352,11 +1418,11 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.28.2" +version = "1.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94d7b1cfd2aa4011f2de74c2c4c63665e27a71006b0a192dcd2710272e73dfa2" +checksum = "2d3ce25f50619af8b0aec2eb23deebe84249e19e2ddd393a6e16e3300a6dadfd" dependencies = [ - "autocfg", + "backtrace", "bytes", "libc", "mio", @@ -1377,7 +1443,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn 2.0.28", ] [[package]] @@ -1468,13 +1534,13 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.24" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74" +checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn 2.0.28", ] [[package]] @@ -1494,9 +1560,9 @@ checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" [[package]] name = "ucd-trie" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81" +checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" [[package]] name = "uncased" @@ -1515,9 +1581,9 @@ checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" [[package]] name = "unicode-ident" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" +checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" [[package]] name = "unicode-normalization" @@ -1566,9 +1632,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.86" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bba0e8cb82ba49ff4e229459ff22a191bbe9a1cb3a341610c9c33efc27ddf73" +checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -1576,24 +1642,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.86" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b04bc93f9d6bdee709f6bd2118f57dd6679cf1176a1af464fca3ab0d66d8fb" +checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.18", + "syn 2.0.28", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.86" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14d6b024f1a526bb0234f52840389927257beb670610081360e5a03c5df9c258" +checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1601,22 +1667,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.86" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8" +checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.18", + "syn 2.0.28", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.86" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed9d5b4305409d1fc9482fee2d7f9bcbf24b3972bf59817ef757e23982242a93" +checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" [[package]] name = "winapi" @@ -1669,9 +1735,9 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.48.0" +version = "0.48.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", diff --git a/Cargo.toml b/Cargo.toml index 668754c9..d09a896f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,7 @@ skc_codegen = { path = "lib/skc_codegen/" } ariadne = "0.1.5" anyhow = "1.0" -inkwell = { git = "https://github.com/TheDan64/inkwell", features = ["llvm12-0"], rev = "845270c99ee6268385b79b2e178a872ab4b1b1a8" } +inkwell = { git = "https://github.com/TheDan64/inkwell", features = ["llvm16-0"], rev = "4030f76" } clap = { version = "3.1.18", features = ["derive"] } either = "1.5.3" env_logger = "0.8.2" diff --git a/README.md b/README.md index 60ce9507..0fde3b59 100644 --- a/README.md +++ b/README.md @@ -110,7 +110,7 @@ See [install.md](./doc/guide/src/install.md) $ cargo test ``` -Only integration tests (test/sk/*.sk): +Only integration tests (test/sk/\*.sk): ``` $ cargo test --test integration_test @@ -128,15 +128,6 @@ With logging enabled $ RUST_LOG='trace' cargo test ``` -### Troubleshooting - -``` - /Users/yhara/.cargo/registry/src/github.com-1ecc6299db9ec823/bdwgc-alloc-0.6.0/vendor/libatomic_ops/configure: line 4683: syntax error near unexpected token `disable-shared' - /Users/yhara/.cargo/registry/src/github.com-1ecc6299db9ec823/bdwgc-alloc-0.6.0/vendor/libatomic_ops/configure: line 4683: `LT_INIT(disable-shared)' -``` - -=> `brew install libtool` - ## License MIT diff --git a/doc/guide/src/install.md b/doc/guide/src/install.md index e708f400..a5b6afa1 100644 --- a/doc/guide/src/install.md +++ b/doc/guide/src/install.md @@ -7,25 +7,25 @@ Only 64bit environments are supported. 1. Install [Git](https://git-scm.com/) 1. Install [Rust](https://www.rust-lang.org/) -1. Install LLVM 12 - - eg. `brew install llvm@12` on Mac - - eg. `sudo apt install llvm-12 clang-12` on Ubuntu +1. Install LLVM 16 + - eg. `brew install llvm@16` on Mac + - eg. `sudo apt install llvm-16 clang-16` on Ubuntu - You may need `sudo apt install cmake` on Ubuntu - (TODO) `apt install libgc-dev` needed on Ubuntu? You may need to setup some environment variables. For example, on Mac: ``` -export PATH="$(brew --prefix)/opt/llvm@12/bin":$PATH -export LDFLAGS="-L$(brew --prefix)/opt/llvm@12/lib" -export CPPFLAGS="-I$(brew --prefix)/opt/llvm@12/include" +export PATH="$(brew --prefix)/opt/llvm@16/bin":$PATH +export LDFLAGS="-L$(brew --prefix)/opt/llvm@16/lib" +export CPPFLAGS="-I$(brew --prefix)/opt/llvm@16/include" ``` and on Ubuntu: ``` -export LLC=llc-12 -export CLANG=clang-12 +export LLC=llc-16 +export CLANG=clang-16 ``` ### Compiling core library @@ -40,7 +40,7 @@ $ cd lib/skc_rustlib; cargo build; cd ../../ $ cargo run -- build-corelib ``` -The `build-corelib` subcommand compiles core classes (builtin/*.sk) into ./builtin/builtin.bc and ./builtin/exports.json. +The `build-corelib` subcommand compiles core classes (builtin/\*.sk) into ./builtin/builtin.bc and ./builtin/exports.json. ### Running a program @@ -73,3 +73,22 @@ because `shiika` looks for corelib in the current directory by default. You can ``` export SHIIKA_ROOT=/path/to/repo/of/shiika ``` + +## Troubleshooting + +``` +error: could not find native static library `Polly`, perhaps an -L flag is missing? + +error: could not compile `llvm-sys` due to previous error +``` + +=> `sudo apt install libpolly-16-dev` + +This may happen when you install llvm from https://apt.llvm.org/ . + +``` + /Users/yhara/.cargo/registry/src/github.com-1ecc6299db9ec823/bdwgc-alloc-0.6.0/vendor/libatomic_ops/configure: line 4683: syntax error near unexpected token `disable-shared' + /Users/yhara/.cargo/registry/src/github.com-1ecc6299db9ec823/bdwgc-alloc-0.6.0/vendor/libatomic_ops/configure: line 4683: `LT_INIT(disable-shared)' +``` + +=> `brew install libtool` diff --git a/lib/skc_ast2hir/src/accessors.rs b/lib/skc_ast2hir/src/accessors.rs index e837a95c..b8a47636 100644 --- a/lib/skc_ast2hir/src/accessors.rs +++ b/lib/skc_ast2hir/src/accessors.rs @@ -54,6 +54,8 @@ fn create_getter(clsname: &ClassFullname, ivar: &SkIVar) -> SkMethod { SkMethodBody::Getter { idx: ivar.idx, name: ivar.name.clone(), + ty: ivar.ty.clone(), + self_ty: clsname.to_ty(), }, ) } @@ -76,6 +78,8 @@ fn create_setter(clsname: &ClassFullname, ivar: &SkIVar) -> SkMethod { SkMethodBody::Setter { idx: ivar.idx, name: ivar.name.clone(), + ty: clsname.to_ty(), + self_ty: clsname.to_ty(), }, ) } diff --git a/lib/skc_codegen/Cargo.toml b/lib/skc_codegen/Cargo.toml index 37ea4ee5..c58b85a6 100644 --- a/lib/skc_codegen/Cargo.toml +++ b/lib/skc_codegen/Cargo.toml @@ -14,6 +14,6 @@ skc_mir = { path = "../skc_mir" } anyhow = "1.0" serde = { version = "1.0.125", features = ["derive"] } serde_json = "1.0" -inkwell = { git = "https://github.com/TheDan64/inkwell", features = ["llvm12-0"], rev = "845270c99ee6268385b79b2e178a872ab4b1b1a8" } +inkwell = { git = "https://github.com/TheDan64/inkwell", features = ["llvm16-0"], rev = "4030f76" } either = "1.5.3" log = "0.4.11" diff --git a/lib/skc_codegen/src/boxing.rs b/lib/skc_codegen/src/boxing.rs index 1a5d9584..d22774fb 100644 --- a/lib/skc_codegen/src/boxing.rs +++ b/lib/skc_codegen/src/boxing.rs @@ -55,9 +55,9 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { let basic_block = self.context.append_basic_block(function, ""); self.builder.position_at_end(basic_block); - let i1_val = SkObj(function.get_params()[0]); - let sk_bool = self.allocate_sk_obj(&class_fullname("Bool"), "sk_bool"); - self.build_ivar_store(&sk_bool, 0, i1_val, "@llvm_bool"); + let i1_val = function.get_params()[0]; + let sk_bool = self.allocate_sk_obj(&class_fullname("Bool")); + self.build_ivar_store_raw(sk_bool.clone(), "@llvm_bool", 0, i1_val); self.build_return(&sk_bool); // unbox_bool @@ -65,18 +65,18 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { let basic_block = self.context.append_basic_block(function, ""); self.builder.position_at_end(basic_block); - let sk_bool = SkObj(function.get_params()[0]); - let i1_val = self.build_ivar_load(sk_bool, 0, "@llvm_bool"); - self.build_return(&i1_val); + let sk_bool = SkObj::new(ty::raw("Bool"), function.get_params()[0]); + let i1_val = self.build_ivar_load_raw(sk_bool, self.i1_type.into(), 0, "@llvm_bool"); + self.builder.build_return(Some(&i1_val)); // box_int let function = self.module.get_function("box_int").unwrap(); let basic_block = self.context.append_basic_block(function, ""); self.builder.position_at_end(basic_block); - let i64_val = SkObj(function.get_params()[0]); - let sk_int = self.allocate_sk_obj(&class_fullname("Int"), "sk_int"); - self.build_ivar_store(&sk_int, 0, i64_val, "@llvm_int"); + let i64_val = function.get_params()[0]; + let sk_int = self.allocate_sk_obj(&class_fullname("Int")); + self.build_ivar_store_raw(sk_int.clone(), "@llvm_int", 0, i64_val); self.build_return(&sk_int); // unbox_int @@ -84,18 +84,21 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { let basic_block = self.context.append_basic_block(function, ""); self.builder.position_at_end(basic_block); - let sk_int = SkObj(function.get_params()[0]); - let i64_val = self.build_ivar_load(sk_int, 0, "@llvm_int"); - self.build_return(&i64_val); + let sk_int = SkObj::new( + ty::raw("Int"), + function.get_params()[0].into_pointer_value(), + ); + let i64_val = self.build_ivar_load_raw(sk_int, self.i64_type.into(), 0, "@llvm_int"); + self.builder.build_return(Some(&i64_val)); // box_float let function = self.module.get_function("box_float").unwrap(); let basic_block = self.context.append_basic_block(function, ""); self.builder.position_at_end(basic_block); - let f64_val = SkObj(function.get_params()[0]); - let sk_float = self.allocate_sk_obj(&class_fullname("Float"), "sk_float"); - self.build_ivar_store(&sk_float, 0, f64_val, "@llvm_float"); + let f64_val = function.get_params()[0]; + let sk_float = self.allocate_sk_obj(&class_fullname("Float")); + self.build_ivar_store_raw(sk_float.clone(), "@llvm_float", 0, f64_val); self.build_return(&sk_float); // unbox_float @@ -103,9 +106,12 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { let basic_block = self.context.append_basic_block(function, ""); self.builder.position_at_end(basic_block); - let sk_float = SkObj(function.get_params()[0]); - let f64_val = self.build_ivar_load(sk_float, 0, "@llvm_float"); - self.build_return(&f64_val); + let sk_float = SkObj::new( + ty::raw("Float"), + function.get_params()[0].into_pointer_value(), + ); + let f64_val = self.build_ivar_load_raw(sk_float, self.f64_type.into(), 0, "@llvm_float"); + self.builder.build_return(Some(&f64_val)); // box_i8ptr let function = self.module.get_function("box_i8ptr").unwrap(); @@ -113,8 +119,8 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { self.builder.position_at_end(basic_block); let i8ptr = function.get_params()[0]; - let sk_ptr = self.allocate_sk_obj(&class_fullname("Shiika::Internal::Ptr"), "sk_ptr"); - self.build_ivar_store_raw(&sk_ptr, 0, i8ptr, "@llvm_i8ptr"); + let sk_ptr = self.allocate_sk_obj(&class_fullname("Shiika::Internal::Ptr")); + self.build_ivar_store_raw(sk_ptr.clone(), "@llvm_i8ptr", 0, i8ptr); self.build_return(&sk_ptr); // unbox_i8ptr @@ -122,9 +128,12 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { let basic_block = self.context.append_basic_block(function, ""); self.builder.position_at_end(basic_block); - let sk_ptr = SkObj(function.get_params()[0]); - let i8ptr = self.build_ivar_load(sk_ptr, 0, "@llvm_i8ptr"); - self.build_return(&i8ptr); + let sk_ptr = SkObj::new( + ty::raw("Shiika::Internal::Ptr"), + function.get_params()[0].into_pointer_value(), + ); + let i8ptr = self.build_ivar_load_raw(sk_ptr, self.i8ptr_type.into(), 0, "@llvm_i8ptr"); + self.builder.build_return(Some(&i8ptr)); // gen_literal_string self.impl_gen_literal_string(); @@ -135,7 +144,7 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { let basic_block = self.context.append_basic_block(function, ""); self.builder.position_at_end(basic_block); - let receiver = self.gen_const_ref(&toplevel_const("String")); + let receiver = self.gen_const_ref(&toplevel_const("String"), &ty::meta("String")); let str_i8ptr = function.get_nth_param(0).unwrap(); let bytesize = function.get_nth_param(1).unwrap().into_int_value(); let args = vec![self.box_i8ptr(str_i8ptr), self.box_int(&bytesize)]; @@ -143,6 +152,7 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { &method_fullname(metaclass_fullname("String").into(), "new"), receiver, &args, + ty::raw("String"), "sk_str", ); self.build_return(&sk_str); @@ -150,7 +160,11 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { /// Convert LLVM bool(i1) into Shiika Bool pub fn box_bool(&self, b: inkwell::values::IntValue<'run>) -> SkObj<'run> { - SkObj(self.call_llvm_func(&llvm_func_name("box_bool"), &[b.into()], "sk_bool")) + SkObj::new( + ty::raw("Bool"), + self.call_llvm_func(&llvm_func_name("box_bool"), &[b.into()], "sk_bool") + .into_pointer_value(), + ) } /// Convert Shiika Bool into LLVM bool(i1) @@ -165,11 +179,15 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { /// Convert LLVM int into Shiika Int pub fn box_int(&self, i: &inkwell::values::IntValue<'run>) -> SkObj<'run> { - SkObj(self.call_llvm_func( - &llvm_func_name("box_int"), - &[i.as_basic_value_enum().into()], - "sk_int", - )) + SkObj::new( + ty::raw("Int"), + self.call_llvm_func( + &llvm_func_name("box_int"), + &[i.as_basic_value_enum().into()], + "sk_int", + ) + .into_pointer_value(), + ) } /// Convert Shiika Int into LLVM int @@ -184,11 +202,15 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { /// Convert LLVM float into Shiika Float pub fn box_float(&self, fl: &inkwell::values::FloatValue<'run>) -> SkObj<'run> { - SkObj(self.call_llvm_func( - &llvm_func_name("box_float"), - &[fl.as_basic_value_enum().into()], - "sk_float", - )) + SkObj::new( + ty::raw("Float"), + self.call_llvm_func( + &llvm_func_name("box_float"), + &[fl.as_basic_value_enum().into()], + "sk_float", + ) + .into_pointer_value(), + ) } /// Convert Shiika Float into LLVM float @@ -203,7 +225,11 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { /// Convert LLVM i8* into Shiika::Internal::Ptr pub fn box_i8ptr(&self, p: inkwell::values::BasicValueEnum<'run>) -> SkObj<'run> { - SkObj(self.call_llvm_func(&llvm_func_name("box_i8ptr"), &[p.into()], "sk_ptr")) + SkObj::new( + ty::raw("Shiika::Internal::Ptr"), + self.call_llvm_func(&llvm_func_name("box_i8ptr"), &[p.into()], "sk_ptr") + .into_pointer_value(), + ) } /// Convert Shiika::Internal::Ptr into LLVM i8* diff --git a/lib/skc_codegen/src/code_gen_context.rs b/lib/skc_codegen/src/code_gen_context.rs index 92b6bb6c..121f67ed 100644 --- a/lib/skc_codegen/src/code_gen_context.rs +++ b/lib/skc_codegen/src/code_gen_context.rs @@ -8,10 +8,7 @@ pub struct CodeGenContext<'hir: 'run, 'run> { /// Current llvm function pub function: inkwell::values::FunctionValue<'run>, /// If `function` corresponds to a lambda or a method - pub function_origin: FunctionOrigin, - /// Parameters of `function` - /// Only used for lambdas - pub function_params: Option<&'hir [MethodParam]>, + pub function_origin: FunctionOrigin<'hir>, /// Ptr of local variables pub lvars: HashMap>, /// End of `while`, if any @@ -23,9 +20,14 @@ pub struct CodeGenContext<'hir: 'run, 'run> { } #[derive(Debug, PartialEq, Eq)] -pub enum FunctionOrigin { - Method, - Lambda { name: String }, +pub enum FunctionOrigin<'hir> { + Method { + params: &'hir [MethodParam], + }, + Lambda { + name: String, + params: &'hir [MethodParam], + }, Other, } @@ -33,14 +35,12 @@ impl<'hir, 'run> CodeGenContext<'hir, 'run> { pub fn new( function: inkwell::values::FunctionValue<'run>, function_end: Rc>, - function_origin: FunctionOrigin, - function_params: Option<&'hir [MethodParam]>, + function_origin: FunctionOrigin<'hir>, lvars: HashMap>, ) -> CodeGenContext<'hir, 'run> { CodeGenContext { function, function_origin, - function_params, lvars, current_loop_end: None, current_func_end: function_end, @@ -66,7 +66,7 @@ impl<'hir, 'run> CodeGenContext<'hir, 'run> { pub fn lambda_name(&self) -> Option<&str> { match &self.function_origin { - FunctionOrigin::Lambda { name } => Some(name), + FunctionOrigin::Lambda { name, .. } => Some(name), _ => None, } } diff --git a/lib/skc_codegen/src/gen_exprs.rs b/lib/skc_codegen/src/gen_exprs.rs index 7d5cc5ed..eca0e557 100644 --- a/lib/skc_codegen/src/gen_exprs.rs +++ b/lib/skc_codegen/src/gen_exprs.rs @@ -2,27 +2,19 @@ use crate::code_gen_context::*; use crate::lambda::LambdaCapture; use crate::utils::*; use crate::values::*; +use crate::vtable::VTableRef; use crate::wtable; use crate::CodeGen; use anyhow::Result; use inkwell::types::*; use inkwell::values::*; -use inkwell::AddressSpace; use shiika_core::{names::*, ty, ty::*}; +use skc_corelib::fn_x; use skc_hir::pattern_match; use skc_hir::HirExpressionBase::*; use skc_hir::*; -use std::convert::TryFrom; use std::rc::Rc; -/// Index of @func of FnX -const FN_X_FUNC_IDX: usize = 0; -/// Index of @the_self of FnX -const FN_X_THE_SELF_IDX: usize = 1; -/// Index of @captures of FnX -const FN_X_CAPTURES_IDX: usize = 2; -/// Index of @exit_status of FnX -const FN_X_EXIT_STATUS_IDX: usize = 3; /// Fn::EXIT_BREAK const EXIT_BREAK: u64 = 1; @@ -31,7 +23,7 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { /// May return `None` when, for example, it ends with a `return` /// expression. pub fn gen_exprs( - &self, + &'run self, ctx: &mut CodeGenContext<'hir, 'run>, exprs: &'hir HirExpressions, ) -> Result>> { @@ -50,7 +42,7 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { } pub fn gen_expr( - &self, + &'run self, ctx: &mut CodeGenContext<'hir, 'run>, expr: &'hir HirExpression, ) -> Result>> { @@ -86,11 +78,11 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { HirLVarAssign { name, rhs } => self.gen_lvar_assign(ctx, name, rhs), HirIVarAssign { name, - idx, rhs, self_ty, + idx, .. - } => self.gen_ivar_assign(ctx, name, idx, rhs, self_ty), + } => self.gen_ivar_assign(ctx, idx, name, rhs, self_ty), HirConstAssign { fullname, rhs } => self.gen_const_assign(ctx, fullname, rhs), HirMethodCall { receiver_expr, @@ -127,10 +119,10 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { arg_exprs, } => self.gen_lambda_invocation(ctx, lambda_expr, arg_exprs, &expr.ty), HirArgRef { idx } => Ok(Some(self.gen_arg_ref(ctx, idx))), - HirLVarRef { name } => Ok(Some(self.gen_lvar_ref(ctx, name))), - HirIVarRef { name, idx, self_ty } => { - Ok(Some(self.gen_ivar_ref(ctx, name, idx, self_ty))) - } + HirLVarRef { name } => Ok(Some(self.gen_lvar_ref(ctx, &expr.ty, name))), + HirIVarRef { + name, self_ty, idx, .. + } => Ok(Some(self.gen_ivar_ref(ctx, idx, name, self_ty, &expr.ty))), HirClassTVarRef { typaram_ref, self_ty, @@ -144,7 +136,7 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { typaram_ref, n_params, } => Ok(Some(self.gen_method_tvar_ref(ctx, typaram_ref, n_params))), - HirConstRef { fullname } => Ok(Some(self.gen_const_ref(fullname))), + HirConstRef { fullname } => Ok(Some(self.gen_const_ref(fullname, &expr.ty))), HirLambdaExpr { name, params, @@ -160,11 +152,11 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { HirStringLiteral { idx } => Ok(Some(self.gen_string_literal(idx))), HirBooleanLiteral { value } => Ok(Some(self.gen_boolean_literal(*value))), - HirLambdaCaptureRef { idx, readonly } => { - Ok(Some(self.gen_lambda_capture_ref(ctx, idx, !readonly))) - } + HirLambdaCaptureRef { idx, readonly } => Ok(Some( + self.gen_lambda_capture_ref(ctx, idx, !readonly, &expr.ty), + )), HirLambdaCaptureWrite { cidx, rhs } => self.gen_lambda_capture_write(ctx, cidx, rhs), - HirBitCast { expr: target } => self.gen_bitcast(ctx, target, &expr.ty), + HirBitCast { expr: target } => self.gen_bitcast(ctx, target), HirClassLiteral { fullname, str_literal_idx, @@ -186,7 +178,7 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { } fn gen_logical_not( - &self, + &'run self, ctx: &mut CodeGenContext<'hir, 'run>, expr: &'hir HirExpression, ) -> Result>> { @@ -200,7 +192,7 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { } fn gen_logical_and( - &self, + &'run self, ctx: &mut CodeGenContext<'hir, 'run>, left: &'hir HirExpression, right: &'hir HirExpression, @@ -229,11 +221,11 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { (&left_value.0, begin_block_end), (&right_value.0, more_block_end), ]); - Ok(Some(SkObj(phi_node.as_basic_value()))) + Ok(Some(SkObj::new(ty::raw("Bool"), phi_node.as_basic_value()))) } fn gen_logical_or( - &self, + &'run self, ctx: &mut CodeGenContext<'hir, 'run>, left: &'hir HirExpression, right: &'hir HirExpression, @@ -262,11 +254,11 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { (&left_value.0, begin_block_end), (&right_value.0, else_block_end), ]); - Ok(Some(SkObj(phi_node.as_basic_value()))) + Ok(Some(SkObj::new(ty::raw("Bool"), phi_node.as_basic_value()))) } fn gen_if_expr( - &self, + &'run self, ctx: &mut CodeGenContext<'hir, 'run>, ty: &TermTy, cond_expr: &'hir HirExpression, @@ -311,13 +303,13 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { let phi_node = self.builder.build_phi(self.llvm_type(ty), "ifResult"); phi_node .add_incoming(&[(&then_val.0, then_block_end), (&else_val.0, else_block_end)]); - Ok(Some(SkObj(phi_node.as_basic_value()))) + Ok(Some(SkObj::new(ty.clone(), phi_node.as_basic_value()))) } } } fn gen_match_expr( - &self, + &'run self, ctx: &mut CodeGenContext<'hir, 'run>, result_ty: &TermTy, cond_assign_expr: &'hir HirExpression, @@ -377,12 +369,15 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { .collect::>() .as_slice(), ); - Ok(Some(SkObj(phi_node.as_basic_value()))) + Ok(Some(SkObj::new( + result_ty.clone(), + phi_node.as_basic_value(), + ))) } } fn gen_match_clause( - &self, + &'run self, ctx: &mut CodeGenContext<'hir, 'run>, clause: &'hir pattern_match::MatchClause, skip_block: inkwell::basic_block::BasicBlock, @@ -412,7 +407,7 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { } fn gen_while_expr( - &self, + &'run self, ctx: &mut CodeGenContext<'hir, 'run>, cond_expr: &'hir HirExpression, body_exprs: &'hir HirExpressions, @@ -437,11 +432,13 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { // WhileEnd: self.builder.position_at_end(*rc2); - Ok(Some(self.gen_const_ref(&toplevel_const("Void")))) + Ok(Some( + self.gen_const_ref(&toplevel_const("Void"), &ty::raw("Void")), + )) } fn gen_break_expr( - &self, + &'run self, ctx: &mut CodeGenContext<'hir, 'run>, from: &HirBreakFrom, ) -> Result>> { @@ -456,9 +453,9 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { HirBreakFrom::Block => { debug_assert!(matches!(ctx.function_origin, FunctionOrigin::Lambda { .. })); // Set @exit_status - let fn_x = self.get_nth_param(&ctx.function, 0); + let fn_x = self.get_nth_param(ty::raw("Fn"), &ctx.function, 0); let i = self.box_int(&self.i64_type.const_int(EXIT_BREAK, false)); - self.build_ivar_store(&fn_x, FN_X_EXIT_STATUS_IDX, i, "@exit_status"); + self.build_ivar_store(fn_x, fn_x::IVAR_EXIT_STATUS_IDX, "@exit_status", i); // Jump to the end of the llvm func self.builder @@ -469,7 +466,7 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { } fn gen_return_expr( - &self, + &'run self, ctx: &mut CodeGenContext<'hir, 'run>, arg: &'hir HirExpression, ) -> Result>> { @@ -483,7 +480,7 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { } fn gen_lvar_assign( - &self, + &'run self, ctx: &mut CodeGenContext<'hir, 'run>, name: &str, rhs: &'hir HirExpression, @@ -498,21 +495,21 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { } fn gen_ivar_assign( - &self, + &'run self, ctx: &mut CodeGenContext<'hir, 'run>, - name: &str, idx: &usize, + name: &str, rhs: &'hir HirExpression, self_ty: &TermTy, ) -> Result>> { let object = self.gen_self_expression(ctx, self_ty); let value = self.gen_expr(ctx, rhs)?.unwrap(); - self.build_ivar_store(&object, *idx, value.clone(), name); + self.build_ivar_store(object, *idx, name, value.clone()); Ok(Some(value)) } fn gen_const_assign( - &self, + &'run self, ctx: &mut CodeGenContext<'hir, 'run>, fullname: &ConstFullname, rhs: &'hir HirExpression, @@ -530,7 +527,7 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { /// Generate method call fn gen_method_call( - &self, + &'run self, ctx: &mut CodeGenContext<'hir, 'run>, method_fullname: &MethodFullname, receiver_expr: &'hir HirExpression, @@ -567,10 +564,12 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { func_type, ); - let result = self.gen_llvm_function_call( - CallableValue::try_from(func).unwrap(), + let result = self.indirect_method_function_call( + ret_ty.clone(), + func, + func_type, receiver_value, - arg_values, + &arg_values, ); if ret_ty.is_never_type() { self.builder.build_unreachable(); @@ -587,17 +586,17 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { /// Retrieve the llvm func fn _get_method_func( - &self, + &'run self, method_name: &MethodFirstname, receiver_ty: &TermTy, receiver_value: SkObj<'run>, func_type: inkwell::types::FunctionType<'ictx>, ) -> inkwell::values::PointerValue<'run> { - let vtable = self.get_vtable_of_obj(receiver_value); let (idx, size) = self.__lookup_vtable(receiver_ty, method_name); - let func_raw = self.build_vtable_ref(vtable, *idx, size); + let vtable = VTableRef::of_sk_obj(self, receiver_value, size); + let func_raw = vtable.get_func(self, *idx); self.builder - .build_bitcast(func_raw, func_type.ptr_type(AddressSpace::Generic), "func") + .build_bitcast(func_raw, func_type.ptr_type(Default::default()), "func") .into_pointer_value() } @@ -615,7 +614,7 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { /// Generate method call via wtable #[allow(clippy::too_many_arguments)] fn gen_module_method_call( - &self, + &'run self, ctx: &mut CodeGenContext<'hir, 'run>, module_fullname: &ModuleFullname, method_name: &MethodFirstname, @@ -656,18 +655,18 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { let func_ptr = self .call_llvm_func(&llvm_func_name("shiika_lookup_wtable"), args, "method") .into_pointer_value(); - let func_type = self - .llvm_func_type(Some(&receiver_expr.ty), &arg_tys, ret_ty) - .ptr_type(AddressSpace::Generic); + let func_type = self.llvm_func_type(Some(&receiver_expr.ty), &arg_tys, ret_ty); let func = self .builder - .build_bitcast(func_ptr, func_type, "as") + .build_bitcast(func_ptr, func_type.ptr_type(Default::default()), "as") .into_pointer_value(); - let result = self.gen_llvm_function_call( - CallableValue::try_from(func).unwrap(), + let result = self.indirect_method_function_call( + ret_ty.clone(), + func, + func_type, receiver_value, - arg_values, + &arg_values, ); if ret_ty.is_never_type() { self.builder.build_unreachable(); @@ -695,7 +694,7 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { /// Generate invocation of a lambda fn gen_lambda_invocation( - &self, + &'run self, ctx: &mut CodeGenContext<'hir, 'run>, lambda_expr: &'hir HirExpression, arg_exprs: &'hir [HirExpression], @@ -705,9 +704,9 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { let n_args = arg_exprs.len(); // Prepare arguments - let mut args = vec![lambda_obj.0.into()]; + let mut args = vec![lambda_obj.clone()]; for e in arg_exprs { - args.push(self.gen_expr(ctx, e)?.unwrap().0.into()); + args.push(self.gen_expr(ctx, e)?.unwrap()); } // Create basic block @@ -721,39 +720,45 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { .append_basic_block(ctx.function, "Invoke_lambda_end"); // Create the type of lambda_xx() - let fn_x_type = self.llvm_type(&ty::raw(&format!("Fn{}", n_args))); + let fn_x_ty = ty::raw(&format!("Fn{}", n_args)); + let fn_x_type = self.llvm_type(&fn_x_ty); let mut arg_types = vec![fn_x_type.into()]; for e in arg_exprs { arg_types.push(self.llvm_type(&e.ty).into()); } let fntype = self.llvm_type(ret_ty).fn_type(&arg_types, false); - let fnptype = fntype.ptr_type(AddressSpace::Generic); + let fnptype = fntype.ptr_type(Default::default()); // Cast `fnptr` to that type - let fnptr = - self.unbox_i8ptr(self.build_ivar_load(lambda_obj.clone(), FN_X_FUNC_IDX, "@func")); + let fnptr = self.unbox_i8ptr(self.build_ivar_load( + lambda_obj.clone(), + ty::raw("Shiika::Internal::Ptr"), + skc_corelib::fn_x::IVAR_FUNC_IDX, + "@func", + )); let func = self .builder .build_bitcast(fnptr.0, fnptype, "") .into_pointer_value(); // Generate function call - let result = self - .builder - .build_call(CallableValue::try_from(func).unwrap(), &args, "result") - .try_as_basic_value() - .left() - .unwrap(); + let result = self.indirect_function_call(ret_ty.clone(), func, fntype, args); // Check `break` in block if ret_ty.is_void_type() { let broke_block = self.context.append_basic_block(ctx.function, "Broke"); - let exit_status = - self.build_ivar_load(lambda_obj, FN_X_EXIT_STATUS_IDX, "@exit_status"); - let eq = self.gen_method_func_call( + let exit_status = self.build_ivar_load( + lambda_obj, + ty::raw("Int"), + skc_corelib::fn_x::IVAR_EXIT_STATUS_IDX, + "@exit_status", + ); + let eq = self.call_method_func( &method_fullname_raw("Int", "=="), exit_status, - vec![self.box_int(&self.i64_type.const_int(EXIT_BREAK, false))], + &vec![self.box_int(&self.i64_type.const_int(EXIT_BREAK, false))], + ty::raw("Bool"), + "eq", ); self.gen_conditional_branch(eq, broke_block, end_block); @@ -761,9 +766,9 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { self.builder.position_at_end(broke_block); if matches!(ctx.function_origin, FunctionOrigin::Lambda { .. }) { // Set @exit_status - let fn_x = self.get_nth_param(&ctx.function, 0); + let fn_x = self.get_nth_param(ty::raw("Fn"), &ctx.function, 0); let i = self.box_int(&self.i64_type.const_int(EXIT_BREAK, false)); - self.build_ivar_store(&fn_x, FN_X_EXIT_STATUS_IDX, i, "@exit_status"); + self.build_ivar_store(fn_x, fn_x::IVAR_EXIT_STATUS_IDX, "@exit_status", i); } self.builder .build_unconditional_branch(*ctx.current_func_end); @@ -772,91 +777,118 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { self.builder.build_unconditional_branch(end_block); } self.builder.position_at_end(end_block); - Ok(Some(SkObj(result))) - } - - /// Generate llvm function call - fn gen_method_func_call( - &self, - method_fullname: &MethodFullname, - receiver_value: SkObj<'run>, - arg_values: Vec>, - ) -> SkObj<'run> { - self.gen_llvm_func_call( - &method_func_name(method_fullname), - receiver_value, - arg_values, - ) + Ok(Some(result)) } - /// Generate llvm function call - // REFACTOR: make this public and make `receiver_value` optional - fn gen_llvm_func_call( - &self, - func_name: &LlvmFuncName, + // Call a method llvm function via function pointer. + fn indirect_method_function_call( + &'run self, + result_ty: TermTy, + function: PointerValue<'run>, + func_type: FunctionType<'ictx>, receiver_value: SkObj<'run>, - arg_values: Vec>, + arg_values: &[SkObj<'run>], ) -> SkObj<'run> { - let function = self.get_llvm_func(func_name); - self.gen_llvm_function_call(function.into(), receiver_value, arg_values) + let mut args = arg_values.to_vec(); + args.insert(0, receiver_value); + self.indirect_function_call(result_ty, function, func_type, args) } - pub(super) fn gen_llvm_function_call( - &self, - function: CallableValue<'run>, - receiver_value: SkObj<'run>, + // Call a llvm function via function pointer. + fn indirect_function_call( + &'run self, + result_ty: TermTy, + function: PointerValue<'run>, + func_type: FunctionType<'ictx>, arg_values: Vec>, ) -> SkObj<'run> { - let mut llvm_args = vec![receiver_value.0.into()]; - llvm_args.append(&mut arg_values.iter().map(|x| x.0.into()).collect()); + let llvm_args = arg_values.iter().map(|x| x.0.into()).collect::>(); match self .builder - .build_call(function, &llvm_args, "result") + .build_indirect_call(func_type, function, &llvm_args, "result") .try_as_basic_value() .left() { - Some(result_value) => SkObj(result_value), - None => self.gen_const_ref(&toplevel_const("Void")), + Some(result_value) => SkObj::new(result_ty, result_value), + None => self.gen_const_ref(&toplevel_const("Void"), &ty::raw("Void")), } } /// Generate IR for HirArgRef. - fn gen_arg_ref(&self, ctx: &mut CodeGenContext<'hir, 'run>, idx: &usize) -> SkObj<'run> { + fn gen_arg_ref(&'run self, ctx: &mut CodeGenContext<'hir, 'run>, idx: &usize) -> SkObj<'run> { + self._llvm_function_arg_ref(ctx, idx, false) + } + + fn gen_tyarg_ref( + &'run self, + ctx: &mut CodeGenContext<'hir, 'run>, + n_params: &usize, + idx: &usize, + ) -> SkObj<'run> { + self._llvm_function_arg_ref(ctx, &(n_params + idx), true) + } + + fn _llvm_function_arg_ref( + &'run self, + ctx: &mut CodeGenContext<'hir, 'run>, + idx: &usize, + is_tyarg: bool, + ) -> SkObj<'run> { match ctx.function_origin { - FunctionOrigin::Method => { - SkObj(ctx.function.get_nth_param((*idx as u32) + 1).unwrap()) // +1 for the first %self + FunctionOrigin::Method { params } => { + let ty = if is_tyarg { + ty::raw("Class") + } else { + params[*idx].ty.clone() + }; + SkObj::new(ty, ctx.function.get_nth_param((*idx as u32) + 1).unwrap()) + // +1 for the first %self } - FunctionOrigin::Lambda { .. } => { + FunctionOrigin::Lambda { params, .. } => { + let ty = if is_tyarg { + ty::raw("Class") + } else { + params[*idx].ty.clone() + }; // +1 for the first %self - let obj = self.get_nth_param(&ctx.function, *idx + 1); + let obj = self.get_nth_param(ty.clone(), &ctx.function, *idx + 1); // Bitcast is needed because lambda params are always `%Object*` - self.bitcast(obj, &ctx.function_params.unwrap()[*idx].ty, "value") + self.bitcast(obj, &ty, "value") } _ => panic!("[BUG] arg ref in invalid place"), } } - fn gen_lvar_ref(&self, ctx: &mut CodeGenContext<'hir, 'run>, name: &str) -> SkObj<'run> { + fn gen_lvar_ref( + &'run self, + ctx: &mut CodeGenContext<'hir, 'run>, + ty: &TermTy, + name: &str, + ) -> SkObj<'run> { let ptr = ctx .lvars .get(name) .unwrap_or_else(|| panic!("[BUG] lvar `{}' not found in ctx.lvars", name)); - SkObj(self.builder.build_load(*ptr, name)) + SkObj::new( + ty.clone(), + self.builder.build_load(self.llvm_type(ty), *ptr, name), + ) } fn gen_ivar_ref( - &self, + &'run self, ctx: &mut CodeGenContext<'hir, 'run>, - name: &str, idx: &usize, + name: &str, self_ty: &TermTy, + ty: &TermTy, ) -> SkObj<'run> { let object = self.gen_self_expression(ctx, self_ty); - self.build_ivar_load(object, *idx, name) + self.build_ivar_load(object, ty.clone(), *idx, name) } fn gen_class_tvar_ref( - &self, + &'run self, ctx: &mut CodeGenContext<'hir, 'run>, typaram_ref: &TyParamRef, self_ty: &TermTy, @@ -871,48 +903,49 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { ) } - fn _get_nth_tyarg_of_self(&self, self_obj: SkObj<'run>, idx: usize) -> SkObj<'run> { + fn _get_nth_tyarg_of_self(&'run self, self_obj: SkObj<'run>, idx: usize) -> SkObj<'run> { let cls_obj = self.get_class_of_obj(self_obj); - self.gen_method_func_call( + self.call_method_func( &method_fullname_raw("Class", "_type_argument"), self.bitcast(cls_obj.as_sk_obj(), &ty::raw("Class"), "as"), - vec![self.gen_decimal_literal(idx as i64)], + &vec![self.gen_decimal_literal(idx as i64)], + ty::raw("Class"), + "tyarg", ) } fn gen_method_tvar_ref( - &self, + &'run self, ctx: &mut CodeGenContext<'hir, 'run>, typaram_ref: &TyParamRef, n_params: &usize, ) -> SkObj<'run> { debug_assert!(typaram_ref.kind == TyParamKind::Method); - self._get_nth_method_tyarg(ctx, n_params, typaram_ref.idx) - } - - fn _get_nth_method_tyarg( - &self, - ctx: &mut CodeGenContext<'hir, 'run>, - n_params: &usize, - n: usize, - ) -> SkObj<'run> { let idx = 1 + // %self *n_params + - n; - SkObj(ctx.function.get_nth_param(idx as u32).unwrap()) + typaram_ref.idx; + SkObj::new( + typaram_ref.to_term_ty(), + ctx.function.get_nth_param(idx as u32).unwrap(), + ) } - pub fn gen_const_ref(&self, fullname: &ConstFullname) -> SkObj<'run> { + pub fn gen_const_ref(&'run self, fullname: &ConstFullname, ty: &TermTy) -> SkObj<'run> { let name = llvm_const_name(fullname); + let llvm_type = self.llvm_type(ty); let ptr = self .module .get_global(&name) .unwrap_or_else(|| panic!("[BUG] global for Constant `{}' not created", fullname)); - SkObj(self.builder.build_load(ptr.as_pointer_value(), &name)) + SkObj::new( + ty.clone(), + self.builder + .build_load(llvm_type, ptr.as_pointer_value(), &name), + ) } fn gen_lambda_expr( - &self, + &'run self, ctx: &mut CodeGenContext<'hir, 'run>, name: &str, params: &[MethodParam], @@ -929,7 +962,7 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { // eg. Fn1.new(fnptr, the_self, captures) let cls_name = format!("Fn{}", params.len()); - let meta = self.gen_const_ref(&toplevel_const(&cls_name)); + let meta = self.gen_const_ref(&toplevel_const(&cls_name), &ty::meta(&cls_name)); let fnptr = self .get_llvm_func(&func_name) .as_global_value() @@ -939,15 +972,17 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { let the_self = self.gen_self_expression(ctx, &ty::raw("Object")); let captured = self._gen_lambda_captures(ctx, name, captures); let arg_values = vec![sk_ptr, the_self, captured.boxed(self)]; - self.gen_method_func_call( + self.call_method_func( &method_fullname(metaclass_fullname(cls_name).into(), "new"), meta, - arg_values, + &arg_values, + fn_x_type.clone(), + "lambda", ) } fn _gen_lambda_captures( - &self, + &'run self, ctx: &mut CodeGenContext<'hir, 'run>, name: &str, captures: &'hir [HirLambdaCapture], @@ -960,10 +995,10 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { let mut item = match &cap.detail { HirLambdaCaptureDetail::CaptureLVar { name } => { if cap.readonly { - self.gen_lvar_ref(ctx, name) + self.gen_lvar_ref(ctx, &cap.ty, name) } else { // Captured by pointer to be reassigned - SkObj(ctx.lvars.get(name).unwrap().as_basic_value_enum()) + SkObj::new(cap.ty.clone(), *ctx.lvars.get(name).unwrap()) } } HirLambdaCaptureDetail::CaptureArg { idx } => { @@ -972,18 +1007,17 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { } HirLambdaCaptureDetail::CaptureFwd { cidx, .. } => { let deref = false; - self.gen_lambda_capture_ref(ctx, cidx, deref) + self.gen_lambda_capture_ref(ctx, cidx, deref, &cap.ty) } HirLambdaCaptureDetail::CaptureMethodTyArg { idx, n_params } => { // Method-wise type arguments are passed as llvm function parameter. - self.gen_arg_ref(ctx, &(n_params + idx)) + self.gen_tyarg_ref(ctx, n_params, idx) } }; if cap.upcast_needed { - let ty = struct_type.get_field_type_at_index(i as u32).unwrap(); - item = SkObj(self.builder.build_bitcast(item.0, ty, "upcast_needed")); + item = self.bitcast(item, &cap.ty, "upcast_needed"); } - lambda_capture.store(self, i, item.0); + lambda_capture.store(self, i, item); } lambda_capture } @@ -992,19 +1026,24 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { /// `ty` is needed for bitcast (because the type information is lost /// in a lambda) fn gen_self_expression( - &self, + &'run self, ctx: &mut CodeGenContext<'hir, 'run>, ty: &TermTy, ) -> SkObj<'run> { - let the_main = if ctx.function.get_name().to_str().unwrap() == "user_main" { + let the_self = if ctx.function.get_name().to_str().unwrap() == "user_main" { self.the_main.clone().unwrap() } else if matches!(ctx.function_origin, FunctionOrigin::Lambda { .. }) { - let fn_x = self.get_nth_param(&ctx.function, 0); - self.build_ivar_load(fn_x, FN_X_THE_SELF_IDX, "@obj") + let fn_x = self.get_nth_param(ty::raw("Fn"), &ctx.function, 0); + self.build_ivar_load( + fn_x, + ty::raw("Object"), + fn_x::IVAR_THE_SELF_IDX, + "@the_self", + ) } else { - self.get_nth_param(&ctx.function, 0) + self.get_nth_param(ty.clone(), &ctx.function, 0) }; - self.bitcast(the_main, ty, "the_main") + self.bitcast(the_self, ty, "the_main") } fn gen_float_literal(&self, value: f64) -> SkObj<'run> { @@ -1016,7 +1055,7 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { } /// Create a string object - fn gen_string_literal(&self, idx: &usize) -> SkObj<'run> { + fn gen_string_literal(&'run self, idx: &usize) -> SkObj<'run> { let byte_ary = self .module .get_global(&format!("str_{}", idx)) @@ -1028,14 +1067,17 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { let bytesize = self .i64_type .const_int(self.str_literals[*idx].len() as u64, false); - SkObj(self.call_llvm_func( - &llvm_func_name("gen_literal_string"), - &[i8ptr.into(), bytesize.into()], - "sk_str", - )) + SkObj::new( + ty::raw("String"), + self.call_llvm_func( + &llvm_func_name("gen_literal_string"), + &[i8ptr.into(), bytesize.into()], + "sk_str", + ), + ) } - fn gen_boolean_literal(&self, value: bool) -> SkObj<'run> { + fn gen_boolean_literal(&'run self, value: bool) -> SkObj<'run> { let n = if value { 1 } else { 0 }; let i = self.i1_type.const_int(n, false); self.box_bool(i) @@ -1043,7 +1085,7 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { /// Generate conditional branch by Shiika Bool fn gen_conditional_branch( - &self, + &'run self, cond: SkObj, then_block: inkwell::basic_block::BasicBlock, else_block: inkwell::basic_block::BasicBlock, @@ -1059,10 +1101,11 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { /// Get an object from `captures` fn gen_lambda_capture_ref( - &self, + &'run self, ctx: &mut CodeGenContext<'hir, 'run>, idx_in_captures: &usize, deref: bool, + ty: &TermTy, ) -> SkObj<'run> { let block = self .context @@ -1071,16 +1114,7 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { self.builder.position_at_end(block); let captures = self._gen_get_lambda_captures(ctx); - let item = captures.load(self, *idx_in_captures); - let ret = if deref { - // `item` is a pointer - let ptr = item.into_pointer_value(); - SkObj(self.builder.build_load(ptr, "ret")) - } else { - // `item` is a value - SkObj(item) - }; - + let ret = captures.get_value(self, *idx_in_captures, ty, deref); let block = self.context.append_basic_block( ctx.function, &format!("CaptureRef_{}th_end", idx_in_captures), @@ -1091,7 +1125,7 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { } fn gen_lambda_capture_write( - &self, + &'run self, ctx: &mut CodeGenContext<'hir, 'run>, idx_in_captures: &usize, rhs: &'hir HirExpression, @@ -1104,7 +1138,7 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { let captures = self._gen_get_lambda_captures(ctx); let value = self.gen_expr(ctx, rhs)?.unwrap(); - captures.reassign(self, *idx_in_captures, value.clone()); + captures.reassign(self, *idx_in_captures, value.clone(), &rhs.ty); let block = self.context.append_basic_block( ctx.function, @@ -1116,37 +1150,33 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { } fn _gen_get_lambda_captures( - &self, + &'run self, ctx: &mut CodeGenContext<'hir, 'run>, ) -> LambdaCapture<'run> { - let fn_x = self.get_nth_param(&ctx.function, 0); - let boxed = self.build_ivar_load(fn_x, FN_X_CAPTURES_IDX, "@captures"); + let fn_x = self.get_nth_param(ty::raw("Fn"), &ctx.function, 0); + let boxed = self.build_ivar_load( + fn_x, + ty::raw("Shiika::Internal::Ptr"), + fn_x::IVAR_CAPTURES_IDX, + "@captures", + ); LambdaCapture::from_boxed(self, boxed, ctx.lambda_name().unwrap()) } fn gen_bitcast( - &self, + &'run self, ctx: &mut CodeGenContext<'hir, 'run>, expr: &'hir HirExpression, - ty: &TermTy, ) -> Result>> { - if let Some(obj) = self.gen_expr(ctx, expr)? { - if expr.ty.equals_to(ty) { - // No bitcast needed - Ok(Some(obj)) - } else { - Ok(Some(self.bitcast(obj, ty, "as"))) - } - } else { - Ok(None) - } + // Just compile the expr (nothing to do more in the runtime) + self.gen_expr(ctx, expr) } /// Create a class object /// ("class literal" is a special Hir that does not appear directly /// on a source text.) fn gen_class_literal( - &self, + &'run self, fullname: &TypeFullname, clsobj_ty: &TermTy, str_literal_idx: &usize, @@ -1159,104 +1189,96 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { self.gen_the_metaclass(str_literal_idx) } else { // Create metaclass object (eg. `#`) with `Metaclass.new` - let the_metaclass = self.gen_const_ref(&toplevel_const("Metaclass")); + let the_metaclass = + self.gen_const_ref(&toplevel_const("Metaclass"), &ty::raw("Metaclass")); let receiver = self.null_ptr(&ty::meta("Metaclass")); let vtable = self .get_vtable_of_class(&class_fullname("Metaclass")) - .as_sk_obj(); - let wtable = SkObj(self.i8ptr_type.const_null().as_basic_value_enum()); - let metacls_obj = self.gen_method_func_call( + .as_object_ptr(self); + let wtable = SkObj::nullptr(self); + let metacls_obj = self.call_method_func( &method_fullname_raw("Metaclass", "_new"), receiver, - vec![ + &vec![ self.gen_string_literal(str_literal_idx), - self.bitcast(vtable, &ty::raw("Object"), "as"), - self.bitcast(wtable, &ty::raw("Object"), "as"), + vtable, + wtable, self.bitcast(the_metaclass, &ty::raw("Metaclass"), "as"), self.null_ptr(&ty::raw("Class")), ], + ty::raw("Metaclass"), + "meta", ); // Create the class object (eg. `#`, which is the value of `::Int`) let receiver = self.null_ptr(&ty::meta("Class")); - let vtable = self.get_vtable_of_class(&fullname.meta_name()).as_sk_obj(); - let wtable = SkObj(self.i8ptr_type.const_null().as_basic_value_enum()); - let cls = self.gen_method_func_call( + let vtable = self + .get_vtable_of_class(&fullname.meta_name()) + .as_object_ptr(self); + let wtable = SkObj::nullptr(self); + let cls = self.call_method_func( &method_fullname(metaclass_fullname("Class").into(), "_new"), receiver, - vec![ + &vec![ self.gen_string_literal(str_literal_idx), - self.bitcast(vtable, &ty::raw("Object"), "as"), - self.bitcast(wtable, &ty::raw("Object"), "as"), + vtable, + wtable, self.bitcast(metacls_obj, &ty::raw("Metaclass"), "as"), self.null_ptr(&ty::raw("Class")), ], + ty::raw("Class"), + "cls", ); if *includes_modules { let fname = wtable::insert_wtable_func_name(&fullname.clone().to_class_fullname()); self.call_void_llvm_func(&llvm_func_name(fname), &[cls.0.into()], "_"); } - self.call_class_level_initialize(&cls, initialize_name, init_cls_name); + self.call_class_level_initialize(cls.clone(), initialize_name, init_cls_name); self.bitcast(cls, clsobj_ty, "as") } } fn call_class_level_initialize( - &self, - receiver: &SkObj, + &'run self, + receiver: SkObj, initialize_name: &MethodFullname, init_cls_name: &ClassFullname, ) { - let ances_type = self - .llvm_struct_types - .get(&init_cls_name.to_type_fullname()) - .expect("ances_type not found") - .ptr_type(inkwell::AddressSpace::Generic); - let addr = SkObj(self.builder.build_bitcast( - receiver.clone().0, - ances_type, - "obj_as_super", - )); + let addr = self.bitcast(receiver, &init_cls_name.to_ty(), "obj_as_super"); let args = vec![addr.0.into()]; let initialize = self.get_llvm_func(&method_func_name(initialize_name)); - self.builder.build_call(initialize, &args, ""); + self.builder.build_direct_call(initialize, &args, ""); } /// Create the metaclass object `Metaclass` - fn gen_the_metaclass(&self, str_literal_idx: &usize) -> SkObj<'run> { + fn gen_the_metaclass(&'run self, str_literal_idx: &usize) -> SkObj<'run> { // We need a trick here to achieve `Metaclass.class == Metaclass`. - let null = self.i8ptr_type.const_null().as_basic_value_enum(); - let cls_obj = self._allocate_sk_obj( - &class_fullname("Metaclass"), - "the_metaclass", - SkClassObj(null), - ); + let null = SkClassObj::nullptr(self); + let cls_obj = self._allocate_sk_obj(&class_fullname("Metaclass"), null); self.build_ivar_store( - &cls_obj, + cls_obj.clone(), skc_corelib::class::IVAR_NAME_IDX, - self.gen_string_literal(str_literal_idx), "@name", + self.gen_string_literal(str_literal_idx), ); self.set_class_of_obj(&cls_obj, SkClassObj(cls_obj.0)); cls_obj } /// Returns a special value (currently a nullptr) that denotes using the default argument value. - fn gen_default_expr(&self, ty: &TermTy) -> SkObj<'run> { + fn gen_default_expr(&'run self, ty: &TermTy) -> SkObj<'run> { self.null_ptr(ty) } /// Returns true if `expr` evaluates to a special value (currently a nullptr) that denotes using the default argument value. fn gen_is_omitted_value( - &self, + &'run self, ctx: &mut CodeGenContext<'hir, 'run>, expr: &'hir HirExpression, ) -> Result>> { let v = self.gen_expr(ctx, expr)?.unwrap(); - let i1 = self - .builder - .build_is_null(v.0.into_pointer_value(), "omitted"); + let i1 = self.builder.build_is_null(v.0, "omitted"); Ok(Some(self.box_bool(i1))) } } diff --git a/lib/skc_codegen/src/lambda.rs b/lib/skc_codegen/src/lambda.rs index 8c76ebe4..21135e96 100644 --- a/lib/skc_codegen/src/lambda.rs +++ b/lib/skc_codegen/src/lambda.rs @@ -5,6 +5,7 @@ use anyhow::Result; use either::Either::*; use inkwell::types::AnyType; use inkwell::types::BasicType; +use inkwell::values::BasicValue; use shiika_core::ty::*; use skc_hir::HirExpressionBase::*; use skc_hir::*; @@ -26,7 +27,7 @@ impl<'run> LambdaCapture<'run> { } pub fn struct_ptr_type<'ictx>(gen: &CodeGen, name: &str) -> inkwell::types::PointerType<'ictx> { - Self::get_struct_type(gen, name).ptr_type(inkwell::AddressSpace::Generic) + Self::get_struct_type(gen, name).ptr_type(Default::default()) } fn new( @@ -75,10 +76,16 @@ impl<'run> LambdaCapture<'run> { } /// Store `value` at the given index - pub fn store(&self, gen: &CodeGen, idx: usize, value: inkwell::values::BasicValueEnum<'run>) { + pub fn store(&self, gen: &CodeGen, idx: usize, value: SkObj<'run>) { + self.store_raw(gen, idx, value.0.as_basic_value_enum()); + } + + /// Store `value` at the given index + fn store_raw(&self, gen: &CodeGen, idx: usize, value: inkwell::values::BasicValueEnum<'run>) { debug_assert!(self.store_type_matches(gen, idx, value)); gen.build_llvm_struct_set( + &self.struct_type(gen), self.to_struct_ptr(), idx, value, @@ -109,29 +116,50 @@ impl<'run> LambdaCapture<'run> { } } - /// Load the value at the given index - pub fn load( + /// Get the (possibly indirectly) stored value. + pub fn get_value( &self, gen: &CodeGen<'_, 'run, '_>, idx: usize, - ) -> inkwell::values::BasicValueEnum<'run> { - gen.build_llvm_struct_ref(self.to_struct_ptr(), idx, "load") + ty: &TermTy, + deref: bool, + ) -> SkObj<'run> { + let v = if deref { + let addr = gen + .build_llvm_struct_ref_raw( + &self.struct_type(gen), + self.to_struct_ptr(), + gen.i8ptr_type.clone().as_basic_type_enum(), + idx, + "load", + ) + .into_pointer_value(); + let pointee_ty = gen.llvm_type(ty).as_basic_type_enum(); + gen.builder.build_load(pointee_ty, addr, "deref") + } else { + gen.build_llvm_struct_ref( + &self.struct_type(gen), + self.to_struct_ptr(), + ty, + idx, + "load", + ) + }; + SkObj::new(ty.clone(), v) } /// Given there is a pointer stored at `idx`, update its value. - pub fn reassign(&self, gen: &CodeGen<'_, 'run, '_>, idx: usize, value: SkObj) { - // eg. `%Int**` - let ptr_ty = self - .struct_type(gen) - .get_field_type_at_index(idx as u32) - .unwrap() - .into_pointer_type(); - // eg. `%Int*` - let ty = ptr_ty.get_element_type().into_pointer_type(); - let upcast = gen.builder.build_bitcast(value.0, ty, "upcast"); - - let ptr = self.load(gen, idx).into_pointer_value(); - gen.builder.build_store(ptr, upcast); + pub fn reassign(&self, gen: &CodeGen<'_, 'run, '_>, idx: usize, value: SkObj, ty: &TermTy) { + let ptr = gen + .build_llvm_struct_ref( + &self.struct_type(gen), + self.to_struct_ptr(), + ty, + idx, + "load", + ) + .into_pointer_value(); + gen.builder.build_store(ptr, value.0); } } @@ -439,7 +467,7 @@ impl<'hir: 'ictx, 'run, 'ictx: 'run> CodeGen<'hir, 'run, 'ictx> { // PERF: not needed to be by-ref when the variable is declared with // `var` but not reassigned from closure. self.llvm_type(&cap.ty) - .ptr_type(inkwell::AddressSpace::Generic) + .ptr_type(Default::default()) .as_basic_type_enum() } } diff --git a/lib/skc_codegen/src/lib.rs b/lib/skc_codegen/src/lib.rs index ca3ade69..692d00ed 100644 --- a/lib/skc_codegen/src/lib.rs +++ b/lib/skc_codegen/src/lib.rs @@ -4,6 +4,7 @@ mod gen_exprs; mod lambda; mod utils; pub mod values; +mod vtable; mod wtable; use crate::code_gen_context::*; use crate::utils::*; @@ -12,7 +13,6 @@ use anyhow::{anyhow, Result}; use either::*; use inkwell::types::*; use inkwell::values::*; -use inkwell::AddressSpace; use shiika_core::{names::*, ty, ty::*}; use skc_hir::pattern_match::MatchClause; use skc_hir::*; @@ -92,7 +92,7 @@ impl<'hir: 'ictx, 'run, 'ictx: 'run> CodeGen<'hir, 'run, 'ictx> { builder, i1_type: context.bool_type(), i8_type: context.i8_type(), - i8ptr_type: context.i8_type().ptr_type(AddressSpace::Generic), + i8ptr_type: context.i8_type().ptr_type(Default::default()), i32_type: context.i32_type(), i64_type: context.i64_type(), f64_type: context.f64_type(), @@ -284,7 +284,7 @@ impl<'hir: 'ictx, 'run, 'ictx: 'run> CodeGen<'hir, 'run, 'ictx> { self.module .add_function(&format!("{}_init_constants", s), fn_type, None); let func = self.get_llvm_func(&llvm_func_name(format!("{}_init_constants", s))); - self.builder.build_call(func, &[], ""); + self.builder.build_direct_call(func, &[], ""); } } @@ -297,7 +297,7 @@ impl<'hir: 'ictx, 'run, 'ictx: 'run> CodeGen<'hir, 'run, 'ictx> { // These builtin classes must be created first for name in &basic_classes { let func = self.get_llvm_func(&llvm_func_name(const_initialize_func_name(name))); - self.builder.build_call(func, &[], ""); + self.builder.build_direct_call(func, &[], ""); } } for expr in const_inits { @@ -306,7 +306,7 @@ impl<'hir: 'ictx, 'run, 'ictx: 'run> CodeGen<'hir, 'run, 'ictx> { if !basic_classes.iter().any(|s| s.0 == fullname.0) { let func = self .get_llvm_func(&llvm_func_name(const_initialize_func_name(fullname))); - self.builder.build_call(func, &[], ""); + self.builder.build_direct_call(func, &[], ""); } } _ => panic!("gen_init_constants: Not a HirConstAssign"), @@ -338,14 +338,14 @@ impl<'hir: 'ictx, 'run, 'ictx: 'run> CodeGen<'hir, 'run, 'ictx> { let create_main_block = self.context.append_basic_block(function, "CreateMain"); self.builder.build_unconditional_branch(create_main_block); self.builder.position_at_end(create_main_block); - self.the_main = Some(self.allocate_sk_obj(&class_fullname("Object"), "main")); + self.the_main = Some(self.allocate_sk_obj(&class_fullname("Object"))); // UserMain: let user_main_block = self.context.append_basic_block(function, "UserMain"); self.builder.build_unconditional_branch(user_main_block); self.builder.position_at_end(user_main_block); - let (end_block, mut ctx) = self.new_ctx(FunctionOrigin::Other, function, None, lvar_ptrs); + let (end_block, mut ctx) = self.new_ctx(FunctionOrigin::Other, function, lvar_ptrs); self.gen_exprs(&mut ctx, main_exprs)?; self.builder.build_unconditional_branch(*end_block); self.builder.position_at_end(*end_block); @@ -363,13 +363,13 @@ impl<'hir: 'ictx, 'run, 'ictx: 'run> CodeGen<'hir, 'run, 'ictx> { // Call GC_init let func = self.get_llvm_func(&llvm_func_name("GC_init")); - self.builder.build_call(func, &[], ""); + self.builder.build_direct_call(func, &[], ""); // Call init_constants, user_main let func = self.get_llvm_func(&llvm_func_name("main_init_constants")); - self.builder.build_call(func, &[], ""); + self.builder.build_direct_call(func, &[], ""); let func = self.get_llvm_func(&llvm_func_name("user_main")); - self.builder.build_call(func, &[], ""); + self.builder.build_direct_call(func, &[], ""); // ret i32 0 self.builder @@ -479,7 +479,7 @@ impl<'hir: 'ictx, 'run, 'ictx: 'run> CodeGen<'hir, 'run, 'ictx> { let basic_block = self.context.append_basic_block(function, ""); self.builder.position_at_end(basic_block); let (end_block, mut ctx) = - self.new_ctx(FunctionOrigin::Other, function, None, HashMap::new()); + self.new_ctx(FunctionOrigin::Other, function, HashMap::new()); self.gen_expr(&mut ctx, expr)?; self.builder.build_unconditional_branch(*end_block); self.builder.position_at_end(*end_block); @@ -731,8 +731,7 @@ impl<'hir: 'ictx, 'run, 'ictx: 'run> CodeGen<'hir, 'run, 'ictx> { Left(method_body) => match method_body { SkMethodBody::Normal { exprs } => self.gen_shiika_function_body( function, - None, - FunctionOrigin::Method, + FunctionOrigin::Method { params }, ret_ty, exprs, lvar_ptrs, @@ -752,25 +751,34 @@ impl<'hir: 'ictx, 'run, 'ictx: 'run> CodeGen<'hir, 'run, 'ictx> { *arity, *const_is_obj, ), - SkMethodBody::Getter { idx, name } => { - let this = self.get_nth_param(&function, 0); - let val = self.build_ivar_load(this, *idx, name); + SkMethodBody::Getter { + name, + self_ty, + idx, + ty, + } => { + let this = self.get_nth_param(self_ty.clone(), &function, 0); + let val = self.build_ivar_load(this, ty.clone(), *idx, name); self.build_return(&val); } - SkMethodBody::Setter { idx, name } => { - let this = self.get_nth_param(&function, 0); - let val = self.get_nth_param(&function, 1); - self.build_ivar_store(&this, *idx, val, name); - let val = self.get_nth_param(&function, 1); + SkMethodBody::Setter { + name, + ty, + self_ty, + idx, + } => { + let this = self.get_nth_param(self_ty.clone(), &function, 0); + let val = self.get_nth_param(ty.clone(), &function, 1); + self.build_ivar_store(this, *idx, name, val.clone()); self.build_return(&val); } }, Right(exprs) => { self.gen_shiika_function_body( function, - Some(params), FunctionOrigin::Lambda { name: lambda_name.unwrap(), + params, }, ret_ty, exprs, @@ -798,9 +806,7 @@ impl<'hir: 'ictx, 'run, 'ictx: 'run> CodeGen<'hir, 'run, 'ictx> { let obj_ty = self.llvm_type(ty); if *captured { // Allocate memory on heap in case it lives longer than the method call. - let ptrptr = self - .allocate_llvm_obj(&obj_ty, "ptrptr") - .into_pointer_value(); + let ptrptr = self.allocate_llvm_obj(&obj_ty).into_pointer_value(); lvar_ptrs.insert(name.to_string(), ptrptr); } else { let ptr = self.builder.build_alloca(obj_ty, name); @@ -817,13 +823,12 @@ impl<'hir: 'ictx, 'run, 'ictx: 'run> CodeGen<'hir, 'run, 'ictx> { fn gen_shiika_function_body( &self, function: inkwell::values::FunctionValue<'run>, - function_params: Option<&'hir [MethodParam]>, - function_origin: FunctionOrigin, + function_origin: FunctionOrigin<'hir>, ret_ty: &TermTy, exprs: &'hir HirExpressions, lvars: HashMap>, ) -> Result<()> { - let (end_block, mut ctx) = self.new_ctx(function_origin, function, function_params, lvars); + let (end_block, mut ctx) = self.new_ctx(function_origin, function, lvars); let (last_value, last_value_block) = if let Some(v) = self.gen_exprs(&mut ctx, exprs)? { let b = self.context.append_basic_block(ctx.function, "Ret"); self.builder.build_unconditional_branch(b); @@ -890,8 +895,8 @@ impl<'hir: 'ictx, 'run, 'ictx: 'run> CodeGen<'hir, 'run, 'ictx> { _const_is_obj: bool, ) { // Allocate memory and set .class (which is the receiver of .new) - let class_obj = SkClassObj(llvm_func_args[0]); - let obj = self._allocate_sk_obj(class_fullname, "addr", class_obj); + let class_obj = SkClassObj(llvm_func_args[0].into_pointer_value()); + let obj = self._allocate_sk_obj(class_fullname, class_obj); // Call initialize let addr = if init_cls_name == class_fullname { @@ -903,8 +908,9 @@ impl<'hir: 'ictx, 'run, 'ictx: 'run> CodeGen<'hir, 'run, 'ictx> { .llvm_struct_types .get(&init_cls_name.to_type_fullname()) .expect("ances_type not found") - .ptr_type(inkwell::AddressSpace::Generic); - SkObj( + .ptr_type(Default::default()); + SkObj::new( + init_cls_name.to_ty(), self.builder .build_bitcast(obj.clone().0, ances_type, "obj_as_super"), ) @@ -919,7 +925,7 @@ impl<'hir: 'ictx, 'run, 'ictx: 'run> CodeGen<'hir, 'run, 'ictx> { }) .collect::>(); let initialize = self.get_llvm_func(&method_func_name(initialize_name)); - self.builder.build_call(initialize, &args, ""); + self.builder.build_direct_call(initialize, &args, ""); self.build_return(&obj); } @@ -927,9 +933,8 @@ impl<'hir: 'ictx, 'run, 'ictx: 'run> CodeGen<'hir, 'run, 'ictx> { /// Create a CodeGenContext fn new_ctx( &self, - origin: FunctionOrigin, + origin: FunctionOrigin<'hir>, function: inkwell::values::FunctionValue<'run>, - function_params: Option<&'hir [MethodParam]>, lvars: HashMap>, ) -> ( Rc>, @@ -938,7 +943,7 @@ impl<'hir: 'ictx, 'run, 'ictx: 'run> CodeGen<'hir, 'run, 'ictx> { let end_block = self.context.append_basic_block(function, "End"); let ref_end_block1 = Rc::new(end_block); let ref_end_block2 = Rc::clone(&ref_end_block1); - let ctx = CodeGenContext::new(function, ref_end_block1, origin, function_params, lvars); + let ctx = CodeGenContext::new(function, ref_end_block1, origin, lvars); (ref_end_block2, ctx) } } diff --git a/lib/skc_codegen/src/utils.rs b/lib/skc_codegen/src/utils.rs index 1e8b0a76..0eb7aca2 100644 --- a/lib/skc_codegen/src/utils.rs +++ b/lib/skc_codegen/src/utils.rs @@ -1,15 +1,15 @@ use crate::values::*; +use crate::vtable::OpaqueVTableRef; use crate::CodeGen; use inkwell::types::*; use inkwell::values::BasicValue; -use inkwell::AddressSpace; use shiika_core::{names::*, ty, ty::*}; use shiika_ffi::{mangle_const, mangle_method}; /// Number of elements before ivars const OBJ_HEADER_SIZE: usize = 2; /// 0th: reference to the vtable -const OBJ_VTABLE_IDX: usize = 0; +pub const OBJ_VTABLE_IDX: usize = 0; /// 1st: reference to the class object const OBJ_CLASS_IDX: usize = 1; @@ -28,142 +28,179 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { /// Build IR to return ::Void pub fn build_return_void(&self) { - let v = self.gen_const_ref(&toplevel_const("Void")); + let v = self.gen_const_ref(&toplevel_const("Void"), &ty::raw("Void")); self.build_return(&v); } - /// Load value of an instance variable - pub fn build_ivar_load(&self, object: SkObj<'run>, idx: usize, name: &str) -> SkObj<'run> { - SkObj(self.build_object_struct_ref(object, OBJ_HEADER_SIZE + idx, name)) + pub fn build_ivar_load( + &'run self, + obj: SkObj<'run>, + item_ty: TermTy, + idx: usize, + name: &str, + ) -> SkObj<'run> { + let value = self.build_ivar_load_raw(obj, self.llvm_type(&item_ty), idx, name); + SkObj::new(item_ty, value) } - /// Store value into an instance variable - pub fn build_ivar_store<'a>( - &'a self, - object: &'a SkObj<'a>, + pub fn build_ivar_load_raw( + &'run self, + obj: SkObj<'run>, + item_ty: inkwell::types::BasicTypeEnum<'run>, idx: usize, - value: SkObj<'a>, name: &str, - ) { - self.build_ivar_store_raw(object, idx, value.0, name) + ) -> inkwell::values::BasicValueEnum<'run> { + self.build_llvm_struct_ref_raw( + &self.llvm_struct_type(&obj.ty()), + obj.0.clone(), + item_ty, + OBJ_HEADER_SIZE + idx, + name, + ) } - /// Store llvm value into an instance variable - pub fn build_ivar_store_raw<'a>( - &'a self, - object: &'a SkObj<'a>, + pub fn build_ivar_store( + &'run self, + obj: SkObj<'run>, idx: usize, - value: inkwell::values::BasicValueEnum<'a>, name: &str, + value: SkObj<'run>, ) { - self.build_object_struct_set(object, OBJ_HEADER_SIZE + idx, value, name) + self.build_ivar_store_raw(obj, name, idx, value.0.as_basic_value_enum()); } - /// Get the vtable of an object as i8ptr - pub fn get_vtable_of_obj(&self, object: SkObj<'run>) -> VTableRef<'run> { - VTableRef(self.build_object_struct_ref(object, OBJ_VTABLE_IDX, "vtable")) + pub fn build_ivar_store_raw( + &'run self, + obj: SkObj<'run>, + name: &str, + idx: usize, + value: inkwell::values::BasicValueEnum<'run>, + ) { + self.build_llvm_struct_set( + &obj.struct_ty(self), + obj.0.clone(), + OBJ_HEADER_SIZE + idx, + value, + name, + ); } /// Get the class object of an object as `*Class` pub fn get_class_of_obj(&self, object: SkObj<'run>) -> SkClassObj<'run> { - SkClassObj(self.build_object_struct_ref(object, OBJ_CLASS_IDX, "class")) + SkClassObj( + self.build_object_struct_ref(object, &ty::raw("Class"), OBJ_CLASS_IDX, "class") + .into_pointer_value(), + ) } /// Set `class_obj` to the class object field of `object` pub fn set_class_of_obj(&self, object: &SkObj<'run>, class_obj: SkClassObj<'run>) { - let cast = self.bitcast(SkObj(class_obj.0), &ty::raw("Class"), "class"); - self.build_object_struct_set(object, OBJ_CLASS_IDX, cast.0, "my_class"); + self.build_object_struct_set( + &ty::raw("Object"), + object, + OBJ_CLASS_IDX, + class_obj.0.as_basic_value_enum(), + "my_class", + ); } /// Set `vtable` to `object` - pub fn set_vtable_of_obj(&self, object: &SkObj<'run>, vtable: VTableRef<'run>) { - self.build_object_struct_set(object, OBJ_VTABLE_IDX, vtable.0, "vtable"); + pub fn set_vtable_of_obj(&self, object: &SkObj<'run>, vtable: OpaqueVTableRef<'run>) { + let v = vtable.ptr.as_basic_value_enum(); + self.build_object_struct_set(&ty::raw("Object"), object, OBJ_VTABLE_IDX, v, "vtable"); } /// Get vtable of the class of the given name - pub fn get_vtable_of_class(&self, classname: &ClassFullname) -> VTableRef<'run> { + pub fn get_vtable_of_class(&self, classname: &ClassFullname) -> OpaqueVTableRef<'run> { let vtable_const_name = llvm_vtable_const_name(classname); let llvm_ary_ptr = self .module .get_global(&vtable_const_name) .unwrap_or_else(|| panic!("[BUG] global `{}' not found", &vtable_const_name)) .as_pointer_value(); - VTableRef( - self.builder - .build_bitcast(llvm_ary_ptr, self.i8ptr_type, "i8ptr"), - ) + OpaqueVTableRef::new(llvm_ary_ptr) } - /// Lookup llvm func from vtable of an object - pub fn build_vtable_ref( + /// Load value of the nth element of the llvm struct of a Shiika object + pub fn build_object_struct_ref( &self, - vtable_ref: VTableRef<'run>, + object: SkObj<'run>, + item_ty: &TermTy, idx: usize, - size: usize, + name: &str, ) -> inkwell::values::BasicValueEnum<'run> { - let ary_type = self.i8ptr_type.array_type(size as u32); - let vtable_ptr = self - .builder - .build_bitcast( - vtable_ref.0, - ary_type.ptr_type(AddressSpace::Generic), - "vtable_ptr", - ) - .into_pointer_value(); - let vtable = self - .builder - .build_load(vtable_ptr, "vtable") - .into_array_value(); - self.builder - .build_extract_value(vtable, idx as u32, "func_raw") - .unwrap() + let struct_ty = self.llvm_struct_type(object.ty()); + self.build_llvm_struct_ref(&struct_ty, object.0, item_ty, idx, name) } - /// Load value of the nth element of the llvm struct of a Shiika object - fn build_object_struct_ref( + /// Load a raw llvm value in a Shiika object + pub fn build_object_struct_ref_raw( &self, object: SkObj<'run>, + item_ty: inkwell::types::BasicTypeEnum<'run>, idx: usize, name: &str, ) -> inkwell::values::BasicValueEnum<'run> { - let ptr = object.0.into_pointer_value(); - self.build_llvm_struct_ref(ptr, idx, name) + let struct_ty = self.llvm_struct_type(object.ty()); + let ptr = object.0; + self.build_llvm_struct_ref_raw(&struct_ty, ptr, item_ty, idx, name) } /// Load value of the nth element of a llvm struct pub fn build_llvm_struct_ref( &self, + struct_ty: &inkwell::types::StructType<'run>, struct_ptr: inkwell::values::PointerValue<'run>, + item_ty: &TermTy, + idx: usize, + name: &str, + ) -> inkwell::values::BasicValueEnum<'run> { + self.build_llvm_struct_ref_raw(struct_ty, struct_ptr, self.llvm_type(item_ty), idx, name) + } + + /// Get a value in an llvm struct + pub fn build_llvm_struct_ref_raw( + &self, + struct_ty: &inkwell::types::StructType<'run>, + struct_ptr: inkwell::values::PointerValue<'run>, + item_ty: inkwell::types::BasicTypeEnum<'run>, idx: usize, name: &str, ) -> inkwell::values::BasicValueEnum<'run> { let ptr = self .builder - .build_struct_gep(struct_ptr, idx as u32, &format!("addr_{}", name)) + .build_struct_gep( + struct_ty.as_basic_type_enum(), + struct_ptr, + idx as u32, + &format!("addr_{}", name), + ) .unwrap_or_else(|_| { panic!( "build_llvm_struct_ref: elem not found (idx: {}, name: {}, struct_ptr: {:?})", &idx, &name, &struct_ptr ) }); - self.builder.build_load(ptr, name) + self.builder.build_load(item_ty, ptr, name) } /// Set the value the nth element of llvm struct of a Shiika object fn build_object_struct_set<'a>( &'a self, + obj_ty: &TermTy, object: &'a SkObj<'a>, idx: usize, value: inkwell::values::BasicValueEnum<'a>, name: &str, ) { - let ptr = object.0.into_pointer_value(); - self.build_llvm_struct_set(ptr, idx, value, name); + let t = self.llvm_struct_type(obj_ty); + self.build_llvm_struct_set(t, object.0, idx, value, name); } /// Set the value the nth element of llvm struct pub fn build_llvm_struct_set<'a>( &'a self, + struct_type: &inkwell::types::StructType<'run>, struct_ptr: inkwell::values::PointerValue<'a>, idx: usize, value: inkwell::values::BasicValueEnum<'a>, @@ -172,6 +209,7 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { let ptr = self .builder .build_struct_gep( + struct_type.as_basic_type_enum(), struct_ptr, idx as u32, &format!("addr_{}", name), @@ -186,34 +224,38 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { } /// Generate call of malloc and returns a ptr to Shiika object - pub fn allocate_sk_obj(&self, class_fullname: &ClassFullname, reg_name: &str) -> SkObj<'run> { + pub fn allocate_sk_obj(&self, class_fullname: &ClassFullname) -> SkObj<'run> { let class_obj = self.load_class_object(class_fullname); - self._allocate_sk_obj(class_fullname, reg_name, class_obj) + self._allocate_sk_obj(class_fullname, class_obj) } /// Load a class object - pub fn load_class_object(&self, class_fullname: &ClassFullname) -> SkClassObj<'run> { + /// NOTE: this does not work with `const_is_obj` classes (i.e. Void, None, etc.) + fn load_class_object(&self, class_fullname: &ClassFullname) -> SkClassObj<'run> { let class_const_name = llvm_const_name(&class_fullname.to_const_fullname()); let class_obj_addr = self .module .get_global(&class_const_name) .unwrap_or_else(|| panic!("global `{}' not found", class_const_name)) .as_pointer_value(); - SkClassObj(self.builder.build_load(class_obj_addr, "class_obj")) + let t = self.llvm_type(&ty::raw("Class")); + SkClassObj( + self.builder + .build_load(t, class_obj_addr, "class_obj") + .into_pointer_value(), + ) } pub fn _allocate_sk_obj( &self, class_fullname: &ClassFullname, - reg_name: &str, class_obj: SkClassObj, ) -> SkObj<'run> { - let object_type = self.llvm_struct_type(&class_fullname.to_type_fullname()); - let ptr = self.allocate_llvm_obj(&object_type.as_basic_type_enum(), reg_name); - let obj = SkObj(ptr.as_basic_value_enum()); + let object_type = self.get_llvm_struct_type(&class_fullname.to_type_fullname()); + let ptr = self.allocate_llvm_obj(&object_type.as_basic_type_enum()); + let obj = SkObj::new(class_fullname.to_ty(), ptr.into_pointer_value()); self.set_vtable_of_obj(&obj, self.get_vtable_of_class(class_fullname)); self.set_class_of_obj(&obj, class_obj); - obj } @@ -221,11 +263,8 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { pub fn allocate_llvm_obj( &self, t: &inkwell::types::BasicTypeEnum<'run>, - reg_name: &str, ) -> inkwell::values::BasicValueEnum<'run> { - let mem = self.allocate_mem(t); - let ptr_type = t.ptr_type(AddressSpace::Generic); - self.builder.build_bitcast(mem.0, ptr_type, reg_name) + self.allocate_mem(t).0.as_basic_value_enum() } /// Allocate some memory for a value of LLVM type `t`. Returns void ptr. @@ -239,7 +278,7 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { let func = self.get_llvm_func(&llvm_func_name("shiika_malloc")); I8Ptr( self.builder - .build_call(func, &[size.as_basic_value_enum().into()], "mem") + .build_direct_call(func, &[size.as_basic_value_enum().into()], "mem") .try_as_basic_value() .left() .unwrap() @@ -253,11 +292,15 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { method_name: &MethodFullname, receiver: SkObj<'run>, args: &[SkObj<'run>], + result_ty: TermTy, reg_name: &str, ) -> SkObj<'run> { let mut llvm_args = vec![receiver.0.into()]; llvm_args.append(&mut args.iter().map(|x| x.0.into()).collect()); - SkObj(self.call_llvm_func(&method_func_name(method_name), &llvm_args, reg_name)) + SkObj::new( + result_ty, + self.call_llvm_func(&method_func_name(method_name), &llvm_args, reg_name), + ) } /// Call llvm function (whose return type is not `void`) @@ -272,7 +315,7 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { .get_function(&func_name.0) .unwrap_or_else(|| panic!("[BUG] llvm function {:?} not found", func_name)); self.builder - .build_call(f, args, reg_name) + .build_direct_call(f, args, reg_name) .try_as_basic_value() .left() .unwrap() @@ -289,79 +332,62 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { .module .get_function(&func_name.0) .unwrap_or_else(|| panic!("[BUG] llvm function {:?} not found", func_name)); - self.builder.build_call(f, args, reg_name); + self.builder.build_direct_call(f, args, reg_name); } /// Get nth parameter of llvm func as SkObj pub fn get_nth_param( &self, + ty: TermTy, function: &inkwell::values::FunctionValue<'run>, n: usize, ) -> SkObj<'run> { - SkObj(function.get_nth_param(n as u32).unwrap()) + SkObj::new(ty, function.get_nth_param(n as u32).unwrap()) } /// Cast an object to different Shiika type pub fn bitcast(&self, obj: SkObj<'run>, ty: &TermTy, reg_name: &str) -> SkObj<'run> { - debug_assert!(!self.obviously_wrong_bitcast(&obj.0, &self.llvm_type(ty))); - SkObj( + //debug_assert!(!self.obviously_wrong_bitcast(&obj.0, &self.llvm_type(ty))); + SkObj::new( + ty.clone(), self.builder .build_bitcast(obj.0, self.llvm_type(ty), reg_name), ) } - fn obviously_wrong_bitcast(&self, val: &V, t1: &T) -> bool - where - T: BasicType<'run>, - V: BasicValue<'run>, - { - // eg. `%Int*` - let t2 = val.as_basic_value_enum().get_type(); - // eg. `%Int**` - let t1ptr = t1.ptr_type(AddressSpace::Generic).as_any_type_enum(); - let t2ptr = t2.ptr_type(AddressSpace::Generic).as_any_type_enum(); - if t1.as_any_type_enum() == t2ptr || t2.as_any_type_enum() == t1ptr { - println!("[BUG] Found wrong bitcast from t2 to t1, where"); - dbg!(&t2); - dbg!(&t1); - true - } else { - false - } - } - /// Create `%Foo* null` pub fn null_ptr(&self, ty: &TermTy) -> SkObj<'run> { let ptr = self.llvm_type(ty).into_pointer_type().const_null(); - SkObj(ptr.into()) + SkObj::new(ty.clone(), ptr) } /// LLVM type of a Shiika object pub fn llvm_type(&self, ty: &TermTy) -> inkwell::types::BasicTypeEnum<'ictx> { + self.llvm_struct_type(ty) + .ptr_type(Default::default()) + .as_basic_type_enum() + } + + /// LLVM struct type of a Shiika object + pub fn llvm_struct_type(&self, ty: &TermTy) -> &inkwell::types::StructType<'ictx> { match &ty.body { - TyBody::TyRaw(t) => self.llvm_type_of_lit_ty(t), + TyBody::TyRaw(t) => self.get_llvm_struct_type(&t.erasure().to_type_fullname()), TyBody::TyPara(TyParamRef { upper_bound, as_class, .. }) => { if *as_class { - self.llvm_type_of_lit_ty(&upper_bound.meta_ty()) + self.get_llvm_struct_type(&upper_bound.meta_ty().erasure().to_type_fullname()) } else { - self.llvm_type_of_lit_ty(upper_bound) + self.get_llvm_struct_type(&upper_bound.erasure().to_type_fullname()) } } } } - fn llvm_type_of_lit_ty(&self, lit_ty: &LitTy) -> inkwell::types::BasicTypeEnum<'ictx> { - self.llvm_struct_type(&lit_ty.erasure().into()) - .ptr_type(AddressSpace::Generic) - .as_basic_type_enum() - } - /// Get the llvm struct type for a class/module - fn llvm_struct_type(&self, name: &TypeFullname) -> &inkwell::types::StructType<'ictx> { + fn get_llvm_struct_type(&self, name: &TypeFullname) -> &inkwell::types::StructType<'ictx> { self.llvm_struct_types .get(name) .unwrap_or_else(|| panic!("[BUG] struct_type not found: {:?}", name)) diff --git a/lib/skc_codegen/src/values.rs b/lib/skc_codegen/src/values.rs index d8e676ff..414e8980 100644 --- a/lib/skc_codegen/src/values.rs +++ b/lib/skc_codegen/src/values.rs @@ -1,10 +1,37 @@ use crate::CodeGen; +use inkwell::values::BasicValue; +use shiika_core::{names::ClassFullname, ty, ty::TermTy}; /// Shiika object (eg. `Int*`, `String*`) #[derive(Clone, Debug)] -pub struct SkObj<'run>(pub inkwell::values::BasicValueEnum<'run>); +pub struct SkObj<'run>(pub inkwell::values::PointerValue<'run>, TermTy); impl<'run> SkObj<'run> { + pub fn new(ty: TermTy, ptr: T) -> SkObj<'run> + where + T: Into>, + { + SkObj(ptr.into().into_pointer_value(), ty) + } + + /// Returns a null pointer cast to `%Object*`. + pub fn nullptr(gen: &CodeGen<'_, 'run, '_>) -> SkObj<'run> { + let ty = ty::raw("Object"); + let null = gen.i8ptr_type.const_null().as_basic_value_enum(); + SkObj::new( + ty.clone(), + gen.builder.build_bitcast(null, gen.llvm_type(&ty), "as"), + ) + } + + pub fn ty(&self) -> &TermTy { + &self.1 + } + + pub fn classname(&self) -> ClassFullname { + self.1.erasure().to_class_fullname() + } + /// A class object is a Shiika object. pub fn as_class_obj(self) -> SkClassObj<'run> { SkClassObj(self.0) @@ -19,27 +46,31 @@ impl<'run> SkObj<'run> { .builder .build_bitcast(self.0, code_gen.i8ptr_type, "ptr") } + + pub fn struct_ty(&self, gen: &'run CodeGen<'_, 'run, '_>) -> inkwell::types::StructType<'run> { + gen.llvm_struct_type(&self.1).clone() + } } /// Shiika class object (eg. `Meta:Int*`, `Meta:String*`) #[derive(Debug)] -pub struct SkClassObj<'run>(pub inkwell::values::BasicValueEnum<'run>); +pub struct SkClassObj<'run>(pub inkwell::values::PointerValue<'run>); impl<'run> SkClassObj<'run> { - /// A class object is a Shiika object. - pub fn as_sk_obj(self) -> SkObj<'run> { - SkObj(self.0) + /// Returns a null pointer cast to `%Object*`. + pub fn nullptr(gen: &CodeGen<'_, 'run, '_>) -> SkClassObj<'run> { + let ty = ty::raw("Class"); + let null = gen.i8ptr_type.const_null().as_basic_value_enum(); + SkClassObj( + gen.builder + .build_bitcast(null, gen.llvm_type(&ty), "as") + .into_pointer_value(), + ) } -} -/// Reference to vtable (eg. `shiika_vtable_Int`) -#[derive(Debug)] -pub struct VTableRef<'run>(pub inkwell::values::BasicValueEnum<'run>); - -impl<'run> VTableRef<'run> { - /// Normally vtables are not Shiika object. This is used internally + /// A class object is a Shiika object. pub fn as_sk_obj(self) -> SkObj<'run> { - SkObj(self.0) + SkObj::new(ty::raw("Class"), self.0) } } diff --git a/lib/skc_codegen/src/vtable.rs b/lib/skc_codegen/src/vtable.rs new file mode 100644 index 00000000..4f64babb --- /dev/null +++ b/lib/skc_codegen/src/vtable.rs @@ -0,0 +1,91 @@ +use crate::utils::OBJ_VTABLE_IDX; +use crate::values::SkObj; +use crate::CodeGen; +use inkwell::types::BasicType; +use inkwell::values::BasicValue; +use shiika_core::ty; + +/// Reference to vtable (eg. `shiika_vtable_Int`) +#[derive(Debug)] +pub struct VTableRef<'run> { + pub ptr: inkwell::values::PointerValue<'run>, + len: usize, +} + +impl<'run> VTableRef<'run> { + pub fn new(ptr: inkwell::values::PointerValue<'run>, len: usize) -> VTableRef<'run> { + VTableRef { ptr, len } + } + + fn llvm_type(gen: &CodeGen<'_, 'run, '_>, len: usize) -> inkwell::types::PointerType<'run> { + Self::llvm_pointee_type(gen, len).ptr_type(Default::default()) + } + + fn llvm_pointee_type( + gen: &CodeGen<'_, 'run, '_>, + len: usize, + ) -> inkwell::types::ArrayType<'run> { + gen.i8ptr_type.array_type(len as u32) + } + + /// Returns the vtable of a Shiika object. + pub fn of_sk_obj( + gen: &CodeGen<'_, 'run, '_>, + object: SkObj<'run>, + len: usize, + ) -> VTableRef<'run> { + let item_ty = Self::llvm_type(gen, len).as_basic_type_enum(); + let ptr = gen + .build_object_struct_ref_raw(object, item_ty, OBJ_VTABLE_IDX, "vtable") + .into_pointer_value(); + VTableRef::new(ptr, len) + } + + pub fn get_func( + &self, + gen: &CodeGen<'_, 'run, '_>, + idx: usize, + ) -> inkwell::values::BasicValueEnum<'run> { + gen.builder + .build_extract_value(self.get_vtable(gen), idx as u32, "func_raw") + .unwrap() + } + + fn get_vtable(&self, gen: &CodeGen<'_, 'run, '_>) -> inkwell::values::ArrayValue<'run> { + gen.builder + .build_load( + Self::llvm_pointee_type(gen, self.len), + self.ptr.clone(), + "vtable", + ) + .into_array_value() + } +} + +/// Reference to vtable where its length is unknown. +#[derive(Debug)] +pub struct OpaqueVTableRef<'run> { + pub ptr: inkwell::values::PointerValue<'run>, +} + +impl<'run> OpaqueVTableRef<'run> { + pub fn new(ptr: inkwell::values::PointerValue<'run>) -> OpaqueVTableRef<'run> { + OpaqueVTableRef { ptr } + } + + /// Normally vtables are not Shiika object. This is used internally + pub fn as_object_ptr(self, gen: &CodeGen<'_, 'run, '_>) -> SkObj<'run> { + let ty = ty::raw("Object"); + SkObj::new( + ty.clone(), + gen.builder + .build_bitcast(self.ptr.as_basic_value_enum(), gen.llvm_type(&ty), "as"), + ) + } +} + +impl<'run> From> for OpaqueVTableRef<'run> { + fn from(x: VTableRef<'run>) -> Self { + OpaqueVTableRef::new(x.ptr) + } +} diff --git a/lib/skc_codegen/src/wtable.rs b/lib/skc_codegen/src/wtable.rs index cbb9e321..99e50686 100644 --- a/lib/skc_codegen/src/wtable.rs +++ b/lib/skc_codegen/src/wtable.rs @@ -43,7 +43,7 @@ pub fn gen_insert_wtable(code_gen: &CodeGen, sk_class: &SkClass) { code_gen, &llvm_wtable_const_name(&sk_class.fullname(), mod_name), ); - let cls = code_gen.get_nth_param(&function, 0); + let cls = code_gen.get_nth_param(ty::raw("Class"), &function, 0); let len = sk_class.wtable.get_len(mod_name); let args = &[ cls.into_i8ptr(code_gen).into(), diff --git a/lib/skc_corelib/src/fn_x.rs b/lib/skc_corelib/src/fn_x.rs index 7c0aa58f..66be6bfa 100644 --- a/lib/skc_corelib/src/fn_x.rs +++ b/lib/skc_corelib/src/fn_x.rs @@ -3,6 +3,11 @@ use shiika_core::ty; use skc_hir::{SkIVar, Supertype}; use std::collections::HashMap; +pub const IVAR_FUNC_IDX: usize = 0; +pub const IVAR_THE_SELF_IDX: usize = 1; +pub const IVAR_CAPTURES_IDX: usize = 2; +pub const IVAR_EXIT_STATUS_IDX: usize = 3; + macro_rules! fn_item { ($i:expr) => {{ let mut typarams = (1..=$i).map(|i| format!("S{}", i)).collect::>(); diff --git a/lib/skc_corelib/src/lib.rs b/lib/skc_corelib/src/lib.rs index 0e80535e..0e93838d 100644 --- a/lib/skc_corelib/src/lib.rs +++ b/lib/skc_corelib/src/lib.rs @@ -1,5 +1,5 @@ pub mod class; -mod fn_x; +pub mod fn_x; pub mod rustlib_methods; use shiika_core::names::*; use shiika_core::ty::{self, Erasure}; diff --git a/lib/skc_corelib/src/shiika_internal_ptr.rs b/lib/skc_corelib/src/shiika_internal_ptr.rs index c3cf4dc9..692e6d8f 100644 --- a/lib/skc_corelib/src/shiika_internal_ptr.rs +++ b/lib/skc_corelib/src/shiika_internal_ptr.rs @@ -22,7 +22,7 @@ pub fn create_methods() -> Vec { |code_gen, function| { let i8ptr = code_gen.unbox_i8ptr(code_gen.get_nth_param(function, 0)); let obj_ptr_type = code_gen.llvm_type(&ty::raw("Object")).into_pointer_type(); - let obj_ptrptr_type = obj_ptr_type.ptr_type(inkwell::AddressSpace::Generic); + let obj_ptrptr_type = obj_ptr_type.ptr_type(Default::default()); let obj_ptr = code_gen .builder .build_bitcast(i8ptr.0, obj_ptrptr_type, "") @@ -39,7 +39,7 @@ pub fn create_methods() -> Vec { |code_gen, function| { let i8ptr = code_gen.unbox_i8ptr(code_gen.get_nth_param(function, 0)); let obj_ptr_type = code_gen.llvm_type(&ty::raw("Object")).into_pointer_type(); - let obj_ptrptr_type = obj_ptr_type.ptr_type(inkwell::AddressSpace::Generic); + let obj_ptrptr_type = obj_ptr_type.ptr_type(Default::default()); let obj_ptr = code_gen .builder .build_bitcast(i8ptr.0, obj_ptrptr_type, "") diff --git a/lib/skc_hir/src/sk_method.rs b/lib/skc_hir/src/sk_method.rs index 08c5b604..4a224d47 100644 --- a/lib/skc_hir/src/sk_method.rs +++ b/lib/skc_hir/src/sk_method.rs @@ -1,6 +1,7 @@ use crate::signature::MethodSignature; use crate::{HirExpressions, HirLVars}; use shiika_core::names::*; +use shiika_core::ty::TermTy; use std::collections::HashMap; #[derive(Debug)] @@ -27,9 +28,19 @@ pub enum SkMethodBody { const_is_obj: bool, }, /// A method that just return the value of `idx`th ivar - Getter { idx: usize, name: String }, + Getter { + idx: usize, + name: String, + ty: TermTy, + self_ty: TermTy, + }, /// A method that just update the value of `idx`th ivar - Setter { idx: usize, name: String }, + Setter { + idx: usize, + name: String, + ty: TermTy, + self_ty: TermTy, + }, } impl SkMethod { diff --git a/lib/skc_hir/src/sk_type.rs b/lib/skc_hir/src/sk_type.rs index 9d9628ab..7ff8dfe0 100644 --- a/lib/skc_hir/src/sk_type.rs +++ b/lib/skc_hir/src/sk_type.rs @@ -34,7 +34,10 @@ impl SkTypes { } pub fn get_class<'hir>(&'hir self, name: &ClassFullname) -> &'hir SkClass { - let sk_type = self.0.get(&name.to_type_fullname()).unwrap(); + let sk_type = self + .0 + .get(&name.to_type_fullname()) + .unwrap_or_else(|| panic!("[BUG] class {} not found", name)); if let SkType::Class(class) = sk_type { class } else {