Add all cast instructions to lib
This commit is contained in:
		
							parent
							
								
									a6c9752883
								
							
						
					
					
						commit
						e73b939de0
					
				| @ -4,8 +4,8 @@ | ||||
| use std::{cell::RefCell, rc::Rc}; | ||||
| 
 | ||||
| use crate::{ | ||||
|     BlockData, CustomTypeKind, FunctionData, Instr, InstructionData, ModuleData, NamedStruct, | ||||
|     TerminatorKind, Type, TypeCategory, TypeData, | ||||
|     Block, BlockData, CustomTypeKind, FunctionData, Instr, InstructionData, ModuleData, | ||||
|     NamedStruct, TerminatorKind, Type, TypeCategory, TypeData, | ||||
|     debug_information::{ | ||||
|         DebugInformation, DebugLocationValue, DebugMetadataValue, DebugProgramValue, | ||||
|         InstructionDebugRecordData, | ||||
| @ -467,6 +467,18 @@ impl Builder { | ||||
|                         _ => Err(()), | ||||
|                     } | ||||
|                 } | ||||
|                 Instr::Trunc(instr, ty) => instr.cast_to(self, &ty).map(|_| ()), | ||||
|                 Instr::ZExt(instr, ty) => instr.cast_to(self, &ty).map(|_| ()), | ||||
|                 Instr::SExt(instr, ty) => instr.cast_to(self, &ty).map(|_| ()), | ||||
|                 Instr::FPTrunc(instr, ty) => instr.cast_to(self, &ty).map(|_| ()), | ||||
|                 Instr::FPExt(instr, ty) => instr.cast_to(self, &ty).map(|_| ()), | ||||
|                 Instr::FPToUI(instr, ty) => instr.cast_to(self, &ty).map(|_| ()), | ||||
|                 Instr::FPToSI(instr, ty) => instr.cast_to(self, &ty).map(|_| ()), | ||||
|                 Instr::UIToFP(instr, ty) => instr.cast_to(self, &ty).map(|_| ()), | ||||
|                 Instr::SIToFP(instr, ty) => instr.cast_to(self, &ty).map(|_| ()), | ||||
|                 Instr::PtrToInt(instr, ty) => instr.cast_to(self, &ty).map(|_| ()), | ||||
|                 Instr::IntToPtr(instr, ty) => instr.cast_to(self, &ty).map(|_| ()), | ||||
|                 Instr::BitCast(instr, ty) => instr.cast_to(self, &ty).map(|_| ()), | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| @ -505,3 +517,125 @@ impl Builder { | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl InstructionValue { | ||||
|     pub fn with_location(self, block: &Block, location: DebugLocationValue) -> InstructionValue { | ||||
|         unsafe { | ||||
|             block.builder.add_instruction_location(&self, location); | ||||
|         } | ||||
|         self | ||||
|     } | ||||
| 
 | ||||
|     pub fn maybe_location( | ||||
|         self, | ||||
|         block: &mut Block, | ||||
|         location: Option<DebugLocationValue>, | ||||
|     ) -> InstructionValue { | ||||
|         unsafe { | ||||
|             if let Some(location) = location { | ||||
|                 block.builder.add_instruction_location(&self, location); | ||||
|             } | ||||
|         } | ||||
|         self | ||||
|     } | ||||
| 
 | ||||
|     pub fn add_record(&self, block: &mut Block, record: InstructionDebugRecordData) { | ||||
|         unsafe { | ||||
|             block.builder.add_instruction_record(self, record); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub(crate) fn get_type(&self, builder: &Builder) -> Result<Type, ()> { | ||||
|         use Instr::*; | ||||
|         unsafe { | ||||
|             match &builder.instr_data(self).kind { | ||||
|                 Param(nth) => builder | ||||
|                     .function_data(&self.0.0) | ||||
|                     .params | ||||
|                     .get(*nth) | ||||
|                     .cloned() | ||||
|                     .ok_or(()), | ||||
|                 Constant(c) => Ok(c.get_type()), | ||||
|                 Add(lhs, rhs) => match_types(lhs, rhs, &builder), | ||||
|                 FAdd(lhs, rhs) => match_types(lhs, rhs, &builder), | ||||
|                 Sub(lhs, rhs) => match_types(lhs, rhs, &builder), | ||||
|                 FSub(lhs, rhs) => match_types(lhs, rhs, &builder), | ||||
|                 Mul(lhs, rhs) => match_types(lhs, rhs, &builder), | ||||
|                 FMul(lhs, rhs) => match_types(lhs, rhs, &builder), | ||||
|                 UDiv(lhs, rhs) => match_types(lhs, rhs, &builder), | ||||
|                 SDiv(lhs, rhs) => match_types(lhs, rhs, &builder), | ||||
|                 FDiv(lhs, rhs) => match_types(lhs, rhs, &builder), | ||||
|                 URem(lhs, rhs) => match_types(lhs, rhs, &builder), | ||||
|                 SRem(lhs, rhs) => match_types(lhs, rhs, &builder), | ||||
|                 FRem(lhs, rhs) => match_types(lhs, rhs, &builder), | ||||
|                 And(lhs, rhs) => match_types(lhs, rhs, &builder), | ||||
|                 ICmp(_, _, _) => Ok(Type::Bool), | ||||
|                 FCmp(_, _, _) => Ok(Type::Bool), | ||||
|                 FunctionCall(function_value, _) => Ok(builder.function_data(function_value).ret), | ||||
|                 Phi(values) => values.first().ok_or(()).and_then(|v| v.get_type(&builder)), | ||||
|                 Alloca(ty) => Ok(Type::Ptr(Box::new(ty.clone()))), | ||||
|                 Load(_, ty) => Ok(ty.clone()), | ||||
|                 Store(_, value) => value.get_type(builder), | ||||
|                 ArrayAlloca(ty, _) => Ok(Type::Ptr(Box::new(ty.clone()))), | ||||
|                 GetElemPtr(instr, _) => { | ||||
|                     let instr_ty = instr.get_type(builder)?; | ||||
|                     let Type::Ptr(inner_ty) = &instr_ty else { | ||||
|                         panic!("GetStructElemPtr on non-pointer! ({:?})", &instr_ty) | ||||
|                     }; | ||||
|                     match *inner_ty.clone() { | ||||
|                         Type::Array(elem_ty, _) => Ok(Type::Ptr(Box::new(*elem_ty.clone()))), | ||||
|                         _ => Ok(instr_ty), | ||||
|                     } | ||||
|                 } | ||||
|                 GetStructElemPtr(instr, idx) => { | ||||
|                     let instr_ty = instr.get_type(builder)?; | ||||
|                     let Type::Ptr(inner_ty) = instr_ty else { | ||||
|                         panic!("GetStructElemPtr on non-pointer! ({:?})", &instr_ty) | ||||
|                     }; | ||||
|                     let Type::CustomType(ty_value) = *inner_ty else { | ||||
|                         panic!("GetStructElemPtr on non-struct! ({:?})", &inner_ty) | ||||
|                     }; | ||||
|                     let field_ty = match builder.type_data(&ty_value).kind { | ||||
|                         CustomTypeKind::NamedStruct(NamedStruct(_, fields)) => { | ||||
|                             fields.get_unchecked(*idx as usize).clone() | ||||
|                         } | ||||
|                     }; | ||||
|                     Ok(Type::Ptr(Box::new(field_ty))) | ||||
|                 } | ||||
|                 ExtractValue(instr, idx) => { | ||||
|                     let instr_ty = instr.get_type(builder)?; | ||||
|                     Ok(match instr_ty { | ||||
|                         Type::CustomType(struct_ty) => { | ||||
|                             let data = builder.type_data(&struct_ty); | ||||
|                             match data.kind { | ||||
|                                 CustomTypeKind::NamedStruct(named_struct) => { | ||||
|                                     named_struct.1.get(*idx as usize).unwrap().clone() | ||||
|                                 } | ||||
|                             } | ||||
|                         } | ||||
|                         Type::Array(elem_ty, _) => *elem_ty.clone(), | ||||
|                         _ => return Err(()), | ||||
|                     }) | ||||
|                 } | ||||
|                 Trunc(instr, ty) => instr.cast_to(builder, ty).map(|_| ty.clone()), | ||||
|                 ZExt(instr, ty) => instr.cast_to(builder, ty).map(|_| ty.clone()), | ||||
|                 SExt(instr, ty) => instr.cast_to(builder, ty).map(|_| ty.clone()), | ||||
|                 FPTrunc(instr, ty) => instr.cast_to(builder, ty).map(|_| ty.clone()), | ||||
|                 FPExt(instr, ty) => instr.cast_to(builder, ty).map(|_| ty.clone()), | ||||
|                 FPToUI(instr, ty) => instr.cast_to(builder, ty).map(|_| ty.clone()), | ||||
|                 FPToSI(instr, ty) => instr.cast_to(builder, ty).map(|_| ty.clone()), | ||||
|                 UIToFP(instr, ty) => instr.cast_to(builder, ty).map(|_| ty.clone()), | ||||
|                 SIToFP(instr, ty) => instr.cast_to(builder, ty).map(|_| ty.clone()), | ||||
|                 PtrToInt(instr, ty) => instr.cast_to(builder, ty).map(|_| ty.clone()), | ||||
|                 IntToPtr(instr, ty) => instr.cast_to(builder, ty).map(|_| ty.clone()), | ||||
|                 BitCast(instr, ty) => instr.cast_to(builder, ty).map(|_| ty.clone()), | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fn cast_to(&self, builder: &Builder, ty: &Type) -> Result<Instr, ()> { | ||||
|         self.get_type(builder)? | ||||
|             .cast_instruction(*self, &ty) | ||||
|             .ok_or(()) | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -943,6 +943,78 @@ impl InstructionHolder { | ||||
|                     *idx, | ||||
|                     name.as_ptr(), | ||||
|                 ), | ||||
|                 Trunc(instr_val, ty) => LLVMBuildTrunc( | ||||
|                     module.builder_ref, | ||||
|                     module.values.get(instr_val).unwrap().value_ref, | ||||
|                     ty.as_llvm(module.context_ref, &module.types), | ||||
|                     name.as_ptr(), | ||||
|                 ), | ||||
|                 ZExt(instr_val, ty) => LLVMBuildZExt( | ||||
|                     module.builder_ref, | ||||
|                     module.values.get(instr_val).unwrap().value_ref, | ||||
|                     ty.as_llvm(module.context_ref, &module.types), | ||||
|                     name.as_ptr(), | ||||
|                 ), | ||||
|                 SExt(instr_val, ty) => LLVMBuildSExt( | ||||
|                     module.builder_ref, | ||||
|                     module.values.get(instr_val).unwrap().value_ref, | ||||
|                     ty.as_llvm(module.context_ref, &module.types), | ||||
|                     name.as_ptr(), | ||||
|                 ), | ||||
|                 FPTrunc(instr_val, ty) => LLVMBuildTrunc( | ||||
|                     module.builder_ref, | ||||
|                     module.values.get(instr_val).unwrap().value_ref, | ||||
|                     ty.as_llvm(module.context_ref, &module.types), | ||||
|                     name.as_ptr(), | ||||
|                 ), | ||||
|                 FPExt(instr_val, ty) => LLVMBuildFPExt( | ||||
|                     module.builder_ref, | ||||
|                     module.values.get(instr_val).unwrap().value_ref, | ||||
|                     ty.as_llvm(module.context_ref, &module.types), | ||||
|                     name.as_ptr(), | ||||
|                 ), | ||||
|                 FPToUI(instr_val, ty) => LLVMBuildFPToUI( | ||||
|                     module.builder_ref, | ||||
|                     module.values.get(instr_val).unwrap().value_ref, | ||||
|                     ty.as_llvm(module.context_ref, &module.types), | ||||
|                     name.as_ptr(), | ||||
|                 ), | ||||
|                 FPToSI(instr_val, ty) => LLVMBuildFPToSI( | ||||
|                     module.builder_ref, | ||||
|                     module.values.get(instr_val).unwrap().value_ref, | ||||
|                     ty.as_llvm(module.context_ref, &module.types), | ||||
|                     name.as_ptr(), | ||||
|                 ), | ||||
|                 UIToFP(instr_val, ty) => LLVMBuildUIToFP( | ||||
|                     module.builder_ref, | ||||
|                     module.values.get(instr_val).unwrap().value_ref, | ||||
|                     ty.as_llvm(module.context_ref, &module.types), | ||||
|                     name.as_ptr(), | ||||
|                 ), | ||||
|                 SIToFP(instr_val, ty) => LLVMBuildSIToFP( | ||||
|                     module.builder_ref, | ||||
|                     module.values.get(instr_val).unwrap().value_ref, | ||||
|                     ty.as_llvm(module.context_ref, &module.types), | ||||
|                     name.as_ptr(), | ||||
|                 ), | ||||
|                 PtrToInt(instr_val, ty) => LLVMBuildPtrToInt( | ||||
|                     module.builder_ref, | ||||
|                     module.values.get(instr_val).unwrap().value_ref, | ||||
|                     ty.as_llvm(module.context_ref, &module.types), | ||||
|                     name.as_ptr(), | ||||
|                 ), | ||||
|                 IntToPtr(instr_val, ty) => LLVMBuildIntToPtr( | ||||
|                     module.builder_ref, | ||||
|                     module.values.get(instr_val).unwrap().value_ref, | ||||
|                     ty.as_llvm(module.context_ref, &module.types), | ||||
|                     name.as_ptr(), | ||||
|                 ), | ||||
|                 BitCast(instr_val, ty) => LLVMBuildBitCast( | ||||
|                     module.builder_ref, | ||||
|                     module.values.get(instr_val).unwrap().value_ref, | ||||
|                     ty.as_llvm(module.context_ref, &module.types), | ||||
|                     name.as_ptr(), | ||||
|                 ), | ||||
|             } | ||||
|         }; | ||||
|         if let Some(record) = &self.record { | ||||
|  | ||||
| @ -342,6 +342,42 @@ impl Debug for Instr { | ||||
|             Instr::ExtractValue(instruction_value, index) => { | ||||
|                 fmt_index(f, instruction_value, &index.to_string()) | ||||
|             } | ||||
|             Instr::Trunc(instr_val, ty) => { | ||||
|                 write!(f, "{:?} to {:?} ({})", instr_val, ty, self.default_name()) | ||||
|             } | ||||
|             Instr::ZExt(instr_val, ty) => { | ||||
|                 write!(f, "{:?} to {:?} ({})", instr_val, ty, self.default_name()) | ||||
|             } | ||||
|             Instr::SExt(instr_val, ty) => { | ||||
|                 write!(f, "{:?} to {:?} ({})", instr_val, ty, self.default_name()) | ||||
|             } | ||||
|             Instr::FPTrunc(instr_val, ty) => { | ||||
|                 write!(f, "{:?} to {:?} ({})", instr_val, ty, self.default_name()) | ||||
|             } | ||||
|             Instr::FPExt(instr_val, ty) => { | ||||
|                 write!(f, "{:?} to {:?} ({})", instr_val, ty, self.default_name()) | ||||
|             } | ||||
|             Instr::FPToUI(instr_val, ty) => { | ||||
|                 write!(f, "{:?} to {:?} ({})", instr_val, ty, self.default_name()) | ||||
|             } | ||||
|             Instr::FPToSI(instr_val, ty) => { | ||||
|                 write!(f, "{:?} to {:?} ({})", instr_val, ty, self.default_name()) | ||||
|             } | ||||
|             Instr::UIToFP(instr_val, ty) => { | ||||
|                 write!(f, "{:?} to {:?} ({})", instr_val, ty, self.default_name()) | ||||
|             } | ||||
|             Instr::SIToFP(instr_val, ty) => { | ||||
|                 write!(f, "{:?} to {:?} ({})", instr_val, ty, self.default_name()) | ||||
|             } | ||||
|             Instr::PtrToInt(instr_val, ty) => { | ||||
|                 write!(f, "{:?} to {:?} ({})", instr_val, ty, self.default_name()) | ||||
|             } | ||||
|             Instr::IntToPtr(instr_val, ty) => { | ||||
|                 write!(f, "{:?} to {:?} ({})", instr_val, ty, self.default_name()) | ||||
|             } | ||||
|             Instr::BitCast(instr_val, ty) => { | ||||
|                 write!(f, "{:?} to {:?} ({})", instr_val, ty, self.default_name()) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -233,6 +233,18 @@ impl Instr { | ||||
|             Instr::ICmp(..) => "icmp", | ||||
|             Instr::FunctionCall(..) => "call", | ||||
|             Instr::FCmp(_, _, _) => "fcmp", | ||||
|             Instr::Trunc(_, _) => "trunc", | ||||
|             Instr::ZExt(_, _) => "zext", | ||||
|             Instr::SExt(_, _) => "sext", | ||||
|             Instr::FPTrunc(_, _) => "fptrunc", | ||||
|             Instr::FPExt(_, _) => "pfext", | ||||
|             Instr::FPToUI(_, _) => "fptoui", | ||||
|             Instr::FPToSI(_, _) => "fptosi", | ||||
|             Instr::UIToFP(_, _) => "uitofp", | ||||
|             Instr::SIToFP(_, _) => "sitofp", | ||||
|             Instr::PtrToInt(_, _) => "ptrtoint", | ||||
|             Instr::IntToPtr(_, _) => "inttoptr", | ||||
|             Instr::BitCast(_, _) => "bitcast", | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -310,34 +322,6 @@ impl<'builder> Block<'builder> { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl InstructionValue { | ||||
|     pub fn with_location(self, block: &Block, location: DebugLocationValue) -> InstructionValue { | ||||
|         unsafe { | ||||
|             block.builder.add_instruction_location(&self, location); | ||||
|         } | ||||
|         self | ||||
|     } | ||||
| 
 | ||||
|     pub fn maybe_location( | ||||
|         self, | ||||
|         block: &mut Block, | ||||
|         location: Option<DebugLocationValue>, | ||||
|     ) -> InstructionValue { | ||||
|         unsafe { | ||||
|             if let Some(location) = location { | ||||
|                 block.builder.add_instruction_location(&self, location); | ||||
|             } | ||||
|         } | ||||
|         self | ||||
|     } | ||||
| 
 | ||||
|     pub fn add_record(&self, block: &mut Block, record: InstructionDebugRecordData) { | ||||
|         unsafe { | ||||
|             block.builder.add_instruction_record(self, record); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(Clone)] | ||||
| pub struct InstructionData { | ||||
|     kind: Instr, | ||||
| @ -355,6 +339,7 @@ pub enum CmpPredicate { | ||||
|     NE, | ||||
| } | ||||
| 
 | ||||
| /// https://llvm.org/docs/LangRef.html#instruction-reference
 | ||||
| #[derive(Clone)] | ||||
| pub enum Instr { | ||||
|     Param(usize), | ||||
| @ -397,8 +382,56 @@ pub enum Instr { | ||||
| 
 | ||||
|     /// Integer Comparison
 | ||||
|     ICmp(CmpPredicate, InstructionValue, InstructionValue), | ||||
|     /// FLoat Comparison
 | ||||
|     FCmp(CmpPredicate, InstructionValue, InstructionValue), | ||||
| 
 | ||||
|     /// The `trunc` instruction truncates the high order bits in value and
 | ||||
|     /// converts the remaining bits to ty2. Since the source size must be larger
 | ||||
|     /// than the destination size, `trunc` cannot be a no-op cast. It will
 | ||||
|     /// always truncate bits.
 | ||||
|     Trunc(InstructionValue, Type), | ||||
|     /// The `zext` fills the high order bits of the value with zero bits until
 | ||||
|     /// it reaches the size of the destination type, ty2.
 | ||||
|     ZExt(InstructionValue, Type), | ||||
|     /// The `sext` instruction performs a sign extension by copying the sign bit
 | ||||
|     /// (highest order bit) of the value until it reaches the bit size of the
 | ||||
|     /// type ty2.
 | ||||
|     SExt(InstructionValue, Type), | ||||
|     /// The `fptrunc` instruction casts a value from a larger floating-point
 | ||||
|     /// type to a smaller floating-point type.
 | ||||
|     FPTrunc(InstructionValue, Type), | ||||
|     /// The `fpext` instruction extends the value from a smaller floating-point
 | ||||
|     /// type to a larger floating-point type.
 | ||||
|     FPExt(InstructionValue, Type), | ||||
|     /// The `fptoui` instruction takes a value to cast, which must be a scalar
 | ||||
|     /// or vector floating-point value, and a type to cast it to ty2, which must
 | ||||
|     /// be an integer type.
 | ||||
|     FPToUI(InstructionValue, Type), | ||||
|     /// The `fptosi` instruction takes a value to cast, which must be a scalar
 | ||||
|     /// or vector floating-point value, and a type to cast it to ty2, which must
 | ||||
|     /// be an integer type.
 | ||||
|     FPToSI(InstructionValue, Type), | ||||
|     /// The `uitofp` instruction takes a value to cast, which must be a scalar
 | ||||
|     /// or vector integer value, and a type to cast it to ty2, which must be an
 | ||||
|     /// floating-point type.
 | ||||
|     UIToFP(InstructionValue, Type), | ||||
|     /// The `sitofp` instruction takes a value to cast, which must be a scalar
 | ||||
|     /// or vector integer value, and a type to cast it to ty2, which must be an
 | ||||
|     /// floating-point type
 | ||||
|     SIToFP(InstructionValue, Type), | ||||
|     /// The `ptrtoint` instruction converts value to integer type ty2 by
 | ||||
|     /// interpreting the all pointer representation bits as an integer
 | ||||
|     /// (equivalent to a bitcast) and either truncating or zero extending that
 | ||||
|     /// value to the size of the integer type.
 | ||||
|     PtrToInt(InstructionValue, Type), | ||||
|     /// The `inttoptr` instruction converts value to type ty2 by applying either
 | ||||
|     /// a zero extension or a truncation depending on the size of the integer
 | ||||
|     /// value.
 | ||||
|     IntToPtr(InstructionValue, Type), | ||||
|     /// The `bitcast` instruction converts value to type ty2. It is always a
 | ||||
|     /// no-op cast because no bits change with this conversion.
 | ||||
|     BitCast(InstructionValue, Type), | ||||
| 
 | ||||
|     FunctionCall(FunctionValue, Vec<InstructionValue>), | ||||
| } | ||||
| 
 | ||||
| @ -473,84 +506,6 @@ pub enum CustomTypeKind { | ||||
| #[derive(Debug, PartialEq, Eq, Clone, Hash)] | ||||
| pub struct NamedStruct(pub String, pub Vec<Type>); | ||||
| 
 | ||||
| impl InstructionValue { | ||||
|     pub(crate) fn get_type(&self, builder: &Builder) -> Result<Type, ()> { | ||||
|         use Instr::*; | ||||
|         unsafe { | ||||
|             match &builder.instr_data(self).kind { | ||||
|                 Param(nth) => builder | ||||
|                     .function_data(&self.0.0) | ||||
|                     .params | ||||
|                     .get(*nth) | ||||
|                     .cloned() | ||||
|                     .ok_or(()), | ||||
|                 Constant(c) => Ok(c.get_type()), | ||||
|                 Add(lhs, rhs) => match_types(lhs, rhs, &builder), | ||||
|                 FAdd(lhs, rhs) => match_types(lhs, rhs, &builder), | ||||
|                 Sub(lhs, rhs) => match_types(lhs, rhs, &builder), | ||||
|                 FSub(lhs, rhs) => match_types(lhs, rhs, &builder), | ||||
|                 Mul(lhs, rhs) => match_types(lhs, rhs, &builder), | ||||
|                 FMul(lhs, rhs) => match_types(lhs, rhs, &builder), | ||||
|                 UDiv(lhs, rhs) => match_types(lhs, rhs, &builder), | ||||
|                 SDiv(lhs, rhs) => match_types(lhs, rhs, &builder), | ||||
|                 FDiv(lhs, rhs) => match_types(lhs, rhs, &builder), | ||||
|                 URem(lhs, rhs) => match_types(lhs, rhs, &builder), | ||||
|                 SRem(lhs, rhs) => match_types(lhs, rhs, &builder), | ||||
|                 FRem(lhs, rhs) => match_types(lhs, rhs, &builder), | ||||
|                 And(lhs, rhs) => match_types(lhs, rhs, &builder), | ||||
|                 ICmp(_, _, _) => Ok(Type::Bool), | ||||
|                 FCmp(_, _, _) => Ok(Type::Bool), | ||||
|                 FunctionCall(function_value, _) => Ok(builder.function_data(function_value).ret), | ||||
|                 Phi(values) => values.first().ok_or(()).and_then(|v| v.get_type(&builder)), | ||||
|                 Alloca(ty) => Ok(Type::Ptr(Box::new(ty.clone()))), | ||||
|                 Load(_, ty) => Ok(ty.clone()), | ||||
|                 Store(_, value) => value.get_type(builder), | ||||
|                 ArrayAlloca(ty, _) => Ok(Type::Ptr(Box::new(ty.clone()))), | ||||
|                 GetElemPtr(instr, _) => { | ||||
|                     let instr_ty = instr.get_type(builder)?; | ||||
|                     let Type::Ptr(inner_ty) = &instr_ty else { | ||||
|                         panic!("GetStructElemPtr on non-pointer! ({:?})", &instr_ty) | ||||
|                     }; | ||||
|                     match *inner_ty.clone() { | ||||
|                         Type::Array(elem_ty, _) => Ok(Type::Ptr(Box::new(*elem_ty.clone()))), | ||||
|                         _ => Ok(instr_ty), | ||||
|                     } | ||||
|                 } | ||||
|                 GetStructElemPtr(instr, idx) => { | ||||
|                     let instr_ty = instr.get_type(builder)?; | ||||
|                     let Type::Ptr(inner_ty) = instr_ty else { | ||||
|                         panic!("GetStructElemPtr on non-pointer! ({:?})", &instr_ty) | ||||
|                     }; | ||||
|                     let Type::CustomType(ty_value) = *inner_ty else { | ||||
|                         panic!("GetStructElemPtr on non-struct! ({:?})", &inner_ty) | ||||
|                     }; | ||||
|                     let field_ty = match builder.type_data(&ty_value).kind { | ||||
|                         CustomTypeKind::NamedStruct(NamedStruct(_, fields)) => { | ||||
|                             fields.get_unchecked(*idx as usize).clone() | ||||
|                         } | ||||
|                     }; | ||||
|                     Ok(Type::Ptr(Box::new(field_ty))) | ||||
|                 } | ||||
|                 ExtractValue(instr, idx) => { | ||||
|                     let instr_ty = instr.get_type(builder)?; | ||||
|                     Ok(match instr_ty { | ||||
|                         Type::CustomType(struct_ty) => { | ||||
|                             let data = builder.type_data(&struct_ty); | ||||
|                             match data.kind { | ||||
|                                 CustomTypeKind::NamedStruct(named_struct) => { | ||||
|                                     named_struct.1.get(*idx as usize).unwrap().clone() | ||||
|                                 } | ||||
|                             } | ||||
|                         } | ||||
|                         Type::Array(elem_ty, _) => *elem_ty.clone(), | ||||
|                         _ => return Err(()), | ||||
|                     }) | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl ConstValue { | ||||
|     pub fn get_type(&self) -> Type { | ||||
|         use Type::*; | ||||
| @ -657,6 +612,63 @@ impl Type { | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn cast_instruction(&self, value: InstructionValue, other: &Type) -> Option<Instr> { | ||||
|         use Type::*; | ||||
|         match (self, other) { | ||||
|             (I8, I16 | I32 | I64 | I128) => Some(Instr::SExt(value, other.clone())), | ||||
|             (I16, I32 | I64 | I128) => Some(Instr::SExt(value, other.clone())), | ||||
|             (I32, I64 | I128) => Some(Instr::SExt(value, other.clone())), | ||||
|             (I64, I128) => Some(Instr::SExt(value, other.clone())), | ||||
|             (I128 | U128, I64 | U64 | I32 | U32 | I16 | U16 | I8 | U8) => { | ||||
|                 Some(Instr::Trunc(value, other.clone())) | ||||
|             } | ||||
|             (I64 | U64, I32 | U32 | I16 | U16 | I8 | U8) => { | ||||
|                 Some(Instr::Trunc(value, other.clone())) | ||||
|             } | ||||
|             (I32 | U32, I16 | U16 | I8 | U8) => Some(Instr::Trunc(value, other.clone())), | ||||
|             (I16 | U16, I8 | U8) => Some(Instr::Trunc(value, other.clone())), | ||||
|             (U8 | I8, U16 | I16 | U32 | I32 | U64 | I64 | U128 | I128) => { | ||||
|                 Some(Instr::ZExt(value, other.clone())) | ||||
|             } | ||||
|             (U16 | I16, U32 | I32 | U64 | I64 | U128 | I128) => { | ||||
|                 Some(Instr::ZExt(value, other.clone())) | ||||
|             } | ||||
|             (U32 | I32, U64 | I64 | U128 | I128) => Some(Instr::ZExt(value, other.clone())), | ||||
|             (U64 | I64, U128 | I128) => Some(Instr::ZExt(value, other.clone())), | ||||
|             (U8 | U16 | U32 | U64 | U128, F16 | F32 | F32B | F64 | F80 | F128 | F128PPC) => { | ||||
|                 Some(Instr::UIToFP(value, other.clone())) | ||||
|             } | ||||
|             (I8 | I16 | I32 | I64 | I128, F16 | F32 | F32B | F64 | F80 | F128 | F128PPC) => { | ||||
|                 Some(Instr::SIToFP(value, other.clone())) | ||||
|             } | ||||
|             (F16 | F32 | F32B | F64 | F80 | F128 | F128PPC, U8 | U16 | U32 | U64 | U128) => { | ||||
|                 Some(Instr::FPToUI(value, other.clone())) | ||||
|             } | ||||
|             (F16 | F32 | F32B | F64 | F80 | F128 | F128PPC, I8 | I16 | I32 | I64 | I128) => { | ||||
|                 Some(Instr::FPToSI(value, other.clone())) | ||||
|             } | ||||
|             (I128 | U128 | I64 | U64 | I32 | U32 | I16 | U16 | I8 | U8, Ptr(_)) => { | ||||
|                 Some(Instr::IntToPtr(value, other.clone())) | ||||
|             } | ||||
|             (Ptr(_), I128 | U128 | I64 | U64 | I32 | U32 | I16 | U16 | I8 | U8) => { | ||||
|                 Some(Instr::PtrToInt(value, other.clone())) | ||||
|             } | ||||
|             (F16, F32 | F32B | F64 | F80 | F128 | F128PPC) => { | ||||
|                 Some(Instr::FPExt(value, other.clone())) | ||||
|             } | ||||
|             (F32 | F32B, F64 | F80 | F128 | F128PPC) => Some(Instr::FPExt(value, other.clone())), | ||||
|             (F64, F80 | F128 | F128PPC) => Some(Instr::FPExt(value, other.clone())), | ||||
|             (F80, F128 | F128PPC) => Some(Instr::FPExt(value, other.clone())), | ||||
|             (F128PPC | F128, F80 | F64 | F32B | F32 | F16) => { | ||||
|                 Some(Instr::FPTrunc(value, other.clone())) | ||||
|             } | ||||
|             (F80, F64 | F32B | F32 | F16) => Some(Instr::FPTrunc(value, other.clone())), | ||||
|             (F64, F32B | F32 | F16) => Some(Instr::FPTrunc(value, other.clone())), | ||||
|             (F32B | F32, F16) => Some(Instr::FPTrunc(value, other.clone())), | ||||
|             _ => None, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #[derive(PartialEq, Eq, PartialOrd, Ord)] | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user