sway_ir/
context.rs

1//! The main handle to an IR instance.
2//!
3//! [`Context`] contains several
4//! [slotmap](https://github.com/orlp/slotmap) collections to maintain the
5//! IR ECS.
6//!
7//! It is passed around as a mutable reference to many of the Sway-IR APIs.
8
9use rustc_hash::FxHashMap;
10use slotmap::{DefaultKey, SlotMap};
11use sway_features::ExperimentalFeatures;
12use sway_types::SourceEngine;
13
14use crate::{
15    block::BlockContent,
16    function::FunctionContent,
17    metadata::Metadatum,
18    module::{Kind, ModuleContent, ModuleIterator},
19    value::ValueContent,
20    variable::LocalVarContent,
21    Constant, ConstantContent, GlobalVarContent, StorageKeyContent, Type, TypeContent,
22};
23
24const PANIC_REVERT_CODE_LOWER_BOUND: u64 = 0xffff_ffff_0000_0000;
25
26/// The main IR context handle.
27///
28/// Every module, function, block and value is stored here.  Some aggregate metadata is also
29/// managed by the context.
30pub struct Context<'eng> {
31    pub source_engine: &'eng SourceEngine,
32
33    pub(crate) modules: SlotMap<DefaultKey, ModuleContent>,
34    pub(crate) functions: SlotMap<DefaultKey, FunctionContent>,
35    pub(crate) blocks: SlotMap<DefaultKey, BlockContent>,
36    pub(crate) values: SlotMap<DefaultKey, ValueContent>,
37    pub(crate) local_vars: SlotMap<DefaultKey, LocalVarContent>,
38    pub(crate) global_vars: SlotMap<DefaultKey, GlobalVarContent>,
39    pub(crate) storage_keys: SlotMap<DefaultKey, StorageKeyContent>,
40    pub(crate) types: SlotMap<DefaultKey, TypeContent>,
41    pub(crate) type_map: FxHashMap<TypeContent, Type>,
42    pub(crate) constants: SlotMap<DefaultKey, ConstantContent>,
43    // Maps the hash of a ConstantContent to the list of constants with that hash.
44    pub(crate) constants_map: FxHashMap<u64, Vec<Constant>>,
45
46    pub(crate) metadata: SlotMap<DefaultKey, Metadatum>,
47
48    pub program_kind: Kind,
49
50    pub experimental: ExperimentalFeatures,
51
52    next_unique_sym_tag: u64,
53    next_unique_panic_revert_code: u64,
54}
55
56impl<'eng> Context<'eng> {
57    pub fn new(source_engine: &'eng SourceEngine, experimental: ExperimentalFeatures) -> Self {
58        let mut def = Self {
59            source_engine,
60            modules: Default::default(),
61            functions: Default::default(),
62            blocks: Default::default(),
63            values: Default::default(),
64            local_vars: Default::default(),
65            global_vars: Default::default(),
66            storage_keys: Default::default(),
67            types: Default::default(),
68            type_map: Default::default(),
69            constants: Default::default(),
70            constants_map: Default::default(),
71            metadata: Default::default(),
72            next_unique_sym_tag: Default::default(),
73            next_unique_panic_revert_code: PANIC_REVERT_CODE_LOWER_BOUND,
74            program_kind: Kind::Contract,
75            experimental,
76        };
77        Type::create_basic_types(&mut def);
78        def
79    }
80
81    pub fn source_engine(&self) -> &'eng SourceEngine {
82        self.source_engine
83    }
84
85    /// Return an iterator for every module in this context.
86    pub fn module_iter(&self) -> ModuleIterator {
87        ModuleIterator::new(self)
88    }
89
90    /// Get a globally unique symbol.
91    ///
92    /// The name will be in the form `"anon_N"`, where `N` is an incrementing decimal.
93    pub fn get_unique_name(&mut self) -> String {
94        format!("anon_{}", self.get_unique_symbol_id())
95    }
96
97    /// Get a globally unique symbol id.
98    pub fn get_unique_symbol_id(&mut self) -> u64 {
99        let sym = self.next_unique_sym_tag;
100        self.next_unique_sym_tag += 1;
101        sym
102    }
103
104    /// Get the next, unique, panic revert code.
105    pub fn get_next_panic_revert_code(&mut self) -> u64 {
106        let sym = self.next_unique_panic_revert_code;
107        self.next_unique_panic_revert_code += 1;
108        sym
109    }
110}
111
112use std::fmt::{Display, Error, Formatter};
113
114impl Display for Context<'_> {
115    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
116        write!(f, "{}", crate::printer::to_string(self))
117    }
118}
119
120impl From<Context<'_>> for String {
121    fn from(context: Context) -> Self {
122        crate::printer::to_string(&context)
123    }
124}