Compare commits

...

13 Commits

Author SHA1 Message Date
David Mak 157854e71f standalone: Add math tests for non-number arguments 2023-10-23 10:05:51 +08:00
David Mak 73537ec458 core: Rework gamma/gammaln to match SciPy behavior
Matches behavior for infinities and NaNs.
2023-10-23 10:05:51 +08:00
David Mak 3fda3ea461 core: Replace TopLevelDef comments with documentation 2023-10-23 10:05:51 +08:00
David Mak 4cb1b9f014 core: Implement numpy and scipy functions 2023-10-23 10:05:51 +08:00
David Mak 59e1cd36ee core: Implement and expose {isinf,isnan} 2023-10-23 10:05:51 +08:00
David Mak 1392862b96 flake: Add scipy 2023-10-23 10:05:51 +08:00
David Mak 8d7ce7086b core: Add create_fn_by_* functions
Used for abstracting the creation of function from different sources.
2023-10-23 10:05:51 +08:00
David Mak a7e89e6b4c core: Do not cast floor/ceil result to int
NumPy explicitly states that the return type of the floor/ceil is float.
2023-10-23 10:05:51 +08:00
David Mak 3d3476619e core: Remove {ceil64,floor64,round,round64}
These are not present in NumPy or Artiq.
2023-10-23 10:05:51 +08:00
David Mak db82291891 standalone: Do not output sign if float is NaN
Matches behavior in Python.
2023-10-23 10:05:51 +08:00
David Mak e49b760e34 ld: Support multiple CFIs with different encoding in .eh_frame
We now parse each CFI to read its encoding as opposed to assuming that
all CFIs within the same EH_Frame uses the same encoding. FDEs are now
iterated in a per-CFI manner.
2023-10-20 18:15:03 +08:00
David Mak aa92778363 ld: Fix remapping of FDEs with multiple CFIs 2023-10-20 18:14:27 +08:00
David Mak e1487ed335 cargo: Update dependencies 2023-10-20 18:11:45 +08:00
14 changed files with 1483 additions and 438 deletions

179
Cargo.lock generated
View File

