Compare commits
No commits in common. "c03a5188ea5dfd33aa5ed6a994c12c0392abcef0" and "c4ab4ac0b3af99920bbc4fa9c9cffc85aaa1b263" have entirely different histories.
c03a5188ea
...
c4ab4ac0b3
@ -18,9 +18,9 @@ fn main() {
|
|||||||
FunctionFlags::default(),
|
FunctionFlags::default(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let arg = m_entry.build_named("const", Constant(I32(5))).unwrap();
|
let arg = m_entry.build("const", Constant(I32(5))).unwrap();
|
||||||
let fibonacci_call = m_entry
|
let fibonacci_call = m_entry
|
||||||
.build_named("const", FunctionCall(fibonacci.value(), vec![arg]))
|
.build("const", FunctionCall(fibonacci.value(), vec![arg]))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
m_entry
|
m_entry
|
||||||
.terminate(TerminatorKind::Ret(fibonacci_call))
|
.terminate(TerminatorKind::Ret(fibonacci_call))
|
||||||
@ -28,10 +28,10 @@ fn main() {
|
|||||||
|
|
||||||
let mut f_entry = fibonacci.block("entry");
|
let mut f_entry = fibonacci.block("entry");
|
||||||
|
|
||||||
let num_3 = f_entry.build_named("const", Constant(I32(3))).unwrap();
|
let num_3 = f_entry.build("const", Constant(I32(3))).unwrap();
|
||||||
let param_n = f_entry.build_named("param", Param(0)).unwrap();
|
let param_n = f_entry.build("param", Param(0)).unwrap();
|
||||||
let cond = f_entry
|
let cond = f_entry
|
||||||
.build_named("cmp", ICmp(CmpPredicate::LT, param_n, num_3))
|
.build("cmp", ICmp(CmpPredicate::LT, param_n, num_3))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let mut then_b = fibonacci.block("then");
|
let mut then_b = fibonacci.block("then");
|
||||||
@ -41,21 +41,21 @@ fn main() {
|
|||||||
.terminate(TerminatorKind::CondBr(cond, then_b.value(), else_b.value()))
|
.terminate(TerminatorKind::CondBr(cond, then_b.value(), else_b.value()))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let ret_const = then_b.build_named("const", Constant(I32(1))).unwrap();
|
let ret_const = then_b.build("const", Constant(I32(1))).unwrap();
|
||||||
then_b.terminate(TerminatorKind::Ret(ret_const)).unwrap();
|
then_b.terminate(TerminatorKind::Ret(ret_const)).unwrap();
|
||||||
|
|
||||||
let const_1 = else_b.build_named("const", Constant(I32(1))).unwrap();
|
let const_1 = else_b.build("const", Constant(I32(1))).unwrap();
|
||||||
let const_2 = else_b.build_named("const", Constant(I32(2))).unwrap();
|
let const_2 = else_b.build("const", Constant(I32(2))).unwrap();
|
||||||
let param_1 = else_b.build_named("sub", Sub(param_n, const_1)).unwrap();
|
let param_1 = else_b.build("sub", Sub(param_n, const_1)).unwrap();
|
||||||
let param_2 = else_b.build_named("sub", Sub(param_n, const_2)).unwrap();
|
let param_2 = else_b.build("sub", Sub(param_n, const_2)).unwrap();
|
||||||
let call_1 = else_b
|
let call_1 = else_b
|
||||||
.build_named("fibonacci", FunctionCall(fibonacci.value(), vec![param_1]))
|
.build("fibonacci", FunctionCall(fibonacci.value(), vec![param_1]))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let call_2 = else_b
|
let call_2 = else_b
|
||||||
.build_named("fibonacci", FunctionCall(fibonacci.value(), vec![param_2]))
|
.build("fibonacci", FunctionCall(fibonacci.value(), vec![param_2]))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let add = else_b.build_named("add", Add(call_1, call_2)).unwrap();
|
let add = else_b.build("add", Add(call_1, call_2)).unwrap();
|
||||||
|
|
||||||
else_b.terminate(TerminatorKind::Ret(add)).unwrap();
|
else_b.terminate(TerminatorKind::Ret(add)).unwrap();
|
||||||
|
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
use std::{cell::RefCell, rc::Rc};
|
use std::{cell::RefCell, rc::Rc};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
Block, BlockData, CustomTypeKind, FunctionData, Instr, InstructionData, ModuleData,
|
BlockData, CustomTypeKind, FunctionData, Instr, InstructionData, ModuleData, NamedStruct,
|
||||||
NamedStruct, TerminatorKind, Type, TypeCategory, TypeData,
|
TerminatorKind, Type, TypeCategory, TypeData,
|
||||||
debug_information::{
|
debug_information::{
|
||||||
DebugInformation, DebugLocationValue, DebugMetadataValue, DebugProgramValue,
|
DebugInformation, DebugLocationValue, DebugMetadataValue, DebugProgramValue,
|
||||||
InstructionDebugRecordData,
|
InstructionDebugRecordData,
|
||||||
@ -467,18 +467,6 @@ impl Builder {
|
|||||||
_ => Err(()),
|
_ => 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(|_| ()),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -517,125 +505,3 @@ 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,78 +943,6 @@ impl InstructionHolder {
|
|||||||
*idx,
|
*idx,
|
||||||
name.as_ptr(),
|
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 {
|
if let Some(record) = &self.record {
|
||||||
@ -1142,12 +1070,12 @@ impl CmpPredicate {
|
|||||||
use CmpPredicate::*;
|
use CmpPredicate::*;
|
||||||
use LLVMRealPredicate::*;
|
use LLVMRealPredicate::*;
|
||||||
match self {
|
match self {
|
||||||
LT => LLVMRealULT,
|
LT => LLVMRealOLT,
|
||||||
LE => LLVMRealULE,
|
LE => LLVMRealOLE,
|
||||||
GT => LLVMRealUGT,
|
GT => LLVMRealOGT,
|
||||||
GE => LLVMRealUGE,
|
GE => LLVMRealOGE,
|
||||||
EQ => LLVMRealUEQ,
|
EQ => LLVMRealOEQ,
|
||||||
NE => LLVMRealUNE,
|
NE => LLVMRealONE,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -342,42 +342,6 @@ impl Debug for Instr {
|
|||||||
Instr::ExtractValue(instruction_value, index) => {
|
Instr::ExtractValue(instruction_value, index) => {
|
||||||
fmt_index(f, instruction_value, &index.to_string())
|
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,24 +233,12 @@ impl Instr {
|
|||||||
Instr::ICmp(..) => "icmp",
|
Instr::ICmp(..) => "icmp",
|
||||||
Instr::FunctionCall(..) => "call",
|
Instr::FunctionCall(..) => "call",
|
||||||
Instr::FCmp(_, _, _) => "fcmp",
|
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",
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'builder> Block<'builder> {
|
impl<'builder> Block<'builder> {
|
||||||
pub fn build_named<T: Into<String>>(
|
pub fn build<T: Into<String>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
name: T,
|
name: T,
|
||||||
instruction: Instr,
|
instruction: Instr,
|
||||||
@ -268,7 +256,7 @@ impl<'builder> Block<'builder> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build(&mut self, instruction: Instr) -> Result<InstructionValue, ()> {
|
pub fn build_anon(&mut self, instruction: Instr) -> Result<InstructionValue, ()> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let name = instruction.default_name().to_owned();
|
let name = instruction.default_name().to_owned();
|
||||||
self.builder.add_instruction(
|
self.builder.add_instruction(
|
||||||
@ -322,6 +310,34 @@ 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)]
|
#[derive(Clone)]
|
||||||
pub struct InstructionData {
|
pub struct InstructionData {
|
||||||
kind: Instr,
|
kind: Instr,
|
||||||
@ -339,7 +355,6 @@ pub enum CmpPredicate {
|
|||||||
NE,
|
NE,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// https://llvm.org/docs/LangRef.html#instruction-reference
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub enum Instr {
|
pub enum Instr {
|
||||||
Param(usize),
|
Param(usize),
|
||||||
@ -382,56 +397,8 @@ pub enum Instr {
|
|||||||
|
|
||||||
/// Integer Comparison
|
/// Integer Comparison
|
||||||
ICmp(CmpPredicate, InstructionValue, InstructionValue),
|
ICmp(CmpPredicate, InstructionValue, InstructionValue),
|
||||||
/// FLoat Comparison
|
|
||||||
FCmp(CmpPredicate, InstructionValue, InstructionValue),
|
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>),
|
FunctionCall(FunctionValue, Vec<InstructionValue>),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -506,6 +473,84 @@ pub enum CustomTypeKind {
|
|||||||
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
|
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
|
||||||
pub struct NamedStruct(pub String, pub Vec<Type>);
|
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 {
|
impl ConstValue {
|
||||||
pub fn get_type(&self) -> Type {
|
pub fn get_type(&self) -> Type {
|
||||||
use Type::*;
|
use Type::*;
|
||||||
@ -612,63 +657,6 @@ 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)]
|
#[derive(PartialEq, Eq, PartialOrd, Ord)]
|
||||||
|
@ -256,9 +256,7 @@ impl ast::Expression {
|
|||||||
Box::new(expr.process(module_id)),
|
Box::new(expr.process(module_id)),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
ast::ExpressionKind::CastTo(expression, ty) => {
|
ast::ExpressionKind::CastTo(expression, _) => todo!(),
|
||||||
mir::ExprKind::CastTo(Box::new(expression.process(module_id)), ty.0.clone().into())
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
mir::Expression(kind, self.1.as_meta(module_id))
|
mir::Expression(kind, self.1.as_meta(module_id))
|
||||||
|
@ -353,16 +353,16 @@ impl mir::Module {
|
|||||||
// Codegen actual parameters
|
// Codegen actual parameters
|
||||||
let arg_name = format!("arg.{}", p_name);
|
let arg_name = format!("arg.{}", p_name);
|
||||||
let param = entry
|
let param = entry
|
||||||
.build_named(format!("{}.get", arg_name), Instr::Param(i))
|
.build(format!("{}.get", arg_name), Instr::Param(i))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let alloca = entry
|
let alloca = entry
|
||||||
.build_named(
|
.build(
|
||||||
&arg_name,
|
&arg_name,
|
||||||
Instr::Alloca(p_ty.get_type(&type_values, &types)),
|
Instr::Alloca(p_ty.get_type(&type_values, &types)),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
entry
|
entry
|
||||||
.build_named(format!("{}.store", arg_name), Instr::Store(alloca, param))
|
.build(format!("{}.store", arg_name), Instr::Store(alloca, param))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
stack_values.insert(
|
stack_values.insert(
|
||||||
p_name.clone(),
|
p_name.clone(),
|
||||||
@ -488,7 +488,7 @@ impl mir::Statement {
|
|||||||
|
|
||||||
let alloca = scope
|
let alloca = scope
|
||||||
.block
|
.block
|
||||||
.build_named(
|
.build(
|
||||||
name,
|
name,
|
||||||
Instr::Alloca(value.1.get_type(scope.type_values, scope.types)),
|
Instr::Alloca(value.1.get_type(scope.type_values, scope.types)),
|
||||||
)
|
)
|
||||||
@ -497,7 +497,7 @@ impl mir::Statement {
|
|||||||
|
|
||||||
scope
|
scope
|
||||||
.block
|
.block
|
||||||
.build_named(
|
.build(
|
||||||
format!("{}.store", name),
|
format!("{}.store", name),
|
||||||
Instr::Store(alloca, value.instr()),
|
Instr::Store(alloca, value.instr()),
|
||||||
)
|
)
|
||||||
@ -557,7 +557,7 @@ impl mir::Statement {
|
|||||||
StackValueKind::Mutable(instr) => {
|
StackValueKind::Mutable(instr) => {
|
||||||
scope
|
scope
|
||||||
.block
|
.block
|
||||||
.build_named(backing_var, Instr::Store(instr, rhs_value.instr()))
|
.build(backing_var, Instr::Store(instr, rhs_value.instr()))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.maybe_location(&mut scope.block, location);
|
.maybe_location(&mut scope.block, location);
|
||||||
}
|
}
|
||||||
@ -600,7 +600,7 @@ impl mir::Expression {
|
|||||||
v.0.derive(
|
v.0.derive(
|
||||||
scope
|
scope
|
||||||
.block
|
.block
|
||||||
.build_named(
|
.build(
|
||||||
format!("{}", varref.1),
|
format!("{}", varref.1),
|
||||||
Instr::Load(
|
Instr::Load(
|
||||||
v.0.instr(),
|
v.0.instr(),
|
||||||
@ -647,7 +647,7 @@ impl mir::Expression {
|
|||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
};
|
};
|
||||||
Some(StackValue(
|
Some(StackValue(
|
||||||
StackValueKind::Immutable(scope.block.build(instr).unwrap()),
|
StackValueKind::Immutable(scope.block.build_anon(instr).unwrap()),
|
||||||
TypeKind::U32,
|
TypeKind::U32,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@ -671,7 +671,7 @@ impl mir::Expression {
|
|||||||
|
|
||||||
let val = scope
|
let val = scope
|
||||||
.block
|
.block
|
||||||
.build_named(
|
.build(
|
||||||
call.name.clone(),
|
call.name.clone(),
|
||||||
Instr::FunctionCall(callee.ir.value(), params),
|
Instr::FunctionCall(callee.ir.value(), params),
|
||||||
)
|
)
|
||||||
@ -686,11 +686,11 @@ impl mir::Expression {
|
|||||||
let ptr = if ret_type_kind != TypeKind::Void {
|
let ptr = if ret_type_kind != TypeKind::Void {
|
||||||
let ptr = scope
|
let ptr = scope
|
||||||
.block
|
.block
|
||||||
.build_named(&call.name, Instr::Alloca(ret_type.clone()))
|
.build(&call.name, Instr::Alloca(ret_type.clone()))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
scope
|
scope
|
||||||
.block
|
.block
|
||||||
.build_named(format!("{}.store", call.name), Instr::Store(ptr, val))
|
.build(format!("{}.store", call.name), Instr::Store(ptr, val))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
Some(ptr)
|
Some(ptr)
|
||||||
@ -704,7 +704,7 @@ impl mir::Expression {
|
|||||||
StackValueKind::Immutable(
|
StackValueKind::Immutable(
|
||||||
scope
|
scope
|
||||||
.block
|
.block
|
||||||
.build_named(call.name.clone(), Instr::Load(ptr, ret_type))
|
.build(call.name.clone(), Instr::Load(ptr, ret_type))
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
),
|
),
|
||||||
ret_type_kind,
|
ret_type_kind,
|
||||||
@ -743,7 +743,7 @@ impl mir::Expression {
|
|||||||
|
|
||||||
let first = scope
|
let first = scope
|
||||||
.block
|
.block
|
||||||
.build_named("array.zero", Instr::Constant(ConstValue::U32(0)))
|
.build("array.zero", Instr::Constant(ConstValue::U32(0)))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let TypeKind::CodegenPtr(inner) = ty else {
|
let TypeKind::CodegenPtr(inner) = ty else {
|
||||||
@ -754,7 +754,7 @@ impl mir::Expression {
|
|||||||
dbg!(&further_inner, &val_t);
|
dbg!(&further_inner, &val_t);
|
||||||
let loaded = scope
|
let loaded = scope
|
||||||
.block
|
.block
|
||||||
.build_named(
|
.build(
|
||||||
"array.load",
|
"array.load",
|
||||||
Instr::Load(
|
Instr::Load(
|
||||||
kind.instr(),
|
kind.instr(),
|
||||||
@ -765,7 +765,7 @@ impl mir::Expression {
|
|||||||
(
|
(
|
||||||
scope
|
scope
|
||||||
.block
|
.block
|
||||||
.build_named(format!("array.gep"), Instr::GetElemPtr(loaded, vec![idx]))
|
.build(format!("array.gep"), Instr::GetElemPtr(loaded, vec![idx]))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.maybe_location(&mut scope.block, location),
|
.maybe_location(&mut scope.block, location),
|
||||||
*further_inner,
|
*further_inner,
|
||||||
@ -777,7 +777,7 @@ impl mir::Expression {
|
|||||||
(
|
(
|
||||||
scope
|
scope
|
||||||
.block
|
.block
|
||||||
.build_named(
|
.build(
|
||||||
format!("array.gep"),
|
format!("array.gep"),
|
||||||
Instr::GetElemPtr(kind.instr(), vec![first, idx]),
|
Instr::GetElemPtr(kind.instr(), vec![first, idx]),
|
||||||
)
|
)
|
||||||
@ -793,7 +793,7 @@ impl mir::Expression {
|
|||||||
kind.derive(
|
kind.derive(
|
||||||
scope
|
scope
|
||||||
.block
|
.block
|
||||||
.build_named(
|
.build(
|
||||||
"array.load",
|
"array.load",
|
||||||
Instr::Load(
|
Instr::Load(
|
||||||
ptr,
|
ptr,
|
||||||
@ -837,7 +837,7 @@ impl mir::Expression {
|
|||||||
|
|
||||||
let array = scope
|
let array = scope
|
||||||
.block
|
.block
|
||||||
.build_named(&array_name, Instr::Alloca(array_ty.clone()))
|
.build(&array_name, Instr::Alloca(array_ty.clone()))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.maybe_location(&mut scope.block, location);
|
.maybe_location(&mut scope.block, location);
|
||||||
|
|
||||||
@ -847,30 +847,30 @@ impl mir::Expression {
|
|||||||
|
|
||||||
let index_expr = scope
|
let index_expr = scope
|
||||||
.block
|
.block
|
||||||
.build_named(
|
.build(
|
||||||
index.to_string(),
|
index.to_string(),
|
||||||
Instr::Constant(ConstValue::U32(index as u32)),
|
Instr::Constant(ConstValue::U32(index as u32)),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let first = scope
|
let first = scope
|
||||||
.block
|
.block
|
||||||
.build_named("zero", Instr::Constant(ConstValue::U32(0)))
|
.build("zero", Instr::Constant(ConstValue::U32(0)))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let ptr = scope
|
let ptr = scope
|
||||||
.block
|
.block
|
||||||
.build_named(gep_n, Instr::GetElemPtr(array, vec![first, index_expr]))
|
.build(gep_n, Instr::GetElemPtr(array, vec![first, index_expr]))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.maybe_location(&mut scope.block, location);
|
.maybe_location(&mut scope.block, location);
|
||||||
scope
|
scope
|
||||||
.block
|
.block
|
||||||
.build_named(store_n, Instr::Store(ptr, *instr))
|
.build(store_n, Instr::Store(ptr, *instr))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.maybe_location(&mut scope.block, location);
|
.maybe_location(&mut scope.block, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
let array_val = scope
|
let array_val = scope
|
||||||
.block
|
.block
|
||||||
.build_named(load_n, Instr::Load(array, array_ty))
|
.build(load_n, Instr::Load(array, array_ty))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.maybe_location(&mut scope.block, location);
|
.maybe_location(&mut scope.block, location);
|
||||||
|
|
||||||
@ -897,7 +897,7 @@ impl mir::Expression {
|
|||||||
|
|
||||||
let value = scope
|
let value = scope
|
||||||
.block
|
.block
|
||||||
.build_named(
|
.build(
|
||||||
gep_n,
|
gep_n,
|
||||||
Instr::GetStructElemPtr(struct_val.instr(), idx as u32),
|
Instr::GetStructElemPtr(struct_val.instr(), idx as u32),
|
||||||
)
|
)
|
||||||
@ -910,7 +910,7 @@ impl mir::Expression {
|
|||||||
struct_val.0.derive(
|
struct_val.0.derive(
|
||||||
scope
|
scope
|
||||||
.block
|
.block
|
||||||
.build_named(
|
.build(
|
||||||
load_n,
|
load_n,
|
||||||
Instr::Load(
|
Instr::Load(
|
||||||
value,
|
value,
|
||||||
@ -937,7 +937,7 @@ impl mir::Expression {
|
|||||||
|
|
||||||
let struct_ptr = scope
|
let struct_ptr = scope
|
||||||
.block
|
.block
|
||||||
.build_named(name, Instr::Alloca(struct_ty.clone()))
|
.build(name, Instr::Alloca(struct_ty.clone()))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.maybe_location(&mut scope.block, location);
|
.maybe_location(&mut scope.block, location);
|
||||||
|
|
||||||
@ -947,13 +947,13 @@ impl mir::Expression {
|
|||||||
|
|
||||||
let elem_ptr = scope
|
let elem_ptr = scope
|
||||||
.block
|
.block
|
||||||
.build_named(gep_n, Instr::GetStructElemPtr(struct_ptr, i as u32))
|
.build(gep_n, Instr::GetStructElemPtr(struct_ptr, i as u32))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.maybe_location(&mut scope.block, location);
|
.maybe_location(&mut scope.block, location);
|
||||||
if let Some(val) = exp.codegen(scope, state) {
|
if let Some(val) = exp.codegen(scope, state) {
|
||||||
scope
|
scope
|
||||||
.block
|
.block
|
||||||
.build_named(store_n, Instr::Store(elem_ptr, val.instr()))
|
.build(store_n, Instr::Store(elem_ptr, val.instr()))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.maybe_location(&mut scope.block, location);
|
.maybe_location(&mut scope.block, location);
|
||||||
}
|
}
|
||||||
@ -961,7 +961,7 @@ impl mir::Expression {
|
|||||||
|
|
||||||
let struct_val = scope
|
let struct_val = scope
|
||||||
.block
|
.block
|
||||||
.build_named(load_n, Instr::Load(struct_ptr, struct_ty))
|
.build(load_n, Instr::Load(struct_ptr, struct_ty))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
Some(StackValue(
|
Some(StackValue(
|
||||||
@ -993,7 +993,7 @@ impl mir::Expression {
|
|||||||
|
|
||||||
let var_ptr_instr = scope
|
let var_ptr_instr = scope
|
||||||
.block
|
.block
|
||||||
.build_named(
|
.build(
|
||||||
format!("{}.deref", varref.1),
|
format!("{}.deref", varref.1),
|
||||||
Instr::Load(
|
Instr::Load(
|
||||||
v.0.instr(),
|
v.0.instr(),
|
||||||
@ -1009,7 +1009,7 @@ impl mir::Expression {
|
|||||||
v.0.derive(
|
v.0.derive(
|
||||||
scope
|
scope
|
||||||
.block
|
.block
|
||||||
.build_named(
|
.build(
|
||||||
format!("{}.deref.inner", varref.1),
|
format!("{}.deref.inner", varref.1),
|
||||||
Instr::Load(
|
Instr::Load(
|
||||||
var_ptr_instr,
|
var_ptr_instr,
|
||||||
@ -1028,21 +1028,6 @@ impl mir::Expression {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
mir::ExprKind::CastTo(expression, type_kind) => {
|
|
||||||
let val = expression.codegen(scope, state)?;
|
|
||||||
let cast_instr = val
|
|
||||||
.1
|
|
||||||
.get_type(scope.type_values, scope.types)
|
|
||||||
.cast_instruction(
|
|
||||||
val.instr(),
|
|
||||||
&type_kind.get_type(scope.type_values, scope.types),
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
Some(StackValue(
|
|
||||||
val.0.derive(scope.block.build(cast_instr).unwrap()),
|
|
||||||
type_kind.clone(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
if let Some(value) = &value {
|
if let Some(value) = &value {
|
||||||
value.instr().maybe_location(&mut scope.block, location);
|
value.instr().maybe_location(&mut scope.block, location);
|
||||||
@ -1123,7 +1108,7 @@ impl mir::IfExpression {
|
|||||||
incoming.extend(else_res.clone());
|
incoming.extend(else_res.clone());
|
||||||
let instr = scope
|
let instr = scope
|
||||||
.block
|
.block
|
||||||
.build_named(
|
.build(
|
||||||
"phi",
|
"phi",
|
||||||
Instr::Phi(incoming.iter().map(|i| i.instr()).collect()),
|
Instr::Phi(incoming.iter().map(|i| i.instr()).collect()),
|
||||||
)
|
)
|
||||||
@ -1165,7 +1150,7 @@ impl mir::CmpOperator {
|
|||||||
impl mir::Literal {
|
impl mir::Literal {
|
||||||
fn as_const(&self, block: &mut Block) -> InstructionValue {
|
fn as_const(&self, block: &mut Block) -> InstructionValue {
|
||||||
block
|
block
|
||||||
.build_named(format!("{}", self), self.as_const_kind())
|
.build(format!("{}", self), self.as_const_kind())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -211,7 +211,6 @@ impl Display for ExprKind {
|
|||||||
ExprKind::Borrow(var_ref, false) => write!(f, "&{}", var_ref),
|
ExprKind::Borrow(var_ref, false) => write!(f, "&{}", var_ref),
|
||||||
ExprKind::Borrow(var_ref, true) => write!(f, "&mut {}", var_ref),
|
ExprKind::Borrow(var_ref, true) => write!(f, "&mut {}", var_ref),
|
||||||
ExprKind::Deref(var_ref) => write!(f, "*{}", var_ref),
|
ExprKind::Deref(var_ref) => write!(f, "*{}", var_ref),
|
||||||
ExprKind::CastTo(expression, type_kind) => write!(f, "{} as {}", expression, type_kind),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,82 +14,6 @@ pub enum ReturnTypeOther {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TypeKind {
|
impl TypeKind {
|
||||||
pub fn collapse_into(&self, other: &TypeKind) -> Result<TypeKind, ErrorKind> {
|
|
||||||
if self == other {
|
|
||||||
return Ok(self.clone());
|
|
||||||
}
|
|
||||||
|
|
||||||
match (self, other) {
|
|
||||||
(TypeKind::Vague(Vague::Integer), other) | (other, TypeKind::Vague(Vague::Integer)) => {
|
|
||||||
match other {
|
|
||||||
TypeKind::Vague(Vague::Unknown) => Ok(TypeKind::Vague(Vague::Integer)),
|
|
||||||
TypeKind::Vague(Vague::Integer) => Ok(TypeKind::Vague(Vague::Integer)),
|
|
||||||
TypeKind::I8
|
|
||||||
| TypeKind::I16
|
|
||||||
| TypeKind::I32
|
|
||||||
| TypeKind::I64
|
|
||||||
| TypeKind::I128
|
|
||||||
| TypeKind::U8
|
|
||||||
| TypeKind::U16
|
|
||||||
| TypeKind::U32
|
|
||||||
| TypeKind::U64
|
|
||||||
| TypeKind::U128 => Ok(other.clone()),
|
|
||||||
_ => Err(ErrorKind::TypesIncompatible(self.clone(), other.clone())),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(TypeKind::Vague(Vague::Decimal), other) | (other, TypeKind::Vague(Vague::Decimal)) => {
|
|
||||||
match other {
|
|
||||||
TypeKind::Vague(Vague::Unknown) => Ok(TypeKind::Vague(Vague::Decimal)),
|
|
||||||
TypeKind::Vague(Vague::Decimal) => Ok(TypeKind::Vague(Vague::Decimal)),
|
|
||||||
TypeKind::F16
|
|
||||||
| TypeKind::F32B
|
|
||||||
| TypeKind::F32
|
|
||||||
| TypeKind::F64
|
|
||||||
| TypeKind::F80
|
|
||||||
| TypeKind::F128
|
|
||||||
| TypeKind::F128PPC => Ok(other.clone()),
|
|
||||||
_ => Err(ErrorKind::TypesIncompatible(self.clone(), other.clone())),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(TypeKind::Vague(Vague::Unknown), other) | (other, TypeKind::Vague(Vague::Unknown)) => {
|
|
||||||
Ok(other.clone())
|
|
||||||
}
|
|
||||||
(TypeKind::Borrow(val1, mut1), TypeKind::Borrow(val2, mut2)) => {
|
|
||||||
// Extracted to give priority for other collapse-error
|
|
||||||
let collapsed = val1.collapse_into(val2)?;
|
|
||||||
if mut1 == mut2 {
|
|
||||||
Ok(TypeKind::Borrow(Box::new(collapsed), *mut1 && *mut2))
|
|
||||||
} else {
|
|
||||||
Err(ErrorKind::TypesDifferMutability(
|
|
||||||
self.clone(),
|
|
||||||
other.clone(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(TypeKind::UserPtr(val1), TypeKind::UserPtr(val2)) => {
|
|
||||||
Ok(TypeKind::UserPtr(Box::new(val1.collapse_into(val2)?)))
|
|
||||||
}
|
|
||||||
_ => Err(ErrorKind::TypesIncompatible(self.clone(), other.clone())),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn cast_into(&self, other: &TypeKind) -> Result<TypeKind, ErrorKind> {
|
|
||||||
if let Ok(collapsed) = self.collapse_into(other) {
|
|
||||||
Ok(collapsed)
|
|
||||||
} else {
|
|
||||||
let self_cat = self.category();
|
|
||||||
let other_cat = other.category();
|
|
||||||
match (self, other) {
|
|
||||||
(TypeKind::UserPtr(_), TypeKind::UserPtr(_)) => Ok(other.clone()),
|
|
||||||
_ => match (&self_cat, &other_cat) {
|
|
||||||
(TypeCategory::Integer, TypeCategory::Integer) => Ok(other.clone()),
|
|
||||||
(TypeCategory::Real, TypeCategory::Real) => Ok(other.clone()),
|
|
||||||
_ => Err(ErrorKind::NotCastableTo(self.clone(), other.clone())),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the type that is the result of a binary operator between two
|
/// Return the type that is the result of a binary operator between two
|
||||||
/// values of this type
|
/// values of this type
|
||||||
pub fn binop_type(&self, op: &BinaryOperator) -> TypeKind {
|
pub fn binop_type(&self, op: &BinaryOperator) -> TypeKind {
|
||||||
@ -235,49 +159,6 @@ impl TypeKind {
|
|||||||
_ => true,
|
_ => true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn category(&self) -> TypeCategory {
|
|
||||||
match self {
|
|
||||||
TypeKind::I8
|
|
||||||
| TypeKind::I16
|
|
||||||
| TypeKind::I32
|
|
||||||
| TypeKind::I64
|
|
||||||
| TypeKind::I128
|
|
||||||
| TypeKind::U8
|
|
||||||
| TypeKind::U16
|
|
||||||
| TypeKind::U32
|
|
||||||
| TypeKind::U64
|
|
||||||
| TypeKind::U128
|
|
||||||
| TypeKind::Str => TypeCategory::Integer,
|
|
||||||
TypeKind::F16
|
|
||||||
| TypeKind::F32B
|
|
||||||
| TypeKind::F32
|
|
||||||
| TypeKind::F64
|
|
||||||
| TypeKind::F128
|
|
||||||
| TypeKind::F80
|
|
||||||
| TypeKind::F128PPC => TypeCategory::Real,
|
|
||||||
TypeKind::Void => TypeCategory::Other,
|
|
||||||
TypeKind::Bool => TypeCategory::Other,
|
|
||||||
TypeKind::Array(_, _) => TypeCategory::Other,
|
|
||||||
TypeKind::CustomType(_) => TypeCategory::Other,
|
|
||||||
TypeKind::Borrow(_, _) => TypeCategory::Other,
|
|
||||||
TypeKind::UserPtr(_) => TypeCategory::Other,
|
|
||||||
TypeKind::CodegenPtr(_) => TypeCategory::Other,
|
|
||||||
TypeKind::Vague(vague_type) => match vague_type {
|
|
||||||
VagueType::Unknown => TypeCategory::Other,
|
|
||||||
VagueType::Integer => TypeCategory::Integer,
|
|
||||||
VagueType::Decimal => TypeCategory::Real,
|
|
||||||
VagueType::TypeRef(_) => TypeCategory::TypeRef,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum TypeCategory {
|
|
||||||
Integer,
|
|
||||||
Real,
|
|
||||||
Other,
|
|
||||||
TypeRef,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl StructType {
|
impl StructType {
|
||||||
@ -438,13 +319,6 @@ impl Expression {
|
|||||||
_ => Err(ReturnTypeOther::DerefNonBorrow(var.2)),
|
_ => Err(ReturnTypeOther::DerefNonBorrow(var.2)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CastTo(expr, type_kind) => match expr.return_type(refs) {
|
|
||||||
Ok(ret_type) => match ret_type {
|
|
||||||
(ReturnKind::Hard, ty) => Ok((ReturnKind::Hard, ty)),
|
|
||||||
_ => Ok((ReturnKind::Soft, type_kind.clone())),
|
|
||||||
},
|
|
||||||
Err(_) => Ok((ReturnKind::Soft, type_kind.clone())),
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -462,7 +336,6 @@ impl Expression {
|
|||||||
ExprKind::BinOp(_, _, _) => None,
|
ExprKind::BinOp(_, _, _) => None,
|
||||||
ExprKind::FunctionCall(_) => None,
|
ExprKind::FunctionCall(_) => None,
|
||||||
ExprKind::If(_) => None,
|
ExprKind::If(_) => None,
|
||||||
ExprKind::CastTo(expression, _) => expression.backing_var(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -490,7 +363,6 @@ impl Expression {
|
|||||||
ExprKind::Block(_) => None,
|
ExprKind::Block(_) => None,
|
||||||
ExprKind::Borrow(_, _) => None,
|
ExprKind::Borrow(_, _) => None,
|
||||||
ExprKind::Deref(_) => None,
|
ExprKind::Deref(_) => None,
|
||||||
ExprKind::CastTo(expression, _) => expression.num_value(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -586,6 +458,73 @@ impl TypeKind {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait Collapsable: Sized + Clone {
|
||||||
|
/// Try to narrow two types into one singular type. E.g. Vague(Number) and
|
||||||
|
/// I32 could be narrowed to just I32.
|
||||||
|
fn collapse_into(&self, other: &Self) -> Result<Self, ErrorKind>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Collapsable for TypeKind {
|
||||||
|
fn collapse_into(&self, other: &TypeKind) -> Result<TypeKind, ErrorKind> {
|
||||||
|
if self == other {
|
||||||
|
return Ok(self.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
match (self, other) {
|
||||||
|
(TypeKind::Vague(Vague::Integer), other) | (other, TypeKind::Vague(Vague::Integer)) => {
|
||||||
|
match other {
|
||||||
|
TypeKind::Vague(Vague::Unknown) => Ok(TypeKind::Vague(Vague::Integer)),
|
||||||
|
TypeKind::Vague(Vague::Integer) => Ok(TypeKind::Vague(Vague::Integer)),
|
||||||
|
TypeKind::I8
|
||||||
|
| TypeKind::I16
|
||||||
|
| TypeKind::I32
|
||||||
|
| TypeKind::I64
|
||||||
|
| TypeKind::I128
|
||||||
|
| TypeKind::U8
|
||||||
|
| TypeKind::U16
|
||||||
|
| TypeKind::U32
|
||||||
|
| TypeKind::U64
|
||||||
|
| TypeKind::U128 => Ok(other.clone()),
|
||||||
|
_ => Err(ErrorKind::TypesIncompatible(self.clone(), other.clone())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(TypeKind::Vague(Vague::Decimal), other) | (other, TypeKind::Vague(Vague::Decimal)) => {
|
||||||
|
match other {
|
||||||
|
TypeKind::Vague(Vague::Unknown) => Ok(TypeKind::Vague(Vague::Decimal)),
|
||||||
|
TypeKind::Vague(Vague::Decimal) => Ok(TypeKind::Vague(Vague::Decimal)),
|
||||||
|
TypeKind::F16
|
||||||
|
| TypeKind::F32B
|
||||||
|
| TypeKind::F32
|
||||||
|
| TypeKind::F64
|
||||||
|
| TypeKind::F80
|
||||||
|
| TypeKind::F128
|
||||||
|
| TypeKind::F128PPC => Ok(other.clone()),
|
||||||
|
_ => Err(ErrorKind::TypesIncompatible(self.clone(), other.clone())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(TypeKind::Vague(Vague::Unknown), other) | (other, TypeKind::Vague(Vague::Unknown)) => {
|
||||||
|
Ok(other.clone())
|
||||||
|
}
|
||||||
|
(TypeKind::Borrow(val1, mut1), TypeKind::Borrow(val2, mut2)) => {
|
||||||
|
// Extracted to give priority for other collapse-error
|
||||||
|
let collapsed = val1.collapse_into(val2)?;
|
||||||
|
if mut1 == mut2 {
|
||||||
|
Ok(TypeKind::Borrow(Box::new(collapsed), *mut1 && *mut2))
|
||||||
|
} else {
|
||||||
|
Err(ErrorKind::TypesDifferMutability(
|
||||||
|
self.clone(),
|
||||||
|
other.clone(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(TypeKind::UserPtr(val1), TypeKind::UserPtr(val2)) => {
|
||||||
|
Ok(TypeKind::UserPtr(Box::new(val1.collapse_into(val2)?)))
|
||||||
|
}
|
||||||
|
_ => Err(ErrorKind::TypesIncompatible(self.clone(), other.clone())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Literal {
|
impl Literal {
|
||||||
pub fn num_value(&self) -> Option<i128> {
|
pub fn num_value(&self) -> Option<i128> {
|
||||||
match self {
|
match self {
|
||||||
@ -614,6 +553,22 @@ impl Literal {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Collapsable for ScopeFunction {
|
||||||
|
fn collapse_into(&self, other: &ScopeFunction) -> Result<ScopeFunction, ErrorKind> {
|
||||||
|
Ok(ScopeFunction {
|
||||||
|
ret: self.ret.collapse_into(&other.ret)?,
|
||||||
|
params: try_all(
|
||||||
|
self.params
|
||||||
|
.iter()
|
||||||
|
.zip(&other.params)
|
||||||
|
.map(|(p1, p2)| p1.collapse_into(&p2))
|
||||||
|
.collect(),
|
||||||
|
)
|
||||||
|
.map_err(|e| e.first().unwrap().clone())?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, thiserror::Error, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Debug, Clone, thiserror::Error, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
pub enum EqualsIssue {
|
pub enum EqualsIssue {
|
||||||
#[error("Function is already defined locally at {:?}", (.0).range)]
|
#[error("Function is already defined locally at {:?}", (.0).range)]
|
||||||
|
@ -72,7 +72,7 @@ impl<'map> Pass for LinkerPass<'map> {
|
|||||||
type Data = ();
|
type Data = ();
|
||||||
type TError = ErrorKind;
|
type TError = ErrorKind;
|
||||||
fn context(&mut self, context: &mut Context, mut state: LinkerPassState) -> PassResult {
|
fn context(&mut self, context: &mut Context, mut state: LinkerPassState) -> PassResult {
|
||||||
let mains = context
|
let mut mains = context
|
||||||
.modules
|
.modules
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.filter(|m| m.is_main)
|
.filter(|m| m.is_main)
|
||||||
|
@ -254,7 +254,6 @@ pub enum ExprKind {
|
|||||||
Block(Block),
|
Block(Block),
|
||||||
Borrow(NamedVariableRef, bool),
|
Borrow(NamedVariableRef, bool),
|
||||||
Deref(NamedVariableRef),
|
Deref(NamedVariableRef),
|
||||||
CastTo(Box<Expression>, TypeKind),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -6,6 +6,7 @@ use crate::{mir::*, util::try_all};
|
|||||||
use VagueType as Vague;
|
use VagueType as Vague;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
|
implement::Collapsable,
|
||||||
pass::{Pass, PassResult, PassState, ScopeVariable},
|
pass::{Pass, PassResult, PassState, ScopeVariable},
|
||||||
typerefs::TypeRefs,
|
typerefs::TypeRefs,
|
||||||
};
|
};
|
||||||
@ -66,8 +67,6 @@ pub enum ErrorKind {
|
|||||||
ImpossibleMutLet(String),
|
ImpossibleMutLet(String),
|
||||||
#[error("Cannot produce a negative unsigned value of type {0}!")]
|
#[error("Cannot produce a negative unsigned value of type {0}!")]
|
||||||
NegativeUnsignedValue(TypeKind),
|
NegativeUnsignedValue(TypeKind),
|
||||||
#[error("Cannot cast type {0} into type {1}!")]
|
|
||||||
NotCastableTo(TypeKind, TypeKind),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Struct used to implement a type-checking pass that can be performed on the
|
/// Struct used to implement a type-checking pass that can be performed on the
|
||||||
@ -713,10 +712,6 @@ impl Expression {
|
|||||||
|
|
||||||
Ok(*inner)
|
Ok(*inner)
|
||||||
}
|
}
|
||||||
ExprKind::CastTo(expression, type_kind) => {
|
|
||||||
let expr = expression.typecheck(state, typerefs, None)?;
|
|
||||||
expr.resolve_ref(typerefs).cast_into(type_kind)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -397,10 +397,6 @@ impl Expression {
|
|||||||
_ => Err(ErrorKind::AttemptedDerefNonBorrow(var.1.clone())),
|
_ => Err(ErrorKind::AttemptedDerefNonBorrow(var.1.clone())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExprKind::CastTo(expression, type_kind) => {
|
|
||||||
expression.infer_types(state, type_refs)?;
|
|
||||||
Ok(type_refs.from_type(type_kind).unwrap())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ use std::{
|
|||||||
|
|
||||||
use crate::mir::VagueType;
|
use crate::mir::VagueType;
|
||||||
|
|
||||||
use super::{typecheck::ErrorKind, BinaryOperator, TypeKind};
|
use super::{implement::Collapsable, typecheck::ErrorKind, BinaryOperator, TypeKind};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct TypeRef<'scope>(TypeIdRef, &'scope ScopeTypeRefs<'scope>);
|
pub struct TypeRef<'scope>(TypeIdRef, &'scope ScopeTypeRefs<'scope>);
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
// Arithmetic, function calls and imports!
|
|
||||||
|
|
||||||
fn other() -> i16 {
|
|
||||||
return 6;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() -> u32 {
|
|
||||||
let value = other() as u32;
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user