115 lines
3.0 KiB
Rust

use std::str::FromStr;
use proc_macro2::TokenStream;
use quote::quote;
use syn::Ident;
use crate::TargetEnv;
use super::{Type, TypeKind, TypeWidth};
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum AbiPrimitive {
Unit,
Bool,
U8,
I8,
U16,
I16,
U31,
U32,
I32,
U64,
I64,
U128,
USize,
}
impl Type for AbiPrimitive {
fn width(&self, env: &TargetEnv) -> TypeWidth {
match self {
Self::Unit => TypeWidth::Zero,
Self::U8 | Self::I8 => TypeWidth::U8,
Self::U16 | Self::I16 => TypeWidth::U16,
Self::U31 => TypeWidth::U31,
Self::U32 | Self::I32 => TypeWidth::U32,
Self::U64 | Self::I64 => TypeWidth::U64,
Self::U128 => TypeWidth::U128,
Self::USize => env.thin_pointer_width,
// ???
Self::Bool => TypeWidth::U32,
}
}
fn kind(&self) -> TypeKind {
TypeKind::Other
}
fn as_rust_type(&self) -> TokenStream {
match self {
Self::Unit => quote!(()),
Self::U8 => quote!(u8),
Self::I8 => quote!(i8),
Self::U16 => quote!(u16),
Self::I16 => quote!(i16),
Self::U32 => quote!(u32),
Self::I32 => quote!(i32),
Self::U64 => quote!(u64),
Self::I64 => quote!(i64),
Self::U128 => quote!(u128),
Self::USize => quote!(usize),
Self::Bool => quote!(bool),
Self::U31 => todo!(),
}
}
fn emit_to_syscall_arguments(&self, env: &TargetEnv, value: &Ident) -> TokenStream {
match self {
Self::USize => quote!(#value),
Self::U128 => todo!("Emit to syscall for u128"),
Self::U64 if env.thin_pointer_width == TypeWidth::U32 => todo!(),
_ => quote!(#value as usize),
}
}
fn emit_from_syscall_arguments(
&self,
env: &TargetEnv,
args: &Ident,
index: usize,
) -> (TokenStream, usize) {
match self {
Self::Bool => (quote!(#args[#index] != 0), 1),
Self::U128 => todo!("Emit from syscall for u128"),
Self::U64 if env.thin_pointer_width == TypeWidth::U32 => todo!(),
_ => {
let ty = self.as_rust_type();
(quote!(#args[#index] as #ty), 1)
}
}
}
}
impl FromStr for AbiPrimitive {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"i8" => Ok(Self::I8),
"u8" => Ok(Self::U8),
"i16" => Ok(Self::I16),
"u16" => Ok(Self::U16),
"i32" => Ok(Self::I32),
"u31" => Ok(Self::U31),
"u32" => Ok(Self::U32),
"i64" => Ok(Self::I64),
"u64" => Ok(Self::U64),
"u128" => Ok(Self::U128),
"bool" => Ok(Self::Bool),
"usize" => Ok(Self::USize),
_ => Err(()),
}
}
}