Initial commit for kernel-side

This commit is contained in:
Mark Poliakov 2024-03-09 15:49:42 +02:00
parent 05fa15df56
commit 55caa8d61b
19 changed files with 206 additions and 104 deletions

5
Cargo.lock generated
View File

@ -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",

View File

@ -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
View 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
View File

View 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
View 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
}
}

View File

@ -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 {

View File

@ -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();

View File

@ -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 {

View File

@ -101,4 +101,13 @@ impl Type for SimpleType {
},
}
}
fn emit_from_syscall_arguments(
&self,
_env: &TargetEnv,
_args: &Ident,
_index: usize,
) -> (TokenStream, usize) {
todo!()
}
}

View File

@ -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
}
}

View File

@ -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()?;

View File

@ -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![,])?;

View File

@ -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![];

View File

@ -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()?;

View File

@ -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![;])?;

View File

@ -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;

View File

@ -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()?;

View File

@ -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()?;