feat: more debug locations

This commit is contained in:
Edgar 2024-02-24 10:57:29 +01:00
parent 1e7bb55d2d
commit 3992a57069
No known key found for this signature in database
GPG key ID: 70ADAE8F35904387
5 changed files with 217 additions and 135 deletions

View file

@ -50,10 +50,18 @@ pub struct Ident {
pub struct Type { pub struct Type {
pub name: Ident, pub name: Ident,
pub generics: Vec<Type>, pub generics: Vec<Type>,
pub is_ref: Option<RefType>, pub qualifiers: Vec<TypeQualifier>,
pub span: Span, pub span: Span,
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum TypeQualifier {
Ref, // &
RefMut, // &mut
Ptr, // *const
PtrMut, // *mut
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct FnParam { pub struct FnParam {
pub name: Ident, pub name: Ident,
@ -61,12 +69,6 @@ pub struct FnParam {
pub span: Span, pub span: Span,
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum RefType {
Not,
Mut,
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Block { pub struct Block {
pub body: Vec<Statement>, pub body: Vec<Statement>,

View file

@ -398,7 +398,7 @@ fn compile_fn(ctx: &ModuleCompileCtx, fn_id: DefId) -> Result<(), BuilderError>
.build_load(compile_basic_type(ctx, &local_ty), ptr, "deref")? .build_load(compile_basic_type(ctx, &local_ty), ptr, "deref")?
.into_pointer_value(); .into_pointer_value();
local_ty = match local_ty.kind { local_ty = match local_ty.kind {
ir::TypeKind::Ptr(inner) => *inner, ir::TypeKind::Ptr(_, inner) => *inner,
ir::TypeKind::Ref(_, inner) => *inner, ir::TypeKind::Ref(_, inner) => *inner,
_ => unreachable!(), _ => unreachable!(),
} }
@ -606,7 +606,7 @@ fn compile_bin_op<'ctx>(
let is_float = matches!(lhs_ty.kind, ir::TypeKind::Float(_)); let is_float = matches!(lhs_ty.kind, ir::TypeKind::Float(_));
let is_signed = matches!(lhs_ty.kind, ir::TypeKind::Int(_)); let is_signed = matches!(lhs_ty.kind, ir::TypeKind::Int(_));
Ok(match op { let (result, ty) = match op {
ir::BinOp::Add => { ir::BinOp::Add => {
let value = if is_float { let value = if is_float {
ctx.builder ctx.builder
@ -931,7 +931,9 @@ fn compile_bin_op<'ctx>(
) )
} }
ir::BinOp::Offset => todo!(), ir::BinOp::Offset => todo!(),
}) };
Ok((result, ty))
} }
fn compile_rvalue<'ctx>( fn compile_rvalue<'ctx>(
@ -941,8 +943,25 @@ fn compile_rvalue<'ctx>(
rvalue: &ir::RValue, rvalue: &ir::RValue,
) -> Result<(BasicValueEnum<'ctx>, TypeInfo), BuilderError> { ) -> Result<(BasicValueEnum<'ctx>, TypeInfo), BuilderError> {
Ok(match rvalue { Ok(match rvalue {
ir::RValue::Use(op) => compile_load_operand(ctx, fn_id, locals, op)?, ir::RValue::Use(op, span) => {
ir::RValue::Ref(_mutable, op) => match op { ctx.set_debug_loc(
ctx.builder
.get_current_debug_location()
.unwrap()
.get_scope(),
*span,
);
compile_load_operand(ctx, fn_id, locals, op)?
}
ir::RValue::Ref(_mutable, op, span) => {
ctx.set_debug_loc(
ctx.builder
.get_current_debug_location()
.unwrap()
.get_scope(),
*span,
);
match op {
ir::Operand::Copy(_) => todo!(), ir::Operand::Copy(_) => todo!(),
ir::Operand::Move(place) => { ir::Operand::Move(place) => {
let mut ptr = *locals.get(&place.local).unwrap(); let mut ptr = *locals.get(&place.local).unwrap();
@ -959,7 +978,7 @@ fn compile_rvalue<'ctx>(
.build_load(compile_basic_type(ctx, &local_ty), ptr, "deref")? .build_load(compile_basic_type(ctx, &local_ty), ptr, "deref")?
.into_pointer_value(); .into_pointer_value();
local_ty = match local_ty.kind { local_ty = match local_ty.kind {
ir::TypeKind::Ptr(inner) => *inner, ir::TypeKind::Ptr(_, inner) => *inner,
ir::TypeKind::Ref(_, inner) => *inner, ir::TypeKind::Ref(_, inner) => *inner,
_ => unreachable!(), _ => unreachable!(),
} }
@ -972,10 +991,29 @@ fn compile_rvalue<'ctx>(
(ptr.as_basic_value_enum(), local_ty) (ptr.as_basic_value_enum(), local_ty)
} }
ir::Operand::Constant(_) => todo!("references to constants not yet implemented"), ir::Operand::Constant(_) => todo!("references to constants not yet implemented"),
}, }
ir::RValue::BinOp(op, lhs, rhs) => compile_bin_op(ctx, fn_id, locals, *op, lhs, rhs)?, }
ir::RValue::LogicOp(_, _, _) => todo!(), ir::RValue::BinOp(op, lhs, rhs, span) => {
ir::RValue::UnOp(op, value) => compile_unary_op(ctx, fn_id, locals, *op, value)?, ctx.set_debug_loc(
ctx.builder
.get_current_debug_location()
.unwrap()
.get_scope(),
*span,
);
compile_bin_op(ctx, fn_id, locals, *op, lhs, rhs)?
}
ir::RValue::LogicOp(_, _, _, _span) => todo!(),
ir::RValue::UnOp(op, value, span) => {
ctx.set_debug_loc(
ctx.builder
.get_current_debug_location()
.unwrap()
.get_scope(),
*span,
);
compile_unary_op(ctx, fn_id, locals, *op, value)?
}
}) })
} }
@ -1017,7 +1055,7 @@ fn compile_load_place<'ctx>(
.build_load(compile_basic_type(ctx, &local_ty), ptr, "deref")? .build_load(compile_basic_type(ctx, &local_ty), ptr, "deref")?
.into_pointer_value(); .into_pointer_value();
local_ty = match local_ty.kind { local_ty = match local_ty.kind {
ir::TypeKind::Ptr(inner) => *inner, ir::TypeKind::Ptr(_, inner) => *inner,
ir::TypeKind::Ref(_, inner) => *inner, ir::TypeKind::Ref(_, inner) => *inner,
_ => unreachable!(), _ => unreachable!(),
} }
@ -1110,6 +1148,10 @@ fn compile_value<'ctx>(
.into_int_type() .into_int_type()
.const_int((*x) as u64, false) .const_int((*x) as u64, false)
.as_basic_value_enum(), .as_basic_value_enum(),
ir::ConstValue::Isize(x) => ty
.into_int_type()
.const_int((*x) as u64, true)
.as_basic_value_enum(),
}, },
ValueTree::Branch(_) => todo!(), ValueTree::Branch(_) => todo!(),
}) })
@ -1178,7 +1220,7 @@ fn compile_basic_type<'ctx>(
ir::TypeKind::FnDef(_def_id, _generic_args) => { ir::TypeKind::FnDef(_def_id, _generic_args) => {
panic!() panic!()
} }
ir::TypeKind::Ptr(_pointee) => ctx ir::TypeKind::Ptr(_is_mut, _pointee) => ctx
.ctx .ctx
.context .context
.ptr_sized_int_type(&ctx.target_data, None) .ptr_sized_int_type(&ctx.target_data, None)
@ -1205,6 +1247,7 @@ fn compile_basic_type<'ctx>(
.struct_type(&fields, false) .struct_type(&fields, false)
.as_basic_type_enum() .as_basic_type_enum()
} }
ir::TypeKind::Str => todo!(),
} }
} }
@ -1308,10 +1351,10 @@ fn compile_debug_type<'ctx>(ctx: &ModuleCompileCtx<'ctx, '_>, ty: &ir::TypeInfo)
ir::TypeKind::FnDef(_def_id, _generic_args) => { ir::TypeKind::FnDef(_def_id, _generic_args) => {
panic!() panic!()
} }
ir::TypeKind::Ptr(pointee) => ctx ir::TypeKind::Ptr(_is_mut, pointee) => ctx
.di_builder .di_builder
.create_pointer_type( .create_pointer_type(
&format!("ptr<{:?}>", pointee.kind), &format!("*{:?}", pointee.kind),
compile_debug_type(ctx, pointee), compile_debug_type(ctx, pointee),
(ctx.target_data.get_pointer_byte_size(None) * 8).into(), (ctx.target_data.get_pointer_byte_size(None) * 8).into(),
ctx.target_data.get_pointer_byte_size(None), ctx.target_data.get_pointer_byte_size(None),
@ -1357,5 +1400,6 @@ fn compile_debug_type<'ctx>(ctx: &ModuleCompileCtx<'ctx, '_>, ty: &ir::TypeInfo)
) )
.as_type() .as_type()
} }
ir::TypeKind::Str => todo!(),
} }
} }

