Add intrinsic min/max to integers and floats
This commit is contained in:
parent
4a33e7d123
commit
5d19d38682
5
examples/math_intrinsics.reid
Normal file
5
examples/math_intrinsics.reid
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
|
||||||
|
fn main() -> i32 {
|
||||||
|
let b = 5;
|
||||||
|
return b.min(7);
|
||||||
|
}
|
@ -6,7 +6,7 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
CmpPredicate, Context, Instr, InstructionData, TerminatorKind,
|
CmpPredicate, Context, Instr, InstructionData, TerminatorKind, Type,
|
||||||
builder::*,
|
builder::*,
|
||||||
debug_information::{
|
debug_information::{
|
||||||
DebugArrayType, DebugBasicType, DebugFieldType, DebugInformation, DebugLocalVariable, DebugLocation,
|
DebugArrayType, DebugBasicType, DebugFieldType, DebugInformation, DebugLocalVariable, DebugLocation,
|
||||||
|
69
reid-llvm-lib/src/intrinsics.rs
Normal file
69
reid-llvm-lib/src/intrinsics.rs
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
use crate::{CompileResult, Type, builder::Builder};
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum LLVMIntrinsic {
|
||||||
|
Max(Type),
|
||||||
|
Min(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)> {
|
||||||
|
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)),
|
||||||
|
_ => 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)),
|
||||||
|
_ => return Err(crate::ErrorKind::Null),
|
||||||
|
};
|
||||||
|
Ok((name, vec![ty.clone(), 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("half"),
|
||||||
|
Type::F32B => String::from("bfloat"),
|
||||||
|
Type::F32 => String::from("float"),
|
||||||
|
Type::F64 => String::from("double"),
|
||||||
|
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"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -11,12 +11,14 @@ use fmt::PrintableModule;
|
|||||||
use crate::{
|
use crate::{
|
||||||
builder::{ConstantValue, GlobalValue},
|
builder::{ConstantValue, GlobalValue},
|
||||||
debug_information::DebugScopeValue,
|
debug_information::DebugScopeValue,
|
||||||
|
intrinsics::LLVMIntrinsic,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub mod builder;
|
pub mod builder;
|
||||||
pub mod compile;
|
pub mod compile;
|
||||||
pub mod debug_information;
|
pub mod debug_information;
|
||||||
mod fmt;
|
mod fmt;
|
||||||
|
pub mod intrinsics;
|
||||||
mod pad_adapter;
|
mod pad_adapter;
|
||||||
mod util;
|
mod util;
|
||||||
|
|
||||||
@ -95,6 +97,25 @@ impl<'ctx> Module<'ctx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn intrinsic(&self, intrinsic: LLVMIntrinsic) -> CompileResult<FunctionValue> {
|
||||||
|
unsafe {
|
||||||
|
let (name, params, ret) = intrinsic.signature(&self.builder)?;
|
||||||
|
Ok(self.builder.add_function(
|
||||||
|
&self.value,
|
||||||
|
FunctionData {
|
||||||
|
name: name.to_owned(),
|
||||||
|
linkage_name: Some(name.to_owned()),
|
||||||
|
ret,
|
||||||
|
params,
|
||||||
|
flags: FunctionFlags {
|
||||||
|
is_extern: true,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn custom_type(&self, ty: CustomTypeKind) -> TypeValue {
|
pub fn custom_type(&self, ty: CustomTypeKind) -> TypeValue {
|
||||||
unsafe {
|
unsafe {
|
||||||
let (name, kind) = match &ty {
|
let (name, kind) = match &ty {
|
||||||
|
@ -1021,9 +1021,8 @@ pub fn analyze_expr(
|
|||||||
function_autocomplete.extend(
|
function_autocomplete.extend(
|
||||||
get_intrinsic_assoc_functions(&invoked_ty)
|
get_intrinsic_assoc_functions(&invoked_ty)
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|(s, f)| f.as_ref().map(|f| (s, f)))
|
.filter(|fun| fun.name.starts_with(name))
|
||||||
.filter(|(_, fun)| fun.name.starts_with(name))
|
.map(|fun| Autocomplete {
|
||||||
.map(|(_, fun)| Autocomplete {
|
|
||||||
text: fun.name.clone(),
|
text: fun.name.clone(),
|
||||||
kind: AutocompleteKind::Function(fun.parameters.clone(), fun.return_type.clone()),
|
kind: AutocompleteKind::Function(fun.parameters.clone(), fun.return_type.clone()),
|
||||||
})
|
})
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
use std::{collections::HashMap, hash::Hash};
|
|
||||||
|
|
||||||
use reid_lib::{builder::InstructionValue, CmpPredicate, ConstValueKind, Instr, Type};
|
use reid_lib::{builder::InstructionValue, CmpPredicate, ConstValueKind, Instr, Type};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
codegen::{ErrorKind, StackValueKind},
|
codegen::{scope::IntrinsicKind, ErrorKind, StackValueKind},
|
||||||
mir::{
|
mir::{
|
||||||
BinaryOperator, BinopDefinition, CmpOperator, FunctionDefinition, FunctionDefinitionKind, FunctionParam,
|
implement::TypeCategory, BinaryOperator, BinopDefinition, CmpOperator, FunctionDefinition,
|
||||||
TypeKind,
|
FunctionDefinitionKind, FunctionParam, TypeKind,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -60,79 +58,108 @@ pub fn form_intrinsics() -> Vec<FunctionDefinition> {
|
|||||||
intrinsics
|
intrinsics
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_intrinsic_assoc_functions(ty: &TypeKind) -> HashMap<String, Option<FunctionDefinition>> {
|
pub fn get_intrinsic_assoc_functions(ty: &TypeKind) -> Vec<FunctionDefinition> {
|
||||||
let mut map = HashMap::new();
|
let mut intrinsics = Vec::new();
|
||||||
map.insert("length".to_owned(), get_intrinsic_assoc_func(ty, "length"));
|
|
||||||
map.insert("sizeof".to_owned(), get_intrinsic_assoc_func(ty, "sizeof"));
|
|
||||||
map.insert("malloc".to_owned(), get_intrinsic_assoc_func(ty, "malloc"));
|
|
||||||
map.insert("null".to_owned(), get_intrinsic_assoc_func(ty, "null"));
|
|
||||||
map
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_intrinsic_assoc_func(ty: &TypeKind, name: &str) -> Option<FunctionDefinition> {
|
|
||||||
if let TypeKind::Array(_, len) = ty {
|
if let TypeKind::Array(_, len) = ty {
|
||||||
match name {
|
intrinsics.push(FunctionDefinition {
|
||||||
"length" => {
|
name: "length".to_owned(),
|
||||||
return Some(FunctionDefinition {
|
|
||||||
name: "length".to_owned(),
|
|
||||||
linkage_name: None,
|
|
||||||
is_pub: true,
|
|
||||||
is_imported: false,
|
|
||||||
return_type: TypeKind::U64,
|
|
||||||
parameters: vec![FunctionParam {
|
|
||||||
name: String::from("self"),
|
|
||||||
ty: TypeKind::Borrow(Box::new(ty.clone()), false),
|
|
||||||
meta: Default::default(),
|
|
||||||
}],
|
|
||||||
kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicConst(*len))),
|
|
||||||
source: None,
|
|
||||||
signature_meta: Default::default(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
match name {
|
|
||||||
"sizeof" => Some(FunctionDefinition {
|
|
||||||
name: "sizeof".to_owned(),
|
|
||||||
linkage_name: None,
|
linkage_name: None,
|
||||||
is_pub: true,
|
is_pub: true,
|
||||||
is_imported: false,
|
is_imported: false,
|
||||||
return_type: TypeKind::U64,
|
return_type: TypeKind::U64,
|
||||||
parameters: Vec::new(),
|
|
||||||
kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicSizeOf(ty.clone()))),
|
|
||||||
source: None,
|
|
||||||
signature_meta: Default::default(),
|
|
||||||
}),
|
|
||||||
"malloc" => Some(FunctionDefinition {
|
|
||||||
name: "malloc".to_owned(),
|
|
||||||
linkage_name: None,
|
|
||||||
is_pub: true,
|
|
||||||
is_imported: false,
|
|
||||||
return_type: TypeKind::UserPtr(Box::new(ty.clone())),
|
|
||||||
parameters: vec![FunctionParam {
|
parameters: vec![FunctionParam {
|
||||||
name: String::from("size"),
|
name: String::from("self"),
|
||||||
ty: TypeKind::U64,
|
ty: TypeKind::Borrow(Box::new(ty.clone()), false),
|
||||||
meta: Default::default(),
|
meta: Default::default(),
|
||||||
}],
|
}],
|
||||||
kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicMalloc(ty.clone()))),
|
kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicConst(*len))),
|
||||||
source: None,
|
source: None,
|
||||||
signature_meta: Default::default(),
|
signature_meta: Default::default(),
|
||||||
}),
|
});
|
||||||
"null" => Some(FunctionDefinition {
|
|
||||||
name: "null".to_owned(),
|
|
||||||
linkage_name: None,
|
|
||||||
is_pub: true,
|
|
||||||
is_imported: false,
|
|
||||||
return_type: TypeKind::UserPtr(Box::new(ty.clone())),
|
|
||||||
parameters: Vec::new(),
|
|
||||||
kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicNullPtr(ty.clone()))),
|
|
||||||
source: None,
|
|
||||||
signature_meta: Default::default(),
|
|
||||||
}),
|
|
||||||
_ => None,
|
|
||||||
}
|
}
|
||||||
|
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(FunctionDefinition {
|
||||||
|
name: "sizeof".to_owned(),
|
||||||
|
linkage_name: None,
|
||||||
|
is_pub: true,
|
||||||
|
is_imported: false,
|
||||||
|
return_type: TypeKind::U64,
|
||||||
|
parameters: Vec::new(),
|
||||||
|
kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicSizeOf(ty.clone()))),
|
||||||
|
source: None,
|
||||||
|
signature_meta: Default::default(),
|
||||||
|
});
|
||||||
|
intrinsics.push(FunctionDefinition {
|
||||||
|
name: "malloc".to_owned(),
|
||||||
|
linkage_name: None,
|
||||||
|
is_pub: true,
|
||||||
|
is_imported: false,
|
||||||
|
return_type: TypeKind::UserPtr(Box::new(ty.clone())),
|
||||||
|
parameters: vec![FunctionParam {
|
||||||
|
name: String::from("size"),
|
||||||
|
ty: TypeKind::U64,
|
||||||
|
meta: Default::default(),
|
||||||
|
}],
|
||||||
|
kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicMalloc(ty.clone()))),
|
||||||
|
source: None,
|
||||||
|
signature_meta: Default::default(),
|
||||||
|
});
|
||||||
|
|
||||||
|
intrinsics.push(FunctionDefinition {
|
||||||
|
name: "null".to_owned(),
|
||||||
|
linkage_name: None,
|
||||||
|
is_pub: true,
|
||||||
|
is_imported: false,
|
||||||
|
return_type: TypeKind::UserPtr(Box::new(ty.clone())),
|
||||||
|
parameters: Vec::new(),
|
||||||
|
kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicNullPtr(ty.clone()))),
|
||||||
|
source: None,
|
||||||
|
signature_meta: Default::default(),
|
||||||
|
});
|
||||||
|
|
||||||
|
intrinsics
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_intrinsic_assoc_func(ty: &TypeKind, name: &str) -> Option<FunctionDefinition> {
|
||||||
|
get_intrinsic_assoc_functions(ty).into_iter().find(|f| f.name == name)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn simple_binop_def<T: Clone + 'static>(op: BinaryOperator, ty: &TypeKind, fun: T) -> BinopDefinition
|
fn simple_binop_def<T: Clone + 'static>(op: BinaryOperator, ty: &TypeKind, fun: T) -> BinopDefinition
|
||||||
@ -441,6 +468,7 @@ impl IntrinsicFunction for IntrinsicNullPtr {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct IntrinsicConst(u64);
|
pub struct IntrinsicConst(u64);
|
||||||
impl IntrinsicFunction for IntrinsicConst {
|
impl IntrinsicFunction for IntrinsicConst {
|
||||||
@ -450,6 +478,23 @@ impl IntrinsicFunction for IntrinsicConst {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct IntrinsicLLVM(IntrinsicKind, 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());
|
||||||
|
let value = scope
|
||||||
|
.block
|
||||||
|
.build(Instr::FunctionCall(
|
||||||
|
intrinsic,
|
||||||
|
params.iter().map(|p| p.instr()).collect(),
|
||||||
|
))
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
Ok(StackValue(StackValueKind::Literal(value), self.1))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// impl IntrinsicFunction for IntrinsicIAdd {
|
// impl IntrinsicFunction for IntrinsicIAdd {
|
||||||
// fn codegen<'ctx, 'a>(
|
// fn codegen<'ctx, 'a>(
|
||||||
// &self,
|
// &self,
|
||||||
|
@ -393,6 +393,7 @@ impl mir::Module {
|
|||||||
}),
|
}),
|
||||||
binops: &binops,
|
binops: &binops,
|
||||||
allocator: Rc::new(RefCell::new(allocator)),
|
allocator: Rc::new(RefCell::new(allocator)),
|
||||||
|
llvm_intrinsics: Rc::new(RefCell::new(HashMap::new())),
|
||||||
};
|
};
|
||||||
|
|
||||||
binop
|
binop
|
||||||
@ -471,6 +472,7 @@ impl mir::Module {
|
|||||||
globals: &globals,
|
globals: &globals,
|
||||||
binops: &binops,
|
binops: &binops,
|
||||||
allocator: Rc::new(RefCell::new(allocator)),
|
allocator: Rc::new(RefCell::new(allocator)),
|
||||||
|
llvm_intrinsics: Rc::new(RefCell::new(HashMap::new())),
|
||||||
};
|
};
|
||||||
|
|
||||||
mir_function
|
mir_function
|
||||||
@ -533,6 +535,7 @@ impl mir::Module {
|
|||||||
globals: &globals,
|
globals: &globals,
|
||||||
binops: &binops,
|
binops: &binops,
|
||||||
allocator: Rc::new(RefCell::new(allocator)),
|
allocator: Rc::new(RefCell::new(allocator)),
|
||||||
|
llvm_intrinsics: Rc::new(RefCell::new(HashMap::new())),
|
||||||
};
|
};
|
||||||
|
|
||||||
mir_function
|
mir_function
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
use std::{cell::RefCell, collections::HashMap, mem, rc::Rc};
|
use std::{cell::RefCell, collections::HashMap, mem, rc::Rc};
|
||||||
|
|
||||||
use reid_lib::{
|
use reid_lib::{
|
||||||
builder::{GlobalValue, InstructionValue, TypeValue},
|
builder::{FunctionValue, GlobalValue, InstructionValue, TypeValue},
|
||||||
debug_information::{DebugInformation, DebugLocation, DebugScopeValue, DebugTypeValue},
|
debug_information::{DebugInformation, DebugLocation, DebugScopeValue, DebugTypeValue},
|
||||||
|
intrinsics::LLVMIntrinsic,
|
||||||
Block, Context, Function, Instr, Module,
|
Block, Context, Function, Instr, Module,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -16,6 +17,12 @@ 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>>,
|
||||||
@ -34,6 +41,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>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ctx, 'a> Scope<'ctx, 'a> {
|
impl<'ctx, 'a> Scope<'ctx, 'a> {
|
||||||
@ -56,6 +64,7 @@ impl<'ctx, 'a> Scope<'ctx, 'a> {
|
|||||||
allocator: self.allocator.clone(),
|
allocator: self.allocator.clone(),
|
||||||
globals: self.globals,
|
globals: self.globals,
|
||||||
binops: self.binops,
|
binops: self.binops,
|
||||||
|
llvm_intrinsics: self.llvm_intrinsics.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,6 +83,23 @@ impl<'ctx, 'a> Scope<'ctx, 'a> {
|
|||||||
pub fn allocate(&self, meta: &Metadata, ty: &TypeKind) -> Option<InstructionValue> {
|
pub fn allocate(&self, meta: &Metadata, ty: &TypeKind) -> Option<InstructionValue> {
|
||||||
self.allocator.borrow_mut().allocate(meta, ty)
|
self.allocator.borrow_mut().allocate(meta, ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_intrinsic(&self, kind: IntrinsicKind) -> FunctionValue {
|
||||||
|
let mut intrinsics = self.llvm_intrinsics.borrow_mut();
|
||||||
|
if let Some(fun) = intrinsics.get(&kind) {
|
||||||
|
*fun
|
||||||
|
} else {
|
||||||
|
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)),
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
intrinsics.insert(kind, intrinsic.clone());
|
||||||
|
intrinsic
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
@ -315,6 +315,16 @@ pub struct FunctionParam {
|
|||||||
pub meta: Metadata,
|
pub meta: Metadata,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl FunctionParam {
|
||||||
|
pub fn from<T: Into<String>>(name: T, ty: TypeKind) -> FunctionParam {
|
||||||
|
FunctionParam {
|
||||||
|
name: name.into(),
|
||||||
|
ty: ty,
|
||||||
|
meta: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub enum SelfKind {
|
pub enum SelfKind {
|
||||||
Borrow,
|
Borrow,
|
||||||
MutBorrow,
|
MutBorrow,
|
||||||
|
Loading…
Reference in New Issue
Block a user