@ -27,9 +27,9 @@ dependencies = [
[[package]] [[package]]
name = "aho-corasick" name = "aho-corasick"
version = "1.1.1" version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea5d730647d4fadd988536d06fecce94b7b4f2a7efdae548f1cf4b63205518ab" checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0"
dependencies = [ dependencies = [
"memchr", "memchr",
] ]
@ -120,15 +120,15 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "2.4.0" version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
[[package]] [[package]]
name = "byteorder" name = "byteorder"
version = "1.4.3" version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]] [[package]]
name = "cc" name = "cc"
@ -176,7 +176,7 @@ dependencies = [
"heck", "heck",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.37", "syn 2.0.38",
] ]
[[package]] [[package]]
@ -332,25 +332,14 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]] [[package]]
name = "errno" name = "errno"
version = "0.3.4" version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "add4f07d43996f76ef320709726a556a9d4f965d9410d8d0271132d2f8293480" checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860"
dependencies = [ dependencies = [
"errno-dragonfly",
"libc", "libc",
"windows-sys 0.48.0", "windows-sys 0.48.0",
] ]
[[package]]
name = "errno-dragonfly"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
dependencies = [
"cc",
"libc",
]
[[package]] [[package]]
name = "fastrand" name = "fastrand"
version = "2.0.1" version = "2.0.1"
@ -409,9 +398,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]] [[package]]
name = "hashbrown" name = "hashbrown"
version = "0.14.1" version = "0.14.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7dfda62a12f55daeae5015f81b0baea145391cb4520f86c248fc615d72640d12" checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156"
[[package]] [[package]]
name = "heck" name = "heck"
@ -442,15 +431,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897" checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897"
dependencies = [ dependencies = [
"equivalent", "equivalent",
"hashbrown 0.14.1", "hashbrown 0.14.2",
] ]
[[package]]
name = "indoc"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfa799dd5ed20a7e349f3b4639aa80d74549c81716d9ec4f994c9b5815598306"
[[package]] [[package]]
name = "indoc" name = "indoc"
version = "2.0.4" version = "2.0.4"
@ -479,7 +462,7 @@ checksum = "b185e7d068d6820411502efa14d8fbf010750485399402156b72dd2a548ef8e9"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.37", "syn 2.0.38",
] ]
[[package]] [[package]]
@ -547,7 +530,7 @@ dependencies = [
"petgraph", "petgraph",
"pico-args", "pico-args",
"regex", "regex",
"regex-syntax", "regex-syntax 0.7.5",
"string_cache", "string_cache",
"term", "term",
"tiny-keccak", "tiny-keccak",
@ -571,9 +554,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.148" version = "0.2.149"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b"
[[package]] [[package]]
name = "libloading" name = "libloading"
@ -593,9 +576,9 @@ checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
[[package]] [[package]]
name = "linux-raw-sys" name = "linux-raw-sys"
version = "0.4.8" version = "0.4.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3852614a3bd9ca9804678ba6be5e3b8ce76dfc902cae004e3e0c44051b6e88db" checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f"
[[package]] [[package]]
name = "llvm-sys" name = "llvm-sys"
@ -612,9 +595,9 @@ dependencies = [
[[package]] [[package]]
name = "lock_api" name = "lock_api"
version = "0.4.10" version = "0.4.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45"
dependencies = [ dependencies = [
"autocfg", "autocfg",
"scopeguard", "scopeguard",
@ -669,7 +652,7 @@ name = "nac3core"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"crossbeam", "crossbeam",
"indoc 2.0.4", "indoc",
"inkwell", "inkwell",
"insta", "insta",
"itertools 0.11.0", "itertools 0.11.0",
@ -738,13 +721,13 @@ dependencies = [
[[package]] [[package]]
name = "parking_lot_core" name = "parking_lot_core"
version = "0.9.8" version = "0.9.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"libc", "libc",
"redox_syscall 0.3.5", "redox_syscall 0.4.1",
"smallvec", "smallvec",
"windows-targets 0.48.5", "windows-targets 0.48.5",
] ]
@ -799,7 +782,7 @@ dependencies = [
"phf_shared 0.11.2", "phf_shared 0.11.2",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.37", "syn 2.0.38",
] ]
[[package]] [[package]]
@ -840,21 +823,21 @@ checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.67" version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]] [[package]]
name = "pyo3" name = "pyo3"
version = "0.19.2" version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e681a6cfdc4adcc93b4d3cf993749a4552018ee0a9b65fc0ccfad74352c72a38" checksum = "04e8453b658fe480c3e70c8ed4e3d3ec33eb74988bd186561b0cc66b85c3bc4b"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"indoc 1.0.9", "indoc",
"libc", "libc",
"memoffset", "memoffset",
"parking_lot", "parking_lot",
@ -866,9 +849,9 @@ dependencies = [
[[package]] [[package]]
name = "pyo3-build-config" name = "pyo3-build-config"
version = "0.19.2" version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "076c73d0bc438f7a4ef6fdd0c3bb4732149136abd952b110ac93e4edb13a6ba5" checksum = "a96fe70b176a89cff78f2fa7b3c930081e163d5379b4dcdf993e3ae29ca662e5"
dependencies = [ dependencies = [
"once_cell", "once_cell",
"target-lexicon", "target-lexicon",
@ -876,9 +859,9 @@ dependencies = [
[[package]] [[package]]
name = "pyo3-ffi" name = "pyo3-ffi"
version = "0.19.2" version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e53cee42e77ebe256066ba8aa77eff722b3bb91f3419177cf4cd0f304d3284d9" checksum = "214929900fd25e6604661ed9cf349727c8920d47deff196c4e28165a6ef2a96b"
dependencies = [ dependencies = [
"libc", "libc",
"pyo3-build-config", "pyo3-build-config",
@ -886,25 +869,26 @@ dependencies = [
[[package]] [[package]]
name = "pyo3-macros" name = "pyo3-macros"
version = "0.19.2" version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dfeb4c99597e136528c6dd7d5e3de5434d1ceaf487436a3f03b2d56b6fc9efd1" checksum = "dac53072f717aa1bfa4db832b39de8c875b7c7af4f4a6fe93cdbf9264cf8383b"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"pyo3-macros-backend", "pyo3-macros-backend",
"quote", "quote",
"syn 1.0.109", "syn 2.0.38",
] ]
[[package]] [[package]]
name = "pyo3-macros-backend" name = "pyo3-macros-backend"
version = "0.19.2" version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "947dc12175c254889edc0c02e399476c2f652b4b9ebd123aa655c224de259536" checksum = "7774b5a8282bd4f25f803b1f0d945120be959a36c72e08e7cd031c792fdfd424"
dependencies = [ dependencies = [
"heck",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 1.0.109", "syn 2.0.38",
] ]
[[package]] [[package]]
@ -984,6 +968,15 @@ dependencies = [
"bitflags 1.3.2", "bitflags 1.3.2",
] ]
[[package]]
name = "redox_syscall"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
dependencies = [
"bitflags 1.3.2",
]
[[package]] [[package]]
name = "redox_users" name = "redox_users"
version = "0.4.3" version = "0.4.3"
@ -997,25 +990,25 @@ dependencies = [
[[package]] [[package]]
name = "regex" name = "regex"
version = "1.9.6" version = "1.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebee201405406dbf528b8b672104ae6d6d63e6d118cb10e4d51abbc7b58044ff" checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343"
dependencies = [ dependencies = [
"aho-corasick", "aho-corasick",
"memchr", "memchr",
"regex-automata", "regex-automata",
"regex-syntax", "regex-syntax 0.8.2",
] ]
[[package]] [[package]]
name = "regex-automata" name = "regex-automata"
version = "0.3.9" version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59b23e92ee4318893fa3fe3e6fb365258efbfe6ac6ab30f090cdcbb7aa37efa9" checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f"
dependencies = [ dependencies = [
"aho-corasick", "aho-corasick",
"memchr", "memchr",
"regex-syntax", "regex-syntax 0.8.2",
] ]
[[package]] [[package]]
@ -1024,6 +1017,12 @@ version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da"
[[package]]
name = "regex-syntax"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
[[package]] [[package]]
name = "runkernel" name = "runkernel"
version = "0.1.0" version = "0.1.0"
@ -1033,11 +1032,11 @@ dependencies = [
[[package]] [[package]]
name = "rustix" name = "rustix"
version = "0.38.17" version = "0.38.20"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f25469e9ae0f3d0047ca8b93fc56843f38e6774f0914a107ff8b41be8be8e0b7" checksum = "67ce50cb2e16c2903e30d1cbccfd8387a74b9d4c938b6a4c5ec6cc7556f7a8a0"
dependencies = [ dependencies = [
"bitflags 2.4.0", "bitflags 2.4.1",
"errno", "errno",
"libc", "libc",
"linux-raw-sys", "linux-raw-sys",
@ -1064,28 +1063,28 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]] [[package]]
name = "semver" name = "semver"
version = "1.0.19" version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad977052201c6de01a8ef2aa3378c4bd23217a056337d1d6da40468d267a4fb0" checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090"
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.188" version = "1.0.189"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" checksum = "8e422a44e74ad4001bdc8eede9a4570ab52f71190e9c076d14369f38b9200537"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.188" version = "1.0.189"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" checksum = "1e48d1f918009ce3145511378cf68d613e3b3d9137d67272562080d68a2b32d5"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.37", "syn 2.0.38",
] ]
[[package]] [[package]]
@ -1113,9 +1112,9 @@ dependencies = [
[[package]] [[package]]
name = "similar" name = "similar"
version = "2.2.1" version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "420acb44afdae038210c99e69aae24109f32f15500aa708e81d46c9f29d55fcf" checksum = "2aeaf503862c419d66959f5d7ca015337d864e9c49485d771b732e2a20453597"
[[package]] [[package]]
name = "siphasher" name = "siphasher"
@ -1172,9 +1171,9 @@ dependencies = [
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.37" version = "2.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8" checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -1183,9 +1182,9 @@ dependencies = [
[[package]] [[package]]
name = "target-lexicon" name = "target-lexicon"
version = "0.12.11" version = "0.12.12"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d0e916b1148c8e263850e1ebcbd046f333e0683c724876bb0da63ea4373dc8a" checksum = "14c39fd04924ca3a864207c66fc2cd7d22d7c016007f9ce846cbb9326331930a"
[[package]] [[package]]
name = "tempfile" name = "tempfile"
@ -1226,22 +1225,22 @@ dependencies = [
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "1.0.49" version = "1.0.50"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4" checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2"
dependencies = [ dependencies = [
"thiserror-impl", "thiserror-impl",
] ]
[[package]] [[package]]
name = "thiserror-impl" name = "thiserror-impl"
version = "1.0.49" version = "1.0.50"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc" checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.37", "syn 2.0.38",
] ]
[[package]] [[package]]
@ -1341,9 +1340,9 @@ checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
[[package]] [[package]]
name = "unicode_names2" name = "unicode_names2"
version = "1.1.0" version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38b2c0942619ae1797f999a0ce7efc6c09592ad30e68e16cdbfdcd48a98c3579" checksum = "5d5506ae2c3c1ccbdf468e52fc5ef536c2ccd981f01273a4cb81aa61021f3a5f"
dependencies = [ dependencies = [
"phf", "phf",
"unicode_names2_generator", "unicode_names2_generator",
@ -1351,9 +1350,9 @@ dependencies = [
[[package]] [[package]]
name = "unicode_names2_generator" name = "unicode_names2_generator"
version = "1.1.0" version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d0d66ab60be9799a70f8eb227ea43da7dcc47561dd9102cbadacfe0930113f7" checksum = "b6dfc680313e95bc6637fa278cd7a22390c3c2cd7b8b2bd28755bc6c0fc811e7"
dependencies = [ dependencies = [
"getopts", "getopts",
"log", "log",
@ -1364,9 +1363,9 @@ dependencies = [
[[package]] [[package]]
name = "unindent" name = "unindent"
version = "0.1.11" version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e1766d682d402817b5ac4490b3c3002d91dfa0d22812f341609f97b08757359c" checksum = "c7de7d73e1754487cb58364ee906a499937a0dfabd86bcb980fa99ec8c8fa2ce"
[[package]] [[package]]
name = "utf8parse" name = "utf8parse"

View File

@ -21,7 +21,7 @@
passthru.cargoLock = cargoLock; passthru.cargoLock = cargoLock;
nativeBuildInputs = [ pkgs.python3 pkgs.llvmPackages_14.clang packages.x86_64-linux.clang-unwrapped pkgs.llvmPackages_14.llvm.out llvm-nac3 ]; nativeBuildInputs = [ pkgs.python3 pkgs.llvmPackages_14.clang packages.x86_64-linux.clang-unwrapped pkgs.llvmPackages_14.llvm.out llvm-nac3 ];
buildInputs = [ pkgs.python3 llvm-nac3 ]; buildInputs = [ pkgs.python3 llvm-nac3 ];
checkInputs = [ (pkgs.python3.withPackages(ps: [ ps.numpy ])) ]; checkInputs = [ (pkgs.python3.withPackages(ps: [ ps.numpy ps.scipy ])) ];
checkPhase = checkPhase =
'' ''
echo "Checking nac3standalone demos..." echo "Checking nac3standalone demos..."
@ -94,7 +94,7 @@
}) })
]; ];
buildInputs = [ buildInputs = [
(python3-mimalloc.withPackages(ps: [ ps.numpy ps.jsonschema nac3artiq-instrumented ])) (python3-mimalloc.withPackages(ps: [ ps.numpy ps.scipy ps.jsonschema nac3artiq-instrumented ]))
pkgs.llvmPackages_14.llvm.out pkgs.llvmPackages_14.llvm.out
]; ];
phases = [ "buildPhase" "installPhase" ]; phases = [ "buildPhase" "installPhase" ];
@ -151,7 +151,7 @@
rustc rustc
# runtime dependencies # runtime dependencies
lld_14 # for running kernels on the host lld_14 # for running kernels on the host
(packages.x86_64-linux.python3-mimalloc.withPackages(ps: [ ps.numpy ])) (packages.x86_64-linux.python3-mimalloc.withPackages(ps: [ ps.numpy ps.scipy ]))
# development tools # development tools
cargo-insta cargo-insta
clippy clippy

View File

@ -9,9 +9,9 @@ name = "nac3artiq"
crate-type = ["cdylib"] crate-type = ["cdylib"]
[dependencies] [dependencies]
pyo3 = { version = "0.19", features = ["extension-module"] } pyo3 = { version = "0.20", features = ["extension-module"] }
parking_lot = "0.12" parking_lot = "0.12"
tempfile = "3" tempfile = "3.8"
nac3parser = { path = "../nac3parser" } nac3parser = { path = "../nac3parser" }
nac3core = { path = "../nac3core" } nac3core = { path = "../nac3core" }
nac3ld = { path = "../nac3ld" } nac3ld = { path = "../nac3ld" }

View File

@ -22,4 +22,4 @@ indoc = "2.0"
insta = "=1.11.0" insta = "=1.11.0"
[build-dependencies] [build-dependencies]
regex = "1" regex = "1.10"

View File

@ -137,4 +137,12 @@ int32_t __nac3_list_slice_assign_var_size(
return dest_arr_len - (dest_end - dest_ind) - 1; return dest_arr_len - (dest_end - dest_ind) - 1;
} }
return dest_arr_len; return dest_arr_len;
}
int32_t __nac3_isinf(double x) {
return __builtin_isinf(x);
}
int32_t __nac3_isnan(double x) {
return __builtin_isnan(x);
} }

View File

@ -7,7 +7,7 @@ use inkwell::{
memory_buffer::MemoryBuffer, memory_buffer::MemoryBuffer,
module::Module, module::Module,
types::BasicTypeEnum, types::BasicTypeEnum,
values::{IntValue, PointerValue}, values::{FloatValue, IntValue, PointerValue},
AddressSpace, IntPredicate, AddressSpace, IntPredicate,
}; };
use nac3parser::ast::Expr; use nac3parser::ast::Expr;
@ -432,3 +432,53 @@ pub fn list_slice_assignment<'ctx, 'a>(
ctx.builder.build_unconditional_branch(cont_bb); ctx.builder.build_unconditional_branch(cont_bb);
ctx.builder.position_at_end(cont_bb); ctx.builder.position_at_end(cont_bb);
} }
/// Generates a call to `isinf` in IR. Returns either an `i32` or `i1` representing the result,
/// depending on the value of `to_i1`.
pub fn call_isinf<'ctx, 'a>(
generator: &dyn CodeGenerator,
ctx: &CodeGenContext<'ctx, 'a>,
v: FloatValue<'ctx>,
to_i1: bool,
) -> IntValue<'ctx> {
let intrinsic_fn = ctx.module.get_function("__nac3_isinf").unwrap_or_else(|| {
let fn_type = ctx.ctx.i32_type().fn_type(&[ctx.ctx.f64_type().into()], false);
ctx.module.add_function("__nac3_isinf", fn_type, None)
});
let val = ctx.builder
.build_call(intrinsic_fn, &[v.into()], "isinf")
.try_as_basic_value()
.unwrap_left()
.into_int_value();
if to_i1 {
generator.bool_to_i1(ctx, val)
} else {
val
}
}
/// Generates a call to `isnan` in IR. Returns either an `i32` or `i1` representing the result,
/// depending on the value of `to_i1`.
pub fn call_isnan<'ctx, 'a>(
generator: &dyn CodeGenerator,
ctx: &CodeGenContext<'ctx, 'a>,
v: FloatValue<'ctx>,
to_i1: bool,
) -> IntValue<'ctx> {
let intrinsic_fn = ctx.module.get_function("__nac3_isnan").unwrap_or_else(|| {
let fn_type = ctx.ctx.i32_type().fn_type(&[ctx.ctx.f64_type().into()], false);
ctx.module.add_function("__nac3_isnan", fn_type, None)
});
let val = ctx.builder
.build_call(intrinsic_fn, &[v.into()], "isnan")
.try_as_basic_value()
.unwrap_left()
.into_int_value();
if to_i1 {
generator.bool_to_i1(ctx, val)
} else {
val
}
}

