Compare commits

...

7 Commits

20 changed files with 315 additions and 101 deletions

View File

@ -1,17 +1,6 @@
// Arithmetic, function calls and imports! // Arithmetic, function calls and imports!
import std::print;
import std::from_str;
import std::add_num_to_str;
import std::free_string;
fn main() -> u32 { fn main() -> u32 {
for i in 0 .. 15 {
let mut text = from_str("num: ");
add_num_to_str(&mut text, i);
print(text);
free_string(&text);
}
let mut num = 0; let mut num = 0;
while num < 10 { while num < 10 {

10
examples/or_bitwise.reid Normal file
View File

@ -0,0 +1,10 @@
// Arithmetic, function calls and imports!
fn main() -> bool {
let bwand = (0xff & 0xf0) >> 4;
let bwor = (0x0fu32 | 0x00) << 4;
let bwxor = (0xf0 | 0x0f);
return (bwxor == 255) && ((bwand == 15) || false) && (bwor == 240);
}

7
examples/test.reid Normal file
View File

@ -0,0 +1,7 @@
// Arithmetic, function calls and imports!
fn main() -> bool {
return 5.0 > -1;
}

View File

@ -410,6 +410,8 @@ impl Builder {
} }
} }
Instr::And(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()), Instr::And(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()),
Instr::Or(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()),
Instr::XOr(lhs, rhs) => match_types(&lhs, &rhs, &self).map(|_| ()),
Instr::ICmp(_, lhs, rhs) => { Instr::ICmp(_, lhs, rhs) => {
let t = match_types(&lhs, &rhs, self)?; let t = match_types(&lhs, &rhs, self)?;
if t.category().comparable() || !t.category().integer() { if t.category().comparable() || !t.category().integer() {
@ -528,6 +530,30 @@ impl Builder {
Instr::PtrToInt(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::IntToPtr(instr, ty) => instr.cast_to(self, &ty).map(|_| ()),
Instr::BitCast(..) => Ok(()), Instr::BitCast(..) => Ok(()),
Instr::ShiftRightLogical(_, rhs) => {
let rhs_ty = rhs.get_type(&self)?;
if rhs_ty.category() == TypeCategory::UnsignedInteger {
Ok(())
} else {
Err(ErrorKind::Null)
}
}
Instr::ShiftRightArithmetic(_, rhs) => {
let rhs_ty = rhs.get_type(&self)?;
if rhs_ty.category() == TypeCategory::UnsignedInteger {
Ok(())
} else {
Err(ErrorKind::Null)
}
}
Instr::ShiftLeft(_, rhs) => {
let rhs_ty = rhs.get_type(&self)?;
if rhs_ty.category() == TypeCategory::UnsignedInteger {
Ok(())
} else {
Err(ErrorKind::Null)
}
}
} }
} }
} }
@ -614,6 +640,8 @@ impl InstructionValue {
SRem(lhs, rhs) => match_types(lhs, rhs, &builder), SRem(lhs, rhs) => match_types(lhs, rhs, &builder),
FRem(lhs, rhs) => match_types(lhs, rhs, &builder), FRem(lhs, rhs) => match_types(lhs, rhs, &builder),
And(lhs, rhs) => match_types(lhs, rhs, &builder), And(lhs, rhs) => match_types(lhs, rhs, &builder),
Or(lhs, rhs) => match_types(lhs, rhs, &builder),
XOr(lhs, rhs) => match_types(lhs, rhs, &builder),
ICmp(_, _, _) => Ok(Type::Bool), ICmp(_, _, _) => Ok(Type::Bool),
FCmp(_, _, _) => Ok(Type::Bool), FCmp(_, _, _) => Ok(Type::Bool),
FunctionCall(function_value, _) => Ok(builder.function_data(function_value).ret), FunctionCall(function_value, _) => Ok(builder.function_data(function_value).ret),
@ -674,6 +702,9 @@ impl InstructionValue {
PtrToInt(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()), IntToPtr(instr, ty) => instr.cast_to(builder, ty).map(|_| ty.clone()),
BitCast(_, ty) => Ok(ty.clone()), BitCast(_, ty) => Ok(ty.clone()),
ShiftRightLogical(lhs, _) => lhs.get_type(builder),
ShiftRightArithmetic(lhs, _) => lhs.get_type(builder),
ShiftLeft(lhs, _) => lhs.get_type(builder),
} }
} }
} }

View File

