mmtk_macros/
lib.rs

1use proc_macro::TokenStream;
2use proc_macro_error::proc_macro_error;
3use syn::parse_macro_input;
4use syn::DeriveInput;
5
6mod has_spaces_impl;
7mod plan_trace_object_impl;
8mod util;
9
10const DEBUG_MACRO_OUTPUT: bool = false;
11
12/// This macro will generate an implementation of `HasSpaces` for a plan or any structs that
13/// contain spaces, including `Gen`, `CommonPlan` and `BasePlan`.
14///
15/// The `HasSpaces` trait is responsible for enumerating spaces in a struct.  When using this
16/// derive macro, the user should do the following.
17///
18/// * Make sure the struct has a generic type parameter named `VM` which requires `VMBinding`.
19///   For example, `struct MyPlan<VM: VMBinding>` will work.
20/// * Add `#[space]` for each space field in the struct.
21/// * Add `#[parent]` to the field that contain more space fields.  This attribute is usually
22///   added to `Gen`, `CommonPlan` or `BasePlan` fields.  There can be at most one parent in
23///   a struct.
24#[proc_macro_error]
25#[proc_macro_derive(HasSpaces, attributes(space, parent))]
26pub fn derive_has_spaces(input: TokenStream) -> TokenStream {
27    let input = parse_macro_input!(input as DeriveInput);
28    let output = has_spaces_impl::derive(input);
29
30    output.into()
31}
32
33/// The macro will generate an implementation of `PlanTraceObject` for the plan. With
34/// `PlanTraceObject`, the plan will be able to use `PlanProcessEdges` for GC tracing.
35///
36/// The user should add `#[space]` and `#[parent]` attributes to fields as specified by the
37/// `HasSpaces` trait.  When using this derive macro, all spaces must implement the
38/// `PolicyTraceObject` trait.  The generated `trace_object` method will check for spaces in the
39/// current plan and, if the object is not in any of them, check for plans in the parent struct.
40/// The parent struct must also implement the `PlanTraceObject` trait.
41///
42/// In addition, the user can add the following attributes to fields in order to control the
43/// behavior of the generated `trace_object` method.
44///
45/// * Add `#[copy_semantics(CopySemantics::X)]` to a space field to specify that when tracing
46///   objects in that space, `Some(CopySemantics::X)` will be passed to the `Space::trace_object`
47///   method as the `copy` argument.
48/// * Add `#[post_scan]` to any space field that has some policy-specific `post_scan_object()`. For
49///   objects in those spaces, `post_scan_object()` in the policy will be called after
50///   `VM::VMScanning::scan_object()`.
51#[proc_macro_error]
52#[proc_macro_derive(PlanTraceObject, attributes(space, parent, copy_semantics, post_scan))]
53pub fn derive_plan_trace_object(input: TokenStream) -> TokenStream {
54    let input = parse_macro_input!(input as DeriveInput);
55    let output = plan_trace_object_impl::derive(input);
56
57    // Debug the output - use the following code to debug the generated code (when cargo exapand is not working)
58    if DEBUG_MACRO_OUTPUT {
59        use quote::ToTokens;
60        println!("{}", output.to_token_stream());
61    }
62
63    output.into()
64}