Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion compiler/hash-abi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ impl CallingConvention {
}
}

new_store_key!(pub FnAbiId);
new_store_key!(pub FnAbiId, derives = Debug);

/// Defines ABI specific information about a function.
///
Expand Down
2 changes: 1 addition & 1 deletion compiler/hash-codegen-vm/src/translation/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use hash_codegen::{
};
use hash_ir::IrCtx;
use hash_pipeline::settings::CompilerSettings;
use hash_vm::bytecode_builder::BytecodeBuilder;
use hash_vm::builder::BytecodeBuilder;

use crate::ctx::Ctx;

Expand Down
38 changes: 38 additions & 0 deletions compiler/hash-ir/src/ir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -839,6 +839,13 @@ impl BasicBlockData {
self.statements.is_empty()
&& self.terminator.as_ref().is_some_and(|t| t.kind == TerminatorKind::Unreachable)
}

/// Get the size of the [BasicBlockData].
///
/// This is the number of statements in the block plus the terminator.
pub fn size(&self) -> usize {
self.statements.len() + self.terminator.as_ref().map_or(0, |_| 1)
}
}

index_vec::define_index_type! {
Expand Down Expand Up @@ -1032,6 +1039,37 @@ impl Body {
pub fn source(&self) -> SourceId {
self.origin.source()
}

/// Get the size of the [Body].
pub fn size(&self) -> usize {
let stats = self.stats();
stats.statements as usize
}

/// Get the statistics of the [Body].
pub fn stats(&self) -> BodyStats {
let mut stats = BodyStats::default();

for block in self.basic_blocks.blocks.iter() {
stats.statements += block.size() as u32;
stats.terminators += block.terminator.as_ref().map_or(0, |_| 1) as u32;
stats.basic_blocks += 1;
}

stats
}
}

/// The statistics of the body.
#[derive(Default)]

pub struct BodyStats {
/// The number of basic blocks in the body.
pub basic_blocks: u32,
/// The number of statements in the body.
pub statements: u32,
/// The number of terminators in the body.
pub terminators: u32,
}

/// This struct contains additional metadata about the body that was lowered,
Expand Down
1 change: 1 addition & 0 deletions compiler/hash-vm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ doctest = false
hash-reporting = { workspace = true }
hash-source = { workspace = true }
hash-utils = { workspace = true }
hash-abi = { workspace = true }
63 changes: 63 additions & 0 deletions compiler/hash-vm/src/builder/func.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
//! Function builder related logic for the Hash VM.

use hash_abi::FnAbiId;
use hash_utils::index_vec::IndexVec;

use crate::bytecode::{Instruction, op::LabelOffset};

// Import FunctionBuilder if it's defined in another module
#[derive(Debug)]
pub struct FunctionBuilder {
/// The ABI of the function, this is used to generate
/// the correct instructions for the function, to read the
/// arguments and return values correctly.
pub abi: FnAbiId,

/// The body of the function. All instructions that make up the function
/// are stored within the body. However, labels are stored separately to
/// allow for easier management of jumps and branches.
pub body: IndexVec<LabelOffset, Instruction>,

/// The labels within the function body, these are used to
/// manage jumps and branches. The labels store the literal index
/// within the function body where the label is located. This is essentially
/// a mapping from instruction labels to their offsets:
///
/// 0 -=-> LabelOffset(0)
/// |
/// \ Instruction 0
/// Instruction 1
/// ...
/// 1---> LabelOffset(5):
/// |
/// \ Instruction 5
/// ...
pub labels: IndexVec<LabelOffset, LabelOffset>,

/// The current label counter, this is used to generate new labels.
label_counter: LabelOffset,
}

impl FunctionBuilder {
/// Create a new [FunctionBuilder] with the given ABI.
pub fn new(abi: FnAbiId) -> Self {
Self {
abi,
body: IndexVec::new(),
labels: IndexVec::new(),
label_counter: LabelOffset::new(0),
}
}

/// Generate a new label within the function.
pub fn new_label(&mut self) -> LabelOffset {
let label = self.label_counter;
self.label_counter = LabelOffset::new(label.get() + 1);
label
}

/// Add an instruction to the function body.
pub fn emit(&mut self, instruction: Instruction) {
self.body.push(instruction);
}
}
Loading
Loading