@ -975,6 +975,31 @@ impl InstructionHolder {
ty.as_llvm(module.context_ref, &module.types), ty.as_llvm(module.context_ref, &module.types),
name.as_ptr(), name.as_ptr(),
), ),
Or(lhs, rhs) => {
let lhs_val = module.values.get(&lhs).unwrap().value_ref;
let rhs_val = module.values.get(&rhs).unwrap().value_ref;
LLVMBuildOr(module.builder_ref, lhs_val, rhs_val, name.as_ptr())
}
XOr(lhs, rhs) => {
let lhs_val = module.values.get(&lhs).unwrap().value_ref;
let rhs_val = module.values.get(&rhs).unwrap().value_ref;
LLVMBuildXor(module.builder_ref, lhs_val, rhs_val, name.as_ptr())
}
ShiftRightLogical(lhs, rhs) => {
let lhs_val = module.values.get(&lhs).unwrap().value_ref;
let rhs_val = module.values.get(&rhs).unwrap().value_ref;
LLVMBuildLShr(module.builder_ref, lhs_val, rhs_val, name.as_ptr())
}
ShiftRightArithmetic(lhs, rhs) => {
let lhs_val = module.values.get(&lhs).unwrap().value_ref;
let rhs_val = module.values.get(&rhs).unwrap().value_ref;
LLVMBuildAShr(module.builder_ref, lhs_val, rhs_val, name.as_ptr())
}
ShiftLeft(lhs, rhs) => {
let lhs_val = module.values.get(&lhs).unwrap().value_ref;
let rhs_val = module.values.get(&rhs).unwrap().value_ref;
LLVMBuildShl(module.builder_ref, lhs_val, rhs_val, name.as_ptr())
}
} }
}; };
if let Some(record) = &self.record { if let Some(record) = &self.record {

View File

@ -9,10 +9,10 @@ use crate::{
CmpPredicate, Context, Instr, InstructionData, TerminatorKind, CmpPredicate, Context, Instr, InstructionData, TerminatorKind,
builder::*, builder::*,
debug_information::{ debug_information::{
DebugArrayType, DebugBasicType, DebugFieldType, DebugInformation, DebugLocalVariable, DebugArrayType, DebugBasicType, DebugFieldType, DebugInformation, DebugLocalVariable, DebugLocation,
DebugLocation, DebugLocationValue, DebugMetadata, DebugMetadataValue, DebugParamVariable, DebugLocationValue, DebugMetadata, DebugMetadataValue, DebugParamVariable, DebugPointerType, DebugPosition,
DebugPointerType, DebugPosition, DebugProgramValue, DebugRecordKind, DebugScopeValue, DebugProgramValue, DebugRecordKind, DebugScopeValue, DebugStructType, DebugSubprogramType, DebugTypeData,
DebugStructType, DebugSubprogramType, DebugTypeData, DebugTypeHolder, DebugTypeValue, DebugTypeHolder, DebugTypeValue,
}, },
pad_adapter::PadAdapter, pad_adapter::PadAdapter,
}; };
@ -68,11 +68,7 @@ impl FunctionHolder {
.map(|p| format!("{:?}", p)) .map(|p| format!("{:?}", p))
.collect::<Vec<_>>() .collect::<Vec<_>>()
.join(", "); .join(", ");
write!( write!(f, "fn {}({}) -> {:?} ", self.data.name, params, self.data.ret)?;
f,
"fn {}({}) -> {:?} ",
self.data.name, params, self.data.ret
)?;
writeln!(f, "{{")?; writeln!(f, "{{")?;
let mut state = Default::default(); let mut state = Default::default();
@ -116,11 +112,7 @@ impl BlockHolder {
terminator.builder_fmt(&mut inner, builder, debug)?; terminator.builder_fmt(&mut inner, builder, debug)?;
} }
if let Some(location) = self.data.terminator_location { if let Some(location) = self.data.terminator_location {
writeln!( writeln!(inner, " ^ (At {}) ", debug.as_ref().unwrap().get_location(location))?;
inner,
" ^ (At {}) ",
debug.as_ref().unwrap().get_location(location)
)?;
} }
Ok(()) Ok(())
@ -148,11 +140,7 @@ impl InstructionHolder {
writeln!(f, " (Debug {} {})", record.variable.hr(debug), kind)?; writeln!(f, " (Debug {} {})", record.variable.hr(debug), kind)?;
} }
} }
writeln!( writeln!(f, "{:?} ({}) = {:?} ", self.value, self.name, self.data.kind)?;
f,
"{:?} ({}) = {:?} ",
self.value, self.name, self.data.kind
)?;
if let Some(debug) = debug { if let Some(debug) = debug {
if let Some(location) = self.data.location { if let Some(location) = self.data.location {
writeln!(f, " ^ (At {}) ", debug.get_location(location))?; writeln!(f, " ^ (At {}) ", debug.get_location(location))?;
@ -188,9 +176,9 @@ impl TerminatorKind {
impl DebugMetadataValue { impl DebugMetadataValue {
fn hr(&self, debug: &DebugInformation) -> String { fn hr(&self, debug: &DebugInformation) -> String {
let kind = match debug.get_metadata(*self) { let kind = match debug.get_metadata(*self) {
DebugMetadata::ParamVar(DebugParamVariable { DebugMetadata::ParamVar(DebugParamVariable { name, arg_idx, ty, .. }) => {
name, arg_idx, ty, .. format!("param {} (idx {}) (type {:?}) ", name, arg_idx, ty)
}) => format!("param {} (idx {}) (type {:?}) ", name, arg_idx, ty), }
DebugMetadata::LocalVar(DebugLocalVariable { name, ty, .. }) => { DebugMetadata::LocalVar(DebugLocalVariable { name, ty, .. }) => {
format!("var {} (type {:?}) ", name, ty) format!("var {} (type {:?}) ", name, ty)
} }
@ -253,14 +241,11 @@ impl Debug for FunctionHolder {
impl Debug for BlockHolder { impl Debug for BlockHolder {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let deleted = if self.data.deleted { " (deleted)" } else { "" }; let deleted = if self.data.deleted { " (deleted)" } else { "" };
f.debug_tuple(&format!( f.debug_tuple(&format!("{}[{:?}]{} ", &self.data.name, &self.value, deleted))
"{}[{:?}]{} ", .field(&self.instructions)
&self.data.name, &self.value, deleted .field(&self.data.terminator)
)) .field(&self.data.terminator_location)
.field(&self.instructions) .finish()
.field(&self.data.terminator)
.field(&self.data.terminator_location)
.finish()
} }
} }
@ -303,11 +288,7 @@ impl Debug for BlockValue {
impl Debug for InstructionValue { impl Debug for InstructionValue {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!( write!(f, "%{}.{}.{}.{}", self.0.0.0.0, self.0.0.1, self.0.1, self.1)
f,
"%{}.{}.{}.{}",
self.0.0.0.0, self.0.0.1, self.0.1, self.1
)
} }
} }
@ -369,9 +350,7 @@ impl Debug for Instr {
fmt_index(f, instruction_value, &index.to_string())?; fmt_index(f, instruction_value, &index.to_string())?;
write!(f, ")") write!(f, ")")
} }
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) => { Instr::Trunc(instr_val, ty) => {
write!(f, "{:?} to {:?} ({})", instr_val, ty, self.default_name()) write!(f, "{:?} to {:?} ({})", instr_val, ty, self.default_name())
} }
@ -408,6 +387,11 @@ impl Debug for Instr {
Instr::BitCast(instr_val, ty) => { Instr::BitCast(instr_val, ty) => {
write!(f, "{:?} to {:?} ({})", instr_val, ty, self.default_name()) write!(f, "{:?} to {:?} ({})", instr_val, ty, self.default_name())
} }
Instr::Or(lhs, rhs) => fmt_binop(f, lhs, &"||", rhs),
Instr::XOr(lhs, rhs) => fmt_binop(f, lhs, &"^", rhs),
Instr::ShiftRightLogical(lhs, rhs) => fmt_binop(f, lhs, &">>l", rhs),
Instr::ShiftRightArithmetic(lhs, rhs) => fmt_binop(f, lhs, &">>a", rhs),
Instr::ShiftLeft(lhs, rhs) => fmt_binop(f, lhs, &"<<", rhs),
} }
} }
} }
@ -579,11 +563,7 @@ impl Debug for DebugScopeValue {
write!( write!(
f, f,
"Scope[{}]", "Scope[{}]",
self.0 self.0.iter().map(|v| v.to_string()).collect::<Vec<_>>().join(", ")
.iter()
.map(|v| v.to_string())
.collect::<Vec<_>>()
.join(", ")
) )
} }
} }

