@@ -27,6 +27,7 @@ use melior::ir::attribute::TypeAttribute;
2727use melior:: ir:: operation:: OperationLike ;
2828use melior:: ir:: r#type:: FunctionType ;
2929use melior:: ir:: r#type:: IntegerType ;
30+ use num:: BigInt ;
3031
3132use crate :: CmpPredicate ;
3233use crate :: StateMutability ;
@@ -224,92 +225,85 @@ impl<'context> Builder<'context> {
224225 . into ( )
225226 }
226227
227- /// Emits a `sol. constant` of the given type from a decimal string .
228+ /// Emits a typed integer constant, selecting the dialect by target type .
228229 ///
229- /// # Errors
230+ /// `i1` is the signless boolean type owned by the arith dialect; every
231+ /// other integer type is signed or unsigned and belongs to the sol
232+ /// dialect. This is the single entry point for MLIR integer constants
233+ /// that carry a `BigInt`-sized value.
234+ ///
235+ /// # Panics
230236 ///
231- /// Returns an error if the string cannot be parsed as an MLIR integer attribute.
232- pub fn emit_sol_constant_from_decimal_str < ' block , B > (
237+ /// Panics if the MLIR attribute parser rejects the `{value} : {type}`
238+ /// rendering. For well-typed callers this is unreachable because the
239+ /// type is a melior `IntegerType` and the value is a `BigInt` that
240+ /// always has a canonical decimal representation.
241+ pub fn emit_constant < ' block , B > (
233242 & self ,
234- value : & str ,
243+ value : & BigInt ,
235244 result_type : Type < ' context > ,
236245 block : & B ,
237- ) -> anyhow :: Result < Value < ' context , ' block > >
246+ ) -> Value < ' context , ' block >
238247 where
239248 B : BlockLike < ' context , ' block > ,
240249 ' context : ' block ,
241250 {
251+ if result_type == self . types . sol_address {
252+ let integer = self . emit_constant ( value, self . types . ui160 , block) ;
253+ return self . emit_sol_address_cast ( integer, result_type, block) ;
254+ }
255+ if TypeFactory :: integer_bit_width ( result_type) == solx_utils:: BIT_LENGTH_BOOLEAN as u32 {
256+ let boolean_attribute =
257+ IntegerAttribute :: new ( result_type, i64:: from ( * value != BigInt :: ZERO ) ) . into ( ) ;
258+ return block
259+ . append_operation ( melior:: dialect:: arith:: constant (
260+ self . context ,
261+ boolean_attribute,
262+ self . unknown_location ,
263+ ) )
264+ . result ( 0 )
265+ . expect ( "arith.constant always produces one result" )
266+ . into ( ) ;
267+ }
268+ // melior does not expose a `BigInt`-accepting attribute constructor,
269+ // so we round-trip through the MLIR attribute parser to avoid
270+ // truncating values wider than 64 bits.
242271 let attribute = Attribute :: parse ( self . context , & format ! ( "{value} : {result_type}" ) )
243- . ok_or_else ( || anyhow :: anyhow! ( "invalid {result_type} decimal literal: {value}" ) ) ? ;
272+ . expect ( "BigInt value and melior integer type always parse as an MLIR attribute" ) ;
244273 self . emit_constant_operation ( attribute, result_type, block)
274+ . expect ( "well-typed BigInt constant never fails emission" )
245275 }
246276
247- /// Emits a `sol.constant` of the given type from a hex string (without `0x` prefix).
248- ///
249- /// # Errors
250- ///
251- /// Returns an error if the string cannot be parsed as an MLIR integer attribute.
252- pub fn emit_sol_constant_from_hex_str < ' block , B > (
253- & self ,
254- hexadecimal : & str ,
255- result_type : Type < ' context > ,
256- block : & B ,
257- ) -> anyhow:: Result < Value < ' context , ' block > >
277+ /// Emits an `i1` boolean constant.
278+ pub fn emit_bool < ' block , B > ( & self , value : bool , block : & B ) -> Value < ' context , ' block >
258279 where
259280 B : BlockLike < ' context , ' block > ,
260281 ' context : ' block ,
261282 {
262- let attribute = Attribute :: parse ( self . context , & format ! ( "0x{hexadecimal} : {result_type}" ) )
263- . ok_or_else ( || anyhow:: anyhow!( "invalid {result_type} hex literal: 0x{hexadecimal}" ) ) ?;
264- self . emit_constant_operation ( attribute, result_type, block)
283+ self . emit_constant ( & BigInt :: from ( u8:: from ( value) ) , self . types . i1 , block)
265284 }
266285
267286 /// Emits an all-ones `sol.constant` for the given integer type.
268- ///
269- /// # Errors
270- ///
271- /// Returns an error if the constant cannot be parsed as an MLIR integer attribute.
272287 pub fn emit_sol_constant_all_ones < ' block , B > (
273288 & self ,
274289 integer_type : Type < ' context > ,
275290 block : & B ,
276- ) -> anyhow:: Result < Value < ' context , ' block > >
277- where
278- B : BlockLike < ' context , ' block > ,
279- ' context : ' block ,
280- {
281- let bit_width = TypeFactory :: integer_bit_width ( integer_type) ;
282- let all_ones_hex = "f" . repeat ( bit_width as usize / 4 ) ;
283- self . emit_sol_constant_from_hex_str ( & all_ones_hex, integer_type, block)
284- }
285-
286- /// Emits an `arith.constant` for a signless `i1` boolean value.
287- ///
288- /// Boolean (`i1`) is signless in MLIR, so it uses `arith.constant`
289- /// instead of `sol.constant` (which is for signed/unsigned int types).
290- ///
291- /// # Panics
292- ///
293- /// Panics if the MLIR operation cannot be constructed.
294- pub fn emit_arith_constant_bool < ' block , B > (
295- & self ,
296- value : bool ,
297- block : & B ,
298291 ) -> Value < ' context , ' block >
299292 where
300293 B : BlockLike < ' context , ' block > ,
301294 ' context : ' block ,
302295 {
303- let i1_type = IntegerType :: new ( self . context , solx_utils:: BIT_LENGTH_BOOLEAN as u32 ) . into ( ) ;
304- block
305- . append_operation ( melior:: dialect:: arith:: constant (
306- self . context ,
307- IntegerAttribute :: new ( i1_type, i64:: from ( value) ) . into ( ) ,
308- self . unknown_location ,
309- ) )
310- . result ( 0 )
311- . expect ( "arith.constant always produces one result" )
312- . into ( )
296+ let all_ones = if IntegerType :: try_from ( integer_type)
297+ . ok ( )
298+ . is_some_and ( |integer| integer. is_signed ( ) )
299+ {
300+ // Two's-complement all-ones for any signed width is `-1`.
301+ BigInt :: from ( -1 )
302+ } else {
303+ let bit_width = TypeFactory :: integer_bit_width ( integer_type) ;
304+ ( BigInt :: from ( 1u32 ) << bit_width) - BigInt :: from ( 1u32 )
305+ } ;
306+ self . emit_constant ( & all_ones, integer_type, block)
313307 }
314308
315309 // ==== String literals ====
0 commit comments