Add a large amount of new intrinsics
This commit is contained in:
		
							parent
							
								
									ae6796acfc
								
							
						
					
					
						commit
						627d1bcfa5
					
				| @ -1,5 +1,5 @@ | ||||
| 
 | ||||
| fn main() -> i32 { | ||||
|     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)] | ||||
| pub enum LLVMIntrinsic { | ||||
|     Abs(Type), | ||||
|     Max(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 { | ||||
|     pub fn check(&self, builder: &Builder) -> CompileResult<()> { | ||||
|         self.signature(builder)?; | ||||
|         Ok(()) | ||||
|     } | ||||
| 
 | ||||
|     pub fn signature(&self, builder: &Builder) -> CompileResult<(String, Vec<Type>, Type)> { | ||||
|     pub(crate) fn signature(&self, builder: &Builder) -> CompileResult<(String, Vec<Type>, Type)> { | ||||
|         match self { | ||||
|             LLVMIntrinsic::Max(ty) => { | ||||
|                 let name = match ty.category() { | ||||
|                     crate::TypeCategory::SignedInteger => format!("llvm.smax.{}", ty.llvm_ty_str(builder)), | ||||
|                     crate::TypeCategory::UnsignedInteger => format!("llvm.umax.{}", ty.llvm_ty_str(builder)), | ||||
|                     crate::TypeCategory::Real => format!("llvm.max.{}", ty.llvm_ty_str(builder)), | ||||
|                     TypeCategory::SignedInteger => format!("llvm.smax.{}", ty.llvm_ty_str(builder)), | ||||
|                     TypeCategory::UnsignedInteger => format!("llvm.umax.{}", ty.llvm_ty_str(builder)), | ||||
|                     TypeCategory::Real => format!("llvm.max.{}", ty.llvm_ty_str(builder)), | ||||
|                     _ => return Err(crate::ErrorKind::Null), | ||||
|                 }; | ||||
|                 Ok((name, vec![ty.clone(), ty.clone()], ty.clone())) | ||||
|             } | ||||
|             LLVMIntrinsic::Min(ty) => { | ||||
|                 let name = match ty.category() { | ||||
|                     crate::TypeCategory::SignedInteger => format!("llvm.smin.{}", ty.llvm_ty_str(builder)), | ||||
|                     crate::TypeCategory::UnsignedInteger => format!("llvm.umin.{}", ty.llvm_ty_str(builder)), | ||||
|                     crate::TypeCategory::Real => format!("llvm.min.{}", ty.llvm_ty_str(builder)), | ||||
|                     TypeCategory::SignedInteger => format!("llvm.smin.{}", ty.llvm_ty_str(builder)), | ||||
|                     TypeCategory::UnsignedInteger => format!("llvm.umin.{}", ty.llvm_ty_str(builder)), | ||||
|                     TypeCategory::Real => format!("llvm.min.{}", ty.llvm_ty_str(builder)), | ||||
|                     _ => return Err(crate::ErrorKind::Null), | ||||
|                 }; | ||||
|                 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 crate::{ | ||||
|     codegen::{scope::IntrinsicKind, ErrorKind, StackValueKind}, | ||||
|     codegen::{ErrorKind, StackValueKind}, | ||||
|     mir::{ | ||||
|         implement::TypeCategory, BinaryOperator, BinopDefinition, CmpOperator, FunctionDefinition, | ||||
|         FunctionDefinitionKind, FunctionParam, TypeKind, | ||||
| @ -33,6 +33,36 @@ const FLOATS: [TypeKind; 7] = [ | ||||
|     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 MALLOC_IDENT: &str = "malloc"; | ||||
| 
 | ||||
| @ -58,6 +88,28 @@ pub fn form_intrinsics() -> Vec<FunctionDefinition> { | ||||
|     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> { | ||||
|     let mut intrinsics = Vec::new(); | ||||
|     if let TypeKind::Array(_, len) = ty { | ||||
| @ -77,42 +129,189 @@ pub fn get_intrinsic_assoc_functions(ty: &TypeKind) -> Vec<FunctionDefinition> { | ||||
|             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() { | ||||
|         TypeCategory::Integer | TypeCategory::Real | TypeCategory::Bool => { | ||||
|             intrinsics.push(FunctionDefinition { | ||||
|                 name: "max".to_owned(), | ||||
|                 linkage_name: None, | ||||
|                 is_pub: true, | ||||
|                 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::Max(ty.clone()), | ||||
|                     ty.clone(), | ||||
|                 ))), | ||||
|                 source: None, | ||||
|                 signature_meta: Default::default(), | ||||
|             }); | ||||
|             intrinsics.push(FunctionDefinition { | ||||
|                 name: "min".to_owned(), | ||||
|                 linkage_name: None, | ||||
|                 is_pub: true, | ||||
|                 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, | ||||
|                 signature_meta: Default::default(), | ||||
|             }); | ||||
|             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 { | ||||
|                     name: "abs".to_owned(), | ||||
|                     linkage_name: None, | ||||
|                     is_pub: true, | ||||
|                     is_imported: false, | ||||
|                     return_type: ty.clone(), | ||||
|                     parameters: vec![FunctionParam { | ||||
|                         name: String::from("self"), | ||||
|                         ty: ty.clone(), | ||||
|                         meta: Default::default(), | ||||
|                     }], | ||||
|                     kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicSimpleUnaryInstr({ | ||||
|                         let ty = ty.clone(); | ||||
|                         |scope, param| { | ||||
|                             let intrinsic = scope.get_intrinsic(LLVMIntrinsicKind::Abs(ty)); | ||||
|                             let constant = scope.block.build(Instr::Constant(ConstValueKind::Bool(false))).unwrap(); | ||||
|                             let value = scope | ||||
|                                 .block | ||||
|                                 .build(Instr::FunctionCall(intrinsic, vec![param, constant])) | ||||
|                                 .unwrap(); | ||||
|                             value | ||||
|                         } | ||||
|                     }))), | ||||
|                     source: None, | ||||
|                     signature_meta: Default::default(), | ||||
|                 }); | ||||
|             } | ||||
|         } | ||||
|         _ => {} | ||||
|     } | ||||
| @ -179,7 +378,7 @@ where | ||||
|             meta: Default::default(), | ||||
|         }, | ||||
|         return_type: ty.clone(), | ||||
|         fn_kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicSimpleInstr(fun))), | ||||
|         fn_kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicSimpleBinaryInstr(fun))), | ||||
|         meta: Default::default(), | ||||
|         exported: false, | ||||
|     } | ||||
| @ -202,7 +401,7 @@ where | ||||
|             meta: Default::default(), | ||||
|         }, | ||||
|         return_type: lhs.clone(), | ||||
|         fn_kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicSimpleInstr(fun))), | ||||
|         fn_kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicSimpleBinaryInstr(fun))), | ||||
|         meta: Default::default(), | ||||
|         exported: false, | ||||
|     } | ||||
| @ -379,12 +578,37 @@ macro_rules! intrinsic_debug { | ||||
| } | ||||
| 
 | ||||
