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,42 +129,189 @@ 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(FunctionDefinition {
|
intrinsics.push(simple_intrinsic(
|
||||||
name: "max".to_owned(),
|
"max",
|
||||||
linkage_name: None,
|
vec!["self", "other"],
|
||||||
is_pub: true,
|
ty.clone(),
|
||||||
is_imported: false,
|
LLVMIntrinsicKind::Max(ty.clone()),
|
||||||
return_type: ty.clone(),
|
));
|
||||||
parameters: vec![
|
intrinsics.push(simple_intrinsic(
|
||||||
FunctionParam::from("self", ty.clone()),
|
"min",
|
||||||
FunctionParam::from("other", ty.clone()),
|
vec!["self", "other"],
|
||||||
],
|
ty.clone(),
|
||||||
kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicLLVM(
|
LLVMIntrinsicKind::Min(ty.clone()),
|
||||||
IntrinsicKind::Max(ty.clone()),
|
));
|
||||||
ty.clone(),
|
if ty.signed() {
|
||||||
))),
|
intrinsics.push(FunctionDefinition {
|
||||||
source: None,
|
name: "abs".to_owned(),
|
||||||
signature_meta: Default::default(),
|
linkage_name: None,
|
||||||
});
|
is_pub: true,
|
||||||
intrinsics.push(FunctionDefinition {
|
is_imported: false,
|
||||||
name: "min".to_owned(),
|
return_type: ty.clone(),
|
||||||
linkage_name: None,
|
parameters: vec![FunctionParam {
|
||||||
is_pub: true,
|
name: String::from("self"),
|
||||||
is_imported: false,
|
ty: ty.clone(),
|
||||||
return_type: ty.clone(),
|
meta: Default::default(),
|
||||||
parameters: vec![
|
}],
|
||||||
FunctionParam::from("self", ty.clone()),
|
kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicSimpleUnaryInstr({
|
||||||
FunctionParam::from("other", ty.clone()),
|
let ty = ty.clone();
|
||||||
],
|
|scope, param| {
|
||||||
kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicLLVM(
|
let intrinsic = scope.get_intrinsic(LLVMIntrinsicKind::Abs(ty));
|
||||||
IntrinsicKind::Min(ty.clone()),
|
let constant = scope.block.build(Instr::Constant(ConstValueKind::Bool(false))).unwrap();
|
||||||
ty.clone(),
|
let value = scope
|
||||||
))),
|
.block
|
||||||
source: None,
|
.build(Instr::FunctionCall(intrinsic, vec![param, constant]))
|
||||||
signature_meta: Default::default(),
|
.unwrap();
|
||||||
});
|
value
|
||||||
|
}
|
||||||
|
}))),
|
||||||
|
source: None,
|
||||||
|
signature_meta: Default::default(),
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
@ -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