From 55caa8d61b7c71e03d506ec79a76e5ae28612ce3 Mon Sep 17 00:00:00 2001 From: Mark Poliakov Date: Sat, 9 Mar 2024 15:49:42 +0200 Subject: [PATCH] Initial commit for kernel-side --- Cargo.lock | 5 ++ Cargo.toml | 14 +++-- handler/Cargo.toml | 9 +++ handler/src/lib.rs | 0 src/abi/mod.rs | 12 +++- src/abi/syscall.rs | 121 ++++++++++++++++++++++++++++++++++++ src/abi/ty/complex.rs | 9 +++ src/abi/ty/mod.rs | 6 ++ src/abi/ty/primitive.rs | 9 +++ src/abi/ty/simple.rs | 9 +++ src/lib.rs | 77 +---------------------- src/syntax/bitfield_type.rs | 6 +- src/syntax/common.rs | 4 +- src/syntax/document.rs | 4 +- src/syntax/enum_type.rs | 4 +- src/syntax/extern_block.rs | 4 +- src/syntax/mod.rs | 11 ++-- src/syntax/newtype.rs | 2 +- src/syntax/syscall.rs | 4 +- 19 files changed, 206 insertions(+), 104 deletions(-) create mode 100644 handler/Cargo.toml create mode 100644 handler/src/lib.rs create mode 100644 src/abi/syscall.rs diff --git a/Cargo.lock b/Cargo.lock index cb89790b..350c4606 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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", diff --git a/Cargo.toml b/Cargo.toml index bc98dd3a..2f369341 100644 --- a/Cargo.toml +++ b/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"] diff --git a/handler/Cargo.toml b/handler/Cargo.toml new file mode 100644 index 00000000..a3818d5d --- /dev/null +++ b/handler/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "handler" +version = "0.1.0" +edition = "2021" + +[dependencies] + +[lib] +proc-macro = true diff --git a/handler/src/lib.rs b/handler/src/lib.rs new file mode 100644 index 00000000..e69de29b diff --git a/src/abi/mod.rs b/src/abi/mod.rs index 02add9a5..b33cf0de 100644 --- a/src/abi/mod.rs +++ b/src/abi/mod.rs @@ -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 for usize { + fn from(value: SyscallFunction) -> usize { + value as usize + } + } }); stream.append_all(self.abi.generate_user_side(&self.target_env)); diff --git a/src/abi/syscall.rs b/src/abi/syscall.rs new file mode 100644 index 00000000..c5127357 --- /dev/null +++ b/src/abi/syscall.rs @@ -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)>, + pub return_type: Option>, +} + +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::(); + let args = args + .iter() + .map(|(name, ty)| { + let ty = ty.as_rust_type(); + quote!(#name: #ty,) + }) + .collect::(); + 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 + } +} diff --git a/src/abi/ty/complex.rs b/src/abi/ty/complex.rs index 97188168..b0a2c29a 100644 --- a/src/abi/ty/complex.rs +++ b/src/abi/ty/complex.rs @@ -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 { diff --git a/src/abi/ty/mod.rs b/src/abi/ty/mod.rs index dc6fc37e..5225aa6b 100644 --- a/src/abi/ty/mod.rs +++ b/src/abi/ty/mod.rs @@ -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(); diff --git a/src/abi/ty/primitive.rs b/src/abi/ty/primitive.rs index 804d8c68..1288f06e 100644 --- a/src/abi/ty/primitive.rs +++ b/src/abi/ty/primitive.rs @@ -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 { diff --git a/src/abi/ty/simple.rs b/src/abi/ty/simple.rs index 9a3c43aa..9eb8ddd5 100644 --- a/src/abi/ty/simple.rs +++ b/src/abi/ty/simple.rs @@ -101,4 +101,13 @@ impl Type for SimpleType { }, } } + + fn emit_from_syscall_arguments( + &self, + _env: &TargetEnv, + _args: &Ident, + _index: usize, + ) -> (TokenStream, usize) { + todo!() + } } diff --git a/src/lib.rs b/src/lib.rs index da99e273..bc49ae63 100644 --- a/src/lib.rs +++ b/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)>, - pub return_type: Option>, -} - -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::(); - let args = args - .iter() - .map(|(name, ty)| { - let ty = ty.as_rust_type(); - quote!(#name: #ty,) - }) - .collect::(); - 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 - } -} diff --git a/src/syntax/bitfield_type.rs b/src/syntax/bitfield_type.rs index 9b0c318d..da3288ef 100644 --- a/src/syntax/bitfield_type.rs +++ b/src/syntax/bitfield_type.rs @@ -35,7 +35,7 @@ impl DocumentItemAttributes for BitfieldType { } impl syn::parse::Parse for BitfieldRange { - fn parse(input: syn::parse::ParseStream) -> syn::Result { + fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result { let start = input.parse()?; if input.peek(Token![..]) { input.parse::()?; @@ -48,7 +48,7 @@ impl syn::parse::Parse for BitfieldRange { } impl syn::parse::Parse for BitfieldTypeField { - fn parse(input: syn::parse::ParseStream) -> syn::Result { + fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result { let attributes = input.parse()?; let name = input.parse()?; input.parse::()?; @@ -62,7 +62,7 @@ impl syn::parse::Parse for BitfieldTypeField { } impl syn::parse::Parse for BitfieldType { - fn parse(input: syn::parse::ParseStream) -> syn::Result { + fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result { let fields; let attributes = input.parse()?; let name = input.parse()?; diff --git a/src/syntax/common.rs b/src/syntax/common.rs index 292a692d..06d7ff39 100644 --- a/src/syntax/common.rs +++ b/src/syntax/common.rs @@ -30,13 +30,13 @@ impl DerefMut for Attributes { } impl syn::parse::Parse for Attributes { - fn parse(input: syn::parse::ParseStream) -> syn::Result { + fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result { syn::Attribute::parse_outer(input).map(Self) } } impl syn::parse::Parse for TypeRepr { - fn parse(input: syn::parse::ParseStream) -> syn::Result { + fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result { let content; parenthesized!(content in input); let content = content.parse_terminated(syn::Ident::parse, Token![,])?; diff --git a/src/syntax/document.rs b/src/syntax/document.rs index be1c2b3b..71cee8ea 100644 --- a/src/syntax/document.rs +++ b/src/syntax/document.rs @@ -39,7 +39,7 @@ enum DocumentItem { } impl syn::parse::Parse for DocumentItem { - fn parse(input: ParseStream) -> syn::Result { + fn parse(input: ParseStream<'_>) -> syn::Result { 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 { + fn parse(input: ParseStream<'_>) -> syn::Result { let mut types = vec![]; let mut syscalls = vec![]; diff --git a/src/syntax/enum_type.rs b/src/syntax/enum_type.rs index 824454c1..328d165d 100644 --- a/src/syntax/enum_type.rs +++ b/src/syntax/enum_type.rs @@ -23,7 +23,7 @@ pub struct EnumType { } impl syn::parse::Parse for EnumTypeVariant { - fn parse(input: syn::parse::ParseStream) -> syn::Result { + fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result { 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 { + fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result { let variants; let attributes = input.parse()?; let name = input.parse()?; diff --git a/src/syntax/extern_block.rs b/src/syntax/extern_block.rs index 9e25fd2d..6c204572 100644 --- a/src/syntax/extern_block.rs +++ b/src/syntax/extern_block.rs @@ -16,7 +16,7 @@ pub struct ExternTypeBlock { } impl syn::parse::Parse for ExternType { - fn parse(input: syn::parse::ParseStream) -> syn::Result { + fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result { let attributes = input.parse()?; input.parse::()?; 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 { + fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result { let types; braced!(types in input); let types = types.parse_terminated(ExternType::parse, Token![;])?; diff --git a/src/syntax/mod.rs b/src/syntax/mod.rs index ad5096cc..a158f9f3 100644 --- a/src/syntax/mod.rs +++ b/src/syntax/mod.rs @@ -2,13 +2,10 @@ use std::{collections::HashMap, rc::Rc, str::FromStr}; use syn::{punctuated::Punctuated, Expr, ExprLit, Lit, PathSegment}; -use crate::{ - abi::{ - syscall_enum_variant_identifier, - ty::{complex::ExternKind, AbiPrimitive, ComplexType, SimpleType}, - Abi, - }, - Syscall, +use crate::abi::{ + syscall_enum_variant_identifier, + ty::{complex::ExternKind, AbiPrimitive, ComplexType, SimpleType}, + Abi, Syscall, }; mod common; diff --git a/src/syntax/newtype.rs b/src/syntax/newtype.rs index f46d6475..40242182 100644 --- a/src/syntax/newtype.rs +++ b/src/syntax/newtype.rs @@ -22,7 +22,7 @@ impl DocumentItemAttributes for NewType { } impl syn::parse::Parse for NewType { - fn parse(input: syn::parse::ParseStream) -> syn::Result { + fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result { let attributes = input.parse()?; let name = input.parse()?; let repr = input.parse()?; diff --git a/src/syntax/syscall.rs b/src/syntax/syscall.rs index 1e670882..5c6caf56 100644 --- a/src/syntax/syscall.rs +++ b/src/syntax/syscall.rs @@ -22,7 +22,7 @@ impl DocumentItemAttributes for SyscallDefinition { } impl syn::parse::Parse for SyscallDefinition { - fn parse(input: ParseStream) -> syn::Result { + fn parse(input: ParseStream<'_>) -> syn::Result { 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 { + fn parse(input: ParseStream<'_>) -> syn::Result { let name = input.parse()?; input.parse::()?; let ty = input.parse()?;