Skip to content

Commit 06a3ce9

Browse files
authored
fix(slang): use arith.constant for i1 booleans (#359)
Boolean (`i1`) is signless in MLIR, so it uses `arith.constant` instead of `sol.constant` (which is for signed/unsigned int types). This matches solc's `bExt.genBool()` in `Util.h:69-74` which emits `arith::ConstantOp`. Adds `emit_arith_constant_bool` to the builder and replaces 5 call sites that were incorrectly using `sol.constant` for `i1` values: - `TrueKeyword` / `FalseKeyword` literal emission - `&&` / `||` short-circuit default values - For-loop implicit `true` condition (infinite loop)
1 parent f9c8d7c commit 06a3ce9

4 files changed

Lines changed: 38 additions & 14 deletions

File tree

solx-mlir/src/context/builder/mod.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,35 @@ impl<'context> Builder<'context> {
282282
self.emit_sol_constant_from_hex_str(&all_ones_hex, integer_type, block)
283283
}
284284

285+
/// Emits an `arith.constant` for a signless `i1` boolean value.
286+
///
287+
/// Boolean (`i1`) is signless in MLIR, so it uses `arith.constant`
288+
/// instead of `sol.constant` (which is for signed/unsigned int types).
289+
///
290+
/// # Panics
291+
///
292+
/// Panics if the MLIR operation cannot be constructed.
293+
pub fn emit_arith_constant_bool<'block, B>(
294+
&self,
295+
value: bool,
296+
block: &B,
297+
) -> Value<'context, 'block>
298+
where
299+
B: BlockLike<'context, 'block>,
300+
'context: 'block,
301+
{
302+
let i1_type = IntegerType::new(self.context, solx_utils::BIT_LENGTH_BOOLEAN as u32).into();
303+
block
304+
.append_operation(melior::dialect::arith::constant(
305+
self.context,
306+
IntegerAttribute::new(i1_type, i64::from(value)).into(),
307+
self.unknown_location,
308+
))
309+
.result(0)
310+
.expect("arith.constant always produces one result")
311+
.into()
312+
}
313+
285314
// ==== Terminators ====
286315

287316
/// Emits a `sol.revert` with an empty signature (no error data).

solx-slang/src/ast/contract/function/expression/logical.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -67,12 +67,10 @@ impl<'state, 'context, 'block> ExpressionEmitter<'state, 'context, 'block> {
6767

6868
let i1_type = self.state.builder.types.i1;
6969
let result_ptr = self.state.builder.emit_sol_alloca(i1_type, &block);
70-
// TODO: solc uses `arith.constant false` here; consider switching to
71-
// arith dialect for i1 constants to match solc output exactly.
72-
let false_val = self.state.builder.emit_sol_constant(0, i1_type, &block);
70+
let false_value = self.state.builder.emit_arith_constant_bool(false, &block);
7371
self.state
7472
.builder
75-
.emit_sol_store(false_val, result_ptr, &block);
73+
.emit_sol_store(false_value, result_ptr, &block);
7674

7775
let (then_block, else_block) = self.state.builder.emit_sol_if(lhs_bool, &block);
7876

@@ -113,10 +111,10 @@ impl<'state, 'context, 'block> ExpressionEmitter<'state, 'context, 'block> {
113111

114112
let i1_type = self.state.builder.types.i1;
115113
let result_ptr = self.state.builder.emit_sol_alloca(i1_type, &block);
116-
let true_val = self.state.builder.emit_sol_constant(1, i1_type, &block);
114+
let true_value = self.state.builder.emit_arith_constant_bool(true, &block);
117115
self.state
118116
.builder
119-
.emit_sol_store(true_val, result_ptr, &block);
117+
.emit_sol_store(true_value, result_ptr, &block);
120118

121119
let (then_block, else_block) = self.state.builder.emit_sol_if(lhs_bool, &block);
122120

solx-slang/src/ast/contract/function/expression/mod.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -127,13 +127,11 @@ impl<'state, 'context, 'block> ExpressionEmitter<'state, 'context, 'block> {
127127
Ok((Some(value), block))
128128
}
129129
Expression::TrueKeyword => {
130-
let i1_type = self.state.builder.types.i1;
131-
let value = self.state.builder.emit_sol_constant(1, i1_type, &block);
130+
let value = self.state.builder.emit_arith_constant_bool(true, &block);
132131
Ok((Some(value), block))
133132
}
134133
Expression::FalseKeyword => {
135-
let i1_type = self.state.builder.types.i1;
136-
let value = self.state.builder.emit_sol_constant(0, i1_type, &block);
134+
let value = self.state.builder.emit_arith_constant_bool(false, &block);
137135
Ok((Some(value), block))
138136
}
139137
Expression::Identifier(identifier) => {

solx-slang/src/ast/contract/function/statement/control_flow.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -134,14 +134,13 @@ impl<'state, 'context, 'block> StatementEmitter<'state, 'context, 'block> {
134134
.emit_sol_condition(condition_boolean, &condition_end);
135135
}
136136
ForStatementCondition::Semicolon => {
137-
let i1_type = self.state.builder.types.i1;
138-
let true_val = self
137+
let true_value = self
139138
.state
140139
.builder
141-
.emit_sol_constant(1, i1_type, &condition_block);
140+
.emit_arith_constant_bool(true, &condition_block);
142141
self.state
143142
.builder
144-
.emit_sol_condition(true_val, &condition_block);
143+
.emit_sol_condition(true_value, &condition_block);
145144
}
146145
}
147146

0 commit comments

Comments
 (0)