| #[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 | ||||
|     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 | ||||
|     T: FnOnce(&mut Scope, InstructionValue, InstructionValue) -> InstructionValue, | ||||
| { | ||||
| @ -479,7 +703,7 @@ impl IntrinsicFunction for IntrinsicConst { | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone, Debug)] | ||||
| pub struct IntrinsicLLVM(IntrinsicKind, TypeKind); | ||||
| pub struct IntrinsicLLVM(LLVMIntrinsicKind, TypeKind); | ||||
| impl IntrinsicFunction for IntrinsicLLVM { | ||||
|     fn codegen<'ctx, 'a>(&self, scope: &mut Scope<'ctx, 'a>, params: &[StackValue]) -> Result<StackValue, ErrorKind> { | ||||
|         let intrinsic = scope.get_intrinsic(self.0.clone()); | ||||
|  | ||||
| @ -8,6 +8,7 @@ use reid_lib::{ | ||||
| }; | ||||
| 
 | ||||
| use crate::{ | ||||
|     codegen::intrinsics::LLVMIntrinsicKind, | ||||
|     lexer::FullToken, | ||||
|     mir::{ | ||||
|         pass::{AssociatedFunctionKey, BinopKey}, | ||||
| @ -17,12 +18,6 @@ use crate::{ | ||||
| 
 | ||||
| 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(super) context: &'ctx Context, | ||||
|     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) debug: Option<Debug<'ctx>>, | ||||
|     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> { | ||||
| @ -84,7 +79,7 @@ impl<'ctx, 'a> Scope<'ctx, 'a> { | ||||
|         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(); | ||||
|         if let Some(fun) = intrinsics.get(&kind) { | ||||
|             *fun | ||||
| @ -92,8 +87,34 @@ impl<'ctx, 'a> Scope<'ctx, 'a> { | ||||
|             let intrinsic = self | ||||
|                 .module | ||||
|                 .intrinsic(match &kind { | ||||
|                     IntrinsicKind::Max(ty) => LLVMIntrinsic::Max(ty.get_type(self.type_values)), | ||||
|                     IntrinsicKind::Min(ty) => LLVMIntrinsic::Min(ty.get_type(self.type_values)), | ||||
|                     LLVMIntrinsicKind::Max(ty) => LLVMIntrinsic::Max(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(); | ||||
|             intrinsics.insert(kind, intrinsic.clone()); | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user