Path: blob/main/cranelift/interpreter/src/environment.rs
1692 views
//! Implements the function environment (e.g. a name-to-function mapping) for interpretation.1use cranelift_codegen::ir::{FuncRef, Function};2use cranelift_entity::{PrimaryMap, entity_impl};3use std::collections::HashMap;45/// A function store contains all of the functions that are accessible to an interpreter.6#[derive(Default, Clone)]7pub struct FunctionStore<'a> {8functions: PrimaryMap<FuncIndex, &'a Function>,9function_names: HashMap<String, FuncIndex>,10}1112/// An opaque reference to a [`Function`] stored in the [FunctionStore].13#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]14pub struct FuncIndex(u32);15entity_impl!(FuncIndex, "fn");1617/// This is a helpful conversion for instantiating a store from a single [Function].18impl<'a> From<&'a Function> for FunctionStore<'a> {19fn from(function: &'a Function) -> Self {20let mut store = FunctionStore::default();21store.add(function.name.to_string(), function);22store23}24}2526impl<'a> FunctionStore<'a> {27/// Add a function by name.28pub fn add(&mut self, name: String, function: &'a Function) {29assert!(!self.function_names.contains_key(&name));30let index = self.functions.push(function);31self.function_names.insert(name, index);32}3334/// Retrieve the index of a function in the function store by its `name`.35pub fn index_of(&self, name: &str) -> Option<FuncIndex> {36self.function_names.get(name).cloned()37}3839/// Retrieve a function by its index in the function store.40pub fn get_by_index(&self, index: FuncIndex) -> Option<&'a Function> {41self.functions.get(index).cloned()42}4344/// Retrieve a function by its name.45pub fn get_by_name(&self, name: &str) -> Option<&'a Function> {46let index = self.index_of(name)?;47self.get_by_index(index)48}4950/// Retrieve a function from a [FuncRef] within a [Function]. TODO this should be optimized, if possible, as51/// currently it retrieves the function name as a string and performs string matching.52pub fn get_from_func_ref(53&self,54func_ref: FuncRef,55function: &Function,56) -> Option<&'a Function> {57self.get_by_name(&get_function_name(func_ref, function))58}59}6061/// Retrieve a function name from a [FuncRef] within a [Function]. TODO this should be optimized, if possible, as62/// currently it retrieves the function name as a string and performs string matching.63fn get_function_name(func_ref: FuncRef, function: &Function) -> String {64function65.stencil66.dfg67.ext_funcs68.get(func_ref)69.expect("function to exist")70.name71.display(Some(&function.params))72.to_string()73}7475#[cfg(test)]76mod tests {77use super::*;78use cranelift_codegen::ir::{Signature, UserFuncName};79use cranelift_codegen::isa::CallConv;8081#[test]82fn addition() {83let mut env = FunctionStore::default();84let a = "a";85let f = Function::new();8687env.add(a.to_string(), &f);88assert!(env.get_by_name(a).is_some());89}9091#[test]92fn nonexistence() {93let env = FunctionStore::default();94assert!(env.get_by_name("a").is_none());95}9697#[test]98fn from() {99let name = UserFuncName::testcase("test");100let signature = Signature::new(CallConv::Fast);101let func = &Function::with_name_signature(name, signature);102let env: FunctionStore = func.into();103assert_eq!(env.index_of("%test"), Some(FuncIndex::from_u32(0)));104}105}106107108