File diff suppressed because it is too large Load Diff

View File

@ -82,51 +82,55 @@ pub struct FunInstance {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum TopLevelDef { pub enum TopLevelDef {
Class { Class {
// name for error messages and symbols /// Name for error messages and symbols.
name: StrRef, name: StrRef,
// object ID used for TypeEnum /// Object ID used for [TypeEnum].
object_id: DefinitionId, object_id: DefinitionId,
/// type variables bounded to the class. /// type variables bounded to the class.
type_vars: Vec<Type>, type_vars: Vec<Type>,
// class fields /// Class fields.
// name, type, is mutable ///
/// Name and type is mutable.
fields: Vec<(StrRef, Type, bool)>, fields: Vec<(StrRef, Type, bool)>,
// class methods, pointing to the corresponding function definition. /// Class methods, pointing to the corresponding function definition.
methods: Vec<(StrRef, Type, DefinitionId)>, methods: Vec<(StrRef, Type, DefinitionId)>,
// ancestor classes, including itself. /// Ancestor classes, including itself.
ancestors: Vec<TypeAnnotation>, ancestors: Vec<TypeAnnotation>,
// symbol resolver of the module defined the class, none if it is built-in type /// Symbol resolver of the module defined the class; [None] if it is built-in type.
resolver: Option<Arc<dyn SymbolResolver + Send + Sync>>, resolver: Option<Arc<dyn SymbolResolver + Send + Sync>>,
// constructor type /// Constructor type.
constructor: Option<Type>, constructor: Option<Type>,
// definition location /// Definition location.
loc: Option<Location>, loc: Option<Location>,
}, },
Function { Function {
// prefix for symbol, should be unique globally /// Prefix for symbol, should be unique globally.
name: String, name: String,
// simple name, the same as in method/function definition /// Simple name, the same as in method/function definition.
simple_name: StrRef, simple_name: StrRef,
// function signature. /// Function signature.
signature: Type, signature: Type,
// instantiated type variable IDs /// Instantiated type variable IDs.
var_id: Vec<u32>, var_id: Vec<u32>,
/// Function instance to symbol mapping /// Function instance to symbol mapping
/// Key: string representation of type variable values, sorted by variable ID in ascending ///
/// * Key: String representation of type variable values, sorted by variable ID in ascending
/// order, including type variables associated with the class. /// order, including type variables associated with the class.
/// Value: function symbol name. /// * Value: Function symbol name.
instance_to_symbol: HashMap<String, String>, instance_to_symbol: HashMap<String, String>,
/// Function instances to annotated AST mapping /// Function instances to annotated AST mapping
/// Key: string representation of type variable values, sorted by variable ID in ascending ///
/// * Key: String representation of type variable values, sorted by variable ID in ascending
/// order, including type variables associated with the class. Excluding rigid type /// order, including type variables associated with the class. Excluding rigid type
/// variables. /// variables.
/// rigid type variables that would be substituted when the function is instantiated. ///
/// Rigid type variables that would be substituted when the function is instantiated.
instance_to_stmt: HashMap<String, FunInstance>, instance_to_stmt: HashMap<String, FunInstance>,
// symbol resolver of the module defined the class /// Symbol resolver of the module defined the class.
resolver: Option<Arc<dyn SymbolResolver + Send + Sync>>, resolver: Option<Arc<dyn SymbolResolver + Send + Sync>>,
// custom codegen callback /// Custom code generation callback.
codegen_callback: Option<Arc<GenCall>>, codegen_callback: Option<Arc<GenCall>>,
// definition location /// Definition location.
loc: Option<Location>, loc: Option<Location>,
}, },
} }

View File

@ -5,4 +5,4 @@ authors = ["M-Labs"]
edition = "2021" edition = "2021"
[dependencies] [dependencies]
byteorder = { version = "1.4", default-features = false } byteorder = { version = "1.5", default-features = false }

View File

@ -27,20 +27,33 @@ pub const DW_EH_PE_indirect: u8 = 0x80;
pub struct DwarfReader<'a> { pub struct DwarfReader<'a> {
pub slice: &'a [u8], pub slice: &'a [u8],
pub virt_addr: u32, pub virt_addr: u32,
base_slice: &'a [u8],
base_virt_addr: u32,
} }
impl<'a> DwarfReader<'a> { impl<'a> DwarfReader<'a> {
pub fn new(slice: &[u8], virt_addr: u32) -> DwarfReader { pub fn new(slice: &[u8], virt_addr: u32) -> DwarfReader {
DwarfReader { slice, virt_addr } DwarfReader { slice, virt_addr, base_slice: slice, base_virt_addr: virt_addr }
} }
pub fn offset(&mut self, offset: i32) { /// Creates a new instance from another instance of [DwarfReader], optionally removing any
/// offsets previously applied to the other instance.
pub fn from_reader(other: &DwarfReader<'a>, reset_offset: bool) -> DwarfReader<'a> {
if reset_offset {
DwarfReader::new(&other.base_slice, other.base_virt_addr)
} else {
DwarfReader::new(&other.slice, other.virt_addr)
}
}
pub fn offset(&mut self, offset: u32) {
self.slice = &self.slice[offset as usize..]; self.slice = &self.slice[offset as usize..];
self.virt_addr = self.virt_addr.wrapping_add(offset as u32); self.virt_addr = self.virt_addr.wrapping_add(offset);
} }
// ULEB128 and SLEB128 encodings are defined in Section 7.6 - "Variable /// ULEB128 and SLEB128 encodings are defined in Section 7.6 - "Variable Length Data" of the
// Length Data". /// [DWARF-4 Manual](https://dwarfstd.org/doc/DWARF4.pdf).
pub fn read_uleb128(&mut self) -> u64 { pub fn read_uleb128(&mut self) -> u64 {
let mut shift: usize = 0; let mut shift: usize = 0;
let mut result: u64 = 0; let mut result: u64 = 0;
@ -70,7 +83,7 @@ impl<'a> DwarfReader<'a> {
} }
// sign-extend // sign-extend
if shift < u64::BITS && (byte & 0x40) != 0 { if shift < u64::BITS && (byte & 0x40) != 0 {
result |= (!0 as u64) << shift; result |= (!0u64) << shift;
} }
result as i64 result as i64
} }
@ -200,38 +213,69 @@ fn round_up(unrounded: usize, align: usize) -> Result<usize, ()> {
} }
} }
// Minimalistic structure to store everything needed for parsing FDEs to synthesize /// Minimalistic structure to store everything needed for parsing FDEs to synthesize `.eh_frame_hdr`
// .eh_frame_hdr section. Since we are only linking 1 object file, there should only be 1 call /// section.
// frame information (CFI) record, so there should be only 1 common information entry (CIE). ///
// So the class parses the only CIE on init, cache the encoding info, then parse the FDE on /// Refer to [The Linux Standard Base Core Specification, Generic Part](https://refspecs.linuxfoundation.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html)
// iterations based on the cached encoding format. /// for more information.
pub struct EH_Frame<'a> { pub struct EH_Frame<'a> {
// It refers to the augmentation data that corresponds to 'R' in the augmentation string reader: DwarfReader<'a>,
pub fde_pointer_encoding: u8,
pub fde_reader: DwarfReader<'a>,
pub fde_sz: usize,
} }
impl<'a> EH_Frame<'a> { impl<'a> EH_Frame<'a> {
/// Creates an [EH_Frame] using the bytes in the `.eh_frame` section and its address in the ELF
/// file.
pub fn new(eh_frame_slice: &[u8], eh_frame_addr: u32) -> Result<EH_Frame, ()> { pub fn new(eh_frame_slice: &[u8], eh_frame_addr: u32) -> Result<EH_Frame, ()> {
let mut cie_reader = DwarfReader::new(eh_frame_slice, eh_frame_addr); Ok(EH_Frame { reader: DwarfReader::new(eh_frame_slice, eh_frame_addr) })
let eh_frame_size = eh_frame_slice.len(); }
/// Returns an [Iterator] over all Call Frame Information (CFI) records.
pub fn cfi_records(&self) -> CFI_Records<'a> {
let reader = DwarfReader::from_reader(&self.reader, true);
let len = reader.slice.len();
CFI_Records {
reader,
available: len,
}
}
}
/// A single Call Frame Information (CFI) record.
///
/// From the [specification](https://refspecs.linuxfoundation.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html):
///
/// > Each CFI record contains a Common Information Entry (CIE) record followed by 1 or more Frame
/// Description Entry (FDE) records.
pub struct CFI_Record<'a> {
// It refers to the augmentation data that corresponds to 'R' in the augmentation string
fde_pointer_encoding: u8,
fde_reader: DwarfReader<'a>,
}
impl<'a> CFI_Record<'a> {
pub fn from_reader(cie_reader: &mut DwarfReader<'a>) -> Result<CFI_Record<'a>, ()> {
let length = cie_reader.read_u32(); let length = cie_reader.read_u32();
let fde_reader = match length { let fde_reader = match length {
// eh_frame with 0 lengths means the CIE is terminated // eh_frame with 0 lengths means the CIE is terminated
// while length == u32::MAX means that the length is only representable with 64 bits, 0 => panic!("Cannot create an EH_Frame from a termination CIE"),
// length == u32::MAX means that the length is only representable with 64 bits,
// which does not make sense in a system with 32-bit address. // which does not make sense in a system with 32-bit address.
0 | 0xFFFFFFFF => unimplemented!(), 0xFFFFFFFF => unimplemented!(),
_ => { _ => {
let mut fde_reader = DwarfReader::new(cie_reader.slice, cie_reader.virt_addr); let mut fde_reader = DwarfReader::from_reader(&cie_reader, false);
fde_reader.offset(length as i32); fde_reader.offset(length);
fde_reader fde_reader
} }
}; };
let fde_sz = eh_frame_size - mem::size_of::<u32>() - length as usize;
// Routine check on the .eh_frame well-formness, in terms of CIE ID & Version args. // Routine check on the .eh_frame well-formness, in terms of CIE ID & Version args.
assert_eq!(cie_reader.read_u32(), 0); let cie_ptr = cie_reader.read_u32();
assert_eq!(cie_ptr, 0);
assert_eq!(cie_reader.read_u8(), 1); assert_eq!(cie_reader.read_u8(), 1);
// Parse augmentation string // Parse augmentation string
@ -242,7 +286,7 @@ impl<'a> EH_Frame<'a> {
// Skip code/data alignment factors & return address register along the way as well // Skip code/data alignment factors & return address register along the way as well
// We only tackle the case where 'z' and 'R' are part of the augmentation string, otherwise // We only tackle the case where 'z' and 'R' are part of the augmentation string, otherwise
// we cannot get the addresses to make .eh_frame_hdr // we cannot get the addresses to make .eh_frame_hdr
let mut aug_data_reader = DwarfReader::new(cie_reader.slice, cie_reader.virt_addr); let mut aug_data_reader = DwarfReader::from_reader(&cie_reader, false);
let mut aug_str_len = 0; let mut aug_str_len = 0;
loop { loop {
if aug_data_reader.read_u8() == b'\0' { if aug_data_reader.read_u8() == b'\0' {
@ -279,43 +323,121 @@ impl<'a> EH_Frame<'a> {
} }
assert_ne!(fde_pointer_encoding, DW_EH_PE_omit); assert_ne!(fde_pointer_encoding, DW_EH_PE_omit);
Ok(EH_Frame { fde_pointer_encoding, fde_reader, fde_sz }) Ok(CFI_Record {
fde_pointer_encoding,
fde_reader,
})
} }
pub fn iterate_fde(&self, callback: &mut dyn FnMut(u32, u32)) -> Result<(), ()> { /// Returns a [DwarfReader] initialized to the first Frame Description Entry (FDE) of this CFI
/// record.
pub fn get_fde_reader(&self) -> DwarfReader<'a> {
DwarfReader::from_reader(&self.fde_reader, true)
}
/// Returns an [Iterator] over all Frame Description Entries (FDEs).
pub fn fde_records(&self) -> FDE_Records<'a> {
let reader = self.get_fde_reader();
let len = reader.slice.len();
FDE_Records {
pointer_encoding: self.fde_pointer_encoding,
reader,
available: len,
}
}
}
/// [Iterator] over Call Frame Information (CFI) records in an
/// [Exception Handling (EH) frame][EH_Frame].
pub struct CFI_Records<'a> {
reader: DwarfReader<'a>,
available: usize,
}
impl<'a> Iterator for CFI_Records<'a> {
type Item = CFI_Record<'a>;
fn next(&mut self) -> Option<Self::Item> {
loop {
if self.available == 0 {
return None;
}
let mut this_reader = DwarfReader::from_reader(&self.reader, false);
// Remove the length of the header and the content from the counter
let length = self.reader.read_u32();
let length = match length {
// eh_frame with 0-length means the CIE is terminated
0 => return None,
0xFFFFFFFF => unimplemented!("CIE entries larger than 4 bytes not supported"),
other => other,
} as usize;
// Remove the length of the header and the content from the counter
self.available -= length + mem::size_of::<u32>();
let mut next_reader = DwarfReader::from_reader(&self.reader, false);
next_reader.offset(length as u32);
let cie_ptr = self.reader.read_u32();
self.reader = next_reader;
// Skip this record if it is a FDE
if cie_ptr == 0 {
// Rewind back to the start of the CFI Record
return Some(CFI_Record::from_reader(&mut this_reader).ok().unwrap())
}
}
}
}
/// [Iterator] over Frame Description Entries (FDEs) in an
/// [Exception Handling (EH) frame][EH_Frame].
pub struct FDE_Records<'a> {
pointer_encoding: u8,
reader: DwarfReader<'a>,
available: usize,
}
impl<'a> Iterator for FDE_Records<'a> {
type Item = (u32, u32);
fn next(&mut self) -> Option<Self::Item> {
// Parse each FDE to obtain the starting address that the FDE applies to // Parse each FDE to obtain the starting address that the FDE applies to
// Send the FDE offset and the mentioned address to a callback that write up the // Send the FDE offset and the mentioned address to a callback that write up the
// .eh_frame_hdr section // .eh_frame_hdr section
let mut remaining_len = self.fde_sz;
let mut reader = DwarfReader::new(self.fde_reader.slice, self.fde_reader.virt_addr);
loop {
if remaining_len == 0 {
break;
}
let fde_virt_addr = reader.virt_addr; if self.available == 0 {
let length = match reader.read_u32() { return None;
0 | 0xFFFFFFFF => unimplemented!(),
other => other,
};
// Remove the length of the header and the content from the counter
remaining_len -= length as usize + mem::size_of::<u32>();
let mut next_fde_reader = DwarfReader::new(reader.slice, reader.virt_addr);
next_fde_reader.offset(length as i32);
// Skip CIE pointer offset
reader.read_u32();
// Parse PC Begin using the encoding scheme mentioned in the CIE
let pc_begin = read_encoded_pointer_with_pc(&mut reader, self.fde_pointer_encoding)?;
callback(pc_begin as u32, fde_virt_addr);
reader = next_fde_reader;
} }
Ok(()) // Remove the length of the header and the content from the counter
let length = match self.reader.read_u32() {
// eh_frame with 0-length means the CIE is terminated
0 => return None,
0xFFFFFFFF => unimplemented!("CIE entries larger than 4 bytes not supported"),
other => other,
} as usize;
// Remove the length of the header and the content from the counter
self.available -= length + mem::size_of::<u32>();
let mut next_fde_reader = DwarfReader::from_reader(&self.reader, false);
next_fde_reader.offset(length as u32);
let cie_ptr = self.reader.read_u32();
let next_val = if cie_ptr != 0 {
let pc_begin = read_encoded_pointer_with_pc(&mut self.reader, self.pointer_encoding)
.expect("Failed to read PC Begin");
Some((pc_begin as u32, self.reader.virt_addr))
} else {
None
};
self.reader = next_fde_reader;
next_val
} }
} }
@ -326,29 +448,32 @@ pub struct EH_Frame_Hdr<'a> {
} }
impl<'a> EH_Frame_Hdr<'a> { impl<'a> EH_Frame_Hdr<'a> {
// Create a EH_Frame_Hdr object, and write out the fixed fields of .eh_frame_hdr to memory
// eh_frame_ptr_enc will be 0x1B (PC-relative, 4 bytes) /// Create a [EH_Frame_Hdr] object, and write out the fixed fields of `.eh_frame_hdr` to memory.
// table_enc will be 0x3B (Relative to the start of .eh_frame_hdr, 4 bytes) ///
// Load address is not known at this point. /// Load address is not known at this point.
pub fn new( pub fn new(
eh_frame_hdr_slice: &mut [u8], eh_frame_hdr_slice: &mut [u8],
eh_frame_hdr_addr: u32, eh_frame_hdr_addr: u32,
eh_frame_addr: u32, eh_frame_addr: u32,
) -> EH_Frame_Hdr { ) -> EH_Frame_Hdr {
let mut writer = DwarfWriter::new(eh_frame_hdr_slice); let mut writer = DwarfWriter::new(eh_frame_hdr_slice);
writer.write_u8(1);
writer.write_u8(0x1B);
writer.write_u8(0x03);
writer.write_u8(0x3B);
let eh_frame_offset = writer.write_u8(1); // version
(eh_frame_addr).wrapping_sub(eh_frame_hdr_addr + ((mem::size_of::<u8>() as u32) * 4)); writer.write_u8(0x1B); // eh_frame_ptr_enc - PC-relative 4-byte signed value
writer.write_u32(eh_frame_offset); writer.write_u8(0x03); // fde_count_enc - 4-byte unsigned value
writer.write_u32(0); writer.write_u8(0x3B); // table_enc - .eh_frame_hdr section-relative 4-byte signed value
let eh_frame_offset = eh_frame_addr
.wrapping_sub(eh_frame_hdr_addr + writer.offset as u32 + ((mem::size_of::<u8>() as u32) * 4));
writer.write_u32(eh_frame_offset); // eh_frame_ptr
writer.write_u32(0); // `fde_count`, will be written in finalize_fde
EH_Frame_Hdr { fde_writer: writer, eh_frame_hdr_addr, fdes: Vec::new() } EH_Frame_Hdr { fde_writer: writer, eh_frame_hdr_addr, fdes: Vec::new() }
} }
/// The offset of the `fde_count` value relative to the start of the `.eh_frame_hdr` section in
/// bytes.
fn fde_count_offset() -> usize { fn fde_count_offset() -> usize {
8 8
} }
@ -382,11 +507,17 @@ impl<'a> EH_Frame_Hdr<'a> {
if entry_length == 0 || entry_length == 0xFFFFFFFF { if entry_length == 0 || entry_length == 0xFFFFFFFF {
unimplemented!() unimplemented!()
} }
if reader.read_u32() != 0 {
// This slot stores the CIE ID (for CIE)/CIE Pointer (for FDE).
// This value must be non-zero for FDEs.
let cie_ptr = reader.read_u32();
if cie_ptr != 0 {
fde_count += 1; fde_count += 1;
} }
reader.offset(entry_length as i32 - mem::size_of::<u32>() as i32)
reader.offset(entry_length - mem::size_of::<u32>() as u32)
} }
12 + fde_count * 8 12 + fde_count * 8
} }
} }

