Skip to content

Commit

Permalink
test():addtest-for-cov
Browse files Browse the repository at this point in the history
  • Loading branch information
fscdc committed Feb 23, 2024
2 parents 9bdc8fe + f547674 commit 0ae143e
Show file tree
Hide file tree
Showing 9 changed files with 180 additions and 7 deletions.
83 changes: 83 additions & 0 deletions src/ir.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,86 @@
//! # Intermediate Representation for OrzCC
//!
//! This module contains the intermediate representation (IR) for the OrzCC.
//!
//! The OrzIR is a low-level representation of programming languages. It is inspired by
//! the LLVM IR, Koopa and Cranelift IRs. The IR is designed to preserve the semantics and
//! structure of higher-level programming languages, while being simple and efficient to
//! manipulate and optimize.
//!
//! The IR has a hierarchical structure, with a module at the top level, which contains functions,
//! globals, and types. Each function contains a data flow graph (DFG) and a layout. The DFG
//! contains the instructions and the layout contains the sequence of basic blocks and instructions.
//!
//! ## Global Slots
//!
//! The [global slots](values::GlobalSlot) are used to store global variables and constants.
//! The global slots are allocated in the data segment of the program, and are used to store the
//! initial values of the global variables and constants.
//!
//! The format to define a global slot is:
//! ```orzir
//! global @var_name = <type> <initial_value>
//! const @const_name = <type> <initial_value>
//! ```
//!
//! ## Functions
//!
//! The [functions](entities::FunctionData) are the main units of computation in the OrzIR.
//!
//! The format to define a function is:
//! ```orzir
//! fn @function_name(<arg0_type>, <arg1_type>, ...) -> <return_type> {
//! # body (blocks)
//! }
//! ```
//!
//! Also, for functions with external linkage, the format is:
//! ```orzir
//! decl fn @function_name(<arg0_type>, <arg1_type>, ...) -> <return_type>
//! ```
//!
//! ## Blocks
//!
//! The [blocks](entities::BlockData) are the basic units of control flow in the OrzIR.
//! The type of a block is [`label`](types::TypeKind::Label), and the name of a block starts with
//! a `^` followed by a sequence of alphanumeric characters.
//!
//! In the OrzIR, phi nodes are not used for SSA, instead, block parameters are used to represent
//! the incoming values from the predecessors of the block. This is the same as MLIR, Koopa, and
//! Cranelift IRs.
//!
//! The format to define a block is:
//! ```orzir
//! ^block_name(<arg0_type> <arg0_name>, <arg1_type> <arg1_name>, ...):
//! # instructions
//! ```
//!
//! ## Instructions
//!
//! The instructions in OrzIR follows several formats.
//! ```orzir
//! # for binary and unary operations.
//! <result> = <op> <operand0>, <operand1>, ...
//!
//! # for load, cast and getelementptr instructions.
//! <result> = <op> <type>, <operand0>, <operand1>, ...
//!
//! # for store and return instructions.
//! <op> <operand0>, <operand1>, ...
//!
//! jump ^block_name(<arg0>, <arg1>, ...)
//!
//! branch <cond>, ^then(<arg0>, ...), ^else(<arg0>, ...)
//!
//! # note that the result is optional
//! <result = >call <return_type> <function_value>(<arg0>, <arg1>, ...)
//! ```
//!
//! ---
//!
//! For more details, please refer to the documentation of each module and the source code.
//!
pub mod builder;
pub mod entities;
pub mod exec;
Expand Down
14 changes: 14 additions & 0 deletions src/ir/frontend/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,12 @@ pub enum AstNode {
/// Local identifier
LocalIdent(String),

/// Zero
Zero,

/// Undef
Undef,

/// A typed operand
Operand(Operand),

Expand Down Expand Up @@ -120,6 +126,14 @@ impl AstNode {
pub fn new_boxed_bytes(bytes: Vec<u8>) -> AstNodeBox {
Box::new(AstNode::Bytes(bytes))
}

pub fn new_boxed_zero() -> AstNodeBox {
Box::new(AstNode::Zero)
}

pub fn new_boxed_undef() -> AstNodeBox {
Box::new(AstNode::Undef)
}
}

#[derive(Debug)]
Expand Down
24 changes: 23 additions & 1 deletion src/ir/frontend/convert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,27 @@ impl Ast {
.bytes(ty.clone(), bytes.clone())
.map_err(|e| e.into())
} else {
panic!("Type not found for local constant")
panic!("type not found for local constant")
}
}
AstNode::Zero => {
if let Some(ref ty) = operand.ty {
dfg_mut!(ctx.module, function)
.builder()
.zero(ty.clone())
.map_err(|e| e.into())
} else {
panic!("type not found for local zero value")
}
}
AstNode::Undef => {
if let Some(ref ty) = operand.ty {
dfg_mut!(ctx.module, function)
.builder()
.undef(ty.clone())
.map_err(|e| e.into())
} else {
panic!("type not found for local undef value")
}
}
_ => unreachable!(),
Expand Down Expand Up @@ -402,6 +422,8 @@ impl Ast {
module.builder().struct_(ty, values)?
}
AstNode::Bytes(bytes) => module.builder().bytes(ty, bytes.clone())?,
AstNode::Zero => module.builder().zero(ty)?,
AstNode::Undef => module.builder().undef(ty)?,
_ => unreachable!(),
};
Ok(value)
Expand Down
14 changes: 14 additions & 0 deletions src/ir/frontend/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,10 +182,22 @@ where
TokenKind::LeftBracket => self.parse_array(),
TokenKind::LeftBrace => self.parse_struct(),
TokenKind::Bytes(_) => self.parse_bytes(),
TokenKind::Keyword(KeywordKind::Zero) => self.parse_zero(),
TokenKind::Keyword(KeywordKind::Undef) => self.parse_undef(),
_ => Err(self.unexpected_token()),
}
}

