Skip to content
Draft
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
60 changes: 60 additions & 0 deletions solx-slang/src/ast/contract/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,16 @@ pub mod function;
use std::collections::HashMap;

use ruint::aliases::U256;
use slang_solidity_v2::abi::AbiEntry;
use slang_solidity_v2::ast::ContractDefinition;
use slang_solidity_v2::ast::ContractMember;
use slang_solidity_v2::ast::FunctionKind;
use slang_solidity_v2::ast::FunctionMutability;
use slang_solidity_v2::ast::NodeId;
use slang_solidity_v2::ast::StateVariableDefinition;

use solx_mlir::Context;
use solx_mlir::StateMutability;

use self::function::FunctionEmitter;
use self::function::expression::call::type_conversion::TypeConversion;
Expand Down Expand Up @@ -109,6 +112,63 @@ impl<'state, 'context> ContractEmitter<'state, 'context> {
self.state.current_contract_type = None;
}

for member in contract.members().iter() {
let ContractMember::StateVariableDefinition(state_variable) = member else {
continue;
};
let Some(slot) = storage_layout.get(&state_variable.node_id()).copied() else {
continue;
};
self.emit_state_variable_getter(&state_variable, slot, &contract_body)?;
}

Ok(())
}

/// Emits the auto-generated external getter for a public state variable.
///
/// Scalar `T public name;` becomes `function name() external view
/// returns (T)` reading slot `slot`. Array/mapping/struct getters
/// require indexed access and are not yet emitted; they are silently
/// skipped here so the rest of the contract still compiles.
fn emit_state_variable_getter(
&self,
state_variable: &StateVariableDefinition,
slot: U256,
contract_body: &melior::ir::BlockRef<'context, '_>,
) -> anyhow::Result<()> {
let Some(AbiEntry::Function(abi)) = state_variable.compute_abi_entry() else {
return Ok(());
};
// Scalar getters only for now — indexed forms need sol.gep / sol.map.
if !abi.inputs().is_empty() {
return Ok(());
}
let Some(signature) = state_variable.compute_canonical_signature() else {
Comment on lines +143 to +147
return Ok(());
};
let Some(selector) = state_variable.compute_selector() else {
return Ok(());
};

let builder = &self.state.builder;
let element_type = TypeConversion::resolve_state_variable_type(state_variable, builder)?;
let pointer_type = builder
.types
.pointer(element_type, solx_utils::DataLocation::Storage);
let entry = builder.emit_sol_func(
&signature,
&[],
std::slice::from_ref(&element_type),
Some(selector),
StateMutability::View,
None,
contract_body,
);
let slot_name = format!("slot_{slot}");
let pointer = builder.emit_sol_addr_of(&slot_name, pointer_type, &entry);
let value = builder.emit_sol_load(pointer, element_type, &entry)?;
builder.emit_sol_return(&[value], &entry);
Ok(())
}

Expand Down
31 changes: 21 additions & 10 deletions solx-slang/src/ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,16 +56,27 @@ impl<'state, 'context> AstEmitter<'state, 'context> {

let mut method_identifiers = BTreeMap::new();
for contract_member in contract.members().iter() {
let ContractMember::FunctionDefinition(function) = contract_member else {
continue;
};
let Some(signature) = function.compute_canonical_signature() else {
continue;
};
let Some(selector) = function.compute_selector() else {
continue;
};
method_identifiers.insert(signature, format!("{selector:08x}"));
match contract_member {
ContractMember::FunctionDefinition(function) => {
let Some(signature) = function.compute_canonical_signature() else {
continue;
};
let Some(selector) = function.compute_selector() else {
continue;
};
method_identifiers.insert(signature, format!("{selector:08x}"));
}
ContractMember::StateVariableDefinition(state_variable) => {
let Some(signature) = state_variable.compute_canonical_signature() else {
continue;
};
let Some(selector) = state_variable.compute_selector() else {
continue;
};
method_identifiers.insert(signature, format!("{selector:08x}"));
}
Comment on lines +69 to +77
_ => {}
}
}

Ok(Some((name, method_identifiers)))
Expand Down
Loading