View File

@ -251,6 +251,11 @@ impl Instr {
Instr::PtrToInt(_, _) => "ptrtoint", Instr::PtrToInt(_, _) => "ptrtoint",
Instr::IntToPtr(_, _) => "inttoptr", Instr::IntToPtr(_, _) => "inttoptr",
Instr::BitCast(_, _) => "bitcast", Instr::BitCast(_, _) => "bitcast",
Instr::Or(..) => "or",
Instr::XOr(..) => "xor",
Instr::ShiftRightLogical(..) => "lshr",
Instr::ShiftRightArithmetic(..) => "ashr",
Instr::ShiftLeft(..) => "shl",
} }
} }
} }
@ -369,7 +374,14 @@ pub enum Instr {
SRem(InstructionValue, InstructionValue), SRem(InstructionValue, InstructionValue),
/// Get the remainder from two floats /// Get the remainder from two floats
FRem(InstructionValue, InstructionValue), FRem(InstructionValue, InstructionValue),
And(InstructionValue, InstructionValue), And(InstructionValue, InstructionValue),
Or(InstructionValue, InstructionValue),
XOr(InstructionValue, InstructionValue),
ShiftRightLogical(InstructionValue, InstructionValue),
ShiftRightArithmetic(InstructionValue, InstructionValue),
ShiftLeft(InstructionValue, InstructionValue),
Phi(Vec<InstructionValue>), Phi(Vec<InstructionValue>),
Alloca(Type), Alloca(Type),

View File

@ -88,6 +88,10 @@ pub enum Token {
LessThan, LessThan,
/// `&` /// `&`
Et, Et,
/// `|`
Pipe,
/// `^`
Hat,
/// `!` /// `!`
Exclamation, Exclamation,
@ -174,6 +178,8 @@ impl ToString for Token {
Token::GreaterThan => String::from('>'), Token::GreaterThan => String::from('>'),
Token::LessThan => String::from('<'), Token::LessThan => String::from('<'),
Token::Et => String::from('&'), Token::Et => String::from('&'),
Token::Pipe => String::from('|'),
Token::Hat => String::from('^'),
Token::Exclamation => String::from('!'), Token::Exclamation => String::from('!'),
Token::ParenOpen => String::from('('), Token::ParenOpen => String::from('('),
Token::ParenClose => String::from(')'), Token::ParenClose => String::from(')'),
@ -411,6 +417,8 @@ pub fn tokenize<T: Into<String>>(to_tokenize: T) -> Result<Vec<FullToken>, Error
'>' => Token::GreaterThan, '>' => Token::GreaterThan,
'<' => Token::LessThan, '<' => Token::LessThan,
'&' => Token::Et, '&' => Token::Et,
'|' => Token::Pipe,
'^' => Token::Hat,
'!' => Token::Exclamation, '!' => Token::Exclamation,
'(' => Token::ParenOpen, '(' => Token::ParenOpen,
')' => Token::ParenClose, ')' => Token::ParenClose,

View File

@ -116,7 +116,14 @@ pub enum BinaryOperator {
Div, Div,
Mod, Mod,
BitshiftRight,
BitshiftLeft,
And, And,
Or,
Xor,
BWAnd,
BWOr,
LT, LT,
LE, LE,
GT, GT,
@ -126,7 +133,7 @@ pub enum BinaryOperator {
} }
impl BinaryOperator { impl BinaryOperator {
pub fn get_precedence(&self) -> i8 { pub fn get_precedence(&self) -> u8 {
use BinaryOperator::*; use BinaryOperator::*;
match &self { match &self {
Minus => 5, Minus => 5,
@ -134,13 +141,20 @@ impl BinaryOperator {
Mult => 15, Mult => 15,
Div => 20, Div => 20,
Mod => 20, Mod => 20,
And => 100, BWAnd => 90,
LT => 100, BWOr => 90,
LE => 100, BWXor => 90,
GT => 100, BitshiftLeft => 100,
GE => 100, BitshiftRight => 100,
EQ => 100, And => 150,
NE => 100, Or => 150,
Xor => 150,
LT => 150,
LE => 150,
GT => 150,
GE => 150,
EQ => 150,
NE => 150,
} }
} }
} }

View File

@ -488,6 +488,10 @@ impl Parse for BinaryOperator {
stream.next(); stream.next();
BinaryOperator::And BinaryOperator::And
} }
(Some(Token::Pipe), Some(Token::Pipe)) => {
stream.next();
BinaryOperator::Or
}
(Some(Token::LessThan), Some(Token::Equals)) => { (Some(Token::LessThan), Some(Token::Equals)) => {
stream.next(); stream.next();
BinaryOperator::LE BinaryOperator::LE
@ -504,6 +508,18 @@ impl Parse for BinaryOperator {
stream.next(); stream.next();
BinaryOperator::NE BinaryOperator::NE
} }
(Some(Token::GreaterThan), Some(Token::GreaterThan)) => {
stream.next();
BinaryOperator::BitshiftRight
}
(Some(Token::LessThan), Some(Token::LessThan)) => {
stream.next();
BinaryOperator::BitshiftLeft
}
(Some(Token::Hat), _) => BinaryOperator::Xor,
(Some(Token::Et), _) => BinaryOperator::BWAnd,
(Some(Token::Pipe), _) => BinaryOperator::BWOr,
(Some(Token::LessThan), _) => BinaryOperator::LT, (Some(Token::LessThan), _) => BinaryOperator::LT,
(Some(Token::GreaterThan), _) => BinaryOperator::GT, (Some(Token::GreaterThan), _) => BinaryOperator::GT,

View File

@ -446,15 +446,21 @@ impl ast::BinaryOperator {
ast::BinaryOperator::Add => mir::BinaryOperator::Add, ast::BinaryOperator::Add => mir::BinaryOperator::Add,
ast::BinaryOperator::Minus => mir::BinaryOperator::Minus, ast::BinaryOperator::Minus => mir::BinaryOperator::Minus,
ast::BinaryOperator::Mult => mir::BinaryOperator::Mult, ast::BinaryOperator::Mult => mir::BinaryOperator::Mult,
ast::BinaryOperator::And => mir::BinaryOperator::And,
ast::BinaryOperator::Div => mir::BinaryOperator::Div, ast::BinaryOperator::Div => mir::BinaryOperator::Div,
ast::BinaryOperator::Mod => mir::BinaryOperator::Mod, ast::BinaryOperator::Mod => mir::BinaryOperator::Mod,
ast::BinaryOperator::And => mir::BinaryOperator::And,
ast::BinaryOperator::Or => mir::BinaryOperator::Or,
ast::BinaryOperator::LT => mir::BinaryOperator::Cmp(mir::CmpOperator::LT), ast::BinaryOperator::LT => mir::BinaryOperator::Cmp(mir::CmpOperator::LT),
ast::BinaryOperator::LE => mir::BinaryOperator::Cmp(mir::CmpOperator::LE), ast::BinaryOperator::LE => mir::BinaryOperator::Cmp(mir::CmpOperator::LE),
ast::BinaryOperator::GT => mir::BinaryOperator::Cmp(mir::CmpOperator::GT), ast::BinaryOperator::GT => mir::BinaryOperator::Cmp(mir::CmpOperator::GT),
ast::BinaryOperator::GE => mir::BinaryOperator::Cmp(mir::CmpOperator::GE), ast::BinaryOperator::GE => mir::BinaryOperator::Cmp(mir::CmpOperator::GE),
ast::BinaryOperator::EQ => mir::BinaryOperator::Cmp(mir::CmpOperator::EQ), ast::BinaryOperator::EQ => mir::BinaryOperator::Cmp(mir::CmpOperator::EQ),
ast::BinaryOperator::NE => mir::BinaryOperator::Cmp(mir::CmpOperator::NE), ast::BinaryOperator::NE => mir::BinaryOperator::Cmp(mir::CmpOperator::NE),
ast::BinaryOperator::BitshiftRight => mir::BinaryOperator::BitshiftRight,
ast::BinaryOperator::BitshiftLeft => mir::BinaryOperator::BitshiftLeft,
ast::BinaryOperator::Xor => mir::BinaryOperator::Xor,
ast::BinaryOperator::BWAnd => mir::BinaryOperator::BitAnd,
ast::BinaryOperator::BWOr => mir::BinaryOperator::BitOr,
} }
} }
} }

