mirror of
https://github.com/edg-l/edlang.git
synced 2024-11-22 07:58:24 +00:00
prog
This commit is contained in:
parent
fed52c0327
commit
167a7cf001
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -563,6 +563,8 @@ dependencies = [
|
|||
"edlang_ast",
|
||||
"edlang_check",
|
||||
"edlang_codegen_mlir",
|
||||
"edlang_ir",
|
||||
"edlang_lowering",
|
||||
"edlang_parser",
|
||||
"edlang_session",
|
||||
"tracing",
|
||||
|
|
|
@ -17,6 +17,8 @@ color-eyre = "0.6.2"
|
|||
edlang_ast = { version = "0.1.0", path = "../edlang_ast" }
|
||||
edlang_check = { version = "0.1.0", path = "../edlang_check" }
|
||||
edlang_codegen_mlir = { version = "0.1.0", path = "../edlang_codegen_mlir" }
|
||||
edlang_ir = { version = "0.1.0", path = "../edlang_ir" }
|
||||
edlang_lowering = { version = "0.1.0", path = "../edlang_lowering" }
|
||||
edlang_parser = { version = "0.1.0", path = "../edlang_parser" }
|
||||
edlang_session = { version = "0.1.0", path = "../edlang_session" }
|
||||
tracing = { workspace = true }
|
||||
|
|
|
@ -3,6 +3,7 @@ use std::{error::Error, path::PathBuf, time::Instant};
|
|||
use ariadne::Source;
|
||||
use clap::Parser;
|
||||
use edlang_codegen_mlir::linker::{link_binary, link_shared_lib};
|
||||
use edlang_lowering::{lower_module, IdGenerator};
|
||||
use edlang_session::{DebugInfo, OptLevel, Session};
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
|
@ -24,6 +25,9 @@ pub struct CompilerArgs {
|
|||
|
||||
#[arg(long, default_value_t = false)]
|
||||
ast: bool,
|
||||
|
||||
#[arg(long, default_value_t = false)]
|
||||
ir: bool,
|
||||
}
|
||||
|
||||
pub fn main() -> Result<(), Box<dyn Error>> {
|
||||
|
@ -81,6 +85,14 @@ pub fn main() -> Result<(), Box<dyn Error>> {
|
|||
return Ok(());
|
||||
}
|
||||
|
||||
let mut gen = IdGenerator::new(0);
|
||||
let ir = lower_module(&mut gen, &module);
|
||||
|
||||
if args.ir {
|
||||
println!("{:#?}", ir);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if args.mlir {
|
||||
println!("{}", edlang_codegen_mlir::compile_mlir(&session, &module)?);
|
||||
return Ok(());
|
||||
|
|
|
@ -1,59 +1,80 @@
|
|||
// Based on a cfg
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use edlang_span::Span;
|
||||
use smallvec::SmallVec;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct Body {
|
||||
pub locals: SmallVec<[Local; 4]>,
|
||||
pub blocks: SmallVec<[BasicBlock; 8]>,
|
||||
pub debug_info: SmallVec<[DebugInfo; 4]>,
|
||||
pub mod scalar_int;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ModuleBody {
|
||||
pub module_id: usize,
|
||||
pub functions: BTreeMap<DefId, Body>,
|
||||
pub modules: BTreeMap<DefId, Self>,
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
/// Definition id.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct DefId {
|
||||
pub module_id: usize,
|
||||
pub id: usize,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Body {
|
||||
pub def_id: DefId,
|
||||
pub is_pub: bool,
|
||||
pub is_extern: bool,
|
||||
pub ret_type: Option<TypeInfo>,
|
||||
pub locals: SmallVec<[Local; 4]>,
|
||||
pub blocks: SmallVec<[BasicBlock; 8]>,
|
||||
pub fn_span: Span,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct DebugInfo {
|
||||
pub id: usize,
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct BasicBlock {
|
||||
pub id: usize,
|
||||
pub statements: SmallVec<[Statement; 8]>,
|
||||
pub terminator: Terminator,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Local {
|
||||
pub id: usize,
|
||||
pub mutable: bool,
|
||||
pub debug_info: Option<usize>,
|
||||
pub ty: usize,
|
||||
pub span: Option<Span>,
|
||||
pub ty: TypeInfo,
|
||||
pub kind: LocalKind,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum LocalKind {
|
||||
Temp,
|
||||
Arg,
|
||||
ReturnPointer,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Statement {
|
||||
pub id: usize,
|
||||
pub debug_info: Option<usize>,
|
||||
pub span: Option<Span>,
|
||||
pub kind: StatementKind,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum StatementKind {
|
||||
Assign(Place, RValue),
|
||||
StorageLive(usize),
|
||||
StorageDead(usize),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Terminator {
|
||||
Target(usize),
|
||||
Return,
|
||||
|
@ -68,24 +89,23 @@ pub enum Terminator {
|
|||
Unreachable,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct TypeInfo {
|
||||
pub id: usize,
|
||||
pub debug_info: Option<usize>,
|
||||
pub span: Option<Span>,
|
||||
pub kind: TypeKind,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum TypeKind {
|
||||
Bool,
|
||||
Char,
|
||||
Int(IntTy),
|
||||
Uint(UintTy),
|
||||
Float(FloatTY),
|
||||
Float(FloatTy),
|
||||
FuncDef { name: String, args: Vec<Self> },
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum IntTy {
|
||||
I128,
|
||||
I64,
|
||||
|
@ -95,7 +115,7 @@ pub enum IntTy {
|
|||
Isize,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum UintTy {
|
||||
U128,
|
||||
U64,
|
||||
|
@ -105,57 +125,51 @@ pub enum UintTy {
|
|||
Usize,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub enum FloatTY {
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum FloatTy {
|
||||
F32,
|
||||
F64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ConstData {
|
||||
pub debug_info: Option<usize>,
|
||||
pub type_info: usize,
|
||||
pub span: Option<Span>,
|
||||
pub type_info: TypeInfo,
|
||||
pub kind: ConstKind,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum ConstKind {
|
||||
Value(ValueTree),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)]
|
||||
pub struct ScalarInt {
|
||||
pub data: u128,
|
||||
pub size: u8,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum ValueTree {
|
||||
Leaf(ScalarInt),
|
||||
Leaf(ConstValue),
|
||||
Branch(Vec<Self>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum RValue {
|
||||
Use(Operand),
|
||||
BinOp(BinOp, Operand, Operand),
|
||||
UnOp(UnOp, Operand),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Operand {
|
||||
Copy(Place),
|
||||
Move(Place),
|
||||
Constant(ConstData),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Place {
|
||||
pub local: usize,
|
||||
pub projection: SmallVec<[PlaceElem; 1]>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum PlaceElem {
|
||||
Deref,
|
||||
Field { field_idx: usize, type_info: usize },
|
||||
|
@ -204,11 +218,11 @@ impl TypeKind {
|
|||
}
|
||||
|
||||
pub fn get_f32() -> Self {
|
||||
Self::Float(FloatTY::F32)
|
||||
Self::Float(FloatTy::F32)
|
||||
}
|
||||
|
||||
pub fn get_f64() -> Self {
|
||||
Self::Float(FloatTY::F64)
|
||||
Self::Float(FloatTy::F64)
|
||||
}
|
||||
|
||||
pub fn get_bool() -> Self {
|
||||
|
@ -220,7 +234,7 @@ impl TypeKind {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum BinOp {
|
||||
Add,
|
||||
Sub,
|
||||
|
@ -241,8 +255,25 @@ pub enum BinOp {
|
|||
Offset,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum UnOp {
|
||||
Not,
|
||||
Neg,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum ConstValue {
|
||||
Bool(bool),
|
||||
I8(i8),
|
||||
I16(i16),
|
||||
I32(i32),
|
||||
I64(i64),
|
||||
I128(i128),
|
||||
U8(u8),
|
||||
U16(u16),
|
||||
U32(u32),
|
||||
U64(u64),
|
||||
U128(u128),
|
||||
F32(f32),
|
||||
F64(f64),
|
||||
}
|
||||
|
|
59
lib/edlang_ir/src/scalar_int.rs
Normal file
59
lib/edlang_ir/src/scalar_int.rs
Normal file
|
@ -0,0 +1,59 @@
|
|||
use std::num::NonZeroU8;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)]
|
||||
#[repr(packed(1))]
|
||||
pub struct ScalarInt {
|
||||
pub data: u128,
|
||||
/// Size in bytes
|
||||
pub size: NonZeroU8,
|
||||
}
|
||||
|
||||
impl ScalarInt {
|
||||
/// Size in bytes
|
||||
#[inline]
|
||||
pub fn size(self) -> u64 {
|
||||
self.size.get().into()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn try_from_int(i: impl Into<i128>, size_in_bytes: u64) -> Option<Self> {
|
||||
let i = i.into();
|
||||
// `into` performed sign extension, we have to truncate
|
||||
let truncated = truncate(size_in_bytes, i as u128);
|
||||
if sign_extend(size_in_bytes, truncated) as i128 == i {
|
||||
Some(Self {
|
||||
data: truncated,
|
||||
size: NonZeroU8::new(size_in_bytes as u8).unwrap(),
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn sign_extend(size: u64, value: u128) -> u128 {
|
||||
let size = size * 8;
|
||||
if size == 0 {
|
||||
// Truncated until nothing is left.
|
||||
return 0;
|
||||
}
|
||||
// Sign-extend it.
|
||||
let shift = 128 - size;
|
||||
// Shift the unsigned value to the left, then shift back to the right as signed
|
||||
// (essentially fills with sign bit on the left).
|
||||
(((value << shift) as i128) >> shift) as u128
|
||||
}
|
||||
|
||||
/// Truncates `value` to `self` bits.
|
||||
#[inline]
|
||||
pub fn truncate(size: u64, value: u128) -> u128 {
|
||||
let size = size * 8;
|
||||
if size == 0 {
|
||||
// Truncated until nothing is left.
|
||||
return 0;
|
||||
}
|
||||
let shift = 128 - size;
|
||||
// Truncate (shift left to drop out leftover values, shift right to fill with zeroes).
|
||||
(value << shift) >> shift
|
||||
}
|
|
@ -1,14 +1,350 @@
|
|||
pub fn add(left: usize, right: usize) -> usize {
|
||||
left + right
|
||||
use std::collections::HashMap;
|
||||
|
||||
use edlang_ast as ast;
|
||||
use edlang_ir as ir;
|
||||
use ir::{DefId, Local, Operand, Place, Statement, TypeInfo};
|
||||
|
||||
pub struct IdGenerator {
|
||||
pub current_id: usize,
|
||||
pub module_id: usize,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
impl IdGenerator {
|
||||
pub const fn new(module_id: usize) -> Self {
|
||||
Self {
|
||||
current_id: 0,
|
||||
module_id: 0,
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn it_works() {
|
||||
let result = add(2, 2);
|
||||
assert_eq!(result, 4);
|
||||
pub fn next_id(&mut self) -> usize {
|
||||
self.current_id += 1;
|
||||
self.current_id
|
||||
}
|
||||
|
||||
pub fn next_defid(&mut self) -> DefId {
|
||||
let id = self.next_id();
|
||||
|
||||
DefId {
|
||||
module_id: self.module_id,
|
||||
id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn lower_module(gen: &mut IdGenerator, module: &ast::Module) -> ir::ModuleBody {
|
||||
let mut body = ir::ModuleBody {
|
||||
module_id: gen.next_id(),
|
||||
functions: Default::default(),
|
||||
modules: Default::default(),
|
||||
span: module.span,
|
||||
};
|
||||
|
||||
let mut module_gen_id = IdGenerator::new(body.module_id);
|
||||
|
||||
for stmt in &module.contents {
|
||||
match stmt {
|
||||
ast::ModuleStatement::Function(func) => {
|
||||
let res = lower_function(&mut module_gen_id, func);
|
||||
body.functions.insert(res.def_id, res);
|
||||
}
|
||||
ast::ModuleStatement::Constant(_) => todo!(),
|
||||
ast::ModuleStatement::Struct(_) => todo!(),
|
||||
ast::ModuleStatement::Module(_) => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
body
|
||||
}
|
||||
|
||||
struct BodyBuilder {
|
||||
pub body: ir::Body,
|
||||
pub statements: Vec<ir::Statement>,
|
||||
pub locals: HashMap<String, usize>,
|
||||
pub ret_local: Option<usize>,
|
||||
}
|
||||
|
||||
fn lower_function(gen: &mut IdGenerator, func: &ast::Function) -> ir::Body {
|
||||
let body = ir::Body {
|
||||
def_id: gen.next_defid(),
|
||||
ret_type: func.return_type.as_ref().map(|x| lower_type(gen, x)),
|
||||
locals: Default::default(),
|
||||
blocks: Default::default(),
|
||||
fn_span: func.span,
|
||||
is_pub: func.is_public,
|
||||
is_extern: func.is_extern,
|
||||
};
|
||||
|
||||
let mut builder = BodyBuilder {
|
||||
body,
|
||||
statements: Vec::new(),
|
||||
locals: HashMap::new(),
|
||||
ret_local: None,
|
||||
};
|
||||
|
||||
// store args ret
|
||||
|
||||
if let Some(ret_type) = func.return_type.as_ref() {
|
||||
let ty = lower_type(gen, ret_type);
|
||||
|
||||
let local = Local {
|
||||
mutable: false,
|
||||
span: None,
|
||||
ty,
|
||||
kind: ir::LocalKind::ReturnPointer,
|
||||
};
|
||||
|
||||
builder.ret_local = Some(builder.body.locals.len());
|
||||
builder.body.locals.push(local);
|
||||
}
|
||||
|
||||
for arg in &func.params {
|
||||
let ty = lower_type(gen, &arg.arg_type);
|
||||
let local = Local {
|
||||
mutable: false,
|
||||
span: Some(arg.span),
|
||||
ty,
|
||||
kind: ir::LocalKind::Arg,
|
||||
};
|
||||
builder
|
||||
.locals
|
||||
.insert(arg.name.name.clone(), builder.locals.len());
|
||||
builder.body.locals.push(local);
|
||||
}
|
||||
|
||||
for stmt in &func.body.body {
|
||||
match stmt {
|
||||
ast::Statement::Let(info) => lower_let(gen, &mut builder, info),
|
||||
ast::Statement::Assign(_) => todo!(),
|
||||
ast::Statement::For(_) => todo!(),
|
||||
ast::Statement::While(_) => todo!(),
|
||||
ast::Statement::If(_) => todo!(),
|
||||
ast::Statement::Return(info) => lower_return(gen, &mut builder, info),
|
||||
ast::Statement::FnCall(_) => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
builder.body
|
||||
}
|
||||
|
||||
fn lower_let(gen: &mut IdGenerator, builder: &mut BodyBuilder, info: &ast::LetStmt) {
|
||||
let rvalue = lower_expr(builder, &info.value, Some(&lower_type(gen, &info.r#type)));
|
||||
|
||||
let local = ir::Local {
|
||||
mutable: info.is_mut,
|
||||
span: Some(info.span),
|
||||
ty: lower_type(gen, &info.r#type),
|
||||
kind: ir::LocalKind::Temp,
|
||||
};
|
||||
|
||||
let id = builder.body.locals.len();
|
||||
builder.locals.insert(info.name.name.clone(), id);
|
||||
builder.body.locals.push(local);
|
||||
|
||||
builder.statements.push(ir::Statement {
|
||||
span: Some(info.span),
|
||||
kind: ir::StatementKind::StorageLive(id),
|
||||
});
|
||||
builder.statements.push(ir::Statement {
|
||||
span: Some(info.span),
|
||||
kind: ir::StatementKind::Assign(
|
||||
Place {
|
||||
local: id,
|
||||
projection: Default::default(),
|
||||
},
|
||||
rvalue,
|
||||
),
|
||||
});
|
||||
}
|
||||
|
||||
fn lower_expr(
|
||||
builder: &mut BodyBuilder,
|
||||
info: &ast::Expression,
|
||||
type_hint: Option<&TypeInfo>,
|
||||
) -> ir::RValue {
|
||||
match info {
|
||||
ast::Expression::Value(info) => ir::RValue::Use(lower_value(builder, info, type_hint)),
|
||||
ast::Expression::FnCall(_) => todo!(),
|
||||
ast::Expression::Unary(_, _) => todo!(),
|
||||
ast::Expression::Binary(_, _, _) => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn lower_value(
|
||||
builder: &mut BodyBuilder,
|
||||
info: &ast::ValueExpr,
|
||||
type_hint: Option<&TypeInfo>,
|
||||
) -> Operand {
|
||||
match info {
|
||||
ast::ValueExpr::Bool { value, span } => ir::Operand::Constant(ir::ConstData {
|
||||
span: Some(*span),
|
||||
type_info: ir::TypeInfo {
|
||||
span: None,
|
||||
kind: ir::TypeKind::Bool,
|
||||
},
|
||||
kind: ir::ConstKind::Value(ir::ValueTree::Leaf(ir::ConstValue::Bool(*value))),
|
||||
}),
|
||||
ast::ValueExpr::Char { value, span } => ir::Operand::Constant(ir::ConstData {
|
||||
span: Some(*span),
|
||||
type_info: ir::TypeInfo {
|
||||
span: None,
|
||||
kind: ir::TypeKind::Char,
|
||||
},
|
||||
kind: ir::ConstKind::Value(ir::ValueTree::Leaf(ir::ConstValue::U32((*value) as u32))),
|
||||
}),
|
||||
ast::ValueExpr::Int { value, span } => {
|
||||
let (ty, val) = match type_hint {
|
||||
Some(type_hint) => match &type_hint.kind {
|
||||
ir::TypeKind::Int(type_hint) => match type_hint {
|
||||
ir::IntTy::I128 => (
|
||||
ir::TypeKind::Int(ir::IntTy::I128),
|
||||
ir::ConstValue::I128((*value) as i128),
|
||||
),
|
||||
ir::IntTy::I64 => (
|
||||
ir::TypeKind::Int(ir::IntTy::I64),
|
||||
ir::ConstValue::I64((*value) as i64),
|
||||
),
|
||||
ir::IntTy::I32 => (
|
||||
ir::TypeKind::Int(ir::IntTy::I32),
|
||||
ir::ConstValue::I32((*value) as i32),
|
||||
),
|
||||
ir::IntTy::I16 => (
|
||||
ir::TypeKind::Int(ir::IntTy::I16),
|
||||
ir::ConstValue::I16((*value) as i16),
|
||||
),
|
||||
ir::IntTy::I8 => (
|
||||
ir::TypeKind::Int(ir::IntTy::I8),
|
||||
ir::ConstValue::I8((*value) as i8),
|
||||
),
|
||||
ir::IntTy::Isize => todo!(),
|
||||
},
|
||||
ir::TypeKind::Uint(type_hint) => match type_hint {
|
||||
ir::UintTy::U128 => (
|
||||
ir::TypeKind::Uint(ir::UintTy::U128),
|
||||
ir::ConstValue::U128(*value),
|
||||
),
|
||||
ir::UintTy::U64 => (
|
||||
ir::TypeKind::Uint(ir::UintTy::U64),
|
||||
ir::ConstValue::U64((*value) as u64),
|
||||
),
|
||||
ir::UintTy::U32 => (
|
||||
ir::TypeKind::Uint(ir::UintTy::U32),
|
||||
ir::ConstValue::U32((*value) as u32),
|
||||
),
|
||||
ir::UintTy::U16 => (
|
||||
ir::TypeKind::Uint(ir::UintTy::U16),
|
||||
ir::ConstValue::U16((*value) as u16),
|
||||
),
|
||||
ir::UintTy::U8 => (
|
||||
ir::TypeKind::Uint(ir::UintTy::U8),
|
||||
ir::ConstValue::U8((*value) as u8),
|
||||
),
|
||||
_ => todo!(),
|
||||
},
|
||||
_ => unreachable!(),
|
||||
},
|
||||
None => todo!(),
|
||||
};
|
||||
|
||||
ir::Operand::Constant(ir::ConstData {
|
||||
span: Some(*span),
|
||||
type_info: ir::TypeInfo {
|
||||
span: None,
|
||||
kind: ty,
|
||||
},
|
||||
kind: ir::ConstKind::Value(ir::ValueTree::Leaf(val)),
|
||||
})
|
||||
}
|
||||
ast::ValueExpr::Float { value, span } => todo!(),
|
||||
ast::ValueExpr::Str { value, span } => todo!(),
|
||||
ast::ValueExpr::Path(info) => {
|
||||
// add deref info to path
|
||||
Operand::Move(lower_path(builder, info))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn lower_return(gen: &mut IdGenerator, builder: &mut BodyBuilder, info: &ast::ReturnStmt) {
|
||||
let ret_type = builder.body.ret_type.clone();
|
||||
if let Some(value) = &info.value {
|
||||
let rvalue = lower_expr(builder, value, ret_type.as_ref());
|
||||
let ret_local = builder.ret_local.unwrap();
|
||||
|
||||
builder.statements.push(Statement {
|
||||
span: Some(info.span),
|
||||
kind: ir::StatementKind::Assign(
|
||||
Place {
|
||||
local: ret_local,
|
||||
projection: Default::default(),
|
||||
},
|
||||
rvalue,
|
||||
),
|
||||
})
|
||||
}
|
||||
|
||||
let statements = std::mem::take(&mut builder.statements);
|
||||
|
||||
builder.body.blocks.push(ir::BasicBlock {
|
||||
id: builder.body.blocks.len(),
|
||||
statements: statements.into(),
|
||||
terminator: ir::Terminator::Return,
|
||||
});
|
||||
}
|
||||
|
||||
fn lower_path(builder: &mut BodyBuilder, info: &ast::PathExpr) -> ir::Place {
|
||||
let local = *builder
|
||||
.locals
|
||||
.get(&info.first.name)
|
||||
.expect("local not found");
|
||||
|
||||
Place {
|
||||
local,
|
||||
projection: Default::default(), // todo, field array deref
|
||||
}
|
||||
}
|
||||
|
||||
pub fn lower_type(gen: &mut IdGenerator, t: &ast::Type) -> ir::TypeInfo {
|
||||
match t.name.name.as_str() {
|
||||
"u8" => ir::TypeInfo {
|
||||
span: Some(t.span),
|
||||
kind: ir::TypeKind::Uint(ir::UintTy::U8),
|
||||
},
|
||||
"u16" => ir::TypeInfo {
|
||||
span: Some(t.span),
|
||||
kind: ir::TypeKind::Uint(ir::UintTy::U16),
|
||||
},
|
||||
"u32" => ir::TypeInfo {
|
||||
span: Some(t.span),
|
||||
kind: ir::TypeKind::Uint(ir::UintTy::U32),
|
||||
},
|
||||
"u64" => ir::TypeInfo {
|
||||
span: Some(t.span),
|
||||
kind: ir::TypeKind::Uint(ir::UintTy::U64),
|
||||
},
|
||||
"u128" => ir::TypeInfo {
|
||||
span: Some(t.span),
|
||||
kind: ir::TypeKind::Uint(ir::UintTy::U128),
|
||||
},
|
||||
"i8" => ir::TypeInfo {
|
||||
span: Some(t.span),
|
||||
kind: ir::TypeKind::Int(ir::IntTy::I8),
|
||||
},
|
||||
"i16" => ir::TypeInfo {
|
||||
span: Some(t.span),
|
||||
kind: ir::TypeKind::Int(ir::IntTy::I16),
|
||||
},
|
||||
"i32" => ir::TypeInfo {
|
||||
span: Some(t.span),
|
||||
kind: ir::TypeKind::Int(ir::IntTy::I32),
|
||||
},
|
||||
"i64" => ir::TypeInfo {
|
||||
span: Some(t.span),
|
||||
kind: ir::TypeKind::Int(ir::IntTy::I64),
|
||||
},
|
||||
"i128" => ir::TypeInfo {
|
||||
span: Some(t.span),
|
||||
kind: ir::TypeKind::Int(ir::IntTy::I128),
|
||||
},
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
||||
|
|
7
programs/simple.ed
Normal file
7
programs/simple.ed
Normal file
|
@ -0,0 +1,7 @@
|
|||
mod Main {
|
||||
|
||||
fn main() -> i32 {
|
||||
let x: i32 = 2;
|
||||
return x;
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue