264 lines
11 KiB
Rust
264 lines
11 KiB
Rust
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(crate) fn signature(&self, builder: &Builder) -> CompileResult<(String, Vec<Type>, Type)> {
|
|
match self {
|
|
LLVMIntrinsic::Max(ty) => {
|
|
let name = match ty.category() {
|
|
TypeCategory::SignedInteger => format!("llvm.smax.{}", ty.llvm_ty_str(builder)),
|
|
TypeCategory::UnsignedInteger => format!("llvm.umax.{}", ty.llvm_ty_str(builder)),
|
|
TypeCategory::Real => format!("llvm.maximum.{}", 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() {
|
|
TypeCategory::SignedInteger => format!("llvm.smin.{}", ty.llvm_ty_str(builder)),
|
|
TypeCategory::UnsignedInteger => format!("llvm.umin.{}", ty.llvm_ty_str(builder)),
|
|
TypeCategory::Real => format!("llvm.minimum.{}", 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::U64, Type::Bool], 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.rint.{}", ty.llvm_ty_str(builder)),
|
|
_ => return Err(crate::ErrorKind::Null),
|
|
};
|
|
Ok((name, vec![ty.clone()], ty.clone()))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Type {
|
|
fn llvm_ty_str(&self, builder: &Builder) -> String {
|
|
match self {
|
|
Type::I8 => String::from("i8"),
|
|
Type::I16 => String::from("u16"),
|
|
Type::I32 => String::from("i32"),
|
|
Type::I64 => String::from("i64"),
|
|
Type::I128 => String::from("i128"),
|
|
Type::U8 => String::from("i8"),
|
|
Type::U16 => String::from("i16"),
|
|
Type::U32 => String::from("i32"),
|
|
Type::U64 => String::from("i64"),
|
|
Type::U128 => String::from("i128"),
|
|
Type::F16 => String::from("f16"),
|
|
Type::F32B => String::from("f32b"),
|
|
Type::F32 => String::from("f32"),
|
|
Type::F64 => String::from("f64"),
|
|
Type::F80 => String::from("x86_fp80"),
|
|
Type::F128 => String::from("fp128"),
|
|
Type::F128PPC => String::from("ppc_fp128"),
|
|
Type::Bool => String::from("i1"),
|
|
Type::Void => String::from("void"),
|
|
Type::CustomType(type_value) => {
|
|
let ty = unsafe { builder.type_data(type_value) };
|
|
ty.name.clone()
|
|
}
|
|
Type::Array(ty, len) => format!("[{} x {}]", len, ty.llvm_ty_str(builder)),
|
|
Type::Ptr(_) => String::from("ptr"),
|
|
}
|
|
}
|
|
}
|