View File

@ -1,3 +1,5 @@
use std::ops::BitAnd;
use reid_lib::{builder::InstructionValue, CmpPredicate, ConstValue, Instr, Type}; use reid_lib::{builder::InstructionValue, CmpPredicate, ConstValue, Instr, Type};
use crate::{ use crate::{
@ -84,6 +86,21 @@ where
} }
} }
fn complex_binop_def<T: Clone + 'static>(op: BinaryOperator, lhs: &TypeKind, rhs: &TypeKind, fun: T) -> BinopDefinition
where
T: FnOnce(&mut Scope, InstructionValue, InstructionValue) -> InstructionValue,
{
BinopDefinition {
lhs: ("lhs".to_owned(), lhs.clone()),
op,
rhs: ("rhs".to_owned(), rhs.clone()),
return_type: lhs.clone(),
fn_kind: FunctionDefinitionKind::Intrinsic(Box::new(IntrinsicSimpleInstr(fun))),
meta: Default::default(),
exported: false,
}
}
fn boolean_binop_def<T: Clone + 'static>(op: BinaryOperator, ty: &TypeKind, fun: T) -> BinopDefinition fn boolean_binop_def<T: Clone + 'static>(op: BinaryOperator, ty: &TypeKind, fun: T) -> BinopDefinition
where where
T: FnOnce(&mut Scope, InstructionValue, InstructionValue) -> InstructionValue, T: FnOnce(&mut Scope, InstructionValue, InstructionValue) -> InstructionValue,
@ -145,6 +162,39 @@ pub fn form_intrinsic_binops() -> Vec<BinopDefinition> {
intrinsics.push(boolean_binop_def(Cmp(CmpOperator::LE), &ty, |scope, lhs, rhs| { intrinsics.push(boolean_binop_def(Cmp(CmpOperator::LE), &ty, |scope, lhs, rhs| {
scope.block.build(Instr::ICmp(CmpPredicate::LE, lhs, rhs)).unwrap() scope.block.build(Instr::ICmp(CmpPredicate::LE, lhs, rhs)).unwrap()
})); }));
// Bitwise operations
intrinsics.push(simple_binop_def(BitOr, &ty, |scope, lhs, rhs| {
scope.block.build(Instr::Or(lhs, rhs)).unwrap()
}));
intrinsics.push(simple_binop_def(BitAnd, &ty, |scope, lhs, rhs| {
scope.block.build(Instr::And(lhs, rhs)).unwrap()
}));
intrinsics.push(complex_binop_def(Xor, &ty, &TypeKind::U64, |scope, lhs, rhs| {
scope.block.build(Instr::XOr(lhs, rhs)).unwrap()
}));
if ty.signed() {
intrinsics.push(complex_binop_def(
BitshiftRight,
&ty,
&TypeKind::U64,
|scope, lhs, rhs| scope.block.build(Instr::ShiftRightArithmetic(lhs, rhs)).unwrap(),
));
} else {
intrinsics.push(complex_binop_def(
BitshiftRight,
&ty,
&TypeKind::U64,
|scope, lhs, rhs| scope.block.build(Instr::ShiftRightLogical(lhs, rhs)).unwrap(),
));
}
intrinsics.push(complex_binop_def(
BitshiftLeft,
&ty,
&TypeKind::U64,
|scope, lhs, rhs| scope.block.build(Instr::ShiftLeft(lhs, rhs)).unwrap(),
));
} }
for ty in INTEGERS.iter().chain(&[TypeKind::Bool, TypeKind::Char]) { for ty in INTEGERS.iter().chain(&[TypeKind::Bool, TypeKind::Char]) {
intrinsics.push(boolean_binop_def(Cmp(CmpOperator::EQ), &ty, |scope, lhs, rhs| { intrinsics.push(boolean_binop_def(Cmp(CmpOperator::EQ), &ty, |scope, lhs, rhs| {
@ -195,6 +245,12 @@ pub fn form_intrinsic_binops() -> Vec<BinopDefinition> {
intrinsics.push(boolean_binop_def(And, &TypeKind::Bool, |scope, lhs, rhs| { intrinsics.push(boolean_binop_def(And, &TypeKind::Bool, |scope, lhs, rhs| {
scope.block.build(Instr::And(lhs, rhs)).unwrap() scope.block.build(Instr::And(lhs, rhs)).unwrap()
})); }));
intrinsics.push(boolean_binop_def(Or, &TypeKind::Bool, |scope, lhs, rhs| {
scope.block.build(Instr::Or(lhs, rhs)).unwrap()
}));
intrinsics.push(boolean_binop_def(Xor, &TypeKind::Bool, |scope, lhs, rhs| {
scope.block.build(Instr::XOr(lhs, rhs)).unwrap()
}));
intrinsics intrinsics
} }

View File

@ -885,6 +885,30 @@ impl mir::Expression {
.maybe_location(&mut scope.block, location); .maybe_location(&mut scope.block, location);
Instr::Sub(lhs, mul) Instr::Sub(lhs, mul)
} }
(mir::BinaryOperator::Or, true, true) => todo!(),
(mir::BinaryOperator::Or, true, false) => todo!(),
(mir::BinaryOperator::Or, false, true) => todo!(),
(mir::BinaryOperator::Or, false, false) => todo!(),
(mir::BinaryOperator::Xor, true, true) => todo!(),
(mir::BinaryOperator::Xor, true, false) => todo!(),
(mir::BinaryOperator::Xor, false, true) => todo!(),
(mir::BinaryOperator::Xor, false, false) => todo!(),
(mir::BinaryOperator::BitOr, true, true) => todo!(),
(mir::BinaryOperator::BitOr, true, false) => todo!(),
(mir::BinaryOperator::BitOr, false, true) => todo!(),
(mir::BinaryOperator::BitOr, false, false) => todo!(),
(mir::BinaryOperator::BitAnd, true, true) => todo!(),
(mir::BinaryOperator::BitAnd, true, false) => todo!(),
(mir::BinaryOperator::BitAnd, false, true) => todo!(),
(mir::BinaryOperator::BitAnd, false, false) => todo!(),
(mir::BinaryOperator::BitshiftRight, true, true) => todo!(),
(mir::BinaryOperator::BitshiftRight, true, false) => todo!(),
(mir::BinaryOperator::BitshiftRight, false, true) => todo!(),
(mir::BinaryOperator::BitshiftRight, false, false) => todo!(),
(mir::BinaryOperator::BitshiftLeft, true, true) => todo!(),
(mir::BinaryOperator::BitshiftLeft, true, false) => todo!(),
(mir::BinaryOperator::BitshiftLeft, false, true) => todo!(),
(mir::BinaryOperator::BitshiftLeft, false, false) => todo!(),
}; };
Some(StackValue( Some(StackValue(
StackValueKind::Immutable( StackValueKind::Immutable(

View File

@ -352,6 +352,12 @@ impl Display for BinaryOperator {
BinaryOperator::Cmp(op) => Display::fmt(op, f), BinaryOperator::Cmp(op) => Display::fmt(op, f),
BinaryOperator::Div => write!(f, "/"), BinaryOperator::Div => write!(f, "/"),
BinaryOperator::Mod => write!(f, "%"), BinaryOperator::Mod => write!(f, "%"),
BinaryOperator::Or => write!(f, "||"),
BinaryOperator::Xor => write!(f, "^"),
BinaryOperator::BitOr => write!(f, "|"),
BinaryOperator::BitAnd => write!(f, "&"),
BinaryOperator::BitshiftRight => write!(f, ">>"),
BinaryOperator::BitshiftLeft => write!(f, "<<"),
} }
} }
} }

View File

@ -26,40 +26,6 @@ enum BlockReturn<'b> {
} }
impl TypeKind { impl TypeKind {
/// Return the type that is the result of a binary operator between two
/// values of this type
pub fn simple_binop_type(&self, op: &BinaryOperator) -> Option<TypeKind> {
if !self.category().is_simple_maths() {
return None;
}
Some(match op {
BinaryOperator::Add => self.clone(),
BinaryOperator::Minus => self.clone(),
BinaryOperator::Mult => self.clone(),
BinaryOperator::And => TypeKind::Bool,
BinaryOperator::Cmp(_) => TypeKind::Bool,
BinaryOperator::Div => self.clone(),
BinaryOperator::Mod => self.clone(),
})
}
/// Reverse of binop_type, where the given hint is the known required output
/// type of the binop, and the output is the hint for the lhs/rhs type.
pub fn simple_binop_hint(&self, op: &BinaryOperator) -> Option<TypeKind> {
if !self.category().is_simple_maths() {
return None;
}
match op {
BinaryOperator::Add
| BinaryOperator::Minus
| BinaryOperator::Mult
| BinaryOperator::Div
| BinaryOperator::Mod => Some(self.clone()),
BinaryOperator::And => None,
BinaryOperator::Cmp(_) => None,
}
}
pub fn signed(&self) -> bool { pub fn signed(&self) -> bool {
match self { match self {
TypeKind::Bool => false, TypeKind::Bool => false,
@ -240,6 +206,12 @@ impl BinaryOperator {
CmpOperator::EQ => true, CmpOperator::EQ => true,
CmpOperator::NE => true, CmpOperator::NE => true,
}, },
BinaryOperator::Or => true,
BinaryOperator::Xor => true,
BinaryOperator::BitOr => true,
BinaryOperator::BitAnd => true,
BinaryOperator::BitshiftRight => false,
BinaryOperator::BitshiftLeft => false,
} }
} }
} }
@ -507,6 +479,12 @@ impl Expression {
} }
maybe(lhs.num_value()?, rhs.num_value()?, |a, b| a % b) maybe(lhs.num_value()?, rhs.num_value()?, |a, b| a % b)
} }
BinaryOperator::Or => None,
BinaryOperator::Xor => maybe(lhs.num_value()?, rhs.num_value()?, |a, b| a ^ b),
BinaryOperator::BitOr => maybe(lhs.num_value()?, rhs.num_value()?, |a, b| a | b),
BinaryOperator::BitAnd => maybe(lhs.num_value()?, rhs.num_value()?, |a, b| a & b),
BinaryOperator::BitshiftRight => maybe(lhs.num_value()?, rhs.num_value()?, |a, b| a >> b),
BinaryOperator::BitshiftLeft => maybe(lhs.num_value()?, rhs.num_value()?, |a, b| a << b),
}, },
ExprKind::FunctionCall(..) => None, ExprKind::FunctionCall(..) => None,
ExprKind::If(_) => None, ExprKind::If(_) => None,

View File

@ -222,6 +222,12 @@ pub enum BinaryOperator {
Div, Div,
Mod, Mod,
And, And,
Or,
Xor,
BitOr,
BitAnd,
BitshiftRight,
BitshiftLeft,
Cmp(CmpOperator), Cmp(CmpOperator),
} }

View File

@ -135,7 +135,14 @@ impl TypeKind {
| TypeKind::U16 | TypeKind::U16
| TypeKind::U32 | TypeKind::U32
| TypeKind::U64 | TypeKind::U64
| TypeKind::U128 => Ok(other.clone()), | TypeKind::U128
| TypeKind::F16
| TypeKind::F32B
| TypeKind::F32
| TypeKind::F64
| TypeKind::F80
| TypeKind::F128
| TypeKind::F128PPC => Ok(other.clone()),
_ => Err(ErrorKind::TypesIncompatible(self.clone(), other.clone())), _ => Err(ErrorKind::TypesIncompatible(self.clone(), other.clone())),
}, },
(TypeKind::Vague(Vague::Decimal), other) | (other, TypeKind::Vague(Vague::Decimal)) => match other { (TypeKind::Vague(Vague::Decimal), other) | (other, TypeKind::Vague(Vague::Decimal)) => match other {

View File

@ -431,6 +431,7 @@ impl Expression {
params: (lhs_type.clone(), rhs_type.clone()), params: (lhs_type.clone(), rhs_type.clone()),
operator: *op, operator: *op,
}); });
// dbg!(&lhs_type, &rhs_type, &binops, &ret_ty, &expected_return_ty);
if let Some(binop) = binops if let Some(binop) = binops
.iter() .iter()
.filter(|f| f.1.return_ty.narrow_into(&expected_return_ty).is_ok()) .filter(|f| f.1.return_ty.narrow_into(&expected_return_ty).is_ok())

