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, 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) types: SlotMap<DefaultKey, TypeContent>,
40    pub(crate) type_map: FxHashMap<TypeContent, Type>,
41    pub(crate) constants: SlotMap<DefaultKey, ConstantContent>,
42    // Maps the hash of a ConstantContent to the list of constants with that hash.
43    pub(crate) constants_map: FxHashMap<u64, Vec<Constant>>,
44
45    pub(crate) metadata: SlotMap<DefaultKey, Metadatum>,
46
47    pub program_kind: Kind,
48
49    pub experimental: ExperimentalFeatures,
50
51    next_unique_sym_tag: u64,
52    next_unique_panic_revert_code: u64,
53}
54
55impl<'eng> Context<'eng> {
56    pub fn new(source_engine: &'eng SourceEngine, experimental: ExperimentalFeatures) -> Self {
57        let mut def = Self {
58            source_engine,
59            modules: Default::default(),
60            functions: Default::default(),
61            blocks: Default::default(),
62            values: Default::default(),
63            local_vars: Default::default(),
64            global_vars: Default::default(),
65            types: Default::default(),
66            type_map: Default::default(),
67            constants: Default::default(),
68            constants_map: Default::default(),
69            metadata: Default::default(),
70            next_unique_sym_tag: Default::default(),
71            next_unique_panic_revert_code: PANIC_REVERT_CODE_LOWER_BOUND,
72            program_kind: Kind::Contract,
73            experimental,
74        };
75        Type::create_basic_types(&mut def);
76        def
77    }
78
79    pub fn source_engine(&self) -> &'eng SourceEngine {
80        self.source_engine
81    }
82
83    /// Return an iterator for every module in this context.
84    pub fn module_iter(&self) -> ModuleIterator {
85        ModuleIterator::new(self)
86    }
87
88    /// Get a globally unique symbol.
89    ///
90    /// The name will be in the form `"anon_N"`, where `N` is an incrementing decimal.
91    pub fn get_unique_name(&mut self) -> String {
92        format!("anon_{}", self.get_unique_symbol_id())
93    }
94
95    /// Get a globally unique symbol id.
96    pub fn get_unique_symbol_id(&mut self) -> u64 {
97        let sym = self.next_unique_sym_tag;
98        self.next_unique_sym_tag += 1;
99        sym
100    }
101
102    /// Get the next, unique, panic revert code.
103    pub fn get_next_panic_revert_code(&mut self) -> u64 {
104        let sym = self.next_unique_panic_revert_code;
105        self.next_unique_panic_revert_code += 1;
106        sym
107    }
108}
109
110use std::fmt::{Display, Error, Formatter};
111
112impl Display for Context<'_> {
113    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
114        write!(f, "{}", crate::printer::to_string(self))
115    }
116}
117
118impl From<Context<'_>> for String {
119    fn from(context: Context) -> Self {
120        crate::printer::to_string(&context)
121    }
122}