Ability to read ABI from string
This commit is contained in:
parent
aab7ac67c3
commit
635bf51bb1
10
Cargo.lock
generated
10
Cargo.lock
generated
@ -12,16 +12,6 @@ dependencies = [
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "abi-kernel-macros"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"abi-generator",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "abi-lib"
|
||||
version = "0.1.0"
|
||||
|
@ -10,4 +10,4 @@ syn = { version = "2.0.32", features = ["full"] }
|
||||
thiserror = "1.0.47"
|
||||
|
||||
[workspace]
|
||||
members = ["abi-lib", "example-abi", "abi-kernel-macros"]
|
||||
members = ["abi-lib", "example-abi"]
|
||||
|
@ -1,14 +0,0 @@
|
||||
[package]
|
||||
name = "abi-kernel-macros"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
proc-macro2 = "1.0.78"
|
||||
quote = "1.0.35"
|
||||
syn = { version = "2.0.52", features = ["full"] }
|
||||
|
||||
abi-generator = { path = ".." }
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
@ -1,106 +0,0 @@
|
||||
use abi_generator::{
|
||||
abi::{ty::TypeWidth, Abi},
|
||||
syntax::UnwrapFancy,
|
||||
TargetEnv,
|
||||
};
|
||||
use proc_macro::TokenStream as TokenStream1;
|
||||
use proc_macro2::Span;
|
||||
use quote::quote;
|
||||
use syn::{parse_macro_input, punctuated::Punctuated, Token};
|
||||
|
||||
enum DispatcherAbiPath {
|
||||
Env(syn::LitStr),
|
||||
}
|
||||
|
||||
struct DispatcherInput {
|
||||
abi_document_path: DispatcherAbiPath,
|
||||
dispatcher_name: syn::Ident,
|
||||
impl_module: syn::Path,
|
||||
}
|
||||
|
||||
impl syn::parse::Parse for DispatcherAbiPath {
|
||||
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
|
||||
let key = input.parse::<syn::Ident>()?;
|
||||
input.parse::<Token![=]>()?;
|
||||
let value = input.parse::<syn::LitStr>()?;
|
||||
|
||||
match key.to_string().as_str() {
|
||||
"env" => Ok(Self::Env(value)),
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl syn::parse::Parse for DispatcherInput {
|
||||
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
|
||||
let abi_document_path = input.parse()?;
|
||||
input.parse::<Token![,]>()?;
|
||||
let dispatcher_name = input.parse()?;
|
||||
input.parse::<Token![,]>()?;
|
||||
let impl_module = input.parse()?;
|
||||
Ok(Self {
|
||||
abi_document_path,
|
||||
dispatcher_name,
|
||||
impl_module,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl DispatcherAbiPath {
|
||||
pub fn value(&self) -> String {
|
||||
match self {
|
||||
Self::Env(var) => std::env::var(var.value()).unwrap(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[proc_macro]
|
||||
pub fn syscall_dispatcher(input: TokenStream1) -> TokenStream1 {
|
||||
let input = parse_macro_input!(input as DispatcherInput);
|
||||
let abi = Abi::read(input.abi_document_path.value()).unwrap_fancy("TODO: proper error here");
|
||||
|
||||
let env = TargetEnv {
|
||||
thin_pointer_width: TypeWidth::U64,
|
||||
fat_pointer_width: TypeWidth::U128,
|
||||
};
|
||||
|
||||
let handler_module = input.impl_module;
|
||||
|
||||
let raw_fn = syn::Ident::new("__fn", Span::call_site());
|
||||
let raw_args = syn::Ident::new("__args", Span::call_site());
|
||||
|
||||
let mut branches = Punctuated::<_, Token![,]>::new();
|
||||
|
||||
for (enum_variant, syscall) in abi.syscalls.iter() {
|
||||
let named_args = (0..syscall.args.len())
|
||||
.map(|i| syn::Ident::new(&format!("__a{}", i), Span::call_site()))
|
||||
.collect::<Vec<_>>();
|
||||
let call_args = named_args
|
||||
.iter()
|
||||
.cloned()
|
||||
.collect::<Punctuated<_, Token![,]>>();
|
||||
let syscall_name = &syscall.name;
|
||||
|
||||
let handler_fn = quote! { #handler_module::#syscall_name };
|
||||
|
||||
let body = quote! {
|
||||
Ok((#handler_fn(#call_args)).into_syscall_register())
|
||||
};
|
||||
|
||||
let match_arm =
|
||||
syscall.emit_handler_branch(&named_args, &raw_args, body, enum_variant, &env);
|
||||
|
||||
branches.push(match_arm);
|
||||
}
|
||||
|
||||
let dispatcher_name = input.dispatcher_name;
|
||||
let dispatcher_fn = quote! {
|
||||
pub(crate) fn #dispatcher_name(#raw_fn: SyscallFunction, #raw_args: &[usize]) -> Result<usize, Error> {
|
||||
match #raw_fn {
|
||||
#branches
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
dispatcher_fn.into()
|
||||
}
|
@ -1,12 +1,8 @@
|
||||
use std::{collections::HashMap, path::Path, rc::Rc};
|
||||
|
||||
use proc_macro2::TokenStream;
|
||||
use proc_macro2::{Span, TokenStream};
|
||||
use quote::{quote, TokenStreamExt};
|
||||
use syn::{
|
||||
punctuated::Punctuated,
|
||||
spanned::Spanned,
|
||||
token::{self},
|
||||
};
|
||||
use syn::{punctuated::Punctuated, spanned::Spanned, token, Token};
|
||||
|
||||
pub mod ty;
|
||||
|
||||
@ -92,10 +88,67 @@ pub fn syscall_enum_variant_identifier(name: &syn::Ident) -> syn::Ident {
|
||||
|
||||
impl AbiBuilder {
|
||||
pub fn from_file<P: AsRef<Path>>(path: P, target_env: TargetEnv) -> Result<Self, ParseError> {
|
||||
let abi = Abi::read(path)?;
|
||||
let abi = Abi::read_file(path)?;
|
||||
Ok(Self { abi, target_env })
|
||||
}
|
||||
|
||||
pub fn from_string<S: AsRef<str>>(data: S, target_env: TargetEnv) -> Result<Self, ParseError> {
|
||||
let abi = Abi::read_string(data)?;
|
||||
Ok(Self { abi, target_env })
|
||||
}
|
||||
|
||||
pub fn emit_syscall_dispatcher(
|
||||
&self,
|
||||
dispatcher_fn: &str,
|
||||
impl_mod: &str,
|
||||
) -> Result<syn::File, ParseError> {
|
||||
let dispatcher_fn = syn::Ident::new(dispatcher_fn, Span::call_site());
|
||||
let impl_mod = syn::Ident::new(impl_mod, Span::call_site());
|
||||
|
||||
let raw_fn = syn::Ident::new("__fn", Span::call_site());
|
||||
let raw_args = syn::Ident::new("__args", Span::call_site());
|
||||
|
||||
let mut branches = Punctuated::<_, Token![,]>::new();
|
||||
|
||||
for (enum_variant, syscall) in self.abi.syscalls.iter() {
|
||||
let named_args = (0..syscall.args.len())
|
||||
.map(|i| syn::Ident::new(&format!("__a{}", i), Span::call_site()))
|
||||
.collect::<Vec<_>>();
|
||||
let call_args = named_args
|
||||
.iter()
|
||||
.cloned()
|
||||
.collect::<Punctuated<_, Token![,]>>();
|
||||
let syscall_name = &syscall.name;
|
||||
|
||||
let handler_fn = quote! { #impl_mod::#syscall_name };
|
||||
|
||||
let body = quote! {
|
||||
Ok((#handler_fn(#call_args)).into_syscall_register())
|
||||
};
|
||||
|
||||
let match_arm = syscall.emit_handler_branch(
|
||||
&named_args,
|
||||
&raw_args,
|
||||
body,
|
||||
enum_variant,
|
||||
&self.target_env,
|
||||
);
|
||||
|
||||
branches.push(match_arm);
|
||||
}
|
||||
|
||||
let dispatcher_fn = quote! {
|
||||
pub(crate) fn #dispatcher_fn(#raw_fn: SyscallFunction, #raw_args: &[usize]) -> Result<usize, Error> {
|
||||
match #raw_fn {
|
||||
#branches
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let file = syn::parse_file(&dispatcher_fn.to_string())?;
|
||||
Ok(file)
|
||||
}
|
||||
|
||||
pub fn emit_file(&self, emit_types: bool, emit_calls: bool) -> Result<syn::File, ParseError> {
|
||||
let mut stream = TokenStream::new();
|
||||
|
||||
@ -188,10 +241,14 @@ impl AbiBuilder {
|
||||
}
|
||||
|
||||
impl Abi {
|
||||
pub fn read<P: AsRef<Path>>(path: P) -> Result<Self, ParseError> {
|
||||
pub fn read_file<P: AsRef<Path>>(path: P) -> Result<Self, ParseError> {
|
||||
let data = std::fs::read_to_string(path)?;
|
||||
parse_abi(&data)
|
||||
}
|
||||
|
||||
pub fn read_string<S: AsRef<str>>(data: S) -> Result<Self, ParseError> {
|
||||
parse_abi(data.as_ref())
|
||||
}
|
||||
}
|
||||
|
||||
impl GenerateTypeDefinition for EnumType {
|
||||
|
Loading…
x
Reference in New Issue
Block a user