forked from M-Labs/nac3
Compare commits
12 Commits
11820f8f66
...
cf50278dad
Author | SHA1 | Date | |
---|---|---|---|
cf50278dad | |||
2c390572d2 | |||
26059208ff | |||
b0cb74423d | |||
2ef8b300b2 | |||
c9b234b0a5 | |||
9a3463e027 | |||
4b816d7211 | |||
a6dcd8dca3 | |||
979209a526 | |||
c3927d0ef6 | |||
202a902cd0 |
87
Cargo.lock
generated
87
Cargo.lock
generated
@ -26,9 +26,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anstream"
|
name = "anstream"
|
||||||
version = "0.6.15"
|
version = "0.6.17"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526"
|
checksum = "23a1e53f0f5d86382dafe1cf314783b2044280f406e7e1506368220ad11b1338"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anstyle",
|
"anstyle",
|
||||||
"anstyle-parse",
|
"anstyle-parse",
|
||||||
@ -41,36 +41,36 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anstyle"
|
name = "anstyle"
|
||||||
version = "1.0.8"
|
version = "1.0.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1"
|
checksum = "8365de52b16c035ff4fcafe0092ba9390540e3e352870ac09933bebcaa2c8c56"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anstyle-parse"
|
name = "anstyle-parse"
|
||||||
version = "0.2.5"
|
version = "0.2.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb"
|
checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"utf8parse",
|
"utf8parse",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anstyle-query"
|
name = "anstyle-query"
|
||||||
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 = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a"
|
checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-sys 0.52.0",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anstyle-wincon"
|
name = "anstyle-wincon"
|
||||||
version = "3.0.4"
|
version = "3.0.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8"
|
checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anstyle",
|
"anstyle",
|
||||||
"windows-sys 0.52.0",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -126,9 +126,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.1.30"
|
version = "1.1.31"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b16803a61b81d9eabb7eae2588776c4c1e584b738ede45fdbb4c972cec1e9945"
|
checksum = "c2e7962b54006dcfcc61cb72735f4d89bb97061dd6a7ed882ec6b8ee53714c6f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"shlex",
|
"shlex",
|
||||||
]
|
]
|
||||||
@ -170,7 +170,7 @@ dependencies = [
|
|||||||
"heck 0.5.0",
|
"heck 0.5.0",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.79",
|
"syn 2.0.85",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -181,9 +181,9 @@ checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "colorchoice"
|
name = "colorchoice"
|
||||||
version = "1.0.2"
|
version = "1.0.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0"
|
checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "console"
|
name = "console"
|
||||||
@ -460,7 +460,7 @@ checksum = "9dd28cfd4cfba665d47d31c08a6ba637eed16770abca2eccbbc3ca831fef1e44"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.79",
|
"syn 2.0.85",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -634,7 +634,6 @@ name = "nac3ast"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"fxhash",
|
"fxhash",
|
||||||
"lazy_static",
|
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
"string-interner",
|
"string-interner",
|
||||||
]
|
]
|
||||||
@ -775,7 +774,7 @@ dependencies = [
|
|||||||
"phf_shared 0.11.2",
|
"phf_shared 0.11.2",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.79",
|
"syn 2.0.85",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -825,9 +824,9 @@ checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.88"
|
version = "1.0.89"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7c3a7fc5db1e57d5a779a352c8cdb57b29aa4c40cc69c3a68a7fedc815fbf2f9"
|
checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
@ -879,7 +878,7 @@ dependencies = [
|
|||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"pyo3-macros-backend",
|
"pyo3-macros-backend",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.79",
|
"syn 2.0.85",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -892,7 +891,7 @@ dependencies = [
|
|||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"pyo3-build-config",
|
"pyo3-build-config",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.79",
|
"syn 2.0.85",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -965,9 +964,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex"
|
name = "regex"
|
||||||
version = "1.11.0"
|
version = "1.11.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8"
|
checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aho-corasick",
|
"aho-corasick",
|
||||||
"memchr",
|
"memchr",
|
||||||
@ -1001,9 +1000,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustix"
|
name = "rustix"
|
||||||
version = "0.38.37"
|
version = "0.38.38"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811"
|
checksum = "aa260229e6538e52293eeb577aabd09945a09d6d9cc0fc550ed7529056c2e32a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"errno",
|
"errno",
|
||||||
@ -1047,29 +1046,29 @@ checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.210"
|
version = "1.0.214"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a"
|
checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.210"
|
version = "1.0.214"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f"
|
checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.79",
|
"syn 2.0.85",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_json"
|
name = "serde_json"
|
||||||
version = "1.0.129"
|
version = "1.0.132"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6dbcf9b78a125ee667ae19388837dd12294b858d101fdd393cb9d5501ef09eb2"
|
checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itoa",
|
"itoa",
|
||||||
"memchr",
|
"memchr",
|
||||||
@ -1169,7 +1168,7 @@ dependencies = [
|
|||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"rustversion",
|
"rustversion",
|
||||||
"syn 2.0.79",
|
"syn 2.0.85",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1185,9 +1184,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.79"
|
version = "2.0.85"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590"
|
checksum = "5023162dfcd14ef8f32034d8bcd4cc5ddc61ef7a247c024a33e24e1f24d21b56"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@ -1238,22 +1237,22 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror"
|
name = "thiserror"
|
||||||
version = "1.0.64"
|
version = "1.0.65"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84"
|
checksum = "5d11abd9594d9b38965ef50805c5e469ca9cc6f197f883f717e0269a3057b3d5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"thiserror-impl",
|
"thiserror-impl",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror-impl"
|
name = "thiserror-impl"
|
||||||
version = "1.0.64"
|
version = "1.0.65"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3"
|
checksum = "ae71770322cbd277e69d762a16c444af02aa0575ac0d174f0b9562d3b37f8602"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.79",
|
"syn 2.0.85",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1506,5 +1505,5 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.79",
|
"syn 2.0.85",
|
||||||
]
|
]
|
||||||
|
@ -1,11 +1,19 @@
|
|||||||
class EmbeddingMap:
|
class EmbeddingMap:
|
||||||
def __init__(self):
|
def __init__(self, old_embedding_map=None):
|
||||||
self.object_inverse_map = {}
|
self.object_inverse_map = {}
|
||||||
self.object_map = {}
|
self.object_map = {}
|
||||||
self.string_map = {}
|
self.string_map = {}
|
||||||
self.string_reverse_map = {}
|
self.string_reverse_map = {}
|
||||||
self.function_map = {}
|
self.function_map = {}
|
||||||
self.attributes_writeback = []
|
self.attributes_writeback = []
|
||||||
|
self.subkernel_map = {}
|
||||||
|
self.subkernel_message_map = {}
|
||||||
|
|
||||||
|
if not old_embedding_map is None:
|
||||||
|
for key, obj_ref in old_embedding_map.subkernels().items():
|
||||||
|
self.object_map[key] = obj_ref
|
||||||
|
obj_id = id(obj_ref)
|
||||||
|
self.object_inverse_map[obj_id] = key
|
||||||
|
|
||||||
# preallocate exception names
|
# preallocate exception names
|
||||||
self.preallocate_runtime_exception_names(["RuntimeError",
|
self.preallocate_runtime_exception_names(["RuntimeError",
|
||||||
@ -38,6 +46,10 @@ class EmbeddingMap:
|
|||||||
self.function_map[key] = fun
|
self.function_map[key] = fun
|
||||||
return key
|
return key
|
||||||
|
|
||||||
|
def store_subkernel(self, key, fun):
|
||||||
|
self.subkernel_map[key] = fun
|
||||||
|
return key
|
||||||
|
|
||||||
def store_object(self, obj):
|
def store_object(self, obj):
|
||||||
obj_id = id(obj)
|
obj_id = id(obj)
|
||||||
if obj_id in self.object_inverse_map:
|
if obj_id in self.object_inverse_map:
|
||||||
@ -64,3 +76,19 @@ class EmbeddingMap:
|
|||||||
def retrieve_str(self, key):
|
def retrieve_str(self, key):
|
||||||
return self.string_map[key]
|
return self.string_map[key]
|
||||||
|
|
||||||
|
def subkernels(self):
|
||||||
|
return self.subkernel_map
|
||||||
|
|
||||||
|
def subkernel_messages(self):
|
||||||
|
messages = {}
|
||||||
|
for msg_id in self.subkernel_message_map.values():
|
||||||
|
messages[msg_id] = self.retrieve_object(msg_id)
|
||||||
|
return messages
|
||||||
|
|
||||||
|
def subkernel_messages_unpaired(self):
|
||||||
|
unpaired = []
|
||||||
|
for msg_id in self.subkernel_message_map.values():
|
||||||
|
msg_obj = self.retrieve_object(msg_id)
|
||||||
|
if msg_obj.send_loc is None or msg_obj.recv_loc is None:
|
||||||
|
unpaired.append(msg_obj)
|
||||||
|
return unpaired
|
@ -135,8 +135,19 @@ def kernel(function_or_method):
|
|||||||
@wraps(function_or_method)
|
@wraps(function_or_method)
|
||||||
def run_on_core(*args, **kwargs):
|
def run_on_core(*args, **kwargs):
|
||||||
raise RuntimeError("Kernel functions need explicit core.run()")
|
raise RuntimeError("Kernel functions need explicit core.run()")
|
||||||
|
run_on_core.__artiq_kernel__ = True
|
||||||
|
run_on_core.__artiq_destination__ = None
|
||||||
return run_on_core
|
return run_on_core
|
||||||
|
|
||||||
|
def subkernel(function_or_method, destination=0):
|
||||||
|
"""Decorates a function or method to be executed on a satellite core device."""
|
||||||
|
_register_function(function_or_method)
|
||||||
|
@wraps(function_or_method)
|
||||||
|
def run_on_core(*args, **kwargs):
|
||||||
|
raise RuntimeError("Subkernels cannot be called by the host")
|
||||||
|
run_on_core.__artiq_kernel__ = True
|
||||||
|
run_on_core.__artiq_destination__ = destination
|
||||||
|
return function_or_method
|
||||||
|
|
||||||
def portable(function):
|
def portable(function):
|
||||||
"""Decorates a function or method to be executed on the same device (host/core device) as the caller."""
|
"""Decorates a function or method to be executed on the same device (host/core device) as the caller."""
|
||||||
@ -215,8 +226,10 @@ class Core:
|
|||||||
else:
|
else:
|
||||||
obj = method
|
obj = method
|
||||||
name = ""
|
name = ""
|
||||||
|
|
||||||
|
dest = getattr(method, "__artiq_destination__", 0)
|
||||||
|
|
||||||
compiler.compile_method_to_file(obj, name, args, "module.elf", embedding)
|
compiler.compile_method_to_file(obj, name, dest, args, "module.elf", embedding)
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def reset(self):
|
def reset(self):
|
||||||
|
@ -196,7 +196,7 @@ impl Nac3 {
|
|||||||
if let StmtKind::FunctionDef { ref decorator_list, .. } = stmt.node {
|
if let StmtKind::FunctionDef { ref decorator_list, .. } = stmt.node {
|
||||||
decorator_list.iter().any(|decorator| {
|
decorator_list.iter().any(|decorator| {
|
||||||
if let Some(id) = decorator_id_string(decorator) {
|
if let Some(id) = decorator_id_string(decorator) {
|
||||||
id == "kernel" || id == "portable" || id == "rpc"
|
id == "kernel" || id == "portable" || id == "rpc" || id == "subkernel"
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
@ -210,7 +210,7 @@ impl Nac3 {
|
|||||||
StmtKind::FunctionDef { ref decorator_list, .. } => {
|
StmtKind::FunctionDef { ref decorator_list, .. } => {
|
||||||
decorator_list.iter().any(|decorator| {
|
decorator_list.iter().any(|decorator| {
|
||||||
if let Some(id) = decorator_id_string(decorator) {
|
if let Some(id) = decorator_id_string(decorator) {
|
||||||
id == "extern" || id == "kernel" || id == "portable" || id == "rpc"
|
id == "extern" || id == "kernel" || id == "portable" || id == "rpc" || id == "subkernel"
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
@ -361,6 +361,7 @@ impl Nac3 {
|
|||||||
&self,
|
&self,
|
||||||
obj: &PyAny,
|
obj: &PyAny,
|
||||||
method_name: &str,
|
method_name: &str,
|
||||||
|
destination: u8,
|
||||||
args: Vec<&PyAny>,
|
args: Vec<&PyAny>,
|
||||||
embedding_map: &PyAny,
|
embedding_map: &PyAny,
|
||||||
py: Python,
|
py: Python,
|
||||||
@ -382,6 +383,7 @@ impl Nac3 {
|
|||||||
let store_obj = embedding_map.getattr("store_object").unwrap().to_object(py);
|
let store_obj = embedding_map.getattr("store_object").unwrap().to_object(py);
|
||||||
let store_str = embedding_map.getattr("store_str").unwrap().to_object(py);
|
let store_str = embedding_map.getattr("store_str").unwrap().to_object(py);
|
||||||
let store_fun = embedding_map.getattr("store_function").unwrap().to_object(py);
|
let store_fun = embedding_map.getattr("store_function").unwrap().to_object(py);
|
||||||
|
let store_subkernel = embedding_map.getattr("store_subkernel").unwrap().to_object(py);
|
||||||
let host_attributes = embedding_map.getattr("attributes_writeback").unwrap().to_object(py);
|
let host_attributes = embedding_map.getattr("attributes_writeback").unwrap().to_object(py);
|
||||||
let global_value_ids: Arc<RwLock<HashMap<_, _>>> = Arc::new(RwLock::new(HashMap::new()));
|
let global_value_ids: Arc<RwLock<HashMap<_, _>>> = Arc::new(RwLock::new(HashMap::new()));
|
||||||
let helper = PythonHelper {
|
let helper = PythonHelper {
|
||||||
@ -412,6 +414,7 @@ impl Nac3 {
|
|||||||
let mut module_to_resolver_cache: HashMap<u64, _> = HashMap::new();
|
let mut module_to_resolver_cache: HashMap<u64, _> = HashMap::new();
|
||||||
|
|
||||||
let mut rpc_ids = vec![];
|
let mut rpc_ids = vec![];
|
||||||
|
let mut subkernel_ids = vec![];
|
||||||
for (stmt, path, module) in &self.top_levels {
|
for (stmt, path, module) in &self.top_levels {
|
||||||
let py_module: &PyAny = module.extract(py)?;
|
let py_module: &PyAny = module.extract(py)?;
|
||||||
let module_id: u64 = id_fn.call1((py_module,))?.extract()?;
|
let module_id: u64 = id_fn.call1((py_module,))?.extract()?;
|
||||||
@ -495,6 +498,32 @@ impl Nac3 {
|
|||||||
.any(|constant| *constant == Constant::Str("async".into()))
|
.any(|constant| *constant == Constant::Str("async".into()))
|
||||||
});
|
});
|
||||||
rpc_ids.push((None, def_id, is_async));
|
rpc_ids.push((None, def_id, is_async));
|
||||||
|
}
|
||||||
|
else if decorator_list
|
||||||
|
.iter()
|
||||||
|
.any(|decorator| decorator_id_string(decorator) == Some("subkernel".to_string()))
|
||||||
|
{
|
||||||
|
if let Constant::Int(sk_dest) = decorator_get_destination(decorator) {
|
||||||
|
if sk_dest < 0 || sk_dest > 255 {
|
||||||
|
return Err(CompileError::new_err(format!(
|
||||||
|
"compilation failed\n----------\nSubkernel destination must be between 0 and 255 (at {})",
|
||||||
|
stmt.location
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
if sk_dest != destination {
|
||||||
|
// subkernels with the same destination as currently compiled kernel
|
||||||
|
// are treated as normal kernels
|
||||||
|
store_subkernel.call1(py, (def_id.0.into_py(py), module.getattr(py, name.to_string().as_str()).unwrap())).unwrap();
|
||||||
|
subkernel_ids.push((None, def_id, destination));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return Err(CompileError::new_err(format!(
|
||||||
|
"compilation failed\n----------\nDestination must be provided for subkernels (at {})",
|
||||||
|
stmt.location
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StmtKind::ClassDef { name, body, .. } => {
|
StmtKind::ClassDef { name, body, .. } => {
|
||||||
@ -517,6 +546,31 @@ impl Nac3 {
|
|||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
rpc_ids.push((Some((class_obj.clone(), *name)), def_id, is_async));
|
rpc_ids.push((Some((class_obj.clone(), *name)), def_id, is_async));
|
||||||
|
} else if decorator_list.iter().any(|decorator| matches!(decorator.node, ExprKind::Name { id, .. } if id == "subkernel".into())) {
|
||||||
|
if let Constant::Int(sk_dest) = decorator_get_destination(decorator) {
|
||||||
|
if name == &"__init__".into() {
|
||||||
|
return Err(CompileError::new_err(format!(
|
||||||
|
"compilation failed\n----------\nThe constructor of class {} should not be decorated with subkernel decorator (at {})",
|
||||||
|
class_name, stmt.location
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
if sk_dest < 0 || sk_dest > 255 {
|
||||||
|
return Err(CompileError::new_err(format!(
|
||||||
|
"compilation failed\n----------\nSubkernel destination must be between 0 and 255 (at {})",
|
||||||
|
stmt.location
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
if sk_dest != destination {
|
||||||
|
subkernel_ids.push((Some((class_obj.clone(), *name)), def_id, sk_dest));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return Err(CompileError::new_err(format!(
|
||||||
|
"compilation failed\n----------\nDestination must be provided for subkernels (at {})",
|
||||||
|
stmt.location
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -592,7 +646,7 @@ impl Nac3 {
|
|||||||
);
|
);
|
||||||
let signature = store.add_cty(signature);
|
let signature = store.add_cty(signature);
|
||||||
|
|
||||||
if let Err(e) = composer.start_analysis(true) {
|
if let Err(e) = composer.start_analysis(true, Some(destination)) {
|
||||||
// report error of __modinit__ separately
|
// report error of __modinit__ separately
|
||||||
return if e.iter().any(|err| err.contains("<nac3_synthesized_modinit>")) {
|
return if e.iter().any(|err| err.contains("<nac3_synthesized_modinit>")) {
|
||||||
let msg = Self::report_modinit(
|
let msg = Self::report_modinit(
|
||||||
@ -655,6 +709,43 @@ impl Nac3 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (class_data, id, sk_dest) in &subkernel_ids {
|
||||||
|
let mut def = defs[id.0].write();
|
||||||
|
match &mut *def {
|
||||||
|
TopLevelDef::Function { codegen_callback, .. } => {
|
||||||
|
*codegen_callback = Some(subkernel_codegen_callback());
|
||||||
|
}
|
||||||
|
TopLevelDef::Class { methods, .. } => {
|
||||||
|
let (class_def, method_name) = class_data.as_ref().unwrap();
|
||||||
|
for (name, _, id) in &*methods {
|
||||||
|
if name != method_name {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if let TopLevelDef::Function { codegen_callback, .. } =
|
||||||
|
&mut *defs[id.0].write()
|
||||||
|
{
|
||||||
|
*codegen_callback = Some(subkernel_codegen_callback());
|
||||||
|
store_subkernel
|
||||||
|
.call1(
|
||||||
|
py,
|
||||||
|
(
|
||||||
|
id.0.into_py(py),
|
||||||
|
class_def
|
||||||
|
.getattr(py, name.to_string().as_str())
|
||||||
|
.unwrap(),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TopLevelDef::Variable { .. } => {
|
||||||
|
return Err(CompileError::new_err(String::from(
|
||||||
|
"Unsupported @subkernel annotation on global variable",
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let instance = {
|
let instance = {
|
||||||
@ -904,6 +995,20 @@ fn decorator_get_flags(decorator: &Located<ExprKind>) -> Vec<Constant> {
|
|||||||
flags
|
flags
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn decorator_get_destination(decorator: &Located<ExprKind>) -> Option<Constant> {
|
||||||
|
if let ExprKind::Call { keywords, .. } = &decorator.node {
|
||||||
|
for keyword in keywords {
|
||||||
|
if keyword.node.arg != Some("destination".into()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if let ExprKind::Constant { value, .. } = &keyword.node.value.node {
|
||||||
|
return Some(value.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
fn link_with_lld(elf_filename: String, obj_filename: String) -> PyResult<()> {
|
fn link_with_lld(elf_filename: String, obj_filename: String) -> PyResult<()> {
|
||||||
let linker_args = vec![
|
let linker_args = vec![
|
||||||
"-shared".to_string(),
|
"-shared".to_string(),
|
||||||
@ -1116,6 +1221,7 @@ impl Nac3 {
|
|||||||
&mut self,
|
&mut self,
|
||||||
obj: &PyAny,
|
obj: &PyAny,
|
||||||
method_name: &str,
|
method_name: &str,
|
||||||
|
destination: u8,
|
||||||
args: Vec<&PyAny>,
|
args: Vec<&PyAny>,
|
||||||
filename: &str,
|
filename: &str,
|
||||||
embedding_map: &PyAny,
|
embedding_map: &PyAny,
|
||||||
@ -1136,7 +1242,7 @@ impl Nac3 {
|
|||||||
Ok(())
|
Ok(())
|
||||||
};
|
};
|
||||||
|
|
||||||
self.compile_method(obj, method_name, args, embedding_map, py, &link_fn)
|
self.compile_method(obj, method_name, destination, args, embedding_map, py, &link_fn)
|
||||||
} else {
|
} else {
|
||||||
let link_fn = |module: &Module| {
|
let link_fn = |module: &Module| {
|
||||||
let object_mem = target_machine
|
let object_mem = target_machine
|
||||||
@ -1154,7 +1260,7 @@ impl Nac3 {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
self.compile_method(obj, method_name, args, embedding_map, py, &link_fn)
|
self.compile_method(obj, method_name, destination, args, embedding_map, py, &link_fn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1162,6 +1268,7 @@ impl Nac3 {
|
|||||||
&mut self,
|
&mut self,
|
||||||
obj: &PyAny,
|
obj: &PyAny,
|
||||||
method_name: &str,
|
method_name: &str,
|
||||||
|
destination: u8,
|
||||||
args: Vec<&PyAny>,
|
args: Vec<&PyAny>,
|
||||||
embedding_map: &PyAny,
|
embedding_map: &PyAny,
|
||||||
py: Python,
|
py: Python,
|
||||||
@ -1185,7 +1292,7 @@ impl Nac3 {
|
|||||||
Ok(PyBytes::new(py, &fs::read(filename).unwrap()).into())
|
Ok(PyBytes::new(py, &fs::read(filename).unwrap()).into())
|
||||||
};
|
};
|
||||||
|
|
||||||
self.compile_method(obj, method_name, args, embedding_map, py, &link_fn)
|
self.compile_method(obj, method_name, destination, args, embedding_map, py, &link_fn)
|
||||||
} else {
|
} else {
|
||||||
let link_fn = |module: &Module| {
|
let link_fn = |module: &Module| {
|
||||||
let object_mem = target_machine
|
let object_mem = target_machine
|
||||||
@ -1198,7 +1305,7 @@ impl Nac3 {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
self.compile_method(obj, method_name, args, embedding_map, py, &link_fn)
|
self.compile_method(obj, method_name, destination, args, embedding_map, py, &link_fn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
365
nac3artiq/src/subkernels.rs
Normal file
365
nac3artiq/src/subkernels.rs
Normal file
@ -0,0 +1,365 @@
|
|||||||
|
pub struct Subkernels {}
|
||||||
|
|
||||||
|
impl Subkernels {
|
||||||
|
fn get_subkernel_builtins() -> Vec<Box<BuiltinFuncSpec>> {
|
||||||
|
vec![
|
||||||
|
Box::new(|primitives, unifier| {
|
||||||
|
let arg_ty = unifier.get_fresh_var(Some("T".into()), None);
|
||||||
|
(
|
||||||
|
"subkernel_await".into(),
|
||||||
|
FunSignature {
|
||||||
|
args: vec![FuncArg {
|
||||||
|
name: "subkernel".into(),
|
||||||
|
ty: arg_ty.ty,
|
||||||
|
default_value: None,
|
||||||
|
is_vararg: false,
|
||||||
|
},
|
||||||
|
FuncArg {
|
||||||
|
name: "timeout".into(),
|
||||||
|
ty: primitives.int32,
|
||||||
|
default_value: 0,
|
||||||
|
is_vararg: false
|
||||||
|
}],
|
||||||
|
// todo: figure out how to return the type function returns
|
||||||
|
// or catch it in the type inferencer
|
||||||
|
ret: primitives.none,
|
||||||
|
vars: into_var_map([arg_ty]),
|
||||||
|
},
|
||||||
|
Arc::new(GenCall::new(Box::new(move |ctx, obj, fun, args, generator| {
|
||||||
|
gen_subkernel_await(ctx, &obj, fun, &args, generator)?;
|
||||||
|
|
||||||
|
Ok(None)
|
||||||
|
}))),
|
||||||
|
)
|
||||||
|
}),
|
||||||
|
Box::new(|primitives, unifier| {
|
||||||
|
let arg_ty = unifier.get_fresh_var(Some("T".into()), None);
|
||||||
|
(
|
||||||
|
"subkernel_preload".into(),
|
||||||
|
FunSignature {
|
||||||
|
args: vec![
|
||||||
|
FuncArg {
|
||||||
|
name: "subkernel".into(),
|
||||||
|
ty: arg_ty.ty,
|
||||||
|
default_value: None,
|
||||||
|
is_vararg: false,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
ret: primitives.none,
|
||||||
|
vars: into_var_map([arg_ty]),
|
||||||
|
},
|
||||||
|
Arc::new(GenCall::new(Box::new(move |ctx, obj, fun, args, generator| {
|
||||||
|
gen_subkernel_preload(ctx, &obj, fun, &args, generator)?;
|
||||||
|
|
||||||
|
Ok(None)
|
||||||
|
}))),
|
||||||
|
)
|
||||||
|
}),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gen_subkernel_await<'ctx>(
|
||||||
|
ctx: &mut CodeGenContext<'ctx, '_>,
|
||||||
|
obj: &Option<(Type, ValueEnum<'ctx>)>,
|
||||||
|
fun: (&FunSignature, DefinitionId),
|
||||||
|
args: &[(Option<StrRef>, ValueEnum<'ctx>)],
|
||||||
|
generator: &mut dyn CodeGenerator,
|
||||||
|
) {
|
||||||
|
let sid_type = ctx.ctx.i32_type();
|
||||||
|
let timeout_type = ctx.ctx.i64_type();
|
||||||
|
assert!(matches!(args.len(), 1..=2));
|
||||||
|
let timeout = if args.len() == 1 {
|
||||||
|
timeout_type.const_zero().to_basic_value_enum(context, generator, obj_ty)?; // ?
|
||||||
|
} else { args[0].1.clone().to_basic_value_enum(context, generator, obj_ty)?; } // ?
|
||||||
|
|
||||||
|
let subkernel_await_finish = ctx.module.get_function("subkernel_await_finish").unwrap_or_else(|| {
|
||||||
|
ctx.module.add_function(
|
||||||
|
"subkernel_await_finish",
|
||||||
|
ctx.ctx.void_type().fn_type(&[sid_type.into(), timeout_type.into()], false),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
// call or invoke
|
||||||
|
// generate RPC for receiving return value depending on fun ret
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gen_subkernel_preload<'ctx>(
|
||||||
|
ctx: &mut CodeGenContext<'ctx, '_>,
|
||||||
|
obj: &Option<(Type, ValueEnum<'ctx>)>,
|
||||||
|
fun: (&FunSignature, DefinitionId),
|
||||||
|
args: &[(Option<StrRef>, ValueEnum<'ctx>)],
|
||||||
|
generator: &mut dyn CodeGenerator,
|
||||||
|
) {
|
||||||
|
assert_eq!(args.len(), 1);
|
||||||
|
let sid_type = ctx.ctx.i32_type();
|
||||||
|
let dest_type = ctx.ctx.i8_type();
|
||||||
|
let run_type = ctx.ctx.bool_type();
|
||||||
|
let subkernel_load_run = ctx.module.get_function("subkernel_load_run").unwrap_or_else(|| {
|
||||||
|
ctx.module.add_function(
|
||||||
|
"subkernel_load_run",
|
||||||
|
ctx.ctx.void_type().fn_type(&[sid_type.into(), dest_type.into(), run_type.into()], false),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
let subkernel_id = int32.const_int(fun.1 .0 as u64, false);
|
||||||
|
let destination = int32.const_int(fun.? as u64, false); // TODO
|
||||||
|
ctx.builder
|
||||||
|
.build_call_or_invoke(subkernel_load_run, &[subkernel_id.into(), destination.into(), run_type.const_zero()], "subkernel.preload")
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn subkernel_callback_fn<'ctx>(
|
||||||
|
ctx: &mut CodeGenContext<'ctx, '_>,
|
||||||
|
obj: Option<(Type, ValueEnum<'ctx>)>,
|
||||||
|
fun: (&FunSignature, DefinitionId),
|
||||||
|
args: Vec<(Option<StrRef>, ValueEnum<'ctx>)>,
|
||||||
|
generator: &mut dyn CodeGenerator,
|
||||||
|
) -> Result<Option<BasicValueEnum<'ctx>>, String> {
|
||||||
|
let int8 = ctx.ctx.i8_type();
|
||||||
|
let int32 = ctx.ctx.i32_type();
|
||||||
|
let size_type = generator.get_size_type(ctx.ctx);
|
||||||
|
let ptr_type = int8.ptr_type(AddressSpace::default());
|
||||||
|
let tag_ptr_type = ctx.ctx.struct_type(&[ptr_type.into(), size_type.into()], false);
|
||||||
|
|
||||||
|
let subkernel_id = int32.const_int(fun.1 .0 as u64, false);
|
||||||
|
let destination = int32.const_int(fun.? as u64, false); // TODO
|
||||||
|
|
||||||
|
// -- start the subkernel
|
||||||
|
let sid_type = ctx.ctx.i32_type();
|
||||||
|
let dest_type = ctx.ctx.i8_type();
|
||||||
|
let run_type = ctx.ctx.i1_type();
|
||||||
|
let subkernel_start = ctx.module.get_function("subkernel_load_run").unwrap_or_else(|| {
|
||||||
|
ctx.module.add_function(
|
||||||
|
"subkernel_load_run",
|
||||||
|
ctx.ctx.void_type().fn_type(
|
||||||
|
&[
|
||||||
|
ctx.ctx.void_type().fn_type(&[sid_type.into(), dest_type.into(), run_type.into()], false),
|
||||||
|
],
|
||||||
|
false,
|
||||||
|
),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
});
|
||||||
|
ctx.builder
|
||||||
|
.build_call_or_invoke(subkernel_start, &[subkernel_id.into(), destination.into(), run_type.const_int(1, false)], "subkernel.run")
|
||||||
|
.unwrap();
|
||||||
|
// -- setup rpc tags
|
||||||
|
let mut tag = Vec::new();
|
||||||
|
if obj.is_some() {
|
||||||
|
tag.push(b'O');
|
||||||
|
}
|
||||||
|
for arg in &fun.0.args {
|
||||||
|
gen_rpc_tag(ctx, arg.ty, &mut tag)?;
|
||||||
|
}
|
||||||
|
tag.push(b':');
|
||||||
|
gen_rpc_tag(ctx, fun.0.ret, &mut tag)?;
|
||||||
|
|
||||||
|
let mut hasher = DefaultHasher::new();
|
||||||
|
tag.hash(&mut hasher);
|
||||||
|
let hash = format!("{}", hasher.finish());
|
||||||
|
|
||||||
|
let tag_ptr = ctx
|
||||||
|
.module
|
||||||
|
.get_global(hash.as_str())
|
||||||
|
.unwrap_or_else(|| {
|
||||||
|
let tag_arr_ptr = ctx.module.add_global(
|
||||||
|
int8.array_type(tag.len() as u32),
|
||||||
|
None,
|
||||||
|
format!("tagptr{}", fun.1 .0).as_str(),
|
||||||
|
);
|
||||||
|
tag_arr_ptr.set_initializer(&int8.const_array(
|
||||||
|
&tag.iter().map(|v| int8.const_int(u64::from(*v), false)).collect::<Vec<_>>(),
|
||||||
|
));
|
||||||
|
tag_arr_ptr.set_linkage(Linkage::Private);
|
||||||
|
let tag_ptr = ctx.module.add_global(tag_ptr_type, None, &hash);
|
||||||
|
tag_ptr.set_linkage(Linkage::Private);
|
||||||
|
tag_ptr.set_initializer(&ctx.ctx.const_struct(
|
||||||
|
&[
|
||||||
|
tag_arr_ptr.as_pointer_value().const_cast(ptr_type).into(),
|
||||||
|
size_type.const_int(tag.len() as u64, false).into(),
|
||||||
|
],
|
||||||
|
false,
|
||||||
|
));
|
||||||
|
tag_ptr
|
||||||
|
})
|
||||||
|
.as_pointer_value();
|
||||||
|
|
||||||
|
let arg_length = args.len() + usize::from(obj.is_some());
|
||||||
|
|
||||||
|
let stackptr = call_stacksave(ctx, Some("subkernel.stack"));
|
||||||
|
let args_ptr = ctx
|
||||||
|
.builder
|
||||||
|
.build_array_alloca(
|
||||||
|
ptr_type,
|
||||||
|
ctx.ctx.i32_type().const_int(arg_length as u64, false),
|
||||||
|
"argptr",
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// -- rpc args handling
|
||||||
|
let mut keys = fun.0.args.clone();
|
||||||
|
let mut mapping = HashMap::new();
|
||||||
|
for (key, value) in args {
|
||||||
|
mapping.insert(key.unwrap_or_else(|| keys.remove(0).name), value);
|
||||||
|
}
|
||||||
|
// default value handling
|
||||||
|
for k in keys {
|
||||||
|
mapping
|
||||||
|
.insert(k.name, ctx.gen_symbol_val(generator, &k.default_value.unwrap(), k.ty).into());
|
||||||
|
}
|
||||||
|
// reorder the parameters
|
||||||
|
let mut real_params = fun
|
||||||
|
.0
|
||||||
|
.args
|
||||||
|
.iter()
|
||||||
|
.map(|arg| {
|
||||||
|
mapping
|
||||||
|
.remove(&arg.name)
|
||||||
|
.unwrap()
|
||||||
|
.to_basic_value_enum(ctx, generator, arg.ty)
|
||||||
|
.map(|llvm_val| (llvm_val, arg.ty))
|
||||||
|
})
|
||||||
|
.collect::<Result<Vec<(_, _)>, _>>()?;
|
||||||
|
if let Some(obj) = obj {
|
||||||
|
if let ValueEnum::Static(obj_val) = obj.1 {
|
||||||
|
real_params.insert(0, (obj_val.get_const_obj(ctx, generator), obj.0));
|
||||||
|
} else {
|
||||||
|
// should be an error here...
|
||||||
|
panic!("only host object is allowed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i, (arg, arg_ty)) in real_params.iter().enumerate() {
|
||||||
|
let arg_slot = format_rpc_arg(generator, ctx, (*arg, *arg_ty, i));
|
||||||
|
let arg_ptr = unsafe {
|
||||||
|
ctx.builder.build_gep(
|
||||||
|
args_ptr,
|
||||||
|
&[int32.const_int(i as u64, false)],
|
||||||
|
&format!("subkernel.arg{i}"),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.unwrap();
|
||||||
|
ctx.builder.build_store(arg_ptr, arg_slot).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
// send the message
|
||||||
|
let subkernel_send = ctx.module.get_function("subkernel_send_message").unwrap_or_else(|| {
|
||||||
|
ctx.module.add_function(
|
||||||
|
"subkernel_send_message",
|
||||||
|
ctx.ctx.void_type().fn_type(
|
||||||
|
&[
|
||||||
|
int32.into(),
|
||||||
|
tag_ptr_type.ptr_type(AddressSpace::default()).into(),
|
||||||
|
ptr_type.ptr_type(AddressSpace::default()).into(),
|
||||||
|
],
|
||||||
|
false,
|
||||||
|
),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
});
|
||||||
|
ctx.builder
|
||||||
|
.build_call_or_invoke(subkernel_send, &[service_id.into(), tag_ptr.into(), args_ptr.into()], "subkernel.send")
|
||||||
|
.unwrap();
|
||||||
|
// reclaim stack space used by arguments
|
||||||
|
call_stackrestore(ctx, stackptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn subkernel_codegen_callback() -> Arc<GenCall> {
|
||||||
|
Arc::new(GenCall::new(Box::new(|ctx, obj, fun, args, generator| {
|
||||||
|
subkernel_codegen_callback_fn(ctx, obj, fun, args, generator)
|
||||||
|
})))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn subkernel_recv_message<'ctx>(
|
||||||
|
ctx: &mut CodeGenContext<'ctx, '_>,
|
||||||
|
obj: Option<(Type, ValueEnum<'ctx>)>,
|
||||||
|
fun: (&FunSignature, DefinitionId),
|
||||||
|
args: Vec<(Option<StrRef>, ValueEnum<'ctx>)>,
|
||||||
|
generator: &mut dyn CodeGenerator,
|
||||||
|
) -> Result<Option<BasicValueEnum<'ctx>>, String> {
|
||||||
|
|
||||||
|
// await for the message first
|
||||||
|
let int8 = ctx.ctx.i8_type();
|
||||||
|
let int64 = ctx.ctx.i64_type();
|
||||||
|
let size_type = generator.get_size_type(ctx.ctx);
|
||||||
|
let ptr_type = int8.ptr_type(AddressSpace::default());
|
||||||
|
let tag_ptr_type = ctx.ctx.struct_type(&[ptr_type.into(), size_type.into()], false);
|
||||||
|
|
||||||
|
let subkernel_await_message = ctx.module.get_function("subkernel_await_message").unwrap_or_else(|| {
|
||||||
|
ctx.module.add_function(
|
||||||
|
"subkernel_await_message",
|
||||||
|
ctx.ctx.void_type().fn_type(
|
||||||
|
&[
|
||||||
|
ctx.ctx.void_type().fn_type(&[int8.into(), int64.into(), tag_ptr_type.into(), int8.into(), int8.into()], false),
|
||||||
|
],
|
||||||
|
false,
|
||||||
|
),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
ctx.builder
|
||||||
|
.build_call_or_invoke(subkernel_await_message, &[subkernel_id.into(), destination.into(), run_type.const_int(1, false)], "subkernel.run")
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// -- receive value:
|
||||||
|
// T result = {
|
||||||
|
// void *ret_ptr = alloca(sizeof(T));
|
||||||
|
// void *ptr = ret_ptr;
|
||||||
|
// loop: int size = rpc_recv(ptr);
|
||||||
|
// // Non-zero: Provide `size` bytes of extra storage for variable-length data.
|
||||||
|
// if(size) { ptr = alloca(size); goto loop; }
|
||||||
|
// else *(T*)ret_ptr
|
||||||
|
// }
|
||||||
|
let rpc_recv = ctx.module.get_function("rpc_recv").unwrap_or_else(|| {
|
||||||
|
ctx.module.add_function("rpc_recv", int32.fn_type(&[ptr_type.into()], false), None)
|
||||||
|
});
|
||||||
|
|
||||||
|
if ctx.unifier.unioned(fun.0.ret, ctx.primitives.none) {
|
||||||
|
ctx.build_call_or_invoke(rpc_recv, &[ptr_type.const_null().into()], "rpc_recv");
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
|
||||||
|
let prehead_bb = ctx.builder.get_insert_block().unwrap();
|
||||||
|
let current_function = prehead_bb.get_parent().unwrap();
|
||||||
|
let head_bb = ctx.ctx.append_basic_block(current_function, "rpc.head");
|
||||||
|
let alloc_bb = ctx.ctx.append_basic_block(current_function, "rpc.continue");
|
||||||
|
let tail_bb = ctx.ctx.append_basic_block(current_function, "rpc.tail");
|
||||||
|
|
||||||
|
let ret_ty = ctx.get_llvm_abi_type(generator, fun.0.ret);
|
||||||
|
let need_load = !ret_ty.is_pointer_type();
|
||||||
|
let slot = ctx.builder.build_alloca(ret_ty, "rpc.ret.slot").unwrap();
|
||||||
|
let slotgen = ctx.builder.build_bitcast(slot, ptr_type, "rpc.ret.ptr").unwrap();
|
||||||
|
ctx.builder.build_unconditional_branch(head_bb).unwrap();
|
||||||
|
ctx.builder.position_at_end(head_bb);
|
||||||
|
|
||||||
|
let phi = ctx.builder.build_phi(ptr_type, "rpc.ptr").unwrap();
|
||||||
|
phi.add_incoming(&[(&slotgen, prehead_bb)]);
|
||||||
|
let alloc_size = ctx
|
||||||
|
.build_call_or_invoke(rpc_recv, &[phi.as_basic_value()], "rpc.size.next")
|
||||||
|
.unwrap()
|
||||||
|
.into_int_value();
|
||||||
|
let is_done = ctx
|
||||||
|
.builder
|
||||||
|
.build_int_compare(inkwell::IntPredicate::EQ, int32.const_zero(), alloc_size, "rpc.done")
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
ctx.builder.build_conditional_branch(is_done, tail_bb, alloc_bb).unwrap();
|
||||||
|
ctx.builder.position_at_end(alloc_bb);
|
||||||
|
|
||||||
|
let alloc_ptr = ctx.builder.build_array_alloca(ptr_type, alloc_size, "rpc.alloc").unwrap();
|
||||||
|
let alloc_ptr = ctx.builder.build_bitcast(alloc_ptr, ptr_type, "rpc.alloc.ptr").unwrap();
|
||||||
|
phi.add_incoming(&[(&alloc_ptr, alloc_bb)]);
|
||||||
|
ctx.builder.build_unconditional_branch(head_bb).unwrap();
|
||||||
|
|
||||||
|
ctx.builder.position_at_end(tail_bb);
|
||||||
|
|
||||||
|
let result = ctx.builder.build_load(slot, "rpc.result").unwrap();
|
||||||
|
if need_load {
|
||||||
|
call_stackrestore(ctx, stackptr);
|
||||||
|
}
|
||||||
|
Ok(Some(result))
|
||||||
|
}
|
||||||
|
}
|
@ -10,7 +10,6 @@ constant-optimization = ["fold"]
|
|||||||
fold = []
|
fold = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
lazy_static = "1.5"
|
|
||||||
parking_lot = "0.12"
|
parking_lot = "0.12"
|
||||||
string-interner = "0.17"
|
string-interner = "0.17"
|
||||||
fxhash = "0.2"
|
fxhash = "0.2"
|
||||||
|
@ -5,14 +5,12 @@ pub use crate::location::Location;
|
|||||||
|
|
||||||
use fxhash::FxBuildHasher;
|
use fxhash::FxBuildHasher;
|
||||||
use parking_lot::{Mutex, MutexGuard};
|
use parking_lot::{Mutex, MutexGuard};
|
||||||
use std::{cell::RefCell, collections::HashMap, fmt};
|
use std::{cell::RefCell, collections::HashMap, fmt, sync::LazyLock};
|
||||||
use string_interner::{symbol::SymbolU32, DefaultBackend, StringInterner};
|
use string_interner::{symbol::SymbolU32, DefaultBackend, StringInterner};
|
||||||
|
|
||||||
pub type Interner = StringInterner<DefaultBackend, FxBuildHasher>;
|
pub type Interner = StringInterner<DefaultBackend, FxBuildHasher>;
|
||||||
lazy_static! {
|
static INTERNER: LazyLock<Mutex<Interner>> =
|
||||||
static ref INTERNER: Mutex<Interner> =
|
LazyLock::new(|| Mutex::new(StringInterner::with_hasher(FxBuildHasher::default())));
|
||||||
Mutex::new(StringInterner::with_hasher(FxBuildHasher::default()));
|
|
||||||
}
|
|
||||||
|
|
||||||
thread_local! {
|
thread_local! {
|
||||||
static LOCAL_INTERNER: RefCell<HashMap<String, StrRef>> = RefCell::default();
|
static LOCAL_INTERNER: RefCell<HashMap<String, StrRef>> = RefCell::default();
|
||||||
|
@ -14,9 +14,6 @@
|
|||||||
clippy::wildcard_imports
|
clippy::wildcard_imports
|
||||||
)]
|
)]
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
extern crate lazy_static;
|
|
||||||
|
|
||||||
mod ast_gen;
|
mod ast_gen;
|
||||||
mod constant;
|
mod constant;
|
||||||
#[cfg(feature = "fold")]
|
#[cfg(feature = "fold")]
|
||||||
|
@ -1777,7 +1777,12 @@ pub fn gen_unaryop_expr_with_values<'ctx, G: CodeGenerator>(
|
|||||||
ast::Unaryop::Invert => ctx.builder.build_not(val, "not").map(Into::into).unwrap(),
|
ast::Unaryop::Invert => ctx.builder.build_not(val, "not").map(Into::into).unwrap(),
|
||||||
ast::Unaryop::Not => ctx
|
ast::Unaryop::Not => ctx
|
||||||
.builder
|
.builder
|
||||||
.build_xor(val, val.get_type().const_all_ones(), "not")
|
.build_int_compare(
|
||||||
|
inkwell::IntPredicate::EQ,
|
||||||
|
val,
|
||||||
|
val.get_type().const_zero(),
|
||||||
|
"not",
|
||||||
|
)
|
||||||
.map(Into::into)
|
.map(Into::into)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
ast::Unaryop::UAdd => val.into(),
|
ast::Unaryop::UAdd => val.into(),
|
||||||
|
@ -463,13 +463,13 @@ impl TopLevelComposer {
|
|||||||
Ok((name, DefinitionId(self.definition_ast_list.len() - 1), Some(ty_to_be_unified)))
|
Ok((name, DefinitionId(self.definition_ast_list.len() - 1), Some(ty_to_be_unified)))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start_analysis(&mut self, inference: bool) -> Result<(), HashSet<String>> {
|
pub fn start_analysis(&mut self, inference: bool, destination: Option<u8>) -> Result<(), HashSet<String>> {
|
||||||
self.analyze_top_level_class_type_var()?;
|
self.analyze_top_level_class_type_var()?;
|
||||||
self.analyze_top_level_class_bases()?;
|
self.analyze_top_level_class_bases()?;
|
||||||
self.analyze_top_level_class_fields_methods()?;
|
self.analyze_top_level_class_fields_methods()?;
|
||||||
self.analyze_top_level_function()?;
|
self.analyze_top_level_function()?;
|
||||||
if inference {
|
if inference {
|
||||||
self.analyze_function_instance()?;
|
self.analyze_function_instance(destination)?;
|
||||||
}
|
}
|
||||||
self.analyze_top_level_variables()?;
|
self.analyze_top_level_variables()?;
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -1736,7 +1736,8 @@ impl TopLevelComposer {
|
|||||||
|
|
||||||
/// step 5, analyze and call type inferencer to fill the `instance_to_stmt` of
|
/// step 5, analyze and call type inferencer to fill the `instance_to_stmt` of
|
||||||
/// [`TopLevelDef::Function`]
|
/// [`TopLevelDef::Function`]
|
||||||
fn analyze_function_instance(&mut self) -> Result<(), HashSet<String>> {
|
/// destination is an ARTIQ-only argument necessary for proper support of subkernels
|
||||||
|
fn analyze_function_instance(&mut self, destination: Option<u8>) -> Result<(), HashSet<String>> {
|
||||||
// first get the class constructor type correct for the following type check in function body
|
// first get the class constructor type correct for the following type check in function body
|
||||||
// also do class field instantiation check
|
// also do class field instantiation check
|
||||||
let init_str_id = "__init__".into();
|
let init_str_id = "__init__".into();
|
||||||
@ -2134,6 +2135,28 @@ impl TopLevelComposer {
|
|||||||
instance_to_symbol.insert(String::new(), simple_name.to_string());
|
instance_to_symbol.insert(String::new(), simple_name.to_string());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if let ExprKind::Call { func, keywords, .. } = &decorator_list[0].node {
|
||||||
|
if matches!(&func.node, ExprKind::Name { id, .. } if id == &"subkernel".into())
|
||||||
|
{
|
||||||
|
let subkernel_dest = keywords.iter().find(|keyword| {
|
||||||
|
if keyword.node.arg == Some("destination".into()) {
|
||||||
|
match &keyword.node.value.node {
|
||||||
|
ExprKind::Constant { .. } => true,
|
||||||
|
_ => false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
).node.value.node.value;
|
||||||
|
// treat subkernel as kernel if the destination is the same as currently compiled
|
||||||
|
if let Some(Constant::Int(sk_dest)) = subkernel_dest {
|
||||||
|
if sk_dest != destination.unwrap_or(0) {
|
||||||
|
instance_to_symbol.insert(String::new(), simple_name.to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if matches!(&decorator_list[0].node, ExprKind::Name { id, .. } if id == &"rpc".into())
|
if matches!(&decorator_list[0].node, ExprKind::Name { id, .. } if id == &"rpc".into())
|
||||||
{
|
{
|
||||||
|
@ -199,7 +199,7 @@ fn test_simple_function_analyze(source: &[&str], tys: &[&str], names: &[&str]) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
composer.start_analysis(true).unwrap();
|
composer.start_analysis(true, None).unwrap();
|
||||||
|
|
||||||
for (i, (def, _)) in composer.definition_ast_list.iter().skip(composer.builtin_num).enumerate()
|
for (i, (def, _)) in composer.definition_ast_list.iter().skip(composer.builtin_num).enumerate()
|
||||||
{
|
{
|
||||||
@ -563,7 +563,7 @@ fn test_analyze(source: &[&str], res: &[&str]) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Err(msg) = composer.start_analysis(false) {
|
if let Err(msg) = composer.start_analysis(false, None) {
|
||||||
if print {
|
if print {
|
||||||
println!("{}", msg.iter().sorted().join("\n----------\n"));
|
println!("{}", msg.iter().sorted().join("\n----------\n"));
|
||||||
} else {
|
} else {
|
||||||
@ -748,7 +748,7 @@ fn test_inference(source: Vec<&str>, res: &[&str]) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Err(msg) = composer.start_analysis(true) {
|
if let Err(msg) = composer.start_analysis(true, None) {
|
||||||
if print {
|
if print {
|
||||||
println!("{}", msg.iter().sorted().join("\n----------\n"));
|
println!("{}", msg.iter().sorted().join("\n----------\n"));
|
||||||
} else {
|
} else {
|
||||||
|
@ -408,7 +408,7 @@ fn main() {
|
|||||||
let signature = store.from_signature(&mut composer.unifier, &primitive, &signature, &mut cache);
|
let signature = store.from_signature(&mut composer.unifier, &primitive, &signature, &mut cache);
|
||||||
let signature = store.add_cty(signature);
|
let signature = store.add_cty(signature);
|
||||||
|
|
||||||
if let Err(errors) = composer.start_analysis(true) {
|
if let Err(errors) = composer.start_analysis(true, None) {
|
||||||
let error_count = errors.len();
|
let error_count = errors.len();
|
||||||
eprintln!("{error_count} error(s) occurred during top level analysis.");
|
eprintln!("{error_count} error(s) occurred during top level analysis.");
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user