mirror of
https://github.com/edg-l/edlang.git
synced 2024-11-23 00:18: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_ast",
|
||||||
"edlang_check",
|
"edlang_check",
|
||||||
"edlang_codegen_mlir",
|
"edlang_codegen_mlir",
|
||||||
|
"edlang_ir",
|
||||||
|
"edlang_lowering",
|
||||||
"edlang_parser",
|
"edlang_parser",
|
||||||
"edlang_session",
|
"edlang_session",
|
||||||
"tracing",
|
"tracing",
|
||||||
|
|
|
@ -17,6 +17,8 @@ color-eyre = "0.6.2"
|
||||||
edlang_ast = { version = "0.1.0", path = "../edlang_ast" }
|
edlang_ast = { version = "0.1.0", path = "../edlang_ast" }
|
||||||
edlang_check = { version = "0.1.0", path = "../edlang_check" }
|
edlang_check = { version = "0.1.0", path = "../edlang_check" }
|
||||||
edlang_codegen_mlir = { version = "0.1.0", path = "../edlang_codegen_mlir" }
|
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_parser = { version = "0.1.0", path = "../edlang_parser" }
|
||||||
edlang_session = { version = "0.1.0", path = "../edlang_session" }
|
edlang_session = { version = "0.1.0", path = "../edlang_session" }
|
||||||
tracing = { workspace = true }
|
tracing = { workspace = true }
|
||||||
|
|
|
@ -3,6 +3,7 @@ use std::{error::Error, path::PathBuf, time::Instant};
|
||||||
use ariadne::Source;
|
use ariadne::Source;
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use edlang_codegen_mlir::linker::{link_binary, link_shared_lib};
|
use edlang_codegen_mlir::linker::{link_binary, link_shared_lib};
|
||||||
|
use edlang_lowering::{lower_module, IdGenerator};
|
||||||
use edlang_session::{DebugInfo, OptLevel, Session};
|
use edlang_session::{DebugInfo, OptLevel, Session};
|
||||||
|
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
|
@ -24,6 +25,9 @@ pub struct CompilerArgs {
|
||||||
|
|
||||||
#[arg(long, default_value_t = false)]
|
#[arg(long, default_value_t = false)]
|
||||||
ast: bool,
|
ast: bool,
|
||||||
|
|
||||||
|
#[arg(long, default_value_t = false)]
|
||||||
|
ir: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn main() -> Result<(), Box<dyn Error>> {
|
pub fn main() -> Result<(), Box<dyn Error>> {
|
||||||
|
@ -81,6 +85,14 @@ pub fn main() -> Result<(), Box<dyn Error>> {
|
||||||
return Ok(());
|
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 {
|
if args.mlir {
|
||||||
println!("{}", edlang_codegen_mlir::compile_mlir(&session, &module)?);
|
println!("{}", edlang_codegen_mlir::compile_mlir(&session, &module)?);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
|
|
|
@ -1,59 +1,80 @@
|
||||||
// Based on a cfg
|
// Based on a cfg
|
||||||
|
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
use edlang_span::Span;
|
use edlang_span::Span;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
pub mod scalar_int;
|
||||||
pub struct Body {
|
|
||||||
pub locals: SmallVec<[Local; 4]>,
|
#[derive(Debug, Clone)]
|
||||||
pub blocks: SmallVec<[BasicBlock; 8]>,
|
pub struct ModuleBody {
|
||||||
pub debug_info: SmallVec<[DebugInfo; 4]>,
|
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 struct DebugInfo {
|
||||||
pub id: usize,
|
pub id: usize,
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct BasicBlock {
|
pub struct BasicBlock {
|
||||||
pub id: usize,
|
pub id: usize,
|
||||||
pub statements: SmallVec<[Statement; 8]>,
|
pub statements: SmallVec<[Statement; 8]>,
|
||||||
pub terminator: Terminator,
|
pub terminator: Terminator,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Local {
|
pub struct Local {
|
||||||
pub id: usize,
|
|
||||||
pub mutable: bool,
|
pub mutable: bool,
|
||||||
pub debug_info: Option<usize>,
|
pub span: Option<Span>,
|
||||||
pub ty: usize,
|
pub ty: TypeInfo,
|
||||||
pub kind: LocalKind,
|
pub kind: LocalKind,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub enum LocalKind {
|
pub enum LocalKind {
|
||||||
Temp,
|
Temp,
|
||||||
Arg,
|
Arg,
|
||||||
ReturnPointer,
|
ReturnPointer,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Statement {
|
pub struct Statement {
|
||||||
pub id: usize,
|
pub span: Option<Span>,
|
||||||
pub debug_info: Option<usize>,
|
|
||||||
pub kind: StatementKind,
|
pub kind: StatementKind,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum StatementKind {
|
pub enum StatementKind {
|
||||||
Assign(Place, RValue),
|
Assign(Place, RValue),
|
||||||
StorageLive(usize),
|
StorageLive(usize),
|
||||||
StorageDead(usize),
|
StorageDead(usize),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Terminator {
|
pub enum Terminator {
|
||||||
Target(usize),
|
Target(usize),
|
||||||
Return,
|
Return,
|
||||||
|
@ -68,24 +89,23 @@ pub enum Terminator {
|
||||||
Unreachable,
|
Unreachable,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct TypeInfo {
|
pub struct TypeInfo {
|
||||||
pub id: usize,
|
pub span: Option<Span>,
|
||||||
pub debug_info: Option<usize>,
|
|
||||||
pub kind: TypeKind,
|
pub kind: TypeKind,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum TypeKind {
|
pub enum TypeKind {
|
||||||
Bool,
|
Bool,
|
||||||
Char,
|
Char,
|
||||||
Int(IntTy),
|
Int(IntTy),
|
||||||
Uint(UintTy),
|
Uint(UintTy),
|
||||||
Float(FloatTY),
|
Float(FloatTy),
|
||||||
FuncDef { name: String, args: Vec<Self> },
|
FuncDef { name: String, args: Vec<Self> },
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum IntTy {
|
pub enum IntTy {
|
||||||
I128,
|
I128,
|
||||||
I64,
|
I64,
|
||||||
|
@ -95,7 +115,7 @@ pub enum IntTy {
|
||||||
Isize,
|
Isize,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum UintTy {
|
pub enum UintTy {
|
||||||
U128,
|
U128,
|
||||||
U64,
|
U64,
|
||||||
|
@ -105,57 +125,51 @@ pub enum UintTy {
|
||||||
Usize,
|
Usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum FloatTY {
|
pub enum FloatTy {
|
||||||
F32,
|
F32,
|
||||||
F64,
|
F64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ConstData {
|
pub struct ConstData {
|
||||||
pub debug_info: Option<usize>,
|
pub span: Option<Span>,
|
||||||
pub type_info: usize,
|
pub type_info: TypeInfo,
|
||||||
pub kind: ConstKind,
|
pub kind: ConstKind,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum ConstKind {
|
pub enum ConstKind {
|
||||||
Value(ValueTree),
|
Value(ValueTree),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ScalarInt {
|
|
||||||
pub data: u128,
|
|
||||||
pub size: u8,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
|
||||||
pub enum ValueTree {
|
pub enum ValueTree {
|
||||||
Leaf(ScalarInt),
|
Leaf(ConstValue),
|
||||||
Branch(Vec<Self>),
|
Branch(Vec<Self>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum RValue {
|
pub enum RValue {
|
||||||
Use(Operand),
|
Use(Operand),
|
||||||
BinOp(BinOp, Operand, Operand),
|
BinOp(BinOp, Operand, Operand),
|
||||||
UnOp(UnOp, Operand),
|
UnOp(UnOp, Operand),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Operand {
|
pub enum Operand {
|
||||||
Copy(Place),
|
Copy(Place),
|
||||||
Move(Place),
|
Move(Place),
|
||||||
Constant(ConstData),
|
Constant(ConstData),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Place {
|
pub struct Place {
|
||||||
pub local: usize,
|
pub local: usize,
|
||||||
pub projection: SmallVec<[PlaceElem; 1]>,
|
pub projection: SmallVec<[PlaceElem; 1]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub enum PlaceElem {
|
pub enum PlaceElem {
|
||||||
Deref,
|
Deref,
|
||||||
Field { field_idx: usize, type_info: usize },
|
Field { field_idx: usize, type_info: usize },
|
||||||
|
@ -204,11 +218,11 @@ impl TypeKind {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_f32() -> Self {
|
pub fn get_f32() -> Self {
|
||||||
Self::Float(FloatTY::F32)
|
Self::Float(FloatTy::F32)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_f64() -> Self {
|
pub fn get_f64() -> Self {
|
||||||
Self::Float(FloatTY::F64)
|
Self::Float(FloatTy::F64)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_bool() -> Self {
|
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 {
|
pub enum BinOp {
|
||||||
Add,
|
Add,
|
||||||
Sub,
|
Sub,
|
||||||
|
@ -241,8 +255,25 @@ pub enum BinOp {
|
||||||
Offset,
|
Offset,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub enum UnOp {
|
pub enum UnOp {
|
||||||
Not,
|
Not,
|
||||||
Neg,
|
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 {
|
use std::collections::HashMap;
|
||||||
left + right
|
|
||||||
|
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)]
|
impl IdGenerator {
|
||||||
mod tests {
|
pub const fn new(module_id: usize) -> Self {
|
||||||
use super::*;
|
Self {
|
||||||
|
current_id: 0,
|
||||||
|
module_id: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
pub fn next_id(&mut self) -> usize {
|
||||||
fn it_works() {
|
self.current_id += 1;
|
||||||
let result = add(2, 2);
|
self.current_id
|
||||||
assert_eq!(result, 4);
|
}
|
||||||
|
|
||||||
|
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