Skip to content

Commit

Permalink
Merge pull request #68 from NLnetLabs/function-macro
Browse files Browse the repository at this point in the history
Add macro for roto functions to reduce some boilerplate
  • Loading branch information
tertsdiepraam authored Sep 30, 2024
2 parents 172659e + e57d465 commit d7f7b17
Show file tree
Hide file tree
Showing 18 changed files with 377 additions and 233 deletions.
24 changes: 19 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
[package]
name = "roto"
version = "0.2.1-dev"
edition = "2021"
authors = ["NLnet Labs <routing-team@nlnetlabs.nl>"]
version.workspace = true
edition.workspace = true
authors.workspace = true
rust-version.workspace = true
license.workspace = true
description = "strongly-typed, compiled language for Rotonda"
documentation = "https://docs.rs/roto/"
repository = "https://github.com/NLnetLabs/roto/"
homepage = "https://www.nlnetlabs.nl/projects/routing/rotonda/"
keywords = ["routing", "bgp"]
categories = ["network-programming"]
license = "BSD-3-Clause"
rust-version = "1.80"



[dependencies]
# ariadne is set to git because of some unpublished contributions made on
Expand All @@ -28,6 +30,8 @@ log = "0.4"
logos = "0.14.0"
inetnum = "0.1.0"
symbol_table = { version = "0.3.0", features = ["global"] }
string-interner = "0.17.0"
roto-macros = { path = "macros" }

[dev-dependencies]
bytes = "1"
Expand All @@ -38,3 +42,13 @@ inherits = "release"
lto = true
strip = "none"
debug = "full"

[workspace]
members = ["macros"]

[workspace.package]
version = "0.2.1-dev"
edition = "2021"
authors = ["NLnet Labs <routing-team@nlnetlabs.nl>"]
license = "BSD-3-Clause"
rust-version = "1.80"
8 changes: 4 additions & 4 deletions examples/simple.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
use roto::{read_files, Runtime, Verdict};
use roto_macros::roto_function;

struct Bla {
_x: u16,
y: u32,
_z: u32,
}

extern "C" fn get_y(bla: *const Bla) -> u32 {
#[roto_function]
fn get_y(bla: *const Bla) -> u32 {
unsafe { &*bla }.y
}

Expand All @@ -16,9 +18,7 @@ fn main() -> Result<(), roto::RotoReport> {
let mut runtime = Runtime::basic().unwrap();

runtime.register_type::<Bla>().unwrap();
runtime
.register_method::<Bla, _, _>("y", get_y as extern "C" fn(_) -> _)
.unwrap();
runtime.register_method::<Bla, _, _>("y", get_y).unwrap();

let mut compiled = read_files(["examples/simple.roto"])?
.compile(runtime, usize::BITS / 8)
Expand Down
15 changes: 15 additions & 0 deletions macros/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[package]
name = "roto-macros"
version.workspace = true
edition.workspace = true
authors.workspace = true
rust-version.workspace = true
license.workspace = true

[lib]
proc-macro = true

[dependencies]
proc-macro2 = "1.0.86"
quote = "1.0.37"
syn = { version = "2.0.77", features = ["full"] }
1 change: 1 addition & 0 deletions macros/LICENSE
73 changes: 73 additions & 0 deletions macros/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, ItemFn};

///
///
/// ```rust,no_run
/// fn foo(a1: A1, a2: A2) -> Ret {
/// /* ... */
/// }
/// ```
///
///
#[proc_macro_attribute]
pub fn roto_function(_attr: TokenStream, item: TokenStream) -> TokenStream {
let input = parse_macro_input!(item as ItemFn);

let ItemFn {
attrs,
vis,
sig,
block: _,
} = input.clone();

assert!(sig.unsafety.is_none());
assert!(sig.generics.params.is_empty());
assert!(sig.generics.where_clause.is_none());
assert!(sig.variadic.is_none());

let ident = sig.ident;
let args = sig.inputs.iter().map(|i| {
let syn::FnArg::Typed(syn::PatType { pat, .. }) = i else {
panic!()
};
pat
});

let inputs = sig.inputs.clone().into_iter();
let ret = match sig.output {
syn::ReturnType::Default => quote!(()),
syn::ReturnType::Type(_, t) => quote!(#t),
};

let input_types: Vec<_> = sig
.inputs
.clone()
.into_iter()
.map(|i| {
let syn::FnArg::Typed(syn::PatType { ty, .. }) = i else {
panic!()
};
ty
})
.collect();

let arg_types = quote!(*mut #ret, #(#input_types,)*);

let expanded = quote! {
#[allow(non_upper_case_globals)]
#vis const #ident: extern "C" fn(#arg_types) = {
#(#attrs)*
extern "C" fn #ident ( out: *mut #ret, #(#inputs,)* ) {
#input

unsafe { *out = #ident(#(#args),*) };
}

#ident as extern "C" fn(#arg_types)
};
};

TokenStream::from(expanded)
}
12 changes: 11 additions & 1 deletion src/codegen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,16 @@ mod tests;
#[derive(Clone)]
pub struct ModuleData(Arc<ManuallyDrop<JITModule>>);

// Just a simple debug to print _something_. We print the Arc pointer to
// distinguish different ModuleData instances.
impl std::fmt::Debug for ModuleData {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("ModuleData")
.field(&Arc::as_ptr(&self.0))
.finish()
}
}

impl From<JITModule> for ModuleData {
fn from(value: JITModule) -> Self {
#[allow(clippy::arc_with_non_send_sync)]
Expand Down Expand Up @@ -89,7 +99,7 @@ pub struct Module {
type_info: TypeInfo,
}

#[derive(Clone)]
#[derive(Clone, Debug)]
pub struct TypedFunc<Params, Return> {
func: *const u8,
return_by_ref: bool,
Expand Down
Loading

0 comments on commit d7f7b17

Please sign in to comment.