@@ -658,241 +658,19 @@ Expression* SExpressionWasmBuilder::parseExpression(Element& s) {
658658}
659659
660660Expression* SExpressionWasmBuilder::makeExpression (Element& s) {
661- IString id = s[0 ]->str ();
662- const char *str = id.str ;
663- const char *dot = strchr (str, ' .' );
664- if (dot) {
665- // type.operation (e.g. i32.add)
666- Type type = stringToType (str, false , true );
667- // Local copy to index into op without bounds checking.
668- enum { maxNameSize = 15 };
669- char op[maxNameSize + 1 ] = {' \0 ' };
670- strncpy (op, dot + 1 , maxNameSize);
671- #define BINARY_INT_OR_FLOAT (op ) (type == i32 ? BinaryOp::op##Int32 : (type == i64 ? BinaryOp::op##Int64 : (type == f32 ? BinaryOp::op##Float32 : BinaryOp::op##Float64)))
672- #define BINARY_INT (op ) (type == i32 ? BinaryOp::op##Int32 : BinaryOp::op##Int64)
673- #define BINARY_FLOAT (op ) (type == f32 ? BinaryOp::op##Float32 : BinaryOp::op##Float64)
674- switch (op[0 ]) {
675- case ' a' : {
676- if (op[1 ] == ' b' ) return makeUnary (s, type == f32 ? UnaryOp::AbsFloat32 : UnaryOp::AbsFloat64, type);
677- if (op[1 ] == ' d' ) return makeBinary (s, BINARY_INT_OR_FLOAT (Add), type);
678- if (op[1 ] == ' n' ) return makeBinary (s, BINARY_INT (And), type);
679- if (op[1 ] == ' t' && !strncmp (op, " atomic." , strlen (" atomic." ))) {
680- if (op[7 ] == ' l' ) return makeLoad (s, type, /* isAtomic=*/ true );
681- if (op[7 ] == ' s' ) return makeStore (s, type, /* isAtomic=*/ true );
682- if (op[7 ] == ' r' ) return makeAtomicRMWOrCmpxchg (s, type);
683- }
684- abort_on (op);
685- }
686- case ' c' : {
687- if (op[1 ] == ' e' ) return makeUnary (s, type == f32 ? UnaryOp::CeilFloat32 : UnaryOp::CeilFloat64, type);
688- if (op[1 ] == ' l' ) return makeUnary (s, type == i32 ? UnaryOp::ClzInt32 : UnaryOp::ClzInt64, type);
689- if (op[1 ] == ' o' ) {
690- if (op[2 ] == ' p' ) return makeBinary (s, BINARY_FLOAT (CopySign), type);
691- if (op[2 ] == ' n' ) {
692- if (op[3 ] == ' v' ) {
693- if (op[8 ] == ' s' ) return makeUnary (s, op[11 ] == ' 3' ? (type == f32 ? UnaryOp::ConvertSInt32ToFloat32 : UnaryOp::ConvertSInt32ToFloat64) : (type == f32 ? UnaryOp::ConvertSInt64ToFloat32 : UnaryOp::ConvertSInt64ToFloat64), type);
694- if (op[8 ] == ' u' ) return makeUnary (s, op[11 ] == ' 3' ? (type == f32 ? UnaryOp::ConvertUInt32ToFloat32 : UnaryOp::ConvertUInt32ToFloat64) : (type == f32 ? UnaryOp::ConvertUInt64ToFloat32 : UnaryOp::ConvertUInt64ToFloat64), type);
695- }
696- if (op[3 ] == ' s' ) return makeConst (s, type);
697- }
698- }
699- if (op[1 ] == ' t' ) return makeUnary (s, type == i32 ? UnaryOp::CtzInt32 : UnaryOp::CtzInt64, type);
700- abort_on (op);
701- }
702- case ' d' : {
703- if (op[1 ] == ' i' ) {
704- if (op[3 ] == ' _' ) return makeBinary (s, op[4 ] == ' u' ? BINARY_INT (DivU) : BINARY_INT (DivS), type);
705- if (op[3 ] == 0 ) return makeBinary (s, BINARY_FLOAT (Div), type);
706- }
707- if (op[1 ] == ' e' ) return makeUnary (s, UnaryOp::DemoteFloat64, type);
708- abort_on (op);
709- }
710- case ' e' : {
711- if (op[1 ] == ' q' ) {
712- if (op[2 ] == 0 ) return makeBinary (s, BINARY_INT_OR_FLOAT (Eq), type);
713- if (op[2 ] == ' z' ) return makeUnary (s, type == i32 ? UnaryOp::EqZInt32 : UnaryOp::EqZInt64, type);
714- }
715- if (op[1 ] == ' x' ) {
716- if (op[6 ] == ' 8' ) return makeUnary (s, type == i32 ? UnaryOp::ExtendS8Int32 : UnaryOp::ExtendS8Int64, type);
717- if (op[6 ] == ' 1' ) return makeUnary (s, type == i32 ? UnaryOp::ExtendS16Int32 : UnaryOp::ExtendS16Int64, type);
718- if (op[6 ] == ' 3' ) return makeUnary (s, UnaryOp::ExtendS32Int64, type);
719- return makeUnary (s, op[7 ] == ' u' ? UnaryOp::ExtendUInt32 : UnaryOp::ExtendSInt32, type);
720- }
721- abort_on (op);
722- }
723- case ' f' : {
724- if (op[1 ] == ' l' ) return makeUnary (s, type == f32 ? UnaryOp::FloorFloat32 : UnaryOp::FloorFloat64, type);
725- abort_on (op);
726- }
727- case ' g' : {
728- if (op[1 ] == ' t' ) {
729- if (op[2 ] == ' _' ) return makeBinary (s, op[3 ] == ' u' ? BINARY_INT (GtU) : BINARY_INT (GtS), type);
730- if (op[2 ] == 0 ) return makeBinary (s, BINARY_FLOAT (Gt), type);
731- }
732- if (op[1 ] == ' e' ) {
733- if (op[2 ] == ' _' ) return makeBinary (s, op[3 ] == ' u' ? BINARY_INT (GeU) : BINARY_INT (GeS), type);
734- if (op[2 ] == 0 ) return makeBinary (s, BINARY_FLOAT (Ge), type);
735- }
736- abort_on (op);
737- }
738- case ' l' : {
739- if (op[1 ] == ' t' ) {
740- if (op[2 ] == ' _' ) return makeBinary (s, op[3 ] == ' u' ? BINARY_INT (LtU) : BINARY_INT (LtS), type);
741- if (op[2 ] == 0 ) return makeBinary (s, BINARY_FLOAT (Lt), type);
742- }
743- if (op[1 ] == ' e' ) {
744- if (op[2 ] == ' _' ) return makeBinary (s, op[3 ] == ' u' ? BINARY_INT (LeU) : BINARY_INT (LeS), type);
745- if (op[2 ] == 0 ) return makeBinary (s, BINARY_FLOAT (Le), type);
746- }
747- if (op[1 ] == ' o' ) return makeLoad (s, type, /* isAtomic=*/ false );
748- abort_on (op);
749- }
750- case ' m' : {
751- if (op[1 ] == ' i' ) return makeBinary (s, BINARY_FLOAT (Min), type);
752- if (op[1 ] == ' a' ) return makeBinary (s, BINARY_FLOAT (Max), type);
753- if (op[1 ] == ' u' ) return makeBinary (s, BINARY_INT_OR_FLOAT (Mul), type);
754- abort_on (op);
755- }
756- case ' n' : {
757- if (op[1 ] == ' e' ) {
758- if (op[2 ] == 0 ) return makeBinary (s, BINARY_INT_OR_FLOAT (Ne), type);
759- if (op[2 ] == ' a' ) return makeUnary (s, type == f32 ? UnaryOp::NearestFloat32 : UnaryOp::NearestFloat64, type);
760- if (op[2 ] == ' g' ) return makeUnary (s, type == f32 ? UnaryOp::NegFloat32 : UnaryOp::NegFloat64, type);
761- }
762- abort_on (op);
763- }
764- case ' o' : {
765- if (op[1 ] == ' r' ) return makeBinary (s, BINARY_INT (Or), type);
766- abort_on (op);
767- }
768- case ' p' : {
769- if (op[1 ] == ' r' ) return makeUnary (s, UnaryOp::PromoteFloat32, type);
770- if (op[1 ] == ' o' ) return makeUnary (s, type == i32 ? UnaryOp::PopcntInt32 : UnaryOp::PopcntInt64, type);
771- abort_on (op);
772- }
773- case ' r' : {
774- if (op[1 ] == ' e' ) {
775- if (op[2 ] == ' m' ) return makeBinary (s, op[4 ] == ' u' ? BINARY_INT (RemU) : BINARY_INT (RemS), type);
776- if (op[2 ] == ' i' ) return makeUnary (s, isFloatType (type) ? (type == f32 ? UnaryOp::ReinterpretInt32 : UnaryOp::ReinterpretInt64) : (type == i32 ? UnaryOp::ReinterpretFloat32 : UnaryOp::ReinterpretFloat64), type);
777- }
778- if (op[1 ] == ' o' && op[2 ] == ' t' ) {
779- return makeBinary (s, op[3 ] == ' l' ? BINARY_INT (RotL) : BINARY_INT (RotR), type);
780- }
781- abort_on (op);
782- }
783- case ' s' : {
784- if (op[1 ] == ' h' ) {
785- if (op[2 ] == ' l' ) return makeBinary (s, BINARY_INT (Shl), type);
786- return makeBinary (s, op[4 ] == ' u' ? BINARY_INT (ShrU) : BINARY_INT (ShrS), type);
787- }
788- if (op[1 ] == ' u' ) return makeBinary (s, BINARY_INT_OR_FLOAT (Sub), type);
789- if (op[1 ] == ' q' ) return makeUnary (s, type == f32 ? UnaryOp::SqrtFloat32 : UnaryOp::SqrtFloat64, type);
790- if (op[1 ] == ' t' ) return makeStore (s, type, /* isAtomic=*/ false );
791- abort_on (op);
792- }
793- case ' t' : {
794- if (op[1 ] == ' r' ) {
795- if (op[6 ] == ' s' ) return makeUnary (s, op[9 ] == ' 3' ? (type == i32 ? UnaryOp::TruncSFloat32ToInt32 : UnaryOp::TruncSFloat32ToInt64) : (type == i32 ? UnaryOp::TruncSFloat64ToInt32 : UnaryOp::TruncSFloat64ToInt64), type);
796- if (op[6 ] == ' u' ) return makeUnary (s, op[9 ] == ' 3' ? (type == i32 ? UnaryOp::TruncUFloat32ToInt32 : UnaryOp::TruncUFloat32ToInt64) : (type == i32 ? UnaryOp::TruncUFloat64ToInt32 : UnaryOp::TruncUFloat64ToInt64), type);
797- if (op[2 ] == ' u' ) return makeUnary (s, type == f32 ? UnaryOp::TruncFloat32 : UnaryOp::TruncFloat64, type);
798- }
799- abort_on (op);
800- }
801- case ' w' : {
802- if (!strncmp (op, " wait" , strlen (" wait" ))) return makeAtomicWait (s, type);
803- if (op[1 ] == ' r' ) return makeUnary (s, UnaryOp::WrapInt64, type);
804- abort_on (op);
805- }
806- case ' x' : {
807- if (op[1 ] == ' o' ) return makeBinary (s, BINARY_INT (Xor), type);
808- abort_on (op);
809- }
810- default : abort_on (op);
811- }
812- } else {
813- // other expression
814- switch (str[0 ]) {
815- case ' b' : {
816- if (str[1 ] == ' l' ) return makeBlock (s);
817- if (str[1 ] == ' r' ) {
818- if (str[2 ] == ' _' && str[3 ] == ' t' ) return makeBreakTable (s);
819- return makeBreak (s);
820- }
821- abort_on (str);
822- }
823- case ' c' : {
824- if (str[1 ] == ' a' ) {
825- if (id == CALL) return makeCall (s);
826- if (id == CALL_INDIRECT) return makeCallIndirect (s);
827- } else if (str[1 ] == ' u' ) return makeHost (s, HostOp::CurrentMemory);
828- abort_on (str);
829- }
830- case ' d' : {
831- if (str[1 ] == ' r' ) return makeDrop (s);
832- abort_on (str);
833- }
834- case ' e' : {
835- if (str[1 ] == ' l' ) return makeThenOrElse (s);
836- abort_on (str);
837- }
838- case ' g' : {
839- if (str[1 ] == ' e' ) {
840- if (str[4 ] == ' l' ) return makeGetLocal (s);
841- if (str[4 ] == ' g' ) return makeGetGlobal (s);
842- }
843- if (str[1 ] == ' r' ) return makeHost (s, HostOp::GrowMemory);
844- abort_on (str);
845- }
846- case ' h' : {
847- abort_on (str);
848- }
849- case ' i' : {
850- if (str[1 ] == ' f' ) return makeIf (s);
851- abort_on (str);
852- }
853- case ' l' : {
854- if (str[1 ] == ' o' ) return makeLoop (s);
855- abort_on (str);
856- }
857- case ' n' : {
858- if (str[1 ] == ' o' ) return allocator.alloc <Nop>();
859- abort_on (str);
860- }
861- case ' p' : {
862- abort_on (str);
863- }
864- case ' s' : {
865- if (str[1 ] == ' e' && str[2 ] == ' t' ) {
866- if (str[4 ] == ' l' ) return makeSetLocal (s);
867- if (str[4 ] == ' g' ) return makeSetGlobal (s);
868- }
869- if (str[1 ] == ' e' && str[2 ] == ' l' ) return makeSelect (s);
870- abort_on (str);
871- }
872- case ' r' : {
873- if (str[1 ] == ' e' ) return makeReturn (s);
874- abort_on (str);
875- }
876- case ' t' : {
877- if (str[1 ] == ' h' ) return makeThenOrElse (s);
878- if (str[1 ] == ' e' && str[2 ] == ' e' ) return makeTeeLocal (s);
879- abort_on (str);
880- }
881- case ' u' : {
882- if (str[1 ] == ' n' ) return allocator.alloc <Unreachable>();
883- abort_on (str);
884- }
885- case ' w' : {
886- if (!strncmp (str, " wake" , strlen (" wake" ))) return makeAtomicWake (s);
887- abort_on (str);
888- }
889- default : abort_on (str);
890- }
891- }
892- abort_on (" unrecognized input string for parsing" );
661+ #define INSTRUCTION_PARSER
662+ #include " gen-s-parser.inc"
893663}
894664
895- Expression* SExpressionWasmBuilder::makeBinary (Element& s, BinaryOp op, Type type) {
665+ Expression* SExpressionWasmBuilder::makeUnreachable () {
666+ return allocator.alloc <Unreachable>();
667+ }
668+
669+ Expression* SExpressionWasmBuilder::makeNop () {
670+ return allocator.alloc <Nop>();
671+ }
672+
673+ Expression* SExpressionWasmBuilder::makeBinary (Element& s, BinaryOp op) {
896674 auto ret = allocator.alloc <Binary>();
897675 ret->op = op;
898676 ret->left = parseExpression (s[1 ]);
@@ -902,67 +680,11 @@ Expression* SExpressionWasmBuilder::makeBinary(Element& s, BinaryOp op, Type typ
902680}
903681
904682
905- Expression* SExpressionWasmBuilder::makeUnary (Element& s, UnaryOp op, Type type ) {
683+ Expression* SExpressionWasmBuilder::makeUnary (Element& s, UnaryOp op) {
906684 auto ret = allocator.alloc <Unary>();
907685 ret->op = op;
908686 ret->value = parseExpression (s[1 ]);
909687 ret->finalize ();
910- // type is the reported type, e.g. i64.ctz reports i64 (but has a return type of i32, in this case)
911- // verify the reported type is correct
912- switch (op) {
913- case EqZInt32:
914- case NegFloat32:
915- case AbsFloat32:
916- case CeilFloat32:
917- case FloorFloat32:
918- case TruncFloat32:
919- case NearestFloat32:
920- case SqrtFloat32:
921- case ClzInt32:
922- case CtzInt32:
923- case PopcntInt32:
924- case EqZInt64:
925- case NegFloat64:
926- case AbsFloat64:
927- case CeilFloat64:
928- case FloorFloat64:
929- case TruncFloat64:
930- case NearestFloat64:
931- case SqrtFloat64:
932- case ClzInt64:
933- case CtzInt64:
934- case PopcntInt64: {
935- if (ret->value ->type != unreachable && type != ret->value ->type ) throw ParseException (std::string (" bad type for " ) + getExpressionName (ret) + " : " + printType (type) + " vs value type " + printType (ret->value ->type ), s.line , s.col );
936- break ;
937- }
938- case ExtendSInt32: case ExtendUInt32:
939- case ExtendS8Int32: case ExtendS16Int32:
940- case ExtendS8Int64: case ExtendS16Int64: case ExtendS32Int64:
941- case WrapInt64:
942- case PromoteFloat32:
943- case DemoteFloat64:
944- case TruncSFloat32ToInt32:
945- case TruncUFloat32ToInt32:
946- case TruncSFloat64ToInt32:
947- case TruncUFloat64ToInt32:
948- case ReinterpretFloat32:
949- case TruncSFloat32ToInt64:
950- case TruncUFloat32ToInt64:
951- case TruncSFloat64ToInt64:
952- case TruncUFloat64ToInt64:
953- case ReinterpretFloat64:
954- case ReinterpretInt32:
955- case ConvertSInt32ToFloat32:
956- case ConvertUInt32ToFloat32:
957- case ConvertSInt64ToFloat32:
958- case ConvertUInt64ToFloat32:
959- case ReinterpretInt64:
960- case ConvertSInt32ToFloat64:
961- case ConvertUInt32ToFloat64:
962- case ConvertSInt64ToFloat64:
963- case ConvertUInt64ToFloat64: break ;
964- default : WASM_UNREACHABLE ();
965- }
966688 return ret;
967689}
968690
0 commit comments