Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
c318607
unique constants in the IR
vaivaswatha Feb 6, 2025
63fc159
Merge branch 'master' into vaivaswatha/ir_consts_1
vaivaswatha Feb 6, 2025
3e840cd
clippy fixes
vaivaswatha Feb 7, 2025
681f8b9
Merge branch 'master' into vaivaswatha/ir_consts_1
vaivaswatha Feb 7, 2025
0176256
Merge branch 'master' into vaivaswatha/ir_consts_1
vaivaswatha Feb 8, 2025
5056ff4
Merge branch 'master' into vaivaswatha/ir_consts_1
IGI-111 Feb 10, 2025
9ed1a99
Introduce global variables and a get_global IR instruction
vaivaswatha Feb 13, 2025
a58e55a
Merge branch 'master' into vaivaswatha/ir_consts_1
vaivaswatha Feb 13, 2025
7679f39
Merge branch 'vaivaswatha/ir_consts_1' of github.com:FuelLabs/sway in…
vaivaswatha Feb 13, 2025
269c3cc
Merge branch 'vaivaswatha/ir_consts_1' into vaivaswatha/ir_consts_2
vaivaswatha Feb 13, 2025
4129d3d
fix bugs
vaivaswatha Feb 14, 2025
503cecf
IR printer and parser for the new IR insruction
vaivaswatha Feb 18, 2025
167bb5e
Merge branch 'master' into vaivaswatha/ir_consts_1
vaivaswatha Feb 18, 2025
625149d
Merge branch 'vaivaswatha/ir_consts_1' into vaivaswatha/ir_consts_2
vaivaswatha Feb 18, 2025
8227ff6
use BTreeMap since we iterate over the entries
vaivaswatha Feb 19, 2025
a15fa81
test updates
vaivaswatha Feb 19, 2025
0e359eb
remove unused globals
vaivaswatha Feb 19, 2025
15b342c
fix a test
vaivaswatha Feb 19, 2025
5c7f1e4
add a unit test that checks addresses of global consts
vaivaswatha Feb 19, 2025
39e3019
pass to promote global consts to immediate constants when possible
vaivaswatha Feb 20, 2025
c1d0136
Merge branch 'master' into vaivaswatha/ir_consts_2
vaivaswatha Feb 20, 2025
3ec3f90
update tests
vaivaswatha Feb 20, 2025
6f142fa
Merge branch 'master' into vaivaswatha/ir_consts_2
vaivaswatha Feb 22, 2025
c29eaea
address review comments
vaivaswatha Feb 26, 2025
63def49
Merge branch 'vaivaswatha/ir_consts_2' of github.com:FuelLabs/sway in…
vaivaswatha Feb 26, 2025
e27927f
Merge branch 'master' into vaivaswatha/ir_consts_2
vaivaswatha Feb 26, 2025
c0f6b7e
clippy fix
vaivaswatha Feb 26, 2025
f3088a8
Merge branch 'vaivaswatha/ir_consts_2' of github.com:FuelLabs/sway in…
vaivaswatha Feb 26, 2025
c8cd1ab
Merge branch 'master' into vaivaswatha/ir_consts_2
vaivaswatha Feb 27, 2025
a840b7a
Merge branch 'master' into vaivaswatha/ir_consts_2
vaivaswatha Feb 27, 2025
a86bc22
address review comments, tests pending
vaivaswatha Mar 1, 2025
4d6c029
Merge branch 'vaivaswatha/ir_consts_2' of github.com:FuelLabs/sway in…
vaivaswatha Mar 1, 2025
8dedba4
disable immutable-initializer check for locals
vaivaswatha Mar 1, 2025
94dec14
add unit tests for mem2reg and dce for globals
vaivaswatha Mar 1, 2025
4d3f865
Update test as per review comments
vaivaswatha Mar 1, 2025
2db107b
Merge branch 'master' into vaivaswatha/ir_consts_2
vaivaswatha Mar 1, 2025
14b4ada
typo fix to please CI
vaivaswatha Mar 1, 2025
3956188
more typo fix
vaivaswatha Mar 1, 2025
b72898c
Merge branch 'master' into vaivaswatha/ir_consts_2
vaivaswatha Mar 3, 2025
d13cfd8
fixes related to review comments
vaivaswatha Mar 3, 2025
2323f34
Merge branch 'vaivaswatha/ir_consts_2' of github.com:FuelLabs/sway in…
vaivaswatha Mar 3, 2025
f34fea9
Merge branch 'master' into vaivaswatha/ir_consts_2
vaivaswatha Mar 3, 2025
839783c
Merge branch 'master' into vaivaswatha/ir_consts_2
vaivaswatha Mar 4, 2025
a68e7ee
Merge branch 'master' into vaivaswatha/ir_consts_2
vaivaswatha Mar 4, 2025
cd41a43
Merge branch 'master' into vaivaswatha/ir_consts_2
vaivaswatha Mar 6, 2025
e7547c2
Merge branch 'master' into vaivaswatha/ir_consts_2
vaivaswatha Mar 7, 2025
10631d7
Merge branch 'master' into vaivaswatha/ir_consts_2
vaivaswatha Mar 10, 2025
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
5 changes: 5 additions & 0 deletions sway-core/src/asm_generation/evm/evm_asm_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,7 @@ impl<'ir, 'eng> EvmAsmBuilder<'ir, 'eng> {
indices,
} => self.compile_get_elem_ptr(instr_val, base, elem_ptr_ty, indices),
InstOp::GetLocal(local_var) => self.compile_get_local(instr_val, local_var),
InstOp::GetGlobal(global_var) => self.compile_get_global(instr_val, global_var),
InstOp::GetConfig(_, name) => self.compile_get_config(instr_val, name),
InstOp::IntToPtr(val, _) => self.compile_int_to_ptr(instr_val, val),
InstOp::Load(src_val) => self.compile_load(handler, instr_val, src_val)?,
Expand Down Expand Up @@ -471,6 +472,10 @@ impl<'ir, 'eng> EvmAsmBuilder<'ir, 'eng> {
todo!();
}

