Add a large amount of new intrinsics
This commit is contained in:
		
							parent
							
								
									ae6796acfc
								
							
						
					
					
						commit
						627d1bcfa5
					
				| @ -1,5 +1,5 @@ | |||||||
| 
 | 
 | ||||||
| fn main() -> i32 { | fn main() -> i32 { | ||||||
|     let b = 5; |     let b = 5; | ||||||
|     return b.min(7); |     return i32::abs(-7); | ||||||
| } | } | ||||||
| @ -1,37 +1,231 @@ | |||||||
| use crate::{CompileResult, Type, builder::Builder}; | use crate::{CompileResult, Type, TypeCategory, builder::Builder}; | ||||||
| 
 | 
 | ||||||
| #[derive(Clone, Debug)] | #[derive(Clone, Debug)] | ||||||
| pub enum LLVMIntrinsic { | pub enum LLVMIntrinsic { | ||||||
|  |     Abs(Type), | ||||||
|     Max(Type), |     Max(Type), | ||||||
|     Min(Type), |     Min(Type), | ||||||
|  |     Memcpy(Type), | ||||||
|  |     Sqrt(Type), | ||||||
|  |     PowI(Type, Type), | ||||||
|  |     Pow(Type), | ||||||
|  |     Sin(Type), | ||||||
|  |     Cos(Type), | ||||||
|  |     Tan(Type), | ||||||
|  |     ASin(Type), | ||||||
|  |     ACos(Type), | ||||||
|  |     ATan(Type), | ||||||
|  |     ATan2(Type), | ||||||
|  |     SinH(Type), | ||||||
|  |     CosH(Type), | ||||||
|  |     TanH(Type), | ||||||
|  |     Log(Type), | ||||||
|  |     Log2(Type), | ||||||
|  |     Log10(Type), | ||||||
|  |     Copysign(Type), | ||||||
|  |     Floor(Type), | ||||||
|  |     Ceil(Type), | ||||||
|  |     Trunc(Type), | ||||||
|  |     RoundEven(Type), | ||||||
|  |     Round(Type), | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl LLVMIntrinsic { | impl LLVMIntrinsic { | ||||||
|     pub fn check(&self, builder: &Builder) -> CompileResult<()> { |     pub(crate) fn signature(&self, builder: &Builder) -> CompileResult<(String, Vec<Type>, Type)> { | ||||||
|         self.signature(builder)?; |  | ||||||
|         Ok(()) |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     pub fn signature(&self, builder: &Builder) -> CompileResult<(String, Vec<Type>, Type)> { |  | ||||||
|         match self { |         match self { | ||||||
|             LLVMIntrinsic::Max(ty) => { |             LLVMIntrinsic::Max(ty) => { | ||||||
|                 let name = match ty.category() { |                 let name = match ty.category() { | ||||||
|                     crate::TypeCategory::SignedInteger => format!("llvm.smax.{}", ty.llvm_ty_str(builder)), |                     TypeCategory::SignedInteger => format!("llvm.smax.{}", ty.llvm_ty_str(builder)), | ||||||
|                     crate::TypeCategory::UnsignedInteger => format!("llvm.umax.{}", ty.llvm_ty_str(builder)), |                     TypeCategory::UnsignedInteger => format!("llvm.umax.{}", ty.llvm_ty_str(builder)), | ||||||
|                     crate::TypeCategory::Real => format!("llvm.max.{}", ty.llvm_ty_str(builder)), |                     TypeCategory::Real => format!("llvm.max.{}", ty.llvm_ty_str(builder)), | ||||||
|                     _ => return Err(crate::ErrorKind::Null), |                     _ => return Err(crate::ErrorKind::Null), | ||||||
|                 }; |                 }; | ||||||
|                 Ok((name, vec![ty.clone(), ty.clone()], ty.clone())) |                 Ok((name, vec![ty.clone(), ty.clone()], ty.clone())) | ||||||
|             } |             } | ||||||
|             LLVMIntrinsic::Min(ty) => { |             LLVMIntrinsic::Min(ty) => { | ||||||
|                 let name = match ty.category() { |                 let name = match ty.category() { | ||||||
|                     crate::TypeCategory::SignedInteger => format!("llvm.smin.{}", ty.llvm_ty_str(builder)), |                     TypeCategory::SignedInteger => format!("llvm.smin.{}", ty.llvm_ty_str(builder)), | ||||||
|                     crate::TypeCategory::UnsignedInteger => format!("llvm.umin.{}", ty.llvm_ty_str(builder)), |                     TypeCategory::UnsignedInteger => format!("llvm.umin.{}", ty.llvm_ty_str(builder)), | ||||||
|                     crate::TypeCategory::Real => format!("llvm.min.{}", ty.llvm_ty_str(builder)), |                     TypeCategory::Real => format!("llvm.min.{}", ty.llvm_ty_str(builder)), | ||||||
|                     _ => return Err(crate::ErrorKind::Null), |                     _ => return Err(crate::ErrorKind::Null), | ||||||
|                 }; |                 }; | ||||||
|                 Ok((name, vec![ty.clone(), ty.clone()], ty.clone())) |                 Ok((name, vec![ty.clone(), ty.clone()], ty.clone())) | ||||||
|             } |             } | ||||||
|  |             LLVMIntrinsic::Abs(ty) => { | ||||||
|  |                 let name = match ty.category() { | ||||||
|  |                     TypeCategory::SignedInteger => format!("llvm.abs.{}", ty.llvm_ty_str(builder)), | ||||||
|  |                     TypeCategory::UnsignedInteger => format!("llvm.abs.{}", ty.llvm_ty_str(builder)), | ||||||
|  |                     TypeCategory::Real => format!("llvm.fabs.{}", ty.llvm_ty_str(builder)), | ||||||
|  |                     _ => return Err(crate::ErrorKind::Null), | ||||||
|  |                 }; | ||||||
|  |                 Ok((name, vec![ty.clone(), Type::Bool], ty.clone())) | ||||||
|  |             } | ||||||
|  |             LLVMIntrinsic::Memcpy(ty) => { | ||||||
|  |                 let name = match ty.category() { | ||||||
|  |                     TypeCategory::Ptr => String::from("llvm.memcpy"), | ||||||
|  |                     _ => return Err(crate::ErrorKind::Null), | ||||||
|  |                 }; | ||||||
|  |                 Ok((name, vec![ty.clone(), ty.clone()], Type::Void)) | ||||||
|  |             } | ||||||
|  |             LLVMIntrinsic::Sqrt(ty) => { | ||||||
|  |                 let name = match ty.category() { | ||||||
|  |                     TypeCategory::Real => format!("llvm.sqrt.{}", ty.llvm_ty_str(builder)), | ||||||
|  |                     _ => return Err(crate::ErrorKind::Null), | ||||||
|  |                 }; | ||||||
|  |                 Ok((name, vec![ty.clone()], ty.clone())) | ||||||
|  |             } | ||||||
|  |             LLVMIntrinsic::PowI(ty1, ty2) => { | ||||||
|  |                 let name = match (ty1.category(), ty2.category()) { | ||||||
|  |                     (TypeCategory::Real, TypeCategory::SignedInteger) => { | ||||||
|  |                         format!("llvm.powi.{}.{}", ty1.llvm_ty_str(builder), ty2.llvm_ty_str(builder)) | ||||||
|  |                     } | ||||||
|  |                     (TypeCategory::Real, TypeCategory::UnsignedInteger) => { | ||||||
|  |                         format!("llvm.powi.{}.{}", ty1.llvm_ty_str(builder), ty2.llvm_ty_str(builder)) | ||||||
|  |                     } | ||||||
|  |                     _ => return Err(crate::ErrorKind::Null), | ||||||
|  |                 }; | ||||||
|  |                 Ok((name, vec![ty1.clone(), ty2.clone()], ty1.clone())) | ||||||
|  |             } | ||||||
|  |             LLVMIntrinsic::Pow(ty) => { | ||||||
|  |                 let name = match ty.category() { | ||||||
|  |                     TypeCategory::Real => format!("llvm.pow.{}", ty.llvm_ty_str(builder)), | ||||||
|  |                     _ => return Err(crate::ErrorKind::Null), | ||||||
|  |                 }; | ||||||
|  |                 Ok((name, vec![ty.clone(), ty.clone()], ty.clone())) | ||||||
|  |             } | ||||||
|  |             LLVMIntrinsic::Sin(ty) => { | ||||||
|  |                 let name = match ty.category() { | ||||||
|  |                     TypeCategory::Real => format!("llvm.sin.{}", ty.llvm_ty_str(builder)), | ||||||
|  |                     _ => return Err(crate::ErrorKind::Null), | ||||||
|  |                 }; | ||||||
|  |                 Ok((name, vec![ty.clone()], ty.clone())) | ||||||
|  |             } | ||||||
|  |             LLVMIntrinsic::Cos(ty) => { | ||||||
|  |                 let name = match ty.category() { | ||||||
|  |                     TypeCategory::Real => format!("llvm.cos.{}", ty.llvm_ty_str(builder)), | ||||||
|  |                     _ => return Err(crate::ErrorKind::Null), | ||||||
|  |                 }; | ||||||
|  |                 Ok((name, vec![ty.clone()], ty.clone())) | ||||||
|  |             } | ||||||
|  |             LLVMIntrinsic::Tan(ty) => { | ||||||
|  |                 let name = match ty.category() { | ||||||
|  |                     TypeCategory::Real => format!("llvm.tan.{}", ty.llvm_ty_str(builder)), | ||||||
|  |                     _ => return Err(crate::ErrorKind::Null), | ||||||
|  |                 }; | ||||||
|  |                 Ok((name, vec![ty.clone()], ty.clone())) | ||||||
|  |             } | ||||||
|  |             LLVMIntrinsic::ASin(ty) => { | ||||||
|  |                 let name = match ty.category() { | ||||||
|  |                     TypeCategory::Real => format!("llvm.asin.{}", ty.llvm_ty_str(builder)), | ||||||
|  |                     _ => return Err(crate::ErrorKind::Null), | ||||||
|  |                 }; | ||||||
|  |                 Ok((name, vec![ty.clone()], ty.clone())) | ||||||
|  |             } | ||||||
|  |             LLVMIntrinsic::ACos(ty) => { | ||||||
|  |                 let name = match ty.category() { | ||||||
|  |                     TypeCategory::Real => format!("llvm.acos.{}", ty.llvm_ty_str(builder)), | ||||||
|  |                     _ => return Err(crate::ErrorKind::Null), | ||||||
|  |                 }; | ||||||
|  |                 Ok((name, vec![ty.clone()], ty.clone())) | ||||||
|  |             } | ||||||
|  |             LLVMIntrinsic::ATan(ty) => { | ||||||
|  |                 let name = match ty.category() { | ||||||
|  |                     TypeCategory::Real => format!("llvm.atan.{}", ty.llvm_ty_str(builder)), | ||||||
|  |                     _ => return Err(crate::ErrorKind::Null), | ||||||
|  |                 }; | ||||||
|  |                 Ok((name, vec![ty.clone()], ty.clone())) | ||||||
|  |             } | ||||||
|  |             LLVMIntrinsic::ATan2(ty) => { | ||||||
|  |                 let name = match ty.category() { | ||||||
|  |                     TypeCategory::Real => format!("llvm.atan2.{}", ty.llvm_ty_str(builder)), | ||||||
|  |                     _ => return Err(crate::ErrorKind::Null), | ||||||
|  |                 }; | ||||||
|  |                 Ok((name, vec![ty.clone(), ty.clone()], ty.clone())) | ||||||
|  |             } | ||||||
|  |             LLVMIntrinsic::SinH(ty) => { | ||||||
|  |                 let name = match ty.category() { | ||||||
|  |                     TypeCategory::Real => format!("llvm.sinh.{}", ty.llvm_ty_str(builder)), | ||||||
|  |                     _ => return Err(crate::ErrorKind::Null), | ||||||
|  |                 }; | ||||||
|  |                 Ok((name, vec![ty.clone()], ty.clone())) | ||||||
|  |             } | ||||||
|  |             LLVMIntrinsic::CosH(ty) => { | ||||||
|  |                 let name = match ty.category() { | ||||||
|  |                     TypeCategory::Real => format!("llvm.cosh.{}", ty.llvm_ty_str(builder)), | ||||||
|  |                     _ => return Err(crate::ErrorKind::Null), | ||||||
|  |                 }; | ||||||
|  |                 Ok((name, vec![ty.clone()], ty.clone())) | ||||||
|  |             } | ||||||
|  |             LLVMIntrinsic::TanH(ty) => { | ||||||
|  |                 let name = match ty.category() { | ||||||
|  |                     TypeCategory::Real => format!("llvm.tanh.{}", ty.llvm_ty_str(builder)), | ||||||
|  |                     _ => return Err(crate::ErrorKind::Null), | ||||||
|  |                 }; | ||||||
|  |                 Ok((name, vec![ty.clone()], ty.clone())) | ||||||
|  |             } | ||||||
|  |             LLVMIntrinsic::Log(ty) => { | ||||||
|  |                 let name = match ty.category() { | ||||||
|  |                     TypeCategory::Real => format!("llvm.log.{}", ty.llvm_ty_str(builder)), | ||||||
|  |                     _ => return Err(crate::ErrorKind::Null), | ||||||
|  |                 }; | ||||||
|  |                 Ok((name, vec![ty.clone()], ty.clone())) | ||||||
|  |             } | ||||||
|  |             LLVMIntrinsic::Log2(ty) => { | ||||||
|  |                 let name = match ty.category() { | ||||||
|  |                     TypeCategory::Real => format!("llvm.log2.{}", ty.llvm_ty_str(builder)), | ||||||
|  |                     _ => return Err(crate::ErrorKind::Null), | ||||||
|  |                 }; | ||||||
|  |                 Ok((name, vec![ty.clone()], ty.clone())) | ||||||
|  |             } | ||||||
|  |             LLVMIntrinsic::Log10(ty) => { | ||||||
|  |                 let name = match ty.category() { | ||||||
|  |                     TypeCategory::Real => format!("llvm.log10.{}", ty.llvm_ty_str(builder)), | ||||||
|  |                     _ => return Err(crate::ErrorKind::Null), | ||||||
|  |                 }; | ||||||
|  |                 Ok((name, vec![ty.clone()], ty.clone())) | ||||||
|  |             } | ||||||
|  |             LLVMIntrinsic::Copysign(ty) => { | ||||||
|  |                 let name = match ty.category() { | ||||||
|  |                     TypeCategory::Real => format!("llvm.copysign.{}", ty.llvm_ty_str(builder)), | ||||||
|  |                     _ => return Err(crate::ErrorKind::Null), | ||||||
|  |                 }; | ||||||
|  |                 Ok((name, vec![ty.clone()], ty.clone())) | ||||||
|  |             } | ||||||
|  |             LLVMIntrinsic::Floor(ty) => { | ||||||
|  |                 let name = match ty.category() { | ||||||
|  |                     TypeCategory::Real => format!("llvm.floor.{}", ty.llvm_ty_str(builder)), | ||||||
|  |                     _ => return Err(crate::ErrorKind::Null), | ||||||
|  |                 }; | ||||||
|  |                 Ok((name, vec![ty.clone()], ty.clone())) | ||||||
|  |             } | ||||||
|  |             LLVMIntrinsic::Ceil(ty) => { | ||||||
|  |                 let name = match ty.category() { | ||||||
|  |                     TypeCategory::Real => format!("llvm.ceil.{}", ty.llvm_ty_str(builder)), | ||||||
|  |                     _ => return Err(crate::ErrorKind::Null), | ||||||
|  |                 }; | ||||||
|  |                 Ok((name, vec![ty.clone()], ty.clone())) | ||||||
|  |             } | ||||||
|  |             LLVMIntrinsic::Trunc(ty) => { | ||||||
|  |                 let name = match ty.category() { | ||||||
|  |                     TypeCategory::Real => format!("llvm.trunc.{}", ty.llvm_ty_str(builder)), | ||||||
|  |                     _ => return Err(crate::ErrorKind::Null), | ||||||
|  |                 }; | ||||||
|  |                 Ok((name, vec![ty.clone()], ty.clone())) | ||||||
|  |             } | ||||||
|  |             LLVMIntrinsic::RoundEven(ty) => { | ||||||
|  |                 let name = match ty.category() { | ||||||
|  |                     TypeCategory::Real => format!("llvm.roundeven.{}", ty.llvm_ty_str(builder)), | ||||||
|  |                     _ => return Err(crate::ErrorKind::Null), | ||||||
|  |                 }; | ||||||
|  |                 Ok((name, vec![ty.clone()], ty.clone())) | ||||||
|  |             } | ||||||
|  |             LLVMIntrinsic::Round(ty) => { | ||||||
|  |                 let name = match ty.category() { | ||||||
|  |                     TypeCategory::Real => format!("llvm.round.{}", ty.llvm_ty_str(builder)), | ||||||
|  |                     _ => return Err(crate::ErrorKind::Null), | ||||||
|  |                 }; | ||||||
|  |                 Ok((name, vec![ty.clone()], ty.clone())) | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,7 +1,7 @@ | |||||||
| use reid_lib::{builder::InstructionValue, CmpPredicate, ConstValueKind, Instr, Type}; | use reid_lib::{builder::InstructionValue, CmpPredicate, ConstValueKind, Instr, Type}; | ||||||
| 
 | 
 | ||||||
| use crate::{ | use crate::{ | ||||||
|     codegen::{scope::IntrinsicKind, ErrorKind, StackValueKind}, |     codegen::{ErrorKind, StackValueKind}, | ||||||
|     mir::{ |     mir::{ | ||||||
|         implement::TypeCategory, BinaryOperator, BinopDefinition, CmpOperator, FunctionDefinition, |         implement::TypeCategory, BinaryOperator, BinopDefinition, CmpOperator, FunctionDefinition, | ||||||
|         FunctionDefinitionKind, FunctionParam, TypeKind, |         FunctionDefinitionKind, FunctionParam, TypeKind, | ||||||
| @ -33,6 +33,36 @@ const FLOATS: [TypeKind; 7] = [ | |||||||
|     TypeKind::F128PPC, |     TypeKind::F128PPC, | ||||||
| ]; | ]; | ||||||
| 
 | 
 | ||||||
|  | #[derive(Debug, Clone, Hash, Eq, PartialEq)] | ||||||
|  | pub enum LLVMIntrinsicKind { | ||||||
|  |     Max(TypeKind), | ||||||
|  |     Min(TypeKind), | ||||||
|  |     Abs(TypeKind), | ||||||
|  |     Memcpy(TypeKind), | ||||||
|  |     Sqrt(TypeKind), | ||||||
|  |     PowI(TypeKind, TypeKind), | ||||||
|  |     Pow(TypeKind), | ||||||
|  |     Sin(TypeKind), | ||||||
|  |     Cos(TypeKind), | ||||||
|  |     Tan(TypeKind), | ||||||
|  |     ASin(TypeKind), | ||||||
|  |     ACos(TypeKind), | ||||||
|  |     ATan(TypeKind), | ||||||
|  |     ATan2(TypeKind), | ||||||
|  |     SinH(TypeKind), | ||||||
|  |     CosH(TypeKind), | ||||||
|  |     TanH(TypeKind), | ||||||
|  |     Log(TypeKind), | ||||||
|  |     Log2(TypeKind), | ||||||
|  |     Log10(TypeKind), | ||||||
|  |     Copysign(TypeKind), | ||||||
|  |     Floor(TypeKind), | ||||||
|  |     Ceil(TypeKind), | ||||||
|  |     Trunc(TypeKind), | ||||||
|  |     RoundEven(TypeKind), | ||||||
|  |     Round(TypeKind), | ||||||
|  | } | ||||||
|  | 
 | ||||||
| const INTRINSIC_IDENT: &str = "reid.intrinsic"; | const INTRINSIC_IDENT: &str = "reid.intrinsic"; | ||||||
| const MALLOC_IDENT: &str = "malloc"; | const MALLOC_IDENT: &str = "malloc"; | ||||||
| 
 | 
 | ||||||
| @ -58,6 +88,28 @@ pub fn form_intrinsics() -> Vec<FunctionDefinition> { | |||||||
|     intrinsics |     intrinsics | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | pub fn simple_intrinsic<T: Into<String> + Clone>( | ||||||
|  |     name: T, | ||||||
|  |     params: Vec<T>, | ||||||
|  |     ret: TypeKind, | ||||||
|  |     intrisic: LLVMIntrinsicKind, | ||||||
|  | ) -> FunctionDefinition { | ||||||
|  |     FunctionDefinition { | ||||||
|  |         name: name.into(), | ||||||
|  |         linkage_name: None, | ||||||
|  |         is_pub: true, | ||||||
|  |         is_imported: false, | ||||||
|  |         return_type: ret.clone(), | ||||||
|  |         parameters: params | ||||||
|  |             .iter() | ||||||
|  |             .map(|p| FunctionParam::from(p.clone(), ret.clone())) | ||||||
|  |             .collect(), | ||||||
|  |         kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicLLVM(intrisic, ret.clone()))), | ||||||
|  |         source: None, | ||||||
|  |         signature_meta: Default::default(), | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| pub fn get_intrinsic_assoc_functions(ty: &TypeKind) -> Vec<FunctionDefinition> { | pub fn get_intrinsic_assoc_functions(ty: &TypeKind) -> Vec<FunctionDefinition> { | ||||||
|     let mut intrinsics = Vec::new(); |     let mut intrinsics = Vec::new(); | ||||||
|     if let TypeKind::Array(_, len) = ty { |     if let TypeKind::Array(_, len) = ty { | ||||||
| @ -77,43 +129,190 @@ pub fn get_intrinsic_assoc_functions(ty: &TypeKind) -> Vec<FunctionDefinition> { | |||||||
|             signature_meta: Default::default(), |             signature_meta: Default::default(), | ||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
|  |     if ty.category() == TypeCategory::Real { | ||||||
|  |         intrinsics.push(simple_intrinsic( | ||||||
|  |             "sin", | ||||||
|  |             vec!["self"], | ||||||
|  |             ty.clone(), | ||||||
|  |             LLVMIntrinsicKind::Sin(ty.clone()), | ||||||
|  |         )); | ||||||
|  |         intrinsics.push(simple_intrinsic( | ||||||
|  |             "cos", | ||||||
|  |             vec!["self"], | ||||||
|  |             ty.clone(), | ||||||
|  |             LLVMIntrinsicKind::Cos(ty.clone()), | ||||||
|  |         )); | ||||||
|  |         intrinsics.push(simple_intrinsic( | ||||||
|  |             "tan", | ||||||
|  |             vec!["self"], | ||||||
|  |             ty.clone(), | ||||||
|  |             LLVMIntrinsicKind::Tan(ty.clone()), | ||||||
|  |         )); | ||||||
|  |         intrinsics.push(simple_intrinsic( | ||||||
|  |             "sinh", | ||||||
|  |             vec!["self"], | ||||||
|  |             ty.clone(), | ||||||
|  |             LLVMIntrinsicKind::SinH(ty.clone()), | ||||||
|  |         )); | ||||||
|  |         intrinsics.push(simple_intrinsic( | ||||||
|  |             "cosh", | ||||||
|  |             vec!["self"], | ||||||
|  |             ty.clone(), | ||||||
|  |             LLVMIntrinsicKind::CosH(ty.clone()), | ||||||
|  |         )); | ||||||
|  |         intrinsics.push(simple_intrinsic( | ||||||
|  |             "tanh", | ||||||
|  |             vec!["self"], | ||||||
|  |             ty.clone(), | ||||||
|  |             LLVMIntrinsicKind::TanH(ty.clone()), | ||||||
|  |         )); | ||||||
|  |         intrinsics.push(simple_intrinsic( | ||||||
|  |             "asin", | ||||||
|  |             vec!["self"], | ||||||
|  |             ty.clone(), | ||||||
|  |             LLVMIntrinsicKind::ASin(ty.clone()), | ||||||
|  |         )); | ||||||
|  |         intrinsics.push(simple_intrinsic( | ||||||
|  |             "acos", | ||||||
|  |             vec!["self"], | ||||||
|  |             ty.clone(), | ||||||
|  |             LLVMIntrinsicKind::ACos(ty.clone()), | ||||||
|  |         )); | ||||||
|  |         intrinsics.push(simple_intrinsic( | ||||||
|  |             "atan", | ||||||
|  |             vec!["self"], | ||||||
|  |             ty.clone(), | ||||||
|  |             LLVMIntrinsicKind::ATan(ty.clone()), | ||||||
|  |         )); | ||||||
|  |         intrinsics.push(simple_intrinsic( | ||||||
|  |             "atan2", | ||||||
|  |             vec!["self", "other"], | ||||||
|  |             ty.clone(), | ||||||
|  |             LLVMIntrinsicKind::ATan2(ty.clone()), | ||||||
|  |         )); | ||||||
|  |         intrinsics.push(simple_intrinsic( | ||||||
|  |             "log", | ||||||
|  |             vec!["self"], | ||||||
|  |             ty.clone(), | ||||||
|  |             LLVMIntrinsicKind::Log(ty.clone()), | ||||||
|  |         )); | ||||||
|  |         intrinsics.push(simple_intrinsic( | ||||||
|  |             "log2", | ||||||
|  |             vec!["self"], | ||||||
|  |             ty.clone(), | ||||||
|  |             LLVMIntrinsicKind::Log2(ty.clone()), | ||||||
|  |         )); | ||||||
|  |         intrinsics.push(simple_intrinsic( | ||||||
|  |             "log10", | ||||||
|  |             vec!["self"], | ||||||
|  |             ty.clone(), | ||||||
|  |             LLVMIntrinsicKind::Log10(ty.clone()), | ||||||
|  |         )); | ||||||
|  |         intrinsics.push(simple_intrinsic( | ||||||
|  |             "floor", | ||||||
|  |             vec!["self"], | ||||||
|  |             ty.clone(), | ||||||
|  |             LLVMIntrinsicKind::Floor(ty.clone()), | ||||||
|  |         )); | ||||||
|  |         intrinsics.push(simple_intrinsic( | ||||||
|  |             "ceil", | ||||||
|  |             vec!["self"], | ||||||
|  |             ty.clone(), | ||||||
|  |             LLVMIntrinsicKind::Ceil(ty.clone()), | ||||||
|  |         )); | ||||||
|  |         intrinsics.push(simple_intrinsic( | ||||||
|  |             "trunc", | ||||||
|  |             vec!["self"], | ||||||
|  |             ty.clone(), | ||||||
|  |             LLVMIntrinsicKind::Trunc(ty.clone()), | ||||||
|  |         )); | ||||||
|  |         intrinsics.push(simple_intrinsic( | ||||||
|  |             "round", | ||||||
|  |             vec!["self"], | ||||||
|  |             ty.clone(), | ||||||
|  |             LLVMIntrinsicKind::Round(ty.clone()), | ||||||
|  |         )); | ||||||
|  |         intrinsics.push(simple_intrinsic( | ||||||
|  |             "even", | ||||||
|  |             vec!["self"], | ||||||
|  |             ty.clone(), | ||||||
|  |             LLVMIntrinsicKind::RoundEven(ty.clone()), | ||||||
|  |         )); | ||||||
|  |         intrinsics.push(simple_intrinsic( | ||||||
|  |             "pow", | ||||||
|  |             vec!["self", "exponent"], | ||||||
|  |             ty.clone(), | ||||||
|  |             LLVMIntrinsicKind::Pow(ty.clone()), | ||||||
|  |         )); | ||||||
|  |         intrinsics.push(FunctionDefinition { | ||||||
|  |             name: "powi".to_owned(), | ||||||
|  |             linkage_name: None, | ||||||
|  |             is_pub: true, | ||||||
|  |             is_imported: false, | ||||||
|  |             return_type: TypeKind::U64, | ||||||
|  |             parameters: vec![ | ||||||
|  |                 FunctionParam { | ||||||
|  |                     name: String::from("self"), | ||||||
|  |                     ty: ty.clone(), | ||||||
|  |                     meta: Default::default(), | ||||||
|  |                 }, | ||||||
|  |                 FunctionParam { | ||||||
|  |                     name: String::from("exponent"), | ||||||
|  |                     ty: TypeKind::U64, | ||||||
|  |                     meta: Default::default(), | ||||||
|  |                 }, | ||||||
|  |             ], | ||||||
|  |             kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicLLVM( | ||||||
|  |                 LLVMIntrinsicKind::PowI(ty.clone(), TypeKind::U64), | ||||||
|  |                 ty.clone(), | ||||||
|  |             ))), | ||||||
|  |             source: None, | ||||||
|  |             signature_meta: Default::default(), | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|     match ty.category() { |     match ty.category() { | ||||||
|         TypeCategory::Integer | TypeCategory::Real | TypeCategory::Bool => { |         TypeCategory::Integer | TypeCategory::Real | TypeCategory::Bool => { | ||||||
|  |             intrinsics.push(simple_intrinsic( | ||||||
|  |                 "max", | ||||||
|  |                 vec!["self", "other"], | ||||||
|  |                 ty.clone(), | ||||||
|  |                 LLVMIntrinsicKind::Max(ty.clone()), | ||||||
|  |             )); | ||||||
|  |             intrinsics.push(simple_intrinsic( | ||||||
|  |                 "min", | ||||||
|  |                 vec!["self", "other"], | ||||||
|  |                 ty.clone(), | ||||||
|  |                 LLVMIntrinsicKind::Min(ty.clone()), | ||||||
|  |             )); | ||||||
|  |             if ty.signed() { | ||||||
|                 intrinsics.push(FunctionDefinition { |                 intrinsics.push(FunctionDefinition { | ||||||
|                 name: "max".to_owned(), |                     name: "abs".to_owned(), | ||||||
|                     linkage_name: None, |                     linkage_name: None, | ||||||
|                     is_pub: true, |                     is_pub: true, | ||||||
|                     is_imported: false, |                     is_imported: false, | ||||||
|                     return_type: ty.clone(), |                     return_type: ty.clone(), | ||||||
|                 parameters: vec![ |                     parameters: vec![FunctionParam { | ||||||
|                     FunctionParam::from("self", ty.clone()), |                         name: String::from("self"), | ||||||
|                     FunctionParam::from("other", ty.clone()), |                         ty: ty.clone(), | ||||||
|                 ], |                         meta: Default::default(), | ||||||
|                 kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicLLVM( |                     }], | ||||||
|                     IntrinsicKind::Max(ty.clone()), |                     kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicSimpleUnaryInstr({ | ||||||
|                     ty.clone(), |                         let ty = ty.clone(); | ||||||
|                 ))), |                         |scope, param| { | ||||||
|                 source: None, |                             let intrinsic = scope.get_intrinsic(LLVMIntrinsicKind::Abs(ty)); | ||||||
|                 signature_meta: Default::default(), |                             let constant = scope.block.build(Instr::Constant(ConstValueKind::Bool(false))).unwrap(); | ||||||
|             }); |                             let value = scope | ||||||
|             intrinsics.push(FunctionDefinition { |                                 .block | ||||||
|                 name: "min".to_owned(), |                                 .build(Instr::FunctionCall(intrinsic, vec![param, constant])) | ||||||
|                 linkage_name: None, |                                 .unwrap(); | ||||||
|                 is_pub: true, |                             value | ||||||
|                 is_imported: false, |                         } | ||||||
|                 return_type: ty.clone(), |                     }))), | ||||||
|                 parameters: vec![ |  | ||||||
|                     FunctionParam::from("self", ty.clone()), |  | ||||||
|                     FunctionParam::from("other", ty.clone()), |  | ||||||
|                 ], |  | ||||||
|                 kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicLLVM( |  | ||||||
|                     IntrinsicKind::Min(ty.clone()), |  | ||||||
|                     ty.clone(), |  | ||||||
|                 ))), |  | ||||||
|                     source: None, |                     source: None, | ||||||
|                     signature_meta: Default::default(), |                     signature_meta: Default::default(), | ||||||
|                 }); |                 }); | ||||||
|             } |             } | ||||||
|  |         } | ||||||
|         _ => {} |         _ => {} | ||||||
|     } |     } | ||||||
|     intrinsics.push(FunctionDefinition { |     intrinsics.push(FunctionDefinition { | ||||||
| @ -179,7 +378,7 @@ where | |||||||
|             meta: Default::default(), |             meta: Default::default(), | ||||||
|         }, |         }, | ||||||
|         return_type: ty.clone(), |         return_type: ty.clone(), | ||||||
|         fn_kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicSimpleInstr(fun))), |         fn_kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicSimpleBinaryInstr(fun))), | ||||||
|         meta: Default::default(), |         meta: Default::default(), | ||||||
|         exported: false, |         exported: false, | ||||||
|     } |     } | ||||||
| @ -202,7 +401,7 @@ where | |||||||
|             meta: Default::default(), |             meta: Default::default(), | ||||||
|         }, |         }, | ||||||
|         return_type: lhs.clone(), |         return_type: lhs.clone(), | ||||||
|         fn_kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicSimpleInstr(fun))), |         fn_kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicSimpleBinaryInstr(fun))), | ||||||
|         meta: Default::default(), |         meta: Default::default(), | ||||||
|         exported: false, |         exported: false, | ||||||
|     } |     } | ||||||
| @ -379,12 +578,37 @@ macro_rules! intrinsic_debug { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Clone)] | #[derive(Clone)] | ||||||
| pub struct IntrinsicSimpleInstr<T>(T) | pub struct IntrinsicSimpleUnaryInstr<T>(T) | ||||||
|  | where | ||||||
|  |     T: FnOnce(&mut Scope, InstructionValue) -> InstructionValue; | ||||||
|  | 
 | ||||||
|  | impl<T> std::fmt::Debug for IntrinsicSimpleUnaryInstr<T> | ||||||
|  | where | ||||||
|  |     T: FnOnce(&mut Scope, InstructionValue) -> InstructionValue, | ||||||
|  | { | ||||||
|  |     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||||
|  |         f.debug_tuple("IntrinsicSimpleUnaryInstr").finish() | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl<T: Clone> IntrinsicFunction for IntrinsicSimpleUnaryInstr<T> | ||||||
|  | where | ||||||
|  |     T: FnOnce(&mut Scope, InstructionValue) -> InstructionValue, | ||||||
|  | { | ||||||
|  |     fn codegen<'b, 'c>(&self, scope: &mut Scope<'b, 'c>, params: &[StackValue]) -> Result<StackValue, ErrorKind> { | ||||||
|  |         let param = params.get(0).unwrap(); | ||||||
|  |         let instr = self.clone().0(scope, param.instr()); | ||||||
|  |         Ok(StackValue(StackValueKind::Literal(instr), param.1.clone())) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[derive(Clone)] | ||||||
|  | pub struct IntrinsicSimpleBinaryInstr<T>(T) | ||||||
| where | where | ||||||
|     T: FnOnce(&mut Scope, InstructionValue, InstructionValue) -> InstructionValue; |     T: FnOnce(&mut Scope, InstructionValue, InstructionValue) -> InstructionValue; | ||||||
| intrinsic_debug!(IntrinsicSimpleInstr<T>, "IntrinsicSimpleInstr"); | intrinsic_debug!(IntrinsicSimpleBinaryInstr<T>, "IntrinsicSimpleBinaryInstr"); | ||||||
| 
 | 
 | ||||||
| impl<T: Clone> IntrinsicFunction for IntrinsicSimpleInstr<T> | impl<T: Clone> IntrinsicFunction for IntrinsicSimpleBinaryInstr<T> | ||||||
| where | where | ||||||
|     T: FnOnce(&mut Scope, InstructionValue, InstructionValue) -> InstructionValue, |     T: FnOnce(&mut Scope, InstructionValue, InstructionValue) -> InstructionValue, | ||||||
| { | { | ||||||
| @ -479,7 +703,7 @@ impl IntrinsicFunction for IntrinsicConst { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Clone, Debug)] | #[derive(Clone, Debug)] | ||||||
| pub struct IntrinsicLLVM(IntrinsicKind, TypeKind); | pub struct IntrinsicLLVM(LLVMIntrinsicKind, TypeKind); | ||||||
| impl IntrinsicFunction for IntrinsicLLVM { | impl IntrinsicFunction for IntrinsicLLVM { | ||||||
|     fn codegen<'ctx, 'a>(&self, scope: &mut Scope<'ctx, 'a>, params: &[StackValue]) -> Result<StackValue, ErrorKind> { |     fn codegen<'ctx, 'a>(&self, scope: &mut Scope<'ctx, 'a>, params: &[StackValue]) -> Result<StackValue, ErrorKind> { | ||||||
|         let intrinsic = scope.get_intrinsic(self.0.clone()); |         let intrinsic = scope.get_intrinsic(self.0.clone()); | ||||||
|  | |||||||
| @ -8,6 +8,7 @@ use reid_lib::{ | |||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| use crate::{ | use crate::{ | ||||||
|  |     codegen::intrinsics::LLVMIntrinsicKind, | ||||||
|     lexer::FullToken, |     lexer::FullToken, | ||||||
|     mir::{ |     mir::{ | ||||||
|         pass::{AssociatedFunctionKey, BinopKey}, |         pass::{AssociatedFunctionKey, BinopKey}, | ||||||
| @ -17,12 +18,6 @@ use crate::{ | |||||||
| 
 | 
 | ||||||
| use super::{allocator::Allocator, ErrorKind, IntrinsicFunction, ModuleCodegen}; | use super::{allocator::Allocator, ErrorKind, IntrinsicFunction, ModuleCodegen}; | ||||||
| 
 | 
 | ||||||
| #[derive(Debug, Clone, Hash, Eq, PartialEq)] |  | ||||||
| pub enum IntrinsicKind { |  | ||||||
|     Max(TypeKind), |  | ||||||
|     Min(TypeKind), |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| pub struct Scope<'ctx, 'scope> { | pub struct Scope<'ctx, 'scope> { | ||||||
|     pub(super) context: &'ctx Context, |     pub(super) context: &'ctx Context, | ||||||
|     pub(super) modules: &'scope HashMap<SourceModuleId, ModuleCodegen<'ctx>>, |     pub(super) modules: &'scope HashMap<SourceModuleId, ModuleCodegen<'ctx>>, | ||||||
| @ -41,7 +36,7 @@ pub struct Scope<'ctx, 'scope> { | |||||||
|     pub(super) globals: &'scope HashMap<String, GlobalValue>, |     pub(super) globals: &'scope HashMap<String, GlobalValue>, | ||||||
|     pub(super) debug: Option<Debug<'ctx>>, |     pub(super) debug: Option<Debug<'ctx>>, | ||||||
|     pub(super) allocator: Rc<RefCell<Allocator>>, |     pub(super) allocator: Rc<RefCell<Allocator>>, | ||||||
|     pub(super) llvm_intrinsics: Rc<RefCell<HashMap<IntrinsicKind, FunctionValue>>>, |     pub(super) llvm_intrinsics: Rc<RefCell<HashMap<LLVMIntrinsicKind, FunctionValue>>>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl<'ctx, 'a> Scope<'ctx, 'a> { | impl<'ctx, 'a> Scope<'ctx, 'a> { | ||||||
| @ -84,7 +79,7 @@ impl<'ctx, 'a> Scope<'ctx, 'a> { | |||||||
|         self.allocator.borrow_mut().allocate(meta, ty) |         self.allocator.borrow_mut().allocate(meta, ty) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     pub fn get_intrinsic(&self, kind: IntrinsicKind) -> FunctionValue { |     pub fn get_intrinsic(&self, kind: LLVMIntrinsicKind) -> FunctionValue { | ||||||
|         let mut intrinsics = self.llvm_intrinsics.borrow_mut(); |         let mut intrinsics = self.llvm_intrinsics.borrow_mut(); | ||||||
|         if let Some(fun) = intrinsics.get(&kind) { |         if let Some(fun) = intrinsics.get(&kind) { | ||||||
|             *fun |             *fun | ||||||
| @ -92,8 +87,34 @@ impl<'ctx, 'a> Scope<'ctx, 'a> { | |||||||
|             let intrinsic = self |             let intrinsic = self | ||||||
|                 .module |                 .module | ||||||
|                 .intrinsic(match &kind { |                 .intrinsic(match &kind { | ||||||
|                     IntrinsicKind::Max(ty) => LLVMIntrinsic::Max(ty.get_type(self.type_values)), |                     LLVMIntrinsicKind::Max(ty) => LLVMIntrinsic::Max(ty.get_type(self.type_values)), | ||||||
|                     IntrinsicKind::Min(ty) => LLVMIntrinsic::Min(ty.get_type(self.type_values)), |                     LLVMIntrinsicKind::Min(ty) => LLVMIntrinsic::Min(ty.get_type(self.type_values)), | ||||||
|  |                     LLVMIntrinsicKind::Abs(ty) => LLVMIntrinsic::Abs(ty.get_type(self.type_values)), | ||||||
|  |                     LLVMIntrinsicKind::Memcpy(ty) => LLVMIntrinsic::Memcpy(ty.get_type(self.type_values)), | ||||||
|  |                     LLVMIntrinsicKind::Sqrt(ty) => LLVMIntrinsic::Sqrt(ty.get_type(self.type_values)), | ||||||
|  |                     LLVMIntrinsicKind::PowI(lhs, rhs) => { | ||||||
|  |                         LLVMIntrinsic::PowI(lhs.get_type(self.type_values), rhs.get_type(self.type_values)) | ||||||
|  |                     } | ||||||
|  |                     LLVMIntrinsicKind::Pow(ty) => LLVMIntrinsic::Pow(ty.get_type(self.type_values)), | ||||||
|  |                     LLVMIntrinsicKind::Sin(ty) => LLVMIntrinsic::Sin(ty.get_type(self.type_values)), | ||||||
|  |                     LLVMIntrinsicKind::Cos(ty) => LLVMIntrinsic::Cos(ty.get_type(self.type_values)), | ||||||
|  |                     LLVMIntrinsicKind::Tan(ty) => LLVMIntrinsic::Tan(ty.get_type(self.type_values)), | ||||||
|  |                     LLVMIntrinsicKind::ASin(ty) => LLVMIntrinsic::ASin(ty.get_type(self.type_values)), | ||||||
|  |                     LLVMIntrinsicKind::ACos(ty) => LLVMIntrinsic::ACos(ty.get_type(self.type_values)), | ||||||
|  |                     LLVMIntrinsicKind::ATan(ty) => LLVMIntrinsic::ATan(ty.get_type(self.type_values)), | ||||||
|  |                     LLVMIntrinsicKind::ATan2(ty) => LLVMIntrinsic::ATan2(ty.get_type(self.type_values)), | ||||||
|  |                     LLVMIntrinsicKind::SinH(ty) => LLVMIntrinsic::SinH(ty.get_type(self.type_values)), | ||||||
|  |                     LLVMIntrinsicKind::CosH(ty) => LLVMIntrinsic::CosH(ty.get_type(self.type_values)), | ||||||
|  |                     LLVMIntrinsicKind::TanH(ty) => LLVMIntrinsic::TanH(ty.get_type(self.type_values)), | ||||||
|  |                     LLVMIntrinsicKind::Log(ty) => LLVMIntrinsic::Log(ty.get_type(self.type_values)), | ||||||
|  |                     LLVMIntrinsicKind::Log2(ty) => LLVMIntrinsic::Log2(ty.get_type(self.type_values)), | ||||||
|  |                     LLVMIntrinsicKind::Log10(ty) => LLVMIntrinsic::Log10(ty.get_type(self.type_values)), | ||||||
|  |                     LLVMIntrinsicKind::Copysign(ty) => LLVMIntrinsic::Copysign(ty.get_type(self.type_values)), | ||||||
|  |                     LLVMIntrinsicKind::Floor(ty) => LLVMIntrinsic::Floor(ty.get_type(self.type_values)), | ||||||
|  |                     LLVMIntrinsicKind::Ceil(ty) => LLVMIntrinsic::Ceil(ty.get_type(self.type_values)), | ||||||
|  |                     LLVMIntrinsicKind::Trunc(ty) => LLVMIntrinsic::Trunc(ty.get_type(self.type_values)), | ||||||
|  |                     LLVMIntrinsicKind::RoundEven(ty) => LLVMIntrinsic::RoundEven(ty.get_type(self.type_values)), | ||||||
|  |                     LLVMIntrinsicKind::Round(ty) => LLVMIntrinsic::Round(ty.get_type(self.type_values)), | ||||||
|                 }) |                 }) | ||||||
|                 .unwrap(); |                 .unwrap(); | ||||||
|             intrinsics.insert(kind, intrinsic.clone()); |             intrinsics.insert(kind, intrinsic.clone()); | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user