View File

@ -556,10 +556,9 @@ impl<'a> Linker<'a> {
eh_frame_hdr_rec.shdr.sh_offset, eh_frame_hdr_rec.shdr.sh_offset,
eh_frame_rec.shdr.sh_offset, eh_frame_rec.shdr.sh_offset,
); );
let mut fde_callback = |init_pos, virt_addr| eh_frame_hdr.add_fde(init_pos, virt_addr); eh_frame.cfi_records()
eh_frame .flat_map(|cfi| cfi.fde_records())
.iterate_fde(&mut fde_callback) .for_each(&mut |(init_pos, virt_addr)| eh_frame_hdr.add_fde(init_pos, virt_addr));
.map_err(|()| "failed to add FDE to .eh_frame_hdr while iterating .eh_frame")?;
// Sort FDE entries in .eh_frame_hdr // Sort FDE entries in .eh_frame_hdr
eh_frame_hdr.finalize_fde(); eh_frame_hdr.finalize_fde();

View File

@ -1,3 +1,4 @@
#include <math.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
@ -12,6 +13,14 @@
#error "Unsupported platform - Platform is not 32-bit or 64-bit" #error "Unsupported platform - Platform is not 32-bit or 64-bit"
#endif #endif
double dbl_nan(void) {
return NAN;
}
double dbl_inf(void) {
return INFINITY;
}
void output_bool(bool x) { void output_bool(bool x) {
puts(x ? "True" : "False"); puts(x ? "True" : "False");
} }
@ -33,7 +42,11 @@ void output_uint64(uint64_t x) {
} }
void output_float64(double x) { void output_float64(double x) {
printf("%f\n", x); if (isnan(x)) {
puts("nan");
} else {
printf("%f\n", x);
}
} }
void output_asciiart(int32_t x) { void output_asciiart(int32_t x) {

View File

@ -3,7 +3,9 @@
import sys import sys
import importlib.util import importlib.util
import importlib.machinery import importlib.machinery
import numpy as np
import pathlib import pathlib
import scipy
from numpy import int32, int64, uint32, uint64 from numpy import int32, int64, uint32, uint64
from typing import TypeVar, Generic from typing import TypeVar, Generic
@ -42,6 +44,12 @@ def Some(v: T) -> Option[T]:
none = Option(None) none = Option(None)
def patch(module): def patch(module):
def dbl_nan():
return np.nan
def dbl_inf():
return np.inf
def output_asciiart(x): def output_asciiart(x):
if x < 0: if x < 0:
sys.stdout.write("\n") sys.stdout.write("\n")
@ -56,7 +64,11 @@ def patch(module):
def extern(fun): def extern(fun):
name = fun.__name__ name = fun.__name__
if name == "output_asciiart": if name == "dbl_nan":
return dbl_nan
elif name == "dbl_inf":
return dbl_inf
elif name == "output_asciiart":
return output_asciiart return output_asciiart
elif name == "output_float64": elif name == "output_float64":
return output_float return output_float
@ -86,6 +98,48 @@ def patch(module):
module.Some = Some module.Some = Some
module.none = none module.none = none
# NumPy math functions
module.isnan = np.isnan
module.isinf = np.isinf
module.sin = np.sin
module.cos = np.cos
module.exp = np.exp
module.exp2 = np.exp2
module.log = np.log
module.log10 = np.log10
module.log2 = np.log2
module.fabs = np.fabs
module.floor = np.floor
module.ceil = np.ceil
module.trunc = np.trunc
module.sqrt = np.sqrt
module.rint = np.rint
module.tan = np.tan
module.arcsin = np.arcsin
module.arccos = np.arccos
module.arctan = np.arctan
module.sinh = np.sinh
module.cosh = np.cosh
module.tanh = np.tanh
module.arcsinh = np.arcsinh
module.arccosh = np.arccosh
module.arctanh = np.arctanh
module.expm1 = np.expm1
module.cbrt = np.cbrt
module.erf = scipy.special.erf
module.erfc = scipy.special.erfc
module.gamma = scipy.special.gamma
module.gammaln = scipy.special.gammaln
module.j0 = scipy.special.j0
module.j1 = scipy.special.j1
module.arctan2 = np.arctan2
module.copysign = np.copysign
module.fmax = np.fmax
module.fmin = np.fmin
module.ldexp = np.ldexp
module.hypot = np.hypot
module.nextafter = np.nextafter
def file_import(filename, prefix="file_import_"): def file_import(filename, prefix="file_import_"):
filename = pathlib.Path(filename) filename = pathlib.Path(filename)

View File

@ -0,0 +1,236 @@
@extern
def output_bool(x: bool):
...
@extern
def output_float64(x: float):
...
@extern
def dbl_nan() -> float:
...
@extern
def dbl_inf() -> float:
...
def dbl_pi() -> float:
return 3.1415926535897932384626433
def dbl_e() -> float:
return 2.71828182845904523536028747135266249775724709369995
def test_isnan():
for x in [dbl_nan(), 0.0, dbl_inf()]:
output_bool(isnan(x))
def test_isinf():
for x in [dbl_inf(), -dbl_inf(), 0.0, dbl_nan()]:
output_bool(isinf(x))
def test_sin():
pi = dbl_pi()
for x in [-pi, -pi / 2.0, -pi / 4.0, 0.0, pi / 4.0, pi / 2.0, pi, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(sin(x))
def test_cos():
pi = dbl_pi()
for x in [-pi, -pi / 2.0, -pi / 4.0, 0.0, pi / 4.0, pi / 2.0, pi, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(cos(x))
def test_exp():
for x in [0.0, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(exp(x))
def test_exp2():
for x in [0.0, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(exp2(x))
def test_log():
e = dbl_e()
for x in [1.0, e, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(log(x))
def test_log10():
for x in [1.0, 10.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(log10(x))
def test_log2():
for x in [1.0, 2.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(log2(x))
def test_fabs():
for x in [-1.0, 0.0, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(fabs(x))
def test_floor():
for x in [-1.5, -0.5, 0.5, 1.5, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(floor(x))
def test_ceil():
for x in [-1.5, -0.5, 0.5, 1.5, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(ceil(x))
def test_trunc():
for x in [-1.5, -0.5, 0.5, 1.5, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(trunc(x))
def test_sqrt():
for x in [1.0, 2.0, 4.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(sqrt(x))
def test_rint():
for x in [-1.5, -0.5, 0.5, 1.5, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(rint(x))
def test_tan():
pi = dbl_pi()
for x in [-pi, -pi / 2.0, -pi / 4.0, 0.0, pi / 4.0, pi / 2.0, pi, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(tan(x))
def test_arcsin():
for x in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(arcsin(x))
def test_arccos():
for x in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(arccos(x))
def test_arctan():
for x in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(arctan(x))
def test_sinh():
for x in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(sinh(x))
def test_cosh():
for x in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(cosh(x))
def test_tanh():
for x in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(tanh(x))
def test_arcsinh():
for x in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(arcsinh(x))
def test_arccosh():
for x in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(arccosh(x))
def test_arctanh():
for x in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(arctanh(x))
def test_expm1():
for x in [0.0, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(expm1(x))
def test_cbrt():
for x in [1.0, 8.0, 27.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(expm1(x))
def test_erf():
for x in [-3.0, -2.0, -1.0, 0.0, 1.0, 2.0, 3.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(erf(x))
def test_erfc():
for x in [-3.0, -2.0, -1.0, 0.0, 1.0, 2.0, 3.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(erfc(x))
def test_gamma():
for x in [-2.0, -1.5, -1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(gamma(x))
def test_gammaln():
for x in [-2.0, -1.5, -1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(gammaln(x))
def test_j0():
for x in [-2.0, -1.5, -1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(j0(x))
def test_j1():
for x in [-2.0, -1.5, -1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0]:
output_float64(j1(x))
def test_arctan2():
for x1 in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
for x2 in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(arctan2(x1, x2))
def test_copysign():
for x1 in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
for x2 in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(copysign(x1, x2))
def test_fmax():
for x1 in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
for x2 in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(fmax(x1, x2))
def test_fmin():
for x1 in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
for x2 in [-1.0, -0.5, 0.0, 0.5, 1.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(fmin(x1, x2))
def test_ldexp():
for x1 in [-2.0, -1.5, -1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
for x2 in [-2, -1, 0, 1, 2]:
output_float64(ldexp(x1, x2))
def test_hypot():
for x1 in [-2.0, -1.5, -1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
for x2 in [-2.0, -1.5, -1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(hypot(x1, x2))
def test_nextafter():
for x1 in [-2.0, -1.5, -1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
for x2 in [-2.0, -1.5, -1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0, dbl_inf(), -dbl_inf(), dbl_nan()]:
output_float64(nextafter(x1, x2))
def run() -> int32:
test_isnan()
test_isinf()
test_sin()
test_cos()
test_exp()
test_exp2()
test_log()
test_log10()
test_log2()
test_fabs()
test_floor()
test_ceil()
test_trunc()
test_sqrt()
test_rint()
test_tan()
test_arcsin()
test_arccos()
test_arctan()
test_sinh()
test_cosh()
test_tanh()
test_arcsinh()
test_arccosh()
test_arctanh()
test_expm1()
test_cbrt()
test_erf()
test_erfc()
test_gamma()
test_gammaln()
test_j0()
test_j1()
test_arctan2()
test_copysign()
test_fmax()
test_fmin()
test_ldexp()
test_hypot()
test_nextafter()
return 0