use proc_macro2::{Span, TokenStream}; use quote::quote; use syn::{Ident, LitStr, Type}; /// Generate the assembly code to load the address of a symbol and add it to a register. pub fn load_addr_of_to(symbol: &LitStr, target: &LitStr) -> TokenStream { quote! { concat!("mov %gs:0, ", #target), concat!("add $", #symbol, ", ", #target) } } /// Get the base address for percpu variables of the current thread. pub fn get_percpu_pointer(percpu: &Ident, ty: &Type) -> TokenStream { let stmt = load_addr_of_to( &LitStr::new("{ident}", Span::call_site()), &LitStr::new("{address}", Span::call_site()), ); quote! { { let base: *mut #ty; ::core::arch::asm!( #stmt, ident = sym #percpu, address = out(reg) base, options(att_syntax, nostack, preserves_flags) ); base } } } pub fn get_percpu_offset(percpu: &Ident) -> TokenStream { quote! { { & #percpu as *const _ as usize } } }