Add necessary codegen for easy.reid
This commit is contained in:
parent
e00d9afc7b
commit
6448b0c438
@ -362,7 +362,7 @@ impl Parse for Block {
|
|||||||
statements.push(BlockLevelStatement::Expression(e));
|
statements.push(BlockLevelStatement::Expression(e));
|
||||||
}
|
}
|
||||||
let statement = stream.parse()?;
|
let statement = stream.parse()?;
|
||||||
if let BlockLevelStatement::Return((r_type, e)) = &statement {
|
if let BlockLevelStatement::Return(r_type, e) = &statement {
|
||||||
match r_type {
|
match r_type {
|
||||||
ReturnType::Hard => {
|
ReturnType::Hard => {
|
||||||
return_stmt = Some((*r_type, e.clone()));
|
return_stmt = Some((*r_type, e.clone()));
|
||||||
@ -387,7 +387,7 @@ pub enum BlockLevelStatement {
|
|||||||
Let(LetStatement),
|
Let(LetStatement),
|
||||||
Import(ImportStatement),
|
Import(ImportStatement),
|
||||||
Expression(Expression),
|
Expression(Expression),
|
||||||
Return((ReturnType, Expression)),
|
Return(ReturnType, Expression),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for BlockLevelStatement {
|
impl Parse for BlockLevelStatement {
|
||||||
@ -400,14 +400,14 @@ impl Parse for BlockLevelStatement {
|
|||||||
stream.next();
|
stream.next();
|
||||||
let exp = stream.parse()?;
|
let exp = stream.parse()?;
|
||||||
stream.expect(Token::Semi)?;
|
stream.expect(Token::Semi)?;
|
||||||
Stmt::Return((ReturnType::Hard, exp))
|
Stmt::Return(ReturnType::Hard, exp)
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
if let Ok(e) = stream.parse() {
|
if let Ok(e) = stream.parse() {
|
||||||
if stream.expect(Token::Semi).is_ok() {
|
if stream.expect(Token::Semi).is_ok() {
|
||||||
Stmt::Expression(e)
|
Stmt::Expression(e)
|
||||||
} else {
|
} else {
|
||||||
Stmt::Return((ReturnType::Soft, e))
|
Stmt::Return(ReturnType::Soft, e)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Err(stream.expected_err("expression")?)?
|
Err(stream.expected_err("expression")?)?
|
||||||
|
@ -12,6 +12,50 @@ fn into_cstring<T: Into<String>>(value: T) -> CString {
|
|||||||
unsafe { CString::from_vec_with_nul_unchecked((string + "\0").into_bytes()) }
|
unsafe { CString::from_vec_with_nul_unchecked((string + "\0").into_bytes()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(thiserror::Error, Debug)]
|
||||||
|
pub enum Error {
|
||||||
|
#[error("Type mismatch: {0:?} vs {1:?}")]
|
||||||
|
TypeMismatch(IRType, IRType),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
|
pub enum IRType {
|
||||||
|
I32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IRType {
|
||||||
|
fn in_context(&self, context: &mut IRContext) -> *mut LLVMType {
|
||||||
|
use IRType::*;
|
||||||
|
unsafe {
|
||||||
|
return match self {
|
||||||
|
I32 => LLVMInt32TypeInContext(context.context),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct IRValue(pub IRType, *mut LLVMValue);
|
||||||
|
|
||||||
|
impl IRValue {
|
||||||
|
pub fn from_literal(literal: &ast::Literal, block: &mut IRBlock) -> Self {
|
||||||
|
use ast::Literal;
|
||||||
|
match literal {
|
||||||
|
Literal::I32(v) => {
|
||||||
|
let ir_type = IRType::I32;
|
||||||
|
unsafe {
|
||||||
|
let ir_value = LLVMConstInt(
|
||||||
|
ir_type.in_context(block.function.module.context),
|
||||||
|
mem::transmute(*v as i64),
|
||||||
|
1,
|
||||||
|
);
|
||||||
|
return IRValue(ir_type, ir_value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct IRContext {
|
pub struct IRContext {
|
||||||
context: *mut LLVMContext,
|
context: *mut LLVMContext,
|
||||||
builder: *mut LLVMBuilder,
|
builder: *mut LLVMBuilder,
|
||||||
@ -71,22 +115,6 @@ impl<'a> Drop for IRModule<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub enum IRType {
|
|
||||||
I32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl IRType {
|
|
||||||
fn in_context(&self, context: &mut IRContext) -> *mut LLVMType {
|
|
||||||
use IRType::*;
|
|
||||||
unsafe {
|
|
||||||
return match self {
|
|
||||||
I32 => LLVMInt32TypeInContext(context.context),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct IRFunction<'a, 'b> {
|
pub struct IRFunction<'a, 'b> {
|
||||||
module: &'b mut IRModule<'a>,
|
module: &'b mut IRModule<'a>,
|
||||||
/// The actual function
|
/// The actual function
|
||||||
@ -132,10 +160,54 @@ impl<'a, 'b, 'c> IRBlock<'a, 'b, 'c> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn add(
|
||||||
|
&mut self,
|
||||||
|
IRValue(lhs_t, lhs_v): IRValue,
|
||||||
|
IRValue(rhs_t, rhs_v): IRValue,
|
||||||
|
) -> Result<IRValue, Error> {
|
||||||
|
unsafe {
|
||||||
|
if lhs_t == rhs_t {
|
||||||
|
Ok(IRValue(
|
||||||
|
lhs_t,
|
||||||
|
LLVMBuildAdd(
|
||||||
|
self.function.module.context.builder,
|
||||||
|
lhs_v,
|
||||||
|
rhs_v,
|
||||||
|
c"tmpadd".as_ptr(),
|
||||||
|
),
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
Err(Error::TypeMismatch(lhs_t, rhs_t))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mult(
|
||||||
|
&mut self,
|
||||||
|
IRValue(lhs_t, lhs_v): IRValue,
|
||||||
|
IRValue(rhs_t, rhs_v): IRValue,
|
||||||
|
) -> Result<IRValue, Error> {
|
||||||
|
unsafe {
|
||||||
|
if lhs_t == rhs_t {
|
||||||
|
Ok(IRValue(
|
||||||
|
lhs_t,
|
||||||
|
LLVMBuildMul(
|
||||||
|
self.function.module.context.builder,
|
||||||
|
lhs_v,
|
||||||
|
rhs_v,
|
||||||
|
c"tmpadd".as_ptr(),
|
||||||
|
),
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
Err(Error::TypeMismatch(lhs_t, rhs_t))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn add_return(self, value: Option<IRValue>) {
|
pub fn add_return(self, value: Option<IRValue>) {
|
||||||
unsafe {
|
unsafe {
|
||||||
if let Some(value) = value {
|
if let Some(IRValue(_, value)) = value {
|
||||||
LLVMBuildRet(self.function.module.context.builder, value.ir_value);
|
LLVMBuildRet(self.function.module.context.builder, value);
|
||||||
} else {
|
} else {
|
||||||
LLVMBuildRetVoid(self.function.module.context.builder);
|
LLVMBuildRetVoid(self.function.module.context.builder);
|
||||||
}
|
}
|
||||||
@ -150,28 +222,3 @@ impl<'a, 'b, 'c> Drop for IRBlock<'a, 'b, 'c> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct IRValue {
|
|
||||||
pub ir_type: IRType,
|
|
||||||
ir_value: *mut LLVMValue,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl IRValue {
|
|
||||||
pub fn from_literal(literal: &ast::Literal, block: &mut IRBlock) -> Self {
|
|
||||||
use ast::Literal;
|
|
||||||
match literal {
|
|
||||||
Literal::I32(v) => {
|
|
||||||
let ir_type = IRType::I32;
|
|
||||||
unsafe {
|
|
||||||
let ir_value = LLVMConstInt(
|
|
||||||
ir_type.in_context(block.function.module.context),
|
|
||||||
mem::transmute(*v as i64),
|
|
||||||
1,
|
|
||||||
);
|
|
||||||
return IRValue { ir_type, ir_value };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -2,16 +2,16 @@ mod llvm;
|
|||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use llvm::{IRBlock, IRContext, IRFunction, IRModule, IRValue};
|
use llvm::{Error, IRBlock, IRContext, IRFunction, IRModule, IRValue};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ast::{Block, Expression, ExpressionKind, FunctionDefinition},
|
ast::{
|
||||||
|
BinaryOperator, Block, BlockLevelStatement, Expression, ExpressionKind, FunctionDefinition,
|
||||||
|
LetStatement, ReturnType,
|
||||||
|
},
|
||||||
TopLevelStatement,
|
TopLevelStatement,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(thiserror::Error, Debug)]
|
|
||||||
pub enum Error {}
|
|
||||||
|
|
||||||
pub fn form_context() -> IRContext {
|
pub fn form_context() -> IRContext {
|
||||||
IRContext::new()
|
IRContext::new()
|
||||||
}
|
}
|
||||||
@ -49,6 +49,10 @@ impl FunctionDefinition {
|
|||||||
|
|
||||||
impl Block {
|
impl Block {
|
||||||
fn codegen(&self, mut scope: Scope) {
|
fn codegen(&self, mut scope: Scope) {
|
||||||
|
for statement in &self.0 {
|
||||||
|
statement.codegen(&mut scope);
|
||||||
|
}
|
||||||
|
|
||||||
if let Some((_, return_exp)) = &self.1 {
|
if let Some((_, return_exp)) = &self.1 {
|
||||||
let value = return_exp.codegen(&mut scope);
|
let value = return_exp.codegen(&mut scope);
|
||||||
scope.block.add_return(Some(value));
|
scope.block.add_return(Some(value));
|
||||||
@ -56,6 +60,23 @@ impl Block {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl BlockLevelStatement {
|
||||||
|
fn codegen(&self, scope: &mut Scope) {
|
||||||
|
use BlockLevelStatement::*;
|
||||||
|
match self {
|
||||||
|
Expression(exp) | Return(ReturnType::Soft, exp) => {
|
||||||
|
exp.codegen(scope);
|
||||||
|
}
|
||||||
|
Let(LetStatement(name, exp, _)) => {
|
||||||
|
let val = exp.codegen(scope);
|
||||||
|
scope.data.insert(name, val);
|
||||||
|
}
|
||||||
|
Return(ReturnType::Hard, _) => panic!("hard returns here should not be possible.."),
|
||||||
|
Import(_) => panic!("block level import not supported"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Expression {
|
impl Expression {
|
||||||
fn codegen(&self, scope: &mut Scope) -> IRValue {
|
fn codegen(&self, scope: &mut Scope) -> IRValue {
|
||||||
let Expression(kind, _) = self;
|
let Expression(kind, _) = self;
|
||||||
@ -64,6 +85,16 @@ impl Expression {
|
|||||||
match kind {
|
match kind {
|
||||||
Literal(lit) => IRValue::from_literal(lit, &mut scope.block),
|
Literal(lit) => IRValue::from_literal(lit, &mut scope.block),
|
||||||
VariableName(v) => scope.data.fetch(v),
|
VariableName(v) => scope.data.fetch(v),
|
||||||
|
Binop(op, lhs, rhs) => {
|
||||||
|
let lhs = lhs.codegen(scope);
|
||||||
|
let rhs = rhs.codegen(scope);
|
||||||
|
use crate::ast::BinaryOperator::*;
|
||||||
|
match op {
|
||||||
|
Add => scope.block.add(lhs, rhs).unwrap(),
|
||||||
|
Mult => scope.block.mult(lhs, rhs).unwrap(),
|
||||||
|
_ => panic!("operator not supported: {:?}", op),
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => panic!("expression type not supported"),
|
_ => panic!("expression type not supported"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user