fn compile_get_global(&mut self, instr_val: &Value, global_var: &GlobalVar) {
todo!();
}

fn compile_get_local(&mut self, instr_val: &Value, local_var: &LocalVar) {
todo!();
}
Expand Down
39 changes: 39 additions & 0 deletions sway-core/src/asm_generation/fuel/fuel_asm_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,7 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> {
indices,
} => self.compile_get_elem_ptr(instr_val, base, elem_ptr_ty, indices),
InstOp::GetLocal(local_var) => self.compile_get_local(instr_val, local_var),
InstOp::GetGlobal(global_var) => self.compile_get_global(instr_val, global_var),
InstOp::GetConfig(_, name) => self.compile_get_config(instr_val, name),
InstOp::IntToPtr(val, _) => self.compile_no_op_move(instr_val, val),
InstOp::Load(src_val) => self.compile_load(instr_val, src_val),
Expand Down Expand Up @@ -1249,6 +1250,44 @@ impl<'ir, 'eng> FuelAsmBuilder<'ir, 'eng> {
Ok(())
}

fn compile_get_global(
&mut self,
instr_val: &Value,
global_var: &GlobalVar,
) -> Result<(), CompileError> {
if global_var.is_mutable(self.context) {
todo!("Implement mutable global variables");
}

let span = self
.md_mgr
.val_to_span(self.context, *instr_val)
.unwrap_or_else(Span::dummy);
let Some(constant) = global_var.get_initializer(self.context) else {
return Err(CompileError::Internal(
"Global constants (immutable variables) must have an initializer.",
span,
));
};
let entry = Entry::from_constant(
self.context,
constant.get_content(self.context),
EntryName::NonConfigurable,
None,
);
let data_id = self.data_section.insert_data_value(entry);

// Allocate a register for it, and an address_of instruction.
let reg = self.reg_seqr.next();
self.cur_bytecode.push(Op {
opcode: either::Either::Left(VirtualOp::AddrDataId(reg.clone(), data_id.clone())),
comment: "get constant's address in data section".into(),
owning_span: Some(span),
});
self.reg_map.insert(*instr_val, reg);
Ok(())
}