fn parse_zero(&mut self) -> Result<AstNodeBox, ParseError> {
self.expect(TokenKind::Keyword(KeywordKind::Zero))?;
Ok(AstNode::new_boxed_zero())
}

fn parse_undef(&mut self) -> Result<AstNodeBox, ParseError> {
self.expect(TokenKind::Keyword(KeywordKind::Undef))?;
Ok(AstNode::new_boxed_undef())
}

fn parse_bytes(&mut self) -> Result<AstNodeBox, ParseError> {
let token = self.next_token()?;
if let TokenKind::Bytes(ref bytes) = token.kind {
Expand Down Expand Up @@ -500,6 +512,8 @@ where
TokenKind::GlobalIdent(ref name) => AstNode::new_boxed_global_ident(name.clone()),
TokenKind::LocalIdent(ref name) => AstNode::new_boxed_local_ident(name.clone()),
TokenKind::Bytes(ref bytes) => AstNode::new_boxed_bytes(bytes.clone()),
TokenKind::Keyword(KeywordKind::Zero) => AstNode::new_boxed_zero(),
TokenKind::Keyword(KeywordKind::Undef) => AstNode::new_boxed_undef(),
_ => return Err(self.unexpected_token()),
};
self.consume();
Expand Down
2 changes: 1 addition & 1 deletion src/ir/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ impl Module {

/// Allocator of ids.
///
/// This is the allocator of [`Value`](super::values::Value), [`Block`](super::values::Block), and
/// This is the allocator of [`Value`], [`Block`], and
/// other entities that need an id to identify them uniquely in the IR.
pub struct IdAllocator {
counter: usize,
Expand Down
8 changes: 4 additions & 4 deletions src/ir/values.rs
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@ impl Store {

/// Load instruction internals.
///
/// The type of the loaded value is available in [`ValueData`](super::entities::ValueData).
/// The type of the loaded value is available in [`ValueData`].
pub struct Load {
ptr: Value,
}
Expand All @@ -361,7 +361,7 @@ impl Load {

/// Type cast
///
/// Perform bitcast operation, the type is available in [`ValueData`](super::entities::ValueData).
/// Perform bitcast operation, the type is available in [`ValueData`].
pub struct Cast {
val: Value,
}
Expand Down Expand Up @@ -398,7 +398,7 @@ impl Alloc {
/// A global memory slot.
///
/// The initial value of the global should be a constant.
/// The type of the global is available in [`ValueData`](super::entities::ValueData).
/// The type of the global is available in [`ValueData`].
pub struct GlobalSlot {
/// The initial value of the global
///
Expand Down Expand Up @@ -509,7 +509,7 @@ impl Return {

/// A function call.
///
/// The function type can be inferred from the args and the [`ValueData`](super::entities::ValueData).
/// The function type can be inferred from the args and the [`ValueData`].
pub struct Call {
/// The callee can be a function or a function pointer.
callee: Value,
Expand Down
28 changes: 28 additions & 0 deletions tests/ir_cases/08_zero.orzir
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@

global @x = i32 zero
const @y = i32 0x20202020
type $z = { i32, float }
global @array = [ i32; 3 ] zero
global @arrarr = [ [float ;3]; 4] zero
type $struct = { i32, [float; 3] }
global @s = [$struct ; 2] zero

fn @function(i32) -> i32 {

^entry(i32 %0):
%ptr0 = getelemptr [$struct;2], @s, i32 zero, i32 0x00
%val0 = load i32, %ptr0
%cond = icmp.sle i32 %0, i32 1234
br i1 %cond, ^ret(i32 0x01, float 0x123), ^else(i32 %0)

^else(i32 %1):
%2 = sub i32 %1, i32 0x01
%3 = sub i32 %1, i32 0x02
%4 = call i32 @function(i32 %2)
%5 = call i32 @function(i32 %3)
%6 = add i32 %4, i32 %5
jump ^ret(i32 %6, float 0x1234)

^ret(i32 %result, float %123):
ret i32 %result
}
File renamed without changes.
14 changes: 13 additions & 1 deletion tests/test_frontend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,18 @@ fn test_07() {

#[test]
fn test_08() {
let ir = include_str!("ir_cases/08_extratest.orzir");
let ir = include_str!("ir_cases/08_zero.orzir");
test_ir(ir);
}

#[test]
fn test_08() {
let ir = include_str!("ir_cases/08_zero.orzir");
test_ir(ir);
}

#[test]
fn test_09() {
let ir = include_str!("ir_cases/09_extratest.orzir");
test_ir(ir);
}

0 comments on commit 0ae143e

Please sign in to comment.