Initial commit for kernel-side
This commit is contained in:
parent
05fa15df56
commit
55caa8d61b
5
Cargo.lock
generated
5
Cargo.lock
generated
@ -9,6 +9,10 @@ dependencies = [
|
||||
"syscall-generator",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "handler"
|
||||
version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "prettyplease"
|
||||
version = "0.2.16"
|
||||
@ -52,6 +56,7 @@ dependencies = [
|
||||
name = "syscall-generator"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"handler",
|
||||
"prettyplease",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
14
Cargo.toml
14
Cargo.toml
@ -4,11 +4,13 @@ version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
prettyplease = "0.2.16"
|
||||
proc-macro2 = "1.0.78"
|
||||
quote = "1.0.35"
|
||||
syn = { version = "2.0.52", features = ["full"] }
|
||||
thiserror = "1.0.57"
|
||||
prettyplease = "0.2.15"
|
||||
proc-macro2 = "^1.0.63"
|
||||
quote = "^1.0"
|
||||
syn = { version = "2.0.32", features = ["full"] }
|
||||
thiserror = "1.0.47"
|
||||
|
||||
handler = { path = "handler", optional = true }
|
||||
|
||||
[workspace]
|
||||
members = ["example-abi"]
|
||||
members = ["example-abi", "handler"]
|
||||
|
9
handler/Cargo.toml
Normal file
9
handler/Cargo.toml
Normal file
@ -0,0 +1,9 @@
|
||||
[package]
|
||||
name = "handler"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
0
handler/src/lib.rs
Normal file
0
handler/src/lib.rs
Normal file
@ -13,11 +13,15 @@ use crate::{
|
||||
parse_abi, Attributes, BitfieldRange, BitfieldType, BitfieldTypeField,
|
||||
DocumentTypeDefinition, EnumType, NewType, ParseError, TypeRepr,
|
||||
},
|
||||
Syscall, TargetEnv,
|
||||
TargetEnv,
|
||||
};
|
||||
|
||||
use self::ty::Type;
|
||||
|
||||
mod syscall;
|
||||
|
||||
pub use syscall::Syscall;
|
||||
|
||||
pub trait GenerateTypeDefinition {
|
||||
fn generate_type_definition(&self, abi_type: &ComplexType, env: &TargetEnv) -> TokenStream;
|
||||
}
|
||||
@ -95,6 +99,12 @@ impl AbiBuilder {
|
||||
pub enum SyscallFunction {
|
||||
#syscall_discriminants
|
||||
}
|
||||
|
||||
impl From<SyscallFunction> for usize {
|
||||
fn from(value: SyscallFunction) -> usize {
|
||||
value as usize
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
stream.append_all(self.abi.generate_user_side(&self.target_env));
|
||||
|
121
src/abi/syscall.rs
Normal file
121
src/abi/syscall.rs
Normal file
@ -0,0 +1,121 @@
|
||||
use core::fmt;
|
||||
use std::rc::Rc;
|
||||
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
|
||||
use crate::{
|
||||
abi::ty::{SimpleType, Type},
|
||||
TargetEnv,
|
||||
};
|
||||
|
||||
use super::ty::ComplexType;
|
||||
|
||||
pub struct Syscall {
|
||||
pub name: syn::Ident,
|
||||
pub args: Vec<(syn::Ident, Rc<ComplexType>)>,
|
||||
pub return_type: Option<Rc<ComplexType>>,
|
||||
}
|
||||
|
||||
impl fmt::Debug for Syscall {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("Syscall")
|
||||
.field("name", &self.name)
|
||||
.field("args", &self.args)
|
||||
.field("return_type", &self.return_type)
|
||||
.finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
|
||||
impl Syscall {
|
||||
// Syntax:
|
||||
//
|
||||
// syscall_handler!("abi-document.abi", pub syscall_handler {
|
||||
// read(fd, buffer) => ...,
|
||||
// write(fd, buffer) => ...,
|
||||
// })
|
||||
pub fn emit_handler_branch(
|
||||
&self,
|
||||
named_args: &[&syn::Ident],
|
||||
raw_args: &syn::Ident,
|
||||
body: &syn::ExprBlock,
|
||||
enum_variant: &syn::Ident,
|
||||
env: &TargetEnv,
|
||||
) -> TokenStream {
|
||||
if self.args.len() != named_args.len() {
|
||||
todo!()
|
||||
}
|
||||
|
||||
let mut extracted_arguments = TokenStream::new();
|
||||
let mut index = 0;
|
||||
|
||||
for ((_, arg), &name) in std::iter::zip(self.args.iter(), named_args) {
|
||||
let (arg_expr, arg_width) = arg.emit_from_syscall_arguments(env, raw_args, index);
|
||||
let arg_assignment = quote! {
|
||||
let #name = #arg_expr;
|
||||
};
|
||||
index += arg_width;
|
||||
|
||||
extracted_arguments.extend(arg_assignment);
|
||||
}
|
||||
|
||||
quote! {
|
||||
#enum_variant => {
|
||||
#extracted_arguments
|
||||
|
||||
#body
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn emit_stub(&self, enum_variant: &syn::Ident, env: &TargetEnv) -> TokenStream {
|
||||
let Self {
|
||||
name,
|
||||
args,
|
||||
return_type,
|
||||
} = self;
|
||||
|
||||
let syscall_args = args
|
||||
.iter()
|
||||
.map(|(name, ty)| {
|
||||
let arg = ty.emit_to_syscall_arguments(env, name);
|
||||
quote!(#arg,)
|
||||
})
|
||||
.collect::<TokenStream>();
|
||||
let args = args
|
||||
.iter()
|
||||
.map(|(name, ty)| {
|
||||
let ty = ty.as_rust_type();
|
||||
quote!(#name: #ty,)
|
||||
})
|
||||
.collect::<TokenStream>();
|
||||
let return_type_arrow = return_type.as_ref().map(|ty| {
|
||||
let ty = ty.as_rust_type();
|
||||
quote!(-> #ty)
|
||||
});
|
||||
|
||||
let sys_call = quote!(syscall!(SyscallFunction::#enum_variant, #syscall_args));
|
||||
|
||||
let wrapped = match return_type.as_deref() {
|
||||
Some(ComplexType::Simple(SimpleType::Never)) => {
|
||||
quote! {
|
||||
#sys_call;
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
Some(ty) => {
|
||||
let ty = ty.as_rust_type();
|
||||
quote!(<#ty>::from_syscall_register(#sys_call))
|
||||
}
|
||||
None => quote!(#sys_call;),
|
||||
};
|
||||
|
||||
let v = quote! {
|
||||
pub unsafe fn #name(#args) #return_type_arrow {
|
||||
#wrapped
|
||||
}
|
||||
};
|
||||
println!("{}", v);
|
||||
v
|
||||
}
|
||||
}
|
@ -113,6 +113,15 @@ impl Type for ComplexType {
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn emit_from_syscall_arguments(
|
||||
&self,
|
||||
_env: &TargetEnv,
|
||||
_args: &Ident,
|
||||
_index: usize,
|
||||
) -> (TokenStream, usize) {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for ComplexType {
|
||||
|
@ -25,6 +25,12 @@ pub trait Type {
|
||||
fn as_rust_type(&self) -> TokenStream;
|
||||
|
||||
fn emit_to_syscall_arguments(&self, env: &TargetEnv, value: &Ident) -> TokenStream;
|
||||
fn emit_from_syscall_arguments(
|
||||
&self,
|
||||
env: &TargetEnv,
|
||||
args: &Ident,
|
||||
index: usize,
|
||||
) -> (TokenStream, usize);
|
||||
|
||||
fn as_rust_ref_type(&self, mutable: bool) -> TokenStream {
|
||||
let inner = self.as_rust_type();
|
||||
|
@ -60,6 +60,15 @@ impl Type for AbiPrimitive {
|
||||
fn emit_to_syscall_arguments(&self, _env: &TargetEnv, value: &Ident) -> TokenStream {
|
||||
quote!(#value as usize)
|
||||
}
|
||||
|
||||
fn emit_from_syscall_arguments(
|
||||
&self,
|
||||
_env: &TargetEnv,
|
||||
_args: &Ident,
|
||||
_index: usize,
|
||||
) -> (TokenStream, usize) {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for AbiPrimitive {
|
||||
|
@ -101,4 +101,13 @@ impl Type for SimpleType {
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn emit_from_syscall_arguments(
|
||||
&self,
|
||||
_env: &TargetEnv,
|
||||
_args: &Ident,
|
||||
_index: usize,
|
||||
) -> (TokenStream, usize) {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
77
src/lib.rs
77
src/lib.rs
@ -1,88 +1,13 @@
|
||||
#![feature(if_let_guard, extend_one, proc_macro_span)]
|
||||
|
||||
use std::{fmt, rc::Rc};
|
||||
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
use syn::Ident;
|
||||
|
||||
use crate::abi::ty::{ComplexType, SimpleType, Type, TypeWidth};
|
||||
use crate::abi::ty::TypeWidth;
|
||||
|
||||
pub mod abi;
|
||||
pub mod error;
|
||||
pub mod syntax;
|
||||
|
||||
pub struct Syscall {
|
||||
pub name: Ident,
|
||||
pub args: Vec<(Ident, Rc<ComplexType>)>,
|
||||
pub return_type: Option<Rc<ComplexType>>,
|
||||
}
|
||||
|
||||
impl fmt::Debug for Syscall {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("Syscall")
|
||||
.field("name", &self.name)
|
||||
.field("args", &self.args)
|
||||
.field("return_type", &self.return_type)
|
||||
.finish_non_exhaustive()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||
pub struct TargetEnv {
|
||||
pub thin_pointer_width: TypeWidth,
|
||||
pub fat_pointer_width: TypeWidth,
|
||||
}
|
||||
|
||||
impl Syscall {
|
||||
pub fn emit_stub(&self, enum_variant: &syn::Ident, env: &TargetEnv) -> TokenStream {
|
||||
let Self {
|
||||
name,
|
||||
args,
|
||||
return_type,
|
||||
} = self;
|
||||
|
||||
let syscall_args = args
|
||||
.iter()
|
||||
.map(|(name, ty)| {
|
||||
let arg = ty.emit_to_syscall_arguments(env, name);
|
||||
quote!(#arg,)
|
||||
})
|
||||
.collect::<TokenStream>();
|
||||
let args = args
|
||||
.iter()
|
||||
.map(|(name, ty)| {
|
||||
let ty = ty.as_rust_type();
|
||||
quote!(#name: #ty,)
|
||||
})
|
||||
.collect::<TokenStream>();
|
||||
let return_type_arrow = return_type.as_ref().map(|ty| {
|
||||
let ty = ty.as_rust_type();
|
||||
quote!(-> #ty)
|
||||
});
|
||||
|
||||
let sys_call = quote!(syscall!(SyscallFunction::#enum_variant, #syscall_args));
|
||||
|
||||
let wrapped = match return_type.as_deref() {
|
||||
Some(ComplexType::Simple(SimpleType::Never)) => {
|
||||
quote! {
|
||||
#sys_call;
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
Some(ty) => {
|
||||
let ty = ty.as_rust_type();
|
||||
quote!(<#ty>::from_syscall_register(#sys_call))
|
||||
}
|
||||
None => quote!(#sys_call;),
|
||||
};
|
||||
|
||||
let v = quote! {
|
||||
pub unsafe fn #name(#args) #return_type_arrow {
|
||||
#wrapped
|
||||
}
|
||||
};
|
||||
println!("{}", v);
|
||||
v
|
||||
}
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ impl DocumentItemAttributes for BitfieldType {
|
||||
}
|
||||
|
||||
impl syn::parse::Parse for BitfieldRange {
|
||||
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
|
||||
fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
|
||||
let start = input.parse()?;
|
||||
if input.peek(Token![..]) {
|
||||
input.parse::<Token![..]>()?;
|
||||
@ -48,7 +48,7 @@ impl syn::parse::Parse for BitfieldRange {
|
||||
}
|
||||
|
||||
impl syn::parse::Parse for BitfieldTypeField {
|
||||
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
|
||||
fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
|
||||
let attributes = input.parse()?;
|
||||
let name = input.parse()?;
|
||||
input.parse::<Token![:]>()?;
|
||||
@ -62,7 +62,7 @@ impl syn::parse::Parse for BitfieldTypeField {
|
||||
}
|
||||
|
||||
impl syn::parse::Parse for BitfieldType {
|
||||
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
|
||||
fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
|
||||
let fields;
|
||||
let attributes = input.parse()?;
|
||||
let name = input.parse()?;
|
||||
|
@ -30,13 +30,13 @@ impl DerefMut for Attributes {
|
||||
}
|
||||
|
||||
impl syn::parse::Parse for Attributes {
|
||||
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
|
||||
fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
|
||||
syn::Attribute::parse_outer(input).map(Self)
|
||||
}
|
||||
}
|
||||
|
||||
impl syn::parse::Parse for TypeRepr {
|
||||
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
|
||||
fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
|
||||
let content;
|
||||
parenthesized!(content in input);
|
||||
let content = content.parse_terminated(syn::Ident::parse, Token![,])?;
|
||||
|
@ -39,7 +39,7 @@ enum DocumentItem {
|
||||
}
|
||||
|
||||
impl syn::parse::Parse for DocumentItem {
|
||||
fn parse(input: ParseStream) -> syn::Result<Self> {
|
||||
fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
|
||||
let lookahead = input.lookahead1();
|
||||
|
||||
if lookahead.peek(Token![extern]) {
|
||||
@ -87,7 +87,7 @@ impl DocumentItemAttributes for DocumentItem {
|
||||
}
|
||||
|
||||
impl syn::parse::Parse for Document {
|
||||
fn parse(input: ParseStream) -> syn::Result<Self> {
|
||||
fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
|
||||
let mut types = vec![];
|
||||
let mut syscalls = vec![];
|
||||
|
||||
|
@ -23,7 +23,7 @@ pub struct EnumType {
|
||||
}
|
||||
|
||||
impl syn::parse::Parse for EnumTypeVariant {
|
||||
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
|
||||
fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
|
||||
let attributes = input.parse()?;
|
||||
let discriminant = input.parse()?;
|
||||
let value = if input.peek(Token![=]) {
|
||||
@ -42,7 +42,7 @@ impl syn::parse::Parse for EnumTypeVariant {
|
||||
}
|
||||
|
||||
impl syn::parse::Parse for EnumType {
|
||||
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
|
||||
fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
|
||||
let variants;
|
||||
let attributes = input.parse()?;
|
||||
let name = input.parse()?;
|
||||
|
@ -16,7 +16,7 @@ pub struct ExternTypeBlock {
|
||||
}
|
||||
|
||||
impl syn::parse::Parse for ExternType {
|
||||
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
|
||||
fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
|
||||
let attributes = input.parse()?;
|
||||
input.parse::<Token![type]>()?;
|
||||
let name = input.parse()?;
|
||||
@ -35,7 +35,7 @@ impl syn::parse::Parse for ExternType {
|
||||
}
|
||||
|
||||
impl syn::parse::Parse for ExternTypeBlock {
|
||||
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
|
||||
fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
|
||||
let types;
|
||||
braced!(types in input);
|
||||
let types = types.parse_terminated(ExternType::parse, Token![;])?;
|
||||
|
@ -2,13 +2,10 @@ use std::{collections::HashMap, rc::Rc, str::FromStr};
|
||||
|
||||
use syn::{punctuated::Punctuated, Expr, ExprLit, Lit, PathSegment};
|
||||
|
||||
use crate::{
|
||||
abi::{
|
||||
use crate::abi::{
|
||||
syscall_enum_variant_identifier,
|
||||
ty::{complex::ExternKind, AbiPrimitive, ComplexType, SimpleType},
|
||||
Abi,
|
||||
},
|
||||
Syscall,
|
||||
Abi, Syscall,
|
||||
};
|
||||
|
||||
mod common;
|
||||
|
@ -22,7 +22,7 @@ impl DocumentItemAttributes for NewType {
|
||||
}
|
||||
|
||||
impl syn::parse::Parse for NewType {
|
||||
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
|
||||
fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result<Self> {
|
||||
let attributes = input.parse()?;
|
||||
let name = input.parse()?;
|
||||
let repr = input.parse()?;
|
||||
|
@ -22,7 +22,7 @@ impl DocumentItemAttributes for SyscallDefinition {
|
||||
}
|
||||
|
||||
impl syn::parse::Parse for SyscallDefinition {
|
||||
fn parse(input: ParseStream) -> syn::Result<Self> {
|
||||
fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
|
||||
let arguments;
|
||||
|
||||
let name = input.parse()?;
|
||||
@ -49,7 +49,7 @@ impl syn::parse::Parse for SyscallDefinition {
|
||||
}
|
||||
|
||||
impl syn::parse::Parse for SyscallArgument {
|
||||
fn parse(input: ParseStream) -> syn::Result<Self> {
|
||||
fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
|
||||
let name = input.parse()?;
|
||||
input.parse::<Token![:]>()?;
|
||||
let ty = input.parse()?;
|
||||
|
Loading…
x
Reference in New Issue
Block a user