fn compile_get_local(
&mut self,
instr_val: &Value,
Expand Down
22 changes: 17 additions & 5 deletions sway-core/src/ir_generation/const_eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use sway_ir::{
context::Context,
module::Module,
value::Value,
Constant, InstOp, Instruction, Type, TypeContent,
Constant, GlobalVar, InstOp, Instruction, Type, TypeContent,
};
use sway_types::{ident::Ident, integer_bits::IntegerBits, span::Spanned, Named, Span};
use sway_utils::mapped_stack::MappedStack;
Expand Down Expand Up @@ -118,10 +118,15 @@ pub(crate) fn compile_const_decl(
// Check if it's a processed global constant.
match (
env.module
.get_global_constant(env.context, &call_path.as_vec_string()),
.get_global_variable(env.context, &call_path.as_vec_string()),
env.module_ns,
) {
(Some(const_val), _) => Ok(Some(const_val)),
(Some(global_var), _) => {
let constant = global_var
.get_initializer(env.context)
.expect("const decl without initializer, should've been detected way early");
Ok(Some(Value::new_constant(env.context, *constant)))
}
(None, Some(module_ns)) => {
// See if we it's a global const and whether we can compile it *now*.
let decl = module_ns.root_items().check_symbol(&call_path.suffix);
Expand Down Expand Up @@ -161,10 +166,17 @@ pub(crate) fn compile_const_decl(
&value,
)?;

env.module.add_global_constant(
let const_val_c = *const_val
.get_constant(env.context)
.expect("Must have been compiled to a constant");

let c_ty = const_val_c.get_content(env.context).ty;
let const_global = GlobalVar::new(env.context, c_ty, Some(const_val_c), false);

env.module.add_global_variable(
env.context,
call_path.as_vec_string().to_vec(),
const_val,
const_global,
);

Ok(Some(const_val))
Expand Down
11 changes: 8 additions & 3 deletions sway-core/src/ir_generation/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3329,11 +3329,16 @@ impl<'eng> FnCompiler<'eng> {
Ok(TerminatorValue::new(val, context))
} else if let Some(val) = self.function.get_arg(context, name.as_str()) {
Ok(TerminatorValue::new(val, context))
} else if let Some(const_val) = self
} else if let Some(global_val) = self
.module
.get_global_constant(context, &call_path.as_vec_string())
.get_global_variable(context, &call_path.as_vec_string())
{
Ok(TerminatorValue::new(const_val, context))
let val = self
.current_block
.append(context)
.get_global(global_val)
.add_metadatum(context, span_md_idx);
Ok(TerminatorValue::new(val, context))
} else if self
.module
.get_config(context, &call_path.suffix.to_string())
Expand Down
6 changes: 3 additions & 3 deletions sway-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ use sway_error::handler::{ErrorEmitted, Handler};
use sway_features::ExperimentalFeatures;
use sway_ir::{
create_o1_pass_group, register_known_passes, Context, Kind, Module, PassGroup, PassManager,
PrintPassesOpts, ARG_DEMOTION_NAME, CONST_DEMOTION_NAME, DCE_NAME, FN_DCE_NAME,
FN_DEDUP_DEBUG_PROFILE_NAME, FN_INLINE_NAME, MEM2REG_NAME, MEMCPYOPT_NAME, MISC_DEMOTION_NAME,
PrintPassesOpts, ARG_DEMOTION_NAME, CONST_DEMOTION_NAME, DCE_NAME, FN_DEDUP_DEBUG_PROFILE_NAME,
FN_INLINE_NAME, GLOBALS_DCE_NAME, MEM2REG_NAME, MEMCPYOPT_NAME, MISC_DEMOTION_NAME,
RET_DEMOTION_NAME, SIMPLIFY_CFG_NAME, SROA_NAME,
};
use sway_types::constants::DOC_COMMENT_ATTRIBUTE_NAME;
Expand Down Expand Up @@ -964,7 +964,7 @@ pub(crate) fn compile_ast_to_ir_to_asm(
pass_group.append_pass(FN_INLINE_NAME);

// Do DCE so other optimizations run faster.
pass_group.append_pass(FN_DCE_NAME);
pass_group.append_pass(GLOBALS_DCE_NAME);
pass_group.append_pass(DCE_NAME);
}
}
Expand Down
3 changes: 3 additions & 0 deletions sway-ir/src/analysis/memory_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,7 @@ pub fn compute_escaped_symbols(context: &Context, function: &Function) -> Escape
}
InstOp::FuelVm(_) => (),
InstOp::GetLocal(_) => (),
InstOp::GetGlobal(_) => (),
InstOp::GetConfig(_, _) => (),
InstOp::GetElemPtr { .. } => (),
InstOp::IntToPtr(_, _) => (),
Expand Down Expand Up @@ -453,6 +454,7 @@ pub fn get_loaded_ptr_values(context: &Context, inst: Value) -> Vec<Value> {
| InstOp::Nop
| InstOp::CastPtr(_, _)
| InstOp::GetLocal(_)
| InstOp::GetGlobal(_)
| InstOp::GetConfig(_, _)
| InstOp::GetElemPtr { .. }
| InstOp::IntToPtr(_, _) => vec![],
Expand Down Expand Up @@ -540,6 +542,7 @@ pub fn get_stored_ptr_values(context: &Context, inst: Value) -> Vec<Value> {
| InstOp::Ret(_, _)
| InstOp::CastPtr(_, _)
| InstOp::GetLocal(_)
| InstOp::GetGlobal(_)
| InstOp::GetConfig(_, _)
| InstOp::GetElemPtr { .. }
| InstOp::IntToPtr(_, _) => vec![],
Expand Down
6 changes: 4 additions & 2 deletions sway-ir/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ use sway_types::SourceEngine;
use crate::{
block::BlockContent,
function::FunctionContent,
local_var::LocalVarContent,
metadata::Metadatum,
module::{Kind, ModuleContent, ModuleIterator},
value::ValueContent,
Constant, ConstantContent, Type, TypeContent,
variable::LocalVarContent,
Constant, ConstantContent, GlobalVarContent, Type, TypeContent,
};

/// The main IR context handle.
Expand All @@ -33,6 +33,7 @@ pub struct Context<'eng> {
pub(crate) blocks: SlotMap<DefaultKey, BlockContent>,
pub(crate) values: SlotMap<DefaultKey, ValueContent>,
pub(crate) local_vars: SlotMap<DefaultKey, LocalVarContent>,
pub(crate) global_vars: SlotMap<DefaultKey, GlobalVarContent>,
pub(crate) types: SlotMap<DefaultKey, TypeContent>,
pub(crate) type_map: FxHashMap<TypeContent, Type>,
pub(crate) constants: SlotMap<DefaultKey, ConstantContent>,
Expand All @@ -57,6 +58,7 @@ impl<'eng> Context<'eng> {
blocks: Default::default(),
values: Default::default(),
local_vars: Default::default(),
global_vars: Default::default(),
types: Default::default(),
type_map: Default::default(),
constants: Default::default(),
Expand Down
60 changes: 38 additions & 22 deletions sway-ir/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,15 @@ pub enum IrError {
VerifyGepInconsistentTypes(String, Option<crate::Value>),
VerifyGepOnNonAggregate,
VerifyGetNonExistentPointer,
VerifyGlobalMissingInitializer(String),
VerifyInsertElementOfIncorrectType,
VerifyInsertValueOfIncorrectType,
VerifyIntToPtrFromNonIntegerType(String),
VerifyIntToPtrToNonPointer(String),
VerifyIntToPtrUnknownSourceType,
VerifyInvalidGtfIndexType,
VerifyLoadFromNonPointer(String),
VerifyLocalMissingInitializer(String, String),
VerifyLogId,
VerifyLogMismatchedTypes,
VerifyMemcopyNonPointer(String),
Expand Down Expand Up @@ -121,10 +123,10 @@ impl fmt::Display for IrError {
}
IrError::InconsistentParent(entity, expected_parent, found_parent) => {
write!(
f,
"For IR Entity (module/function/block) {entity}, expected parent to be {expected_parent}, \
f,
"For IR Entity (module/function/block) {entity}, expected parent to be {expected_parent}, \
but found {found_parent}."
)
)
}
IrError::VerifyArgumentValueIsNotArgument(callee) => write!(
f,
Expand Down Expand Up @@ -160,9 +162,9 @@ impl fmt::Display for IrError {
}
IrError::VerifyCallArgTypeMismatch(callee, caller_ty, callee_ty) => {
write!(
f,
"Verification failed: Type mismatch found for call to '{callee}': {caller_ty} is not a {callee_ty}."
)
f,
"Verification failed: Type mismatch found for call to '{callee}': {caller_ty} is not a {callee_ty}."
)
}
IrError::VerifyCallToMissingFunction(callee) => {
write!(
Expand Down Expand Up @@ -282,23 +284,23 @@ impl fmt::Display for IrError {
IrError::VerifyEntryBlockHasPredecessors(function_name, predecessors) => {
let plural_s = if predecessors.len() == 1 { "" } else { "s" };
write!(
f,
"Verification failed: Entry block of the function \"{function_name}\" has {}predecessor{}. \
f,
"Verification failed: Entry block of the function \"{function_name}\" has {}predecessor{}. \
The predecessor{} {} {}.",
if predecessors.len() == 1 {
"a "
} else {
""
},
plural_s,
plural_s,
if predecessors.len() == 1 {
"is"
} else {
"are"
},
predecessors.iter().map(|block_label| format!("\"{block_label}\"")).collect_vec().join(", ")
)
if predecessors.len() == 1 {
"a "
} else {
""
},
plural_s,
plural_s,
if predecessors.len() == 1 {
"is"
} else {
"are"
},
predecessors.iter().map(|block_label| format!("\"{block_label}\"")).collect_vec().join(", ")
)
}
IrError::VerifyBlockArgMalformed => {
write!(f, "Verification failed: Block argument is malformed")
Expand Down Expand Up @@ -420,6 +422,20 @@ impl fmt::Display for IrError {
"Verification failed: smo coins value must be an integer."
)
}
IrError::VerifyGlobalMissingInitializer(global_name) => {
write!(
f,
"Verification failed: Immutable global variable {global_name}\
is missing an initializer."
)
}
IrError::VerifyLocalMissingInitializer(local_name, func_name) => {
write!(
f,
"Verification failed: Immutable local variable {local_name} in function \
{func_name} is missing an initializer."
)
}
}
}
}
2 changes: 1 addition & 1 deletion sway-ir/src/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ use crate::{
context::Context,
error::IrError,
irtype::Type,
local_var::{LocalVar, LocalVarContent},
metadata::MetadataIndex,
module::Module,
value::{Value, ValueDatum},
variable::{LocalVar, LocalVarContent},
BlockArgument, BranchToWithArgs,
};
use crate::{Constant, InstOp};
Expand Down
17 changes: 15 additions & 2 deletions sway-ir/src/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ use crate::{
context::Context,
function::Function,
irtype::Type,
local_var::LocalVar,
pretty::DebugWithContext,
value::{Value, ValueDatum},
AsmInstruction, ConstantContent, Module,
variable::LocalVar,
AsmInstruction, ConstantContent, GlobalVar, Module,
};

#[derive(Debug, Clone, DebugWithContext)]
Expand Down Expand Up @@ -85,6 +85,8 @@ pub enum InstOp {
FuelVm(FuelVmInstruction),
/// Return a local variable.
GetLocal(LocalVar),
/// Return a global variable.
GetGlobal(GlobalVar),
/// Return a ptr to a config
GetConfig(Module, String),
/// Translate a pointer from a base to a nested element in an aggregate type.
Expand Down Expand Up @@ -299,6 +301,7 @@ impl InstOp {
// These return pointer types.
InstOp::GetElemPtr { elem_ptr_ty, .. } => Some(*elem_ptr_ty),
InstOp::GetLocal(local_var) => Some(local_var.get_type(context)),
InstOp::GetGlobal(global_var) => Some(global_var.get_type(context)),
InstOp::GetConfig(module, name) => Some(match module.get_config(context, name)? {
crate::ConfigContent::V0 { ptr_ty, .. } => *ptr_ty,
crate::ConfigContent::V1 { ptr_ty, .. } => *ptr_ty,
Expand Down Expand Up @@ -390,6 +393,10 @@ impl InstOp {
// `GetLocal` returns an SSA `Value` but does not take any as an operand.
vec![]
}
InstOp::GetGlobal(_global_var) => {
// `GetGlobal` returns an SSA `Value` but does not take any as an operand.
vec![]
}
InstOp::GetConfig(_, _) => {
// `GetConfig` returns an SSA `Value` but does not take any as an operand.
vec![]
Expand Down Expand Up @@ -523,6 +530,7 @@ impl InstOp {
replace(gas);
}
InstOp::GetLocal(_) => (),
InstOp::GetGlobal(_) => (),
InstOp::GetConfig(_, _) => (),
InstOp::GetElemPtr {
base,
Expand Down Expand Up @@ -684,6 +692,7 @@ impl InstOp {
| InstOp::FuelVm(FuelVmInstruction::StateLoadWord(_))
| InstOp::GetElemPtr { .. }
| InstOp::GetLocal(_)
| InstOp::GetGlobal(_)
| InstOp::GetConfig(_, _)
| InstOp::IntToPtr(..)
| InstOp::Load(_)
Expand Down Expand Up @@ -1042,6 +1051,10 @@ impl<'a, 'eng> InstructionInserter<'a, 'eng> {
insert_instruction!(self, InstOp::GetLocal(local_var))
}

pub fn get_global(self, global_var: GlobalVar) -> Value {
insert_instruction!(self, InstOp::GetGlobal(global_var))
}

pub fn get_config(self, module: Module, name: String) -> Value {
insert_instruction!(self, InstOp::GetConfig(module, name))
}
Expand Down
Loading
Loading