Skip to content

Commit

Permalink
Add all the stuff back in that Git forgot about (#70)
Browse files Browse the repository at this point in the history
remove some unnecessary leftovers from ip addr implementation

more docs on parameters and reflect

cargo fmt

start on supporting prefixes

pffff

implement IpAddr eq via Rust's implementation

fix returning ZST from runtime function

macros register functions and (static) methods

upgrade cranelift to (unreleased) 0.113.0 for correct prefix alignment
  • Loading branch information
tertsdiepraam authored Sep 30, 2024
1 parent d7f7b17 commit aad83a7
Show file tree
Hide file tree
Showing 22 changed files with 1,046 additions and 261 deletions.
17 changes: 12 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,6 @@ categories = ["network-programming"]
# is released
ariadne = { version = "0.4.0", git = "https://github.com/zesterer/ariadne.git", rev = "4e5987cd55d954858da4a4130255eca1bf0bee5f" }
clap = { version = "4.4.6", features = ["derive"] }
cranelift = "0.107.0"
cranelift-codegen = { version = "0.107.0", features = ["disas"] }
cranelift-jit = "0.107.0"
cranelift-module = "0.107.0"
cranelift-native = "0.107.0"
env_logger = "0.10"
log = "0.4"
logos = "0.14.0"
Expand All @@ -33,6 +28,18 @@ symbol_table = { version = "0.3.0", features = ["global"] }
string-interner = "0.17.0"
roto-macros = { path = "macros" }

[dependencies.cranelift]
version = "0.113.0"
features = ["frontend", "jit", "module", "native"]
git = "https://github.com/bytecodealliance/wasmtime.git"
rev = "1af294ea2d6c18c5a8fa9b4f272398b7c98e0c48"

[dependencies.cranelift-codegen]
version = "0.113.0"
features = ["disas"]
git = "https://github.com/bytecodealliance/wasmtime.git"
rev = "1af294ea2d6c18c5a8fa9b4f272398b7c98e0c48"

[dev-dependencies]
bytes = "1"
routecore = { version = "0.4.0", features = ["bgp", "bmp"] }
Expand Down
13 changes: 6 additions & 7 deletions examples/simple.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,23 @@
use roto::{read_files, Runtime, Verdict};
use roto_macros::roto_function;
use roto_macros::roto_method;

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

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

fn main() -> Result<(), roto::RotoReport> {
env_logger::init();

let mut runtime = Runtime::basic().unwrap();

runtime.register_type::<Bla>().unwrap();
runtime.register_method::<Bla, _, _>("y", get_y).unwrap();

#[roto_method(runtime, Bla, y)]
fn get_y(bla: *const Bla) -> u32 {
unsafe { &*bla }.y
}

let mut compiled = read_files(["examples/simple.roto"])?
.compile(runtime, usize::BITS / 8)
Expand Down
186 changes: 157 additions & 29 deletions macros/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,30 +1,153 @@
use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, ItemFn};

///
///
/// ```rust,no_run
/// fn foo(a1: A1, a2: A2) -> Ret {
/// /* ... */
/// }
/// ```
///
///
use syn::{parse_macro_input, Token};

struct Intermediate {
function: proc_macro2::TokenStream,
name: syn::Ident,
identifier: proc_macro2::TokenStream,
}

struct FunctionArgs {
runtime_ident: syn::Ident,
name: Option<syn::Ident>,
}

impl syn::parse::Parse for FunctionArgs {
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
let runtime_ident = input.parse()?;

let mut name = None;
if input.peek(Token![,]) {
input.parse::<Token![,]>()?;
if input.peek(syn::Ident) {
name = input.parse()?;
}
}

Ok(Self {
runtime_ident,
name,
})
}
}

#[proc_macro_attribute]
pub fn roto_function(attr: TokenStream, item: TokenStream) -> TokenStream {
let item = parse_macro_input!(item as syn::ItemFn);
let Intermediate {
function,
identifier,
name: function_ident,
} = generate_function(item);

let FunctionArgs {
runtime_ident,
name,
} = syn::parse(attr).unwrap();

let name = name.unwrap_or(function_ident);

let expanded = quote! {
#function

#runtime_ident.register_function(stringify!(#name), #identifier).unwrap();
};

TokenStream::from(expanded)
}

