struct IrgenFunc<'i> {
return_type: Dtype,
bid_init: BlockId,
phinodes_init: Vec<Named<Dtype>>,
allocations: Vec<Named<Dtype>>,
blocks: BTreeMap<BlockId, Block>,
bid_counter: usize,
tempid_counter: usize,
typedefs: &'i HashMap<String, Dtype>,
structs: &'i HashMap<String, Option<Dtype>>,
symbol_table: Vec<HashMap<String, Operand>>,
}
Expand description
A C function being translated.
Fields§
§return_type: Dtype
return type of the function.
bid_init: BlockId
initial block id for the function, typically 0.
phinodes_init: Vec<Named<Dtype>>
arguments represented as initial phinodes. Order must be the same of that given in the C function.
allocations: Vec<Named<Dtype>>
local allocations.
blocks: BTreeMap<BlockId, Block>
Map from block id to basic blocks
bid_counter: usize
current block id. blocks
must have an entry for all ids less then this
tempid_counter: usize
current temporary id. Used to create temporary names in the IR for e.g,
typedefs: &'i HashMap<String, Dtype>
Usable definitions
structs: &'i HashMap<String, Option<Dtype>>
Usable structs
symbol_table: Vec<HashMap<String, Operand>>
Current symbol table. The initial symbol table has the global variables.
Implementations§
Source§impl IrgenFunc<'_>
impl IrgenFunc<'_>
Sourcefn alloc_tempid(&mut self) -> String
fn alloc_tempid(&mut self) -> String
Allocate a new temporary id.
Sourcefn insert_alloc(&mut self, alloc: Named<Dtype>) -> RegisterId
fn insert_alloc(&mut self, alloc: Named<Dtype>) -> RegisterId
Create a new allocation with type given by alloc
.
Sourcefn insert_block(&mut self, context: Context, exit: BlockExit)
fn insert_block(&mut self, context: Context, exit: BlockExit)
Insert a new block context
with exit instruction exit
.
§Panic
Panics if another block with the same bid as context
already existed.
Sourcefn enter_scope(&mut self)
fn enter_scope(&mut self)
Enter a scope and create a new symbol table entry, i.e, we are at a {
in the function.
Sourcefn exit_scope(&mut self)
fn exit_scope(&mut self)
Exit a scope and remove the a oldest symbol table entry. i.e, we are at a }
in the
function.
§Panic
Panics if there are no scopes to exit, i.e, the function has a unmatched }
.
Sourcefn insert_symbol_table_entry(
&mut self,
var: String,
value: Operand,
) -> Result<(), IrgenErrorMessage>
fn insert_symbol_table_entry( &mut self, var: String, value: Operand, ) -> Result<(), IrgenErrorMessage>
Inserts var
with value
to the current symbol table.
Returns Ok() if the current scope has no previously-stored entry for a given variable.
Sourcefn translate_stmt(
&mut self,
stmt: &Statement,
context: &mut Context,
bid_continue: Option<BlockId>,
bid_break: Option<BlockId>,
) -> Result<(), IrgenError>
fn translate_stmt( &mut self, stmt: &Statement, context: &mut Context, bid_continue: Option<BlockId>, bid_break: Option<BlockId>, ) -> Result<(), IrgenError>
Transalte a C statement stmt
under the current block context
, with continue
block
bid_continue
and break block bid_break
.
Sourcefn translate_parameter_decl(
&mut self,
signature: &FunctionSignature,
bid_init: BlockId,
name_of_params: &[String],
context: &mut Context,
) -> Result<(), IrgenErrorMessage>
fn translate_parameter_decl( &mut self, signature: &FunctionSignature, bid_init: BlockId, name_of_params: &[String], context: &mut Context, ) -> Result<(), IrgenErrorMessage>
Translate initial parameter declarations of the functions to IR.
For example, given the following C function from foo.c
:
int foo(int x, int y, int z) {
if (x == y) {
return y;
} else {
return z;
}
}
The IR before this function looks roughly as follows:
fun i32 @foo (i32, i32, i32) {
init:
bid: b0
allocations:
block b0:
%b0:p0:i32:x
%b0:p1:i32:y
%b0:p2:i32:z
...
With the following arguments :
signature = FunctionSignature { ret: ir::INT, params: vec![ir::INT, ir::INT, ir::INT] }
bid_init = 0
name_of_params = ["x", "y", "z"]
context = // omitted
The resulting IR after this function should be roughly follows :
fun i32 @foo (i32, i32, i32) {
init:
bid: b0
allocations:
%l0:i32:x
%l1:i32:y
%l2:i32:z
block b0:
%b0:p0:i32:x
%b0:p1:i32:y
%b0:p2:i32:z
%b0:i0:unit = store %b0:p0:i32 %l0:i32*
%b0:i1:unit = store %b0:p1:i32 %l1:i32*
%b0:i2:unit = store %b0:p2:i32 %l2:i32*
...
In particular, note that it is added to the local allocation list and store them to the initial phinodes.
Note that the resulting IR is a solution. If you can think of a better way to translate parameters, feel free to do so.
Auto Trait Implementations§
impl<'i> Freeze for IrgenFunc<'i>
impl<'i> RefUnwindSafe for IrgenFunc<'i>
impl<'i> Send for IrgenFunc<'i>
impl<'i> Sync for IrgenFunc<'i>
impl<'i> Unpin for IrgenFunc<'i>
impl<'i> UnwindSafe for IrgenFunc<'i>
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read more