@@ -12,6 +12,7 @@ use crate::error::Result;
1212use crate :: ir:: * ;
1313use crate :: ENTRY_WITNESS_ABI_MAGIC ;
1414
15+ use super :: assembler:: align_up;
1516use super :: {
1617 fixed_aggregate_pointer_param_width, fixed_byte_pointer_param_width, fixed_register_width, named_type_name, type_static_length,
1718 CellScriptRuntimeError , CodeGenerator ,
@@ -80,6 +81,15 @@ pub(crate) fn entry_abi_arg_count(params: &[IrParam], abi: Option<&CallableAbi>)
8081 . sum ( )
8182}
8283
84+ pub ( crate ) fn outgoing_stack_arg_bytes ( abi_arg_count : usize ) -> usize {
85+ let bytes = abi_arg_count. saturating_sub ( 8 ) * 8 ;
86+ if bytes == 0 {
87+ 0
88+ } else {
89+ align_up ( bytes, 16 )
90+ }
91+ }
92+
8393pub ( crate ) fn call_param_abi_arg_count ( param : & IrParam , needs_type_hash : bool ) -> usize {
8494 if named_type_name ( & param. ty ) . is_some ( ) {
8595 return 2 + usize:: from ( needs_type_hash) * 2 ;
@@ -211,7 +221,7 @@ impl CodeGenerator {
211221 let callable_abi = self . callable_abis . get ( target) . cloned ( ) ;
212222 let type_hash_param_indices = callable_abi. as_ref ( ) . map ( |abi| abi. type_hash_param_indices . clone ( ) ) . unwrap_or_default ( ) ;
213223 let runtime_bound_param_indices = callable_abi. as_ref ( ) . map ( |abi| abi. runtime_bound_param_indices . clone ( ) ) . unwrap_or_default ( ) ;
214- let outgoing_stack_arg_bytes = entry_abi_arg_count ( params, callable_abi. as_ref ( ) ) . saturating_sub ( 8 ) * 8 ;
224+ let outgoing_stack_arg_bytes = outgoing_stack_arg_bytes ( entry_abi_arg_count ( params, callable_abi. as_ref ( ) ) ) ;
215225 let payload = entry_witness_payload_layout ( params, & runtime_bound_param_indices) ;
216226 let payload_len = payload. iter ( ) . map ( |arg| arg. width ) . sum :: < usize > ( ) ;
217227 let has_witness_payload = payload. iter ( ) . any ( |arg| arg. width > 0 || arg. unsupported ) ;
@@ -388,9 +398,15 @@ impl CodeGenerator {
388398 self . emit ( format ! ( "addi t0, t0, {}" , ENTRY_WITNESS_BUFFER_OFFSET ) ) ;
389399 if abi_index < 8 {
390400 self . emit_entry_witness_scalar_load_from_reg ( & format ! ( "a{}" , abi_index) , "t0" , width) ;
401+ if param. ty == IrType :: Bool {
402+ self . emit_entry_bool_canonical_check ( & format ! ( "a{}" , abi_index) , & fail_label) ;
403+ }
391404 } else {
392405 let caller_stack_offset = ( abi_index - 8 ) * 8 ;
393406 self . emit_entry_witness_scalar_load_from_reg ( "t3" , "t0" , width) ;
407+ if param. ty == IrType :: Bool {
408+ self . emit_entry_bool_canonical_check ( "t3" , & fail_label) ;
409+ }
394410 self . emit ( format ! (
395411 "# cellscript entry abi: scalar param {} stored to caller stack +{}" ,
396412 param. name, caller_stack_offset
@@ -480,9 +496,15 @@ impl CodeGenerator {
480496 let stack_offset = ENTRY_WITNESS_BUFFER_OFFSET + ENTRY_WITNESS_HEADER_SIZE + payload_cursor;
481497 if abi_index < 8 {
482498 self . emit_entry_witness_scalar_load ( & format ! ( "a{}" , abi_index) , stack_offset, width) ;
499+ if param. ty == IrType :: Bool {
500+ self . emit_entry_bool_canonical_check ( & format ! ( "a{}" , abi_index) , & fail_label) ;
501+ }
483502 } else {
484503 let caller_stack_offset = ( abi_index - 8 ) * 8 ;
485504 self . emit_entry_witness_scalar_load ( "t3" , stack_offset, width) ;
505+ if param. ty == IrType :: Bool {
506+ self . emit_entry_bool_canonical_check ( "t3" , & fail_label) ;
507+ }
486508 self . emit ( format ! (
487509 "# cellscript entry abi: scalar param {} stored to caller stack +{}" ,
488510 param. name, caller_stack_offset
@@ -606,6 +628,17 @@ impl CodeGenerator {
606628 }
607629 }
608630
631+ fn emit_entry_bool_canonical_check ( & mut self , register : & str , fail_label : & str ) {
632+ let zero_ok = self . fresh_label ( "entry_bool_zero_ok" ) ;
633+ let bool_ok = self . fresh_label ( "entry_bool_canonical_ok" ) ;
634+ self . emit ( format ! ( "beqz {}, {}" , register, zero_ok) ) ;
635+ self . emit ( "li t2, 1" ) ;
636+ self . emit ( format ! ( "beq {}, t2, {}" , register, bool_ok) ) ;
637+ self . emit ( format ! ( "j {}" , fail_label) ) ;
638+ self . emit_label ( & zero_ok) ;
639+ self . emit_label ( & bool_ok) ;
640+ }
641+
609642 fn emit_entry_load_u32_from_stack ( & mut self , dest_reg : & str , stack_offset : usize ) {
610643 self . emit ( format ! ( "li {}, 0" , dest_reg) ) ;
611644 for byte_index in 0 ..4 {
@@ -729,9 +762,15 @@ impl CodeGenerator {
729762 * abi_index += 2 ;
730763 } else if * abi_index < 8 {
731764 self . emit_entry_witness_scalar_load_from_reg ( & format ! ( "a{}" , * abi_index) , "t0" , width) ;
765+ if param. ty == IrType :: Bool {
766+ self . emit_entry_bool_canonical_check ( & format ! ( "a{}" , * abi_index) , fail_label) ;
767+ }
732768 * abi_index += 1 ;
733769 } else {
734770 self . emit_entry_witness_scalar_load_from_reg ( "t4" , "t0" , width) ;
771+ if param. ty == IrType :: Bool {
772+ self . emit_entry_bool_canonical_check ( "t4" , fail_label) ;
773+ }
735774 self . emit_entry_abi_reg_arg ( * abi_index, "t4" , outgoing_stack_arg_bytes) ;
736775 * abi_index += 1 ;
737776 }
0 commit comments