View file

@ -222,7 +222,8 @@ pub enum TypeKind {
Uint(UintTy), Uint(UintTy),
Float(FloatTy), Float(FloatTy),
FnDef(DefId, Vec<TypeInfo>), // The vec are generic types, not arg types FnDef(DefId, Vec<TypeInfo>), // The vec are generic types, not arg types
Ptr(Box<TypeInfo>), Str,
Ptr(bool, Box<TypeInfo>),
Ref(bool, Box<TypeInfo>), Ref(bool, Box<TypeInfo>),
Struct(DefId), // todo, add generics Struct(DefId), // todo, add generics
} }
@ -259,9 +260,10 @@ impl TypeKind {
Self::Float(_) => todo!(), Self::Float(_) => todo!(),
TypeKind::Unit => unreachable!(), TypeKind::Unit => unreachable!(),
TypeKind::FnDef(_, _) => unreachable!(), TypeKind::FnDef(_, _) => unreachable!(),
TypeKind::Ptr(_pointee) => todo!(), TypeKind::Ptr(_, _pointee) => todo!(),
TypeKind::Ref(_, inner) => inner.kind.get_falsy_value(), TypeKind::Ref(_, inner) => inner.kind.get_falsy_value(),
TypeKind::Struct(_) => todo!(), TypeKind::Struct(_) => todo!(),
TypeKind::Str => todo!(),
} }
} }
} }
@ -329,6 +331,7 @@ impl ValueTree {
ConstValue::F32(_) => TypeKind::Float(FloatTy::F32), ConstValue::F32(_) => TypeKind::Float(FloatTy::F32),
ConstValue::F64(_) => TypeKind::Float(FloatTy::F64), ConstValue::F64(_) => TypeKind::Float(FloatTy::F64),
ConstValue::Char(_) => TypeKind::Char, ConstValue::Char(_) => TypeKind::Char,
ConstValue::Isize(_) => TypeKind::Int(IntTy::Isize),
}, },
ValueTree::Branch(_) => todo!(), ValueTree::Branch(_) => todo!(),
} }
@ -337,11 +340,11 @@ impl ValueTree {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum RValue { pub enum RValue {
Use(Operand), Use(Operand, Span),
Ref(bool, Operand), Ref(bool, Operand, Span),
BinOp(BinOp, Operand, Operand), BinOp(BinOp, Operand, Operand, Span),
LogicOp(LogicalOp, Operand, Operand), LogicOp(LogicalOp, Operand, Operand, Span),
UnOp(UnOp, Operand), UnOp(UnOp, Operand, Span),
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -465,6 +468,7 @@ pub enum ConstValue {
I32(i32), I32(i32),
I64(i64), I64(i64),
I128(i128), I128(i128),
Isize(isize),
U8(u8), U8(u8),
U16(u16), U16(u16),
U32(u32), U32(u32),

View file

@ -235,7 +235,7 @@ fn lower_while(builder: &mut BodyBuilder, info: &WhileStmt, ret_type: &TypeKind)
terminator_span: Some(info.block.span), terminator_span: Some(info.block.span),
}); });
let (discriminator, discriminator_type) = lower_expr(builder, &info.condition, None); let (discriminator, discriminator_type, disc_span) = lower_expr(builder, &info.condition, None);
let local = builder.add_temp_local(TypeKind::Bool); let local = builder.add_temp_local(TypeKind::Bool);
let place = Place { let place = Place {
@ -244,7 +244,7 @@ fn lower_while(builder: &mut BodyBuilder, info: &WhileStmt, ret_type: &TypeKind)
}; };
builder.statements.push(Statement { builder.statements.push(Statement {
span: Some(info.span), span: Some(disc_span),
kind: StatementKind::Assign(place.clone(), discriminator), kind: StatementKind::Assign(place.clone(), discriminator),
}); });
@ -303,7 +303,7 @@ fn lower_while(builder: &mut BodyBuilder, info: &WhileStmt, ret_type: &TypeKind)
fn lower_if_stmt(builder: &mut BodyBuilder, info: &ast::IfStmt, ret_type: &TypeKind) { fn lower_if_stmt(builder: &mut BodyBuilder, info: &ast::IfStmt, ret_type: &TypeKind) {
let cond_ty = find_expr_type(builder, &info.condition).expect("coouldnt find cond type"); let cond_ty = find_expr_type(builder, &info.condition).expect("coouldnt find cond type");
let (condition, condition_ty) = lower_expr(builder, &info.condition, Some(&cond_ty)); let (condition, condition_ty, cond_span) = lower_expr(builder, &info.condition, Some(&cond_ty));
let local = builder.add_temp_local(TypeKind::Bool); let local = builder.add_temp_local(TypeKind::Bool);
let place = Place { let place = Place {
@ -312,7 +312,7 @@ fn lower_if_stmt(builder: &mut BodyBuilder, info: &ast::IfStmt, ret_type: &TypeK
}; };
builder.statements.push(Statement { builder.statements.push(Statement {
span: Some(info.span), span: Some(cond_span),
kind: StatementKind::Assign(place.clone(), condition), kind: StatementKind::Assign(place.clone(), condition),
}); });
@ -400,7 +400,7 @@ fn lower_if_stmt(builder: &mut BodyBuilder, info: &ast::IfStmt, ret_type: &TypeK
fn lower_let(builder: &mut BodyBuilder, info: &ast::LetStmt) { fn lower_let(builder: &mut BodyBuilder, info: &ast::LetStmt) {
let ty = lower_type(&builder.ctx, &info.r#type, builder.local_module); let ty = lower_type(&builder.ctx, &info.r#type, builder.local_module);
let (rvalue, _ty) = lower_expr(builder, &info.value, Some(&ty.kind)); let (rvalue, _ty, _span) = lower_expr(builder, &info.value, Some(&ty.kind));
let local_idx = builder.name_to_local.get(&info.name.name).copied().unwrap(); let local_idx = builder.name_to_local.get(&info.name.name).copied().unwrap();
builder.statements.push(Statement { builder.statements.push(Statement {
span: Some(info.name.span), span: Some(info.name.span),
@ -419,11 +419,14 @@ fn lower_let(builder: &mut BodyBuilder, info: &ast::LetStmt) {
} }
fn lower_assign(builder: &mut BodyBuilder, info: &ast::AssignStmt) { fn lower_assign(builder: &mut BodyBuilder, info: &ast::AssignStmt) {
let (mut place, mut ty) = lower_path(builder, &info.name); let (mut place, mut ty, _span) = lower_path(builder, &info.name);
for _ in 0..info.deref_times { for _ in 0..info.deref_times {
match &ty { match &ty {
TypeKind::Ptr(inner) => { TypeKind::Ptr(is_mut, inner) => {
if !is_mut {
panic!("trying to mutate non mut ptr");
}
ty = inner.kind.clone(); ty = inner.kind.clone();
} }
TypeKind::Ref(is_mut, inner) => { TypeKind::Ref(is_mut, inner) => {
@ -437,7 +440,7 @@ fn lower_assign(builder: &mut BodyBuilder, info: &ast::AssignStmt) {
place.projection.push(PlaceElem::Deref); place.projection.push(PlaceElem::Deref);
} }
let (rvalue, _ty) = lower_expr(builder, &info.value, Some(&ty)); let (rvalue, _ty, _span) = lower_expr(builder, &info.value, Some(&ty));
builder.statements.push(Statement { builder.statements.push(Statement {
span: Some(info.name.first.span), span: Some(info.name.first.span),
@ -507,21 +510,37 @@ fn lower_expr(
builder: &mut BodyBuilder, builder: &mut BodyBuilder,
info: &ast::Expression, info: &ast::Expression,
type_hint: Option<&TypeKind>, type_hint: Option<&TypeKind>,
) -> (ir::RValue, TypeKind) { ) -> (ir::RValue, TypeKind, Span) {
match info { match info {
ast::Expression::Value(info) => { ast::Expression::Value(info) => {
let (value, ty) = lower_value(builder, info, type_hint); let (value, ty, span) = lower_value(builder, info, type_hint);
(ir::RValue::Use(value), ty) (ir::RValue::Use(value, span), ty, span)
} }
ast::Expression::FnCall(info) => { ast::Expression::FnCall(info) => {
let (value, ty) = lower_fn_call(builder, info); let (value, ty, span) = lower_fn_call(builder, info);
(ir::RValue::Use(value), ty) (ir::RValue::Use(value, span), ty, span)
} }
ast::Expression::Unary(_, _) => todo!(), ast::Expression::Unary(_, _) => todo!(),
ast::Expression::Binary(lhs, op, rhs) => { ast::Expression::Binary(lhs, op, rhs) => {
lower_binary_expr(builder, lhs, op, rhs, type_hint) lower_binary_expr(builder, lhs, op, rhs, type_hint)
} }
ast::Expression::Deref(_) => todo!(), ast::Expression::Deref(inner) => {
let (value, ty, span) = lower_expr(builder, inner, type_hint);
// check if its a use directly, to avoid a temporary.
let mut value = match value {
RValue::Use(op, _) => match op {
Operand::Copy(place) => place,
Operand::Move(place) => place,
Operand::Constant(_) => todo!("constant data deref"),
},
_ => unreachable!(),
};
value.projection.push(PlaceElem::Deref);
(RValue::Use(Operand::Move(value), span), ty, span)
}
ast::Expression::AsRef(inner, mutable) => { ast::Expression::AsRef(inner, mutable) => {
let type_hint = match type_hint { let type_hint = match type_hint {
Some(inner) => match inner { Some(inner) => match inner {
@ -530,11 +549,11 @@ fn lower_expr(
}, },
None => None, None => None,
}; };
let (mut value, ty) = lower_expr(builder, inner, type_hint); let (mut value, ty, span) = lower_expr(builder, inner, type_hint);
// check if its a use directly, to avoid a temporary. // check if its a use directly, to avoid a temporary.
value = match value { value = match value {
RValue::Use(op) => RValue::Ref(*mutable, op), RValue::Use(op, _span) => RValue::Ref(*mutable, op, span),
value => { value => {
let inner_local = builder.add_local(Local::temp(ty.clone())); let inner_local = builder.add_local(Local::temp(ty.clone()));
let inner_place = Place { let inner_place = Place {
@ -551,19 +570,19 @@ fn lower_expr(
span: None, span: None,
kind: StatementKind::Assign(inner_place.clone(), value), kind: StatementKind::Assign(inner_place.clone(), value),
}); });
RValue::Ref(*mutable, Operand::Move(inner_place)) RValue::Ref(*mutable, Operand::Move(inner_place), span)
} }
}; };
let ty = TypeKind::Ref( let ty = TypeKind::Ref(
*mutable, *mutable,
Box::new(TypeInfo { Box::new(TypeInfo {
span: None, span: Some(span),
kind: ty, kind: ty,
}), }),
); );
(value, ty) (value, ty, span)
} }
ast::Expression::StructInit(info) => { ast::Expression::StructInit(info) => {
let id = *builder let id = *builder
@ -595,11 +614,10 @@ fn lower_expr(
field_place field_place
.projection .projection
.push(PlaceElem::Field { field_idx: idx }); .push(PlaceElem::Field { field_idx: idx });
let span = value.span;
let variant = &struct_body.variants[idx].ty.kind; let variant = &struct_body.variants[idx].ty.kind;
let (value, _value_ty) = lower_expr(builder, &value.value, Some(variant)); let (value, _value_ty, span) = lower_expr(builder, &value.value, Some(variant));
builder.statements.push(Statement { builder.statements.push(Statement {
span: Some(span), span: Some(span),
@ -607,7 +625,7 @@ fn lower_expr(
}); });
} }
(RValue::Use(Operand::Move(place)), ty) (RValue::Use(Operand::Move(place), info.span), ty, info.span)
} }
} }
} }
@ -618,17 +636,17 @@ fn lower_binary_expr(
op: &ast::BinaryOp, op: &ast::BinaryOp,
rhs: &ast::Expression, rhs: &ast::Expression,
type_hint: Option<&TypeKind>, type_hint: Option<&TypeKind>,
) -> (ir::RValue, TypeKind) { ) -> (ir::RValue, TypeKind, Span) {
trace!("lowering binary op: {:?}", op); trace!("lowering binary op: {:?}", op);
let (lhs, lhs_ty) = if type_hint.is_none() { let (lhs, lhs_ty, _) = if type_hint.is_none() {
let ty = find_expr_type(builder, lhs) let ty = find_expr_type(builder, lhs)
.unwrap_or_else(|| find_expr_type(builder, rhs).expect("cant find type")); .unwrap_or_else(|| find_expr_type(builder, rhs).expect("cant find type"));
lower_expr(builder, lhs, Some(&ty)) lower_expr(builder, lhs, Some(&ty))
} else { } else {
lower_expr(builder, lhs, type_hint) lower_expr(builder, lhs, type_hint)
}; };
let (rhs, rhs_ty) = if type_hint.is_none() { let (rhs, rhs_ty, _) = if type_hint.is_none() {
let ty = find_expr_type(builder, rhs).unwrap_or(lhs_ty.clone()); let ty = find_expr_type(builder, rhs).unwrap_or(lhs_ty.clone());
lower_expr(builder, rhs, Some(&ty)) lower_expr(builder, rhs, Some(&ty))
} else { } else {
@ -636,7 +654,7 @@ fn lower_binary_expr(
}; };
let lhs = match lhs { let lhs = match lhs {
RValue::Use(op) => op, RValue::Use(op, _span) => op,
lhs => { lhs => {
let lhs_local = builder.add_local(Local::temp(lhs_ty.clone())); let lhs_local = builder.add_local(Local::temp(lhs_ty.clone()));
let lhs_place = Place { let lhs_place = Place {
@ -658,7 +676,7 @@ fn lower_binary_expr(
}; };
let rhs = match rhs { let rhs = match rhs {
RValue::Use(op) => op, RValue::Use(op, _span) => op,
rhs => { rhs => {
let rhs_local = builder.add_local(Local::temp(rhs_ty.clone())); let rhs_local = builder.add_local(Local::temp(rhs_ty.clone()));
let rhs_place = Place { let rhs_place = Place {
@ -680,46 +698,50 @@ fn lower_binary_expr(
}; };
match op { match op {
ast::BinaryOp::Arith(op, _) => ( ast::BinaryOp::Arith(op, span) => (
match op { match op {
ast::ArithOp::Add => ir::RValue::BinOp(ir::BinOp::Add, lhs, rhs), ast::ArithOp::Add => ir::RValue::BinOp(ir::BinOp::Add, lhs, rhs, *span),
ast::ArithOp::Sub => ir::RValue::BinOp(ir::BinOp::Sub, lhs, rhs), ast::ArithOp::Sub => ir::RValue::BinOp(ir::BinOp::Sub, lhs, rhs, *span),
ast::ArithOp::Mul => ir::RValue::BinOp(ir::BinOp::Mul, lhs, rhs), ast::ArithOp::Mul => ir::RValue::BinOp(ir::BinOp::Mul, lhs, rhs, *span),
ast::ArithOp::Div => ir::RValue::BinOp(ir::BinOp::Div, lhs, rhs), ast::ArithOp::Div => ir::RValue::BinOp(ir::BinOp::Div, lhs, rhs, *span),
ast::ArithOp::Mod => ir::RValue::BinOp(ir::BinOp::Rem, lhs, rhs), ast::ArithOp::Mod => ir::RValue::BinOp(ir::BinOp::Rem, lhs, rhs, *span),
}, },
lhs_ty, lhs_ty,
*span,
), ),
ast::BinaryOp::Logic(op, _) => ( ast::BinaryOp::Logic(op, span) => (
match op { match op {
ast::LogicOp::And => ir::RValue::LogicOp(ir::LogicalOp::And, lhs, rhs), ast::LogicOp::And => ir::RValue::LogicOp(ir::LogicalOp::And, lhs, rhs, *span),
ast::LogicOp::Or => ir::RValue::LogicOp(ir::LogicalOp::Or, lhs, rhs), ast::LogicOp::Or => ir::RValue::LogicOp(ir::LogicalOp::Or, lhs, rhs, *span),
}, },
TypeKind::Bool, TypeKind::Bool,
*span,
), ),
ast::BinaryOp::Compare(op, _) => ( ast::BinaryOp::Compare(op, span) => (
match op { match op {
ast::CmpOp::Eq => ir::RValue::BinOp(ir::BinOp::Eq, lhs, rhs), ast::CmpOp::Eq => ir::RValue::BinOp(ir::BinOp::Eq, lhs, rhs, *span),
ast::CmpOp::NotEq => ir::RValue::BinOp(ir::BinOp::Ne, lhs, rhs), ast::CmpOp::NotEq => ir::RValue::BinOp(ir::BinOp::Ne, lhs, rhs, *span),
ast::CmpOp::Lt => ir::RValue::BinOp(ir::BinOp::Lt, lhs, rhs), ast::CmpOp::Lt => ir::RValue::BinOp(ir::BinOp::Lt, lhs, rhs, *span),
ast::CmpOp::LtEq => ir::RValue::BinOp(ir::BinOp::Le, lhs, rhs), ast::CmpOp::LtEq => ir::RValue::BinOp(ir::BinOp::Le, lhs, rhs, *span),
ast::CmpOp::Gt => ir::RValue::BinOp(ir::BinOp::Gt, lhs, rhs), ast::CmpOp::Gt => ir::RValue::BinOp(ir::BinOp::Gt, lhs, rhs, *span),
ast::CmpOp::GtEq => ir::RValue::BinOp(ir::BinOp::Ge, lhs, rhs), ast::CmpOp::GtEq => ir::RValue::BinOp(ir::BinOp::Ge, lhs, rhs, *span),
}, },
TypeKind::Bool, TypeKind::Bool,
*span,
), ),
ast::BinaryOp::Bitwise(op, _) => ( ast::BinaryOp::Bitwise(op, span) => (
match op { match op {
ast::BitwiseOp::And => ir::RValue::BinOp(ir::BinOp::BitAnd, lhs, rhs), ast::BitwiseOp::And => ir::RValue::BinOp(ir::BinOp::BitAnd, lhs, rhs, *span),
ast::BitwiseOp::Or => ir::RValue::BinOp(ir::BinOp::BitOr, lhs, rhs), ast::BitwiseOp::Or => ir::RValue::BinOp(ir::BinOp::BitOr, lhs, rhs, *span),
ast::BitwiseOp::Xor => ir::RValue::BinOp(ir::BinOp::BitXor, lhs, rhs), ast::BitwiseOp::Xor => ir::RValue::BinOp(ir::BinOp::BitXor, lhs, rhs, *span),
}, },
lhs_ty, lhs_ty,
*span,
), ),
} }
} }
fn lower_fn_call(builder: &mut BodyBuilder, info: &ast::FnCallExpr) -> (Operand, TypeKind) { fn lower_fn_call(builder: &mut BodyBuilder, info: &ast::FnCallExpr) -> (Operand, TypeKind, Span) {
let fn_id = { let fn_id = {
let mod_body = builder.get_module_body(); let mod_body = builder.get_module_body();
@ -765,7 +787,7 @@ fn lower_fn_call(builder: &mut BodyBuilder, info: &ast::FnCallExpr) -> (Operand,
let mut args = Vec::new(); let mut args = Vec::new();
for (arg, arg_ty) in info.params.iter().zip(args_ty) { for (arg, arg_ty) in info.params.iter().zip(args_ty) {
let (rvalue, _rvalue_ty) = lower_expr(builder, arg, Some(&arg_ty.kind)); let (rvalue, _rvalue_ty, _span) = lower_expr(builder, arg, Some(&arg_ty.kind));
args.push(rvalue); args.push(rvalue);
} }
@ -793,14 +815,14 @@ fn lower_fn_call(builder: &mut BodyBuilder, info: &ast::FnCallExpr) -> (Operand,
terminator_span: Some(info.span), terminator_span: Some(info.span),
}); });
(Operand::Move(dest_place), ret_ty.kind.clone()) (Operand::Move(dest_place), ret_ty.kind.clone(), info.span)
} }
fn lower_value( fn lower_value(
builder: &mut BodyBuilder, builder: &mut BodyBuilder,
info: &ast::ValueExpr, info: &ast::ValueExpr,
type_hint: Option<&TypeKind>, type_hint: Option<&TypeKind>,
) -> (Operand, TypeKind) { ) -> (Operand, TypeKind, Span) {
match info { match info {
ast::ValueExpr::Bool { value, span } => ( ast::ValueExpr::Bool { value, span } => (
ir::Operand::Constant(ir::ConstData { ir::Operand::Constant(ir::ConstData {
@ -812,6 +834,7 @@ fn lower_value(
kind: ir::ConstKind::Value(ir::ValueTree::Leaf(ir::ConstValue::Bool(*value))), kind: ir::ConstKind::Value(ir::ValueTree::Leaf(ir::ConstValue::Bool(*value))),
}), }),
TypeKind::Bool, TypeKind::Bool,
*span,
), ),
ast::ValueExpr::Char { value, span } => ( ast::ValueExpr::Char { value, span } => (
ir::Operand::Constant(ir::ConstData { ir::Operand::Constant(ir::ConstData {
@ -825,6 +848,7 @@ fn lower_value(
))), ))),
}), }),
TypeKind::Char, TypeKind::Char,
*span,
), ),
ast::ValueExpr::Int { value, span } => { ast::ValueExpr::Int { value, span } => {
let (ty, val) = match type_hint { let (ty, val) = match type_hint {
@ -875,6 +899,10 @@ fn lower_value(
), ),
_ => todo!(), _ => todo!(),
}, },
ir::TypeKind::Ptr(_, _) => (
ir::TypeKind::Int(ir::IntTy::Isize),
ir::ConstValue::Isize((*value) as isize),
),
_ => unreachable!(), _ => unreachable!(),
}, },
None => todo!(), None => todo!(),
@ -890,6 +918,7 @@ fn lower_value(
kind: ir::ConstKind::Value(ir::ValueTree::Leaf(val)), kind: ir::ConstKind::Value(ir::ValueTree::Leaf(val)),
}), }),
ty, ty,
*span,
) )
} }
ast::ValueExpr::Float { value, span } => match type_hint { ast::ValueExpr::Float { value, span } => match type_hint {
@ -907,6 +936,7 @@ fn lower_value(
))), ))),
}), }),
type_hint.clone(), type_hint.clone(),
*span,
), ),
ir::FloatTy::F64 => ( ir::FloatTy::F64 => (
ir::Operand::Constant(ir::ConstData { ir::Operand::Constant(ir::ConstData {
@ -920,6 +950,7 @@ fn lower_value(
))), ))),
}), }),
type_hint.clone(), type_hint.clone(),
*span,
), ),
}, },
_ => unreachable!(), _ => unreachable!(),
@ -928,17 +959,17 @@ fn lower_value(
}, },
ast::ValueExpr::Str { value: _, span: _ } => todo!(), ast::ValueExpr::Str { value: _, span: _ } => todo!(),
ast::ValueExpr::Path(info) => { ast::ValueExpr::Path(info) => {
let (place, ty) = lower_path(builder, info); let (place, ty, span) = lower_path(builder, info);
(Operand::Move(place), ty) (Operand::Move(place), ty, span)
} }
} }
} }
fn lower_return(builder: &mut BodyBuilder, info: &ast::ReturnStmt, return_type: &TypeKind) { fn lower_return(builder: &mut BodyBuilder, info: &ast::ReturnStmt, return_type: &TypeKind) {
if let Some(value_expr) = &info.value { if let Some(value_expr) = &info.value {
let (value, _ty) = lower_expr(builder, value_expr, Some(return_type)); let (value, _ty, span) = lower_expr(builder, value_expr, Some(return_type));
builder.statements.push(Statement { builder.statements.push(Statement {
span: Some(info.span), span: Some(span),
kind: StatementKind::Assign( kind: StatementKind::Assign(
Place { Place {
local: builder.ret_local, local: builder.ret_local,
@ -957,7 +988,7 @@ fn lower_return(builder: &mut BodyBuilder, info: &ast::ReturnStmt, return_type:
}); });
} }
fn lower_path(builder: &mut BodyBuilder, info: &ast::PathExpr) -> (ir::Place, TypeKind) { fn lower_path(builder: &mut BodyBuilder, info: &ast::PathExpr) -> (ir::Place, TypeKind, Span) {
let local = *builder let local = *builder
.name_to_local .name_to_local
.get(&info.first.name) .get(&info.first.name)
@ -992,12 +1023,13 @@ fn lower_path(builder: &mut BodyBuilder, info: &ast::PathExpr) -> (ir::Place, Ty
projection: projection.into(), // todo, array projection: projection.into(), // todo, array
}, },
ty, ty,
info.span,
) )
} }
#[allow(clippy::only_used_in_recursion)] #[allow(clippy::only_used_in_recursion)]
pub fn lower_type(ctx: &BuildCtx, t: &ast::Type, module_id: DefId) -> ir::TypeInfo { pub fn lower_type(ctx: &BuildCtx, t: &ast::Type, module_id: DefId) -> ir::TypeInfo {
let inner_ty = match t.name.name.as_str() { let mut ty = match t.name.name.as_str() {
"()" => ir::TypeInfo { "()" => ir::TypeInfo {
span: Some(t.span), span: Some(t.span),
kind: ir::TypeKind::Unit, kind: ir::TypeKind::Unit,
@ -1050,13 +1082,9 @@ pub fn lower_type(ctx: &BuildCtx, t: &ast::Type, module_id: DefId) -> ir::TypeIn
span: Some(t.span), span: Some(t.span),
kind: ir::TypeKind::Bool, kind: ir::TypeKind::Bool,
}, },
"ptr" => ir::TypeInfo { "str" => ir::TypeInfo {
span: Some(t.span), span: Some(t.span),
kind: ir::TypeKind::Ptr(Box::new(lower_type( kind: ir::TypeKind::Str,
ctx,
t.generics.first().unwrap(),
module_id,
))),
}, },
other => { other => {
let module = ctx.body.modules.get(&module_id).expect("module not found"); let module = ctx.body.modules.get(&module_id).expect("module not found");
@ -1072,17 +1100,19 @@ pub fn lower_type(ctx: &BuildCtx, t: &ast::Type, module_id: DefId) -> ir::TypeIn
} }
}; };
match t.is_ref { for qualifier in &t.qualifiers {
Some(x) => ir::TypeInfo { let kind = match qualifier {
ast::TypeQualifier::Ref => TypeKind::Ref(false, Box::new(ty)),
ast::TypeQualifier::RefMut => TypeKind::Ref(true, Box::new(ty)),
ast::TypeQualifier::Ptr => TypeKind::Ptr(false, Box::new(ty)),
ast::TypeQualifier::PtrMut => TypeKind::Ptr(true, Box::new(ty)),
};
ty = TypeInfo {
span: Some(t.span), span: Some(t.span),
kind: TypeKind::Ref( kind,
match x { };
ast::RefType::Not => false,
ast::RefType::Mut => true,
},
Box::new(inner_ty),
),
},
None => inner_ty,
} }
ty
} }

View file

@ -140,17 +140,24 @@ pub(crate) Ident: ast::Ident = {
} }
} }
pub(crate) TypeQualifier: ast::TypeQualifier = {
"&" => ast::TypeQualifier::Ref,
"&" "mut" => ast::TypeQualifier::RefMut,
"*" "const" => ast::TypeQualifier::Ptr,
"*" "mut" => ast::TypeQualifier::PtrMut,
}
pub(crate) Type: ast::Type = { pub(crate) Type: ast::Type = {
<lo:@L> <is_ref:RefType?> <name:Ident> <hi:@R> => ast::Type { <lo:@L> <qualifiers:TypeQualifier*> <name:Ident> <hi:@R> => ast::Type {
name, name,
generics: vec![], generics: vec![],
is_ref, qualifiers,
span: ast::Span::new(lo, hi), span: ast::Span::new(lo, hi),
}, },
<lo:@L> <is_ref:RefType?> <name:Ident> "<" <generics:Comma<Type>> ">" <hi:@R> => ast::Type { <lo:@L> <qualifiers:TypeQualifier*> <name:Ident> "<" <generics:Comma<Type>> ">" <hi:@R> => ast::Type {
name, name,
generics, generics,
is_ref, qualifiers,
span: ast::Span::new(lo, hi), span: ast::Span::new(lo, hi),
}, },
} }
@ -160,13 +167,13 @@ pub(crate) IdentWithOptionalType: ast::Type = {
<lo:@L> <name:Ident> <hi:@R> => ast::Type { <lo:@L> <name:Ident> <hi:@R> => ast::Type {
name, name,
generics: vec![], generics: vec![],
is_ref: None, qualifiers: vec![],
span: ast::Span::new(lo, hi), span: ast::Span::new(lo, hi),
}, },
<lo:@L> <name:Ident> "::" "<" <generics:Comma<Type>> ">" <hi:@R> => ast::Type { <lo:@L> <name:Ident> "::" "<" <generics:Comma<Type>> ">" <hi:@R> => ast::Type {
name, name,
generics, generics,
is_ref: None, qualifiers: vec![],
span: ast::Span::new(lo, hi), span: ast::Span::new(lo, hi),
}, },
} }
@ -404,11 +411,6 @@ pub(crate) StructInitExpr: ast::StructInitExpr = {
} }
} }
pub(crate) RefType: ast::RefType = {
"&" => ast::RefType::Not,
"&" "mut" => ast::RefType::Mut,
}
pub(crate) FnParam: ast::FnParam = { pub(crate) FnParam: ast::FnParam = {
<lo:@L> <name:Ident> ":" <arg_type:Type> <hi:@R> => ast::FnParam { <lo:@L> <name:Ident> ":" <arg_type:Type> <hi:@R> => ast::FnParam {
name, name,