@@ -31,6 +31,51 @@ use std::str::FromStr;
3131use std:: { u16, u32} ;
3232use target_lexicon:: Triple ;
3333
34+ macro_rules! match_imm {
35+ ( $signed: ty, $unsigned: ty, $parser: expr, $err_msg: expr) => { {
36+ if let Some ( Token :: Integer ( text) ) = $parser. token( ) {
37+ $parser. consume( ) ;
38+ let negative = text. starts_with( '-' ) ;
39+ let positive = text. starts_with( '+' ) ;
40+ let text = if negative || positive {
41+ // Strip sign prefix.
42+ & text[ 1 ..]
43+ } else {
44+ text
45+ } ;
46+
47+ // Parse the text value; the lexer gives us raw text that looks like an integer.
48+ let value = if text. starts_with( "0x" ) {
49+ // Skip underscores.
50+ let text = text. replace( "_" , "" ) ;
51+ // Parse it in hexadecimal form.
52+ <$unsigned>:: from_str_radix( & text[ 2 ..] , 16 ) . map_err( |_| {
53+ $parser. error( "unable to parse value as a hexadecimal immediate" )
54+ } ) ?
55+ } else {
56+ // Parse it as a signed type to check for overflow and other issues.
57+ text. parse( )
58+ . map_err( |_| $parser. error( "expected decimal immediate" ) ) ?
59+ } ;
60+
61+ // Apply sign if necessary.
62+ let signed = if negative {
63+ let value = value. wrapping_neg( ) as $signed;
64+ if value > 0 {
65+ return Err ( $parser. error( "negative number too small" ) ) ;
66+ }
67+ value
68+ } else {
69+ value as $signed
70+ } ;
71+
72+ Ok ( signed)
73+ } else {
74+ err!( $parser. loc, $err_msg)
75+ }
76+ } } ;
77+ }
78+
3479/// After some quick benchmarks a program should never have more than 100,000 blocks.
3580const MAX_BLOCKS_IN_A_FUNCTION : u32 = 100_000 ;
3681
@@ -793,175 +838,23 @@ impl<'a> Parser<'a> {
793838
794839 // Match and consume an i8 immediate.
795840 fn match_imm8 ( & mut self , err_msg : & str ) -> ParseResult < i8 > {
796- if let Some ( Token :: Integer ( text) ) = self . token ( ) {
797- self . consume ( ) ;
798- let negative = text. starts_with ( '-' ) ;
799- let positive = text. starts_with ( '+' ) ;
800- let text = if negative || positive {
801- // Strip sign prefix.
802- & text[ 1 ..]
803- } else {
804- text
805- } ;
806-
807- // Parse the text value; the lexer gives us raw text that looks like an integer.
808- let value = if text. starts_with ( "0x" ) {
809- // Skip underscores.
810- let text = text. replace ( "_" , "" ) ;
811- // Parse it as a i8 in hexadecimal form.
812- u8:: from_str_radix ( & text[ 2 ..] , 16 )
813- . map_err ( |_| self . error ( "unable to parse i8 as a hexadecimal immediate" ) ) ?
814- } else {
815- // Parse it as a i8 to check for overflow and other issues.
816- text. parse ( )
817- . map_err ( |_| self . error ( "expected i8 decimal immediate" ) ) ?
818- } ;
819-
820- // Apply sign if necessary.
821- let signed = if negative {
822- let value = value. wrapping_neg ( ) as i8 ;
823- if value > 0 {
824- return Err ( self . error ( "negative number too small" ) ) ;
825- }
826- value
827- } else {
828- value as i8
829- } ;
830-
831- Ok ( signed)
832- } else {
833- err ! ( self . loc, err_msg)
834- }
841+ match_imm ! ( i8 , u8 , self , err_msg)
835842 }
836843
837844 // Match and consume a signed 16-bit immediate.
838845 fn match_imm16 ( & mut self , err_msg : & str ) -> ParseResult < i16 > {
839- if let Some ( Token :: Integer ( text) ) = self . token ( ) {
840- self . consume ( ) ;
841- let negative = text. starts_with ( '-' ) ;
842- let positive = text. starts_with ( '+' ) ;
843- let text = if negative || positive {
844- // Strip sign prefix.
845- & text[ 1 ..]
846- } else {
847- text
848- } ;
849-
850- // Parse the text value; the lexer gives us raw text that looks like an integer.
851- let value = if text. starts_with ( "0x" ) {
852- // Skip underscores.
853- let text = text. replace ( "_" , "" ) ;
854- // Parse it as a i16 in hexadecimal form.
855- u16:: from_str_radix ( & text[ 2 ..] , 16 )
856- . map_err ( |_| self . error ( "unable to parse i16 as a hexadecimal immediate" ) ) ?
857- } else {
858- // Parse it as a i16 to check for overflow and other issues.
859- text. parse ( )
860- . map_err ( |_| self . error ( "expected i16 decimal immediate" ) ) ?
861- } ;
862-
863- // Apply sign if necessary.
864- let signed = if negative {
865- let value = value. wrapping_neg ( ) as i16 ;
866- if value > 0 {
867- return Err ( self . error ( "negative number too small" ) ) ;
868- }
869- value
870- } else {
871- value as i16
872- } ;
873-
874- Ok ( signed)
875- } else {
876- err ! ( self . loc, err_msg)
877- }
846+ match_imm ! ( i16 , u16 , self , err_msg)
878847 }
879848
880849 // Match and consume an i32 immediate.
881850 // This is used for stack argument byte offsets.
882851 fn match_imm32 ( & mut self , err_msg : & str ) -> ParseResult < i32 > {
883- if let Some ( Token :: Integer ( text) ) = self . token ( ) {
884- self . consume ( ) ;
885- let negative = text. starts_with ( '-' ) ;
886- let positive = text. starts_with ( '+' ) ;
887- let text = if negative || positive {
888- // Strip sign prefix.
889- & text[ 1 ..]
890- } else {
891- text
892- } ;
893-
894- // Parse the text value; the lexer gives us raw text that looks like an integer.
895- let value = if text. starts_with ( "0x" ) {
896- // Skip underscores.
897- let text = text. replace ( "_" , "" ) ;
898- // Parse it as a i32 in hexadecimal form.
899- u32:: from_str_radix ( & text[ 2 ..] , 16 )
900- . map_err ( |_| self . error ( "unable to parse i32 as a hexadecimal immediate" ) ) ?
901- } else {
902- // Parse it as a i32 to check for overflow and other issues.
903- text. parse ( )
904- . map_err ( |_| self . error ( "expected i32 decimal immediate" ) ) ?
905- } ;
906-
907- // Apply sign if necessary.
908- let signed = if negative {
909- let value = value. wrapping_neg ( ) as i32 ;
910- if value > 0 {
911- return Err ( self . error ( "negative number too small" ) ) ;
912- }
913- value
914- } else {
915- value as i32
916- } ;
917-
918- Ok ( signed)
919- } else {
920- err ! ( self . loc, err_msg)
921- }
852+ match_imm ! ( i32 , u32 , self , err_msg)
922853 }
923854
924855 // Match and consume an i128 immediate.
925856 fn match_imm128 ( & mut self , err_msg : & str ) -> ParseResult < i128 > {
926- if let Some ( Token :: Integer ( text) ) = self . token ( ) {
927- self . consume ( ) ;
928- let negative = text. starts_with ( '-' ) ;
929- let positive = text. starts_with ( '+' ) ;
930- let text = if negative || positive {
931- // Strip sign prefix.
932- & text[ 1 ..]
933- } else {
934- text
935- } ;
936-
937- // Parse the text value; the lexer gives us raw text that looks like an integer.
938- let value = if text. starts_with ( "0x" ) {
939- // Skip underscores.
940- let text = text. replace ( "_" , "" ) ;
941- // Parse it as a i128 in hexadecimal form.
942- u128:: from_str_radix ( & text[ 2 ..] , 16 )
943- . map_err ( |_| self . error ( "unable to parse i128 as a hexadecimal immediate" ) ) ?
944- } else {
945- // Parse it as a i128 to check for overflow and other issues.
946- text. parse ( )
947- . map_err ( |_| self . error ( "expected i128 decimal immediate" ) ) ?
948- } ;
949-
950- // Apply sign if necessary.
951- let signed = if negative {
952- let value = value. wrapping_neg ( ) as i128 ;
953- if value > 0 {
954- return Err ( self . error ( "negative number too small" ) ) ;
955- }
956- value
957- } else {
958- value as i128
959- } ;
960-
961- Ok ( signed)
962- } else {
963- err ! ( self . loc, err_msg)
964- }
857+ match_imm ! ( i128 , u128 , self , err_msg)
965858 }
966859
967860 // Match and consume an optional offset32 immediate.
0 commit comments