struct MethodArgs {
runtime_ident: syn::Ident,
ty: syn::Type,
name: Option<syn::Ident>,
}

impl syn::parse::Parse for MethodArgs {
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
let runtime_ident = input.parse()?;
input.parse::<Token![,]>()?;
let ty = input.parse()?;

let mut name = None;
if input.peek(Token![,]) {
input.parse::<Token![,]>()?;
if input.peek(syn::Ident) {
name = input.parse()?;
}
}
Ok(Self {
runtime_ident,
ty,
name,
})
}
}

#[proc_macro_attribute]
pub fn roto_method(attr: TokenStream, item: TokenStream) -> TokenStream {
let item = parse_macro_input!(item as syn::ItemFn);
let Intermediate {
function,
identifier,
name: function_name,
} = generate_function(item);

let MethodArgs {
runtime_ident,
ty,
name,
} = parse_macro_input!(attr as MethodArgs);

let name = name.unwrap_or(function_name);

let expanded = quote! {
#function

#runtime_ident.register_method::<#ty, _, _>(stringify!(#name), #identifier).unwrap();
};

TokenStream::from(expanded)
}

#[proc_macro_attribute]
pub fn roto_function(_attr: TokenStream, item: TokenStream) -> TokenStream {
let input = parse_macro_input!(item as ItemFn);
pub fn roto_static_method(
attr: TokenStream,
item: TokenStream,
) -> TokenStream {
let item = parse_macro_input!(item as syn::ItemFn);
let Intermediate {
function,
identifier,
name: function_name,
} = generate_function(item);

let MethodArgs {
runtime_ident,
ty,
name,
} = parse_macro_input!(attr as MethodArgs);

let ItemFn {
let name = name.unwrap_or(function_name);

let expanded = quote! {
#function

#runtime_ident.register_static_method::<#ty, _, _>(stringify!(#name), #identifier).unwrap();
};

TokenStream::from(expanded)
}

fn generate_function(item: syn::ItemFn) -> Intermediate {
let syn::ItemFn {
attrs,
vis,
sig,
block: _,
} = input.clone();
} = item.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;
Expand All @@ -35,6 +158,7 @@ pub fn roto_function(_attr: TokenStream, item: TokenStream) -> TokenStream {
pat
});

let generics = sig.generics;
let inputs = sig.inputs.clone().into_iter();
let ret = match sig.output {
syn::ReturnType::Default => quote!(()),
Expand All @@ -53,21 +177,25 @@ pub fn roto_function(_attr: TokenStream, item: TokenStream) -> TokenStream {
})
.collect();

let arg_types = quote!(*mut #ret, #(#input_types,)*);
let underscored_types = input_types.iter().map(|_| quote!(_));
let arg_types = quote!(_, #(#underscored_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
let function = quote! {
#(#attrs)*
#vis extern "C" fn #ident #generics ( out: *mut #ret, #(#inputs,)* ) {
#item

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

#ident as extern "C" fn(#arg_types)
};
let identifier = quote! {
#ident as extern "C" fn(#arg_types)
};

TokenStream::from(expanded)
Intermediate {
function,
name: ident,
identifier,
}
}
8 changes: 1 addition & 7 deletions src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ pub enum Literal {
#[allow(dead_code)]
String(String),
Asn(Asn),
IpAddress(IpAddress),
IpAddress(std::net::IpAddr),
Integer(i64),
Bool(bool),
}
Expand Down Expand Up @@ -313,9 +313,3 @@ impl std::fmt::Display for BinOp {
)
}
}

#[derive(Clone, Debug)]
pub enum IpAddress {
Ipv4(std::net::Ipv4Addr),
Ipv6(std::net::Ipv6Addr),
}
Loading

0 comments on commit aad83a7

Please sign in to comment.