View File

@ -390,6 +390,9 @@ impl Expression {
widened_rhs = widened_rhs.widen_into(&binop.hands.1); widened_rhs = widened_rhs.widen_into(&binop.hands.1);
} }
let binop_res = type_refs.from_binop(*op, &lhs_ref, &rhs_ref); let binop_res = type_refs.from_binop(*op, &lhs_ref, &rhs_ref);
// dbg!(&return_ty);
// dbg!(&binop_res);
// dbg!(&lhs_ref, &rhs_ref, &binops, &widened_lhs, &widened_rhs);
lhs_ref.narrow(&type_refs.from_type(&widened_lhs).unwrap()); lhs_ref.narrow(&type_refs.from_type(&widened_lhs).unwrap());
rhs_ref.narrow(&type_refs.from_type(&widened_rhs).unwrap()); rhs_ref.narrow(&type_refs.from_type(&widened_rhs).unwrap());
*return_ty = binop_res.as_type(); *return_ty = binop_res.as_type();

View File

@ -332,21 +332,56 @@ impl<'outer> ScopeTypeRefs<'outer> {
.widen(self.types); .widen(self.types);
self.narrow_to_type(&hint1, &ty)?; self.narrow_to_type(&hint1, &ty)?;
let hint1_typeref = self.types.retrieve_typeref(*hint1.0.borrow()).unwrap(); let hint1_typeref = self.types.retrieve_typeref(*hint1.0.borrow()).unwrap();
let hint2_typeref = self.types.retrieve_typeref(*hint2.0.borrow()).unwrap();
match (&hint1_typeref, &hint2_typeref) {
(TypeRefKind::Direct(ret_ty), TypeRefKind::BinOp(op, lhs, rhs)) => {
let mut lhs_ref = self.from_type(&lhs).unwrap();
let mut rhs_ref = self.from_type(&rhs).unwrap();
let binops = self.available_binops(op, &mut lhs_ref, &mut rhs_ref);
let mut binops = binops
.iter()
.filter(|b| b.return_ty.narrow_into(ret_ty).is_ok())
.into_iter();
if let Some(binop) = binops.next() {
let mut lhs_widened = binop.hands.0.clone();
let mut rhs_widened = binop.hands.1.clone();
while let Some(binop) = binops.next() {
lhs_widened = lhs_widened.widen_into(&binop.hands.0);
rhs_widened = rhs_widened.widen_into(&binop.hands.1);
}
lhs_ref.narrow(&self.from_type(&lhs_widened).unwrap());
rhs_ref.narrow(&self.from_type(&rhs_widened).unwrap());
}
}
_ => {}
}
for idx in self.types.type_refs.borrow_mut().iter_mut() { for idx in self.types.type_refs.borrow_mut().iter_mut() {
match hint1_typeref { match (&hint1_typeref, &hint2_typeref) {
TypeRefKind::Direct(_) => { (TypeRefKind::Direct(_), TypeRefKind::Direct(_)) => {
if *idx == hint2.0 && idx != &hint1.0 { if *idx == hint2.0 && idx != &hint1.0 {
*idx.borrow_mut() = *hint1.0.borrow(); *idx.borrow_mut() = *hint1.0.borrow();
} }
} }
TypeRefKind::BinOp(_, _, _) => { (TypeRefKind::Direct(_), TypeRefKind::BinOp(..)) => {}
(TypeRefKind::BinOp(..), TypeRefKind::Direct(..)) => {
// TODO may not be good ? // TODO may not be good ?
// if *idx == hint2.0 && idx != &hint1.0 { // if *idx == hint2.0 && idx != &hint1.0 {
// *idx.borrow_mut() = *hint1.0.borrow(); // *idx.borrow_mut() = *hint1.0.borrow();
// } // }
} }
(TypeRefKind::BinOp(..), TypeRefKind::BinOp(..)) => {
// TODO may not be good ?
if *idx == hint2.0 && idx != &hint1.0 {
*idx.borrow_mut() = *hint1.0.borrow();
}
}
} }
} }
Some(TypeRef(hint1.0.clone(), self)) Some(TypeRef(hint1.0.clone(), self))
} }
} }